@spinajs/reflection 2.0.180 → 2.0.181
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/cjs/index.browser.d.ts +1 -1
- package/lib/cjs/index.browser.js +20 -20
- package/lib/cjs/index.d.ts +34 -34
- package/lib/cjs/index.js +181 -181
- package/lib/mjs/index.browser.d.ts +1 -1
- package/lib/mjs/index.browser.js +4 -4
- package/lib/mjs/index.d.ts +34 -34
- package/lib/mjs/index.js +146 -146
- package/lib/tsconfig.cjs.tsbuildinfo +1 -1
- package/lib/tsconfig.mjs.tsbuildinfo +1 -1
- package/package.json +6 -6
package/lib/mjs/index.js
CHANGED
|
@@ -1,147 +1,147 @@
|
|
|
1
|
-
import * as fs from 'fs';
|
|
2
|
-
import glob from 'glob';
|
|
3
|
-
import * as path from 'path';
|
|
4
|
-
import ts from 'typescript';
|
|
5
|
-
import _ from 'lodash';
|
|
6
|
-
import { Configuration } from '@spinajs/configuration-common';
|
|
7
|
-
import { AsyncService, DI } from '@spinajs/di';
|
|
8
|
-
import { InvalidArgument, Exception } from '@spinajs/exceptions';
|
|
9
|
-
import { Log } from '@spinajs/log-common';
|
|
10
|
-
export * from 'typescript-mix';
|
|
11
|
-
/**
|
|
12
|
-
* Exception thrown when some error during reflection occurs
|
|
13
|
-
*/
|
|
14
|
-
export class ReflectionException extends Exception {
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Helper class for extracting various information from typescript source code
|
|
18
|
-
*/
|
|
19
|
-
export class TypescriptCompiler {
|
|
20
|
-
constructor(filename) {
|
|
21
|
-
this.tsFile = filename;
|
|
22
|
-
this.compiled = ts.createProgram([this.tsFile], {
|
|
23
|
-
module: ts.ModuleKind.NodeNext,
|
|
24
|
-
target: ts.ScriptTarget.Latest,
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
*
|
|
29
|
-
* Extracts all members info from typescript class eg. method name, parameters, return types etc.
|
|
30
|
-
*
|
|
31
|
-
* @param className - name of class to parse
|
|
32
|
-
*/
|
|
33
|
-
getClassMembers(className) {
|
|
34
|
-
const members = new Map();
|
|
35
|
-
const sourceFile = this.compiled.getSourceFile(this.tsFile);
|
|
36
|
-
// Walk the tree to search for classes
|
|
37
|
-
ts.forEachChild(sourceFile, this.walkClassNode(className, this.walkMemberNode((method) => {
|
|
38
|
-
// method.name.getText() returns null ?
|
|
39
|
-
// UGLY HACK FOR THIS
|
|
40
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
41
|
-
members.set(method.name.text, method);
|
|
42
|
-
})));
|
|
43
|
-
return members;
|
|
44
|
-
}
|
|
45
|
-
walkClassNode(className, callback) {
|
|
46
|
-
return (node) => {
|
|
47
|
-
if (node.kind === ts.SyntaxKind.ClassDeclaration) {
|
|
48
|
-
const cldecl = node;
|
|
49
|
-
if (cldecl.name.text === className) {
|
|
50
|
-
callback(cldecl);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
walkMemberNode(callback) {
|
|
56
|
-
return (node) => {
|
|
57
|
-
for (const member of node.members) {
|
|
58
|
-
if (member.kind === ts.SyntaxKind.MethodDeclaration) {
|
|
59
|
-
const method = member;
|
|
60
|
-
callback(method);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Returns resolved instances of classes from specified files.
|
|
68
|
-
* It automatically checks if should resolve promise or not, calls resolve strategy, checks if should return new or signleton etc, resolves
|
|
69
|
-
* dependencies etc.
|
|
70
|
-
*
|
|
71
|
-
* @param filter - files to look at, uses glob pattern to search
|
|
72
|
-
* @param configPath - dir paths taken from app config eg. "system.dirs.controllers". Path MUST be avaible in configuration
|
|
73
|
-
*
|
|
74
|
-
*/
|
|
75
|
-
export function ResolveFromFiles(filter, configPath, typeMatcher) {
|
|
76
|
-
return _listOrResolveFromFiles(filter, configPath, typeMatcher);
|
|
77
|
-
}
|
|
78
|
-
function _listOrResolveFromFiles(filter, configPath, typeMatcher) {
|
|
79
|
-
return (target, propertyKey) => {
|
|
80
|
-
if (!filter) {
|
|
81
|
-
throw new InvalidArgument('filter parameter is null or empty');
|
|
82
|
-
}
|
|
83
|
-
if (!configPath) {
|
|
84
|
-
throw new InvalidArgument('configPath parameter is null or empty');
|
|
85
|
-
}
|
|
86
|
-
let instances = null;
|
|
87
|
-
const getter = () => {
|
|
88
|
-
if (!instances) {
|
|
89
|
-
instances = _loadInstances();
|
|
90
|
-
}
|
|
91
|
-
return instances;
|
|
92
|
-
};
|
|
93
|
-
Object.defineProperty(target, propertyKey, {
|
|
94
|
-
enumerable: true,
|
|
95
|
-
get: getter,
|
|
96
|
-
});
|
|
97
|
-
async function _loadInstances() {
|
|
98
|
-
const config = DI.get(Configuration);
|
|
99
|
-
const logger = DI.resolve(Log, ['reflection']);
|
|
100
|
-
let directories = config.get(configPath);
|
|
101
|
-
if (!directories || directories.length === 0) {
|
|
102
|
-
return [];
|
|
103
|
-
}
|
|
104
|
-
if (!Array.isArray(directories)) {
|
|
105
|
-
directories = [directories];
|
|
106
|
-
}
|
|
107
|
-
// eslint-disable -next-line @typescript-eslint/await-thenable
|
|
108
|
-
const fPromises = _.uniq(directories)
|
|
109
|
-
.filter((d) => {
|
|
110
|
-
/* eslint-disable */
|
|
111
|
-
const exists = fs.existsSync(path.normalize(d));
|
|
112
|
-
if (!exists) {
|
|
113
|
-
logger.warn(`Directory ${d} not exists`);
|
|
114
|
-
}
|
|
115
|
-
return exists;
|
|
116
|
-
})
|
|
117
|
-
.flatMap((d) => glob.sync(path.join(d, filter).replace(/\\/g, '/')))
|
|
118
|
-
.flatMap((f) => {
|
|
119
|
-
logger.trace(`Loading file ${f}`);
|
|
120
|
-
return DI.__spinajs_require__(f).then((fTypes) => {
|
|
121
|
-
for (const key of Object.keys(fTypes)) {
|
|
122
|
-
const nameToResolve = typeMatcher ? typeMatcher(path.parse(f).name, key) : key;
|
|
123
|
-
const type = fTypes[`${nameToResolve}`];
|
|
124
|
-
if (type.prototype instanceof AsyncService) {
|
|
125
|
-
return DI.resolve(type).then((instance) => {
|
|
126
|
-
return {
|
|
127
|
-
file: f,
|
|
128
|
-
instance,
|
|
129
|
-
name: nameToResolve,
|
|
130
|
-
type,
|
|
131
|
-
};
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
return Promise.resolve({
|
|
135
|
-
file: f,
|
|
136
|
-
instance: DI.resolve(type),
|
|
137
|
-
name: nameToResolve,
|
|
138
|
-
type,
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
return Promise.all(fPromises);
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
|
-
}
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import glob from 'glob';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import ts from 'typescript';
|
|
5
|
+
import _ from 'lodash';
|
|
6
|
+
import { Configuration } from '@spinajs/configuration-common';
|
|
7
|
+
import { AsyncService, DI } from '@spinajs/di';
|
|
8
|
+
import { InvalidArgument, Exception } from '@spinajs/exceptions';
|
|
9
|
+
import { Log } from '@spinajs/log-common';
|
|
10
|
+
export * from 'typescript-mix';
|
|
11
|
+
/**
|
|
12
|
+
* Exception thrown when some error during reflection occurs
|
|
13
|
+
*/
|
|
14
|
+
export class ReflectionException extends Exception {
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Helper class for extracting various information from typescript source code
|
|
18
|
+
*/
|
|
19
|
+
export class TypescriptCompiler {
|
|
20
|
+
constructor(filename) {
|
|
21
|
+
this.tsFile = filename;
|
|
22
|
+
this.compiled = ts.createProgram([this.tsFile], {
|
|
23
|
+
module: ts.ModuleKind.NodeNext,
|
|
24
|
+
target: ts.ScriptTarget.Latest,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* Extracts all members info from typescript class eg. method name, parameters, return types etc.
|
|
30
|
+
*
|
|
31
|
+
* @param className - name of class to parse
|
|
32
|
+
*/
|
|
33
|
+
getClassMembers(className) {
|
|
34
|
+
const members = new Map();
|
|
35
|
+
const sourceFile = this.compiled.getSourceFile(this.tsFile);
|
|
36
|
+
// Walk the tree to search for classes
|
|
37
|
+
ts.forEachChild(sourceFile, this.walkClassNode(className, this.walkMemberNode((method) => {
|
|
38
|
+
// method.name.getText() returns null ?
|
|
39
|
+
// UGLY HACK FOR THIS
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
41
|
+
members.set(method.name.text, method);
|
|
42
|
+
})));
|
|
43
|
+
return members;
|
|
44
|
+
}
|
|
45
|
+
walkClassNode(className, callback) {
|
|
46
|
+
return (node) => {
|
|
47
|
+
if (node.kind === ts.SyntaxKind.ClassDeclaration) {
|
|
48
|
+
const cldecl = node;
|
|
49
|
+
if (cldecl.name.text === className) {
|
|
50
|
+
callback(cldecl);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
walkMemberNode(callback) {
|
|
56
|
+
return (node) => {
|
|
57
|
+
for (const member of node.members) {
|
|
58
|
+
if (member.kind === ts.SyntaxKind.MethodDeclaration) {
|
|
59
|
+
const method = member;
|
|
60
|
+
callback(method);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Returns resolved instances of classes from specified files.
|
|
68
|
+
* It automatically checks if should resolve promise or not, calls resolve strategy, checks if should return new or signleton etc, resolves
|
|
69
|
+
* dependencies etc.
|
|
70
|
+
*
|
|
71
|
+
* @param filter - files to look at, uses glob pattern to search
|
|
72
|
+
* @param configPath - dir paths taken from app config eg. "system.dirs.controllers". Path MUST be avaible in configuration
|
|
73
|
+
*
|
|
74
|
+
*/
|
|
75
|
+
export function ResolveFromFiles(filter, configPath, typeMatcher) {
|
|
76
|
+
return _listOrResolveFromFiles(filter, configPath, typeMatcher);
|
|
77
|
+
}
|
|
78
|
+
function _listOrResolveFromFiles(filter, configPath, typeMatcher) {
|
|
79
|
+
return (target, propertyKey) => {
|
|
80
|
+
if (!filter) {
|
|
81
|
+
throw new InvalidArgument('filter parameter is null or empty');
|
|
82
|
+
}
|
|
83
|
+
if (!configPath) {
|
|
84
|
+
throw new InvalidArgument('configPath parameter is null or empty');
|
|
85
|
+
}
|
|
86
|
+
let instances = null;
|
|
87
|
+
const getter = () => {
|
|
88
|
+
if (!instances) {
|
|
89
|
+
instances = _loadInstances();
|
|
90
|
+
}
|
|
91
|
+
return instances;
|
|
92
|
+
};
|
|
93
|
+
Object.defineProperty(target, propertyKey, {
|
|
94
|
+
enumerable: true,
|
|
95
|
+
get: getter,
|
|
96
|
+
});
|
|
97
|
+
async function _loadInstances() {
|
|
98
|
+
const config = DI.get(Configuration);
|
|
99
|
+
const logger = DI.resolve(Log, ['reflection']);
|
|
100
|
+
let directories = config.get(configPath);
|
|
101
|
+
if (!directories || directories.length === 0) {
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
if (!Array.isArray(directories)) {
|
|
105
|
+
directories = [directories];
|
|
106
|
+
}
|
|
107
|
+
// eslint-disable -next-line @typescript-eslint/await-thenable
|
|
108
|
+
const fPromises = _.uniq(directories)
|
|
109
|
+
.filter((d) => {
|
|
110
|
+
/* eslint-disable */
|
|
111
|
+
const exists = fs.existsSync(path.normalize(d));
|
|
112
|
+
if (!exists) {
|
|
113
|
+
logger.warn(`Directory ${d} not exists`);
|
|
114
|
+
}
|
|
115
|
+
return exists;
|
|
116
|
+
})
|
|
117
|
+
.flatMap((d) => glob.sync(path.join(d, filter).replace(/\\/g, '/')))
|
|
118
|
+
.flatMap((f) => {
|
|
119
|
+
logger.trace(`Loading file ${f}`);
|
|
120
|
+
return DI.__spinajs_require__(f).then((fTypes) => {
|
|
121
|
+
for (const key of Object.keys(fTypes)) {
|
|
122
|
+
const nameToResolve = typeMatcher ? typeMatcher(path.parse(f).name, key) : key;
|
|
123
|
+
const type = fTypes[`${nameToResolve}`];
|
|
124
|
+
if (type.prototype instanceof AsyncService) {
|
|
125
|
+
return DI.resolve(type).then((instance) => {
|
|
126
|
+
return {
|
|
127
|
+
file: f,
|
|
128
|
+
instance,
|
|
129
|
+
name: nameToResolve,
|
|
130
|
+
type,
|
|
131
|
+
};
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return Promise.resolve({
|
|
135
|
+
file: f,
|
|
136
|
+
instance: DI.resolve(type),
|
|
137
|
+
name: nameToResolve,
|
|
138
|
+
type,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
return Promise.all(fPromises);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
147
|
//# sourceMappingURL=index.js.map
|