@teqfw/di 0.20.0 → 0.21.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.
@@ -0,0 +1,70 @@
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
+ * @return {Promise<*>}
30
+ */
31
+ this.create = async function (depId, module, stack, container) {
32
+ if (stack.includes(depId.value))
33
+ throw new Error(`Circular dependency for '${depId.value}'. Parents are: ${JSON.stringify(stack)}`);
34
+ if (depId.exportName) {
35
+ // use export from the es6-module
36
+ const stackNew = [...stack, depId.value];
37
+ const {[depId.exportName]: exp} = module;
38
+ if (depId.composition === Defs.COMPOSE_FACTORY) {
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.value}' are: ${JSON.stringify(deps)}`);
43
+ const spec = {};
44
+ for (const dep of deps)
45
+ spec[dep] = await container.compose(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
+ // TODO: this is almost useless option
60
+ return module;
61
+ }
62
+ };
63
+
64
+ this.setDebug = function (data) {
65
+ _debug = data;
66
+ };
67
+
68
+ // MAIN
69
+ }
70
+ };
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Default parser for object keys in format:
3
+ * - Vnd_Pkg_Prj_Mod$FA
4
+ *
5
+ * @namespace TeqFw_Di_Container_A_Parser_Chunk_Def
6
+ */
7
+ import Dto from '../../../../DepId.js';
8
+ import Defs from '../../../../Defs.js';
9
+
10
+ // VARS
11
+ /** @type {RegExp} expression for default object key (Ns_Module[.|#]export$[F|A][S|I]) */
12
+ const REGEXP = /^((([A-Z])[A-Za-z0-9_]*)((#|\.)?([A-Za-z0-9]*)((\$)([F|A])?([S|I])?)?)?)$/;
13
+
14
+ /**
15
+ * @implements TeqFw_Di_Api_Container_Parser_Chunk
16
+ */
17
+ export default class TeqFw_Di_Container_A_Parser_Chunk_Def {
18
+
19
+ canParse(depId) {
20
+ // default parser always trys to parse the depId
21
+ return true;
22
+ }
23
+
24
+ parse(objectKey) {
25
+ const res = new Dto();
26
+ res.value = objectKey;
27
+ const parts = REGEXP.exec(objectKey);
28
+ if (parts) {
29
+ res.moduleName = parts[2];
30
+ if (parts[5] === '.') {
31
+ // App_Service.export...
32
+ if (parts[8] === '$') {
33
+ // App_Service.export$...
34
+ res.composition = Defs.COMPOSE_FACTORY;
35
+ res.exportName = parts[6];
36
+ res.life = (parts[10] === Defs.LIFE_INSTANCE)
37
+ ? Defs.LIFE_INSTANCE : Defs.LIFE_SINGLETON;
38
+ } else {
39
+ res.composition = ((parts[8] === undefined) || (parts[8] === Defs.COMPOSE_AS_IS))
40
+ ? Defs.COMPOSE_AS_IS : Defs.COMPOSE_FACTORY;
41
+ res.exportName = parts[6];
42
+ res.life = ((parts[8] === undefined) || (parts[10] === Defs.LIFE_SINGLETON))
43
+ ? Defs.LIFE_SINGLETON : Defs.LIFE_INSTANCE;
44
+ }
45
+
46
+
47
+ } else if (parts[8] === '$') {
48
+ // App_Logger$FS
49
+ res.composition = ((parts[9] === undefined) || (parts[9] === Defs.COMPOSE_FACTORY))
50
+ ? Defs.COMPOSE_FACTORY : Defs.COMPOSE_AS_IS;
51
+ res.exportName = 'default';
52
+ if (parts[10]) {
53
+ res.life = (parts[10] === Defs.LIFE_SINGLETON) ? Defs.LIFE_SINGLETON : Defs.LIFE_INSTANCE;
54
+ } else {
55
+ res.life = (res.composition === Defs.COMPOSE_FACTORY) ? Defs.LIFE_SINGLETON : Defs.LIFE_INSTANCE;
56
+ }
57
+ } else {
58
+ // App_Service
59
+ res.composition = Defs.COMPOSE_AS_IS;
60
+ res.exportName = 'default';
61
+ res.life = Defs.LIFE_SINGLETON;
62
+ }
63
+ }
64
+
65
+ // we should always use singletons for as-is exports
66
+ if ((res.composition === Defs.COMPOSE_AS_IS) && (res.life === Defs.LIFE_INSTANCE))
67
+ throw new Error(`Export is not a function and should be used as a singleton only: '${res.value}'.`);
68
+ return res;
69
+ }
70
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The parser for the runtime dependency ID contains multiple chunks. Each npm package can have its own format for
3
+ * a `depId`. The parser calls the chunks one by one to parse the string ID as a structure and returns the first result.
4
+ * If none of the chunks processed the `depId`, the parser calls the default chunk.
5
+ */
6
+ import DefChunk from './A/Parser/Chunk/Def.js';
7
+
8
+ /**
9
+ * @implements TeqFw_Di_Api_Container_Parser
10
+ */
11
+ export default class TeqFw_Di_Container_Parser {
12
+ constructor() {
13
+ // VARS
14
+ /**
15
+ * The default chunk to parse the depId if no other chunks have parsed this depId.
16
+ *
17
+ * @type {TeqFw_Di_Api_Container_Parser_Chunk}
18
+ */
19
+ let _defaultChunk = new DefChunk();
20
+ /**
21
+ * The array of the chunks to parse dependency IDs.
22
+ * @type {TeqFw_Di_Api_Container_Parser_Chunk[]}
23
+ */
24
+ const _chunks = [];
25
+
26
+ // INSTANCE METHODS
27
+
28
+ this.addChunk = function (chunk) {
29
+ _chunks.push(chunk);
30
+ };
31
+
32
+ this.parse = function (depId) {
33
+ let res;
34
+ for (const one of _chunks)
35
+ if (one.canParse(depId)) {
36
+ res = one.parse(depId);
37
+ break;
38
+ }
39
+ if (!res)
40
+ res = _defaultChunk?.parse(depId);
41
+ return res;
42
+ };
43
+
44
+ this.setDefaultChunk = function (chunk) {
45
+ _defaultChunk = chunk;
46
+ };
47
+ }
48
+ };
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The post-processor handles the result object after composition and before returning.
3
+ *
4
+ * @implements TeqFw_Di_Api_Container_PostProcessor
5
+ */
6
+ export default class TeqFw_Di_Container_PostProcessor {
7
+
8
+ constructor() {
9
+ // VARS
10
+
11
+ /**
12
+ * The array of the chunks to modify dependency IDs.
13
+ * @type {TeqFw_Di_Api_Container_PostProcessor_Chunk[]}
14
+ */
15
+ const _chunks = [];
16
+
17
+ // INSTANCE METHODS
18
+
19
+ this.addChunk = function (chunk) {
20
+ _chunks.push(chunk);
21
+ };
22
+
23
+ this.modify = async function (obj, depId, stack) {
24
+ let res = obj;
25
+ for (const one of _chunks) {
26
+ res = one.modify(res, depId, stack);
27
+ if (res instanceof Promise) res = await res;
28
+ }
29
+ return res;
30
+ };
31
+ }
32
+ };
@@ -0,0 +1,34 @@
1
+ /**
2
+ * The preprocessor handles object keys after the parsing but before creating any objects.
3
+ * A replacement rules can be implemented here.
4
+ * Every handler is a function with 2 arguments:
5
+ * - objectKey: current key after processing with other handlers;
6
+ * - originalKey: the key before any processing;
7
+ *
8
+ * @implements TeqFw_Di_Api_Container_PreProcessor
9
+ */
10
+ export default class TeqFw_Di_Container_PreProcessor {
11
+
12
+ constructor() {
13
+ // VARS
14
+
15
+ /**
16
+ * The array of the chunks to modify dependency IDs.
17
+ * @type {TeqFw_Di_Api_Container_PreProcessor_Chunk[]}
18
+ */
19
+ const _chunks = [];
20
+
21
+ // INSTANCE METHODS
22
+
23
+ this.addChunk = function (chunk) {
24
+ _chunks.push(chunk);
25
+ };
26
+
27
+ this.modify = function (depId, stack) {
28
+ let res = depId;
29
+ for (const one of _chunks)
30
+ res = one.modify(res, depId, stack);
31
+ return res;
32
+ };
33
+ }
34
+ };
@@ -7,7 +7,7 @@
7
7
  * - every package has sources with the same extensions (*.js, *.mjs, *.es6, ...)
8
8
  * - namespaces can be nested (App_Web_ => ./@app/web/..., App_Web_Api_ => ./@app/web_api/...)
9
9
  */
10
- import Defs from './Defs.js';
10
+ import Defs from '../Defs.js';
11
11
 
12
12
  // VARS
13
13
  const KEY_EXT = 'ext';
@@ -21,7 +21,7 @@ const KEY_PATH = 'root';
21
21
  const NSS = '_';
22
22
 
23
23
  // MAIN
24
- export default class TeqFw_Di_Resolver {
24
+ export default class TeqFw_Di_Container_Resolver {
25
25
 
26
26
  constructor() {
27
27
  // VARS
@@ -55,7 +55,8 @@ export default class TeqFw_Di_Resolver {
55
55
  }
56
56
  }
57
57
  if (root && ext) {
58
- const tail = moduleName.replace(ns, '');
58
+ let tail = moduleName.replace(ns, '');
59
+ if (tail.indexOf(NSS) === 0) tail = tail.replace(NSS, '');
59
60
  const file = tail.replaceAll(NSS, _ps);
60
61
  return `${root}${_ps}${file}.${ext}`;
61
62
  } else return moduleName;
package/src/Container.js CHANGED
@@ -1,19 +1,18 @@
1
1
  /**
2
2
  * The Object Container (composition root).
3
+ * @namespace TeqFw_Di_Container
3
4
  */
4
- import Composer from './Composer.js';
5
+ import Composer from './Container/A/Composer.js';
5
6
  import Defs from './Defs.js';
6
- import Parser from './Parser.js';
7
- import PreProcessor from './PreProcessor.js';
8
- import NewReplace from './PreProcessor/Replace.js';
9
- import Resolver from './Resolver.js';
10
-
11
- // VARS
7
+ import Parser from './Container/Parser.js';
8
+ import PreProcessor from './Container/PreProcessor.js';
9
+ import PostProcessor from './Container/PostProcessor.js';
10
+ import Resolver from './Container/Resolver.js';
12
11
 
13
12
  // FUNCS
14
13
  /**
15
14
  * ID to store singletons in the internal registry.
16
- * @param {TeqFw_Di_Api_ObjectKey} key
15
+ * @param {TeqFw_Di_DepId} key
17
16
  * @return {string}
18
17
  */
19
18
  function getSingletonId(key) {
@@ -21,6 +20,9 @@ function getSingletonId(key) {
21
20
  }
22
21
 
23
22
  // MAIN
23
+ /**
24
+ * @implements TeqFw_Di_Api_Container
25
+ */
24
26
  export default class TeqFw_Di_Container {
25
27
 
26
28
  constructor() {
@@ -29,13 +31,14 @@ export default class TeqFw_Di_Container {
29
31
  let _debug = false;
30
32
  let _parser = new Parser();
31
33
  let _preProcessor = new PreProcessor();
32
- _preProcessor.addHandler(NewReplace()); // create new instance of the replacement handler
34
+ let _postProcessor = new PostProcessor();
33
35
 
34
36
  /**
35
- * Registry for loaded es6 modules.
36
- * @type {Object<string, Module>}
37
+ * Registry for paths for loaded es6 modules.
38
+ *
39
+ * @type {Object<string, string>}
37
40
  */
38
- const _regModules = {};
41
+ const _regPaths = {};
39
42
  /**
40
43
  * Registry to store singletons.
41
44
  * @type {Object<string, *>}
@@ -44,31 +47,38 @@ export default class TeqFw_Di_Container {
44
47
  let _resolver = new Resolver();
45
48
 
46
49
  // FUNCS
47
- function error() {
48
- console.error(...arguments);
49
- }
50
50
 
51
51
  function log() {
52
52
  if (_debug) console.log(...arguments);
53
53
  }
54
54
 
55
-
56
55
  // INSTANCE METHODS
57
56
 
58
- this.get = async function (objectKey, stack = []) {
59
- log(`Object '${objectKey}' is requested.`);
57
+ this.get = async function (runtimeDepId) {
58
+ return this.compose(runtimeDepId, []);
59
+ };
60
+
61
+ /**
62
+ * This method is 'private' for the npm package. It is used in the Composer only.
63
+ *
64
+ * @param {string} depId runtime dependency ID
65
+ * @param {string[]} stack set of the depId to detect circular dependencies
66
+ * @return {Promise<*>}
67
+ */
68
+ this.compose = async function (depId, stack = []) {
69
+ log(`Object '${depId}' is requested.`);
60
70
  // return container itself if requested
61
71
  if (
62
- (objectKey === Defs.KEY_CONTAINER) ||
63
- (objectKey === Defs.KEY_CONTAINER_NS)
72
+ (depId === Defs.KEY_CONTAINER) ||
73
+ (depId === Defs.KEY_CONTAINER_NS)
64
74
  ) {
65
75
  log(`Container itself is returned.`);
66
76
  return _regSingles[Defs.KEY_CONTAINER];
67
77
  }
68
78
  // parse the `objectKey` and get the structured DTO
69
- const parsed = _parser.parse(objectKey);
79
+ const parsed = _parser.parse(depId);
70
80
  // modify original key according to some rules (replacements, etc.)
71
- const key = _preProcessor.process(parsed);
81
+ const key = _preProcessor.modify(parsed, stack);
72
82
  // return existing singleton
73
83
  if (key.life === Defs.LIFE_SINGLETON) {
74
84
  const singleId = getSingletonId(key);
@@ -77,52 +87,47 @@ export default class TeqFw_Di_Container {
77
87
  return _regSingles[singleId];
78
88
  }
79
89
  }
80
- // load es6 module if not loaded before
81
- if (!_regModules[key.moduleName]) {
82
- log(`ES6 module '${key.moduleName}' is not loaded yet`);
90
+ // resolve path to es6 module if not resolved before
91
+ if (!_regPaths[key.moduleName]) {
92
+ log(`ES6 module '${key.moduleName}' is not resolved yet`);
83
93
  // convert module name to the path to es6-module file with a sources
84
- const path = _resolver.resolve(key.moduleName);
85
- try {
86
- _regModules[key.moduleName] = await import(path);
87
- log(`ES6 module '${key.moduleName}' is loaded from '${path}'.`);
88
- } catch (e) {
89
- console.error(
90
- e?.message,
91
- `Object key: "${objectKey}".`,
92
- `Path: "${path}".`,
93
- `Stack: ${JSON.stringify(stack)}`
94
- );
95
- throw e;
96
- }
97
-
94
+ _regPaths[key.moduleName] = _resolver.resolve(key.moduleName);
98
95
  }
99
- // create object using the composer
100
- let res = await _composer.create(key, _regModules[key.moduleName], stack, this);
101
- log(`Object '${objectKey}' is created.`);
102
-
103
- // TODO: refactor this code to use wrappers w/o hardcode
104
- if (key.wrappers.includes(Defs.WRAP_PROXY)) {
105
- const me = this;
106
- res = new Proxy({dep: undefined, objectKey}, {
107
- get: async function (base, name) {
108
- if (name === 'create') base.dep = await me.get(base.objectKey);
109
- return base.dep;
110
- }
111
- });
96
+
97
+ // load es6 module
98
+ let module;
99
+ const path = _regPaths[key.moduleName];
100
+ try {
101
+ module = await import(path);
102
+ log(`ES6 module '${key.moduleName}' is loaded from '${path}'.`);
103
+ } catch (e) {
104
+ console.error(
105
+ e?.message,
106
+ `Object key: "${depId}".`,
107
+ `Path: "${path}".`,
108
+ `Stack: ${JSON.stringify(stack)}`
109
+ );
110
+ throw e;
112
111
  }
112
+ // create object using the composer then modify it in post-processor
113
+ let res = await _composer.create(key, module, stack, this);
114
+ res = await _postProcessor.modify(res, key, stack);
115
+ log(`Object '${depId}' is created.`);
113
116
 
117
+ // save singletons
114
118
  if (key.life === Defs.LIFE_SINGLETON) {
115
119
  const singleId = getSingletonId(key);
116
120
  _regSingles[singleId] = res;
117
- log(`Object '${objectKey}' is saved as singleton.`);
121
+ log(`Object '${depId}' is saved as singleton.`);
118
122
  }
119
123
  return res;
120
124
  };
121
125
 
122
126
  this.getParser = () => _parser;
123
127
 
124
- this.getPreProcessor = () => _preProcessor
125
- ;
128
+ this.getPreProcessor = () => _preProcessor;
129
+
130
+ this.getPostProcessor = () => _postProcessor;
126
131
  this.getResolver = () => _resolver;
127
132
 
128
133
  this.setDebug = function (data) {
@@ -134,6 +139,8 @@ export default class TeqFw_Di_Container {
134
139
 
135
140
  this.setPreProcessor = (data) => _preProcessor = data;
136
141
 
142
+ this.setPostProcessor = (data) => _postProcessor = data;
143
+
137
144
  this.setResolver = (data) => _resolver = data;
138
145
 
139
146
  // MAIN
package/src/Defs.js CHANGED
@@ -1,5 +1,6 @@
1
1
  /**
2
- * Hardcoded constants for the package.
2
+ * Hardcoded constants and useful utilities for the package.
3
+ * @namespace TeqFw_Di_Defs
3
4
  */
4
5
  export default {
5
6
  COMPOSE_AS_IS: 'A',
@@ -9,6 +10,9 @@ export default {
9
10
  KEY_CONTAINER_NS: 'TeqFw_Di_Container$',
10
11
  LIFE_INSTANCE: 'I',
11
12
  LIFE_SINGLETON: 'S',
13
+ /**
14
+ * @deprecated use TeqFw_Core_Shared_Defaults.DI_WRAP_PROXY
15
+ */
12
16
  WRAP_PROXY: 'proxy',
13
17
 
14
18
  /**
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * This is a DTO that represents the structure of an ID for a runtime dependency.
3
+ * @namespace TeqFw_Di_DepId
3
4
  */
4
- export default class TeqFw_Di_Api_ObjectKey {
5
+ export default class TeqFw_Di_DepId {
5
6
  /**
6
7
  * The name of an export of the module.
7
8
  * @type {string}
package/teqfw.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "@teqfw/di": {
3
+ "autoload": {
4
+ "ns": "TeqFw_Di",
5
+ "path": "./src",
6
+ "ext": "js"
7
+ }
8
+ }
9
+ }
package/src/Composer.js DELETED
@@ -1,68 +0,0 @@
1
- /**
2
- *
3
- */
4
- import Defs from './Defs.js';
5
- import specAnalyser from './SpecAnalyser.js';
6
-
7
- // FUNCS
8
-
9
- // MAIN
10
- export default class TeqFw_Di_Composer {
11
-
12
- constructor() {
13
- // VARS
14
- let _debug = false;
15
-
16
- // FUNCS
17
- function log(msg) {
18
- if (_debug) console.log(msg);
19
- }
20
-
21
- // INSTANCE METHODS
22
-
23
- /**
24
- *
25
- * @param {TeqFw_Di_Api_ObjectKey} key
26
- * @param {Object} module
27
- * @param {string[]} stack array of the parent objects to prevent dependency loop
28
- * @param {TeqFw_Di_Container} container
29
- * @return {Promise<*>}
30
- */
31
- this.create = async function (key, module, stack, container) {
32
- if (stack.includes(key.value))
33
- throw new Error(`Circular dependency for '${key.value}'. Parents are: ${JSON.stringify(stack)}`);
34
- if (key.exportName) {
35
- // use export from the es6-module
36
- const stackNew = [...stack, key.value];
37
- const {[key.exportName]: exp} = module;
38
- if (key.composition === Defs.COMPOSE_FACTORY) {
39
- if (typeof exp === 'function') {
40
- // create deps for factory function
41
- const deps = specAnalyser(exp);
42
- if (deps.length) log(`Deps for object '${key.value}' 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
- return exp;
57
- } else {
58
- return module;
59
- }
60
- };
61
-
62
- this.setDebug = function (data) {
63
- _debug = data;
64
- };
65
-
66
- // MAIN
67
- }
68
- };
@@ -1,68 +0,0 @@
1
- /**
2
- * This is default parser that converts dependency ID to the `depId` DTO.
3
- * @namespace ObjectKey.Parser
4
- */
5
- // IMPORTS
6
- import {ObjectKey} from '../Api/ObjectKey.mjs';
7
-
8
- // VARS
9
- /** @type {RegExp} expression for depId (Ns_Module.export$$#adapter) */
10
- const TMPL = /^(([A-Z])[A-Za-z0-9_]*)((.)([A-Za-z0-9_]*)?((\$|\$\$)?((#)([A-Za-z0-9_]*)?)?)?)?$/;
11
-
12
- // FUNCS
13
- /**
14
- * @param {string} depId
15
- * @return {Api.ObjectKey}
16
- */
17
- export default function (depId) {
18
- let res;
19
- const parts = TMPL.exec(depId);
20
- if (parts) {
21
- const nameMod = parts[1];
22
- const sepMod = parts[4]; // after-module separator
23
- const sepExp = parts[6]; // after-export separator
24
- const sepLife = parts[9]; // after-life separator
25
-
26
- res = new ObjectKey();
27
- // always presents
28
- res.nameModule = nameMod;
29
- if (sepLife === '#') {
30
- // the longest form of the ID (Mod.exp$#adp)
31
- res.adapter = parts[10] ?? 'default';
32
- res.isExport = true;
33
- res.isFactory = parts[7] !== undefined;
34
- if (parts[7] === '$') res.isSingleton = true;
35
- else if (parts[7] === '$$') res.isSingleton = false;
36
- res.nameExport = parts[5];
37
- } else if (sepMod === '#') {
38
- // Mod#adp
39
- res.adapter = parts[5] ?? 'default';
40
- res.isExport = true;
41
- res.isFactory = false;
42
- res.nameExport = 'default';
43
- } else if ((sepExp === '$') || (sepExp === '$$')) {
44
- if (sepMod === '.') {
45
- // Mod.exp$$
46
- res.isExport = true;
47
- res.isFactory = true;
48
- if (parts[7] === '$') res.isSingleton = true;
49
- else if (parts[7] === '$$') res.isSingleton = false;
50
- res.nameExport = parts[5];
51
- } else if (sepMod === '$') {
52
- // Mod$$
53
- res.isExport = true;
54
- res.isFactory = true;
55
- if (parts[3] === '$') res.isSingleton = true;
56
- else if (parts[3] === '$$') res.isSingleton = false;
57
- res.nameExport = 'default';
58
- }
59
- } else {
60
- // Mod.exp
61
- res.isFactory = false;
62
- res.isExport = (sepMod === '.');
63
- // define the name of the export
64
- if (res.isExport) res.nameExport = parts[5] ?? 'default';
65
- }
66
- }
67
- return res;
68
- }