@teqfw/di 1.2.0 → 2.0.0

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.
Files changed (43) hide show
  1. package/CHANGELOG.md +5 -42
  2. package/README.md +173 -271
  3. package/dist/esm.js +1 -1
  4. package/dist/umd.js +1 -1
  5. package/package.json +12 -8
  6. package/src/AGENTS.md +177 -0
  7. package/src/Config/NamespaceRegistry.mjs +210 -0
  8. package/src/Container/Instantiate/ExportSelector.mjs +39 -0
  9. package/src/Container/Instantiate/Instantiator.mjs +143 -0
  10. package/src/Container/Lifecycle/Registry.mjs +81 -0
  11. package/src/Container/Resolve/GraphResolver.mjs +119 -0
  12. package/src/Container/Resolver.mjs +175 -0
  13. package/src/Container/Wrapper/Executor.mjs +71 -0
  14. package/src/Container.mjs +380 -0
  15. package/src/Def/Parser.mjs +146 -0
  16. package/src/Dto/DepId.mjs +131 -0
  17. package/src/Dto/Resolver/Config/Namespace.mjs +48 -0
  18. package/src/Dto/Resolver/Config.mjs +58 -0
  19. package/src/Enum/Composition.mjs +11 -0
  20. package/src/Enum/Life.mjs +11 -0
  21. package/src/Enum/Platform.mjs +12 -0
  22. package/src/Internal/Logger.mjs +54 -0
  23. package/types.d.ts +58 -21
  24. package/src/Api/Container/Parser/Chunk.js +0 -23
  25. package/src/Api/Container/Parser.js +0 -28
  26. package/src/Api/Container/PostProcessor/Chunk.js +0 -17
  27. package/src/Api/Container/PostProcessor.js +0 -25
  28. package/src/Api/Container/PreProcessor/Chunk.js +0 -17
  29. package/src/Api/Container/PreProcessor.js +0 -23
  30. package/src/Api/Container/Resolver.js +0 -16
  31. package/src/Container/A/Composer/A/SpecParser.js +0 -86
  32. package/src/Container/A/Composer.js +0 -69
  33. package/src/Container/A/Parser/Chunk/Def.js +0 -69
  34. package/src/Container/A/Parser/Chunk/V02X.js +0 -66
  35. package/src/Container/Parser.js +0 -48
  36. package/src/Container/PostProcessor.js +0 -32
  37. package/src/Container/PreProcessor.js +0 -34
  38. package/src/Container/Resolver.js +0 -80
  39. package/src/Container.js +0 -187
  40. package/src/Defs.js +0 -22
  41. package/src/DepId.js +0 -52
  42. package/src/Pre/Replace.js +0 -80
  43. package/teqfw.json +0 -8
