@teqfw/di 0.7.0 → 0.11.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/README.md CHANGED
@@ -3,10 +3,12 @@
3
3
  "_DI_" means both "_Dynamic Import_" and "_Dependency Injection_" here. This package allows defining logical namespaces
4
4
  in your projects, dynamically importing ES6-modules from these namespaces, creating new objects from imported
5
5
  functions/classes and resolving dependencies in constructors. It uses pure ECMAScript 2015+ (ES6+) and works both for
6
- modern browsers & nodejs apps. You can share the same code between your frontend (browser) and your backend (nodejs) without TypeScript and preprocessors. Code in the browser's debugger will be the same as in your editor. Finally, you even can use interfaces in you projects and replace it with implementations.
6
+ modern browsers & nodejs apps. You can share the same code between your frontend (browser) and your backend (nodejs)
7
+ without TypeScript and preprocessors. Code in the browser's debugger will be the same as in your editor. Finally, you
8
+ even can use interfaces in you projects and replace it with implementations.
7
9
 
8
- The '_proxy object_' for `constructor` specification is inspired by [awilix](https://github.com/jeffijoe/awilix).
9
- Thanks guys.
10
+ The '_proxy object_' for `constructor` specification is inspired by [awilix](https://github.com/jeffijoe/awilix). Thanks
11
+ guys.
10
12
 
11
13
  ## Installation
12
14
 
@@ -36,7 +38,8 @@ import ScanData from '../Api/Dto/Scanned.mjs';
36
38
  import {existsSync, readdirSync, readFileSync, statSync} from 'fs';
37
39
  ```
38
40
 
39
- but DI container cannot process these imports. Function or class should have this interface to be compatible with DI container:
41
+ but DI container cannot process these imports. Function or class should have this interface to be compatible with DI
42
+ container:
40
43
 
41
44
  ```ecmascript 6
42
45
  export default function ObjectFactory(spec) {/* ... */}
package/RELEASE.md ADDED
@@ -0,0 +1,24 @@
1
+ # @teqfw/di releases
2
+
3
+ ## 0.11.0
4
+
5
+ * Restructure `/@teqfw/di/replace` node in `teqfw.json`.
6
+ * Remove `TeqFw_Di_Shared_Api_Enum_Area` enumeration.
7
+ * Fix example code (`npm run example`).
8
+
9
+ ## 0.10.0
10
+
11
+ * Improve error messaging.
12
+ * Use '.' instead of '#' in depIDs (Vnd_Plugin#export => Vnd_Plugin.export). Both variants are available for now.
13
+ * Experimental proxy for deps are added (Vnd_Plugin.export@@).
14
+
15
+ ## 0.9.0
16
+
17
+ * `TeqFw_Di_Shared_Api_Enum_Area` enumeration is added;
18
+
19
+ ## 0.8.0
20
+
21
+ * docs for plugin's teq-descriptor (see in `main` branch);
22
+ * use object notation instead of array notation in namespace replacement statements of
23
+ teq-descriptor (`@teqfw/di.replace` node format is changed in `./teqfw.json`);
24
+ * array is used as a container for upline dependencies in [SpecProxy](./src/Shared/SpecProxy.mjs) (object was);
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env bash
2
+ ##
3
+ # Clean development files from release branch
4
+ ##
5
+ DIR_ROOT=${DIR_ROOT:-$(cd "$(dirname "$0")/../../" && pwd)}
6
+
7
+ rm -fr "${DIR_ROOT}/doc/"
8
+ rm -fr "${DIR_ROOT}/node_modules/"
9
+ rm -fr "${DIR_ROOT}/package-lock.json"
10
+ rm -fr "${DIR_ROOT}/test/"
11
+ rm -fr "${DIR_ROOT}/tmp/"
package/package.json CHANGED
@@ -1,9 +1,7 @@
1
1
  {
2
2
  "name": "@teqfw/di",
3
- "version": "0.7.0",
3
+ "version": "0.11.0",
4
4
  "description": "Dependency Injection container based on logical namespaces for ES6 modules.",
5
- "type": "module",
6
- "main": "src/Shared/Container.mjs",
7
5
  "keywords": [
8
6
  "dependency injection",
9
7
  "di",
@@ -23,6 +21,8 @@
23
21
  "email": "alex@flancer64.com",
24
22
  "url": "https://github.com/flancer64"
25
23
  },
24
+ "main": "src/Shared/Container.mjs",
25
+ "type": "module",
26
26
  "repository": {
27
27
  "type": "git",
28
28
  "url": "git+https://github.com/teqfw/di.git"
@@ -9,7 +9,12 @@ const NS = 'TeqFw_Di_Back_Api_Dto_Plugin_Desc';
9
9
  export default class TeqFw_Di_Back_Api_Dto_Plugin_Desc {
10
10
  /** @type {TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Autoload} */
11
11
  autoload;
12
- /** @type {TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace[]} */
12
+ /**
13
+ * Replacements for IDs:
14
+ * - {'Interface_Name': 'Impl_Name'}: replace es6-module 'Interface_Name' with 'Impl_Name' on injection;
15
+ * - {'front': {'Interface_Name': 'Impl_Name'}}: do the same for 'front' area only (should be implemented outside this plugin)
16
+ * @type {Object<string, string>|Object<string, Object<string, string>>}
17
+ */
13
18
  replace;
14
19
  }
15
20
 
@@ -23,27 +28,37 @@ TeqFw_Di_Back_Api_Dto_Plugin_Desc.REPLACE = 'replace';
23
28
  */
24
29
  export class Factory {
25
30
  constructor(spec) {
26
- // EXTRACT DEPS
27
- /** @type {typeof TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Autoload} */
28
- const TAutoload = spec['TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Autoload#'];
29
31
  /** @type {TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Autoload.Factory} */
30
32
  const fAutoload = spec['TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Autoload#Factory$'];
31
- /** @type {typeof TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace} */
32
- const TReplace = spec['TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace#'];
33
- /** @type {TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace.Factory} */
34
- const fReplace = spec['TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace#Factory$'];
35
33
 
36
34
  /**
37
- * @param {TeqFw_Di_Back_Api_Dto_Plugin_Desc|null} data
35
+ * @param {*} data
38
36
  * @return {TeqFw_Di_Back_Api_Dto_Plugin_Desc}
39
37
  */
40
38
  this.create = function (data = null) {
39
+
40
+ // DEFINE INNER FUNCTIONS
41
+ function parseReplace(data) {
42
+ const res = {};
43
+ if (typeof data === 'object')
44
+ for (const ns of Object.keys(data)) {
45
+ const node = data[ns];
46
+ if (typeof node === 'string') {
47
+ res[ns] = data[ns]; // {"interface": "impl"}
48
+ } else if (typeof node === 'object') {
49
+ res[ns] = {}; // {"interface": {"area": "impl"}}
50
+ for (const area of Object.keys(node))
51
+ if (typeof node[area] === 'string')
52
+ res[ns][area] = node[area];
53
+ }
54
+ }
55
+ return res;
56
+ }
57
+
58
+ // MAIN FUNCTIONALITY
41
59
  const res = new TeqFw_Di_Back_Api_Dto_Plugin_Desc();
42
- res.autoload = (data?.autoload instanceof TAutoload)
43
- ? data.autoload : fAutoload.create(data?.autoload);
44
- res.replace = Array.isArray(data?.replace)
45
- ? data.replace.map((one) => (one instanceof TReplace) ? one : fReplace.create(one))
46
- : [];
60
+ res.autoload = fAutoload.create(data?.autoload);
61
+ res.replace = parseReplace(data?.replace);
47
62
  return res;
48
63
  }
49
64
  }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Interface for proxy factory to create objects using 'Vnd_Plugin_Single@' & 'Vnd_Plugin_Obj@@' dependency ID.
3
+ * @interface
4
+ */
5
+ export default class TeqFw_Di_Shared_Api_IProxy {
6
+ /**
7
+ * Get target object asynchronously.
8
+ * @return {Promise<*>}
9
+ */
10
+ get create() { }
11
+ }
@@ -50,11 +50,14 @@ export default class TeqFw_Di_Shared_Container {
50
50
  singletons.set('container', this); // as singleton
51
51
  singletons.set('TeqFw_Di_Shared_Container', this); // as singleton of the class
52
52
 
53
+ // pin itself for nested functions
54
+ const me = this;
55
+
53
56
  /**
54
57
  * Internal function to get/create object|function|class|module by given `id`.
55
58
  *
56
59
  * @param {string} mainId main object ID (singleton, module, new object, default export singleton)
57
- * @param {Object.<string, boolean>} uplineDeps dependencies registry to prevent circular loop.
60
+ * @param {string[]} uplineDeps dependencies registry to prevent circular loop.
58
61
  * @returns {Promise<*>}
59
62
  */
60
63
  async function getObject(mainId, uplineDeps) {
@@ -122,7 +125,7 @@ export default class TeqFw_Di_Shared_Container {
122
125
  // try to create object and start chain of deps resolving in SpecProxy
123
126
  fnCreate();
124
127
  } else {
125
- throw new Error('Unexpected type of loaded module.');
128
+ throw new Error(`Unexpected type of factory function for '${mainId}'.`);
126
129
  }
127
130
  // `resolve` for this promise is called from fnCreate
128
131
  // (fnCreate is recalled from spec proxy on every dep failure)
@@ -165,7 +168,7 @@ export default class TeqFw_Di_Shared_Container {
165
168
  const parsed = $parser.parse(mainId);
166
169
  parsed.nameModule = checkReplacements(parsed.nameModule);
167
170
  // try to find requested dependency in local storages
168
- result = await getFromStorages(parsed);
171
+ if (!parsed.isProxy) result = await getFromStorages(parsed);
169
172
  // if not found then try to load sources and create new one
170
173
  if (result === undefined) {
171
174
  // Sources for requested dependency are not imported or not set manually before.
@@ -181,13 +184,25 @@ export default class TeqFw_Di_Shared_Container {
181
184
  // result as ES6 module export
182
185
  result = module[parsed.nameExport];
183
186
  } else {
184
- // we need use module export as factory for new object or singleton for the first time
185
- const factory = module[parsed.nameExport];
186
- factories.set(parsed.mapKey, factory);
187
- const object = await _useFactory(factory);
188
- // save singleton object in container storage
189
- if (parsed.typeTarget === ParsedId.TYPE_TARGET_SINGLETON) singletons.set(parsed.mapKey, object);
190
- result = object;
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
+ }
191
206
  }
192
207
  }
193
208
  return result;
@@ -252,7 +267,7 @@ export default class TeqFw_Di_Shared_Container {
252
267
  * TODO: /bootstrap path, for example/).
253
268
  */
254
269
  this.get = async function (depId, context = null) {
255
- return await getObject(depId, {});
270
+ return await getObject(depId, []);
256
271
  };
257
272
 
258
273
  /**
@@ -30,6 +30,11 @@
30
30
  * Structure to store parsing results of identifiers for imports and injects.
31
31
  */
32
32
  export default class TeqFw_Di_Shared_IdParser_Dto {
33
+ /**
34
+ * 'true' if dependency should be a proxy.
35
+ * @type {boolean}
36
+ */
37
+ isProxy;
33
38
  /**
34
39
  * Key to map object in container's store (singletons, constructors, modules) - original id w/o '$' chars.
35
40
  * @type {string}
@@ -2,12 +2,28 @@
2
2
  import ParsedId from './IdParser/Dto.mjs';
3
3
 
4
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 = '#';
5
11
  /** @type {RegExp} expression for filepath based IDs (@vendor/package!module#export$$) */
6
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 = '$$';
7
17
  /** @type {RegExp} expression for logical namespace IDs (Ns_Module#export$$) */
8
- const LOGICAL_NS_ID = /^((([A-Z])[A-Za-z0-9_]*)(#?([A-Za-z0-9_]*)(\${1,2})?)?)$/;
18
+ const LOGICAL_NS_ID = /^((([A-Z])[A-Za-z0-9_]*)((#|.)?([A-Za-z0-9_]*)(\${1,2}|@{1,2})?)?)$/;
9
19
  /** @type {RegExp} expression for objects that manually added to DI container (singleton, namedFactory$$) */
10
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 = '$';
11
27
 
12
28
  // MODULE'S CLASSES
13
29
  /**
@@ -49,8 +65,8 @@ export default class TeqFw_Di_Shared_IdParser {
49
65
  result.nameModule = parts[6];
50
66
  result.mapKey = parts[1];
51
67
  result.typeTarget = ParsedId.TYPE_TARGET_MODULE;
52
- if (parts[8] === '#') {
53
- result.nameExport = 'default';
68
+ if (parts[8] === EXP_OLD) {
69
+ result.nameExport = DEF_EXP;
54
70
  result.typeTarget = ParsedId.TYPE_TARGET_EXPORT;
55
71
  result.mapKey = undefined;
56
72
  }
@@ -60,16 +76,16 @@ export default class TeqFw_Di_Shared_IdParser {
60
76
  result.mapKey = undefined;
61
77
  }
62
78
  if (parts[10]) {
63
- if (parts[10] === '$$') {
79
+ if (parts[10] === INST) {
64
80
  result.typeTarget = ParsedId.TYPE_TARGET_FACTORY;
65
- } else if (parts[10] === '$') {
81
+ } else if (parts[10] === SNGLT) {
66
82
  result.typeTarget = ParsedId.TYPE_TARGET_SINGLETON;
67
83
  }
68
84
  if (result.nameExport === undefined) {
69
- result.nameExport = 'default';
70
- result.mapKey = result.namePackage + '!' + result.nameModule;
85
+ result.nameExport = DEF_EXP;
86
+ result.mapKey = result.namePackage + FSM + result.nameModule;
71
87
  } else {
72
- result.mapKey = result.namePackage + '!' + result.nameModule + '#' + result.nameExport;
88
+ result.mapKey = result.namePackage + FSM + result.nameModule + EXP_OLD + result.nameExport;
73
89
  }
74
90
  }
75
91
  }
@@ -90,31 +106,59 @@ export default class TeqFw_Di_Shared_IdParser {
90
106
  result.orig = id;
91
107
  result.typeId = ParsedId.TYPE_ID_LOGICAL;
92
108
  result.nameModule = parts[2];
93
- result.mapKey = result.nameModule;
109
+ result.isProxy = false;
110
+ result.mapKey = result.nameModule; // init mapKey with module's name
94
111
  result.typeTarget = ParsedId.TYPE_TARGET_MODULE;
95
- if (parts[4] === '#') {
96
- result.nameExport = 'default';
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];
97
138
  result.typeTarget = ParsedId.TYPE_TARGET_EXPORT;
98
139
  result.mapKey = undefined;
99
140
  }
100
- if (parts[5]) {
101
- result.nameExport = parts[5];
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;
102
159
  result.typeTarget = ParsedId.TYPE_TARGET_EXPORT;
103
160
  result.mapKey = undefined;
104
161
  }
105
- if (parts[6]) {
106
- if (parts[6] === '$$') {
107
- result.typeTarget = ParsedId.TYPE_TARGET_FACTORY;
108
- } else if (parts[6] === '$') {
109
- result.typeTarget = ParsedId.TYPE_TARGET_SINGLETON;
110
- }
111
- if (result.nameExport === undefined) {
112
- result.nameExport = 'default';
113
- result.mapKey = result.nameModule;
114
- } else {
115
- result.mapKey = result.nameModule + '#' + result.nameExport;
116
- }
117
- }
118
162
  }
119
163
  return result;
120
164
  }
@@ -18,7 +18,7 @@ const $parser = new IdParser();
18
18
  export default class TeqFw_Di_Shared_SpecProxy {
19
19
  /**
20
20
  * @param {string} mainId ID of the constructing object ('Vendor_Module$', 'Vendor_Module$$', 'dbCfg').
21
- * @param {Object.<string, Boolean>} uplineDeps All incomplete dependencies in current construction process
21
+ * @param {string[]} uplineDeps All incomplete dependencies in current construction process
22
22
  * (to prevent circular dependencies).
23
23
  * @param {Map} containerSingletons Container level registry with created singletons (ids: 'dbCfg', 'Module$$').
24
24
  * @param {Function} fnCreate constructing process level registry to save functions that
@@ -73,14 +73,14 @@ export default class TeqFw_Di_Shared_SpecProxy {
73
73
  } else {
74
74
  // check stack of incomplete dependencies
75
75
  if (parsed.nameModule) { // don't process manually inserted singletons
76
- if (uplineDeps[parsed.nameModule]) {
76
+ if (uplineDeps.includes(parsed.nameModule)) {
77
77
  // `dep_id` is already requested to be created, so we report it as 'main'
78
78
  const err = new Error(`Circular dependencies (main: ${depId}; dep: ${mainId})`);
79
79
  fnRejectUseFactory(err); // reject async _useFactory
80
80
  throw err; // break sync object's constructor
81
81
  }
82
82
  // ... and register new one
83
- uplineDeps[parsed.nameModule] = true;
83
+ uplineDeps.push(parsed.nameModule);
84
84
  }
85
85
  // create new required dependency for this object
86
86
  fnGetObject(depId, uplineDeps).then((obj) => {
@@ -88,7 +88,7 @@ export default class TeqFw_Di_Shared_SpecProxy {
88
88
  // save created `dep_id` instance to local dependencies registry
89
89
  deps[depId] = obj;
90
90
  // remove created dependency from circular registry
91
- uplineDeps[parsed.nameModule] = false;
91
+ uplineDeps.splice(uplineDeps.indexOf(parsed.nameModule), 1);
92
92
  // re-call main object construction function
93
93
  fnCreate();
94
94
  }).catch(err => {
@@ -1,63 +0,0 @@
1
- /**
2
- * DTO to represent plugin descriptor (teqfw.json) structure
3
- * that is related to 'di/replace' node:
4
- */
5
- // MODULE'S VARS
6
- const NS = 'TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace';
7
-
8
- // MODULE'S CLASSES
9
- export default class TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace {
10
- /**
11
- * Logical name for ES6 module with replacement code (Vnd_Plug_Implementation).
12
- * @type {string}
13
- */
14
- alter;
15
- /**
16
- * App area to use replacement ('back', 'front', 'shared').
17
- * @type {string}
18
- */
19
- area;
20
- /**
21
- * Logical name for original ES6 module (Vnd_Plug_Interface).
22
- * @type {string}
23
- */
24
- orig;
25
- }
26
-
27
- // attributes names to use as aliases in queries to object props
28
- TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace.ALTER = 'alter';
29
- TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace.AREA = 'area';
30
- TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace.ORIG = 'orig';
31
-
32
- TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace.DATA_AREA_BACK = 'back';
33
- TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace.DATA_AREA_FRONT = 'front';
34
- TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace.DATA_AREA_SHARED = 'shared';
35
-
36
- /**
37
- * Factory to create new DTO instances.
38
- * @memberOf TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace
39
- */
40
- export class Factory {
41
- constructor() {
42
- /**
43
- * @param {TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace|null} data
44
- * @return {TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace}
45
- */
46
- this.create = function (data = null) {
47
- const res = new TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace();
48
- const clazz = TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace;
49
- res.alter = data?.alter;
50
- res.area = (
51
- (data?.area === clazz.DATA_AREA_BACK) ||
52
- (data?.area === clazz.DATA_AREA_FRONT)
53
- )
54
- ? data.area : clazz.DATA_AREA_SHARED;
55
- res.orig = data?.orig;
56
- return res;
57
- }
58
- }
59
- }
60
-
61
- // freeze DTO class to deny attributes changes and pin namespace
62
- Object.freeze(TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace);
63
- Object.defineProperty(Factory, 'name', {value: `${NS}.${Factory.constructor.name}`});