@teqfw/di 0.10.0 → 0.12.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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @teqfw/di releases
2
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
+
3
9
  ## 0.10.0
4
10
 
5
11
  * Improve error messaging.
@@ -4,6 +4,7 @@
4
4
  ##
5
5
  DIR_ROOT=${DIR_ROOT:-$(cd "$(dirname "$0")/../../" && pwd)}
6
6
 
7
+ rm -fr "${DIR_ROOT}/doc/"
7
8
  rm -fr "${DIR_ROOT}/node_modules/"
8
9
  rm -fr "${DIR_ROOT}/package-lock.json"
9
10
  rm -fr "${DIR_ROOT}/test/"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teqfw/di",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "description": "Dependency Injection container based on logical namespaces for ES6 modules.",
5
5
  "keywords": [
6
6
  "dependency injection",
@@ -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 {Object<string, 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
 
@@ -22,28 +27,37 @@ TeqFw_Di_Back_Api_Dto_Plugin_Desc.REPLACE = 'replace';
22
27
  * @memberOf TeqFw_Di_Back_Api_Dto_Plugin_Desc
23
28
  */
24
29
  export class Factory {
30
+ static namespace = NS;
31
+
25
32
  constructor(spec) {
26
33
  /** @type {TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Autoload.Factory} */
27
- const fAutoload = spec['TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Autoload#Factory$'];
28
- /** @type {TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace.Factory} */
29
- const fReplace = spec['TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace#Factory$'];
34
+ const fAutoload = spec['TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Autoload.Factory$'];
30
35
 
31
36
  /**
32
- * @param {TeqFw_Di_Back_Api_Dto_Plugin_Desc|null} data
37
+ * @param {*} data
33
38
  * @return {TeqFw_Di_Back_Api_Dto_Plugin_Desc}
34
39
  */
35
40
  this.create = function (data = null) {
36
41
 
37
- // DEFINE INNER FUNCTIONS
42
+ // FUNCS
38
43
  function parseReplace(data) {
39
44
  const res = {};
40
45
  if (typeof data === 'object')
41
- for (const ns of Object.keys(data))
42
- res[ns] = fReplace.create(data[ns]);
46
+ for (const ns of Object.keys(data)) {
47
+ const node = data[ns];
48
+ if (typeof node === 'string') {
49
+ res[ns] = data[ns]; // {"interface": "impl"}
50
+ } else if (typeof node === 'object') {
51
+ res[ns] = {}; // {"interface": {"area": "impl"}}
52
+ for (const area of Object.keys(node))
53
+ if (typeof node[area] === 'string')
54
+ res[ns][area] = node[area];
55
+ }
56
+ }
43
57
  return res;
44
58
  }
45
59
 
46
- // MAIN FUNCTIONALITY
60
+ // MAIN
47
61
  const res = new TeqFw_Di_Back_Api_Dto_Plugin_Desc();
48
62
  res.autoload = fAutoload.create(data?.autoload);
49
63
  res.replace = parseReplace(data?.replace);
@@ -54,4 +68,3 @@ export class Factory {
54
68
 
55
69
  // freeze DTO class to deny attributes changes and pin namespace
56
70
  Object.freeze(TeqFw_Di_Back_Api_Dto_Plugin_Desc);
57
- Object.defineProperty(Factory, 'name', {value: `${NS}.${Factory.constructor.name}`});
@@ -15,15 +15,15 @@ const TEQFW = 'teqfw.json';
15
15
  export default class TeqFw_Di_Back_Plugin_Scanner {
16
16
 
17
17
  constructor(spec) {
18
- // EXTRACT DEPS
18
+ // DEPS
19
19
  /** @type {TeqFw_Di_Back_Defaults} */
20
20
  const DEF = spec['TeqFw_Di_Back_Defaults$'];
21
21
  /** @type {TeqFw_Di_Back_Api_Dto_Plugin_Desc.Factory} */
22
- const fDesc = spec['TeqFw_Di_Back_Api_Dto_Plugin_Desc#Factory$'];
22
+ const fDesc = spec['TeqFw_Di_Back_Api_Dto_Plugin_Desc.Factory$'];
23
23
  /** @type {TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Autoload.Factory} */
24
- const fAutoload = spec['TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Autoload#Factory$'];
24
+ const fAutoload = spec['TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Autoload.Factory$'];
25
25
 
26
- // DEFINE INSTANCE METHODS
26
+ // INSTANCE METHODS
27
27
 
28
28
  this.getDescriptors = async function (path) {
29
29
  const result = [];
@@ -75,9 +75,9 @@ export default class TeqFw_Di_Back_Plugin_Scanner {
75
75
  * @return {Promise<Object.<string, TeqFw_Di_Back_Api_Dto_Scanned>>} Object-to-path map for found plugins
76
76
  */
77
77
  async scanFilesystem(path) {
78
- // DEFINE INNER FUNCTIONS
78
+ // FUNCS
79
79
  function readData(path) {
80
- // DEFINE INNER FUNCTIONS
80
+ // FUNCS
81
81
  /**
82
82
  * Check existence of JSON file, read content, parse JSON and return data.
83
83
  *
@@ -106,7 +106,7 @@ export default class TeqFw_Di_Back_Plugin_Scanner {
106
106
  return result;
107
107
  }
108
108
 
109
- // MAIN FUNCTIONALITY
109
+ // MAIN
110
110
  let result = null;
111
111
  const pathTeqfw = join(path, TEQFW);
112
112
  const pathPkg = join(path, PACKAGE);
@@ -121,7 +121,7 @@ export default class TeqFw_Di_Back_Plugin_Scanner {
121
121
  return result;
122
122
  }
123
123
 
124
- // MAIN FUNCTIONALITY
124
+ // MAIN
125
125
  const result = {};
126
126
  // get scan data for root folder (application itself)
127
127
  const dataRoot = readData(path);
@@ -28,6 +28,8 @@ TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Autoload.PATH = 'path';
28
28
  * @memberOf TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Autoload
29
29
  */
30
30
  export class Factory {
31
+ static namespace = NS;
32
+
31
33
  constructor() {
32
34
  /**
33
35
  * @param {TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Autoload|null} data
@@ -46,4 +48,3 @@ export class Factory {
46
48
 
47
49
  // freeze DTO class to deny attributes changes and pin namespace
48
50
  Object.freeze(TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Autoload);
49
- Object.defineProperty(Factory, 'name', {value: `${NS}.${Factory.constructor.name}`});
@@ -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
+ }
@@ -62,7 +62,7 @@ export default class TeqFw_Di_Shared_Container {
62
62
  */
63
63
  async function getObject(mainId, uplineDeps) {
64
64
 
65
- // DEFINE INNER FUNCTIONS
65
+ // FUNCS
66
66
  /**
67
67
  * Add 'spec' proxy as fnConstruct argument and create new object and all deps.
68
68
  *
@@ -73,7 +73,7 @@ export default class TeqFw_Di_Shared_Container {
73
73
  function _useFactory(fnConstruct) {
74
74
  // This promise will be resolved after all dependencies in spec proxy will be created.
75
75
  return new Promise(function (resolve, reject) {
76
- // MAIN FUNCTIONALITY
76
+ // MAIN
77
77
  const constructorType = typeof fnConstruct;
78
78
  if (constructorType === 'object') {
79
79
  // `constructor` is an object, clone this fnConstruct and return cloned object
@@ -162,7 +162,7 @@ export default class TeqFw_Di_Shared_Container {
162
162
  return orig;
163
163
  }
164
164
 
165
- // MAIN FUNCTIONALITY
165
+ // MAIN
166
166
  let result;
167
167
  /** @type {TeqFw_Di_Shared_IdParser_Dto} */
168
168
  const parsed = $parser.parse(mainId);
@@ -1,50 +0,0 @@
1
- /**
2
- * DTO to represent plugin descriptor (teqfw.json) structure
3
- * that is related to 'di/replace' node:
4
- */
5
- // MODULE'S IMPORT
6
- import AREA from '../../../Enum/Area.mjs';
7
- // MODULE'S VARS
8
- const NS = 'TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace';
9
-
10
- // MODULE'S CLASSES
11
- export default class TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace {
12
- /**
13
- * App area to use replacement ('back', 'front', 'shared').
14
- * @type {string}
15
- */
16
- area;
17
- /**
18
- * Logical name for ES6 module with replacement code (Vnd_Plug_Implementation).
19
- * @type {string}
20
- */
21
- ns;
22
- }
23
-
24
- // attributes names to use as aliases in queries to object props
25
- TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace.AREA = 'area';
26
- TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace.NS = 'ns';
27
-
28
- /**
29
- * Factory to create new DTO instances.
30
- * @memberOf TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace
31
- */
32
- export class Factory {
33
- constructor() {
34
- /**
35
- * @param {TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace|null} data
36
- * @return {TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace}
37
- */
38
- this.create = function (data = null) {
39
- const res = new TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace();
40
- res.ns = data?.ns;
41
- res.area = ((data?.area === AREA.BACK) || (data?.area === AREA.FRONT))
42
- ? data.area : AREA.SHARED;
43
- return res;
44
- }
45
- }
46
- }
47
-
48
- // freeze DTO class to deny attributes changes and pin namespace
49
- Object.freeze(TeqFw_Di_Shared_Api_Dto_Plugin_Desc_Replace);
50
- Object.defineProperty(Factory, 'name', {value: `${NS}.${Factory.constructor.name}`});
@@ -1,10 +0,0 @@
1
- /**
2
- * Enumeration for application areas.
3
- */
4
- const TeqFw_Di_Shared_Api_Enum_Area = {
5
- BACK: 'back', // nodejs compatible 'import' is allowed
6
- FRONT: 'front', // browser compatible 'import' is allowed
7
- SHARED: 'shared', // relative 'import' only is allowed
8
- }
9
- Object.freeze(TeqFw_Di_Shared_Api_Enum_Area);
10
- export default TeqFw_Di_Shared_Api_Enum_Area;
@@ -1,11 +0,0 @@
1
- /**
2
- * Interface for factory to create objects.
3
- * @interface
4
- */
5
- export default class TeqFw_Di_Shared_Api_IFactory {
6
- /**
7
- * @param opts
8
- * @return {*}
9
- */
10
- async create(opts = null) {}
11
- }