@@ -0,0 +1,48 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * DTO and factory for resolver namespace rule records.
5
+ */
6
+
7
+ /**
8
+ * Runtime DTO for one namespace resolution rule.
9
+ */
10
+ export class DTO {
11
+ /** @type {string|undefined} Namespace prefix in depId module name. */
12
+ prefix;
13
+ /** @type {string|undefined} Import target base for matched namespace. */
14
+ target;
15
+ /** @type {string|undefined} Default extension appended to matched module path. */
16
+ defaultExt;
17
+ }
18
+
19
+ /**
20
+ * Factory for resolver namespace DTO with optional immutability.
21
+ */
22
+ export default class Factory {
23
+ /**
24
+ * Creates normalized resolver namespace DTO.
25
+ *
26
+ * @param {Partial<TeqFw_Di_Dto_Resolver_Config_Namespace$DTO$>|Record<string, unknown>} [input] Source values.
27
+ * @param {{immutable?: boolean}|Record<string, unknown>} [options] Factory options.
28
+ * @returns {TeqFw_Di_Dto_Resolver_Config_Namespace$DTO$}
29
+ */
30
+ create(input, options) {
31
+ /** @type {Partial<TeqFw_Di_Dto_Resolver_Config_Namespace$DTO$>|Record<string, unknown>} */
32
+ const source = (input && (typeof input === 'object')) ? input : {};
33
+ /** @type {{immutable?: boolean}|Record<string, unknown>} */
34
+ const mode = (options && (typeof options === 'object')) ? options : {};
35
+
36
+ /** @type {TeqFw_Di_Dto_Resolver_Config_Namespace$DTO$} */
37
+ const dto = new DTO();
38
+ dto.prefix = (typeof source.prefix === 'string') ? source.prefix : undefined;
39
+ dto.target = (typeof source.target === 'string') ? source.target : undefined;
40
+ dto.defaultExt = (typeof source.defaultExt === 'string') ? source.defaultExt : undefined;
41
+
42
+ if (mode.immutable === true) {
43
+ Object.freeze(dto);
44
+ }
45
+
46
+ return dto;
47
+ }
48
+ }
@@ -0,0 +1,58 @@
1
+ // @ts-check
2
+
3
+ import TeqFw_Di_Dto_Resolver_Config_Namespace from './Config/Namespace.mjs';
4
+
5
+ /**
6
+ * DTO and factory for resolver configuration records.
7
+ */
8
+
9
+ /**
10
+ * Runtime DTO for resolver configuration.
11
+ */
12
+ export class DTO {
13
+ /** @type {TeqFw_Di_Dto_Resolver_Config_Namespace$DTO$[]} Namespace resolution rules. */
14
+ namespaces;
15
+ /** @type {string|undefined} Optional node_modules root prefix for npm modules. */
16
+ nodeModulesRoot;
17
+ }
18
+
19
+ /**
20
+ * Factory for resolver configuration DTO with optional immutability.
21
+ */
22
+ export default class Factory {
23
+ /**
24
+ * Creates factory instance.
25
+ */
26
+ constructor() {
27
+ /** @type {TeqFw_Di_Dto_Resolver_Config_Namespace} Factory for namespace DTO records. */
28
+ const nsFactory = new TeqFw_Di_Dto_Resolver_Config_Namespace();
29
+
30
+ /**
31
+ * Creates normalized resolver configuration DTO.
32
+ *
33
+ * @param {Partial<TeqFw_Di_Dto_Resolver_Config$DTO>|Record<string, unknown>} [input] Source values.
34
+ * @param {{immutable?: boolean}|Record<string, unknown>} [options] Factory options.
35
+ * @returns {TeqFw_Di_Dto_Resolver_Config$DTO}
36
+ */
37
+ this.create = function (input, options) {
38
+ /** @type {Partial<TeqFw_Di_Dto_Resolver_Config$DTO>|Record<string, unknown>} */
39
+ const source = (input && (typeof input === 'object')) ? input : {};
40
+ /** @type {{immutable?: boolean}|Record<string, unknown>} */
41
+ const mode = (options && (typeof options === 'object')) ? options : {};
42
+
43
+ /** @type {TeqFw_Di_Dto_Resolver_Config$DTO} */
44
+ const dto = new DTO();
45
+ /** @type {unknown[]} */
46
+ const items = Array.isArray(source.namespaces) ? source.namespaces : [];
47
+ dto.namespaces = items.map((item) => nsFactory.create(item, mode));
48
+ dto.nodeModulesRoot = (typeof source.nodeModulesRoot === 'string') ? source.nodeModulesRoot : undefined;
49
+
50
+ if (mode.immutable === true) {
51
+ Object.freeze(dto.namespaces);
52
+ Object.freeze(dto);
53
+ }
54
+
55
+ return dto;
56
+ };
57
+ }
58
+ }
@@ -0,0 +1,11 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * Composition mode enum used in dependency identity DTO.
5
+ */
6
+ const TeqFw_Di_Enum_Composition = {
7
+ AS_IS: 'A',
8
+ FACTORY: 'F',
9
+ };
10
+
11
+ export default TeqFw_Di_Enum_Composition;
@@ -0,0 +1,11 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * Lifecycle mode enum used in dependency identity DTO.
5
+ */
6
+ const TeqFw_Di_Enum_Life = {
7
+ SINGLETON: 'S',
8
+ TRANSIENT: 'T',
9
+ };
10
+
11
+ export default TeqFw_Di_Enum_Life;
@@ -0,0 +1,12 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * Platform enum used to resolve module loading strategy.
5
+ */
6
+ const TeqFw_Di_Enum_Platform = {
7
+ TEQ: 'teq',
8
+ NODE: 'node',
9
+ NPM: 'npm',
10
+ };
11
+
12
+ export default TeqFw_Di_Enum_Platform;
@@ -0,0 +1,54 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * Internal synchronous console logger.
5
+ *
6
+ * This module is internal infrastructure and must not be exposed as a public API.
7
+ */
8
+ export default class TeqFw_Di_Internal_Logger {
9
+ /**
10
+ * @param {string} scope
11
+ */
12
+ constructor(scope = 'teqfw/di') {
13
+ /** @type {string} */
14
+ const prefix = `[${scope}]`;
15
+
16
+ /**
17
+ * @param {string} message
18
+ * @returns {void}
19
+ */
20
+ this.log = function (message) {
21
+ console.debug(`${prefix} ${message}`);
22
+ };
23
+
24
+ /**
25
+ * @param {string} message
26
+ * @param {unknown} [error]
27
+ * @returns {void}
28
+ */
29
+ this.error = function (message, error) {
30
+ console.error(`${prefix} ${message}`);
31
+ if (error instanceof Error) {
32
+ console.error(error.stack ?? error.message);
33
+ return;
34
+ }
35
+ if (error !== undefined) {
36
+ console.error(error);
37
+ }
38
+ };
39
+ }
40
+ }
41
+
42
+ /**
43
+ * No-op logger for disabled logging mode.
44
+ */
45
+ export const TeqFw_Di_Internal_Logger_Noop = Object.freeze({
46
+ /**
47
+ * @returns {void}
48
+ */
49
+ log() {},
50
+ /**
51
+ * @returns {void}
52
+ */
53
+ error() {},
54
+ });
package/types.d.ts CHANGED
@@ -1,24 +1,61 @@
1
- type TeqFw_Di_Container_A_Composer = InstanceType<typeof import("./src/Container/A/Composer.js").default>;
2
- type TeqFw_Di_Container_A_Composer_A_SpecParser = import("./src/Container/A/Composer/A/SpecParser.js").default;
3
- type TeqFw_Di_Container_A_Parser_Chunk_Def = InstanceType<typeof import("./src/Container/A/Parser/Chunk/Def.js").default>;
4
- type TeqFw_Di_Container_A_Parser_Chunk_V02X = InstanceType<typeof import("./src/Container/A/Parser/Chunk/V02X.js").default>;
5
- type TeqFw_Di_Container_Parser = InstanceType<typeof import("./src/Container/Parser.js").default>;
6
- type TeqFw_Di_Container_PostProcessor = InstanceType<typeof import("./src/Container/PostProcessor.js").default>;
7
- type TeqFw_Di_Container_PreProcessor = InstanceType<typeof import("./src/Container/PreProcessor.js").default>;
8
- type TeqFw_Di_Container_Resolver = InstanceType<typeof import("./src/Container/Resolver.js").default>;
1
+ type TeqFw_Di_Def_Parser = InstanceType<typeof import("./src/Def/Parser.mjs").default>;
2
+ type TeqFw_Di_Config_NamespaceRegistry = InstanceType<typeof import("./src/Config/NamespaceRegistry.mjs").default>;
3
+ export type TeqFw_Di_Container = InstanceType<typeof import("./src/Container.mjs").default>;
4
+ export type TeqFw_Di_Container_Instantiate_ExportSelector = InstanceType<
5
+ typeof import("./src/Container/Instantiate/ExportSelector.mjs").default
6
+ >;
7
+ export type TeqFw_Di_Container_Instantiate_Instantiator = InstanceType<
8
+ typeof import("./src/Container/Instantiate/Instantiator.mjs").default
9
+ >;
10
+ export type TeqFw_Di_Container_Lifecycle_Registry = InstanceType<
11
+ typeof import("./src/Container/Lifecycle/Registry.mjs").default
12
+ >;
13
+ export type TeqFw_Di_Container_Resolve_GraphResolver = InstanceType<
14
+ typeof import("./src/Container/Resolve/GraphResolver.mjs").default
15
+ >;
16
+ export type TeqFw_Di_Container_Wrapper_Executor = InstanceType<
17
+ typeof import("./src/Container/Wrapper/Executor.mjs").default
18
+ >;
19
+ type TeqFw_Di_DepId = InstanceType<typeof import("./src/Dto/DepId.mjs").default>;
20
+ type TeqFw_Di_Dto_Resolver_Config = InstanceType<typeof import("./src/Dto/Resolver/Config.mjs").default>;
21
+ type TeqFw_Di_Dto_Resolver_Config_Namespace = InstanceType<
22
+ typeof import("./src/Dto/Resolver/Config/Namespace.mjs").default
23
+ >;
24
+ type TeqFw_Di_Resolver = InstanceType<typeof import("./src/Container/Resolver.mjs").default>;
9
25
 
