slicejs-cli 2.8.6 → 2.9.1
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/README.md +347 -315
- package/client.js +526 -539
- package/commands/Print.js +167 -167
- package/commands/Validations.js +103 -103
- package/commands/build/build.js +40 -0
- package/commands/buildProduction/buildProduction.js +45 -10
- package/commands/bundle/bundle.js +235 -231
- package/commands/createComponent/VisualComponentTemplate.js +55 -55
- package/commands/createComponent/createComponent.js +126 -126
- package/commands/deleteComponent/deleteComponent.js +77 -77
- package/commands/doctor/doctor.js +369 -369
- package/commands/getComponent/getComponent.js +747 -747
- package/commands/init/init.js +261 -261
- package/commands/listComponents/listComponents.js +175 -175
- package/commands/startServer/startServer.js +260 -270
- package/commands/startServer/watchServer.js +79 -79
- package/commands/utils/PathHelper.js +68 -68
- package/commands/utils/VersionChecker.js +167 -167
- package/commands/utils/bundling/BundleGenerator.js +1331 -783
- package/commands/utils/bundling/DependencyAnalyzer.js +859 -679
- package/commands/utils/updateManager.js +437 -384
- package/package.json +46 -46
- package/post.js +25 -25
- package/refactor.md +271 -271
- package/tests/bundle-generator.test.js +38 -0
- package/tests/dependency-analyzer.test.js +24 -0
|
@@ -1,384 +1,437 @@
|
|
|
1
|
-
// commands/utils/updateManager.js
|
|
2
|
-
|
|
3
|
-
import { exec } from "child_process";
|
|
4
|
-
import { promisify } from "util";
|
|
5
|
-
import inquirer from "inquirer";
|
|
6
|
-
import ora from "ora";
|
|
7
|
-
import Print from "../Print.js";
|
|
8
|
-
import versionChecker from "./VersionChecker.js";
|
|
9
|
-
import { getProjectRoot } from "../utils/PathHelper.js";
|
|
10
|
-
import path from "path";
|
|
11
|
-
import { fileURLToPath } from "url";
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
updates,
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
console.log(`
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
console.log('
|
|
108
|
-
console.log('');
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
let
|
|
189
|
-
let
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
console.log(`
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
console.log(`
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
console.log('');
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
const
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
1
|
+
// commands/utils/updateManager.js
|
|
2
|
+
|
|
3
|
+
import { exec } from "child_process";
|
|
4
|
+
import { promisify } from "util";
|
|
5
|
+
import inquirer from "inquirer";
|
|
6
|
+
import ora from "ora";
|
|
7
|
+
import Print from "../Print.js";
|
|
8
|
+
import versionChecker from "./VersionChecker.js";
|
|
9
|
+
import { getProjectRoot } from "../utils/PathHelper.js";
|
|
10
|
+
import path from "path";
|
|
11
|
+
import { fileURLToPath } from "url";
|
|
12
|
+
import fs from "fs-extra";
|
|
13
|
+
|
|
14
|
+
const execAsync = promisify(exec);
|
|
15
|
+
|
|
16
|
+
class UpdateManager {
|
|
17
|
+
constructor() {
|
|
18
|
+
this.packagesToUpdate = [];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async detectCliInstall() {
|
|
22
|
+
try {
|
|
23
|
+
const moduleDir = path.dirname(fileURLToPath(import.meta.url));
|
|
24
|
+
const cliRoot = path.join(moduleDir, '../../');
|
|
25
|
+
const projectRoot = getProjectRoot(import.meta.url);
|
|
26
|
+
let globalPrefix = '';
|
|
27
|
+
try {
|
|
28
|
+
const { stdout } = await execAsync('npm config get prefix');
|
|
29
|
+
globalPrefix = stdout.toString().trim();
|
|
30
|
+
} catch {}
|
|
31
|
+
const localNodeModules = path.join(projectRoot, 'node_modules');
|
|
32
|
+
const globalNodeModules = globalPrefix ? path.join(globalPrefix, 'node_modules') : '';
|
|
33
|
+
|
|
34
|
+
if (cliRoot.startsWith(localNodeModules)) {
|
|
35
|
+
return { type: 'local', cliRoot, projectRoot, globalPrefix };
|
|
36
|
+
}
|
|
37
|
+
if (globalNodeModules && cliRoot.startsWith(globalNodeModules)) {
|
|
38
|
+
return { type: 'global', cliRoot, projectRoot, globalPrefix };
|
|
39
|
+
}
|
|
40
|
+
return { type: 'unknown', cliRoot, projectRoot, globalPrefix };
|
|
41
|
+
} catch (error) {
|
|
42
|
+
return { type: 'unknown' };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Check for available updates and return structured info
|
|
48
|
+
*/
|
|
49
|
+
async checkForUpdates() {
|
|
50
|
+
try {
|
|
51
|
+
const updateInfo = await versionChecker.checkForUpdates(true); // Silent mode
|
|
52
|
+
|
|
53
|
+
if (!updateInfo) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const updates = [];
|
|
58
|
+
|
|
59
|
+
if (updateInfo.cli.status === 'outdated') {
|
|
60
|
+
updates.push({
|
|
61
|
+
name: 'slicejs-cli',
|
|
62
|
+
displayName: 'Slice.js CLI',
|
|
63
|
+
current: updateInfo.cli.current,
|
|
64
|
+
latest: updateInfo.cli.latest,
|
|
65
|
+
type: 'cli'
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (updateInfo.framework.status === 'outdated') {
|
|
70
|
+
updates.push({
|
|
71
|
+
name: 'slicejs-web-framework',
|
|
72
|
+
displayName: 'Slice.js Framework',
|
|
73
|
+
current: updateInfo.framework.current,
|
|
74
|
+
latest: updateInfo.framework.latest,
|
|
75
|
+
type: 'framework'
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
hasUpdates: updates.length > 0,
|
|
81
|
+
updates,
|
|
82
|
+
allCurrent: updateInfo.cli.status === 'current' && updateInfo.framework.status === 'current'
|
|
83
|
+
};
|
|
84
|
+
} catch (error) {
|
|
85
|
+
Print.error(`Checking for updates: ${error.message}`);
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Display available updates in a formatted way
|
|
92
|
+
*/
|
|
93
|
+
displayUpdates(updateInfo) {
|
|
94
|
+
if (!updateInfo || !updateInfo.hasUpdates) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
console.log('');
|
|
99
|
+
Print.warning('📦 Available Updates:');
|
|
100
|
+
console.log('');
|
|
101
|
+
|
|
102
|
+
updateInfo.updates.forEach(pkg => {
|
|
103
|
+
console.log(` ${pkg.type === 'cli' ? '🔧' : '⚡'} ${pkg.displayName}`);
|
|
104
|
+
console.log(` ${pkg.current} → ${pkg.latest}`);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
console.log('');
|
|
108
|
+
console.log(' 📚 Changelog: https://github.com/VKneider/slice.js/releases');
|
|
109
|
+
console.log('');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Prompt user to select which packages to update
|
|
114
|
+
*/
|
|
115
|
+
async promptForUpdates(updateInfo, options = {}) {
|
|
116
|
+
if (!updateInfo || !updateInfo.hasUpdates) {
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// If --yes flag is set, return all updates
|
|
121
|
+
if (options.yes) {
|
|
122
|
+
return updateInfo.updates.map(pkg => pkg.name);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// If specific package flags are set
|
|
126
|
+
if (options.cli || options.framework) {
|
|
127
|
+
const selected = [];
|
|
128
|
+
if (options.cli) {
|
|
129
|
+
const cliUpdate = updateInfo.updates.find(pkg => pkg.type === 'cli');
|
|
130
|
+
if (cliUpdate) selected.push(cliUpdate.name);
|
|
131
|
+
}
|
|
132
|
+
if (options.framework) {
|
|
133
|
+
const frameworkUpdate = updateInfo.updates.find(pkg => pkg.type === 'framework');
|
|
134
|
+
if (frameworkUpdate) selected.push(frameworkUpdate.name);
|
|
135
|
+
}
|
|
136
|
+
return selected;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Interactive selection
|
|
140
|
+
const choices = updateInfo.updates.map(pkg => ({
|
|
141
|
+
name: `${pkg.displayName} (${pkg.current} → ${pkg.latest})`,
|
|
142
|
+
value: pkg.name,
|
|
143
|
+
checked: true
|
|
144
|
+
}));
|
|
145
|
+
|
|
146
|
+
const answers = await inquirer.prompt([
|
|
147
|
+
{
|
|
148
|
+
type: 'checkbox',
|
|
149
|
+
name: 'packages',
|
|
150
|
+
message: 'Which packages do you want to update?',
|
|
151
|
+
choices,
|
|
152
|
+
validate: (answer) => {
|
|
153
|
+
if (answer.length === 0) {
|
|
154
|
+
return 'You must select at least one package';
|
|
155
|
+
}
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
]);
|
|
160
|
+
|
|
161
|
+
return answers.packages;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async buildUpdatePlan(packages) {
|
|
165
|
+
const plan = [];
|
|
166
|
+
const info = await this.detectCliInstall();
|
|
167
|
+
for (const pkg of packages) {
|
|
168
|
+
if (pkg === 'slicejs-cli') {
|
|
169
|
+
if (info.type === 'global') {
|
|
170
|
+
plan.push({ package: pkg, target: 'global', command: 'npm install -g slicejs-cli@latest' });
|
|
171
|
+
} else {
|
|
172
|
+
plan.push({ package: pkg, target: 'project', command: 'npm install slicejs-cli@latest' });
|
|
173
|
+
}
|
|
174
|
+
} else if (pkg === 'slicejs-web-framework') {
|
|
175
|
+
plan.push({ package: pkg, target: 'project', command: 'npm install slicejs-web-framework@latest' });
|
|
176
|
+
} else {
|
|
177
|
+
plan.push({ package: pkg, target: 'project', command: `npm install ${pkg}@latest` });
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return plan;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Execute npm update command for a specific package
|
|
185
|
+
*/
|
|
186
|
+
async updatePackage(packageName) {
|
|
187
|
+
try {
|
|
188
|
+
let installCmd = `npm install ${packageName}@latest`;
|
|
189
|
+
let uninstallCmd = `npm uninstall ${packageName}`;
|
|
190
|
+
let options = {};
|
|
191
|
+
|
|
192
|
+
if (packageName === 'slicejs-cli') {
|
|
193
|
+
const info = await this.detectCliInstall();
|
|
194
|
+
if (info.type === 'global') {
|
|
195
|
+
installCmd = `npm install -g slicejs-cli@latest`;
|
|
196
|
+
uninstallCmd = `npm uninstall -g slicejs-cli`;
|
|
197
|
+
} else {
|
|
198
|
+
options.cwd = info.projectRoot || getProjectRoot(import.meta.url);
|
|
199
|
+
}
|
|
200
|
+
} else {
|
|
201
|
+
options.cwd = getProjectRoot(import.meta.url);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Try uninstall first (ignore failure)
|
|
205
|
+
try {
|
|
206
|
+
await execAsync(uninstallCmd, options);
|
|
207
|
+
} catch {}
|
|
208
|
+
|
|
209
|
+
const { stdout, stderr } = await execAsync(installCmd, options);
|
|
210
|
+
|
|
211
|
+
return {
|
|
212
|
+
success: true,
|
|
213
|
+
packageName,
|
|
214
|
+
stdout,
|
|
215
|
+
stderr
|
|
216
|
+
};
|
|
217
|
+
} catch (error) {
|
|
218
|
+
return {
|
|
219
|
+
success: false,
|
|
220
|
+
packageName,
|
|
221
|
+
error: error.message
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Update multiple packages with progress indication
|
|
228
|
+
*/
|
|
229
|
+
async installUpdates(packages) {
|
|
230
|
+
const results = [];
|
|
231
|
+
|
|
232
|
+
for (const packageName of packages) {
|
|
233
|
+
const spinner = ora(`Updating ${packageName}...`).start();
|
|
234
|
+
|
|
235
|
+
try {
|
|
236
|
+
const result = await this.updatePackage(packageName);
|
|
237
|
+
|
|
238
|
+
if (result.success) {
|
|
239
|
+
spinner.succeed(`${packageName} updated successfully`);
|
|
240
|
+
results.push({ packageName, success: true });
|
|
241
|
+
} else {
|
|
242
|
+
spinner.fail(`Error updating ${packageName}`);
|
|
243
|
+
Print.error(`Details: ${result.error}`);
|
|
244
|
+
results.push({ packageName, success: false, error: result.error });
|
|
245
|
+
}
|
|
246
|
+
} catch (error) {
|
|
247
|
+
spinner.fail(`Error updating ${packageName}`);
|
|
248
|
+
Print.error(`Details: ${error.message}`);
|
|
249
|
+
results.push({ packageName, success: false, error: error.message });
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return results;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Main method to check and prompt for updates
|
|
258
|
+
*/
|
|
259
|
+
async checkAndPromptUpdates(options = {}) {
|
|
260
|
+
const spinner = ora('Checking for updates...').start();
|
|
261
|
+
|
|
262
|
+
try {
|
|
263
|
+
const updateInfo = await this.checkForUpdates();
|
|
264
|
+
spinner.stop();
|
|
265
|
+
|
|
266
|
+
if (!updateInfo) {
|
|
267
|
+
Print.error('Could not check for updates. Verify your internet connection.');
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (updateInfo.allCurrent) {
|
|
272
|
+
Print.success('✅ All components are up to date!');
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (!updateInfo.hasUpdates) {
|
|
277
|
+
Print.success('✅ All components are up to date!');
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Display available updates
|
|
282
|
+
this.displayUpdates(updateInfo);
|
|
283
|
+
|
|
284
|
+
// Get packages to update
|
|
285
|
+
const packagesToUpdate = await this.promptForUpdates(updateInfo, options);
|
|
286
|
+
|
|
287
|
+
if (!packagesToUpdate || packagesToUpdate.length === 0) {
|
|
288
|
+
Print.info('No packages selected for update.');
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Show plan and confirm installation if not auto-confirmed
|
|
293
|
+
let plan = await this.buildUpdatePlan(packagesToUpdate);
|
|
294
|
+
console.log('');
|
|
295
|
+
Print.info('🧭 Update plan:');
|
|
296
|
+
plan.forEach(item => {
|
|
297
|
+
const where = item.target === 'global' ? 'GLOBAL' : 'PROJECT';
|
|
298
|
+
console.log(` • ${item.package} → ${where}`);
|
|
299
|
+
console.log(` ${item.command}`);
|
|
300
|
+
});
|
|
301
|
+
console.log('');
|
|
302
|
+
|
|
303
|
+
const cliInfo = await this.detectCliInstall();
|
|
304
|
+
if (cliInfo.type === 'global' && !packagesToUpdate.includes('slicejs-cli')) {
|
|
305
|
+
if (!options.yes && !options.cli) {
|
|
306
|
+
const { addCli } = await inquirer.prompt([
|
|
307
|
+
{
|
|
308
|
+
type: 'confirm',
|
|
309
|
+
name: 'addCli',
|
|
310
|
+
message: 'Global CLI detected. Add the global CLI update to the plan?',
|
|
311
|
+
default: true
|
|
312
|
+
}
|
|
313
|
+
]);
|
|
314
|
+
if (addCli) {
|
|
315
|
+
packagesToUpdate.push('slicejs-cli');
|
|
316
|
+
plan = await this.buildUpdatePlan(packagesToUpdate);
|
|
317
|
+
console.log('');
|
|
318
|
+
Print.info('🧭 Updated plan:');
|
|
319
|
+
plan.forEach(item => {
|
|
320
|
+
const where = item.target === 'global' ? 'GLOBAL' : 'PROJECT';
|
|
321
|
+
console.log(` • ${item.package} → ${where}`);
|
|
322
|
+
console.log(` ${item.command}`);
|
|
323
|
+
});
|
|
324
|
+
console.log('');
|
|
325
|
+
}
|
|
326
|
+
} else {
|
|
327
|
+
Print.warning('Global CLI detected. It is recommended to update slicejs-cli globally to keep aligned with the framework.');
|
|
328
|
+
console.log(' Suggestion: npm install -g slicejs-cli@latest');
|
|
329
|
+
console.log('');
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (!options.yes && !options.cli && !options.framework) {
|
|
334
|
+
const { confirm } = await inquirer.prompt([
|
|
335
|
+
{
|
|
336
|
+
type: 'confirm',
|
|
337
|
+
name: 'confirm',
|
|
338
|
+
message: 'Do you want to proceed with the update according to the plan shown?',
|
|
339
|
+
default: true
|
|
340
|
+
}
|
|
341
|
+
]);
|
|
342
|
+
|
|
343
|
+
if (!confirm) {
|
|
344
|
+
Print.info('Update cancelled.');
|
|
345
|
+
return false;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
console.log(''); // Line break
|
|
350
|
+
Print.info('📥 Installing updates...');
|
|
351
|
+
console.log('');
|
|
352
|
+
|
|
353
|
+
// Install updates
|
|
354
|
+
const results = await this.installUpdates(packagesToUpdate);
|
|
355
|
+
|
|
356
|
+
// Summary
|
|
357
|
+
console.log('');
|
|
358
|
+
const successCount = results.filter(r => r.success).length;
|
|
359
|
+
const failCount = results.filter(r => !r.success).length;
|
|
360
|
+
|
|
361
|
+
if (failCount === 0) {
|
|
362
|
+
Print.success(`✅ ${successCount} package(s) updated successfully!`);
|
|
363
|
+
} else {
|
|
364
|
+
Print.warning(`⚠️ ${successCount} successful, ${failCount} failed`);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (successCount > 0) {
|
|
368
|
+
console.log('');
|
|
369
|
+
Print.info('💡 It is recommended to restart the development server if it is running.');
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const frameworkUpdated = results.find(r => r.packageName === 'slicejs-web-framework' && r.success);
|
|
373
|
+
if (frameworkUpdated) {
|
|
374
|
+
await this.updateApiIndexIfNeeded(options);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return failCount === 0;
|
|
378
|
+
|
|
379
|
+
} catch (error) {
|
|
380
|
+
spinner.stop();
|
|
381
|
+
Print.error(`Error during update: ${error.message}`);
|
|
382
|
+
return false;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
async updateApiIndexIfNeeded(options = {}) {
|
|
387
|
+
try {
|
|
388
|
+
const projectRoot = getProjectRoot(import.meta.url);
|
|
389
|
+
const projectApiPath = path.join(projectRoot, 'api', 'index.js');
|
|
390
|
+
const frameworkApiPath = path.join(projectRoot, 'node_modules', 'slicejs-web-framework', 'api', 'index.js');
|
|
391
|
+
|
|
392
|
+
if (!await fs.pathExists(projectApiPath) || !await fs.pathExists(frameworkApiPath)) {
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const projectContent = await fs.readFile(projectApiPath, 'utf-8');
|
|
397
|
+
const frameworkContent = await fs.readFile(frameworkApiPath, 'utf-8');
|
|
398
|
+
|
|
399
|
+
if (projectContent === frameworkContent) {
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
Print.warning('⚠️ Detected changes in framework api/index.js.');
|
|
404
|
+
|
|
405
|
+
let confirmUpdate = options.yes === true;
|
|
406
|
+
if (!confirmUpdate) {
|
|
407
|
+
const answers = await inquirer.prompt([
|
|
408
|
+
{
|
|
409
|
+
type: 'confirm',
|
|
410
|
+
name: 'confirm',
|
|
411
|
+
message: 'Update your project api/index.js to the latest framework version?',
|
|
412
|
+
default: false
|
|
413
|
+
}
|
|
414
|
+
]);
|
|
415
|
+
confirmUpdate = answers.confirm;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
if (!confirmUpdate) {
|
|
419
|
+
Print.info('Skipping api/index.js update.');
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const backupPath = `${projectApiPath}.bak`;
|
|
424
|
+
await fs.copy(projectApiPath, backupPath);
|
|
425
|
+
await fs.writeFile(projectApiPath, frameworkContent, 'utf-8');
|
|
426
|
+
Print.success('✅ api/index.js updated from framework template.');
|
|
427
|
+
Print.info(`Backup created at ${backupPath}`);
|
|
428
|
+
} catch (error) {
|
|
429
|
+
Print.error(`Failed to update api/index.js: ${error.message}`);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// Singleton instance
|
|
435
|
+
const updateManager = new UpdateManager();
|
|
436
|
+
|
|
437
|
+
export default updateManager;
|