@teqfw/di 0.12.0 → 0.20.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 (41) hide show
  1. package/.eslintrc.mjs +0 -0
  2. package/README.md +27 -0
  3. package/RELEASE.md +13 -0
  4. package/bin/release/clean.sh +2 -1
  5. package/dist/di.cjs.js +205 -0
  6. package/dist/di.esm.js +206 -0
  7. package/index.cjs +5 -0
  8. package/index.mjs +6 -0
  9. package/package.json +12 -4
  10. package/src/Api/ObjectKey.js +35 -0
  11. package/src/Composer.js +68 -0
  12. package/src/Container.js +142 -0
  13. package/src/Defs.js +25 -0
  14. package/src/DepId/Parser.mjs +68 -0
  15. package/src/Parser/Def.js +63 -0
  16. package/src/Parser/Old.js +108 -0
  17. package/src/Parser.js +65 -0
  18. package/src/PreProcessor/Replace.js +48 -0
  19. package/src/PreProcessor.js +45 -0
  20. package/src/Resolver.js +64 -0
  21. package/src/Spec/Parser.mjs +101 -0
  22. package/src/SpecAnalyser.js +82 -0
  23. package/webpack.config.mjs +15 -0
  24. package/src/Back/Api/Dto/Plugin/Desc.mjs +0 -70
  25. package/src/Back/Api/Dto/Scanned.mjs +0 -12
  26. package/src/Back/Api/README.md +0 -1
  27. package/src/Back/Defaults.mjs +0 -11
  28. package/src/Back/Plugin/Scanner.mjs +0 -154
  29. package/src/Back/README.md +0 -1
  30. package/src/Shared/Api/Dto/Plugin/Desc/Autoload.mjs +0 -50
  31. package/src/Shared/Api/IProxy.mjs +0 -11
  32. package/src/Shared/Container.mjs +0 -333
  33. package/src/Shared/IdParser/Dto.mjs +0 -96
  34. package/src/Shared/IdParser.mjs +0 -187
  35. package/src/Shared/ModuleLoader.mjs +0 -38
  36. package/src/Shared/README.md +0 -1
  37. package/src/Shared/Resolver/FilepathNs.mjs +0 -51
  38. package/src/Shared/Resolver/LogicalNs.mjs +0 -136
  39. package/src/Shared/Resolver.mjs +0 -67
  40. package/src/Shared/SpecProxy.mjs +0 -110
  41. package/teqfw.json +0 -8
