@teqfw/di 0.30.0 → 0.30.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,16 +1,69 @@
1
1
  # @teqfw/di
2
2
 
3
- A Dependency Injection container for regular JavaScript is provided, which can be used in both browser and Node.js
4
- applications with JS, and in Node.js only with TS.
3
+ ![npms.io](https://img.shields.io/npm/dm/@teqfw/di)
4
+ ![jsdelivr](https://img.shields.io/jsdelivr/npm/hm/@teqfw/di)
5
5
 
6
- **This library exclusively supports ES6 modules.**
6
+ `@teqfw/di` is a lightweight dependency injection container for standard JavaScript, enabling late binding of code
7
+ objects with minimal manual configuration. It integrates smoothly in both browser and Node.js environments, supporting
8
+ flexibility, modularity, and easier testing for your applications.
7
9
 
8
- The primary objective of this library is the late binding for code objects with minimal manual configuration for the
9
- object container. All linking instructions are encapsulated within the dependency identifiers and used in constructors
10
- or factory functions (the constructor injection scheme):
10
+ Unlike typical object containers, `@teqfw/di` requires no manual registration of objects, instead mapping dependency IDs
11
+ directly to their source paths for greater simplicity.
11
12
 
12
- ```js
13
- export default class App_Main {
13
+ **This library is specifically optimized for ES6 modules, ensuring top performance and compatibility. It does not
14
+ support CommonJS, AMD, UMD, or other module formats.**
15
+
16
+ While this library is primarily designed for JavaScript, it is also fully compatible with TypeScript. Developers can use
17
+ TypeScript to compose dependency identifiers in the same way as in JavaScript. It is important to ensure that TypeScript
18
+ transpiles the source code to ES6 modules for proper functionality. With this setup, TypeScript users can effectively
19
+ leverage the benefits of this library without any additional configuration.
20
+
21
+ ## Samples
22
+
23
+ Explore `@teqfw/di` in action through the following demo applications:
24
+
25
+ - [demo-di-app](https://flancer64.github.io/demo-di-app/): A simple demonstration of dependency injection with
26
+ `@teqfw/di`.
27
+ - [demo-wa-esm-openai](https://github.com/flancer64/demo-wa-esm-openai): Integrates OpenAI with ES6 modules.
28
+ - [pwa-wallet](https://github.com/flancer64/pwa-wallet): A progressive web application wallet showcasing the library's
29
+ modularity.
30
+ - [spa-remote-console](https://github.com/flancer64/spa-remote-console): Demonstrates remote console functionality in a
31
+ single-page application.
32
+ - [demo-webauthn-pubkey](https://github.com/flancer64/demo-webauthn-pubkey): Uses Web Authentication (WebAuthn) with
33
+ public key credentials.
34
+ - [tg-bot-habr-demo-grammy](https://github.com/flancer64/tg-bot-habr-demo-grammy): A Telegram bot demo built with the
35
+ grammY library.
36
+
37
+ These projects offer practical examples and insights into using `@teqfw/di` effectively!
38
+
39
+ ## Example of Typical Usage
40
+
41
+ Using `@teqfw/di` typically involves a few simple steps: organizing the file structure, declaring dependencies,
42
+ configuring the container, and finally retrieving the main object with injected dependencies.
43
+
44
+ ### Step 1: Organize File Structure
45
+
46
+ Here’s an example of how files might be organized in a project. This structure can vary depending on your project needs,
47
+ as the container can be configured to work with any layout (e.g., within `/home/user/project/`):
48
+
49
+ ```
50
+ ./src/
51
+ ./Service/
52
+ ./Customer.js
53
+ ./Sale.js
54
+ ./Config.js
55
+ ./Logger.js
56
+ ./Main.js
57
+ ```
58
+
59
+ ### Step 2: Declare Dependencies
60
+
61
+ In your code, declare dependencies by defining them as keys in the constructor. Dependency identifiers here follow a
62
+ namespace style similar to PHP Zend 1, which is used by default in this library. You can also implement a custom parser
63
+ if you prefer a different naming convention or mapping strategy.
64
+
65
+ ```js
66
+ export default class App_Main {
14
67
  constructor(
15
68
  {
16
69
  App_Config$: config,
@@ -18,91 +71,175 @@ export default class App_Main {
18
71
  App_Service_Customer$: servCustomer,
19
72
  App_Service_Sale$: servSale,
20
73
  }
21
- ) { ... }
22
-
74
+ ) { /* ... */ }
23
75
  }
24
- ```
76
+ ```
25
77
 
26
- The files corresponded to this case:
78
+ ### Step 3: Configure the Container
27
79
 
28
- ```
29
- ./src/
30
- ./Service/
31
- ./Customer.js
32
- ./Sale.js
33
- ./Config.js
34
- ./Logger.js
35
- ./Main.js
36
- ```
80
+ Next, set up the container and configure it to use the correct namespace and path for your dependencies:
37
81
 
38
- Just set up a mapping rules for the container:
39
-
40
- ```js
41
- import Container from '@teqfw/di';
82
+ ```js
83
+ import Container from '@teqfw/di';
42
84
 
85
+ // Create a new instance of the container
43
86
  const container = new Container();
87
+
88
+ // Get the resolver from the container
44
89
  const resolver = container.getResolver();
45
- resolver.addNamespaceRoot('App_', '/path/to/src'); // or 'https://cdn.jsdelivr.net/npm/@vendor/pkg@latest/src'
90
+
91
+ // Define the namespace root for dependencies, allowing the container to resolve identifiers like 'App_*'
92
+ resolver.addNamespaceRoot('App_', '/home/user/project/src');
93
+ ```
94
+
95
+ ### Step 4: Retrieve the Main Object with Dependencies
96
+
97
+ Finally, retrieve your main application instance. The container automatically injects all declared dependencies:
98
+
99
+ ```js
100
+ // Retrieve the main application instance as a singleton asynchronously
46
101
  const app = await container.get('App_Main$');
47
- ```
102
+ ```
103
+
104
+ ## Key Benefits
105
+
106
+ `@teqfw/di` offers the core functionality of any object container — creating objects and injecting dependencies — with
107
+ extensive flexibility and configurability. This allows the library to adapt seamlessly to a wide range of project needs.
108
+ Here’s what makes it stand out:
109
+
110
+ - **Automatic Dependency Resolution**: The library simplifies managing complex objects and their dependencies by
111
+ automatically resolving and injecting them based on container configuration. This basic functionality works out of the
112
+ box but can be fully customized if needed.
113
+
114
+ - **Flexible Dependency ID Configuration**: With customizable parsers and chunks, you can define unique ID schemes for
115
+ dependencies, making it easy to adapt the library to specific naming conventions or custom mapping rules.
116
+
117
+ - **Mapping IDs to Source Modules via Resolvers**: Thanks to resolvers, `@teqfw/di` lets you map dependency IDs to their
118
+ source locations effortlessly. This makes the library adaptable to any project structure or file layout.
119
+
120
+ - **Preprocessing for Enhanced Control**: Built-in preprocessing allows modifying dependencies at the time of creation,
121
+ enabling local overrides or adjustments in functionality. This is especially useful for larger projects, where
122
+ different teams may tailor dependencies to their specific requirements. The default preprocessing can also be replaced
123
+ to suit more precise needs.
48
124
 
49
- That's all.
125
+ - **Interfaces and Dependencies Without TypeScript**: `@teqfw/di` allows you to define interfaces using standard
126
+ JavaScript files with JSDoc annotations. The container supports configuring dependencies to replace interfaces with
127
+ project-specific implementations, offering flexibility without requiring TypeScript.
50
128
 
51
- ## The main benefits
129
+ - **Postprocessing for Object Customization**: Use postprocessing to add wrappers or extend created objects. This can be
130
+ valuable for adding factories, logging, or other behavior, tailored to each project’s requirements.
52
131
 
53
- * **Late Binding**: Enjoy all the typical advantages of late binding during runtime, including flexibility, testability,
54
- modularity, manageability, and clear separation of concerns.
55
- * **Integration with ES6 Modules**: Seamlessly integrate singletons and instances based on ES6 module exports.
56
- * **Interface Usage in Vanilla JS**: Utilize "interfaces" in standard JavaScript, along with dependency substitution (
57
- preprocessing).
58
- * **Object Wrapping**: Add wrappers to created objects (postprocessing) for enhanced functionality.
132
+ These features make `@teqfw/di` a powerful, adaptable DI container that not only provides ready-to-use solutions but can
133
+ be easily customized to meet unique project demands.
59
134
 
60
135
  ## Installation
61
136
 
62
- NodeJS:
137
+ ### For Node.js
63
138
 
64
- ```shell
65
- $ npm i --save @teqfw/di
66
- ```
139
+ To install `@teqfw/di` in a Node.js environment, use the following command:
140
+
141
+ ```shell
142
+ $ npm install @teqfw/di
143
+ ```
144
+
145
+ Then, import and initialize the container:
67
146
 
68
- Web as ESM (~5Kb):
147
+ ```js
148
+ import Container from '@teqfw/di';
149
+
150
+ /** @type {TeqFw_Di_Container} */
151
+ const container = new Container();
152
+ ```
69
153
 
70
- ```html
154
+ ### For the Browser (ESM Module)
155
+
156
+ To use `@teqfw/di` in a browser environment with ES modules, include it as follows (~5KB):
157
+
158
+ ```html
71
159
 
72
160
  <script type="module">
73
- import {default as Container} from 'https://cdn.jsdelivr.net/npm/@teqfw/di@latest/+esm';
161
+ import Container from 'https://cdn.jsdelivr.net/npm/@teqfw/di@latest/+esm';
74
162
 
75
163
  /** @type {TeqFw_Di_Container} */
76
164
  const container = new Container();
77
- ...
78
165
  </script>
79
- ```
166
+ ```
167
+
168
+ ### For the Browser (UMD Module)
80
169
 
81
- Web as UMD (~5Kb):
170
+ Alternatively, you can use the UMD version in the browser (~5KB):
82
171
 
83
- ```html
172
+ ```html
84
173
 
85
174
  <script src="https://cdn.jsdelivr.net/npm/@teqfw/di@latest/dist/umd.js"></script>
86
175
  <script>
87
176
  const {default: Container} = window.TeqFw_Di_Container;
88
177
  /** @type {TeqFw_Di_Container} */
89
178
  const container = new Container();
90
- ...
91
179
  </script>
92
- ```
180
+ ```
181
+
182
+ ---
183
+
184
+ ## Using the Container
185
+
186
+ ### In Node.js
187
+
188
+ 1. **Configure Dependency Mapping**: Configure the resolver to detect the platform environment. Then, set up namespace
189
+ roots to map dependency IDs to their source paths.
190
+
191
+ ```js
192
+ import { platform } from 'node:process';
193
+
194
+ const resolver = container.getResolver();
195
+ resolver.setWindowsEnv(platform === 'win32'); // Adjusts for Windows environment if needed
196
+ resolver.addNamespaceRoot('App_', '/path/to/src');
197
+ ```
198
+
199
+ 2. **Retrieve Singleton Instances**: Retrieve the main application instance as a singleton asynchronously:
93
200
 
94
- ## Types of Dependency ID
201
+ ```js
202
+ const app = await container.get('App_Main$');
203
+ ```
95
204
 
96
- * `App_Service`=> `import * as Service from './App/Service.js'` as ES Module
97
- * `App_Service.default` => `import {default} from './App/Service.js'` default export as-is
98
- * `App_Service.name` => `import {name} from './App/Service.js'` named export as-is
99
- * `App_Service$` => `import {default} from './App/Service.js'; return res ?? (res = default({...}));` as singleton for
100
- container
101
- * `App_Service$$` => `import {default} from './App/Service.js'; return new default({...})` as instance for every
102
- dep
103
- * `App_Service.name$` => `import {name} from './App/Service.js'; return res ?? (res = name({...}));` as singleton
104
- * `App_Service.name$$` => `import {name} from './App/Service.js'; const res = new name({...})` as instance
105
- * `...(proxy,factory,...)`: add custom wrappers on postprocessing
205
+ ### In the Browser
206
+
207
+ 1. **Configure Dependency Mapping**: Set up namespace roots to map dependency IDs to their source paths, using URLs as
208
+ needed.
209
+
210
+ ```js
211
+ const resolver = container.getResolver();
212
+ resolver.addNamespaceRoot('App_', 'https://cdn.jsdelivr.net/npm/@flancer64/demo-di-app@0.2/src');
213
+ ```
214
+
215
+ 2. **Retrieve Singleton Instances**: Retrieve the main application instance as a singleton asynchronously:
216
+
217
+ ```js
218
+ const app = await container.get('App_Main$');
219
+ ```
220
+
221
+ With these steps, the container is configured to automatically resolve and inject dependencies based on your setup,
222
+ whether in Node.js or in a browser environment.
223
+
224
+ ## Dependency ID Types
225
+
226
+ `@teqfw/di` supports various dependency ID formats to match different import styles and object requirements. Here’s a
227
+ quick reference:
228
+
229
+ | Dependency ID | Import Style | Description |
230
+ |-----------------------------|--------------------------------------------------------|-------------------------------------------------------------------------------------------------------|
231
+ | `App_Service` | `import * as Service from './App/Service.js';` | Imports the entire module as an ES module. |
232
+ | `App_Service.default` | `import {default} from './App/Service.js';` | Imports the default export as-is. |
233
+ | `App_Service.name` | `import {name} from './App/Service.js';` | Imports a named export as-is. |
234
+ | `App_Service$` | `import {default as Factory} from './App/Service.js';` | Uses default export as a singleton for the container. |
235
+ | `App_Service$$` | `import {default as Factory} from './App/Service.js';` | Creates a new instance from the default export for each dependency. |
236
+ | `App_Service.name$` | `import {name} from './App/Service.js';` | Uses a named export as a singleton. |
237
+ | `App_Service.name$$` | `import {name} from './App/Service.js';` | Creates a new instance from a named export for each dependency. |
238
+ | `App_Service.name$$(proxy)` | `import {name} from './App/Service.js';` | Applies a custom wrapper to the created object in postprocessing, using a handler function `proxy()`. |
239
+
240
+ ### Example Usage
241
+
242
+ Here’s an example showing a class with multiple dependencies, each using different dependency IDs:
106
243
 
107
244
  ```js
108
245
  export default class App_Main {
@@ -118,16 +255,27 @@ export default class App_Main {
118
255
  'App_Service.name(factory)': factoryToCreateInstancesFromNamedExport,
119
256
  }
120
257
  ) {
121
- const {default as SrvDef, name as SrvName} = EsModule; // deconstruct the module and access the exports
258
+ const {default: SrvDef, name: SrvName} = EsModule; // Deconstruct the module and access the exports
122
259
  }
123
-
124
260
  }
125
261
  ```
126
262
 
127
- ## Resume
263
+ ## Summary
264
+
265
+ `@teqfw/di` is a versatile and lightweight dependency injection container tailored for modern JavaScript applications.
266
+ With its flexible dependency mapping, customizable ID configurations, and support for dynamic object creation,
267
+ `@teqfw/di` empowers developers to build modular, testable, and scalable codebases.
268
+
269
+ Whether you’re working in Node.js or a browser environment, `@teqfw/di` provides a solid foundation with built-in
270
+ functionality that you can further adapt to fit your project’s unique requirements. You are encouraged to explore and
271
+ extend this library as needed to create your ideal development environment.
272
+
273
+ For any questions, feedback, or collaboration opportunities, please feel free to reach out through the following
274
+ channels:
275
+
276
+ - **Website**: [wiredgeese.com](https://wiredgeese.com)
277
+ - **LinkedIn**: [LinkedIn Profile](https://www.linkedin.com/in/aleksandrs-gusevs-011ba928/)
278
+
279
+ You can also leave suggestions, feedback, and feature requests directly on GitHub by opening an issue in the repository.
128
280
 
129
- `@teqfw/di` offers Dependency Injection for regular JavaScript with minimal manual configuration, supporting both
130
- browser and Node.js environments. Its use of late binding and an object container in JavaScript applications, along with
131
- the ability to modify the behavior of created objects (via pseudo-interfaces and wrappers), allows you to apply
132
- architectural solutions from other languages (such as Java, PHP, C#) and fully harness the capabilities of npm packages
133
- and ES6 modules in JavaScript applications, particularly in the Node.js environment.
281
+ Happy coding!ges and ES6 modules in JavaScript applications, especially within the Node.js environment.
package/RELEASE.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # @teqfw/di releases
2
2
 
3
+ ## 0.30.2
4
+
5
+ * Enhanced the README with updates from ChatGPT.
6
+ * Unified JSDoc annotations.
7
+
8
+ ## 0.30.1
9
+
10
+ * Improve the README.
11
+
3
12
  ## 0.30.0
4
13
 
5
14
  * New format of the depId for default parser (`Ns_Module.export$$(post)`).
package/dist/esm.js CHANGED
@@ -1 +1 @@
1
- var e={COMP_A:"A",COMP_F:"F",ID:"container",ID_FQN:"TeqFw_Di_Container$",LIFE_I:"I",LIFE_S:"S",isClass(e){const t=Object.getOwnPropertyDescriptor(e,"prototype");return t&&!t.writable}};const t=/(function)*\s*\w*\s*\(\s*\{([^\}]*)\}/s,o=/constructor\s*\(\s*\{([^\}]*)\}/s;function s(e){const t=[];try{const o=new Function(`{${e}}`,"return");o(new Proxy({},{get:(e,o)=>t.push(o)}))}catch(t){throw new Error(`Cannot analyze the deps specification:${e}\n\nPlease, be sure that spec does not contain extra ')' in a comments.\n\nError: ${t}`)}return t}function n(n){return"function"==typeof n?e.isClass(n)?function(e){const t=[],n=e.toString(),r=o.exec(n);return r&&t.push(...s(r[1])),t}(n):function(e){const o=[],n=e.toString(),r=t.exec(n);return r&&o.push(...s(r[2])),o}(n):[]}class r{constructor(){let t=!1;this.create=async function(o,s,r,i){if(r.includes(o.value))throw new Error(`Circular dependency for '${o.value}'. Parents are: ${JSON.stringify(r)}`);if(o.exportName){const a=[...r,o.value],{[o.exportName]:u}=s;if(o.composition===e.COMP_F){if("function"==typeof u){const s=n(u);s.length&&(c=`Deps for object '${o.value}' are: ${JSON.stringify(s)}`,t&&console.log(c));const r={};for(const e of s)r[e]=await i.compose(e,a);const l=e.isClass(u)?new u(r):u(r);return l instanceof Promise?await l:l}return Object.assign({},u)}return u}return s;var c},this.setDebug=function(e){t=e}}}class i{exportName;composition;life;moduleName;value;wrappers=[]}const c=/^((([A-Z])[A-Za-z0-9_]*)((\.)?([A-Za-z0-9_]*)((\$)?(\$)?)?)?(\(([A-Za-z0-9_,]*)\))?)$/;class a{canParse(e){return!0}parse(t){const o=new i;o.value=t;const s=c.exec(t);if(s&&(o.moduleName=s[2],"."===s[5]?"$"===s[7]||"$$"===s[7]?(o.composition=e.COMP_F,o.exportName=s[6],o.life="$"===s[7]?e.LIFE_S:e.LIFE_I):(o.composition=e.COMP_A,o.life=e.LIFE_S,o.exportName=""!==s[6]?s[6]:"default"):"$"===s[7]||"$$"===s[7]?(o.composition=e.COMP_F,o.exportName="default",o.life="$"===s[7]?e.LIFE_S:e.LIFE_I):(o.composition=void 0,o.exportName=void 0,o.life=void 0),s[11]&&(o.wrappers=s[11].split(","))),o.composition===e.COMP_A&&o.life===e.LIFE_I)throw new Error(`Export is not a function and should be used as a singleton only: '${o.value}'.`);return o}}class u{constructor(){let e=new a;const t=[];this.addChunk=function(e){t.push(e)},this.parse=function(o){let s;for(const e of t)if(e.canParse(o)){s=e.parse(o);break}return s||(s=e?.parse(o)),s},this.setDefaultChunk=function(t){e=t}}}class l{constructor(){const e=[];this.addChunk=function(t){e.push(t)},this.modify=function(t,o){let s=t;for(const n of e)s=n.modify(s,t,o);return s}}}class f{constructor(){const e=[];this.addChunk=function(t){e.push(t)},this.modify=async function(t,o,s){let n=t;for(const t of e)n=t.modify(n,o,s),n instanceof Promise&&(n=await n);return n}}}const p="ext",m="ns",d="root";class h{constructor(){const e={};let t=!1,o=[],s="/";this.addNamespaceRoot=function(s,n,r){const i=(t?n.replace(/^\\/,""):n).replace(/\\/g,"/"),c=t?`file://${i}`:i;e[s]={[p]:r??"js",[m]:s,[d]:c},o=Object.keys(e).sort(((e,t)=>t.localeCompare(e)))},this.resolve=function(t){let n,r,i;for(i of o)if(t.startsWith(i)){n=e[i][d],r=e[i].ext;break}if(n&&r){let e=t.replace(i,"");0===e.indexOf("_")&&(e=e.replace("_",""));const o=e.replaceAll("_",s);return`${n}${s}${o}.${r}`}return t},this.setWindowsEnv=function(e=!0){t=e,s=e?"\\":"/"}}}function $(e){return`${e.moduleName}#${e.exportName}`}class w{constructor(){let t=new r,o=!1,s=new u,n=new l,i=new f;const c={},a={};let p=new h;function m(){o&&console.log(...arguments)}this.get=async function(e){return this.compose(e,[])},this.compose=async function(o,r=[]){if(m(`Object '${o}' is requested.`),o===e.ID||o===e.ID_FQN)return m("Container itself is returned."),a[e.ID];const u=s.parse(o),l=n.modify(u,r);if(l.life===e.LIFE_S){const e=$(l);if(a[e])return m(`Existing singleton '${e}' is returned.`),a[e]}let f;c[l.moduleName]||(m(`ES6 module '${l.moduleName}' is not resolved yet`),c[l.moduleName]=p.resolve(l.moduleName));const d=c[l.moduleName];try{f=await import(d),m(`ES6 module '${l.moduleName}' is loaded from '${d}'.`)}catch(e){throw console.error(e?.message,`Object key: "${o}".`,`Path: "${d}".`,`Stack: ${JSON.stringify(r)}`),e}let h=await t.create(l,f,r,this);if(h=await i.modify(h,l,r),m(`Object '${o}' is created.`),l.life===e.LIFE_S){const e=$(l);a[e]=h,m(`Object '${o}' is saved as singleton.`)}return h},this.getParser=()=>s,this.getPreProcessor=()=>n,this.getPostProcessor=()=>i,this.getResolver=()=>p,this.setDebug=function(e){o=e,t.setDebug(e)},this.setParser=e=>s=e,this.setPreProcessor=e=>n=e,this.setPostProcessor=e=>i=e,this.setResolver=e=>p=e,a[e.ID]=this}}export{w as default};
1
+ var e={COMP_A:"A",COMP_F:"F",ID:"container",ID_FQN:"TeqFw_Di_Container$",LIFE_I:"I",LIFE_S:"S",isClass(e){const t=Object.getOwnPropertyDescriptor(e,"prototype");return t&&!t.writable}};const t=/(function)*\s*\w*\s*\(\s*\{([^\}]*)\}/s,o=/constructor\s*\(\s*\{([^\}]*)\}/s;function s(e){const t=[];try{const o=new Function(`{${e}}`,"return");o(new Proxy({},{get:(e,o)=>t.push(o)}))}catch(t){throw new Error(`Cannot analyze the deps specification:${e}\n\nPlease, be sure that spec does not contain extra ')' in a comments.\n\nError: ${t}`)}return t}function n(n){return"function"==typeof n?e.isClass(n)?function(e){const t=[],n=e.toString(),r=o.exec(n);return r&&t.push(...s(r[1])),t}(n):function(e){const o=[],n=e.toString(),r=t.exec(n);return r&&o.push(...s(r[2])),o}(n):[]}class r{constructor(){let t=!1;this.create=async function(o,s,r,i){if(r.includes(o.value))throw new Error(`Circular dependency for '${o.value}'. Parents are: ${JSON.stringify(r)}`);if(o.exportName){const a=[...r,o.value],{[o.exportName]:u}=s;if(o.composition===e.COMP_F){if("function"==typeof u){const s=n(u);s.length&&(c=`Deps for object '${o.value}' are: ${JSON.stringify(s)}`,t&&console.log(c));const r={};for(const e of s)r[e]=await i.compose(e,a);const l=e.isClass(u)?new u(r):u(r);return l instanceof Promise?await l:l}return Object.assign({},u)}return u}return s;var c},this.setDebug=function(e){t=e}}}class i{exportName;composition;life;moduleName;value;wrappers=[]}const c=/^((([A-Z])[A-Za-z0-9_]*)((\.)?([A-Za-z0-9_]*)((\$)?(\$)?)?)?(\(([A-Za-z0-9_,]*)\))?)$/;class a{canParse(e){return!0}parse(t){const o=new i;o.value=t;const s=c.exec(t);if(s&&(o.moduleName=s[2],"."===s[5]?"$"===s[7]||"$$"===s[7]?(o.composition=e.COMP_F,o.exportName=s[6],o.life="$"===s[7]?e.LIFE_S:e.LIFE_I):(o.composition=e.COMP_A,o.life=e.LIFE_S,o.exportName=""!==s[6]?s[6]:"default"):"$"===s[7]||"$$"===s[7]?(o.composition=e.COMP_F,o.exportName="default",o.life="$"===s[7]?e.LIFE_S:e.LIFE_I):(o.composition=void 0,o.exportName=void 0,o.life=void 0),s[11]&&(o.wrappers=s[11].split(","))),o.composition===e.COMP_A&&o.life===e.LIFE_I)throw new Error(`Export is not a function and should be used as a singleton only: '${o.value}'.`);return o}}class u{constructor(){let e=new a;const t=[];this.addChunk=function(e){t.push(e)},this.parse=function(o){let s;for(const e of t)if(e.canParse(o)){s=e.parse(o);break}return s||(s=e?.parse(o)),s},this.setDefaultChunk=function(t){e=t}}}class l{constructor(){const e=[];this.addChunk=function(t){e.push(t)},this.modify=function(t,o){let s=t;for(const n of e)s=n.modify(s,t,o);return s}}}class f{constructor(){const e=[];this.addChunk=function(t){e.push(t)},this.modify=async function(t,o,s){let n=t;for(const t of e)n=t.modify(n,o,s),n instanceof Promise&&(n=await n);return n}}}const p="root";class m{constructor(){const e={};let t=!1,o=[],s="/";this.addNamespaceRoot=function(s,n,r){const i=(t?n.replace(/^\\/,""):n).replace(/\\/g,"/"),c=t?`file://${i}`:i;e[s]={ext:r??"js",ns:s,[p]:c},o=Object.keys(e).sort(((e,t)=>t.localeCompare(e)))},this.resolve=function(t){let n,r,i;for(i of o)if(t.startsWith(i)){n=e[i][p],r=e[i].ext;break}if(n&&r){let e=t.replace(i,"");0===e.indexOf("_")&&(e=e.replace("_",""));const o=e.replaceAll("_",s);return`${n}${s}${o}.${r}`}return t},this.setWindowsEnv=function(e=!0){t=e,s=e?"\\":"/"}}}function d(e){return`${e.moduleName}#${e.exportName}`}class h{constructor(){let t=new r,o=!1,s=new u,n=new l,i=new f;const c={},a={};let p=new m;function h(){o&&console.log(...arguments)}this.get=async function(e){return this.compose(e,[])},this.compose=async function(o,r=[]){if(h(`Object '${o}' is requested.`),o===e.ID||o===e.ID_FQN)return h("Container itself is returned."),a[e.ID];const u=s.parse(o),l=n.modify(u,r);if(l.life===e.LIFE_S){const e=d(l);if(a[e])return h(`Existing singleton '${e}' is returned.`),a[e]}let f;c[l.moduleName]||(h(`ES6 module '${l.moduleName}' is not resolved yet`),c[l.moduleName]=p.resolve(l.moduleName));const m=c[l.moduleName];try{f=await import(m),h(`ES6 module '${l.moduleName}' is loaded from '${m}'.`)}catch(e){throw console.error(e?.message,`Object key: "${o}".`,`Path: "${m}".`,`Stack: ${JSON.stringify(r)}`),e}let $=await t.create(l,f,r,this);if($=await i.modify($,l,r),h(`Object '${o}' is created.`),l.life===e.LIFE_S){const e=d(l);a[e]=$,h(`Object '${o}' is saved as singleton.`)}return $},this.getParser=()=>s,this.getPreProcessor=()=>n,this.getPostProcessor=()=>i,this.getResolver=()=>p,this.setDebug=function(e){o=e,t.setDebug(e)},this.setParser=e=>s=e,this.setPreProcessor=e=>n=e,this.setPostProcessor=e=>i=e,this.setResolver=e=>p=e,a[e.ID]=this}}export{h as default};
package/dist/umd.js CHANGED
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).TeqFw_Di_Container=t()}(this,(function(){"use strict";var e={COMP_A:"A",COMP_F:"F",ID:"container",ID_FQN:"TeqFw_Di_Container$",LIFE_I:"I",LIFE_S:"S",isClass(e){const t=Object.getOwnPropertyDescriptor(e,"prototype");return t&&!t.writable}};const t=/(function)*\s*\w*\s*\(\s*\{([^\}]*)\}/s,o=/constructor\s*\(\s*\{([^\}]*)\}/s;function n(e){const t=[];try{const o=new Function(`{${e}}`,"return");o(new Proxy({},{get:(e,o)=>t.push(o)}))}catch(t){throw new Error(`Cannot analyze the deps specification:${e}\n\nPlease, be sure that spec does not contain extra ')' in a comments.\n\nError: ${t}`)}return t}function s(s){return"function"==typeof s?e.isClass(s)?function(e){const t=[],s=e.toString(),r=o.exec(s);return r&&t.push(...n(r[1])),t}(s):function(e){const o=[],s=e.toString(),r=t.exec(s);return r&&o.push(...n(r[2])),o}(s):[]}class r{constructor(){let t=!1;this.create=async function(o,n,r,i){if(r.includes(o.value))throw new Error(`Circular dependency for '${o.value}'. Parents are: ${JSON.stringify(r)}`);if(o.exportName){const a=[...r,o.value],{[o.exportName]:u}=n;if(o.composition===e.COMP_F){if("function"==typeof u){const n=s(u);n.length&&(c=`Deps for object '${o.value}' are: ${JSON.stringify(n)}`,t&&console.log(c));const r={};for(const e of n)r[e]=await i.compose(e,a);const l=e.isClass(u)?new u(r):u(r);return l instanceof Promise?await l:l}return Object.assign({},u)}return u}return n;var c},this.setDebug=function(e){t=e}}}class i{exportName;composition;life;moduleName;value;wrappers=[]}const c=/^((([A-Z])[A-Za-z0-9_]*)((\.)?([A-Za-z0-9_]*)((\$)?(\$)?)?)?(\(([A-Za-z0-9_,]*)\))?)$/;class a{canParse(e){return!0}parse(t){const o=new i;o.value=t;const n=c.exec(t);if(n&&(o.moduleName=n[2],"."===n[5]?"$"===n[7]||"$$"===n[7]?(o.composition=e.COMP_F,o.exportName=n[6],o.life="$"===n[7]?e.LIFE_S:e.LIFE_I):(o.composition=e.COMP_A,o.life=e.LIFE_S,o.exportName=""!==n[6]?n[6]:"default"):"$"===n[7]||"$$"===n[7]?(o.composition=e.COMP_F,o.exportName="default",o.life="$"===n[7]?e.LIFE_S:e.LIFE_I):(o.composition=void 0,o.exportName=void 0,o.life=void 0),n[11]&&(o.wrappers=n[11].split(","))),o.composition===e.COMP_A&&o.life===e.LIFE_I)throw new Error(`Export is not a function and should be used as a singleton only: '${o.value}'.`);return o}}class u{constructor(){let e=new a;const t=[];this.addChunk=function(e){t.push(e)},this.parse=function(o){let n;for(const e of t)if(e.canParse(o)){n=e.parse(o);break}return n||(n=e?.parse(o)),n},this.setDefaultChunk=function(t){e=t}}}class l{constructor(){const e=[];this.addChunk=function(t){e.push(t)},this.modify=function(t,o){let n=t;for(const s of e)n=s.modify(n,t,o);return n}}}class f{constructor(){const e=[];this.addChunk=function(t){e.push(t)},this.modify=async function(t,o,n){let s=t;for(const t of e)s=t.modify(s,o,n),s instanceof Promise&&(s=await s);return s}}}const p="ext",d="ns",m="root";class h{constructor(){const e={};let t=!1,o=[],n="/";this.addNamespaceRoot=function(n,s,r){const i=(t?s.replace(/^\\/,""):s).replace(/\\/g,"/"),c=t?`file://${i}`:i;e[n]={[p]:r??"js",[d]:n,[m]:c},o=Object.keys(e).sort(((e,t)=>t.localeCompare(e)))},this.resolve=function(t){let s,r,i;for(i of o)if(t.startsWith(i)){s=e[i][m],r=e[i].ext;break}if(s&&r){let e=t.replace(i,"");0===e.indexOf("_")&&(e=e.replace("_",""));const o=e.replaceAll("_",n);return`${s}${n}${o}.${r}`}return t},this.setWindowsEnv=function(e=!0){t=e,n=e?"\\":"/"}}}function $(e){return`${e.moduleName}#${e.exportName}`}return class{constructor(){let t=new r,o=!1,n=new u,s=new l,i=new f;const c={},a={};let p=new h;function d(){o&&console.log(...arguments)}this.get=async function(e){return this.compose(e,[])},this.compose=async function(o,r=[]){if(d(`Object '${o}' is requested.`),o===e.ID||o===e.ID_FQN)return d("Container itself is returned."),a[e.ID];const u=n.parse(o),l=s.modify(u,r);if(l.life===e.LIFE_S){const e=$(l);if(a[e])return d(`Existing singleton '${e}' is returned.`),a[e]}let f;c[l.moduleName]||(d(`ES6 module '${l.moduleName}' is not resolved yet`),c[l.moduleName]=p.resolve(l.moduleName));const m=c[l.moduleName];try{f=await import(m),d(`ES6 module '${l.moduleName}' is loaded from '${m}'.`)}catch(e){throw console.error(e?.message,`Object key: "${o}".`,`Path: "${m}".`,`Stack: ${JSON.stringify(r)}`),e}let h=await t.create(l,f,r,this);if(h=await i.modify(h,l,r),d(`Object '${o}' is created.`),l.life===e.LIFE_S){const e=$(l);a[e]=h,d(`Object '${o}' is saved as singleton.`)}return h},this.getParser=()=>n,this.getPreProcessor=()=>s,this.getPostProcessor=()=>i,this.getResolver=()=>p,this.setDebug=function(e){o=e,t.setDebug(e)},this.setParser=e=>n=e,this.setPreProcessor=e=>s=e,this.setPostProcessor=e=>i=e,this.setResolver=e=>p=e,a[e.ID]=this}}}));
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).TeqFw_Di_Container=t()}(this,(function(){"use strict";var e={COMP_A:"A",COMP_F:"F",ID:"container",ID_FQN:"TeqFw_Di_Container$",LIFE_I:"I",LIFE_S:"S",isClass(e){const t=Object.getOwnPropertyDescriptor(e,"prototype");return t&&!t.writable}};const t=/(function)*\s*\w*\s*\(\s*\{([^\}]*)\}/s,o=/constructor\s*\(\s*\{([^\}]*)\}/s;function n(e){const t=[];try{const o=new Function(`{${e}}`,"return");o(new Proxy({},{get:(e,o)=>t.push(o)}))}catch(t){throw new Error(`Cannot analyze the deps specification:${e}\n\nPlease, be sure that spec does not contain extra ')' in a comments.\n\nError: ${t}`)}return t}function s(s){return"function"==typeof s?e.isClass(s)?function(e){const t=[],s=e.toString(),r=o.exec(s);return r&&t.push(...n(r[1])),t}(s):function(e){const o=[],s=e.toString(),r=t.exec(s);return r&&o.push(...n(r[2])),o}(s):[]}class r{constructor(){let t=!1;this.create=async function(o,n,r,i){if(r.includes(o.value))throw new Error(`Circular dependency for '${o.value}'. Parents are: ${JSON.stringify(r)}`);if(o.exportName){const a=[...r,o.value],{[o.exportName]:u}=n;if(o.composition===e.COMP_F){if("function"==typeof u){const n=s(u);n.length&&(c=`Deps for object '${o.value}' are: ${JSON.stringify(n)}`,t&&console.log(c));const r={};for(const e of n)r[e]=await i.compose(e,a);const l=e.isClass(u)?new u(r):u(r);return l instanceof Promise?await l:l}return Object.assign({},u)}return u}return n;var c},this.setDebug=function(e){t=e}}}class i{exportName;composition;life;moduleName;value;wrappers=[]}const c=/^((([A-Z])[A-Za-z0-9_]*)((\.)?([A-Za-z0-9_]*)((\$)?(\$)?)?)?(\(([A-Za-z0-9_,]*)\))?)$/;class a{canParse(e){return!0}parse(t){const o=new i;o.value=t;const n=c.exec(t);if(n&&(o.moduleName=n[2],"."===n[5]?"$"===n[7]||"$$"===n[7]?(o.composition=e.COMP_F,o.exportName=n[6],o.life="$"===n[7]?e.LIFE_S:e.LIFE_I):(o.composition=e.COMP_A,o.life=e.LIFE_S,o.exportName=""!==n[6]?n[6]:"default"):"$"===n[7]||"$$"===n[7]?(o.composition=e.COMP_F,o.exportName="default",o.life="$"===n[7]?e.LIFE_S:e.LIFE_I):(o.composition=void 0,o.exportName=void 0,o.life=void 0),n[11]&&(o.wrappers=n[11].split(","))),o.composition===e.COMP_A&&o.life===e.LIFE_I)throw new Error(`Export is not a function and should be used as a singleton only: '${o.value}'.`);return o}}class u{constructor(){let e=new a;const t=[];this.addChunk=function(e){t.push(e)},this.parse=function(o){let n;for(const e of t)if(e.canParse(o)){n=e.parse(o);break}return n||(n=e?.parse(o)),n},this.setDefaultChunk=function(t){e=t}}}class l{constructor(){const e=[];this.addChunk=function(t){e.push(t)},this.modify=function(t,o){let n=t;for(const s of e)n=s.modify(n,t,o);return n}}}class f{constructor(){const e=[];this.addChunk=function(t){e.push(t)},this.modify=async function(t,o,n){let s=t;for(const t of e)s=t.modify(s,o,n),s instanceof Promise&&(s=await s);return s}}}const p="root";class d{constructor(){const e={};let t=!1,o=[],n="/";this.addNamespaceRoot=function(n,s,r){const i=(t?s.replace(/^\\/,""):s).replace(/\\/g,"/"),c=t?`file://${i}`:i;e[n]={ext:r??"js",ns:n,[p]:c},o=Object.keys(e).sort(((e,t)=>t.localeCompare(e)))},this.resolve=function(t){let s,r,i;for(i of o)if(t.startsWith(i)){s=e[i][p],r=e[i].ext;break}if(s&&r){let e=t.replace(i,"");0===e.indexOf("_")&&(e=e.replace("_",""));const o=e.replaceAll("_",n);return`${s}${n}${o}.${r}`}return t},this.setWindowsEnv=function(e=!0){t=e,n=e?"\\":"/"}}}function m(e){return`${e.moduleName}#${e.exportName}`}return class{constructor(){let t=new r,o=!1,n=new u,s=new l,i=new f;const c={},a={};let p=new d;function h(){o&&console.log(...arguments)}this.get=async function(e){return this.compose(e,[])},this.compose=async function(o,r=[]){if(h(`Object '${o}' is requested.`),o===e.ID||o===e.ID_FQN)return h("Container itself is returned."),a[e.ID];const u=n.parse(o),l=s.modify(u,r);if(l.life===e.LIFE_S){const e=m(l);if(a[e])return h(`Existing singleton '${e}' is returned.`),a[e]}let f;c[l.moduleName]||(h(`ES6 module '${l.moduleName}' is not resolved yet`),c[l.moduleName]=p.resolve(l.moduleName));const d=c[l.moduleName];try{f=await import(d),h(`ES6 module '${l.moduleName}' is loaded from '${d}'.`)}catch(e){throw console.error(e?.message,`Object key: "${o}".`,`Path: "${d}".`,`Stack: ${JSON.stringify(r)}`),e}let $=await t.create(l,f,r,this);if($=await i.modify($,l,r),h(`Object '${o}' is created.`),l.life===e.LIFE_S){const e=m(l);a[e]=$,h(`Object '${o}' is saved as singleton.`)}return $},this.getParser=()=>n,this.getPreProcessor=()=>s,this.getPostProcessor=()=>i,this.getResolver=()=>p,this.setDebug=function(e){o=e,t.setDebug(e)},this.setParser=e=>n=e,this.setPreProcessor=e=>s=e,this.setPostProcessor=e=>i=e,this.setResolver=e=>p=e,a[e.ID]=this}}}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teqfw/di",
3
- "version": "0.30.0",
3
+ "version": "0.30.2",
4
4
  "description": "Dependency Injection container for ES6 modules that works in both browser and Node.js apps.",
5
5
  "keywords": [
6
6
  "dependency injection",
@@ -10,14 +10,14 @@ export default class TeqFw_Di_Api_Container_Parser_Chunk {
10
10
  * Returns 'true' if this chunk can parse the given dependency ID.
11
11
  *
12
12
  * @param {string} depId
13
- * @return {boolean}
13
+ * @returns {boolean}
14
14
  */
15
15
  canParse(depId) {};
16
16
 
17
17
  /**
18
18
  * Parses a string ID for a runtime dependency and returns structured data (DTO).
19
19
  * @param {string} depId
20
- * @return {TeqFw_Di_DepId}
20
+ * @returns {TeqFw_Di_DepId}
21
21
  */
22
22
  parse(depId) {}
23
23
  };
@@ -15,7 +15,7 @@ export default class TeqFw_Di_Api_Container_Parser {
15
15
  /**
16
16
  * Parse given dependency ID and return structured data as DTO.
17
17
  * @param {string} depId
18
- * @return {TeqFw_Di_DepId}
18
+ * @returns {TeqFw_Di_DepId}
19
19
  */
20
20
  parse(depId) {}
21
21
 
@@ -11,7 +11,7 @@ export default class TeqFw_Di_Api_Container_PostProcessor_Chunk {
11
11
  * @param {*} obj - created object
12
12
  * @param {TeqFw_Di_DepId} originalId - original `depId` DTO
13
13
  * @param {string[]} stack - stack of parents depIds
14
- * @return {*} modified object
14
+ * @returns {*} modified object
15
15
  */
16
16
  modify(obj, originalId, stack) {}
17
17
  };
@@ -18,7 +18,7 @@ export default class TeqFw_Di_Api_Container_PostProcessor {
18
18
  * @param {*} obj - The result object to be modified.
19
19
  * @param {TeqFw_Di_DepId} depId - The original depID DTO.
20
20
  * @param {string[]} - The stack of parent IDs.
21
- * @return {Promise<*>}
21
+ * @returns {Promise<*>}
22
22
  */
23
23
  modify(obj, depId, stack) {}
24
24
 
@@ -11,7 +11,7 @@ export default class TeqFw_Di_Api_Container_PreProcessor_Chunk {
11
11
  * @param {TeqFw_Di_DepId} depId - `depId` DTO after all previous pre-processing steps
12
12
  * @param {TeqFw_Di_DepId} originalId - original `depId` DTO
13
13
  * @param {string[]} stack - stack of parents depIds
14
- * @return {TeqFw_Di_DepId}
14
+ * @returns {TeqFw_Di_DepId}
15
15
  */
16
16
  modify(depId, originalId, stack) {}
17
17
  };
@@ -16,7 +16,7 @@ export default class TeqFw_Di_Api_Container_PreProcessor {
16
16
  * Modify parsed depID and return it.
17
17
  * @param {TeqFw_Di_DepId} depId - The depID as DTO.
18
18
  * @param {string[]} stack - The stack of parent IDs.
19
- * @return {TeqFw_Di_DepId} -
19
+ * @returns {TeqFw_Di_DepId} -
20
20
  */
21
21
  modify(depId, stack) {}
22
22
 
@@ -9,7 +9,7 @@ export default class TeqFw_Di_Api_Container_Resolver {
9
9
  /**
10
10
  * Convert the module name to the path of the source files .
11
11
  * @param {string} moduleName 'Vendor_Package_Module'
12
- * @return {string} '/home/user/app/node_modules/@vendor/package/src/Module.js'
12
+ * @returns {string} '/home/user/app/node_modules/@vendor/package/src/Module.js'
13
13
  */
14
14
  resolve(moduleName) {}
15
15
 
@@ -9,27 +9,27 @@ export default class TeqFw_Di_Api_Container {
9
9
  * Gets or creates a runtime object by ID.
10
10
  *
11
11
  * @param {string} runtimeDepId - The ID of the runtime object.
12
- * @return {Promise<*>} - A promise that resolves to the runtime object.
12
+ * @returns {Promise<*>} - A promise that resolves to the runtime object.
13
13
  */
14
14
  get(runtimeDepId) {};
15
15
 
16
16
  /**
17
- * @return {TeqFw_Di_Api_Container_Parser}
17
+ * @returns {TeqFw_Di_Api_Container_Parser}
18
18
  */
19
19
  getParser() {};
20
20
 
21
21
  /**
22
- * @return {TeqFw_Di_Api_Container_PreProcessor}
22
+ * @returns {TeqFw_Di_Api_Container_PreProcessor}
23
23
  */
24
24
  getPreProcessor() {};
25
25
 
26
26
  /**
27
- * @return {TeqFw_Di_Api_Container_PostProcessor}
27
+ * @returns {TeqFw_Di_Api_Container_PostProcessor}
28
28
  */
29
29
  getPostProcessor() {};
30
30
 
31
31
  /**
32
- * @return {TeqFw_Di_Container_Resolver} - the default resolver
32
+ * @returns {TeqFw_Di_Container_Resolver} - the default resolver
33
33
  */
34
34
  getResolver() {};
35
35
 
@@ -17,7 +17,7 @@ const CLASS = /constructor\s*\(\s*\{([^\}]*)\}/s;
17
17
  * Internal function to analyze extracted parameters.
18
18
  *
19
19
  * @param {string} params
20
- * @return {string[]}
20
+ * @returns {string[]}
21
21
  * @private
22
22
  */
23
23
  function _analyze(params) {
@@ -41,7 +41,7 @@ function _analyze(params) {
41
41
 
42
42
  /**
43
43
  * @param {Function|Object} exp
44
- * @return {string[]}
44
+ * @returns {string[]}
45
45
  */
46
46
  function _analyzeClass(exp) {
47
47
  const res = [];
@@ -56,7 +56,7 @@ function _analyzeClass(exp) {
56
56
 
57
57
  /**
58
58
  * @param {Function|Object} exp
59
- * @return {string[]}
59
+ * @returns {string[]}
60
60
  */
61
61
  function _analyzeFunc(exp) {
62
62
  const res = [];
@@ -72,7 +72,7 @@ function _analyzeFunc(exp) {
72
72
  // MAIN
73
73
  /**
74
74
  * @param {Function|Object} exp
75
- * @return {string[]}
75
+ * @returns {string[]}
76
76
  */
77
77
  export default function (exp) {
78
78
  if (typeof exp === 'function') {
@@ -26,7 +26,7 @@ export default class TeqFw_Di_Container_A_Composer {
26
26
  * @param {Object} module - imported es6 module
27
27
  * @param {string[]} stack - array of the parent objects IDs to prevent dependency loop
28
28
  * @param {TeqFw_Di_Container} container - to create dependencies for requested object
29
- * @return {Promise<*>}
29
+ * @returns {Promise<*>}
30
30
  */
31
31
  this.create = async function (depId, module, stack, container) {
32
32
  if (stack.includes(depId.value))
@@ -49,7 +49,7 @@ export default class TeqFw_Di_Container_Resolver {
49
49
  /**
50
50
  * Convert the module name to the path of the source files .
51
51
  * @param {string} moduleName 'Vendor_Package_Module'
52
- * @return {string} '/home/user/app/node_modules/@vendor/package/src/Module.js'
52
+ * @returns {string} '/home/user/app/node_modules/@vendor/package/src/Module.js'
53
53
  */
54
54
  this.resolve = function (moduleName) {
55
55
  let root, ext, ns;
package/src/Container.js CHANGED
@@ -13,7 +13,7 @@ import Resolver from './Container/Resolver.js';
13
13
  /**
14
14
  * ID to store singletons in the internal registry.
15
15
  * @param {TeqFw_Di_DepId} key
16
- * @return {string}
16
+ * @returns {string}
17
17
  */
18
18
  function getSingletonId(key) {
19
19
  return `${key.moduleName}#${key.exportName}`;
@@ -63,7 +63,7 @@ export default class TeqFw_Di_Container {
63
63
  *
64
64
  * @param {string} depId runtime dependency ID
65
65
  * @param {string[]} stack set of the depId to detect circular dependencies
66
- * @return {Promise<*>}
66
+ * @returns {Promise<*>}
67
67
  */
68
68
  this.compose = async function (depId, stack = []) {
69
69
  log(`Object '${depId}' is requested.`);
package/src/Defs.js CHANGED
@@ -15,7 +15,7 @@ export default {
15
15
  * See: https://stackoverflow.com/a/29094018/4073821
16
16
  *
17
17
  * @param {function} fn
18
- * @return {boolean}
18
+ * @returns {boolean}
19
19
  */
20
20
  isClass(fn) {
21
21
  const proto = Object.getOwnPropertyDescriptor(fn, 'prototype');