Compare commits
10 Commits
dependabot
...
v0.1.0-alp
Author | SHA1 | Date | |
---|---|---|---|
ab07e03c0f | |||
8bb153fe54 | |||
![]() |
794c1e07c3 | ||
1a67d3f4e3 | |||
042d918d00 | |||
06ae6737fd | |||
81873f3689 | |||
4aa12321e8 | |||
26b35d1e5b | |||
78564b9a76 |
@@ -9,17 +9,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Added
|
||||
|
||||
- feat: Add new `IdentifierRequiredError` class for missing identifiers.
|
||||
- feat: Add the option to use the decorators without passing the identifier: In this case, the identifier will be the class name (register) or the property name (inject).
|
||||
- Add pre release building to release workflow on dev/* branches an version changes.
|
||||
|
||||
|
||||
### Deprecated
|
||||
|
||||
|
||||
### Removed
|
||||
|
||||
- feat!: Disable `experimentalDecorators` and `emitDecoratorMetadata` in the `tsconfig.json` file to reflect the change to the stable decorators api.
|
||||
|
||||
### Fixed
|
||||
|
||||
- feat!: Update `Register`, `RegisterInstance` and `Inject` decorators to reflect the change to the stable decorators api.
|
||||
- feat!: Update `Inject` Decorator typing to reflect the correct property type.
|
||||
|
||||
### Security
|
||||
|
||||
|
297
package-lock.json
generated
297
package-lock.json
generated
@@ -1,19 +1,19 @@
|
||||
{
|
||||
"name": "ts-injex",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.0-alpha",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ts-injex",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.0-alpha",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"jest-environment-jsdom": "^29.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@stylistic/eslint-plugin": "^2.10.1",
|
||||
"@stylistic/eslint-plugin": "^2.6.2",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.14.11",
|
||||
"@typescript-eslint/eslint-plugin": "^8.1.0",
|
||||
@@ -1218,14 +1218,79 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.10.1.tgz",
|
||||
"integrity": "sha512-U+4yzNXElTf9q0kEfnloI9XbOyD4cnEQCxjUI94q0+W++0GAEQvJ/slwEj9lwjDHfGADRSr+Tco/z0XJvmDfCQ==",
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.6.2.tgz",
|
||||
"integrity": "sha512-Ic5oFNM/25iuagob6LiIBkSI/A2y45TsyKtDtODXHRZDy52WfPfeexI6r+OH5+aWN9QGob2Bw+4JRM9/4areWw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/utils": "^8.12.2",
|
||||
"eslint-visitor-keys": "^4.2.0",
|
||||
"espree": "^10.3.0",
|
||||
"@stylistic/eslint-plugin-js": "2.6.2",
|
||||
"@stylistic/eslint-plugin-jsx": "2.6.2",
|
||||
"@stylistic/eslint-plugin-plus": "2.6.2",
|
||||
"@stylistic/eslint-plugin-ts": "2.6.2",
|
||||
"@types/eslint": "^9.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": ">=8.40.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin-js": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-2.6.2.tgz",
|
||||
"integrity": "sha512-wCr/kVctAPayMU3pcOI1MKR7MoKIh6VKZU89lPklAqtJoxT+Em6RueiiARbpznUYG5eg3LymiU+aMD+aIZXdqA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/eslint": "^9.6.0",
|
||||
"acorn": "^8.12.1",
|
||||
"eslint-visitor-keys": "^4.0.0",
|
||||
"espree": "^10.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": ">=8.40.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin-js/node_modules/eslint-visitor-keys": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz",
|
||||
"integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin-js/node_modules/espree": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz",
|
||||
"integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"acorn": "^8.12.0",
|
||||
"acorn-jsx": "^5.3.2",
|
||||
"eslint-visitor-keys": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin-jsx": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-2.6.2.tgz",
|
||||
"integrity": "sha512-dSXK/fSPA938J1fBi10QmhzLKtZ/2TuyVNHQMk8jUhWfKJDleAogaSqcWNAbN8fwcoe9UWmt/3StiIf2oYC1aQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@stylistic/eslint-plugin-js": "^2.6.2",
|
||||
"@types/eslint": "^9.6.0",
|
||||
"estraverse": "^5.3.0",
|
||||
"picomatch": "^4.0.2"
|
||||
},
|
||||
@@ -1236,169 +1301,7 @@
|
||||
"eslint": ">=8.40.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "8.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.12.2.tgz",
|
||||
"integrity": "sha512-gPLpLtrj9aMHOvxJkSbDBmbRuYdtiEbnvO25bCMza3DhMjTQw0u7Y1M+YR5JPbMsXXnSPuCf5hfq0nEkQDL/JQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.12.2",
|
||||
"@typescript-eslint/visitor-keys": "8.12.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/types": {
|
||||
"version": "8.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.12.2.tgz",
|
||||
"integrity": "sha512-VwDwMF1SZ7wPBUZwmMdnDJ6sIFk4K4s+ALKLP6aIQsISkPv8jhiw65sAK6SuWODN/ix+m+HgbYDkH+zLjrzvOA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "8.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.12.2.tgz",
|
||||
"integrity": "sha512-mME5MDwGe30Pq9zKPvyduyU86PH7aixwqYR2grTglAdB+AN8xXQ1vFGpYaUSJ5o5P/5znsSBeNcs5g5/2aQwow==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.12.2",
|
||||
"@typescript-eslint/visitor-keys": "8.12.2",
|
||||
"debug": "^4.3.4",
|
||||
"fast-glob": "^3.3.2",
|
||||
"is-glob": "^4.0.3",
|
||||
"minimatch": "^9.0.4",
|
||||
"semver": "^7.6.0",
|
||||
"ts-api-utils": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/utils": {
|
||||
"version": "8.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.12.2.tgz",
|
||||
"integrity": "sha512-UTTuDIX3fkfAz6iSVa5rTuSfWIYZ6ATtEocQ/umkRSyC9O919lbZ8dcH7mysshrCdrAM03skJOEYaBugxN+M6A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"@typescript-eslint/scope-manager": "8.12.2",
|
||||
"@typescript-eslint/types": "8.12.2",
|
||||
"@typescript-eslint/typescript-estree": "8.12.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^8.57.0 || ^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "8.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.12.2.tgz",
|
||||
"integrity": "sha512-PChz8UaKQAVNHghsHcPyx1OMHoFRUEA7rJSK/mDhdq85bk+PLsUHUBqTQTFt18VJZbmxBovM65fezlheQRsSDA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.12.2",
|
||||
"eslint-visitor-keys": "^3.4.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
|
||||
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin/node_modules/eslint-visitor-keys": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
|
||||
"integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin/node_modules/espree": {
|
||||
"version": "10.3.0",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz",
|
||||
"integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"acorn": "^8.14.0",
|
||||
"acorn-jsx": "^5.3.2",
|
||||
"eslint-visitor-keys": "^4.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin/node_modules/minimatch": {
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin/node_modules/picomatch": {
|
||||
"node_modules/@stylistic/eslint-plugin-jsx/node_modules/picomatch": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
|
||||
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
||||
@@ -1410,6 +1313,36 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin-plus": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-2.6.2.tgz",
|
||||
"integrity": "sha512-cANcPASfRvq3VTbbQCrSIXq+2AI0IW68PNYaZoXXS0ENlp7HDB8dmrsJnOgWCcoEvdCB8z/eWcG/eq/v5Qcl+Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/eslint": "^9.6.0",
|
||||
"@typescript-eslint/utils": "^8.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin-ts": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-2.6.2.tgz",
|
||||
"integrity": "sha512-6OEN3VtUNxjgOvWPavnC10MByr1H4zsgwNND3rQXr5lDFv93MLUnTsH+/SH15OkuqdyJgrQILI6b9lYecb1vIg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@stylistic/eslint-plugin-js": "2.6.2",
|
||||
"@types/eslint": "^9.6.0",
|
||||
"@typescript-eslint/utils": "^8.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": ">=8.40.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tootallnate/once": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
|
||||
@@ -1463,8 +1396,7 @@
|
||||
"version": "9.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz",
|
||||
"integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "*",
|
||||
"@types/json-schema": "*"
|
||||
@@ -1474,8 +1406,7 @@
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
|
||||
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/@types/graceful-fs": {
|
||||
"version": "4.1.9",
|
||||
@@ -1540,8 +1471,7 @@
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/@types/json5": {
|
||||
"version": "0.0.29",
|
||||
@@ -1805,9 +1735,9 @@
|
||||
"deprecated": "Use your platform's native atob() and btoa() methods instead"
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.14.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
||||
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
|
||||
"version": "8.12.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
|
||||
"integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -6028,6 +5958,11 @@
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
|
||||
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
|
||||
},
|
||||
"node_modules/reflect-metadata": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz",
|
||||
"integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q=="
|
||||
},
|
||||
"node_modules/regexp.prototype.flags": {
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ts-injex",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.0-alpha",
|
||||
"description": "Simple boilerplate code free dependency injection system for TypeScript.",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
@@ -36,7 +36,7 @@
|
||||
"typescript": "^5.5.4",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.14.11",
|
||||
"@stylistic/eslint-plugin": "^2.10.1",
|
||||
"@stylistic/eslint-plugin": "^2.6.2",
|
||||
"@typescript-eslint/eslint-plugin": "^8.1.0",
|
||||
"@typescript-eslint/parser": "^8.1.0",
|
||||
"eslint-plugin-deprecation": "^3.0.0",
|
||||
|
@@ -67,6 +67,29 @@ export function test_InjectDecorator(
|
||||
expect(instance.getDependency().value).toBe('test-value-init');
|
||||
});
|
||||
|
||||
it('should inject dependency and run initializer without identifier', () => {
|
||||
container.register('MockDependencyIdentifier', {
|
||||
value: 'test-value',
|
||||
});
|
||||
|
||||
class TestClass {
|
||||
@Inject(undefined, (x: string) => {
|
||||
(x as unknown as { value: string }).value =
|
||||
'test-value-init';
|
||||
|
||||
return x;
|
||||
})
|
||||
MockDependencyIdentifier!: any;
|
||||
|
||||
public getDependency() {
|
||||
return this.MockDependencyIdentifier;
|
||||
}
|
||||
}
|
||||
|
||||
const instance = new TestClass();
|
||||
expect(instance.getDependency().value).toBe('test-value-init');
|
||||
});
|
||||
|
||||
it('should throw an error when necessary is true and the initializer throws an error', () => {
|
||||
let _error: Error | undefined = undefined;
|
||||
|
||||
@@ -78,7 +101,7 @@ export function test_InjectDecorator(
|
||||
class TestClass {
|
||||
@Inject(
|
||||
'InitThrowDependencie',
|
||||
() => {
|
||||
(): any => {
|
||||
throw new Error('Initializer error');
|
||||
},
|
||||
true,
|
||||
@@ -275,6 +298,19 @@ export function test_RegisterDecorator(
|
||||
TestClass,
|
||||
);
|
||||
});
|
||||
|
||||
it('should register a dependency without an identifier', () => {
|
||||
@register()
|
||||
class TestClass {
|
||||
private readonly _dependency!: any;
|
||||
|
||||
public getDependency() {
|
||||
return this._dependency;
|
||||
}
|
||||
}
|
||||
|
||||
expect(container.resolve('TestClass')).toBe(TestClass);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -311,6 +347,23 @@ export function test_RegisterInstanceDecorator(
|
||||
).toBe('instance');
|
||||
});
|
||||
|
||||
it('should register an instance of a dependency with an identifier', () => {
|
||||
@registerInstance()
|
||||
class TestClass {
|
||||
private readonly _dependency!: any;
|
||||
|
||||
public getDependency() {
|
||||
return this._dependency;
|
||||
}
|
||||
|
||||
public mark: string = 'instance';
|
||||
}
|
||||
|
||||
expect(container.resolve<TestClass>('TestClass').mark).toBe(
|
||||
'instance',
|
||||
);
|
||||
});
|
||||
|
||||
it('should register an instance of a dependency an run the init function', () => {
|
||||
@registerInstance(
|
||||
'InstanceIdentifier',
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
DependencyResolutionError,
|
||||
IdentifierRequiredError,
|
||||
InitializationError,
|
||||
InjectorError,
|
||||
NoInstantiationMethodError,
|
||||
@@ -10,17 +11,17 @@ import { InitDelegate } from '../types/InitDelegate';
|
||||
|
||||
/**
|
||||
* A decorator to inject a dependency from a DI (Dependency Injection) container into a class property.
|
||||
* @template T The type of the dependency to be injected.
|
||||
* @template U The type of the property to be injected.
|
||||
* @param identifier The identifier used to resolve the class in the DI container.
|
||||
* @see {@link Identifier} for more information on identifiers.
|
||||
* @param init Optional an initializer function to transform the dependency before injection
|
||||
* @template TargetType The type of the class to inject the dependency into.
|
||||
* @template DependencyType The type of the dependency to be injected.
|
||||
* @template PropertyType The type of the property to be injected.
|
||||
* @param identifier The {@link Identifier|identifier} used to resolve the dependencie in the DI container or the property name if not provided.
|
||||
* @param init An optional initializer {@link InitDelegate|function} to transform the dependency before injection
|
||||
* or true to instantiate the dependency if it has a constructor.
|
||||
* @see {@link InitDelegate} for more information on initializer functions.
|
||||
* @param necessary If true, throws an error if the dependency is not found.
|
||||
* @returns The resolved dependency or undefined if the dependency is not necessary
|
||||
* and not found, or throws an error if the dependency is necessary and not found.
|
||||
* @throws **Only throws errors if the dependency is necessary.**
|
||||
* @throws An {@link IdentifierRequiredError} if the identifier is not provided and the class name is not available.
|
||||
* @throws A {@link DependencyResolutionError} if the dependency is not found.
|
||||
* @throws A {@link InjectorError} if an error occurs during the injection process.
|
||||
* @throws A {@link NoInstantiationMethodError} if the dependency does not have a constructor.
|
||||
@@ -40,70 +41,86 @@ import { InitDelegate } from '../types/InitDelegate';
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export function Inject<T, U>(
|
||||
identifier: Identifier,
|
||||
init?: InitDelegate<T, U> | true,
|
||||
export function Inject<TargetType, DependencyType, PropertyType>(
|
||||
identifier?: Identifier,
|
||||
init?: InitDelegate<DependencyType, PropertyType> | true,
|
||||
necessary = true,
|
||||
) {
|
||||
return function (target: unknown, propertyKey: string | symbol): void {
|
||||
return function (
|
||||
constructor: undefined,
|
||||
context: ClassFieldDecoratorContext<TargetType> & {
|
||||
name: PropertyType;
|
||||
},
|
||||
): void {
|
||||
const _identifier = identifier ?? context.name;
|
||||
|
||||
if (_identifier == null && necessary === true)
|
||||
throw new IdentifierRequiredError();
|
||||
|
||||
/**
|
||||
* Function to evaluate the dependency lazily
|
||||
* to avoid circular dependencies, not found dependencies, etc.
|
||||
* @returns The resolved dependency or undefined if the dependency is not found.
|
||||
*/
|
||||
const resolve = (): T | undefined => {
|
||||
return TSinjex.getInstance().resolve<T>(identifier, necessary);
|
||||
const resolve = (): DependencyType | undefined => {
|
||||
return TSinjex.getInstance().resolve<DependencyType>(
|
||||
_identifier,
|
||||
necessary,
|
||||
);
|
||||
};
|
||||
|
||||
Object.defineProperty(target, propertyKey, {
|
||||
get() {
|
||||
let instance: T | U | undefined;
|
||||
context.addInitializer(function (this: TargetType) {
|
||||
Object.defineProperty(this, context.name, {
|
||||
get() {
|
||||
let instance: DependencyType | PropertyType | undefined;
|
||||
|
||||
const dependency: T | undefined = tryAndCatch(
|
||||
() => resolve(),
|
||||
necessary,
|
||||
identifier,
|
||||
DependencyResolutionError,
|
||||
);
|
||||
const dependency: DependencyType | undefined = tryAndCatch(
|
||||
() => resolve(),
|
||||
necessary,
|
||||
_identifier,
|
||||
DependencyResolutionError,
|
||||
);
|
||||
|
||||
if (dependency != null) {
|
||||
const initFunction: (() => U) | undefined =
|
||||
typeof init === 'function' && dependency != null
|
||||
? (): U => init(dependency)
|
||||
: init === true && hasConstructor(dependency)
|
||||
? (): U => new dependency() as U
|
||||
: undefined;
|
||||
if (dependency != null) {
|
||||
const initFunction: (() => PropertyType) | undefined =
|
||||
typeof init === 'function' && dependency != null
|
||||
? (): PropertyType => init(dependency)
|
||||
: init === true && hasConstructor(dependency)
|
||||
? (): PropertyType =>
|
||||
new dependency() as PropertyType
|
||||
: undefined;
|
||||
|
||||
if (init == null) instance = dependency;
|
||||
else if (initFunction != null)
|
||||
instance = tryAndCatch(
|
||||
initFunction,
|
||||
necessary,
|
||||
identifier,
|
||||
InitializationError,
|
||||
);
|
||||
else if (necessary)
|
||||
throw new NoInstantiationMethodError(identifier);
|
||||
} else if (necessary)
|
||||
throw new DependencyResolutionError(identifier);
|
||||
if (init == null) instance = dependency;
|
||||
else if (initFunction != null)
|
||||
instance = tryAndCatch(
|
||||
initFunction,
|
||||
necessary,
|
||||
_identifier,
|
||||
InitializationError,
|
||||
);
|
||||
else if (necessary)
|
||||
throw new NoInstantiationMethodError(_identifier);
|
||||
} else if (necessary)
|
||||
throw new DependencyResolutionError(_identifier);
|
||||
|
||||
/**
|
||||
* Replace itself with the resolved dependency
|
||||
* for performance reasons.
|
||||
*/
|
||||
Object.defineProperty(this, context.name, {
|
||||
value: instance,
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
});
|
||||
|
||||
return instance;
|
||||
},
|
||||
/**
|
||||
* Replace itself with the resolved dependency
|
||||
* for performance reasons.
|
||||
* Make the property configurable to allow replacing it
|
||||
*/
|
||||
Object.defineProperty(this, propertyKey, {
|
||||
value: instance,
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
});
|
||||
|
||||
return instance;
|
||||
},
|
||||
/**
|
||||
* Make the property configurable to allow replacing it
|
||||
*/
|
||||
configurable: true,
|
||||
configurable: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@@ -1,14 +1,14 @@
|
||||
import { IdentifierRequiredError } from 'src/interfaces/Exceptions';
|
||||
import { TSinjex } from '../classes/TSinjex';
|
||||
import { Identifier } from '../types/Identifier';
|
||||
|
||||
/**
|
||||
* A decorator to register a class in the **TSinjex** DI (Dependency Injection) container.
|
||||
* @template TargetType The type of the class to be registered.
|
||||
* @param identifier The identifier used to register the class in the DI container.
|
||||
* @see {@link Identifier} for more information on identifiers.
|
||||
* @param deprecated If true, the dependency is deprecated and a warning
|
||||
* is logged only once upon the first resolution of the dependency.
|
||||
* @param identifier The {@link Identifier|identifier} used to register the class in the DI container or the class name if not provided.
|
||||
* @param deprecated If true, the dependency is deprecated and a warning is logged only once upon the first resolution of the dependency.
|
||||
* @returns The decorator function to be applied on the class.
|
||||
* @throws An {@link IdentifierRequiredError} if the identifier is not provided and the class name is not available.
|
||||
* @example
|
||||
* ```ts
|
||||
* \@Register('MyClassIdentifier')
|
||||
@@ -19,12 +19,16 @@ import { Identifier } from '../types/Identifier';
|
||||
*/
|
||||
export function Register<
|
||||
TargetType extends new (...args: unknown[]) => InstanceType<TargetType>,
|
||||
>(identifier: Identifier, deprecated?: boolean) {
|
||||
return function (constructor: TargetType, ...args: unknown[]): void {
|
||||
// Get the instance of the DI container
|
||||
const diContainer = TSinjex.getInstance();
|
||||
>(identifier?: Identifier, deprecated?: boolean) {
|
||||
return function (
|
||||
constructor: TargetType,
|
||||
context: ClassDecoratorContext<TargetType>,
|
||||
) {
|
||||
const _identifier = identifier ?? context.name;
|
||||
|
||||
// Register the class in the DI container
|
||||
diContainer.register(identifier, constructor, deprecated);
|
||||
if (_identifier == null) throw new IdentifierRequiredError();
|
||||
|
||||
const diContainer = TSinjex.getInstance();
|
||||
diContainer.register(_identifier, constructor, deprecated);
|
||||
};
|
||||
}
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { IdentifierRequiredError } from 'src/interfaces/Exceptions';
|
||||
import { TSinjex } from '../classes/TSinjex';
|
||||
import { Identifier } from '../types/Identifier';
|
||||
import { InitDelegate } from '../types/InitDelegate';
|
||||
@@ -5,12 +6,11 @@ import { InitDelegate } from '../types/InitDelegate';
|
||||
/**
|
||||
* A decorator to register an instance of a class in the DI (Dependency Injection) container.
|
||||
* @template TargetType The type of the class whose instance is to be registered.
|
||||
* @param identifier The identifier used to register the instance in the DI container.
|
||||
* @see {@link Identifier} for more information on identifiers.
|
||||
* @param init An optional initializer function which get the constructor of the class
|
||||
* @param identifier The {@link Identifier|identifier} used to register the class in the DI container or the class name if not provided.
|
||||
* @param init An optional initializer {@link InitDelegate|function} which get the constructor of the class
|
||||
* as input and returns an instance of the class.
|
||||
* @see {@link InitDelegate} for more information on initializer functions.
|
||||
* @returns The decorator function to be applied on the class.
|
||||
* @throws An {@link IdentifierRequiredError} if the identifier is not provided and the class name is not available.
|
||||
* @example
|
||||
* ```ts
|
||||
* \@RegisterInstance('MyClassInstanceIdentifier', (constructor) => new constructor())
|
||||
@@ -22,43 +22,51 @@ import { InitDelegate } from '../types/InitDelegate';
|
||||
export function RegisterInstance<
|
||||
TargetType extends new (..._args: unknown[]) => InstanceType<TargetType>,
|
||||
>(
|
||||
identifier: Identifier,
|
||||
identifier?: Identifier,
|
||||
init?: InitDelegate<
|
||||
TargetType & { new (..._args: unknown[]): InstanceType<TargetType> },
|
||||
InstanceType<TargetType>
|
||||
>,
|
||||
) {
|
||||
return function (constructor: TargetType, ...args: unknown[]): void {
|
||||
// Get the instance of the DI container
|
||||
return function (
|
||||
constructor: TargetType,
|
||||
context: ClassDecoratorContext<TargetType>,
|
||||
): void {
|
||||
const _identifier = identifier ?? context.name;
|
||||
|
||||
if (_identifier == null) throw new IdentifierRequiredError();
|
||||
|
||||
const diContainer = TSinjex.getInstance();
|
||||
let instance: InstanceType<TargetType>;
|
||||
|
||||
/**
|
||||
* Get the instance of the class
|
||||
* and replace the lazy proxy with the instance
|
||||
* for performance optimization.
|
||||
*/
|
||||
const getAndRegisterInstance = (): void => {
|
||||
if (instance == null) {
|
||||
if (init) {
|
||||
instance = init(constructor);
|
||||
} else {
|
||||
instance = new constructor();
|
||||
}
|
||||
}
|
||||
diContainer.register(_identifier, instance);
|
||||
};
|
||||
|
||||
// Create a proxy to instantiate the class when needed (Lazy Initialization)
|
||||
let lazyProxy: unknown = new Proxy(
|
||||
const lazyProxy: unknown = new Proxy(
|
||||
{},
|
||||
{
|
||||
get(target, prop, receiver) {
|
||||
if (instance == null) {
|
||||
if (init) {
|
||||
instance = init(constructor);
|
||||
} else {
|
||||
instance = new constructor(...args);
|
||||
}
|
||||
}
|
||||
lazyProxy = instance;
|
||||
get(_target, prop, _receiver) {
|
||||
getAndRegisterInstance();
|
||||
|
||||
// Return the requested property of the instance
|
||||
return instance[prop as keyof InstanceType<TargetType>];
|
||||
},
|
||||
set(target, prop, value, receiver) {
|
||||
if (instance == null) {
|
||||
if (init) {
|
||||
instance = init(constructor);
|
||||
} else {
|
||||
instance = new constructor(...args);
|
||||
}
|
||||
}
|
||||
lazyProxy = instance;
|
||||
set(_target, prop, value, _receiver) {
|
||||
getAndRegisterInstance();
|
||||
|
||||
// Set the requested property of the instance
|
||||
return (instance[prop as keyof InstanceType<TargetType>] =
|
||||
@@ -67,7 +75,6 @@ export function RegisterInstance<
|
||||
},
|
||||
);
|
||||
|
||||
// Register the lazy proxy in the DI container
|
||||
diContainer.register(identifier, lazyProxy);
|
||||
diContainer.register(_identifier, lazyProxy);
|
||||
};
|
||||
}
|
||||
|
@@ -15,6 +15,19 @@ export class TSinjexError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Error class for missing identifiers in {@link ITSinjex} methods.
|
||||
*/
|
||||
export class IdentifierRequiredError extends TSinjexError {
|
||||
/**
|
||||
* Creates a new instance of {@link IdentifierRequiredError}
|
||||
*/
|
||||
constructor() {
|
||||
super('Identifier is required.');
|
||||
this.name = 'TSinjexIdentifierRequiredError';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Error class for dependency resolution errors in {@link ITSinjex}.
|
||||
* @see {@link ITSinjex.resolve}
|
||||
|
@@ -18,8 +18,6 @@
|
||||
"importHelpers": true,
|
||||
"isolatedModules": true,
|
||||
"resolveJsonModule": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"strictNullChecks": true,
|
||||
"strictPropertyInitialization": true,
|
||||
"lib": [
|
||||
|
Reference in New Issue
Block a user