{"id":20022235,"url":"https://github.com/lucifier129/functional-di","last_synced_at":"2025-05-05T01:31:25.946Z","repository":{"id":59939298,"uuid":"539318524","full_name":"Lucifier129/functional-di","owner":"Lucifier129","description":"Dependency injection in functional style","archived":false,"fork":false,"pushed_at":"2022-09-21T12:25:11.000Z","size":97,"stargazers_count":19,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-23T12:52:55.687Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Lucifier129.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-09-21T05:23:37.000Z","updated_at":"2024-05-05T14:05:26.000Z","dependencies_parsed_at":"2022-09-25T08:51:28.613Z","dependency_job_id":null,"html_url":"https://github.com/Lucifier129/functional-di","commit_stats":null,"previous_names":["lucifier129/fp-di"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Lucifier129%2Ffunctional-di","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Lucifier129%2Ffunctional-di/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Lucifier129%2Ffunctional-di/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Lucifier129%2Ffunctional-di/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Lucifier129","download_url":"https://codeload.github.com/Lucifier129/functional-di/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252423142,"owners_count":21745548,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-13T08:39:38.902Z","updated_at":"2025-05-05T01:31:21.256Z","avatar_url":"https://github.com/Lucifier129.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# functional-di\n\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"400\" src=\"./assets/logo.png\"\u003e\n\u003c/p\u003e\n\n[![npm version](https://img.shields.io/npm/v/functional-di.svg?style=flat)](https://www.npmjs.com/package/functional-di)\n[![Documentation](https://img.shields.io/badge/documentation-yes-brightgreen.svg)](https://github.com/Lucifier129/functional-di#readme)\n[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/Lucifier129/functional-di/graphs/commit-activity)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/Lucifier129/functional-di/blob/master/LICENSE)\n[![Twitter: guyingjie129](https://img.shields.io/twitter/follow/guyingjie129.svg?style=social)](https://twitter.com/guyingjie129)\n\n\u003e Dependency injection in functional style\n\n### Installation\n\n```sh\nnpm install --save functional-di\n\nyarn add functional-di\n```\n\n### Usage\n\n- `def` for creating injectable function\n- `run` for injecting function\n\n```typescript\nimport { def, run } from 'functional-di'\n\n// define some interfaces\ninterface ServiceA {\n  foo(): number\n}\n\ninterface ServiceB {\n  foo: string\n  bar: string\n}\n\n// use def to create injectable \u0026 callable function\nconst ServiceA = def\u003cServiceA, number\u003e('ServiceA')\nconst ServiceB = def\u003cServiceB\u003e('ServiceB')\n\n// use #impl(handler) to handle request for injected\nconst serviceAImpl = ServiceA.impl((n) =\u003e {\n  return {\n    foo() {\n      return 111 + n\n    },\n  }\n})\n\nconst serviceBImpl = ServiceB.impl(() =\u003e {\n  return {\n    // call function with argument to make a request\n    foo: ServiceA(1).foo().toFixed(2),\n    // different argument is supported\n    bar: ServiceA(2).foo().toFixed(2),\n  }\n})\n\nconst serviceBDirectImpl = ServiceB.impl(() =\u003e {\n  return {\n    foo: '666',\n    bar: '777',\n  }\n})\n\n{\n  const value0 = run(() =\u003e ServiceA(1), [serviceAImpl]).foo()\n  const value1 = run(() =\u003e ServiceA(2), [serviceAImpl]).foo()\n\n  expect(value0).toEqual(112)\n  expect(value1).toEqual(113)\n}\n\n{\n  const value = run(() =\u003e ServiceB(), [serviceAImpl, serviceBImpl])\n\n  expect(value).toEqual({ foo: '112.00', bar: '113.00' })\n}\n\n// supports nested\nconst serverBNestImpl = ServiceB.impl(() =\u003e {\n  const { foo } = run(() =\u003e ServiceB(), [serviceAImpl, serviceBImpl])\n  const { bar } = run(() =\u003e ServiceB(), [serviceBDirectImpl])\n  return {\n    foo,\n    bar,\n  }\n})\n\n{\n  const value = run(() =\u003e ServiceB(), [serverBNestImpl])\n\n  expect(value).toEqual({ foo: '112.00', bar: '777' })\n}\n```\n\n## Apis\n\n### def\u003cvalue, arg = void\u003e(name?, defaultHandler?): (arg =\u003e value)\n\n`def` is used for define injectable function\n\n- if `default-handler` was given, getValue formed like a normal function which can be called directly\n- otherwise it should not be called without `run(fn)`\n\n```typescript\nconst getValue = def\u003cnumber\u003e(\n  // the name used for improving readability of the error message\n  'getValue',\n  // default-handler when no injected handler found.\n  () =\u003e 0,\n)\n\n/**\n * if default-handler was given, getValue formed like a normal function which can be called directly\n * otherwise it should not be called without `run(fn)`\n */\nconsole.log(getValue()) // 0\n\n/**\n * the first type variable is for return type\n * the second type variable is for arg type\n */\nconst getValueWithArg = def\u003cstring, number\u003e('getValueWithArg', (input: number) =\u003e `input is : ${input}`)\n\n/**\n * give another impl for getValue\n * it can be used to inject, replacing the default handler\n */\nconst getValueImpl = getValue.impl(() =\u003e 100)\n\nconst getValueWithArgImpl = getValueWithArg.impl((input: number) =\u003e {\n  return `another-impl: input is : ${input}`\n})\n```\n\n### run(fn, injectedList?): ReturnType\u003ctypeof fn\u003e\n\n`run` is used for injecting value consumed by the consumers in `fn()`\n\n```typescript\nconst getValue = def\u003cnumber\u003e(\n  // the name used for improving readability of the error message\n  'getValue',\n  // default-handler when no injected handler found.\n  () =\u003e 0,\n)\n\nconsole.log(run(() =\u003e getValue(), [getValue.impl(() =\u003e 1)])) // 1\n```\n\n# PRs are welcome\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucifier129%2Ffunctional-di","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flucifier129%2Ffunctional-di","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucifier129%2Ffunctional-di/lists"}