{"_id":"@dmytrolesyk/custom-nest","name":"@dmytrolesyk/custom-nest","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@dmytrolesyk/custom-nest","version":"0.1.0","description":"A minimal IoC container with decorator-driven constructor injection","keywords":["ioc","di","dependency-injection","container","decorators","reflect-metadata"],"homepage":"https://github.com/dmytrolesyk/custom-nest#readme","bugs":{"url":"https://github.com/dmytrolesyk/custom-nest/issues"},"repository":{"type":"git","url":"git+https://github.com/dmytrolesyk/custom-nest.git"},"license":"ISC","author":{"name":"Dmytro Lesyk"},"main":"./dist/index.js","scripts":{"build":"rm -rf dist && tsc -p tsconfig.build.json","build:test":"rm -rf dist && tsc","test":"node --test \"dist/*.test.js\"","test:src":"node --require ts-node/register --test \"*.test.ts\"","typecheck":"tsc --noEmit","prepublishOnly":"pnpm build:test && pnpm test && pnpm build"},"packageManager":"pnpm@10.24.0","devDependencies":{"@types/node":"^26.3.0","reflect-metadata":"^0.2.2","ts-node":"^10.9.2","typescript":"^6.0.3"},"types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"engines":{"node":">=20"},"peerDependencies":{"reflect-metadata":"^0.2.2"},"publishConfig":{"access":"public"},"gitHead":"451cd9b384052fd037d67adfd643c04a38771589","_id":"@dmytrolesyk/custom-nest@0.1.0","_nodeVersion":"24.19.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-3ZQeBUxgF6V68ddZxxaPXh7C6WoGjrvCIQPsVfbHYViKxNd4ohAKpwlwn3p9J6g+iTsElbx+lf4sqLXQ6LWmfQ==","shasum":"912b7a76798f0ddc685d6d6d5bb651ad2bb6cf2a","tarball":"https://registry.npmjs.org/@dmytrolesyk/custom-nest/-/custom-nest-0.1.0.tgz","fileCount":15,"unpackedSize":22973,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIG0o+zcz0PpaNzsBjTGnOhvKrV+YaSiAhPyhrzFUj3cvAiEAlSyhu6hZlPk8mgXCuNIAVqqyoM/ybFI3rS+MjHutZVE="}]},"_npmUser":{"name":"dmytrolesyk","email":"dmytrolesyk@proton.me"},"directories":{},"maintainers":[{"name":"dmytrolesyk","email":"dmytrolesyk@proton.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/custom-nest_0.1.0_1787752758518_0.1983600311225333"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-26T13:59:18.289Z","0.1.0":"2026-08-26T13:59:18.662Z","modified":"2026-08-26T13:59:18.930Z"},"maintainers":[{"name":"dmytrolesyk","email":"dmytrolesyk@proton.me"}],"description":"A minimal IoC container with decorator-driven constructor injection","homepage":"https://github.com/dmytrolesyk/custom-nest#readme","keywords":["ioc","di","dependency-injection","container","decorators","reflect-metadata"],"repository":{"type":"git","url":"git+https://github.com/dmytrolesyk/custom-nest.git"},"author":{"name":"Dmytro Lesyk"},"bugs":{"url":"https://github.com/dmytrolesyk/custom-nest/issues"},"license":"ISC","readme":"# @dmytrolesyk/custom-nest\n\nA minimal IoC container with decorator-driven constructor injection — the part\nof NestJS that reads `design:paramtypes` and assembles your object graph, built\nfrom scratch.\n\n## Install\n\n```sh\npnpm add @dmytrolesyk/custom-nest reflect-metadata\n```\n\n`reflect-metadata` is a peer dependency: the metadata registry must be a single\nglobal instance, so the container cannot bring its own copy.\n\nYour `tsconfig.json` needs both decorator flags:\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true\n  }\n}\n```\n\n## Quick start\n\n```ts\nimport 'reflect-metadata';\nimport { Container, injectable } from '@dmytrolesyk/custom-nest';\n\n@injectable()\nclass Engine {}\n\n@injectable()\nclass Car {\n  constructor(readonly engine: Engine) {}\n}\n\nconst car = new Container().get(Car) as Car;\ncar.engine instanceof Engine; // true\n```\n\nClasses marked `@injectable()` are auto-bound on first resolve, so a graph of\nconcrete classes needs no registration at all.\n\n## Tokens\n\nTypeScript erases interfaces, so an interface-typed parameter emits `Object`\nand cannot be resolved by type. Give it an explicit token instead:\n\n```ts\nconst LOGGER = Symbol.for('logger');\n\n@injectable()\nclass Repo {\n  constructor(@inject(LOGGER) private logger: Logger) {}\n}\n\ncontainer.bind(LOGGER).to(ConsoleLogger);\n```\n\nThe same applies to primitives — `damage: number` emits `Number`, which the\ncontainer refuses to construct.\n\n## Binding\n\n```ts\ncontainer.bind(Token).to(Implementation);        // construct this class\ncontainer.bind(Token).toConstantValue(value);    // hand back a fixed value\ncontainer.bind(SomeClass).toSelf();              // construct the identifier itself\ncontainer.bind(Token).setScope('transient').to(Impl);\ncontainer.unbind(Token);                         // also drops the cached singleton\n```\n\n`bind()` returns a builder; the terminal call registers the binding. Set the\nscope before choosing a target.\n\n## Scopes\n\n| scope | behaviour |\n| --- | --- |\n| `singleton` | default — one instance per container |\n| `transient` | a new instance on every resolve |\n\nSingletons are cached per container, not globally.\n\n## Circular dependencies\n\nA cycle throws with the full chain rather than overflowing the stack:\n\n```\n[ResolutionError] circular dependencies detected A -> B -> A\n```\n\nDiamonds are not cycles — a dependency reached twice by different paths\nresolves normally.\n\n## Options\n\n```ts\nnew Container({ autobind: false });\n```\n\nWith `autobind` disabled, every identifier must be bound explicitly before it\ncan be resolved.\n\n## License\n\nISC\n","readmeFilename":"README.md","_rev":"1-43b72d4793c3f41f0012dd40044822d7"}