Compare commits

..

25 Commits

Author SHA1 Message Date
dependabot[bot]
0343bd7a34 Bump typedoc from 0.26.5 to 0.26.11
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.26.5 to 0.26.11.
- [Release notes](https://github.com/TypeStrong/TypeDoc/releases)
- [Changelog](https://github.com/TypeStrong/typedoc/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/TypeDoc/compare/v0.26.5...v0.26.11)

---
updated-dependencies:
- dependency-name: typedoc
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-04 12:32:27 +00:00
2942e15fcf docs: Reflect changes to changelog 2024-08-24 03:13:56 +02:00
1d94b33542 ci: Add a build option for pre release buils from dev/* branches 2024-08-24 03:13:56 +02:00
08d58b2d41 build: Add new complete prepare deploy command 2024-08-24 03:13:56 +02:00
19f7be1e3d ci: Disable branch validation workflow 2024-08-23 21:34:18 +02:00
Max P.
a490ea980a Revert "feat: Update Identifier documentation in TypeScript"
This reverts commit 6e6a521c1f.
2024-08-23 21:23:56 +02:00
Max P.
d69eacf9be Revert "docs: Add Identifiers Changelog entry"
This reverts commit 099c8dbfa3.
2024-08-23 21:23:56 +02:00
099c8dbfa3 docs: Add Identifiers Changelog entry 2024-08-23 19:24:47 +02:00
6e6a521c1f feat: Update Identifier documentation in TypeScript 2024-08-23 19:24:47 +02:00
ac99f7d306 ci: Fix release naming in workflow 2024-08-23 00:25:57 +02:00
58767b85f7 docs: Reflect Version change in Changelog 2024-08-23 00:23:56 +02:00
5e095d7b09 docs: Push version to 0.1.0 2024-08-23 00:17:14 +02:00
32126c0784 docs: Add changelog entrys 2024-08-23 00:17:14 +02:00
5df69c219e test: Add additional tests for Inject decorator 2024-08-23 00:17:14 +02:00
5bc9aef9ad feat: Add initialization error handling and refactor Inject 2024-08-23 00:17:14 +02:00
ae9f25fe94 feat: Add new Error InitializationError to reflect errors during initialization of a dependency 2024-08-23 00:17:14 +02:00
4a97a46aed docs: Added **ChangeLog** file 2024-08-23 00:17:14 +02:00
e0542214c0 docs: Add Identifiers and Jest Sections to the README.md file 2024-08-23 00:17:14 +02:00
e6e304dfc7 ci: changed version format to prefix the version wth v 2024-08-23 00:17:14 +02:00
75333b3310 Add error handling and constructor checks to Inject
- Import additional exception classes from `src/interfaces/Exceptions`
- Modify `Inject` function to:
  - Accept `init` parameter as a function or `true` for instantiation
  - Throw specific errors: `DependencyResolutionError`, `InjectorError`, `NoInstantiationMethodError`
  - Ensure necessary dependencies are handled properly
  - Define property with `Object.defineProperty` for performance
- Add `hasConstructor` helper function to check if an object has a constructor
2024-08-23 00:17:14 +02:00
ba9ec70c77 Add InjectorError and NoInstantiationMethodError classes
- Added `InjectorError` class for handling injector errors
- Added `NoInstantiationMethodError` class for missing instantiation methods
- Both classes extend `TSinjexError` and provide detailed error messages
2024-08-23 00:17:14 +02:00
6f20913e4a Update DependencyResolutionError to use Identifier type
- Import `Identifier` from `src/types/Identifier`
- Change `identifier` parameter type in `DependencyResolutionError` constructor from `string` to `Identifier`
- Update error message to call `identifier.toString()`
2024-08-23 00:17:14 +02:00
c5ea21356c Update Identifier type to include symbol
- Modified `Identifier` type in `src/types/Identifier.ts` from `string` to `string | symbol`
2024-08-23 00:17:14 +02:00
9a4fdecaac Update warning message in TSinjex class
- Converted `identifier` to string in the deprecation warning.
2024-08-23 00:17:14 +02:00
6f189942f6 Ignore test files in Istanbul coverage reporting
- Added `/* istanbul ignore file */` comment to `Decorators.spec.ts`, `Functions.spec.ts`, `ITSinjex.spec.ts`
2024-08-23 00:17:14 +02:00
13 changed files with 839 additions and 85 deletions

View File

@@ -4,6 +4,7 @@ on:
push:
branches:
- main
- 'dev/*'
paths:
- 'package.json'
workflow_dispatch: # Allows manual execution of the workflow.
@@ -22,20 +23,14 @@ jobs:
with:
node-version: '20.8.0'
- name: Install Dependencies
run: npm install
- name: Run Tests
run: npm run test:verbose
- name: Build the Project
run: npm run build:tsc
- name: Install dependencies, run tests and build
run: npm run prepare:deploy
- name: Get the version
id: get_version
run: |
VERSION=$(npm run version:show | tail -n 1)
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "VERSION=v$VERSION" >> $GITHUB_ENV
shell: bash
- name: Get previous release tag
@@ -77,8 +72,9 @@ jobs:
echo "Generating release notes from ${{ env.PREVIOUS_TAG }} to HEAD..."
repo_url=$(git config --get remote.origin.url)
notes=$(git log ${{ env.PREVIOUS_TAG }}..HEAD --pretty=format:"- [\`%h\`]($repo_url/commit/%H): %s%n")
echo "Release notes:"
echo "See [CHANGELOG.md](./CHANGELOG.md) for more details."
echo "$notes"
echo ""
echo "### Changes in this release" > release_notes.md
echo "$notes" >> release_notes.md
shell: bash
@@ -90,17 +86,6 @@ jobs:
git config --local user.email "actions@github.com"
shell: bash
# - name: Create temporary branch
# id: create_temp_branch
# if: steps.check_version.outputs.skip_release == 'false'
# run: |
# git checkout --orphan release/v${{ env.VERSION }}
# git reset
# rm -f .gitignore
# git add README.md package.json LICENSE dist/ src/ tsconfig.json
# git commit -m "Prepare files for release ${{ env.VERSION }}"
# shell: bash
- name: Create and push tag
id: create_tag
if: steps.check_version.outputs.skip_release == 'false'
@@ -111,6 +96,15 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
- name: Set Release Prerelease Flag
id: set_prerelease_flag
run: |
if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
echo "PRE_RELEASE=false" >> $GITHUB_ENV
elif [[ "${{ github.ref }}" == refs/heads/dev/* ]]; then
echo "PRE_RELEASE=true" >> $GITHUB_ENV
fi
- name: Release
if: steps.check_version.outputs.skip_release == 'false'
uses: softprops/action-gh-release@v2
@@ -118,6 +112,6 @@ jobs:
tag_name: ${{ env.VERSION }}
name: Release ${{ env.VERSION }}
body_path: release_notes.md
prerelease: true
prerelease: ${{ env.PRE_RELEASE }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -3,7 +3,7 @@ name: Validate Branch Name on Pull Request
on:
pull_request:
branches:
- main
- UNDEFINED
jobs:
validate-branch-name-on-pull-request:

58
CHANGELOG.md Normal file
View File

@@ -0,0 +1,58 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- Add pre release building to release workflow on dev/* branches an version changes.
### Deprecated
### Removed
### Fixed
### Security
## [0.0.14]
### Added
- Added **ChangeLog** file and format it according to [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
- Added reference to **Semantic Versioning** in the changelog file. (History will be updated on time).
- Version format is now `v0.0.0` instead of `0.0.0`. Changes to this are also reflected in the workflos.
- Add `Identifiers` and `Jest` Sections to the `README.md` file.
- feat: Add new Error `InitializationError` to reflect errors during initialization of a dependency.
- feat: Add initialization error handling and refactor Inject.
- feat: After injecting a dependency, the lazzy loading getter will be replaced with the dependency itself.
- feat: remove the use of a private property to store the injected dependencies. Now the dependencies are stored in the property itself.
- test: Add tests for the new features.
### Deprecated
- Deprecated the old version format `0.0.0`.
### Removed
### Fixed
### Security
---
[unreleased]: https://github.com/PxaMMaxP/TSinjex/compare/0.0.14...HEAD
[0.0.14]: https://github.com/PxaMMaxP/TSinjex/compare/0.0.13...v0.0.14

View File

@@ -6,8 +6,14 @@
## Configuration
### Identifiers
Strings and symbols are possible for the **identifiers**.
### Jest
For the use of TSinjex with Jest, the corresponding source files can be found under `./src` of the TSinjex node_module folder. To use these files, the `moduleNameMapper` must be configured in the Jest configuration file. The following example shows how to configure the Jest configuration file to use the source files of TSinjex.
#### Example jest setup
```ts

482
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "ts-injex",
"version": "0.0.9",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "ts-injex",
"version": "0.0.9",
"version": "0.1.0",
"license": "MIT",
"dependencies": {
"eslint-plugin-prettier": "^5.2.1",
@@ -26,7 +26,7 @@
"istanbul-badges-readme": "^1.9.0",
"jest": "^29.7.0",
"ts-jest": "^29.2.3",
"typedoc": "^0.26.5",
"typedoc": "^0.26.11",
"typescript": "^5.5.4"
}
},
@@ -1188,14 +1188,56 @@
}
},
"node_modules/@shikijs/core": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.13.0.tgz",
"integrity": "sha512-Mj5NVfbAXcD1GnwOTSPl8hBn/T8UDpfFQTptp+p41n/CbUcJtOq98WaRD7Lz3hCglYotUTHUWtzu3JhK6XlkAA==",
"version": "1.22.2",
"resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.2.tgz",
"integrity": "sha512-bvIQcd8BEeR1yFvOYv6HDiyta2FFVePbzeowf5pPS1avczrPK+cjmaxxh0nx5QzbON7+Sv0sQfQVciO7bN72sg==",
"dev": true,
"dependencies": {
"@shikijs/engine-javascript": "1.22.2",
"@shikijs/engine-oniguruma": "1.22.2",
"@shikijs/types": "1.22.2",
"@shikijs/vscode-textmate": "^9.3.0",
"@types/hast": "^3.0.4",
"hast-util-to-html": "^9.0.3"
}
},
"node_modules/@shikijs/engine-javascript": {
"version": "1.22.2",
"resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.2.tgz",
"integrity": "sha512-iOvql09ql6m+3d1vtvP8fLCVCK7BQD1pJFmHIECsujB0V32BJ0Ab6hxk1ewVSMFA58FI0pR2Had9BKZdyQrxTw==",
"dev": true,
"dependencies": {
"@shikijs/types": "1.22.2",
"@shikijs/vscode-textmate": "^9.3.0",
"oniguruma-to-js": "0.4.3"
}
},
"node_modules/@shikijs/engine-oniguruma": {
"version": "1.22.2",
"resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.2.tgz",
"integrity": "sha512-GIZPAGzQOy56mGvWMoZRPggn0dTlBf1gutV5TdceLCZlFNqWmuc7u+CzD0Gd9vQUTgLbrt0KLzz6FNprqYAxlA==",
"dev": true,
"dependencies": {
"@shikijs/types": "1.22.2",
"@shikijs/vscode-textmate": "^9.3.0"
}
},
"node_modules/@shikijs/types": {
"version": "1.22.2",
"resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.2.tgz",
"integrity": "sha512-NCWDa6LGZqTuzjsGfXOBWfjS/fDIbDdmVDug+7ykVe1IKT4c1gakrvlfFYp5NhAXH/lyqLM8wsAPo5wNy73Feg==",
"dev": true,
"dependencies": {
"@shikijs/vscode-textmate": "^9.3.0",
"@types/hast": "^3.0.4"
}
},
"node_modules/@shikijs/vscode-textmate": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz",
"integrity": "sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==",
"dev": true
},
"node_modules/@sinclair/typebox": {
"version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
@@ -1479,6 +1521,15 @@
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
"dev": true
},
"node_modules/@types/mdast": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
"integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==",
"dev": true,
"dependencies": {
"@types/unist": "*"
}
},
"node_modules/@types/node": {
"version": "20.14.15",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.15.tgz",
@@ -1725,8 +1776,7 @@
"node_modules/@ungap/structured-clone": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
"peer": true
"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="
},
"node_modules/abab": {
"version": "2.0.6",
@@ -2295,6 +2345,16 @@
}
]
},
"node_modules/ccount": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
"integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -2319,6 +2379,26 @@
"node": ">=10"
}
},
"node_modules/character-entities-html4": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
"integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/character-entities-legacy": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz",
"integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/ci-info": {
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
@@ -2396,6 +2476,16 @@
"node": ">= 0.8"
}
},
"node_modules/comma-separated-tokens": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
"integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/comment-parser": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz",
@@ -2627,6 +2717,15 @@
"node": ">=0.4.0"
}
},
"node_modules/dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/detect-newline": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
@@ -2636,6 +2735,19 @@
"node": ">=8"
}
},
"node_modules/devlop": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
"integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
"dev": true,
"dependencies": {
"dequal": "^2.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/diff-sequences": {
"version": "29.6.3",
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
@@ -3948,6 +4060,42 @@
"node": ">= 0.4"
}
},
"node_modules/hast-util-to-html": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz",
"integrity": "sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==",
"dev": true,
"dependencies": {
"@types/hast": "^3.0.0",
"@types/unist": "^3.0.0",
"ccount": "^2.0.0",
"comma-separated-tokens": "^2.0.0",
"hast-util-whitespace": "^3.0.0",
"html-void-elements": "^3.0.0",
"mdast-util-to-hast": "^13.0.0",
"property-information": "^6.0.0",
"space-separated-tokens": "^2.0.0",
"stringify-entities": "^4.0.0",
"zwitch": "^2.0.4"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-whitespace": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
"integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==",
"dev": true,
"dependencies": {
"@types/hast": "^3.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/html-encoding-sniffer": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
@@ -3965,6 +4113,16 @@
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
"dev": true
},
"node_modules/html-void-elements": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz",
"integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/http-proxy-agent": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
@@ -5327,6 +5485,27 @@
"markdown-it": "bin/markdown-it.mjs"
}
},
"node_modules/mdast-util-to-hast": {
"version": "13.2.0",
"resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz",
"integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==",
"dev": true,
"dependencies": {
"@types/hast": "^3.0.0",
"@types/mdast": "^4.0.0",
"@ungap/structured-clone": "^1.0.0",
"devlop": "^1.0.0",
"micromark-util-sanitize-uri": "^2.0.0",
"trim-lines": "^3.0.0",
"unist-util-position": "^5.0.0",
"unist-util-visit": "^5.0.0",
"vfile": "^6.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/mdurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
@@ -5348,6 +5527,95 @@
"node": ">= 8"
}
},
"node_modules/micromark-util-character": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz",
"integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"dependencies": {
"micromark-util-symbol": "^2.0.0",
"micromark-util-types": "^2.0.0"
}
},
"node_modules/micromark-util-encode": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz",
"integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
]
},
"node_modules/micromark-util-sanitize-uri": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz",
"integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
"dependencies": {
"micromark-util-character": "^2.0.0",
"micromark-util-encode": "^2.0.0",
"micromark-util-symbol": "^2.0.0"
}
},
"node_modules/micromark-util-symbol": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz",
"integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
]
},
"node_modules/micromark-util-types": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz",
"integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==",
"dev": true,
"funding": [
{
"type": "GitHub Sponsors",
"url": "https://github.com/sponsors/unifiedjs"
},
{
"type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
]
},
"node_modules/micromatch": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
@@ -5567,6 +5835,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/oniguruma-to-js": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz",
"integrity": "sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==",
"dev": true,
"dependencies": {
"regex": "^4.3.2"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/optionator": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
@@ -5885,6 +6165,16 @@
"node": ">= 6"
}
},
"node_modules/property-information": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz",
"integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
@@ -5958,6 +6248,12 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
},
"node_modules/regex": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/regex/-/regex-4.4.0.tgz",
"integrity": "sha512-uCUSuobNVeqUupowbdZub6ggI5/JZkYyJdDogddJr60L764oxC2pMZov1fQ3wM9bdyzUILDG+Sqx6NAKAz9rKQ==",
"dev": true
},
"node_modules/regexp.prototype.flags": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz",
@@ -6208,12 +6504,16 @@
}
},
"node_modules/shiki": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/shiki/-/shiki-1.13.0.tgz",
"integrity": "sha512-e0dWfnONbEv6xl7FJy3XIhsVHQ/65XHDZl92+6H9+4xWjfdo7pmkqG7Kg47KWtDiEtzM5Z+oEfb4vtRvoZ/X9w==",
"version": "1.22.2",
"resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.2.tgz",
"integrity": "sha512-3IZau0NdGKXhH2bBlUk4w1IHNxPh6A5B2sUpyY+8utLu2j/h1QpFkAaUA1bAMxOWWGtTWcAh531vnS4NJKS/lA==",
"dev": true,
"dependencies": {
"@shikijs/core": "1.13.0",
"@shikijs/core": "1.22.2",
"@shikijs/engine-javascript": "1.22.2",
"@shikijs/engine-oniguruma": "1.22.2",
"@shikijs/types": "1.22.2",
"@shikijs/vscode-textmate": "^9.3.0",
"@types/hast": "^3.0.4"
}
},
@@ -6280,6 +6580,16 @@
"source-map": "^0.6.0"
}
},
"node_modules/space-separated-tokens": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz",
"integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/spdx-exceptions": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
@@ -6403,6 +6713,20 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/stringify-entities": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
"integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==",
"dev": true,
"dependencies": {
"character-entities-html4": "^2.0.0",
"character-entities-legacy": "^3.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
@@ -6557,6 +6881,16 @@
"node": ">=12"
}
},
"node_modules/trim-lines": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
"integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/ts-api-utils": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz",
@@ -6761,16 +7095,16 @@
}
},
"node_modules/typedoc": {
"version": "0.26.5",
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.5.tgz",
"integrity": "sha512-Vn9YKdjKtDZqSk+by7beZ+xzkkr8T8CYoiasqyt4TTRFy5+UHzL/mF/o4wGBjRF+rlWQHDb0t6xCpA3JNL5phg==",
"version": "0.26.11",
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.11.tgz",
"integrity": "sha512-sFEgRRtrcDl2FxVP58Ze++ZK2UQAEvtvvH8rRlig1Ja3o7dDaMHmaBfvJmdGnNEFaLTpQsN8dpvZaTqJSu/Ugw==",
"dev": true,
"dependencies": {
"lunr": "^2.3.9",
"markdown-it": "^14.1.0",
"minimatch": "^9.0.5",
"shiki": "^1.9.1",
"yaml": "^2.4.5"
"shiki": "^1.16.2",
"yaml": "^2.5.1"
},
"bin": {
"typedoc": "bin/typedoc"
@@ -6779,7 +7113,7 @@
"node": ">= 18"
},
"peerDependencies": {
"typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x"
"typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x"
}
},
"node_modules/typedoc/node_modules/brace-expansion": {
@@ -6845,6 +7179,74 @@
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
},
"node_modules/unist-util-is": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz",
"integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==",
"dev": true,
"dependencies": {
"@types/unist": "^3.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/unist-util-position": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz",
"integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==",
"dev": true,
"dependencies": {
"@types/unist": "^3.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/unist-util-stringify-position": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
"integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==",
"dev": true,
"dependencies": {
"@types/unist": "^3.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/unist-util-visit": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz",
"integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==",
"dev": true,
"dependencies": {
"@types/unist": "^3.0.0",
"unist-util-is": "^6.0.0",
"unist-util-visit-parents": "^6.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/unist-util-visit-parents": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz",
"integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==",
"dev": true,
"dependencies": {
"@types/unist": "^3.0.0",
"unist-util-is": "^6.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/universalify": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
@@ -6915,6 +7317,34 @@
"node": ">=10.12.0"
}
},
"node_modules/vfile": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
"integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==",
"dev": true,
"dependencies": {
"@types/unist": "^3.0.0",
"vfile-message": "^4.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/vfile-message": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz",
"integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==",
"dev": true,
"dependencies": {
"@types/unist": "^3.0.0",
"unist-util-stringify-position": "^4.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/w3c-xmlserializer": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
@@ -7116,9 +7546,9 @@
"dev": true
},
"node_modules/yaml": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz",
"integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==",
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz",
"integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==",
"dev": true,
"bin": {
"yaml": "bin.mjs"
@@ -7164,6 +7594,16 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/zwitch": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
"integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
}
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "ts-injex",
"version": "0.0.13",
"version": "0.1.0",
"description": "Simple boilerplate code free dependency injection system for TypeScript.",
"type": "module",
"main": "./dist/index.js",
@@ -22,7 +22,8 @@
"docs:fix:coverage": "node scripts/fix-coverage-paths.cjs",
"docs:generate:badge": "node scripts/generate-badge.cjs",
"docs:fix:escape": "node scripts/replace-doc-escaping.cjs",
"version:show": "node -e \"console.log(require('./package.json').version)\""
"version:show": "node -e \"console.log(require('./package.json').version)\"",
"prepare:deploy": "npm install && npm run test:verbose && npm run build:tsc"
},
"repository": {
"type": "git",
@@ -44,7 +45,7 @@
"eslint-plugin-override": "https://github.com/PxaMMaxP/eslint-plugin-override",
"jest": "^29.7.0",
"ts-jest": "^29.2.3",
"typedoc": "^0.26.5",
"typedoc": "^0.26.11",
"istanbul-badges-readme": "^1.9.0",
"axios": "^1.7.2"
},

View File

@@ -1,3 +1,4 @@
/* istanbul ignore file */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Inject } from 'src/decorators/Inject';
import { DependencyResolutionError } from 'src/interfaces/Exceptions';
@@ -117,6 +118,130 @@ export function test_InjectDecorator(
}
expect(_error).toBeInstanceOf(DependencyResolutionError);
});
it('should replace the property with the resolved dependency', () => {
container.register('MockDependencyIdentifier', {
value: 'test-value',
});
class TestClass {
@Inject('MockDependencyIdentifier')
private readonly _dependency!: any;
public getDependency() {
return this._dependency;
}
public isDependencyTypeofFunction() {
return typeof this._dependency === 'function';
}
}
const instance = new TestClass();
expect(instance.getDependency().value).toBe('test-value');
expect(instance.isDependencyTypeofFunction()).toBe(false);
expect(instance.getDependency().value).toBe('test-value');
});
it('should use a empty initializer when none is provided but true', () => {
container.register(
'MockDependencyIdentifier',
class X {
public value: string = 'test-value';
constructor() {}
},
);
class TestClass {
@Inject('MockDependencyIdentifier', true)
private readonly _dependency!: any;
public getDependency() {
return this._dependency;
}
}
const instance = new TestClass();
expect(instance.getDependency().value).toBe('test-value');
});
it('should throw an error when the dependency has no instantiation method', () => {
container.register('MockDependencyIdentifier', {
value: 'test-value',
});
class TestClass {
@Inject('MockDependencyIdentifier', true)
private readonly _dependency!: any;
public getDependency() {
return this._dependency;
}
}
expect(() => {
const instance = new TestClass();
instance.getDependency();
}).toThrow(new RegExp('No instantiation method found for.*'));
});
it('should not throw an error when the dependency has no instantiation method if not necessary', () => {
container.register('MockDependencyIdentifier', {
value: 'test-value',
});
class TestClass {
@Inject('MockDependencyIdentifier', true, false)
private readonly _dependency!: any;
public getDependency() {
return this._dependency;
}
}
expect(() => {
const instance = new TestClass();
instance.getDependency();
}).not.toThrow(new RegExp('No instantiation method found for.*'));
});
it('should throw an error when the dependency cannot be resolved', () => {
container.register('MockDependencyIdentifier', null);
class TestClass {
@Inject('MockDependencyIdentifier', true)
private readonly _dependency!: any;
public getDependency() {
return this._dependency;
}
}
expect(() => {
const instance = new TestClass();
instance.getDependency();
}).toThrow(new RegExp('.*could not be resolved.*'));
});
it('should not throw an error when the dependency cannot be resolved if not necessary', () => {
container.register('MockDependencyIdentifier', null);
class TestClass {
@Inject('MockDependencyIdentifier', true, false)
private readonly _dependency!: any;
public getDependency() {
return this._dependency;
}
}
expect(() => {
const instance = new TestClass();
instance.getDependency();
}).not.toThrow(new RegExp('.*could not be resolved.*'));
});
});
}

