@gadmin2n/cli 0.0.105 → 0.0.107
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/CHANGELOG.md +17 -0
- package/actions/new.action.js +140 -94
- package/actions/update.action.d.ts +1 -0
- package/actions/update.action.js +564 -630
- package/commands/command.input.d.ts +1 -6
- package/commands/command.input.js +1 -7
- package/commands/command.loader.js +0 -2
- package/commands/new.command.js +8 -3
- package/commands/update.command.js +27 -37
- package/lib/template-merge/base-store.d.ts +16 -0
- package/lib/template-merge/base-store.js +127 -0
- package/lib/template-merge/binary-detect.d.ts +7 -0
- package/lib/template-merge/binary-detect.js +36 -0
- package/lib/template-merge/classify.d.ts +10 -0
- package/lib/template-merge/classify.js +61 -0
- package/lib/template-merge/config-validate.d.ts +5 -0
- package/lib/template-merge/config-validate.js +33 -0
- package/lib/template-merge/excludes.d.ts +7 -0
- package/lib/template-merge/excludes.js +109 -0
- package/lib/template-merge/index.d.ts +9 -8
- package/lib/template-merge/index.js +10 -8
- package/lib/template-merge/materialize.d.ts +18 -0
- package/lib/template-merge/materialize.js +129 -0
- package/lib/template-merge/merge3way.d.ts +15 -0
- package/lib/template-merge/merge3way.js +54 -0
- package/lib/template-merge/residual-scan.d.ts +10 -0
- package/lib/template-merge/residual-scan.js +31 -0
- package/lib/template-merge/types.d.ts +27 -0
- package/lib/template-merge/types.js +5 -0
- package/lib/ui/messages.d.ts +0 -2
- package/lib/ui/messages.js +0 -2
- package/package.json +2 -2
- package/commands/build.command.d.ts +0 -5
- package/commands/build.command.js +0 -50
- package/lib/template-merge/config-loader.d.ts +0 -15
- package/lib/template-merge/config-loader.js +0 -38
- package/lib/template-merge/env-merger.d.ts +0 -5
- package/lib/template-merge/env-merger.js +0 -57
- package/lib/template-merge/glob.d.ts +0 -5
- package/lib/template-merge/glob.js +0 -78
- package/lib/template-merge/json-merger.d.ts +0 -5
- package/lib/template-merge/json-merger.js +0 -269
- package/lib/template-merge/merger.d.ts +0 -30
- package/lib/template-merge/merger.js +0 -2
- package/lib/template-merge/prisma-merger.d.ts +0 -5
- package/lib/template-merge/prisma-merger.js +0 -112
- package/lib/template-merge/registry.d.ts +0 -25
- package/lib/template-merge/registry.js +0 -42
- package/lib/template-merge/ts-module-merger.d.ts +0 -16
- package/lib/template-merge/ts-module-merger.js +0 -193
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TsModuleMerger = void 0;
|
|
4
|
-
const ts = require("typescript");
|
|
5
|
-
const schematics_1 = require("@gadmin2n/schematics");
|
|
6
|
-
const METADATA_KEYS = ['imports', 'providers', 'controllers', 'exports'];
|
|
7
|
-
/**
|
|
8
|
-
* Smart merger for NestJS-style `*.module.ts` files.
|
|
9
|
-
*
|
|
10
|
-
* Strategy: extract symbols from template's `@Module(...)` metadata arrays
|
|
11
|
-
* (imports/providers/controllers/exports) and missing top-level `import { ... } from '...'`
|
|
12
|
-
* lines, then insert each missing item into the instance file. Existing items are
|
|
13
|
-
* preserved. Method bodies and other class members are not touched.
|
|
14
|
-
*
|
|
15
|
-
* Falls back (returns `{ok: false}`) when the instance has no `@Module` decorator
|
|
16
|
-
* or when AST parsing/insertion throws.
|
|
17
|
-
*/
|
|
18
|
-
class TsModuleMerger {
|
|
19
|
-
constructor() {
|
|
20
|
-
this.name = 'ts-module';
|
|
21
|
-
}
|
|
22
|
-
merge(ctx) {
|
|
23
|
-
var _a, _b;
|
|
24
|
-
const policies = (_a = ctx.policies) !== null && _a !== void 0 ? _a : {};
|
|
25
|
-
const notes = [];
|
|
26
|
-
try {
|
|
27
|
-
const templateSource = ts.createSourceFile('template.ts', ctx.templateContent, ts.ScriptTarget.ES2017, true);
|
|
28
|
-
const instanceSourceInitial = ts.createSourceFile('instance.ts', ctx.instanceContent, ts.ScriptTarget.ES2017, true);
|
|
29
|
-
if (!findModuleDecoratorArg(instanceSourceInitial)) {
|
|
30
|
-
return { ok: false, reason: 'no @Module decorator in instance' };
|
|
31
|
-
}
|
|
32
|
-
const templateModuleArg = findModuleDecoratorArg(templateSource);
|
|
33
|
-
let content = ctx.instanceContent;
|
|
34
|
-
// 1. Per-slot metadata merge (imports, providers, controllers, exports).
|
|
35
|
-
if (templateModuleArg) {
|
|
36
|
-
for (const key of METADATA_KEYS) {
|
|
37
|
-
const policy = (_b = policies[`ts-module.${key}`]) !== null && _b !== void 0 ? _b : 'union';
|
|
38
|
-
if (policy === 'skip') {
|
|
39
|
-
notes.push(`${key}: skip (policy)`);
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
const templateElements = extractMetadataArrayElements(templateModuleArg, key, templateSource);
|
|
43
|
-
if (templateElements.length === 0)
|
|
44
|
-
continue;
|
|
45
|
-
for (const element of templateElements) {
|
|
46
|
-
// Re-parse the current (possibly mutated) instance to get fresh
|
|
47
|
-
// existing-element lookup. This mirrors the pattern used in
|
|
48
|
-
// schematics' service.factory: each MetadataManager.insert call
|
|
49
|
-
// takes the latest content.
|
|
50
|
-
const reparsed = ts.createSourceFile('instance.ts', content, ts.ScriptTarget.ES2017, true);
|
|
51
|
-
const arg = findModuleDecoratorArg(reparsed);
|
|
52
|
-
if (!arg) {
|
|
53
|
-
return { ok: false, reason: 'lost @Module decorator during merge' };
|
|
54
|
-
}
|
|
55
|
-
const existing = extractMetadataArrayElements(arg, key, reparsed);
|
|
56
|
-
if (existing.includes(element)) {
|
|
57
|
-
notes.push(`${key}: kept ${element}`);
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
const next = new schematics_1.MetadataManager(content).insert(key, element);
|
|
61
|
-
if (next === content) {
|
|
62
|
-
// MetadataManager returned content unchanged (e.g. symbol already
|
|
63
|
-
// exists by its own equality check). Treat as kept.
|
|
64
|
-
notes.push(`${key}: kept ${element}`);
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
content = next;
|
|
68
|
-
notes.push(`${key}: added ${element}`);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
// 2. Top-level import lines merge.
|
|
74
|
-
const templateImports = collectTopImports(templateSource);
|
|
75
|
-
const instanceForImports = ts.createSourceFile('instance.ts', content, ts.ScriptTarget.ES2017, true);
|
|
76
|
-
const instanceImports = collectTopImports(instanceForImports);
|
|
77
|
-
const existingSymbols = new Set();
|
|
78
|
-
for (const imp of instanceImports) {
|
|
79
|
-
for (const s of imp.symbols)
|
|
80
|
-
existingSymbols.add(s);
|
|
81
|
-
}
|
|
82
|
-
const linesToAdd = [];
|
|
83
|
-
for (const imp of templateImports) {
|
|
84
|
-
if (imp.symbols.length === 0)
|
|
85
|
-
continue;
|
|
86
|
-
const allExist = imp.symbols.every((s) => existingSymbols.has(s));
|
|
87
|
-
if (allExist)
|
|
88
|
-
continue;
|
|
89
|
-
linesToAdd.push(imp.line);
|
|
90
|
-
for (const s of imp.symbols)
|
|
91
|
-
existingSymbols.add(s);
|
|
92
|
-
notes.push(`import: added ${imp.symbols.join(', ')} from '${imp.from}'`);
|
|
93
|
-
}
|
|
94
|
-
if (linesToAdd.length > 0) {
|
|
95
|
-
let lastEnd = -1;
|
|
96
|
-
for (const stmt of instanceForImports.statements) {
|
|
97
|
-
if (ts.isImportDeclaration(stmt)) {
|
|
98
|
-
lastEnd = stmt.getEnd();
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
const insertion = '\n' + linesToAdd.join('\n');
|
|
102
|
-
if (lastEnd >= 0) {
|
|
103
|
-
content = content.slice(0, lastEnd) + insertion + content.slice(lastEnd);
|
|
104
|
-
}
|
|
105
|
-
else {
|
|
106
|
-
// No existing imports — prepend.
|
|
107
|
-
content = linesToAdd.join('\n') + '\n' + content;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
if (content === ctx.instanceContent) {
|
|
111
|
-
return { ok: true, merged: content, notes: ['no changes'] };
|
|
112
|
-
}
|
|
113
|
-
return { ok: true, merged: content, notes };
|
|
114
|
-
}
|
|
115
|
-
catch (err) {
|
|
116
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
117
|
-
return { ok: false, reason: `ts-module merge failed: ${message}` };
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
exports.TsModuleMerger = TsModuleMerger;
|
|
122
|
-
/**
|
|
123
|
-
* Walk the AST to find the first `@Module(...)` decorator's
|
|
124
|
-
* `ObjectLiteralExpression` argument. Returns `undefined` if not found.
|
|
125
|
-
*/
|
|
126
|
-
function findModuleDecoratorArg(source) {
|
|
127
|
-
let result;
|
|
128
|
-
const visit = (node) => {
|
|
129
|
-
if (result)
|
|
130
|
-
return;
|
|
131
|
-
if (ts.isDecorator(node) && ts.isCallExpression(node.expression)) {
|
|
132
|
-
const callee = node.expression.expression;
|
|
133
|
-
if (ts.isIdentifier(callee) && callee.text === 'Module') {
|
|
134
|
-
const arg = node.expression.arguments[0];
|
|
135
|
-
if (arg && ts.isObjectLiteralExpression(arg)) {
|
|
136
|
-
result = arg;
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
ts.forEachChild(node, visit);
|
|
142
|
-
};
|
|
143
|
-
visit(source);
|
|
144
|
-
return result;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Extract the source text of each element of a metadata array property
|
|
148
|
-
* (e.g. `imports: [A, B.forRoot({...})]`).
|
|
149
|
-
*/
|
|
150
|
-
function extractMetadataArrayElements(arg, key, source) {
|
|
151
|
-
for (const prop of arg.properties) {
|
|
152
|
-
if (!ts.isPropertyAssignment(prop))
|
|
153
|
-
continue;
|
|
154
|
-
let propName = '';
|
|
155
|
-
if (ts.isIdentifier(prop.name))
|
|
156
|
-
propName = prop.name.text;
|
|
157
|
-
else if (ts.isStringLiteral(prop.name))
|
|
158
|
-
propName = prop.name.text;
|
|
159
|
-
if (propName !== key)
|
|
160
|
-
continue;
|
|
161
|
-
if (!ts.isArrayLiteralExpression(prop.initializer))
|
|
162
|
-
continue;
|
|
163
|
-
return prop.initializer.elements.map((el) => el.getText(source));
|
|
164
|
-
}
|
|
165
|
-
return [];
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Collect top-level `import { Named, ... } from '...'` declarations from a
|
|
169
|
-
* source file. Default and namespace imports are intentionally ignored — the
|
|
170
|
-
* NestJS module template convention is named-imports only.
|
|
171
|
-
*/
|
|
172
|
-
function collectTopImports(source) {
|
|
173
|
-
const result = [];
|
|
174
|
-
for (const stmt of source.statements) {
|
|
175
|
-
if (!ts.isImportDeclaration(stmt))
|
|
176
|
-
continue;
|
|
177
|
-
if (!ts.isStringLiteral(stmt.moduleSpecifier))
|
|
178
|
-
continue;
|
|
179
|
-
const symbols = [];
|
|
180
|
-
const ic = stmt.importClause;
|
|
181
|
-
if (ic && ic.namedBindings && ts.isNamedImports(ic.namedBindings)) {
|
|
182
|
-
for (const el of ic.namedBindings.elements) {
|
|
183
|
-
symbols.push(el.name.text);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
result.push({
|
|
187
|
-
line: stmt.getText(source),
|
|
188
|
-
symbols,
|
|
189
|
-
from: stmt.moduleSpecifier.text,
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
return result;
|
|
193
|
-
}
|