10
- declare global {
11
- type TeqFw_Di_Api_Container_Parser = InstanceType<typeof import("./src/Api/Container/Parser.js").default>;
12
- type TeqFw_Di_Api_Container_Parser_Chunk = InstanceType<typeof import("./src/Api/Container/Parser/Chunk.js").default>;
13
- type TeqFw_Di_Api_Container_PostProcessor = InstanceType<typeof import("./src/Api/Container/PostProcessor.js").default>;
14
- type TeqFw_Di_Api_Container_PostProcessor_Chunk = InstanceType<typeof import("./src/Api/Container/PostProcessor/Chunk.js").default>;
15
- type TeqFw_Di_Api_Container_PreProcessor = InstanceType<typeof import("./src/Api/Container/PreProcessor.js").default>;
16
- type TeqFw_Di_Api_Container_PreProcessor_Chunk = InstanceType<typeof import("./src/Api/Container/PreProcessor/Chunk.js").default>;
17
- type TeqFw_Di_Api_Container_Resolver = InstanceType<typeof import("./src/Api/Container/Resolver.js").default>;
18
- type TeqFw_Di_Container = InstanceType<typeof import("./src/Container.js").default>;
19
- type TeqFw_Di_Defs = import("./src/Defs.js").default;
20
- type TeqFw_Di_DepId = InstanceType<typeof import("./src/DepId.js").default>;
21
- type TeqFw_Di_Pre_Replace = InstanceType<typeof import("./src/Pre/Replace.js").default>;
22
- }
26
+ export type TeqFw_Di_DepId$DTO = typeof import("./src/Dto/DepId.mjs").DTO;
27
+ export type TeqFw_Di_DepId$DTO$ = InstanceType<TeqFw_Di_DepId$DTO>;
28
+ export type TeqFw_Di_Dto_Resolver_Config$DTO = typeof import("./src/Dto/Resolver/Config.mjs").DTO;
29
+ export type TeqFw_Di_Dto_Resolver_Config$DTO$ = InstanceType<TeqFw_Di_Dto_Resolver_Config$DTO>;
30
+ export type TeqFw_Di_Dto_Resolver_Config_Namespace$DTO = typeof import("./src/Dto/Resolver/Config/Namespace.mjs").DTO;
31
+ export type TeqFw_Di_Dto_Resolver_Config_Namespace$DTO$ = InstanceType<TeqFw_Di_Dto_Resolver_Config_Namespace$DTO>;
23
32
 