View File

@@ -1,3 +1,4 @@
/* istanbul ignore file */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { ITSinjex, ITSinjex_ } from 'src/interfaces/ITSinjex';

View File

@@ -1,3 +1,4 @@
/* istanbul ignore file */
import { ITSinjex_, ITSinjex } from '../interfaces/ITSinjex';
/**

View File

@@ -114,7 +114,7 @@ export class TSinjex implements ITSinjex {
}
if (dependency.deprecated) {
console.warn(`Dependency ${identifier} is deprecated`);
console.warn(`Dependency ${identifier.toString()} is deprecated`);
// Remove the deprecation warning; it should only be logged once.
dependency.deprecated = false;

View File

@@ -1,3 +1,9 @@
import {
DependencyResolutionError,
InitializationError,
InjectorError,
NoInstantiationMethodError,
} from 'src/interfaces/Exceptions';
import { TSinjex } from '../classes/TSinjex';
import { Identifier } from '../types/Identifier';
import { InitDelegate } from '../types/InitDelegate';
@@ -8,12 +14,17 @@ import { InitDelegate } from '../types/InitDelegate';
* @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 An optional initializer function to transform the dependency before injection.
* @param init Optional an initializer 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 A {@link DependencyResolutionError} if the dependency is not found and necessary.
* @throws **Only throws errors if the dependency is necessary.**
* @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.
* @throws An {@link InitializationError} if an error occurs during the initialization process.
* @example
* ```ts
* class MyClass {
@@ -31,47 +42,110 @@ import { InitDelegate } from '../types/InitDelegate';
*/
export function Inject<T, U>(
identifier: Identifier,
init?: InitDelegate<T, U>,
init?: InitDelegate<T, U> | true,
necessary = true,
) {
return function (target: unknown, propertyKey: string | symbol): void {
// Unique symbol to store the private property
const privatePropertyKey: unique symbol = Symbol();
// Get the DI container instance
const diContainer = TSinjex.getInstance();
// Function to evaluate the dependency lazily
// to avoid circular dependencies, not found dependencies, etc.
const evaluate = (): T | undefined => {
return diContainer.resolve<T>(identifier, necessary);
/**
* 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);
};
// Define the property
Object.defineProperty(target, propertyKey, {
get() {
// If the property is not defined, evaluate the dependency
if (!this.hasOwnProperty(privatePropertyKey)) {
if (init) {
try {
this[privatePropertyKey] = init(evaluate() as T);
} catch (error) {
if (necessary) {
throw error;
}
}
} else {
this[privatePropertyKey] = evaluate();
}
}
let instance: T | U | undefined;
return this[privatePropertyKey];
const dependency: T | 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 (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, propertyKey, {
value: instance,
writable: false,
enumerable: false,
configurable: false,
});
return instance;
},
// Not necessary to set the property
// set(value: PropertieType) {
// this[privatePropertyKey] = value;
// },
enumerable: true,
configurable: false,
/**
* Make the property configurable to allow replacing it
*/
configurable: true,
});
};
}
/**
* Tries to execute a function and catches any errors that occur.
* If the function is necessary and an error occurs, it throws the error
* with the specified error class and identifier.
* @param fn The function to execute.
* @param necessary If true, throws an error if an error occurs.
* @param identifier The identifier of the dependency.
* @param errorClass The error class to throw if an error occurs.
* @returns The result of the function or undefined if an error occurs and the function is not necessary.
*/
function tryAndCatch<ReturnType, ErrorType>(
fn: () => ReturnType,
necessary: boolean,
identifier?: Identifier,
errorClass?: ErrorType,
): ReturnType | undefined {
try {
return fn();
} catch (error) {
if (necessary)
throw new (errorClass != null ? errorClass : error)(
identifier ?? 'not specified',
error,
);
else return undefined;
}
}
/**
* Checks if an object has a constructor.
* @param obj The object to check.
* @returns True if the object has a constructor, false otherwise.
*/
function hasConstructor<T>(obj: T): obj is T & { new (): unknown } {
const _obj = obj as unknown as { prototype?: { constructor?: unknown } };
return (
_obj?.prototype != null &&
typeof _obj.prototype.constructor === 'function'
);
}

