@spinajs/reflection 1.0.4 → 1.2.7
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/lib/index.d.ts +49 -3
- package/lib/index.js +78 -28
- package/lib/index.js.map +1 -1
- package/package.json +15 -30
- package/test/reflection.test.ts +0 -195
- package/test/test-services/alwaysnew/FooService.ts +0 -11
- package/test/test-services/async/FooService.ts +0 -12
- package/test/test-services/async/FooService2.ts +0 -9
- package/test/test-services/mixed/FooService.ts +0 -4
- package/test/test-services/mixed/FooService2.ts +0 -9
- package/test/test-services/singletons/FooService.ts +0 -7
- package/test/test-services/singletons/FooService2.ts +0 -4
- package/test/test-services/throw/FooService.ts +0 -3
- package/test/test-services/throw/FooService2.ts +0 -4
- package/test/test-services/throwasync/FooService.ts +0 -9
- package/test/test-services/throwasync/FooService2.ts +0 -9
- package/typedoc.json +0 -16
- package/yarn-error.log +0 -1924
package/lib/index.d.ts
CHANGED
|
@@ -1,17 +1,63 @@
|
|
|
1
|
-
import * as ts from
|
|
1
|
+
import * as ts from 'typescript';
|
|
2
|
+
import { Exception } from '@spinajs/exceptions';
|
|
3
|
+
/**
|
|
4
|
+
* Class info structure
|
|
5
|
+
*/
|
|
2
6
|
export declare class ClassInfo<T> {
|
|
7
|
+
/**
|
|
8
|
+
* Full file path of loaded class
|
|
9
|
+
*/
|
|
3
10
|
file: string;
|
|
11
|
+
/**
|
|
12
|
+
* Class name
|
|
13
|
+
*/
|
|
4
14
|
name: string;
|
|
15
|
+
/**
|
|
16
|
+
* Javascript class object
|
|
17
|
+
*/
|
|
5
18
|
type: any;
|
|
19
|
+
/**
|
|
20
|
+
* Resolved instance
|
|
21
|
+
*/
|
|
6
22
|
instance?: T;
|
|
7
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Exception thrown when some error during reflection occurs
|
|
26
|
+
*/
|
|
27
|
+
export declare class ReflectionException extends Exception {
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Helper class for extracting various information from typescript source code
|
|
31
|
+
*/
|
|
8
32
|
export declare class TypescriptCompiler {
|
|
9
33
|
private tsFile;
|
|
10
34
|
private compiled;
|
|
11
35
|
constructor(filename: string);
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
* Extracts all members info from typescript class eg. method name, parameters, return types etc.
|
|
39
|
+
*
|
|
40
|
+
* @param className - name of class to parse
|
|
41
|
+
*/
|
|
12
42
|
getClassMembers(className: string): Map<string, ts.MethodDeclaration>;
|
|
13
43
|
private walkClassNode;
|
|
14
44
|
private walkMemberNode;
|
|
15
45
|
}
|
|
16
|
-
|
|
17
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Returns resolved instances of classes from specified files.
|
|
48
|
+
* It automatically checks if should resolve promise or not, calls resolve strategy, checks if should return new or signleton etc, resolves
|
|
49
|
+
* dependencies etc.
|
|
50
|
+
*
|
|
51
|
+
* @param filter - files to look at, uses glob pattern to search
|
|
52
|
+
* @param configPath - dir paths taken from app config eg. "system.dirs.controllers". Path MUST be avaible in configuration
|
|
53
|
+
*
|
|
54
|
+
*/
|
|
55
|
+
export declare function ResolveFromFiles(filter: string, configPath: string, typeMatcher?: (fileName: string) => string): (target: any, propertyKey: string | symbol) => void;
|
|
56
|
+
/**
|
|
57
|
+
* Returns list of class types found in specified path. It do not resolve / create instances
|
|
58
|
+
*
|
|
59
|
+
* @param filter - files to look at, uses glob pattern to search
|
|
60
|
+
* @param configPath - dir paths taken from app config eg. "system.dirs.controllers". Path MUST be avaible in configuration
|
|
61
|
+
*
|
|
62
|
+
*/
|
|
63
|
+
export declare function ListFromFiles(filter: string, configPath: string, typeMatcher?: (fileName: string) => string): (target: any, propertyKey: string | symbol) => void;
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ListFromFiles = exports.ResolveFromFiles = exports.TypescriptCompiler = exports.ReflectionException = exports.ClassInfo = void 0;
|
|
3
4
|
const fs = require("fs");
|
|
4
5
|
const glob = require("glob");
|
|
5
6
|
const path = require("path");
|
|
@@ -7,26 +8,43 @@ const ts = require("typescript");
|
|
|
7
8
|
const configuration_1 = require("@spinajs/configuration");
|
|
8
9
|
const di_1 = require("@spinajs/di");
|
|
9
10
|
const exceptions_1 = require("@spinajs/exceptions");
|
|
11
|
+
const log_1 = require("@spinajs/log");
|
|
12
|
+
/**
|
|
13
|
+
* Class info structure
|
|
14
|
+
*/
|
|
10
15
|
class ClassInfo {
|
|
11
16
|
}
|
|
12
17
|
exports.ClassInfo = ClassInfo;
|
|
18
|
+
/**
|
|
19
|
+
* Exception thrown when some error during reflection occurs
|
|
20
|
+
*/
|
|
21
|
+
class ReflectionException extends exceptions_1.Exception {
|
|
22
|
+
}
|
|
23
|
+
exports.ReflectionException = ReflectionException;
|
|
24
|
+
/**
|
|
25
|
+
* Helper class for extracting various information from typescript source code
|
|
26
|
+
*/
|
|
13
27
|
class TypescriptCompiler {
|
|
14
28
|
constructor(filename) {
|
|
15
29
|
this.tsFile = filename;
|
|
16
30
|
this.compiled = ts.createProgram([this.tsFile], {
|
|
17
31
|
module: ts.ModuleKind.CommonJS,
|
|
18
|
-
target: ts.ScriptTarget.Latest
|
|
32
|
+
target: ts.ScriptTarget.Latest,
|
|
19
33
|
});
|
|
20
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
*
|
|
37
|
+
* Extracts all members info from typescript class eg. method name, parameters, return types etc.
|
|
38
|
+
*
|
|
39
|
+
* @param className - name of class to parse
|
|
40
|
+
*/
|
|
21
41
|
getClassMembers(className) {
|
|
22
42
|
const members = new Map();
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
}
|
|
43
|
+
const sourceFile = this.compiled.getSourceFile(this.tsFile);
|
|
44
|
+
// Walk the tree to search for classes
|
|
45
|
+
ts.forEachChild(sourceFile, this.walkClassNode(className, this.walkMemberNode((method) => {
|
|
46
|
+
members.set(method.name.getText(), method);
|
|
47
|
+
})));
|
|
30
48
|
return members;
|
|
31
49
|
}
|
|
32
50
|
walkClassNode(className, callback) {
|
|
@@ -41,29 +59,47 @@ class TypescriptCompiler {
|
|
|
41
59
|
}
|
|
42
60
|
walkMemberNode(callback) {
|
|
43
61
|
return (node) => {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
62
|
+
for (const member of node.members) {
|
|
63
|
+
if (member.kind === ts.SyntaxKind.MethodDeclaration) {
|
|
64
|
+
const method = member;
|
|
65
|
+
callback(method);
|
|
66
|
+
}
|
|
47
67
|
}
|
|
48
68
|
};
|
|
49
69
|
}
|
|
50
70
|
}
|
|
51
71
|
exports.TypescriptCompiler = TypescriptCompiler;
|
|
52
|
-
|
|
53
|
-
|
|
72
|
+
/**
|
|
73
|
+
* Returns resolved instances of classes from specified files.
|
|
74
|
+
* It automatically checks if should resolve promise or not, calls resolve strategy, checks if should return new or signleton etc, resolves
|
|
75
|
+
* dependencies etc.
|
|
76
|
+
*
|
|
77
|
+
* @param filter - files to look at, uses glob pattern to search
|
|
78
|
+
* @param configPath - dir paths taken from app config eg. "system.dirs.controllers". Path MUST be avaible in configuration
|
|
79
|
+
*
|
|
80
|
+
*/
|
|
81
|
+
function ResolveFromFiles(filter, configPath, typeMatcher) {
|
|
82
|
+
return _listOrResolveFromFiles(filter, configPath, true, typeMatcher);
|
|
54
83
|
}
|
|
55
84
|
exports.ResolveFromFiles = ResolveFromFiles;
|
|
56
|
-
|
|
57
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Returns list of class types found in specified path. It do not resolve / create instances
|
|
87
|
+
*
|
|
88
|
+
* @param filter - files to look at, uses glob pattern to search
|
|
89
|
+
* @param configPath - dir paths taken from app config eg. "system.dirs.controllers". Path MUST be avaible in configuration
|
|
90
|
+
*
|
|
91
|
+
*/
|
|
92
|
+
function ListFromFiles(filter, configPath, typeMatcher) {
|
|
93
|
+
return _listOrResolveFromFiles(filter, configPath, false, typeMatcher);
|
|
58
94
|
}
|
|
59
95
|
exports.ListFromFiles = ListFromFiles;
|
|
60
|
-
function _listOrResolveFromFiles(filter, configPath, resolve) {
|
|
96
|
+
function _listOrResolveFromFiles(filter, configPath, resolve, typeMatcher) {
|
|
61
97
|
return (target, propertyKey) => {
|
|
62
98
|
if (!filter) {
|
|
63
|
-
throw new exceptions_1.
|
|
99
|
+
throw new exceptions_1.InvalidArgument('filter parameter is null or empty');
|
|
64
100
|
}
|
|
65
101
|
if (!configPath) {
|
|
66
|
-
throw new exceptions_1.
|
|
102
|
+
throw new exceptions_1.InvalidArgument('configPath parameter is null or empty');
|
|
67
103
|
}
|
|
68
104
|
let instances = null;
|
|
69
105
|
const getter = () => {
|
|
@@ -77,29 +113,43 @@ function _listOrResolveFromFiles(filter, configPath, resolve) {
|
|
|
77
113
|
get: getter,
|
|
78
114
|
});
|
|
79
115
|
function _loadInstances() {
|
|
80
|
-
const config = di_1.DI.
|
|
81
|
-
const
|
|
116
|
+
const config = di_1.DI.get(configuration_1.Configuration);
|
|
117
|
+
const logger = di_1.DI.resolve(log_1.Log, ['reflection']);
|
|
118
|
+
let directories = config.get(configPath);
|
|
82
119
|
if (!directories || directories.length === 0) {
|
|
83
120
|
return [];
|
|
84
121
|
}
|
|
122
|
+
if (!Array.isArray(directories)) {
|
|
123
|
+
directories = [directories];
|
|
124
|
+
}
|
|
85
125
|
let promised = false;
|
|
86
|
-
const result = directories
|
|
87
|
-
.filter((d) =>
|
|
126
|
+
const result = directories
|
|
127
|
+
.filter((d) => {
|
|
128
|
+
/* eslint-disable */
|
|
129
|
+
const exists = fs.existsSync(path.normalize(d));
|
|
130
|
+
if (!exists) {
|
|
131
|
+
logger.warn(`Directory ${d} not exists`);
|
|
132
|
+
}
|
|
133
|
+
return exists;
|
|
134
|
+
})
|
|
88
135
|
.flatMap((d) => glob.sync(path.join(d, filter)))
|
|
89
136
|
.map((f) => {
|
|
137
|
+
logger.trace(`Loading file ${f}`);
|
|
90
138
|
const name = path.parse(f).name;
|
|
91
|
-
const
|
|
139
|
+
const nameToResolve = typeMatcher ? typeMatcher(name) : name;
|
|
140
|
+
/* eslint-disable */
|
|
141
|
+
const type = require(f)[`${nameToResolve}`];
|
|
92
142
|
if (!type) {
|
|
93
|
-
throw new
|
|
143
|
+
throw new ReflectionException(`cannot find class ${nameToResolve} in file ${f}`);
|
|
94
144
|
}
|
|
95
145
|
if (resolve) {
|
|
96
|
-
if (type.prototype instanceof di_1.
|
|
146
|
+
if (type.prototype instanceof di_1.AsyncModule) {
|
|
97
147
|
promised = true;
|
|
98
148
|
return di_1.DI.resolve(type).then((instance) => {
|
|
99
149
|
return {
|
|
100
150
|
file: f,
|
|
101
151
|
instance,
|
|
102
|
-
name,
|
|
152
|
+
name: nameToResolve,
|
|
103
153
|
type,
|
|
104
154
|
};
|
|
105
155
|
});
|
|
@@ -108,11 +158,11 @@ function _listOrResolveFromFiles(filter, configPath, resolve) {
|
|
|
108
158
|
return {
|
|
109
159
|
file: f,
|
|
110
160
|
instance: resolve ? di_1.DI.resolve(type) : null,
|
|
111
|
-
name,
|
|
161
|
+
name: nameToResolve,
|
|
112
162
|
type,
|
|
113
163
|
};
|
|
114
164
|
});
|
|
115
|
-
return
|
|
165
|
+
return promised && resolve ? Promise.all(result) : result;
|
|
116
166
|
}
|
|
117
167
|
};
|
|
118
168
|
}
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spinajs/reflection",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.7",
|
|
4
4
|
"description": "SpinaJS reflection helpers",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"private": false,
|
|
@@ -8,15 +8,20 @@
|
|
|
8
8
|
"test": "ts-mocha -p tsconfig.json test/**/*.test.ts",
|
|
9
9
|
"coverage": "nyc npm run test",
|
|
10
10
|
"build-docs": "rimraf docs && typedoc --options typedoc.json src/",
|
|
11
|
-
"build": "
|
|
11
|
+
"build": "npm run clean && npm run compile",
|
|
12
|
+
"compile": "tsc -p tsconfig.build.json",
|
|
13
|
+
"clean": "",
|
|
12
14
|
"prepare": "npm run build",
|
|
13
|
-
"format": "prettier --write \"src/**/*.ts\"
|
|
14
|
-
"lint": "
|
|
15
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
16
|
+
"lint": "eslint -c .eslintrc.js --ext .ts src",
|
|
15
17
|
"prepublishOnly": "npm test && npm run lint",
|
|
16
18
|
"preversion": "npm run lint",
|
|
17
19
|
"version": "npm run format && git add -A src",
|
|
18
20
|
"postversion": "git push && git push --tags"
|
|
19
21
|
},
|
|
22
|
+
"files": [
|
|
23
|
+
"lib/**/*"
|
|
24
|
+
],
|
|
20
25
|
"author": "SpinaJS <spinajs@coderush.pl> (https://github.com/spinajs/core)",
|
|
21
26
|
"license": "MIT",
|
|
22
27
|
"bugs": {
|
|
@@ -24,31 +29,11 @@
|
|
|
24
29
|
},
|
|
25
30
|
"homepage": "https://github.com/spinajs/reflection#readme",
|
|
26
31
|
"dependencies": {
|
|
27
|
-
"@spinajs/configuration": "^1.
|
|
28
|
-
"@spinajs/di": "^1.
|
|
29
|
-
"@spinajs/exceptions": "^1.
|
|
30
|
-
"@
|
|
32
|
+
"@spinajs/configuration": "^1.2.7",
|
|
33
|
+
"@spinajs/di": "^1.2.7",
|
|
34
|
+
"@spinajs/exceptions": "^1.2.7",
|
|
35
|
+
"@spinajs/log": "^1.2.7",
|
|
36
|
+
"lodash": "^4.17.21"
|
|
31
37
|
},
|
|
32
|
-
"
|
|
33
|
-
"@types/bunyan": "^1.8.6",
|
|
34
|
-
"@types/chai": "^4.1.7",
|
|
35
|
-
"@types/chai-as-promised": "^7.1.0",
|
|
36
|
-
"@types/chai-subset": "^1.3.3",
|
|
37
|
-
"@types/lodash": "^4.14.136",
|
|
38
|
-
"chai": "^4.2.0",
|
|
39
|
-
"chai-as-promised": "^7.1.1",
|
|
40
|
-
"chai-subset": "^1.6.0",
|
|
41
|
-
"mocha": "^6.1.4",
|
|
42
|
-
"nyc": "^14.1.1",
|
|
43
|
-
"prettier": "^1.18.2",
|
|
44
|
-
"ts-mocha": "^6.0.0",
|
|
45
|
-
"ts-node": "^8.3.0",
|
|
46
|
-
"tslint": "^5.20.1",
|
|
47
|
-
"tslint-circular-dependencies": "^0.1.0",
|
|
48
|
-
"tslint-config-prettier": "^1.18.0",
|
|
49
|
-
"tslint-config-standard": "^8.0.1",
|
|
50
|
-
"tslint-no-unused-expression-chai": "^0.1.4",
|
|
51
|
-
"typedoc": "^0.14.2",
|
|
52
|
-
"typescript": "^3.5.3"
|
|
53
|
-
}
|
|
38
|
+
"gitHead": "389cf142b4ca63b7850b93fc858184ddcbb43ce1"
|
|
54
39
|
}
|
package/test/reflection.test.ts
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
import { Configuration } from '@spinajs/configuration';
|
|
2
|
-
import { DI } from '@spinajs/di';
|
|
3
|
-
import * as chai from 'chai';
|
|
4
|
-
import * as chaiAsPromised from 'chai-as-promised';
|
|
5
|
-
import * as chaiSubset from 'chai-subset';
|
|
6
|
-
import _ = require('lodash');
|
|
7
|
-
import 'mocha';
|
|
8
|
-
import { join, normalize, resolve } from 'path';
|
|
9
|
-
import { ResolveFromFiles, ListFromFiles } from '../src';
|
|
10
|
-
import { FooService } from './test-services/singletons/FooService';
|
|
11
|
-
import { IOException } from '@spinajs/exceptions';
|
|
12
|
-
|
|
13
|
-
export function dir(path: string) {
|
|
14
|
-
return resolve(normalize(join(__dirname, path)));
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const expect = chai.expect;
|
|
18
|
-
chai.use(chaiAsPromised);
|
|
19
|
-
chai.use(chaiSubset);
|
|
20
|
-
|
|
21
|
-
export class MockCfg extends Configuration {
|
|
22
|
-
|
|
23
|
-
private conf = {
|
|
24
|
-
system: {
|
|
25
|
-
dirs: {
|
|
26
|
-
singletons: [dir("./test-services/singletons")],
|
|
27
|
-
alwaysnew: [dir("./test-services/alwaysnew")],
|
|
28
|
-
async: [dir("./test-services/async")],
|
|
29
|
-
throw: [dir("./test-services/throw")],
|
|
30
|
-
mixed: [dir("./test-services/mixed")],
|
|
31
|
-
throwasync: [dir("./test-services/throwasync")],
|
|
32
|
-
empty: [dir("./test-services/empty")]
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
public get(path: string[], defaultValue?: any): any {
|
|
39
|
-
return _.get(this.conf, path, defaultValue);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
describe("Reflection tests", () => {
|
|
44
|
-
beforeEach(() => {
|
|
45
|
-
DI.clear();
|
|
46
|
-
DI.register(MockCfg).as(Configuration);
|
|
47
|
-
|
|
48
|
-
FooService.Counter = 0;
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it("Should load services", () => {
|
|
52
|
-
const target = {
|
|
53
|
-
services: [] as any[]
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
ResolveFromFiles("/**/*.{ts,js}", "system.dirs.singletons")(target, "services");
|
|
57
|
-
|
|
58
|
-
expect(target.services).to.be.not.null;
|
|
59
|
-
expect(target.services).to.be.an("array").that.have.length(2);
|
|
60
|
-
expect(target.services[0]).to.include({
|
|
61
|
-
name: "FooService"
|
|
62
|
-
}).and.to.have.property("instance").not.null;
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
it("Should load services as singletons default", () => {
|
|
66
|
-
const target = {
|
|
67
|
-
services: [] as any[]
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
ResolveFromFiles("/**/*.{ts,js}", "system.dirs.singletons")(target, "services");
|
|
71
|
-
|
|
72
|
-
const services = target.services;
|
|
73
|
-
const cache = DI.RootContainer.Cache as any;
|
|
74
|
-
|
|
75
|
-
expect(services).to.be.an("array").that.have.length(2);
|
|
76
|
-
expect(cache).to.be.an("Map");
|
|
77
|
-
expect(cache.get("FooService")).to.not.null;
|
|
78
|
-
expect(cache.get("FooService2")).to.not.null;
|
|
79
|
-
|
|
80
|
-
expect(DI.resolve(FooService)).to.be.not.null;
|
|
81
|
-
expect(FooService.Counter).to.eq(1);
|
|
82
|
-
|
|
83
|
-
console.log(services);
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
it("Should load service async", async () => {
|
|
87
|
-
const target = {
|
|
88
|
-
services: [] as any[]
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
ResolveFromFiles("/**/*.{ts,js}", "system.dirs.async")(target, "services");
|
|
92
|
-
|
|
93
|
-
expect((target.services as any).then).to.be.instanceOf(Function);
|
|
94
|
-
expect(target.services).to.be.fulfilled.and.eventually.be.an("array");
|
|
95
|
-
|
|
96
|
-
const servs = await target.services;
|
|
97
|
-
expect(servs[0].name).to.eq("FooService");
|
|
98
|
-
expect(servs[0].instance.Counter).to.eq(1);
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
it("Should load mixed sync and async as async", async () => {
|
|
102
|
-
const target = {
|
|
103
|
-
services: [] as any[]
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
ResolveFromFiles("/**/*.{ts,js}", "system.dirs.mixed")(target, "services");
|
|
107
|
-
|
|
108
|
-
expect((target.services as any).then).to.be.instanceOf(Function);
|
|
109
|
-
expect(target.services).to.be.fulfilled.and.eventually.be.an("array");
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const servs = await target.services;
|
|
113
|
-
expect(servs[0].name).to.eq("FooService");
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
it("Should throw when class not found", () => {
|
|
117
|
-
const target = {
|
|
118
|
-
services: [] as any[]
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
ResolveFromFiles("/**/*.{ts,js}", "system.dirs.throw")(target, "services");
|
|
122
|
-
|
|
123
|
-
expect(() => {
|
|
124
|
-
// tslint:disable-next-line: no-unused-expression-chai
|
|
125
|
-
target.services;
|
|
126
|
-
}).to.throw(IOException);
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
it("Should reject on async class not found", () => {
|
|
130
|
-
const target = {
|
|
131
|
-
services: [] as any[]
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
ResolveFromFiles("/**/*.{ts,js}", "system.dirs.mixed")(target, "services");
|
|
135
|
-
|
|
136
|
-
expect((target.services as any).then).to.be.instanceOf(Function);
|
|
137
|
-
expect(target.services).to.be.rejected;
|
|
138
|
-
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
it("Should load service as new always", () => {
|
|
143
|
-
|
|
144
|
-
const target = {
|
|
145
|
-
services: [] as any[]
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
const target2 = {
|
|
149
|
-
services: [] as any[]
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
ResolveFromFiles("/**/*.{ts,js}", "system.dirs.alwaysnew")(target, "services");
|
|
154
|
-
ResolveFromFiles("/**/*.{ts,js}", "system.dirs.alwaysnew")(target2, "services");
|
|
155
|
-
|
|
156
|
-
expect(target.services[0].instance.Counter).to.eq(1);
|
|
157
|
-
expect(target2.services[0].instance.Counter).to.eq(1);
|
|
158
|
-
|
|
159
|
-
expect(DI.RootContainer.Cache).to.be.an("Map");
|
|
160
|
-
expect(DI.RootContainer.Cache.get("FooService")).to.be.not.null;
|
|
161
|
-
})
|
|
162
|
-
|
|
163
|
-
it("Should list class from files", () => {
|
|
164
|
-
|
|
165
|
-
const target = {
|
|
166
|
-
services: [] as any[]
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
ListFromFiles("/**/*.{ts,js}", "system.dirs.alwaysnew")(target, "services");
|
|
171
|
-
|
|
172
|
-
expect(target.services).to.be.an("array");
|
|
173
|
-
expect(target.services[0].name).to.eq("FooService");
|
|
174
|
-
expect(target.services[0].instance).to.be.null;
|
|
175
|
-
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
it("should load empty array if args missing", ()=>{
|
|
179
|
-
const target = {
|
|
180
|
-
services: null as any[]
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
ListFromFiles("/**/*.{ts,js}", "fake.config.parameter")(target, "services");
|
|
184
|
-
expect(target.services).to.be.an("array").with.length(0);
|
|
185
|
-
})
|
|
186
|
-
|
|
187
|
-
it("should load empty array if directory is empty", ()=>{
|
|
188
|
-
const target = {
|
|
189
|
-
services: null as any[]
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
ListFromFiles("/**/*.{ts,js}", "system.dirs.empty")(target, "services");
|
|
193
|
-
expect(target.services).to.be.an("array").with.length(0);
|
|
194
|
-
})
|
|
195
|
-
});
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { AsyncResolveStrategy, IContainer } from "@spinajs/di";
|
|
2
|
-
|
|
3
|
-
export class FooService extends AsyncResolveStrategy {
|
|
4
|
-
|
|
5
|
-
public Counter = 0;
|
|
6
|
-
|
|
7
|
-
public resolveAsync(_: IContainer): Promise<void> {
|
|
8
|
-
this.Counter ++;
|
|
9
|
-
return Promise.resolve();
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
}
|
package/typedoc.json
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"mode": "modules",
|
|
3
|
-
"out": "docs",
|
|
4
|
-
"name": "spine",
|
|
5
|
-
"theme": "default",
|
|
6
|
-
"ignoreCompilerErrors": "true",
|
|
7
|
-
"experimentalDecorators": "true",
|
|
8
|
-
"emitDecoratorMetadata": "true",
|
|
9
|
-
"target": "ES6",
|
|
10
|
-
"moduleResolution": "node",
|
|
11
|
-
"preserveConstEnums": "true",
|
|
12
|
-
"stripInternal": "true",
|
|
13
|
-
"suppressExcessPropertyErrors": "true",
|
|
14
|
-
"suppressImplicitAnyIndexErrors": "true",
|
|
15
|
-
"module": "commonjs"
|
|
16
|
-
}
|