24
33
  export {};
34
+
35
+ declare global {
36
+ type TeqFw_Di_Container = InstanceType<typeof import("./src/Container.mjs").default>;
37
+ type TeqFw_Di_Config_NamespaceRegistry = InstanceType<typeof import("./src/Config/NamespaceRegistry.mjs").default>;
38
+ type TeqFw_Di_Def_Parser = InstanceType<typeof import("./src/Def/Parser.mjs").default>;
39
+ type TeqFw_Di_DepId = InstanceType<typeof import("./src/Dto/DepId.mjs").default>;
40
+ type TeqFw_Di_DepId$DTO = import("./src/Dto/DepId.mjs").DTO;
41
+ type TeqFw_Di_Dto_Resolver_Config = InstanceType<typeof import("./src/Dto/Resolver/Config.mjs").default>;
42
+ type TeqFw_Di_Dto_Resolver_Config$DTO = import("./src/Dto/Resolver/Config.mjs").DTO;
43
+ type TeqFw_Di_Dto_Resolver_Config_Namespace = InstanceType<
44
+ typeof import("./src/Dto/Resolver/Config/Namespace.mjs").default
45
+ >;
46
+ type TeqFw_Di_Dto_Resolver_Config_Namespace$DTO = typeof import("./src/Dto/Resolver/Config/Namespace.mjs").DTO;
47
+ type TeqFw_Di_Dto_Resolver_Config_Namespace$DTO$ = InstanceType<TeqFw_Di_Dto_Resolver_Config_Namespace$DTO>;
48
+ type TeqFw_Di_Enum_Composition = typeof import("./src/Enum/Composition.mjs").default;
49
+ type TeqFw_Di_Enum_Life = typeof import("./src/Enum/Life.mjs").default;
50
+ type TeqFw_Di_Enum_Platform = typeof import("./src/Enum/Platform.mjs").default;
51
+ type TeqFw_Di_Container_Resolve_GraphResolver = InstanceType<
52
+ typeof import("./src/Container/Resolve/GraphResolver.mjs").default
53
+ >;
54
+ type TeqFw_Di_Container_Lifecycle_Registry = InstanceType<
55
+ typeof import("./src/Container/Lifecycle/Registry.mjs").default
56
+ >;
57
+ type TeqFw_Di_Container_Wrapper_Executor = InstanceType<
58
+ typeof import("./src/Container/Wrapper/Executor.mjs").default
59
+ >;
60
+ type TeqFw_Di_Resolver = InstanceType<typeof import("./src/Container/Resolver.mjs").default>;
61
+ }
@@ -1,23 +0,0 @@
1
- /**
2
- * Interface for one chunk of the runtime dependency ID parser.
3
- *
4
- * This is not executable code, it is just for documentation purposes (similar to .h files in the C/C++ language).
5
- * @interface
6
- */
7
- export default class TeqFw_Di_Api_Container_Parser_Chunk {
8
-
9
- /**
10
- * Returns 'true' if this chunk can parse the given dependency ID.
11
- *
12
- * @param {string} depId
13
- * @returns {boolean}
14
- */
15
- canParse(depId) {};
16
-
17
- /**
18
- * Parses a string ID for a runtime dependency and returns structured data (DTO).
19
- * @param {string} depId
20
- * @returns {TeqFw_Di_DepId}
21
- */
22
- parse(depId) {}
23
- };
@@ -1,28 +0,0 @@
1
- /**
2
- * Interface for the parser of the runtime dependency ID.
3
- *
4
- * This is not executable code, it is just for documentation purposes (similar to .h files in the C/C++ language).
5
- * @interface
6
- */
7
- export default class TeqFw_Di_Api_Container_Parser {
8
- /**
9
- * Adds the given chunk to the parser.
10
- *
11
- * @param {TeqFw_Di_Api_Container_Parser_Chunk} chunk
12
- */
13
- addChunk(chunk) {}
14
-
15
- /**
16
- * Parse given dependency ID and return structured data as DTO.
17
- * @param {string} depId
18
- * @returns {TeqFw_Di_DepId}
19
- */
20
- parse(depId) {}
21
-
22
- /**
23
- * Sets the default chunk of the parser.
24
- *
25
- * @param {TeqFw_Di_Api_Container_Parser_Chunk} chunk
26
- */
27
- setDefaultChunk(chunk) {}
28
- }
@@ -1,17 +0,0 @@
1
- /**
2
- * Interface for one chunk of the post-processor that modifies result.
3
- *
4
- * This is not executable code, it is just for documentation purposes (similar to .h files in the C/C++ language).
5
- * @interface
6
- */
7
- export default class TeqFw_Di_Api_Container_PostProcessor_Chunk {
8
-
9
- /**
10
- * Modify result before returning to the caller.
11
- * @param {*} obj - created object
12
- * @param {TeqFw_Di_DepId} originalId - original `depId` DTO
13
- * @param {string[]} stack - stack of parents depIds
14
- * @returns {*} modified object
15
- */
16
- modify(obj, originalId, stack) {}
17
- };
@@ -1,25 +0,0 @@
1
- /**
2
- * Interface for the post-processor of the result object.
3
- *
4
- * This is not executable code, it is just for documentation purposes (similar to .h files in the C/C++ language).
5
- * @interface
6
- */
7
- export default class TeqFw_Di_Api_Container_PostProcessor {
8
- /**
9
- * Adds the given chunk to the parser.
10
- *
11
- * @param {TeqFw_Di_Api_Container_PostProcessor_Chunk} chunk
12
- */
13
- addChunk(chunk) {}
14
-
15
- /**
16
- * Modifies the result of the object composition.
17
- *
18
- * @param {*} obj - The result object to be modified.
19
- * @param {TeqFw_Di_DepId} depId - The original depID DTO.
20
- * @param {string[]} - The stack of parent IDs.
21
- * @returns {Promise<*>}
22
- */
23
- modify(obj, depId, stack) {}
24
-
25
- }
@@ -1,17 +0,0 @@
1
- /**
2
- * Interface for one chunk of the pre-processor that modify initial `depId`.
3
- *
4
- * This is not executable code, it is just for documentation purposes (similar to .h files in the C/C++ language).
5
- * @interface
6
- */
7
- export default class TeqFw_Di_Api_Container_PreProcessor_Chunk {
8
-
9
- /**
10
- * Modify runtime dependency ID before creating any object.
11
- * @param {TeqFw_Di_DepId} depId - `depId` DTO after all previous pre-processing steps
12
- * @param {TeqFw_Di_DepId} originalId - original `depId` DTO
13
- * @param {string[]} stack - stack of parents depIds
14
- * @returns {TeqFw_Di_DepId}
15
- */
16
- modify(depId, originalId, stack) {}
17
- };
@@ -1,23 +0,0 @@
1
- /**
2
- * Interface for the pre-processor of the runtime dependency ID.
3
- *
4
- * This is not executable code, it is just for documentation purposes (similar to .h files in the C/C++ language).
5
- * @interface
6
- */
7
- export default class TeqFw_Di_Api_Container_PreProcessor {
8
- /**
9
- * Adds the given chunk to the parser.
10
- *
11
- * @param {TeqFw_Di_Api_Container_PreProcessor_Chunk} chunk
12
- */
13
- addChunk(chunk) {}
14
-
15
- /**
16
- * Modify parsed depID and return it.
17
- * @param {TeqFw_Di_DepId} depId - The depID as DTO.
18
- * @param {string[]} stack - The stack of parent IDs.
19
- * @returns {TeqFw_Di_DepId} -
20
- */
21
- modify(depId, stack) {}
22
-
23
- }
@@ -1,16 +0,0 @@
1
- /**
2
- * Interface for the resolver to map a module name of the dependency ID into the path to the sources.
3
- *
4
- * This is not executable code, it is just for documentation purposes (similar to .h files in the C/C++ language).
5
- * @interface
6
- */
7
- export default class TeqFw_Di_Api_Container_Resolver {
8
-
9
- /**
10
- * Convert the module name to the path of the source files .
11
- * @param {string} moduleName 'Vendor_Package_Module'
12
- * @returns {string} '/home/user/app/node_modules/@vendor/package/src/Module.js'
13
- */
14
- resolve(moduleName) {}
15
-
16
- }
@@ -1,86 +0,0 @@
1
- /**
2
- * This function analyses specification of dependencies extracted from the text definition of the function itself.
3
- *
4
- * This is a local module and is used only inside the `TeqFw_Di_Container_A_Composer` space.
5
- *
6
- * @namespace TeqFw_Di_Container_A_Composer_A_SpecParser
7
- */
8
- import Defs from '../../../../Defs.js';
9
-
10
- // VARS
11
- const FUNC = /(function)*\s*\w*\s*\(\s*\{([^}]*)}/s;
12
- const CLASS = /constructor\s*\(\s*\{([^}]*)}/s;
13
-
14
- // FUNCS
15
-
16
- /**
17
- * Internal function to analyze extracted parameters.
18
- *
19
- * @param {string} params
20
- * @returns {string[]}
21
- * @private
22
- */
23
- function _analyze(params) {
24
- const res = [];
25
- // create wrapper for arguments and collect dependencies using Proxy
26
- try {
27
- const fn = new Function(`{${params}}`, 'return');
28
- const spec = new Proxy({}, {
29
- get: (target, prop) => res.push(prop),
30
- });
31
- // run wrapper and return dependencies
32
- fn(spec);
33
- } catch (e) {
34
- const msg = `Cannot analyze the deps specification:${params}\n`
35
- + '\nPlease, be sure that spec does not contain extra \')\' in a comments.'
36
- + `\n\nError: ${e}`;
37
- throw new Error(msg);
38
- }
39
- return res;
40
- }
41
-
42
- /**
43
- * @param {Function|Object} exp
44
- * @returns {string[]}
45
- */
46
- function _analyzeClass(exp) {
47
- const res = [];
48
- // extract arguments from constructor
49
- const def = exp.toString();
50
- const parts = CLASS.exec(def);
51
- if (parts) {
52
- res.push(..._analyze(parts[1]));
53
- } // else: constructor does not have arguments
54
- return res;
55
- }
56
-
57
- /**
58
- * @param {Function|Object} exp
59
- * @returns {string[]}
60
- */
61
- function _analyzeFunc(exp) {
62
- const res = [];
63
- // extract arguments from factory function
64
- const def = exp.toString();
65
- const parts = FUNC.exec(def);
66
- if (parts) {
67
- res.push(..._analyze(parts[2]));
68
- } // else: constructor does not have arguments
69
- return res;
70
- }
71
-
72
- // MAIN
73
- /**
74
- * @param {Function|Object} exp
75
- * @returns {string[]}
76
- */
77
- export default function (exp) {
78
- if (typeof exp === 'function') {
79
- if (Defs.isClass(exp)) {
80
- return _analyzeClass(exp);
81
- } else {
82
- return _analyzeFunc(exp);
83
- }
84
- } else
85
- return [];
86
- }
@@ -1,69 +0,0 @@
1
- /**
2
- * The composer creates requested objects. It uses the container to create dependencies.
3
- *
4
- * @namespace TeqFw_Di_Container_A_Composer
5
- */
6
- import Defs from '../../Defs.js';
7
- import specParser from './Composer/A/SpecParser.js';
8
-
9
- export default class TeqFw_Di_Container_A_Composer {
10
-
11
- constructor() {
12
- // VARS
13
- let _debug = false;
14
-
15
- // FUNCS
16
- function log(msg) {
17
- if (_debug) console.log(msg);
18
- }
19
-
20
- // INSTANCE METHODS
21
-
22
- /**
23
- * Returns or creates and returns the requested object.
24
- *
25
- * @param {TeqFw_Di_DepId} depId
26
- * @param {object} module - imported es6 module
27
- * @param {string[]} stack - array of the parent objects IDs to prevent dependency loop
28
- * @param {TeqFw_Di_Container} container - to create dependencies for requested object
29
- * @returns {Promise<*>}
30
- */
31
- this.create = async function (depId, module, stack, container) {
32
- if (stack.includes(depId.origin))
33
- throw new Error(`Circular dependency for '${depId.origin}'. Parents are: ${JSON.stringify(stack)}`);
34
- if (depId.exportName) {
35
- // use export from the es6-module
36
- const stackNew = [...stack, depId.origin];
37
- const {[depId.exportName]: exp} = module;
38
- if (depId.composition === Defs.CF) {
39
- if (typeof exp === 'function') {
40
- // create deps for factory function
41
- const deps = specParser(exp);
42
- if (deps.length) log(`Deps for object '${depId.origin}' are: ${JSON.stringify(deps)}`);
43
- const spec = {};
44
- for (const dep of deps)
45
- spec[dep] = await container.get(dep, stackNew);
46
- // create a new object with the factory function
47
- const res = (Defs.isClass(exp)) ? new exp(spec) : exp(spec);
48
- if (res instanceof Promise)
49
- return await res;
50
- else
51
- return res;
52
- } else
53
- // just clone the export
54
- return Object.assign({}, exp);
55
- } else
56
- // just return the export (w/o factory function)
57
- return exp;
58
- } else {
59
- return module;
60
- }
61
- };
62
-
63
- this.setDebug = function (data) {
64
- _debug = data;
65
- };
66
-
67
- // MAIN
68
- }
69
- };
@@ -1,69 +0,0 @@
1
- /**
2
- * Default parser for object keys in format:
3
- * - Ns_Module.export$$(post)
4
- * - node:package.export$$(post)
5
- * - node:@scope/package.export$$(post)
6
- *
7
- * @namespace TeqFw_Di_Container_A_Parser_Chunk_Def
8
- */
9
- import Dto from '../../../../DepId.js';
10
- import Defs from '../../../../Defs.js';
11
-
12
- // VARS
13
- /** @type {RegExp} expression for a default object key */
14
- const REGEXP = /^(node:)?(@?[A-Za-z0-9_-]+\/?[A-Za-z0-9_-]*)(([.#])?([A-Za-z0-9_]*)((\$)?(\$)?)?)?(\(([A-Za-z0-9_,]*)\))?$/;
15
-
16
- /**
17
- * @implements TeqFw_Di_Api_Container_Parser_Chunk
18
- */
19
- export default class TeqFw_Di_Container_A_Parser_Chunk_Def {
20
-
21
- canParse() {
22
- // the default parser always tries to parse the depId
23
- return true;
24
- }
25
-
26
- parse(objectKey) {
27
- const res = new Dto();
28
- res.origin = objectKey;
29
- const parts = REGEXP.exec(objectKey);
30
- if (parts) {
31
- res.isNodeModule = Boolean(parts[1]); // Detect 'node:' prefix
32
- res.moduleName = parts[2].replace(/^node:/, ''); // Remove 'node:' prefix
33
-
34
- if ((parts[4] === '.') || (parts[4] === '#')) {
35
- // Ns_Module.export or node:package.export
36
- if ((parts[6] === '$') || (parts[6] === '$$')) {
37
- res.composition = Defs.CF;
38
- res.exportName = parts[5];
39
- res.life = (parts[6] === '$') ? Defs.LS : Defs.LI;
40
- } else {
41
- res.composition = Defs.CA;
42
- res.life = Defs.LS;
43
- res.exportName = (parts[5] !== '') ? parts[5] : 'default';
44
- }
45
- } else if ((parts[6] === '$') || parts[6] === '$$') {
46
- // Ns_Module$$ or node:package$$
47
- res.composition = Defs.CF;
48
- res.exportName = 'default';
49
- res.life = (parts[6] === '$') ? Defs.LS : Defs.LI;
50
- } else {
51
- // Ns_Module or node:package (ES6 module)
52
- res.composition = undefined;
53
- res.exportName = undefined;
54
- res.life = undefined;
55
- }
56
-
57
- // Wrappers handling
58
- if (parts[10]) {
59
- res.wrappers = parts[10].split(',');
60
- }
61
- }
62
-
63
- // Ensure singletons for non-factory exports
64
- if ((res.composition === Defs.CA) && (res.life === Defs.LI))
65
- throw new Error(`Export is not a function and should be used as a singleton only: '${res.origin}'.`);
66
-
67
- return res;
68
- }
69
- }