@@ -1,333 +0,0 @@
1
- /**
2
- * Dependency Injection container for Tequila Framework.
3
- *
4
- * @namespace TeqFw_Di_Shared_Container
5
- */
6
- // MODULE'S IMPORT
7
- /* don't import ES-modules with nodejs dependencies (will not work in browsers) */
8
- import DAutoload from './Api/Dto/Plugin/Desc/Autoload.mjs';
9
- import IdParser from './IdParser.mjs';
10
- import ModuleLoader from './ModuleLoader.mjs';
11
- import ParsedId from './IdParser/Dto.mjs';
12
- import Resolver from './Resolver.mjs';
13
- import SpecProxy from './SpecProxy.mjs';
14
-
15
- // MODULE'S VARS
16
- const $parser = new IdParser();
17
-
18
- // MODULE'S CLASSES
19
- /**
20
- *
21
- */
22
- export default class TeqFw_Di_Shared_Container {
23
- /**
24
- * @param {Object} [spec]
25
- * @param {TeqFw_Di_Shared_Resolver} [spec.namespaceResolver] custom resolver to map module names to file paths
26
- */
27
- constructor(spec = {}) {
28
- /** @type {TeqFw_Di_Shared_Resolver} Modules loader (given in constructor or empty one). */
29
- const resolver = spec.namespaceResolver || new Resolver();
30
- /** @type {TeqFw_Di_Shared_ModuleLoader} */
31
- const moduleLoader = new ModuleLoader(resolver);
32
- /**
33
- * Storage for constructors (named or default exports of ES modules) to create new objects.
34
- * Module name ('Vendor_Project_Module') is a key in the map.
35
- */
36
- const factories = new Map();
37
- /**
38
- * Storage for created instances (singletons).
39
- * Module name ('Vendor_Project_Module') or singleton name ('dbConnection') is a key in the map.
40
- */
41
- const singletons = new Map();
42
- /**
43
- * Storage for ES modules replacements (interface => implementation).
44
- * Sample: {['Vnd_Plug_Interface']:'Vnd_Plug_Impl', ...}
45
- * @type {Object<string, string>}
46
- */
47
- const replacements = {};
48
-
49
- // set default instance of the DI container
50
- singletons.set('container', this); // as singleton
51
- singletons.set('TeqFw_Di_Shared_Container', this); // as singleton of the class
52
-
53
- // pin itself for nested functions
54
- const me = this;
55
-
56
- /**
57
- * Internal function to get/create object|function|class|module by given `id`.
58
- *
59
- * @param {string} mainId main object ID (singleton, module, new object, default export singleton)
60
- * @param {string[]} uplineDeps dependencies registry to prevent circular loop.
61
- * @returns {Promise<*>}
62
- */
63
- async function getObject(mainId, uplineDeps) {
64
-
65
- // FUNCS
66
- /**
67
- * Add 'spec' proxy as fnConstruct argument and create new object and all deps.
68
- *
69
- * @param {Function|Object} fnConstruct
70
- * @returns {Promise<*>} created object
71
- * @private
72
- */
73
- function _useFactory(fnConstruct) {
74
- // This promise will be resolved after all dependencies in spec proxy will be created.
75
- return new Promise(function (resolve, reject) {
76
- // MAIN
77
- const constructorType = typeof fnConstruct;
78
- if (constructorType === 'object') {
79
- // `constructor` is an object, clone this fnConstruct and return cloned object
80
- const objClone = Object.assign({}, fnConstruct);
81
- resolve(objClone);
82
- } else if (constructorType === 'function') {
83
- // `constructor` is simple function or class
84
-
85
- /**
86
- * Create new function to resolve all deps and to create requested object.
87
- * This function will be called from spec proxy for every failed dependency.
88
- */
89
- const fnCreate = function () {
90
- try {
91
- // https://stackoverflow.com/a/29094018/4073821
92
- const proto = Object.getOwnPropertyDescriptor(fnConstruct, 'prototype');
93
- const isClass = proto && !proto.writable;
94
- const instNew = (isClass) ? new fnConstruct(spec) : fnConstruct(spec);
95
- // code line below will be inaccessible until all deps will be created in `spec`
96
- // SpecProxy.EXCEPTION_TO_STEALTH will be thrown for every missed dep in `spec`
97
- if (instNew instanceof Promise) {
98
- instNew
99
- .then((asyncInst) => {
100
- resolve(asyncInst)
101
- }
102
- ).catch((e) => {
103
- // SpecProxy rejects `_useFactory` promise on any error
104
- if (e === SpecProxy.EXCEPTION_TO_STEALTH) {
105
- // stealth constructor exceptions to prevent execution interrupt on missed dependency
106
- } else {
107
- throw e;
108
- }
109
- }
110
- );
111
- } else {
112
- resolve(instNew);
113
- }
114
- } catch (e) {
115
- // SpecProxy rejects `_useFactory` promise on any error
116
- if (e === SpecProxy.EXCEPTION_TO_STEALTH) {
117
- // stealth constructor exceptions to prevent execution interrupt on missed dependency
118
- } else {
119
- throw e;
120
- }
121
- }
122
- };
123
- // create spec proxy to analyze dependencies of the constructing object in current scope
124
- const spec = new SpecProxy(mainId, uplineDeps, singletons, fnCreate, getObject, reject);
125
- // try to create object and start chain of deps resolving in SpecProxy
126
- fnCreate();
127
- } else {
128
- throw new Error(`Unexpected type of factory function for '${mainId}'.`);
129
- }
130
- // `resolve` for this promise is called from fnCreate
131
- // (fnCreate is recalled from spec proxy on every dep failure)
132
- });
133
- }
134
-
135
- /**
136
- * Lookup for requested dependency in internal storages or create new one if dependency constructor
137
- * is available.
138
- * @param {TeqFw_Di_Shared_IdParser_Dto} parsed
139
- * @returns {*}
140
- */
141
- async function getFromStorages(parsed) {
142
- let result;
143
- // get required instance from own registries or load sources and create new one
144
- if ((parsed.typeTarget === ParsedId.TYPE_TARGET_SINGLETON) && (singletons.get(parsed.mapKey) !== undefined)) {
145
- // singleton was created before, just return it
146
- result = singletons.get(parsed.mapKey);
147
- } else if ((parsed.typeTarget === ParsedId.TYPE_TARGET_FACTORY) && (factories.get(parsed.mapKey) !== undefined)) {
148
- // factory with required `id` was loaded before, create & return new object
149
- const factory = factories.get(parsed.mapKey);
150
- result = await _useFactory(factory);
151
- }
152
- return result;
153
- }
154
-
155
- /**
156
- * Replace original ES6 module name (interface) with it's alternative (implementation).
157
- * @param {string} orig
158
- * @return {string}
159
- */
160
- function checkReplacements(orig) {
161
- while (replacements[orig]) orig = replacements[orig];
162
- return orig;
163
- }
164
-
165
- // MAIN
166
- let result;
167
- /** @type {TeqFw_Di_Shared_IdParser_Dto} */
168
- const parsed = $parser.parse(mainId);
169
- parsed.nameModule = checkReplacements(parsed.nameModule);
170
- // try to find requested dependency in local storages
171
- if (!parsed.isProxy) result = await getFromStorages(parsed);
172
- // if not found then try to load sources and create new one
173
- if (result === undefined) {
174
- // Sources for requested dependency are not imported or not set manually before.
175
- // Get ES6 module from loader.
176
- const moduleId = (parsed.typeId === ParsedId.TYPE_ID_FILEPATH) ?
177
- parsed.namePackage + '!' + parsed.nameModule :
178
- parsed.nameModule;
179
- const module = await moduleLoader.getModule(moduleId);
180
- if (parsed.typeTarget === ParsedId.TYPE_TARGET_MODULE) {
181
- // result as ES6 module
182
- result = module;
183
- } else if (parsed.typeTarget === ParsedId.TYPE_TARGET_EXPORT) {
184
- // result as ES6 module export
185
- result = module[parsed.nameExport];
186
- } else {
187
- // create new object (singleton or instance) using factory
188
- if (parsed.isProxy) {
189
- // we need to create proxy to resolve deps for the object later
190
- const depId = parsed.orig.replace(/@/gi, '$');
191
- result = new Proxy({dep: undefined, depId}, {
192
- get: async function (base, name) {
193
- if (name === 'create') base.dep = await me.get(base.depId);
194
- return base.dep;
195
- }
196
- });
197
- } else {
198
- // we need use module export as factory for new object or singleton for the first time
199
- const factory = module[parsed.nameExport];
200
- factories.set(parsed.mapKey, factory);
201
- const object = await _useFactory(factory);
202
- // save singleton object in container storage
203
- if (parsed.typeTarget === ParsedId.TYPE_TARGET_SINGLETON) singletons.set(parsed.mapKey, object);
204
- result = object;
205
- }
206
- }
207
- }
208
- return result;
209
- }
210
-
211
- /**
212
- * Add replacement for ES6 modules.
213
- *
214
- * @param {string} orig ('Vnd_Plug_Interface')
215
- * @param {string} alter ('Vnd_Plug_Impl')
216
- */
217
- this.addModuleReplacement = function (orig, alter) {
218
- replacements[orig] = alter;
219
- }
220
-
221
- /**
222
- *
223
- * @param {string} namespace
224
- * @param {string} path
225
- * @param {boolean} [is_absolute]
226
- * @param {string} [ext]
227
- */
228
- this.addSourceMapping = function (namespace, path, is_absolute = false, ext = 'mjs') {
229
- let parsed = $parser.parseLogicalNsId(namespace);
230
- if (!parsed) parsed = $parser.parseFilepathId(namespace);
231
- if (
232
- (parsed.typeTarget !== ParsedId.TYPE_TARGET_MODULE) &&
233
- (parsed.typeTarget !== ParsedId.TYPE_TARGET_PACKAGE)
234
- )
235
- throw new Error('Namespace cannot contain \'$\' symbol.');
236
- const details = new DAutoload();
237
- Object.assign(details, {ns: namespace, path, ext, isAbsolute: is_absolute});
238
- resolver.addNamespaceRoot(details);
239
- };
240
-
241
- /**
242
- * Delete stored instance or import result (factory function or object) by `id` (if exist).
243
- *
244
- * @param {string} depId
245
- */
246
- this.delete = function (depId) {
247
- const parsed = $parser.parse(depId);
248
- if (parsed.typeTarget === ParsedId.TYPE_TARGET_SINGLETON) {
249
- singletons.delete(parsed.mapKey);
250
- } else if (parsed.typeTarget === ParsedId.TYPE_TARGET_FACTORY) {
251
- factories.delete(parsed.mapKey);
252
- } else {
253
- const errMsg = `Dependency ID is not manually inserted factory or singleton: ${depId}. `
254
- + 'See \'https://github.com/teqfw/di/blob/master/docs/identifiers.md\'.';
255
- throw new Error(errMsg);
256
- }
257
- };
258
-
259
- /**
260
- * Get/create object|function|class|module by dependency ID (wrapper for internal function).
261
- *
262
- * @param {string} depId 'namedDep', 'Vendor_Module', 'New_Object_From_Default$', 'Singleton_From_Default$$'
263
- * @param {String} context ID of the main object for whom container retrieves the dependency (TODO)
264
- * @returns {Promise<*>}
265
- *
266
- * TODO: we can use context to get significant info from requester (requester depId or prepared deps
267
- * TODO: /bootstrap path, for example/).
268
- */
269
- this.get = async function (depId, context = null) {
270
- return await getObject(depId, []);
271
- };
272
-
273
- /**
274
- * @returns {TeqFw_Di_Shared_Resolver}
275
- */
276
- this.getNsResolver = function () {
277
- return resolver;
278
- };
279
- /**
280
- * Check existence of created instance or imported data in container.
281
- *
282
- * @param {string} depId
283
- * @returns {boolean}
284
- */
285
- this.has = function (depId) {
286
- const parsed = $parser.parse(depId);
287
- if (parsed.typeTarget === ParsedId.TYPE_TARGET_SINGLETON) {
288
- return singletons.has(parsed.mapKey);
289
- } else if (parsed.typeTarget === ParsedId.TYPE_TARGET_FACTORY) {
290
- return factories.has(parsed.mapKey);
291
- } else {
292
- const errMsg = `Dependency ID is not manually inserted factory or singleton: ${depId}. `
293
- + 'See \'https://github.com/teqfw/di/blob/master/docs/identifiers.md\'.';
294
- throw new Error(errMsg);
295
- }
296
- };
297
-
298
- /**
299
- * Get list of contained dependencies (created instances and loaded modules).
300
- * @returns {{constructors: string[], singletons: string[], modules: string[]}}
301
- */
302
- this.list = function () {
303
- const sItems = Array.from(singletons.keys()).sort();
304
- const fItems = Array.from(factories.keys()).sort();
305
- return {singletons: sItems, constructors: fItems};
306
- };
307
-
308
- /**
309
- * Place object into the container. Replace existing instance with the same ID.
310
- *
311
- * 'object' should correlate with 'depId':
312
- * - singleton ('namedDep'): any object will be stored as singleton;
313
- * - ES module ('Vendor_Module'): will be stored as ES module;
314
- * - constructor ('New_Object_From_Default$'): will be stored as object constructor with key 'New_Object_From_Default';
315
- * - instance ('Singleton_From_Default$$'): will be stored as singleton with key 'Singleton_From_Default';
316
- *
317
- * @param {string} depId 'namedDep', 'Vendor_Module', 'New_Object_From_Default$', 'Singleton_From_Default$$'.
318
- * @param {Object} object
319
- */
320
- this.set = function (depId, object) {
321
- const parsed = $parser.parse(depId);
322
- if (parsed.typeTarget === ParsedId.TYPE_TARGET_SINGLETON) {
323
- singletons.set(parsed.mapKey, object);
324
- } else if (parsed.typeTarget === ParsedId.TYPE_TARGET_FACTORY) {
325
- factories.set(parsed.mapKey, object);
326
- } else {
327
- const errMsg = `Dependency ID is not valid for factory or singleton: ${depId}. `
328
- + 'See \'https://github.com/teqfw/di/blob/master/docs/identifiers.md\'.';
329
- throw new Error(errMsg);
330
- }
331
- };
332
- }
333
- }
@@ -1,96 +0,0 @@
1
- /**
2
- * Data transfer object to store parsing results of identifiers for imports and injects:
3
- *
4
- * Manually inserted into dependency injection container:
5
- * - 'namedSingleton': singleton object stored in container (dependency injection);
6
- * - 'namedFactory$$': create new object using stored factory (dependency injection);
7
- *
8
- * Filepath based identifiers for dynamic imports and dependency injection:
9
- * - '@vendor/package!module': load and get ES module using Filepath Namespaces (dynamic import);
10
- * - '@vendor/package!module#': load ES module and get default export (dynamic import);
11
- * - '@vendor/package!module$': load ES module, create new object from default export and use as singleton;
12
- * - '@vendor/package!module$$': load ES module and use default export as factory for new objects;
13
- * - '@vendor/package!module#export': load ES module and get named export;
14
- * - '@vendor/package!module#export$': load ES module, create new object from named export and use as singleton;
15
- * - '@vendor/package!module#export$$': load ES module and use named export as factory for new objects;
16
-
17
- * Logical namespaces identifiers for dependency injection and dynamic imports:
18
- * - 'Ns_Module': load and get ES module using Logical Namespaces (dynamic import);
19
- * - 'Ns_Module#': load ES module and get default export (dynamic import);
20
- * - 'Ns_Module$': load ES module, create new object from default export and use as singleton;
21
- * - 'Ns_Module$$': load ES module and use default export as factory for new objects;
22
- * - 'Ns_Module#export': load ES module and get named export;
23
- * - 'Ns_Module#export$': load ES module, create new object from named export and use as singleton;
24
- * - 'Ns_Module#export$$': load ES module and use named export as factory for new objects;
25
- *
26
- * @see https://github.com/teqfw/di/blob/master/docs/identifiers.md
27
- */
28
- // MODULE'S CLASSES
29
- /**
30
- * Structure to store parsing results of identifiers for imports and injects.
31
- */
32
- export default class TeqFw_Di_Shared_IdParser_Dto {
33
- /**
34
- * 'true' if dependency should be a proxy.
35
- * @type {boolean}
36
- */
37
- isProxy;
38
- /**
39
- * Key to map object in container's store (singletons, constructors, modules) - original id w/o '$' chars.
40
- * @type {string}
41
- */
42
- mapKey;
43
- /**
44
- * Name of an export in the ES6-module (export default fn() {}).
45
- * @type {string}
46
- */
47
- nameExport;
48
- /**
49
- * Module name: 'module', 'Ns_Module'.
50
- * @type {string}
51
- */
52
- nameModule;
53
- /**
54
- * Package name: '@vendor/package'.
55
- * @type {string}
56
- */
57
- namePackage;
58
- /**
59
- * Original identifier: namedSingleton, namedConstructor$$, @vendor/package!module#export$$, Ns_Module#export$$.
60
- * @type {string}
61
- */
62
- orig;
63
- /**
64
- * type of ID (manual, filepath based, logical namespace; see TYPE_ID_...).
65
- * @type {symbol}
66
- */
67
- typeId;
68
- /**
69
- * Type of target object identified by ID (package, module, export, factory, singleton).
70
- * @type {symbol}
71
- */
72
- typeTarget;
73
- }
74
-
75
- // ES2015 (ES6) 'static' is not compatible with Safari, so add as class props
76
- /** @type {symbol} marker for filepath based IDs (@vendor/package!module#exportName$$) */
77
- TeqFw_Di_Shared_IdParser_Dto.TYPE_ID_FILEPATH = Symbol('TYPE_ID_FILEPATH');
78
- /** @type {symbol} marker for logical namespace IDs (Ns_Module#exportName$$) */
79
- TeqFw_Di_Shared_IdParser_Dto.TYPE_ID_LOGICAL = Symbol('TYPE_ID_LOGICAL');
80
- /** @type {symbol} marker for IDs for manually inserted objects into DI container (singleton, factory$$) */
81
- TeqFw_Di_Shared_IdParser_Dto.TYPE_ID_MANUAL = Symbol('TYPE_ID_MANUAL');
82
- /** @type {symbol} marker for export targets (@vendor/package!module#exportName) */
83
- TeqFw_Di_Shared_IdParser_Dto.TYPE_TARGET_EXPORT = Symbol('TYPE_TARGET_EXPORT');
84
- /** @type {symbol} marker for factory targets (@vendor/package!module#exportName$$) */
85
- TeqFw_Di_Shared_IdParser_Dto.TYPE_TARGET_FACTORY = Symbol('TYPE_TARGET_FACTORY');
86
- /** @type {symbol} marker for module targets (@vendor/package!module) */
87
- TeqFw_Di_Shared_IdParser_Dto.TYPE_TARGET_MODULE = Symbol('TYPE_TARGET_MODULE');
88
- /** @type {symbol} marker for package targets (@vendor/package! - RESERVED, NOT USED) */
89
- TeqFw_Di_Shared_IdParser_Dto.TYPE_TARGET_PACKAGE = Symbol('TYPE_TARGET_PACKAGE');
90
- /** @type {symbol} marker for singleton targets (@vendor/package!module#exportName$) */
91
- TeqFw_Di_Shared_IdParser_Dto.TYPE_TARGET_SINGLETON = Symbol('TYPE_TARGET_SINGLETON');
92
-
93
- // This DTO does not contain Factory class because it is used internally.
94
-
95
- // freeze class to deny attributes changes
96
- Object.freeze(TeqFw_Di_Shared_IdParser_Dto);
@@ -1,187 +0,0 @@
1
- // MODULE'S IMPORT
2
- import ParsedId from './IdParser/Dto.mjs';
3
-
4
- // MODULE'S VARS
5
- /** @type {string} default export keyword */
6
- const DEF_EXP = 'default';
7
- /** @type {string} logical namespace export mark (Ns_Mod.export) */
8
- const EXP = '.';
9
- /** @type {string} filesystem export mark (@vendor/package!module#export$$) and old logical export mark */
10
- const EXP_OLD = '#';
11
- /** @type {RegExp} expression for filepath based IDs (@vendor/package!module#export$$) */
12
- const FILEPATH_ID = /^((([a-z@])([A-Za-z0-9_\-/@]*))(!([A-Za-z0-9_\-/@]*)?((#)?([A-Za-z0-9_]*)(\${1,2})?)?)?)$/;
13
- /** @type {string} filesystem module mark (@vendor/package!module#export$$) */
14
- const FSM = '!';
15
- /** @type {string} new instance mark (Ns_Mod.export$$) */
16
- const INST = '$$';
17
- /** @type {RegExp} expression for logical namespace IDs (Ns_Module#export$$) */
18
- const LOGICAL_NS_ID = /^((([A-Z])[A-Za-z0-9_]*)((#|.)?([A-Za-z0-9_]*)(\${1,2}|@{1,2})?)?)$/;
19
- /** @type {RegExp} expression for objects that manually added to DI container (singleton, namedFactory$$) */
20
- const MANUAL_DI_ID = /^((([a-z])[A-Za-z0-9_]*)(\$\$)?)$/;
21
- /** @type {string} new instance proxy mark (Ns_Mod.export@@) */
22
- const P_INST = '@@';
23
- /** @type {string} singleton proxy mark (Ns_Mod.export@) */
24
- const P_SNGLT = '@';
25
- /** @type {string} singleton mark (Ns_Mod.export$) */
26
- const SNGLT = '$';
27
-
28
- // MODULE'S CLASSES
29
- /**
30
- * Dependency identifiers parser.
31
- */
32
- export default class TeqFw_Di_Shared_IdParser {
33
- /**
34
- * Validate dependency identifier, parse and return parts of the identifier.
35
- *
36
- * @param {string} id Dependency identifier to validate and parse.
37
- * @returns {TeqFw_Di_Shared_IdParser_Dto} Parsed data for given ID.
38
- * @throws {Error} if `id` is not valid.
39
- */
40
- parse(id) {
41
- let result = this.parseManualDiId(id);
42
- if (!result) result = this.parseLogicalNsId(id);
43
- if (!result) result = this.parseFilepathId(id);
44
- if (!result)
45
- throw new Error(`Invalid identifier: '${id}'. See 'https://github.com/teqfw/di/blob/master/docs/identifiers.md'.`);
46
- return result;
47
- }
48
-
49
- /**
50
- * Parse filepath based identifiers (@vendor/package!module#exportedFactory$$).
51
- * @param {string} id
52
- * @returns {null|TeqFw_Di_Shared_IdParser_Dto}
53
- */
54
- parseFilepathId(id) {
55
- let result = null;
56
- const parts = FILEPATH_ID.exec(id);
57
- if (parts) {
58
- result = new ParsedId();
59
- result.orig = id;
60
- result.typeId = ParsedId.TYPE_ID_FILEPATH;
61
- result.namePackage = parts[2];
62
- if (!parts[6]) {
63
- result.typeTarget = ParsedId.TYPE_TARGET_PACKAGE;
64
- } else {
65
- result.nameModule = parts[6];
66
- result.mapKey = parts[1];
67
- result.typeTarget = ParsedId.TYPE_TARGET_MODULE;
68
- if (parts[8] === EXP_OLD) {
69
- result.nameExport = DEF_EXP;
70
- result.typeTarget = ParsedId.TYPE_TARGET_EXPORT;
71
- result.mapKey = undefined;
72
- }
73
- if (parts[9]) {
74
- result.nameExport = parts[9];
75
- result.typeTarget = ParsedId.TYPE_TARGET_EXPORT;
76
- result.mapKey = undefined;
77
- }
78
- if (parts[10]) {
79
- if (parts[10] === INST) {
80
- result.typeTarget = ParsedId.TYPE_TARGET_FACTORY;
81
- } else if (parts[10] === SNGLT) {
82
- result.typeTarget = ParsedId.TYPE_TARGET_SINGLETON;
83
- }
84
- if (result.nameExport === undefined) {
85
- result.nameExport = DEF_EXP;
86
- result.mapKey = result.namePackage + FSM + result.nameModule;
87
- } else {
88
- result.mapKey = result.namePackage + FSM + result.nameModule + EXP_OLD + result.nameExport;
89
- }
90
- }
91
- }
92
- }
93
- return result;
94
- }
95
-
96
- /**
97
- * Parse logical namespaces identifiers (Ns_Module#exportedFactory$$).
98
- * @param {string} id
99
- * @returns {null|TeqFw_Di_Shared_IdParser_Dto}
100
- */
101
- parseLogicalNsId(id) {
102
- let result = null;
103
- const parts = LOGICAL_NS_ID.exec(id);
104
- if (parts) {
105
- result = new ParsedId();
106
- result.orig = id;
107
- result.typeId = ParsedId.TYPE_ID_LOGICAL;
108
- result.nameModule = parts[2];
109
- result.isProxy = false;
110
- result.mapKey = result.nameModule; // init mapKey with module's name
111
- result.typeTarget = ParsedId.TYPE_TARGET_MODULE;
112
- // Ns_Module.name$$[@@] - named instance [proxy]
113
- if (
114
- ((parts[5] === EXP) || (parts[5] === EXP_OLD))
115
- && ((parts[7] === INST) || (parts[7] === P_INST))
116
- ) {
117
- result.isProxy = (parts[7] === P_INST);
118
- result.nameExport = parts[6];
119
- result.typeTarget = ParsedId.TYPE_TARGET_FACTORY;
120
- result.mapKey = result.nameModule + EXP + result.nameExport;
121
- }
122
- // Ns_Module.name$[@] - named singleton [proxy]
123
- else if (
124
- ((parts[5] === EXP) || (parts[5] === EXP_OLD))
125
- && ((parts[7] === SNGLT) || (parts[7] === P_SNGLT))
126
- ) {
127
- result.isProxy = (parts[7] === P_SNGLT);
128
- result.nameExport = parts[6];
129
- result.typeTarget = ParsedId.TYPE_TARGET_SINGLETON;
130
- result.mapKey = result.nameModule + EXP + result.nameExport;
131
- }
132
- // Ns_Module.name - named export
133
- else if (
134
- ((parts[5] === EXP) || (parts[5] === EXP_OLD))
135
- && ((parts[6] !== undefined) && (parts[6] !== ''))
136
- ) {
137
- result.nameExport = parts[6];
138
- result.typeTarget = ParsedId.TYPE_TARGET_EXPORT;
139
- result.mapKey = undefined;
140
- }
141
- // Ns_Module$$[@@]- default instance [proxy]
142
- else if ((parts[4] === INST) || (parts[4] === P_INST)) {
143
- result.isProxy = (parts[4] === P_INST);
144
- result.nameExport = DEF_EXP;
145
- result.typeTarget = ParsedId.TYPE_TARGET_FACTORY;
146
- }
147
- // Ns_Module$[@] - default singleton [proxy]
148
- else if ((parts[4] === SNGLT) || (parts[4] === P_SNGLT)) {
149
- result.isProxy = (parts[4] === P_SNGLT);
150
- result.nameExport = DEF_EXP;
151
- result.typeTarget = ParsedId.TYPE_TARGET_SINGLETON;
152
- }
153
- // Ns_Module#[.] - default export
154
- else if (
155
- ((parts[5] === EXP) || (parts[5] === EXP_OLD))
156
- && (parts[7] === undefined)
157
- ) {
158
- result.nameExport = DEF_EXP;
159
- result.typeTarget = ParsedId.TYPE_TARGET_EXPORT;
160
- result.mapKey = undefined;
161
- }
162
- }
163
- return result;
164
- }
165
-
166
- /**
167
- * Parse manually inserted identifiers (singleton, factory$$).
168
- * @param {string} id
169
- * @returns {null|TeqFw_Di_Shared_IdParser_Dto}
170
- */
171
- parseManualDiId(id) {
172
- let result = null;
173
- const parts = MANUAL_DI_ID.exec(id);
174
- if (parts) {
175
- result = new ParsedId();
176
- result.orig = id;
177
- result.typeId = ParsedId.TYPE_ID_MANUAL;
178
- result.mapKey = parts[2];
179
- if (parts[4] === '$$') {
180
- result.typeTarget = ParsedId.TYPE_TARGET_FACTORY;
181
- } else {
182
- result.typeTarget = ParsedId.TYPE_TARGET_SINGLETON;
183
- }
184
- }
185
- return result;
186
- }
187
- }
@@ -1,38 +0,0 @@
1
- // MODULE'S CLASSES
2
- /**
3
- * Load ES6 module sources and save it to internal registry.
4
- */
5
- export default class TeqFw_Di_Shared_ModuleLoader {
6
- /** @type {TeqFw_Di_Shared_Resolver} */
7
- resolver
8
-
9
- /**
10
- * @param {TeqFw_Di_Shared_Resolver} resolver
11
- */
12
- constructor(resolver) {
13
- this.resolver = resolver;
14
- /**
15
- * Storage for loaded modules.
16
- * Module name ('Vendor_Project_Module') is a key in the map.
17
- */
18
- const _modules = new Map();
19
-
20
- this.getModule = async function (moduleId) {
21
- let result, sourceFile;
22
- if (_modules[moduleId]) {
23
- result = _modules[moduleId];
24
- } else {
25
- try {
26
- sourceFile = this.resolver.resolveModuleId(moduleId);
27
- result = await import(sourceFile);
28
- _modules.set(moduleId, result);
29
- } catch (e) {
30
- let msg = `Cannot load source file '${sourceFile}' (module id: ${moduleId}).`;
31
- if (e.message) msg = `${msg} Error: ${e.message}`;
32
- throw new Error(msg);
33
- }
34
- }
35
- return result;
36
- };
37
- }
38
- }
@@ -1 +0,0 @@
1
- This code can be used in browsers and nodejs apps.