View File

@@ -1,3 +1,4 @@
import { Identifier } from 'src/types/Identifier';
import { ITSinjex } from './ITSinjex';
/**
@@ -23,8 +24,61 @@ export class DependencyResolutionError extends TSinjexError {
* Creates a new instance of {@link DependencyResolutionError}
* @param identifier **The identifier of the dependency**
*/
constructor(identifier: string) {
super(`Dependency ${identifier} could not be resolved.`);
constructor(identifier: Identifier) {
super(`Dependency ${identifier.toString()} could not be resolved.`);
this.name = 'TSinjexResolutionError';
}
}
/**
* Error class for Injector errors in {@link ITSinjex}.
* @see {@link ITSinjex.inject}
*/
export class InjectorError extends TSinjexError {
/**
* Creates a new instance of {@link InjectorError}
* @param identifier **The identifier of the dependency**
* @param originalError **The original error that caused the injection error**
*/
constructor(identifier: Identifier, originalError?: Error) {
super(
`Error injecting dependency ${identifier.toString()} with error: "${originalError}"`,
);
this.name = 'TSinjexInjectorError';
}
}
/**
* Error class for missing instantiation methods in {@link ITSinjex}.
* @see {@link ITSinjex.inject}
*/
export class NoInstantiationMethodError extends TSinjexError {
/**
* Creates a new instance of {@link NoInstantiationMethodError}
* @param identifier **The identifier of the dependency**
*/
constructor(identifier: Identifier) {
super(
`No instantiation method found for dependency ${identifier.toString()}.`,
);
this.name = 'TSinjexNoInstantiationMethodError';
}
}
/**
* Error class for errors during the initialization of a dependency in {@link ITSinjex}.
* @see {@link ITSinjex.inject}
*/
export class InitializationError extends TSinjexError {
/**
* Creates a new instance of {@link InitializationError}
* @param identifier **The identifier of the dependency**
* @param originalError **The original error that caused the initialization error**
*/
constructor(identifier: Identifier, originalError?: Error) {
super(
`Error initializing dependency ${identifier.toString()} with error: "${originalError}"`,
);
this.name = 'TSinjexInitializationError';
}
}

View File

@@ -8,4 +8,4 @@
* I.e. a class `ClassA` that implements the interface `IClassA` and is
* registered as a dependent class is registered under the interface name `IClassA`.
*/
export type Identifier = string;
export type Identifier = string | symbol;