@lenne.tech/cli 1.6.9 → 1.7.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/build/commands/completion.js +28 -1
- package/build/commands/config/validate.js +4 -1
- package/build/commands/fullstack/init.js +61 -12
- package/build/commands/server/create.js +59 -61
- package/build/commands/update.js +49 -2
- package/build/extensions/api-mode.js +440 -0
- package/build/extensions/server.js +38 -7
- package/build/templates/nest-server-starter/README.md.ejs +0 -1
- package/docs/lt.config.md +9 -2
- package/package.json +8 -8
package/build/commands/update.js
CHANGED
|
@@ -9,6 +9,24 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const child_process_1 = require("child_process");
|
|
13
|
+
/**
|
|
14
|
+
* Get the version that a new CLI process would use by running 'lt --version'.
|
|
15
|
+
* This is the most reliable way to check if the update was successful,
|
|
16
|
+
* as it tests the actual behavior of a new process.
|
|
17
|
+
*/
|
|
18
|
+
function getNewProcessVersion() {
|
|
19
|
+
try {
|
|
20
|
+
const result = (0, child_process_1.execSync)('lt --version', {
|
|
21
|
+
encoding: 'utf-8',
|
|
22
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
23
|
+
});
|
|
24
|
+
return result.trim();
|
|
25
|
+
}
|
|
26
|
+
catch (_a) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
12
30
|
/**
|
|
13
31
|
* Update @lenne.tech/cli
|
|
14
32
|
*/
|
|
@@ -19,12 +37,41 @@ const NewCommand = {
|
|
|
19
37
|
name: 'update',
|
|
20
38
|
run: (toolbox) => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
39
|
// Retrieve the tools we need
|
|
22
|
-
const { helper, runtime: { brand }, } = toolbox;
|
|
40
|
+
const { helper, meta, print: { info, warning }, runtime: { brand }, } = toolbox;
|
|
41
|
+
// Store version before update
|
|
42
|
+
const versionBefore = meta.version();
|
|
23
43
|
// Update cli and show process
|
|
24
44
|
yield helper.updateCli({ showInfos: true });
|
|
45
|
+
// Check what version a new process would use
|
|
46
|
+
const newProcessVersion = getNewProcessVersion();
|
|
47
|
+
// Check if update was successful and version changed
|
|
48
|
+
if (newProcessVersion && newProcessVersion !== versionBefore) {
|
|
49
|
+
info('');
|
|
50
|
+
info(`Update successful: ${versionBefore} → ${newProcessVersion}`);
|
|
51
|
+
info('');
|
|
52
|
+
const shell = process.env.SHELL || '';
|
|
53
|
+
if (shell.includes('zsh')) {
|
|
54
|
+
info(`To use the new version, run 'rehash' or open a new terminal.`);
|
|
55
|
+
}
|
|
56
|
+
else if (shell.includes('bash')) {
|
|
57
|
+
info(`To use the new version, run 'hash -r' or open a new terminal.`);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
info(`To use the new version, open a new terminal.`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else if (newProcessVersion === versionBefore) {
|
|
64
|
+
info('');
|
|
65
|
+
info(`CLI is already up to date (${versionBefore}).`);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// Could not verify update
|
|
69
|
+
warning('');
|
|
70
|
+
warning(`Could not verify update. Please run 'lt --version' to check.`);
|
|
71
|
+
}
|
|
25
72
|
// For tests
|
|
26
73
|
return `updated ${brand}`;
|
|
27
74
|
}),
|
|
28
75
|
};
|
|
29
76
|
exports.default = NewCommand;
|
|
30
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
77
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBkYXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbW1hbmRzL3VwZGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztBQUFBLGlEQUF5QztBQUt6Qzs7OztHQUlHO0FBQ0gsU0FBUyxvQkFBb0I7SUFDM0IsSUFBSSxDQUFDO1FBQ0gsTUFBTSxNQUFNLEdBQUcsSUFBQSx3QkFBUSxFQUFDLGNBQWMsRUFBRTtZQUN0QyxRQUFRLEVBQUUsT0FBTztZQUNqQixLQUFLLEVBQUUsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQztTQUNoQyxDQUFDLENBQUM7UUFDSCxPQUFPLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUN2QixDQUFDO0lBQUMsV0FBTSxDQUFDO1FBQ1AsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0FBQ0gsQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLEdBQW1CO0lBQ2pDLEtBQUssRUFBRSxDQUFDLElBQUksQ0FBQztJQUNiLFdBQVcsRUFBRSx3QkFBd0I7SUFDckMsTUFBTSxFQUFFLEtBQUs7SUFDYixJQUFJLEVBQUUsUUFBUTtJQUNkLEdBQUcsRUFBRSxDQUFPLE9BQStCLEVBQUUsRUFBRTtRQUM3Qyw2QkFBNkI7UUFDN0IsTUFBTSxFQUNKLE1BQU0sRUFDTixJQUFJLEVBQ0osS0FBSyxFQUFFLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxFQUN4QixPQUFPLEVBQUUsRUFBRSxLQUFLLEVBQUUsR0FDbkIsR0FBRyxPQUFPLENBQUM7UUFFWiw4QkFBOEI7UUFDOUIsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBRXJDLDhCQUE4QjtRQUM5QixNQUFNLE1BQU0sQ0FBQyxTQUFTLENBQUMsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUU1Qyw2Q0FBNkM7UUFDN0MsTUFBTSxpQkFBaUIsR0FBRyxvQkFBb0IsRUFBRSxDQUFDO1FBRWpELHFEQUFxRDtRQUNyRCxJQUFJLGlCQUFpQixJQUFJLGlCQUFpQixLQUFLLGFBQWEsRUFBRSxDQUFDO1lBQzdELElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNULElBQUksQ0FBQyxzQkFBc0IsYUFBYSxNQUFNLGlCQUFpQixFQUFFLENBQUMsQ0FBQztZQUNuRSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDVCxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDdEMsSUFBSSxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQzFCLElBQUksQ0FBQyw4REFBOEQsQ0FBQyxDQUFDO1lBQ3ZFLENBQUM7aUJBQU0sSUFBSSxLQUFLLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7Z0JBQ2xDLElBQUksQ0FBQywrREFBK0QsQ0FBQyxDQUFDO1lBQ3hFLENBQUM7aUJBQU0sQ0FBQztnQkFDTixJQUFJLENBQUMsOENBQThDLENBQUMsQ0FBQztZQUN2RCxDQUFDO1FBQ0gsQ0FBQzthQUFNLElBQUksaUJBQWlCLEtBQUssYUFBYSxFQUFFLENBQUM7WUFDL0MsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ1QsSUFBSSxDQUFDLDhCQUE4QixhQUFhLElBQUksQ0FBQyxDQUFDO1FBQ3hELENBQUM7YUFBTSxDQUFDO1lBQ04sMEJBQTBCO1lBQzFCLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNaLE9BQU8sQ0FBQyw4REFBOEQsQ0FBQyxDQUFDO1FBQzFFLENBQUM7UUFFRCxZQUFZO1FBQ1osT0FBTyxXQUFXLEtBQUssRUFBRSxDQUFDO0lBQzVCLENBQUMsQ0FBQTtDQUNGLENBQUM7QUFFRixrQkFBZSxVQUFVLENBQUMifQ==
|
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.ApiMode = void 0;
|
|
13
|
+
const path_1 = require("path");
|
|
14
|
+
/**
|
|
15
|
+
* API Mode processing for nest-server-starter template
|
|
16
|
+
*
|
|
17
|
+
* Reads the api-mode.manifest.json from the project and processes it
|
|
18
|
+
* based on the selected API mode (Rest, GraphQL, Both).
|
|
19
|
+
*/
|
|
20
|
+
class ApiMode {
|
|
21
|
+
constructor(toolbox) {
|
|
22
|
+
this.toolbox = toolbox;
|
|
23
|
+
this.filesystem = toolbox.filesystem;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Process the API mode for a project
|
|
27
|
+
*
|
|
28
|
+
* @param projectPath - Path to the project root
|
|
29
|
+
* @param mode - Selected API mode
|
|
30
|
+
*/
|
|
31
|
+
processApiMode(projectPath, mode) {
|
|
32
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
const manifestPath = (0, path_1.join)(projectPath, 'api-mode.manifest.json');
|
|
34
|
+
// Read manifest
|
|
35
|
+
const manifestContent = this.filesystem.read(manifestPath);
|
|
36
|
+
if (!manifestContent) {
|
|
37
|
+
return; // No manifest = nothing to do
|
|
38
|
+
}
|
|
39
|
+
const manifest = JSON.parse(manifestContent);
|
|
40
|
+
if (mode === 'Both') {
|
|
41
|
+
// Both mode: just remove markers and cleanup
|
|
42
|
+
this.stripAllMarkers(projectPath);
|
|
43
|
+
}
|
|
44
|
+
else if (mode === 'Rest') {
|
|
45
|
+
// REST mode: remove graphql regions, keep rest regions
|
|
46
|
+
yield this.removeMode(projectPath, manifest, 'graphql', 'rest');
|
|
47
|
+
yield this.modifyConfigEnvForRest(projectPath);
|
|
48
|
+
}
|
|
49
|
+
else if (mode === 'GraphQL') {
|
|
50
|
+
// GraphQL mode: remove rest regions, keep graphql regions
|
|
51
|
+
yield this.removeMode(projectPath, manifest, 'rest', 'graphql');
|
|
52
|
+
}
|
|
53
|
+
// Remove manifest and strip-markers script
|
|
54
|
+
this.filesystem.remove(manifestPath);
|
|
55
|
+
this.filesystem.remove((0, path_1.join)(projectPath, 'scripts', 'strip-api-mode-markers.mjs'));
|
|
56
|
+
// Remove strip-markers script from package.json
|
|
57
|
+
this.removeScriptFromPackageJson(projectPath, 'strip-markers');
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Remove a specific mode from the project
|
|
62
|
+
*/
|
|
63
|
+
removeMode(projectPath, manifest, removeMarker, keepMarker) {
|
|
64
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
65
|
+
var _a, _b, _c;
|
|
66
|
+
const modeConfig = manifest.modes[removeMarker];
|
|
67
|
+
if (!modeConfig) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
// 1. Delete files matching filePatterns
|
|
71
|
+
if (modeConfig.filePatterns) {
|
|
72
|
+
for (const pattern of modeConfig.filePatterns) {
|
|
73
|
+
const matches = this.filesystem.find(projectPath, {
|
|
74
|
+
matching: pattern,
|
|
75
|
+
});
|
|
76
|
+
for (const file of matches) {
|
|
77
|
+
this.filesystem.remove(file);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// 2. Remove packages from package.json
|
|
82
|
+
const pkgPath = (0, path_1.join)(projectPath, 'package.json');
|
|
83
|
+
const pkg = JSON.parse(this.filesystem.read(pkgPath));
|
|
84
|
+
if (modeConfig.packages) {
|
|
85
|
+
for (const p of modeConfig.packages) {
|
|
86
|
+
(_a = pkg.dependencies) === null || _a === void 0 ? true : delete _a[p];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (modeConfig.devPackages) {
|
|
90
|
+
for (const p of modeConfig.devPackages) {
|
|
91
|
+
(_b = pkg.devDependencies) === null || _b === void 0 ? true : delete _b[p];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// 3. Remove scripts
|
|
95
|
+
if (modeConfig.scripts) {
|
|
96
|
+
for (const s of modeConfig.scripts) {
|
|
97
|
+
(_c = pkg.scripts) === null || _c === void 0 ? true : delete _c[s];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// 4. Edit scripts (e.g. remove parts from a script value)
|
|
101
|
+
if (modeConfig.scriptEdits && pkg.scripts) {
|
|
102
|
+
for (const [scriptName, edit] of Object.entries(modeConfig.scriptEdits)) {
|
|
103
|
+
if (pkg.scripts[scriptName] && edit.remove) {
|
|
104
|
+
pkg.scripts[scriptName] = pkg.scripts[scriptName].replace(edit.remove, '');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
this.filesystem.write(pkgPath, pkg, { jsonIndent: 2 });
|
|
109
|
+
// 5. Strip regions from source files
|
|
110
|
+
this.stripRegions(projectPath, removeMarker, keepMarker);
|
|
111
|
+
// 6. Clean orphan imports
|
|
112
|
+
this.cleanOrphanImports(projectPath);
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Strip region markers from all .ts files
|
|
117
|
+
*
|
|
118
|
+
* For removeMarker: delete marker lines AND content between them
|
|
119
|
+
* For keepMarker: delete only the marker lines, keep content
|
|
120
|
+
*/
|
|
121
|
+
stripRegions(projectPath, removeMarker, keepMarker) {
|
|
122
|
+
const dirs = [(0, path_1.join)(projectPath, 'src'), (0, path_1.join)(projectPath, 'tests')];
|
|
123
|
+
for (const dir of dirs) {
|
|
124
|
+
if (!this.filesystem.exists(dir)) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const files = this.filesystem.find(dir, { matching: '**/*.ts' });
|
|
128
|
+
for (const file of files) {
|
|
129
|
+
const content = this.filesystem.read(file);
|
|
130
|
+
if (!content) {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
const processed = this.processFileRegions(content, removeMarker, keepMarker);
|
|
134
|
+
if (processed !== content) {
|
|
135
|
+
this.filesystem.write(file, processed);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Process region markers in file content
|
|
142
|
+
*/
|
|
143
|
+
processFileRegions(content, removeMarker, keepMarker) {
|
|
144
|
+
const lines = content.split('\n');
|
|
145
|
+
const result = [];
|
|
146
|
+
let removing = false;
|
|
147
|
+
for (const line of lines) {
|
|
148
|
+
const trimmed = line.trim();
|
|
149
|
+
// Check for region start
|
|
150
|
+
if (trimmed === `// #region ${removeMarker}`) {
|
|
151
|
+
removing = true;
|
|
152
|
+
continue; // Skip the marker line
|
|
153
|
+
}
|
|
154
|
+
// Check for region end
|
|
155
|
+
if (trimmed === `// #endregion ${removeMarker}`) {
|
|
156
|
+
removing = false;
|
|
157
|
+
continue; // Skip the marker line
|
|
158
|
+
}
|
|
159
|
+
// Check for keep markers (just remove the marker lines, keep content)
|
|
160
|
+
if (trimmed === `// #region ${keepMarker}` || trimmed === `// #endregion ${keepMarker}`) {
|
|
161
|
+
continue; // Skip marker line, content between them is kept naturally
|
|
162
|
+
}
|
|
163
|
+
// Skip content inside remove region
|
|
164
|
+
if (removing) {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
result.push(line);
|
|
168
|
+
}
|
|
169
|
+
// Clean up multiple consecutive blank lines (max 1)
|
|
170
|
+
return this.collapseBlankLines(result.join('\n'));
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Strip ALL markers (for Both mode) - keep all content
|
|
174
|
+
*/
|
|
175
|
+
stripAllMarkers(projectPath) {
|
|
176
|
+
const dirs = [(0, path_1.join)(projectPath, 'src'), (0, path_1.join)(projectPath, 'tests')];
|
|
177
|
+
for (const dir of dirs) {
|
|
178
|
+
if (!this.filesystem.exists(dir)) {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
const files = this.filesystem.find(dir, { matching: '**/*.ts' });
|
|
182
|
+
for (const file of files) {
|
|
183
|
+
const content = this.filesystem.read(file);
|
|
184
|
+
if (!content) {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
const lines = content.split('\n');
|
|
188
|
+
const filtered = lines.filter((line) => {
|
|
189
|
+
const trimmed = line.trim();
|
|
190
|
+
return !trimmed.match(/^\/\/ #(region|endregion)\s/);
|
|
191
|
+
});
|
|
192
|
+
const processed = filtered.join('\n');
|
|
193
|
+
if (processed !== content) {
|
|
194
|
+
this.filesystem.write(file, processed);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Modify config.env.ts for REST mode using ts-morph AST manipulation
|
|
201
|
+
*
|
|
202
|
+
* - Replace `graphQl: { ... }` blocks with `graphQl: false`
|
|
203
|
+
* - Remove `execAfterInit` properties
|
|
204
|
+
*/
|
|
205
|
+
modifyConfigEnvForRest(projectPath) {
|
|
206
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
207
|
+
var _a;
|
|
208
|
+
const configPath = (0, path_1.join)(projectPath, 'src', 'config.env.ts');
|
|
209
|
+
if (!this.filesystem.exists(configPath)) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
try {
|
|
213
|
+
const { Project, SyntaxKind } = require('ts-morph');
|
|
214
|
+
const project = new Project({ skipAddingFilesFromTsConfig: true });
|
|
215
|
+
const sourceFile = project.addSourceFileAtPath(configPath);
|
|
216
|
+
// Find the 'config' variable declaration directly
|
|
217
|
+
// Structure: export const config: { [env: string]: ... } = { ci: { ... }, develop: { ... }, ... };
|
|
218
|
+
let configObj;
|
|
219
|
+
const variableStatements = sourceFile.getVariableStatements();
|
|
220
|
+
for (const vs of variableStatements) {
|
|
221
|
+
for (const decl of vs.getDeclarations()) {
|
|
222
|
+
if (decl.getName() === 'config') {
|
|
223
|
+
const init = decl.getInitializer();
|
|
224
|
+
if ((init === null || init === void 0 ? void 0 : init.getKind()) === SyntaxKind.ObjectLiteralExpression) {
|
|
225
|
+
configObj = init;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// Handle merge() call: const config = merge({ default: ... }, { local: ... }, ...)
|
|
229
|
+
if (!configObj) {
|
|
230
|
+
const init = decl.getInitializer();
|
|
231
|
+
if ((init === null || init === void 0 ? void 0 : init.getKind()) === SyntaxKind.CallExpression) {
|
|
232
|
+
const args = (_a = init.getArguments) === null || _a === void 0 ? void 0 : _a.call(init);
|
|
233
|
+
if (args) {
|
|
234
|
+
for (const arg of args) {
|
|
235
|
+
if (arg.getKind() === SyntaxKind.ObjectLiteralExpression) {
|
|
236
|
+
this.processConfigObject(arg, SyntaxKind);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (configObj) {
|
|
245
|
+
this.processConfigObject(configObj, SyntaxKind);
|
|
246
|
+
}
|
|
247
|
+
sourceFile.saveSync();
|
|
248
|
+
}
|
|
249
|
+
catch (_b) {
|
|
250
|
+
// If ts-morph is not available or fails, fall back to regex
|
|
251
|
+
this.modifyConfigEnvForRestFallback(projectPath);
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Process a config object literal: replace graphQl and remove execAfterInit
|
|
257
|
+
*/
|
|
258
|
+
processConfigObject(obj, SyntaxKind) {
|
|
259
|
+
// Process all nested object literals (environment configs)
|
|
260
|
+
const properties = obj.getProperties();
|
|
261
|
+
for (const prop of properties) {
|
|
262
|
+
if (prop.getKind() !== SyntaxKind.PropertyAssignment) {
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
const name = prop.getName();
|
|
266
|
+
// Replace graphQl: { ... } with graphQl: false
|
|
267
|
+
if (name === 'graphQl') {
|
|
268
|
+
const init = prop.getInitializer();
|
|
269
|
+
if (init && init.getKind() === SyntaxKind.ObjectLiteralExpression) {
|
|
270
|
+
prop.setInitializer('false');
|
|
271
|
+
}
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
// Remove execAfterInit
|
|
275
|
+
if (name === 'execAfterInit') {
|
|
276
|
+
prop.remove();
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
// Recurse into nested objects (environment configs like default, local, etc.)
|
|
280
|
+
const init = prop.getInitializer();
|
|
281
|
+
if ((init === null || init === void 0 ? void 0 : init.getKind()) === SyntaxKind.ObjectLiteralExpression) {
|
|
282
|
+
this.processConfigObject(init, SyntaxKind);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Fallback: Regex-based config.env.ts modification
|
|
288
|
+
*/
|
|
289
|
+
modifyConfigEnvForRestFallback(projectPath) {
|
|
290
|
+
const configPath = (0, path_1.join)(projectPath, 'src', 'config.env.ts');
|
|
291
|
+
let content = this.filesystem.read(configPath);
|
|
292
|
+
if (!content) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
// Replace graphQl: { ... } blocks with graphQl: false
|
|
296
|
+
// Match graphQl: { ... }, handling nested braces
|
|
297
|
+
content = content.replace(/graphQl:\s*\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\},?/g, 'graphQl: false,');
|
|
298
|
+
// Remove execAfterInit lines
|
|
299
|
+
content = content.replace(/\s*execAfterInit:.*,?\n/g, '\n');
|
|
300
|
+
this.filesystem.write(configPath, content);
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Clean orphan imports after region stripping
|
|
304
|
+
*
|
|
305
|
+
* After removing region content, some imports may reference identifiers
|
|
306
|
+
* that no longer exist in the file. This removes those imports.
|
|
307
|
+
*/
|
|
308
|
+
cleanOrphanImports(projectPath) {
|
|
309
|
+
const dirs = [(0, path_1.join)(projectPath, 'src')];
|
|
310
|
+
for (const dir of dirs) {
|
|
311
|
+
if (!this.filesystem.exists(dir)) {
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
const files = this.filesystem.find(dir, { matching: '**/*.ts' });
|
|
315
|
+
for (const file of files) {
|
|
316
|
+
const content = this.filesystem.read(file);
|
|
317
|
+
if (!content) {
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
const cleaned = this.removeUnusedImports(content);
|
|
321
|
+
if (cleaned !== content) {
|
|
322
|
+
this.filesystem.write(file, cleaned);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Remove unused imports from TypeScript file content
|
|
329
|
+
*/
|
|
330
|
+
removeUnusedImports(content) {
|
|
331
|
+
const lines = content.split('\n');
|
|
332
|
+
const importLines = [];
|
|
333
|
+
// Parse import statements
|
|
334
|
+
let i = 0;
|
|
335
|
+
while (i < lines.length) {
|
|
336
|
+
const line = lines[i];
|
|
337
|
+
const singleImportMatch = line.match(/^import\s+\{([^}]+)\}\s+from\s+['"]/);
|
|
338
|
+
const multiImportStart = line.match(/^import\s+\{$/);
|
|
339
|
+
if (singleImportMatch) {
|
|
340
|
+
const imports = singleImportMatch[1].split(',')
|
|
341
|
+
.map((s) => s.trim())
|
|
342
|
+
.filter(Boolean)
|
|
343
|
+
.map((s) => ({ original: s, resolved: this.resolveImportAlias(s) }));
|
|
344
|
+
importLines.push({ end: i, imports, start: i });
|
|
345
|
+
}
|
|
346
|
+
else if (multiImportStart) {
|
|
347
|
+
// Multi-line import
|
|
348
|
+
const start = i;
|
|
349
|
+
const imports = [];
|
|
350
|
+
i++;
|
|
351
|
+
while (i < lines.length && !lines[i].match(/^\}\s+from\s+['"]/)) {
|
|
352
|
+
const raw = lines[i].replace(/,?\s*$/, '').trim();
|
|
353
|
+
if (raw) {
|
|
354
|
+
imports.push({ original: raw, resolved: this.resolveImportAlias(raw) });
|
|
355
|
+
}
|
|
356
|
+
i++;
|
|
357
|
+
}
|
|
358
|
+
importLines.push({ end: i, imports, start });
|
|
359
|
+
}
|
|
360
|
+
i++;
|
|
361
|
+
}
|
|
362
|
+
// Get the non-import part of the file
|
|
363
|
+
const maxImportEnd = importLines.reduce((max, il) => Math.max(max, il.end), -1);
|
|
364
|
+
const codeContent = lines.slice(maxImportEnd + 1).join('\n');
|
|
365
|
+
// Check each import
|
|
366
|
+
const linesToRemove = new Set();
|
|
367
|
+
for (const imp of importLines) {
|
|
368
|
+
const usedImports = imp.imports.filter(({ resolved }) => {
|
|
369
|
+
// Check if resolved identifier is used in code (not in imports)
|
|
370
|
+
const regex = new RegExp(`\\b${resolved.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`);
|
|
371
|
+
return regex.test(codeContent);
|
|
372
|
+
});
|
|
373
|
+
if (usedImports.length === 0) {
|
|
374
|
+
// Remove entire import
|
|
375
|
+
for (let j = imp.start; j <= imp.end; j++) {
|
|
376
|
+
linesToRemove.add(j);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
else if (usedImports.length < imp.imports.length) {
|
|
380
|
+
// Rebuild import with only used identifiers (using original text for aliases)
|
|
381
|
+
const fromMatch = lines[imp.end].match(/from\s+['"].*['"]/);
|
|
382
|
+
const fromClause = fromMatch ? fromMatch[0] : '';
|
|
383
|
+
if (fromClause) {
|
|
384
|
+
// Remove old lines
|
|
385
|
+
for (let j = imp.start; j <= imp.end; j++) {
|
|
386
|
+
linesToRemove.add(j);
|
|
387
|
+
}
|
|
388
|
+
const originals = usedImports.map((ui) => ui.original);
|
|
389
|
+
// Add rebuilt import at start position
|
|
390
|
+
if (originals.length <= 3) {
|
|
391
|
+
lines[imp.start] = `import { ${originals.join(', ')} } ${fromClause};`;
|
|
392
|
+
linesToRemove.delete(imp.start);
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
// Multi-line for many imports
|
|
396
|
+
lines[imp.start] = `import {\n ${originals.join(',\n ')},\n} ${fromClause};`;
|
|
397
|
+
linesToRemove.delete(imp.start);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
// Remove marked lines
|
|
403
|
+
const result = lines.filter((_, idx) => !linesToRemove.has(idx));
|
|
404
|
+
return this.collapseBlankLines(result.join('\n'));
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Resolve import alias: "Schema as MongooseSchema" -> "MongooseSchema"
|
|
408
|
+
* For non-aliased imports, returns the identifier as-is.
|
|
409
|
+
*/
|
|
410
|
+
resolveImportAlias(identifier) {
|
|
411
|
+
const asMatch = identifier.match(/^\S+\s+as\s+(\S+)$/);
|
|
412
|
+
return asMatch ? asMatch[1] : identifier;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Collapse multiple consecutive blank lines into at most one
|
|
416
|
+
*/
|
|
417
|
+
collapseBlankLines(content) {
|
|
418
|
+
return content.replace(/\n{3,}/g, '\n\n');
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Remove a script from package.json
|
|
422
|
+
*/
|
|
423
|
+
removeScriptFromPackageJson(projectPath, scriptName) {
|
|
424
|
+
var _a;
|
|
425
|
+
const pkgPath = (0, path_1.join)(projectPath, 'package.json');
|
|
426
|
+
const pkg = JSON.parse(this.filesystem.read(pkgPath));
|
|
427
|
+
if ((_a = pkg.scripts) === null || _a === void 0 ? void 0 : _a[scriptName]) {
|
|
428
|
+
delete pkg.scripts[scriptName];
|
|
429
|
+
this.filesystem.write(pkgPath, pkg, { jsonIndent: 2 });
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
exports.ApiMode = ApiMode;
|
|
434
|
+
/**
|
|
435
|
+
* Extend toolbox
|
|
436
|
+
*/
|
|
437
|
+
exports.default = (toolbox) => {
|
|
438
|
+
toolbox.apiMode = new ApiMode(toolbox);
|
|
439
|
+
};
|
|
440
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBpLW1vZGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZXh0ZW5zaW9ucy9hcGktbW9kZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7QUFDQSwrQkFBNEI7QUFJNUI7Ozs7O0dBS0c7QUFDSCxNQUFhLE9BQU87SUFHbEIsWUFBc0IsT0FBK0I7UUFBL0IsWUFBTyxHQUFQLE9BQU8sQ0FBd0I7UUFDbkQsSUFBSSxDQUFDLFVBQVUsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDO0lBQ3ZDLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNHLGNBQWMsQ0FBQyxXQUFtQixFQUFFLElBQWlDOztZQUN6RSxNQUFNLFlBQVksR0FBRyxJQUFBLFdBQUksRUFBQyxXQUFXLEVBQUUsd0JBQXdCLENBQUMsQ0FBQztZQUVqRSxnQkFBZ0I7WUFDaEIsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDM0QsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO2dCQUNyQixPQUFPLENBQUMsOEJBQThCO1lBQ3hDLENBQUM7WUFFRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBRTdDLElBQUksSUFBSSxLQUFLLE1BQU0sRUFBRSxDQUFDO2dCQUNwQiw2Q0FBNkM7Z0JBQzdDLElBQUksQ0FBQyxlQUFlLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDcEMsQ0FBQztpQkFBTSxJQUFJLElBQUksS0FBSyxNQUFNLEVBQUUsQ0FBQztnQkFDM0IsdURBQXVEO2dCQUN2RCxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsTUFBTSxDQUFDLENBQUM7Z0JBQ2hFLE1BQU0sSUFBSSxDQUFDLHNCQUFzQixDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ2pELENBQUM7aUJBQU0sSUFBSSxJQUFJLEtBQUssU0FB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
|