@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/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