@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.
- package/CHANGELOG.md +5 -42
- package/README.md +173 -271
- package/dist/esm.js +1 -1
- package/dist/umd.js +1 -1
- package/package.json +12 -8
- package/src/AGENTS.md +177 -0
- package/src/Config/NamespaceRegistry.mjs +210 -0
- package/src/Container/Instantiate/ExportSelector.mjs +39 -0
- package/src/Container/Instantiate/Instantiator.mjs +143 -0
- package/src/Container/Lifecycle/Registry.mjs +81 -0
- package/src/Container/Resolve/GraphResolver.mjs +119 -0
- package/src/Container/Resolver.mjs +175 -0
- package/src/Container/Wrapper/Executor.mjs +71 -0
- package/src/Container.mjs +380 -0
- package/src/Def/Parser.mjs +146 -0
- package/src/Dto/DepId.mjs +131 -0
- package/src/Dto/Resolver/Config/Namespace.mjs +48 -0
- package/src/Dto/Resolver/Config.mjs +58 -0
- package/src/Enum/Composition.mjs +11 -0
- package/src/Enum/Life.mjs +11 -0
- package/src/Enum/Platform.mjs +12 -0
- package/src/Internal/Logger.mjs +54 -0
- package/types.d.ts +58 -21
- package/src/Api/Container/Parser/Chunk.js +0 -23
- package/src/Api/Container/Parser.js +0 -28
- package/src/Api/Container/PostProcessor/Chunk.js +0 -17
- package/src/Api/Container/PostProcessor.js +0 -25
- package/src/Api/Container/PreProcessor/Chunk.js +0 -17
- package/src/Api/Container/PreProcessor.js +0 -23
- package/src/Api/Container/Resolver.js +0 -16
- package/src/Container/A/Composer/A/SpecParser.js +0 -86
- package/src/Container/A/Composer.js +0 -69
- package/src/Container/A/Parser/Chunk/Def.js +0 -69
- package/src/Container/A/Parser/Chunk/V02X.js +0 -66
- package/src/Container/Parser.js +0 -48
- package/src/Container/PostProcessor.js +0 -32
- package/src/Container/PreProcessor.js +0 -34
- package/src/Container/Resolver.js +0 -80
- package/src/Container.js +0 -187
- package/src/Defs.js +0 -22
- package/src/DepId.js +0 -52
- package/src/Pre/Replace.js +0 -80
- 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,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
|
|
2
|
-
type
|
|
3
|
-
type
|
|
4
|
-
type
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
type
|
|
8
|
-
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
}
|