@dalexto/lexsys-cli 0.0.2 → 0.0.4
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 +8 -15
- package/dist/commands/reset.d.ts +1 -0
- package/dist/config/config.d.ts +1 -1
- package/dist/config/installed.d.ts +6 -0
- package/dist/index.js +557 -477
- package/dist/install/component-drift.d.ts +4 -0
- package/dist/install/installer.d.ts +1 -1
- package/dist/install/results.d.ts +10 -0
- package/dist/install/target.d.ts +0 -1
- package/dist/install/update-engine.d.ts +3 -1
- package/dist/registry/closure.d.ts +1 -1
- package/dist/scaffold/scaffold-helpers.d.ts +4 -0
- package/dist/{core → utils}/fs.d.ts +0 -1
- package/dist/utils/prompt.d.ts +9 -0
- package/package.json +2 -2
- package/dist/install/uninstall-results.d.ts +0 -10
- package/dist/utils/version.d.ts +0 -2
- /package/dist/{core → utils}/backup.d.ts +0 -0
- /package/dist/{core → utils}/cli-error.d.ts +0 -0
- /package/dist/{core → utils}/context.d.ts +0 -0
- /package/dist/{core → utils}/flags.d.ts +0 -0
- /package/dist/{core → utils}/hash.d.ts +0 -0
package/dist/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import prompts from 'prompts';
|
|
3
2
|
import { registryManifest, getInstallLayer, registryItems, validateRegistry, registryStyles, registryVersion, validateRegistryItem, registryUtilities as registryUtilities$1 } from '@dalexto/lexsys-registry';
|
|
4
3
|
import { readFile, access, mkdir, copyFile, writeFile, unlink, readdir, rm } from 'fs/promises';
|
|
5
4
|
import { dirname, join, resolve, relative, basename } from 'path';
|
|
@@ -7,8 +6,9 @@ import { createHash } from 'crypto';
|
|
|
7
6
|
import { constants } from 'fs';
|
|
8
7
|
import { fileURLToPath } from 'url';
|
|
9
8
|
import { execFileSync } from 'child_process';
|
|
9
|
+
import prompts from 'prompts';
|
|
10
10
|
|
|
11
|
-
// src/
|
|
11
|
+
// src/utils/cli-error.ts
|
|
12
12
|
var CliError = class extends Error {
|
|
13
13
|
suggestion;
|
|
14
14
|
constructor(message, suggestion) {
|
|
@@ -37,6 +37,38 @@ var handleCliError = (error) => {
|
|
|
37
37
|
}
|
|
38
38
|
process.exit(1);
|
|
39
39
|
};
|
|
40
|
+
|
|
41
|
+
// src/config/installed.ts
|
|
42
|
+
var isLegacyInstalledRecord = (value) => {
|
|
43
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
44
|
+
};
|
|
45
|
+
var normalizeInstalled = (value) => {
|
|
46
|
+
if (Array.isArray(value)) {
|
|
47
|
+
return value.filter((entry) => typeof entry === "string");
|
|
48
|
+
}
|
|
49
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
50
|
+
return Object.keys(value);
|
|
51
|
+
}
|
|
52
|
+
return [];
|
|
53
|
+
};
|
|
54
|
+
var isInstalled = (installed, name) => {
|
|
55
|
+
const normalized = name.toLowerCase();
|
|
56
|
+
return installed.some((entry) => entry.toLowerCase() === normalized);
|
|
57
|
+
};
|
|
58
|
+
var addInstalled = (installed, itemName) => {
|
|
59
|
+
if (isInstalled(installed, itemName)) {
|
|
60
|
+
return installed;
|
|
61
|
+
}
|
|
62
|
+
return [...installed, itemName];
|
|
63
|
+
};
|
|
64
|
+
var removeInstalled = (installed, itemName) => {
|
|
65
|
+
const normalized = itemName.toLowerCase();
|
|
66
|
+
return installed.filter((entry) => entry.toLowerCase() !== normalized);
|
|
67
|
+
};
|
|
68
|
+
var findInstalledKey = (installed, name) => {
|
|
69
|
+
const normalized = name.toLowerCase();
|
|
70
|
+
return installed.find((entry) => entry.toLowerCase() === normalized);
|
|
71
|
+
};
|
|
40
72
|
var hashContent = (content) => {
|
|
41
73
|
return createHash("sha256").update(content, "utf-8").digest("hex");
|
|
42
74
|
};
|
|
@@ -67,7 +99,7 @@ var filesAreEqual = async (sourcePath, targetPath) => {
|
|
|
67
99
|
return sourceHash === targetHash;
|
|
68
100
|
};
|
|
69
101
|
|
|
70
|
-
// src/
|
|
102
|
+
// src/utils/context.ts
|
|
71
103
|
var currentWorkingDirectory = process.cwd();
|
|
72
104
|
var setCwd = (cwd2) => {
|
|
73
105
|
currentWorkingDirectory = cwd2;
|
|
@@ -98,7 +130,7 @@ var defaultConfig = {
|
|
|
98
130
|
paths: defaultPathsConfig,
|
|
99
131
|
aliases: defaultAliasesConfig,
|
|
100
132
|
tailwind: defaultTailwindConfig,
|
|
101
|
-
installed:
|
|
133
|
+
installed: [],
|
|
102
134
|
registryUrl: null
|
|
103
135
|
};
|
|
104
136
|
var getConfigPath = () => {
|
|
@@ -111,7 +143,7 @@ var loadConfig = async () => {
|
|
|
111
143
|
}
|
|
112
144
|
const content = await readFile(configPath, "utf-8");
|
|
113
145
|
const parsed = JSON.parse(content);
|
|
114
|
-
|
|
146
|
+
const config = {
|
|
115
147
|
...defaultConfig,
|
|
116
148
|
...parsed,
|
|
117
149
|
paths: {
|
|
@@ -125,8 +157,13 @@ var loadConfig = async () => {
|
|
|
125
157
|
tailwind: {
|
|
126
158
|
...defaultTailwindConfig,
|
|
127
159
|
...parsed.tailwind
|
|
128
|
-
}
|
|
160
|
+
},
|
|
161
|
+
installed: normalizeInstalled(parsed.installed)
|
|
129
162
|
};
|
|
163
|
+
if (isLegacyInstalledRecord(parsed.installed)) {
|
|
164
|
+
await saveConfig(config);
|
|
165
|
+
}
|
|
166
|
+
return config;
|
|
130
167
|
};
|
|
131
168
|
var saveConfig = async (config) => {
|
|
132
169
|
const configPath = getConfigPath();
|
|
@@ -191,12 +228,10 @@ var validateTemplateFiles = async (item) => {
|
|
|
191
228
|
|
|
192
229
|
// src/install/results.ts
|
|
193
230
|
var createInstallResourceResult = () => {
|
|
194
|
-
return {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
conflicted: []
|
|
199
|
-
};
|
|
231
|
+
return { created: [], updated: [], skipped: [], conflicted: [] };
|
|
232
|
+
};
|
|
233
|
+
var createUninstallResourceResult = () => {
|
|
234
|
+
return { removed: [], skipped: [], conflicted: [], missing: [] };
|
|
200
235
|
};
|
|
201
236
|
var mergeInstallResults = (results) => {
|
|
202
237
|
return results.reduce(
|
|
@@ -209,33 +244,6 @@ var mergeInstallResults = (results) => {
|
|
|
209
244
|
createInstallResourceResult()
|
|
210
245
|
);
|
|
211
246
|
};
|
|
212
|
-
var hasInstallConflicts = (result) => {
|
|
213
|
-
return result.conflicted.length > 0;
|
|
214
|
-
};
|
|
215
|
-
var printResourceSummary = (label, result) => {
|
|
216
|
-
const total = result.created.length + result.updated.length + result.skipped.length + result.conflicted.length;
|
|
217
|
-
if (!total) {
|
|
218
|
-
console.log(`- ${label}: no changes`);
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
const parts = [
|
|
222
|
-
result.created.length ? `${result.created.length} created` : void 0,
|
|
223
|
-
result.updated.length ? `${result.updated.length} updated` : void 0,
|
|
224
|
-
result.skipped.length ? `${result.skipped.length} skipped` : void 0,
|
|
225
|
-
result.conflicted.length ? `${result.conflicted.length} conflicted` : void 0
|
|
226
|
-
].filter((part) => typeof part === "string");
|
|
227
|
-
console.log(`- ${label}: ${parts.join(", ")}`);
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
// src/install/uninstall-results.ts
|
|
231
|
-
var createUninstallResourceResult = () => {
|
|
232
|
-
return {
|
|
233
|
-
removed: [],
|
|
234
|
-
skipped: [],
|
|
235
|
-
conflicted: [],
|
|
236
|
-
missing: []
|
|
237
|
-
};
|
|
238
|
-
};
|
|
239
247
|
var mergeUninstallResults = (results) => {
|
|
240
248
|
return results.reduce(
|
|
241
249
|
(merged, result) => ({
|
|
@@ -247,21 +255,39 @@ var mergeUninstallResults = (results) => {
|
|
|
247
255
|
createUninstallResourceResult()
|
|
248
256
|
);
|
|
249
257
|
};
|
|
258
|
+
var hasInstallConflicts = (result) => {
|
|
259
|
+
return result.conflicted.length > 0;
|
|
260
|
+
};
|
|
250
261
|
var hasUninstallConflicts = (result) => {
|
|
251
262
|
return result.conflicted.length > 0;
|
|
252
263
|
};
|
|
264
|
+
var formatParts = (parts) => {
|
|
265
|
+
return parts.filter((p) => p.count > 0).map((p) => `${p.count} ${p.label}`);
|
|
266
|
+
};
|
|
267
|
+
var printResourceSummary = (label, result) => {
|
|
268
|
+
const parts = formatParts([
|
|
269
|
+
{ label: "created", count: result.created.length },
|
|
270
|
+
{ label: "updated", count: result.updated.length },
|
|
271
|
+
{ label: "skipped", count: result.skipped.length },
|
|
272
|
+
{ label: "conflicted", count: result.conflicted.length }
|
|
273
|
+
]);
|
|
274
|
+
if (!parts.length) {
|
|
275
|
+
console.log(`- ${label}: no changes`);
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
console.log(`- ${label}: ${parts.join(", ")}`);
|
|
279
|
+
};
|
|
253
280
|
var printUninstallSummary = (label, result) => {
|
|
254
|
-
const
|
|
255
|
-
|
|
281
|
+
const parts = formatParts([
|
|
282
|
+
{ label: "removed", count: result.removed.length },
|
|
283
|
+
{ label: "skipped", count: result.skipped.length },
|
|
284
|
+
{ label: "missing", count: result.missing.length },
|
|
285
|
+
{ label: "conflicted", count: result.conflicted.length }
|
|
286
|
+
]);
|
|
287
|
+
if (!parts.length) {
|
|
256
288
|
console.log(`- ${label}: no changes`);
|
|
257
289
|
return;
|
|
258
290
|
}
|
|
259
|
-
const parts = [
|
|
260
|
-
result.removed.length ? `${result.removed.length} removed` : void 0,
|
|
261
|
-
result.skipped.length ? `${result.skipped.length} skipped` : void 0,
|
|
262
|
-
result.missing.length ? `${result.missing.length} missing` : void 0,
|
|
263
|
-
result.conflicted.length ? `${result.conflicted.length} conflicted` : void 0
|
|
264
|
-
].filter((part) => typeof part === "string");
|
|
265
291
|
console.log(`- ${label}: ${parts.join(", ")}`);
|
|
266
292
|
};
|
|
267
293
|
|
|
@@ -749,7 +775,7 @@ var isRegistryItem = (value) => {
|
|
|
749
775
|
return false;
|
|
750
776
|
}
|
|
751
777
|
const item = value;
|
|
752
|
-
return typeof item.name === "string" && typeof item.canonicalName === "string" && typeof item.
|
|
778
|
+
return typeof item.name === "string" && typeof item.canonicalName === "string" && typeof item.type === "string" && typeof item.category === "string" && Array.isArray(item.aliases) && isStringArray(item.files) && isStringArray(item.dependencies) && isStringArray(item.registryDependencies) && isStringArray(item.utilities) && isStringArray(item.styles) && typeof item.target === "string";
|
|
753
779
|
};
|
|
754
780
|
var findInvalidRegistryItemIndex = (items) => {
|
|
755
781
|
return items.findIndex((item) => {
|
|
@@ -1010,7 +1036,7 @@ var resolveRegistryUtilities = (names) => {
|
|
|
1010
1036
|
});
|
|
1011
1037
|
};
|
|
1012
1038
|
|
|
1013
|
-
// src/
|
|
1039
|
+
// src/utils/flags.ts
|
|
1014
1040
|
var hasFlag = (args2, ...flags) => {
|
|
1015
1041
|
return flags.some((f) => args2.includes(f));
|
|
1016
1042
|
};
|
|
@@ -1036,30 +1062,37 @@ var removeFlagsWithValues = (args2, flags) => {
|
|
|
1036
1062
|
}
|
|
1037
1063
|
return result;
|
|
1038
1064
|
};
|
|
1039
|
-
|
|
1040
|
-
// src/commands/add.ts
|
|
1041
|
-
var promptSelectItems = async () => {
|
|
1065
|
+
var promptMultiselect = async (message, choices, options = {}) => {
|
|
1042
1066
|
const response = await prompts({
|
|
1043
1067
|
type: "multiselect",
|
|
1044
|
-
name: "
|
|
1045
|
-
message
|
|
1046
|
-
choices
|
|
1047
|
-
|
|
1048
|
-
value: item.name
|
|
1049
|
-
}))
|
|
1068
|
+
name: "selected",
|
|
1069
|
+
message,
|
|
1070
|
+
choices,
|
|
1071
|
+
...options.min !== void 0 ? { min: options.min } : {}
|
|
1050
1072
|
});
|
|
1051
1073
|
if (typeof response !== "object" || response === null) {
|
|
1052
1074
|
return [];
|
|
1053
1075
|
}
|
|
1054
|
-
const
|
|
1055
|
-
if (!Array.isArray(
|
|
1076
|
+
const selected = response.selected;
|
|
1077
|
+
if (!Array.isArray(selected)) {
|
|
1056
1078
|
return [];
|
|
1057
1079
|
}
|
|
1058
|
-
return
|
|
1080
|
+
return selected.filter((item) => typeof item === "string");
|
|
1081
|
+
};
|
|
1082
|
+
|
|
1083
|
+
// src/commands/add.ts
|
|
1084
|
+
var promptSelectItems = async () => {
|
|
1085
|
+
return promptMultiselect(
|
|
1086
|
+
"Select components to add",
|
|
1087
|
+
registryItems.map((item) => ({
|
|
1088
|
+
title: `${item.canonicalName} (${item.category})`,
|
|
1089
|
+
value: item.name
|
|
1090
|
+
}))
|
|
1091
|
+
);
|
|
1059
1092
|
};
|
|
1060
1093
|
var runAdd = async (args2) => {
|
|
1061
1094
|
const dryRun = hasFlag(args2, "--dry-run", "-d");
|
|
1062
|
-
hasFlag(args2, "--yes", "-y");
|
|
1095
|
+
const yes = hasFlag(args2, "--yes", "-y");
|
|
1063
1096
|
const noFallback = hasFlag(args2, "--no-fallback");
|
|
1064
1097
|
let items = removeFlagsWithValues(args2, ["--cwd", "-C"]);
|
|
1065
1098
|
items = removeFlags(items, [
|
|
@@ -1070,6 +1103,10 @@ var runAdd = async (args2) => {
|
|
|
1070
1103
|
"--no-fallback"
|
|
1071
1104
|
]);
|
|
1072
1105
|
if (!items.length) {
|
|
1106
|
+
if (yes) {
|
|
1107
|
+
console.log("No components specified. Pass component names to add them.");
|
|
1108
|
+
return;
|
|
1109
|
+
}
|
|
1073
1110
|
items = await promptSelectItems();
|
|
1074
1111
|
if (!items.length) {
|
|
1075
1112
|
console.log("No components selected.");
|
|
@@ -1106,7 +1143,7 @@ var runAdd = async (args2) => {
|
|
|
1106
1143
|
console.log("Dry run: no files or dependencies will be changed.\n");
|
|
1107
1144
|
console.log("Components:");
|
|
1108
1145
|
for (const item of resolvedItems) {
|
|
1109
|
-
console.log(`- ${item.canonicalName}
|
|
1146
|
+
console.log(`- ${item.canonicalName}`);
|
|
1110
1147
|
}
|
|
1111
1148
|
console.log("\nDependencies:");
|
|
1112
1149
|
for (const dependency of dependencies) {
|
|
@@ -1145,11 +1182,9 @@ var runAdd = async (args2) => {
|
|
|
1145
1182
|
}
|
|
1146
1183
|
console.log("");
|
|
1147
1184
|
}
|
|
1148
|
-
|
|
1149
|
-
...config.installed ?? {}
|
|
1150
|
-
};
|
|
1185
|
+
let installed = [...config.installed ?? []];
|
|
1151
1186
|
for (const item of successfullyInstalled) {
|
|
1152
|
-
installed
|
|
1187
|
+
installed = addInstalled(installed, item.name);
|
|
1153
1188
|
}
|
|
1154
1189
|
await saveConfig({
|
|
1155
1190
|
...config,
|
|
@@ -1253,13 +1288,13 @@ var runDoctor = async (options = {}) => {
|
|
|
1253
1288
|
if (registryFailed && options.noFallback) {
|
|
1254
1289
|
return;
|
|
1255
1290
|
}
|
|
1256
|
-
const installed = config.installed ??
|
|
1257
|
-
if (
|
|
1291
|
+
const installed = config.installed ?? [];
|
|
1292
|
+
if (installed.length) {
|
|
1258
1293
|
console.log("\nTracked components:");
|
|
1259
|
-
for (const
|
|
1294
|
+
for (const name of installed) {
|
|
1260
1295
|
const item = await findItem(name);
|
|
1261
1296
|
if (!item) {
|
|
1262
|
-
console.log(`\xD7 ${name}
|
|
1297
|
+
console.log(`\xD7 ${name} (missing from registry)`);
|
|
1263
1298
|
continue;
|
|
1264
1299
|
}
|
|
1265
1300
|
const componentPath = join(
|
|
@@ -1268,9 +1303,7 @@ var runDoctor = async (options = {}) => {
|
|
|
1268
1303
|
);
|
|
1269
1304
|
const exists = await fileExists(componentPath);
|
|
1270
1305
|
const layer = getInstallLayer(item) ?? "unknown";
|
|
1271
|
-
console.log(
|
|
1272
|
-
`${exists ? "\u2713" : "\xD7"} ${item.canonicalName} v${version} (${layer})`
|
|
1273
|
-
);
|
|
1306
|
+
console.log(`${exists ? "\u2713" : "\xD7"} ${item.canonicalName} (${layer})`);
|
|
1274
1307
|
}
|
|
1275
1308
|
}
|
|
1276
1309
|
};
|
|
@@ -1324,7 +1357,7 @@ Options
|
|
|
1324
1357
|
--all, -a Update all tracked components
|
|
1325
1358
|
--styles, -S Update generated token/theme CSS files
|
|
1326
1359
|
--utilities, -u Update shared utility files
|
|
1327
|
-
--sync Refresh tracked components even when
|
|
1360
|
+
--sync Refresh tracked components even when templates already match
|
|
1328
1361
|
--dry-run, -d Preview update without writing files
|
|
1329
1362
|
--force, -f Write conflicted updates after creating backups
|
|
1330
1363
|
--yes, -y Auto-confirm safe prompts
|
|
@@ -1363,6 +1396,24 @@ Usage
|
|
|
1363
1396
|
Options
|
|
1364
1397
|
--no-fallback Fail instead of falling back to local registry
|
|
1365
1398
|
--help, -h Show this help
|
|
1399
|
+
`,
|
|
1400
|
+
reset: `
|
|
1401
|
+
Usage
|
|
1402
|
+
lexsys reset [component...]
|
|
1403
|
+
|
|
1404
|
+
Options
|
|
1405
|
+
--dry-run, -d Preview reset without writing files
|
|
1406
|
+
--with-deps, -w Also reset installed registry dependencies in the closure
|
|
1407
|
+
--no-fallback Fail instead of falling back to local registry
|
|
1408
|
+
--cwd, -C <path> Run from a different project directory
|
|
1409
|
+
--help, -h Show this help
|
|
1410
|
+
|
|
1411
|
+
Run without arguments for guided reset picker.
|
|
1412
|
+
|
|
1413
|
+
Examples
|
|
1414
|
+
lexsys reset button
|
|
1415
|
+
lexsys reset sidebar --with-deps
|
|
1416
|
+
lexsys reset button --dry-run
|
|
1366
1417
|
`,
|
|
1367
1418
|
uninstall: `
|
|
1368
1419
|
Usage
|
|
@@ -1445,6 +1496,7 @@ Scaffold
|
|
|
1445
1496
|
Components
|
|
1446
1497
|
add <component...> Install components into your project [alias: a]
|
|
1447
1498
|
update [component...] Update installed components [alias: up]
|
|
1499
|
+
reset [component...] Restore components from registry templates
|
|
1448
1500
|
uninstall [component...] Remove installed components [alias: rm]
|
|
1449
1501
|
|
|
1450
1502
|
Inspect
|
|
@@ -1468,6 +1520,49 @@ Global Options
|
|
|
1468
1520
|
Run \`lexsys <command> --help\` for command-specific options.
|
|
1469
1521
|
`);
|
|
1470
1522
|
};
|
|
1523
|
+
var writeScaffoldFile = async (targetPath, content, options = {}) => {
|
|
1524
|
+
if (await fileExists(targetPath)) {
|
|
1525
|
+
const existingContent = await readFile(targetPath, "utf-8");
|
|
1526
|
+
if (existingContent === content) {
|
|
1527
|
+
console.log(`Skipped identical scaffold file: ${targetPath}`);
|
|
1528
|
+
return;
|
|
1529
|
+
}
|
|
1530
|
+
if (options.allowExisting) {
|
|
1531
|
+
console.log(`Skipped existing scaffold file: ${targetPath}`);
|
|
1532
|
+
return;
|
|
1533
|
+
}
|
|
1534
|
+
throw new Error(
|
|
1535
|
+
`Refusing to overwrite existing scaffold file: ${targetPath}`
|
|
1536
|
+
);
|
|
1537
|
+
}
|
|
1538
|
+
await mkdir(dirname(targetPath), { recursive: true });
|
|
1539
|
+
await writeFile(targetPath, content, "utf-8");
|
|
1540
|
+
console.log(`Created scaffold file: ${targetPath}`);
|
|
1541
|
+
};
|
|
1542
|
+
var writePackageJsonFile = async (targetDirectory, getContent, mergeContent) => {
|
|
1543
|
+
const targetPath = join(targetDirectory, "package.json");
|
|
1544
|
+
if (!await fileExists(targetPath)) {
|
|
1545
|
+
await writeFile(targetPath, getContent(targetDirectory), "utf-8");
|
|
1546
|
+
console.log(`Created scaffold file: ${targetPath}`);
|
|
1547
|
+
return;
|
|
1548
|
+
}
|
|
1549
|
+
let parsed;
|
|
1550
|
+
try {
|
|
1551
|
+
parsed = JSON.parse(await readFile(targetPath, "utf-8"));
|
|
1552
|
+
} catch {
|
|
1553
|
+
throw new Error(`Invalid existing package.json: ${targetPath}`);
|
|
1554
|
+
}
|
|
1555
|
+
const content = await readFile(targetPath, "utf-8");
|
|
1556
|
+
const mergedContent = mergeContent(targetDirectory, parsed);
|
|
1557
|
+
if (content === mergedContent) {
|
|
1558
|
+
console.log(`Skipped package.json: ${targetPath} already configured`);
|
|
1559
|
+
return;
|
|
1560
|
+
}
|
|
1561
|
+
await writeFile(targetPath, mergedContent, "utf-8");
|
|
1562
|
+
console.log(`Updated package.json: ${targetPath}`);
|
|
1563
|
+
};
|
|
1564
|
+
|
|
1565
|
+
// src/scaffold/next.ts
|
|
1471
1566
|
var NEXT_VERSION = "15.3.3";
|
|
1472
1567
|
var gitIgnore = `node_modules
|
|
1473
1568
|
.next
|
|
@@ -1648,50 +1743,9 @@ var mergePackageJson = (targetDirectory, existingPackageJson) => {
|
|
|
1648
1743
|
}
|
|
1649
1744
|
return JSON.stringify(mergedPackageJson, null, 2) + "\n";
|
|
1650
1745
|
};
|
|
1651
|
-
var writePackageJson = async (targetDirectory) => {
|
|
1652
|
-
const targetPath = join(targetDirectory, "package.json");
|
|
1653
|
-
if (!await fileExists(targetPath)) {
|
|
1654
|
-
await writeFile(targetPath, getPackageJson(targetDirectory), "utf-8");
|
|
1655
|
-
console.log(`Created scaffold file: ${targetPath}`);
|
|
1656
|
-
return;
|
|
1657
|
-
}
|
|
1658
|
-
let parsed;
|
|
1659
|
-
try {
|
|
1660
|
-
parsed = JSON.parse(await readFile(targetPath, "utf-8"));
|
|
1661
|
-
} catch {
|
|
1662
|
-
throw new Error(`Invalid existing package.json: ${targetPath}`);
|
|
1663
|
-
}
|
|
1664
|
-
const content = await readFile(targetPath, "utf-8");
|
|
1665
|
-
const mergedContent = mergePackageJson(targetDirectory, parsed);
|
|
1666
|
-
if (content === mergedContent) {
|
|
1667
|
-
console.log(`Skipped package.json: ${targetPath} already configured`);
|
|
1668
|
-
return;
|
|
1669
|
-
}
|
|
1670
|
-
await writeFile(targetPath, mergedContent, "utf-8");
|
|
1671
|
-
console.log(`Updated package.json: ${targetPath}`);
|
|
1672
|
-
};
|
|
1673
|
-
var writeScaffoldFile = async (targetPath, content, options = {}) => {
|
|
1674
|
-
if (await fileExists(targetPath)) {
|
|
1675
|
-
const existingContent = await readFile(targetPath, "utf-8");
|
|
1676
|
-
if (existingContent === content) {
|
|
1677
|
-
console.log(`Skipped identical scaffold file: ${targetPath}`);
|
|
1678
|
-
return;
|
|
1679
|
-
}
|
|
1680
|
-
if (options.allowExisting) {
|
|
1681
|
-
console.log(`Skipped existing scaffold file: ${targetPath}`);
|
|
1682
|
-
return;
|
|
1683
|
-
}
|
|
1684
|
-
throw new Error(
|
|
1685
|
-
`Refusing to overwrite existing scaffold file: ${targetPath}`
|
|
1686
|
-
);
|
|
1687
|
-
}
|
|
1688
|
-
await mkdir(dirname(targetPath), { recursive: true });
|
|
1689
|
-
await writeFile(targetPath, content, "utf-8");
|
|
1690
|
-
console.log(`Created scaffold file: ${targetPath}`);
|
|
1691
|
-
};
|
|
1692
1746
|
var scaffoldNextProject = async (targetDirectory) => {
|
|
1693
1747
|
await mkdir(targetDirectory, { recursive: true });
|
|
1694
|
-
await
|
|
1748
|
+
await writePackageJsonFile(targetDirectory, getPackageJson, mergePackageJson);
|
|
1695
1749
|
await writeScaffoldFile(join(targetDirectory, ".gitignore"), gitIgnore, {
|
|
1696
1750
|
allowExisting: true
|
|
1697
1751
|
});
|
|
@@ -2176,83 +2230,42 @@ var mergePackageJson2 = (targetDirectory, existingPackageJson) => {
|
|
|
2176
2230
|
}
|
|
2177
2231
|
return JSON.stringify(mergedPackageJson, null, 2) + "\n";
|
|
2178
2232
|
};
|
|
2179
|
-
var writePackageJson2 = async (targetDirectory) => {
|
|
2180
|
-
const targetPath = join(targetDirectory, "package.json");
|
|
2181
|
-
if (!await fileExists(targetPath)) {
|
|
2182
|
-
await writeFile(targetPath, getPackageJson2(targetDirectory), "utf-8");
|
|
2183
|
-
console.log(`Created scaffold file: ${targetPath}`);
|
|
2184
|
-
return;
|
|
2185
|
-
}
|
|
2186
|
-
let parsed;
|
|
2187
|
-
try {
|
|
2188
|
-
parsed = JSON.parse(await readFile(targetPath, "utf-8"));
|
|
2189
|
-
} catch {
|
|
2190
|
-
throw new Error(`Invalid existing package.json: ${targetPath}`);
|
|
2191
|
-
}
|
|
2192
|
-
const content = await readFile(targetPath, "utf-8");
|
|
2193
|
-
const mergedContent = mergePackageJson2(targetDirectory, parsed);
|
|
2194
|
-
if (content === mergedContent) {
|
|
2195
|
-
console.log(`Skipped package.json: ${targetPath} already configured`);
|
|
2196
|
-
return;
|
|
2197
|
-
}
|
|
2198
|
-
await writeFile(targetPath, mergedContent, "utf-8");
|
|
2199
|
-
console.log(`Updated package.json: ${targetPath}`);
|
|
2200
|
-
};
|
|
2201
|
-
var writeScaffoldFile2 = async (targetPath, content, options = {}) => {
|
|
2202
|
-
if (await fileExists(targetPath)) {
|
|
2203
|
-
const existingContent = await readFile(targetPath, "utf-8");
|
|
2204
|
-
if (existingContent === content) {
|
|
2205
|
-
console.log(`Skipped identical scaffold file: ${targetPath}`);
|
|
2206
|
-
return;
|
|
2207
|
-
}
|
|
2208
|
-
if (options.allowExisting) {
|
|
2209
|
-
console.log(`Skipped existing scaffold file: ${targetPath}`);
|
|
2210
|
-
return;
|
|
2211
|
-
}
|
|
2212
|
-
throw new Error(
|
|
2213
|
-
`Refusing to overwrite existing scaffold file: ${targetPath}`
|
|
2214
|
-
);
|
|
2215
|
-
}
|
|
2216
|
-
await mkdir(dirname(targetPath), { recursive: true });
|
|
2217
|
-
await writeFile(targetPath, content, "utf-8");
|
|
2218
|
-
console.log(`Created scaffold file: ${targetPath}`);
|
|
2219
|
-
};
|
|
2220
2233
|
var scaffoldViteProject = async (targetDirectory) => {
|
|
2221
2234
|
await mkdir(targetDirectory, { recursive: true });
|
|
2222
|
-
await
|
|
2223
|
-
await
|
|
2235
|
+
await writePackageJsonFile(targetDirectory, getPackageJson2, mergePackageJson2);
|
|
2236
|
+
await writeScaffoldFile(join(targetDirectory, ".gitignore"), gitIgnore2, {
|
|
2224
2237
|
allowExisting: true
|
|
2225
2238
|
});
|
|
2226
|
-
await
|
|
2239
|
+
await writeScaffoldFile(
|
|
2227
2240
|
join(targetDirectory, ".prettierignore"),
|
|
2228
2241
|
prettierIgnore2,
|
|
2229
2242
|
{
|
|
2230
2243
|
allowExisting: true
|
|
2231
2244
|
}
|
|
2232
2245
|
);
|
|
2233
|
-
await
|
|
2246
|
+
await writeScaffoldFile(
|
|
2234
2247
|
join(targetDirectory, ".prettierrc"),
|
|
2235
2248
|
prettierConfig2,
|
|
2236
2249
|
{
|
|
2237
2250
|
allowExisting: true
|
|
2238
2251
|
}
|
|
2239
2252
|
);
|
|
2240
|
-
await
|
|
2241
|
-
await
|
|
2242
|
-
await
|
|
2253
|
+
await writeScaffoldFile(join(targetDirectory, "index.html"), indexHtml);
|
|
2254
|
+
await writeScaffoldFile(join(targetDirectory, "tsconfig.json"), tsConfig2);
|
|
2255
|
+
await writeScaffoldFile(
|
|
2243
2256
|
join(targetDirectory, "tsconfig.app.json"),
|
|
2244
2257
|
tsConfigApp
|
|
2245
2258
|
);
|
|
2246
|
-
await
|
|
2259
|
+
await writeScaffoldFile(
|
|
2247
2260
|
join(targetDirectory, "tsconfig.node.json"),
|
|
2248
2261
|
tsConfigNode
|
|
2249
2262
|
);
|
|
2250
|
-
await
|
|
2263
|
+
await writeScaffoldFile(join(targetDirectory, "vite.config.ts"), viteConfig, {
|
|
2251
2264
|
allowExisting: true
|
|
2252
2265
|
});
|
|
2253
|
-
await
|
|
2254
|
-
await
|
|
2255
|
-
await
|
|
2266
|
+
await writeScaffoldFile(join(targetDirectory, "src", "main.tsx"), mainTsx);
|
|
2267
|
+
await writeScaffoldFile(join(targetDirectory, "src", "App.tsx"), appTsx);
|
|
2268
|
+
await writeScaffoldFile(join(targetDirectory, "src", "style.css"), styleCss, {
|
|
2256
2269
|
allowExisting: true
|
|
2257
2270
|
});
|
|
2258
2271
|
};
|
|
@@ -2426,7 +2439,6 @@ var runList = async (options = {}) => {
|
|
|
2426
2439
|
const simplified = registryItems3.map((item) => ({
|
|
2427
2440
|
name: item.name,
|
|
2428
2441
|
canonicalName: item.canonicalName,
|
|
2429
|
-
version: item.version,
|
|
2430
2442
|
category: item.category,
|
|
2431
2443
|
layer: getInstallLayer(item)
|
|
2432
2444
|
}));
|
|
@@ -2448,9 +2460,7 @@ var runList = async (options = {}) => {
|
|
|
2448
2460
|
}
|
|
2449
2461
|
console.log(`${layerLabels[layer] ?? layer}:`);
|
|
2450
2462
|
for (const item of items) {
|
|
2451
|
-
console.log(
|
|
2452
|
-
`- ${item.canonicalName} v${item.version} (${item.category})`
|
|
2453
|
-
);
|
|
2463
|
+
console.log(`- ${item.canonicalName} (${item.category})`);
|
|
2454
2464
|
}
|
|
2455
2465
|
console.log("");
|
|
2456
2466
|
}
|
|
@@ -2474,7 +2484,7 @@ var printRegistrySummary = (result) => {
|
|
|
2474
2484
|
for (const item of result.items) {
|
|
2475
2485
|
const remoteFileCount = item.remoteFiles?.length ?? 0;
|
|
2476
2486
|
console.log(
|
|
2477
|
-
`- ${item.canonicalName}
|
|
2487
|
+
`- ${item.canonicalName} (${item.type}/${item.category}, remote files: ${remoteFileCount})`
|
|
2478
2488
|
);
|
|
2479
2489
|
}
|
|
2480
2490
|
};
|
|
@@ -2560,12 +2570,43 @@ var runRegistry = async (options = {}) => {
|
|
|
2560
2570
|
process.exitCode = 1;
|
|
2561
2571
|
}
|
|
2562
2572
|
};
|
|
2573
|
+
var getComponentDriftStatus = async (name) => {
|
|
2574
|
+
const item = await findItem(name);
|
|
2575
|
+
if (!item) {
|
|
2576
|
+
return "missing";
|
|
2577
|
+
}
|
|
2578
|
+
const hasDrift = await itemHasTemplateDrift(item);
|
|
2579
|
+
return hasDrift ? "drift" : "in-sync";
|
|
2580
|
+
};
|
|
2581
|
+
var itemHasTemplateDrift = async (item) => {
|
|
2582
|
+
const config = await loadConfig();
|
|
2583
|
+
const installTarget = resolveItemInstallTarget(config, item);
|
|
2584
|
+
for (const file of item.files) {
|
|
2585
|
+
const fileName = file.split("/").at(-1);
|
|
2586
|
+
if (!fileName) {
|
|
2587
|
+
return true;
|
|
2588
|
+
}
|
|
2589
|
+
const targetPath = join(getCwd(), installTarget, fileName);
|
|
2590
|
+
if (!await fileExists(targetPath)) {
|
|
2591
|
+
return true;
|
|
2592
|
+
}
|
|
2593
|
+
const preparedContent = prepareInstalledFileContent(
|
|
2594
|
+
await readFile(getRegistryTemplatePath(file), "utf-8"),
|
|
2595
|
+
item
|
|
2596
|
+
);
|
|
2597
|
+
const targetContent = await readFile(targetPath, "utf-8");
|
|
2598
|
+
if (!hashesAreEqual(preparedContent, targetContent)) {
|
|
2599
|
+
return true;
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
return false;
|
|
2603
|
+
};
|
|
2563
2604
|
|
|
2564
2605
|
// src/commands/status.ts
|
|
2565
2606
|
var runStatus = async (options = {}) => {
|
|
2566
2607
|
const config = await loadConfig();
|
|
2567
|
-
const installed = config.installed ??
|
|
2568
|
-
if (!
|
|
2608
|
+
const installed = config.installed ?? [];
|
|
2609
|
+
if (!installed.length) {
|
|
2569
2610
|
console.log("No Lexsys components are currently tracked.");
|
|
2570
2611
|
return;
|
|
2571
2612
|
}
|
|
@@ -2580,14 +2621,15 @@ var runStatus = async (options = {}) => {
|
|
|
2580
2621
|
return;
|
|
2581
2622
|
}
|
|
2582
2623
|
console.log("Installed Lexsys components:\n");
|
|
2583
|
-
for (const
|
|
2624
|
+
for (const name of installed) {
|
|
2584
2625
|
const item = await findItem(name);
|
|
2585
2626
|
if (!item) {
|
|
2586
|
-
console.log(`- ${name}
|
|
2627
|
+
console.log(`- ${name} (missing from registry)`);
|
|
2587
2628
|
continue;
|
|
2588
2629
|
}
|
|
2589
|
-
const
|
|
2590
|
-
|
|
2630
|
+
const driftStatus = await getComponentDriftStatus(name);
|
|
2631
|
+
const status = driftStatus === "drift" ? "out of sync with registry" : "up to date with registry";
|
|
2632
|
+
console.log(`- ${item.canonicalName} (${status})`);
|
|
2591
2633
|
}
|
|
2592
2634
|
};
|
|
2593
2635
|
|
|
@@ -2612,7 +2654,7 @@ var computeRegistryClosure = (rootNames, items) => {
|
|
|
2612
2654
|
return closure;
|
|
2613
2655
|
};
|
|
2614
2656
|
var findOrphanInstalledItems = (removedTargetNames, remainingInstalled, items) => {
|
|
2615
|
-
const remainingNames =
|
|
2657
|
+
const remainingNames = remainingInstalled;
|
|
2616
2658
|
const removedDependencyNames = /* @__PURE__ */ new Set();
|
|
2617
2659
|
for (const removedName of removedTargetNames) {
|
|
2618
2660
|
const closure = computeRegistryClosure([removedName], items);
|
|
@@ -2631,43 +2673,281 @@ var findOrphanInstalledItems = (removedTargetNames, remainingInstalled, items) =
|
|
|
2631
2673
|
)
|
|
2632
2674
|
).filter((item) => Boolean(item)).filter((item) => removedDependencyNames.has(item.name));
|
|
2633
2675
|
};
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
};
|
|
2639
|
-
|
|
2640
|
-
const names = Object.keys(installed);
|
|
2641
|
-
if (!names.length) {
|
|
2642
|
-
return [];
|
|
2643
|
-
}
|
|
2644
|
-
return resolveRegistryItems(names);
|
|
2645
|
-
};
|
|
2646
|
-
var collectOrphanedSharedResources = (removedItems, remainingItems) => {
|
|
2647
|
-
const removedUtilities = collectUtilities(removedItems);
|
|
2648
|
-
const removedStyles = collectStyles(removedItems);
|
|
2649
|
-
const remainingUtilities = new Set(collectUtilities(remainingItems));
|
|
2650
|
-
const remainingStyles = new Set(collectStyles(remainingItems));
|
|
2651
|
-
return {
|
|
2652
|
-
utilities: removedUtilities.filter((utility) => {
|
|
2653
|
-
return !remainingUtilities.has(utility);
|
|
2654
|
-
}),
|
|
2655
|
-
styles: removedStyles.filter((style) => {
|
|
2656
|
-
return !remainingStyles.has(style);
|
|
2657
|
-
})
|
|
2658
|
-
};
|
|
2659
|
-
};
|
|
2660
|
-
var removeInstalledKey = (installed, itemName) => {
|
|
2661
|
-
const installedKey = Object.keys(installed).find((key) => {
|
|
2662
|
-
return normalizeInstalledKey(key) === normalizeInstalledKey(itemName);
|
|
2663
|
-
});
|
|
2664
|
-
if (installedKey) {
|
|
2665
|
-
delete installed[installedKey];
|
|
2676
|
+
var checkItemFiles = async (name) => {
|
|
2677
|
+
const item = await findItem(name);
|
|
2678
|
+
const config = await loadConfig();
|
|
2679
|
+
if (!item) {
|
|
2680
|
+
console.log(`Component "${name}" no longer exists in the registry.`);
|
|
2681
|
+
return;
|
|
2666
2682
|
}
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
const
|
|
2670
|
-
|
|
2683
|
+
const installTarget = resolveItemInstallTarget(config, item);
|
|
2684
|
+
console.log(`File check for ${item.canonicalName}:`);
|
|
2685
|
+
for (const file of item.files) {
|
|
2686
|
+
const fileName = file.split("/").at(-1);
|
|
2687
|
+
if (!fileName) {
|
|
2688
|
+
console.log(`- invalid registry file path: ${file}`);
|
|
2689
|
+
continue;
|
|
2690
|
+
}
|
|
2691
|
+
const targetPath = join(getCwd(), installTarget, fileName);
|
|
2692
|
+
if (!await fileExists(targetPath)) {
|
|
2693
|
+
console.log(`- missing: ${targetPath}`);
|
|
2694
|
+
continue;
|
|
2695
|
+
}
|
|
2696
|
+
const preparedContent = prepareInstalledFileContent(
|
|
2697
|
+
await readFile(getRegistryTemplatePath(file), "utf-8"),
|
|
2698
|
+
item
|
|
2699
|
+
);
|
|
2700
|
+
const targetContent = await readFile(targetPath, "utf-8");
|
|
2701
|
+
if (hashesAreEqual(preparedContent, targetContent)) {
|
|
2702
|
+
console.log(`- identical: ${targetPath}`);
|
|
2703
|
+
continue;
|
|
2704
|
+
}
|
|
2705
|
+
console.log(`- conflict: ${targetPath}`);
|
|
2706
|
+
}
|
|
2707
|
+
};
|
|
2708
|
+
var applyItemOverwrite = async (name, force) => {
|
|
2709
|
+
const item = await findItem(name);
|
|
2710
|
+
const config = await loadConfig();
|
|
2711
|
+
if (!item) {
|
|
2712
|
+
console.log(`Component "${name}" no longer exists in the registry.`);
|
|
2713
|
+
return false;
|
|
2714
|
+
}
|
|
2715
|
+
const installTarget = resolveItemInstallTarget(config, item);
|
|
2716
|
+
let hasConflict = false;
|
|
2717
|
+
console.log(`Applying update for ${item.canonicalName}:`);
|
|
2718
|
+
for (const file of item.files) {
|
|
2719
|
+
const sourcePath = getRegistryTemplatePath(file);
|
|
2720
|
+
const fileName = file.split("/").at(-1);
|
|
2721
|
+
if (!fileName) {
|
|
2722
|
+
console.log(`- invalid registry file path: ${file}`);
|
|
2723
|
+
hasConflict = true;
|
|
2724
|
+
continue;
|
|
2725
|
+
}
|
|
2726
|
+
const targetPath = join(getCwd(), installTarget, fileName);
|
|
2727
|
+
const preparedContent = prepareInstalledFileContent(
|
|
2728
|
+
await readFile(sourcePath, "utf-8"),
|
|
2729
|
+
item
|
|
2730
|
+
);
|
|
2731
|
+
await mkdir(dirname(targetPath), { recursive: true });
|
|
2732
|
+
if (!await fileExists(targetPath)) {
|
|
2733
|
+
await writeFile(targetPath, preparedContent, "utf-8");
|
|
2734
|
+
console.log(`- restored missing file: ${targetPath}`);
|
|
2735
|
+
continue;
|
|
2736
|
+
}
|
|
2737
|
+
const targetContent = await readFile(targetPath, "utf-8");
|
|
2738
|
+
if (hashesAreEqual(preparedContent, targetContent)) {
|
|
2739
|
+
console.log(`- identical: ${targetPath}`);
|
|
2740
|
+
continue;
|
|
2741
|
+
}
|
|
2742
|
+
if (force) {
|
|
2743
|
+
const backupPath = await createBackupFile(targetPath);
|
|
2744
|
+
if (backupPath) {
|
|
2745
|
+
console.log(`- backup created: ${backupPath}`);
|
|
2746
|
+
}
|
|
2747
|
+
await writeFile(targetPath, preparedContent, "utf-8");
|
|
2748
|
+
console.log(`- force updated file: ${targetPath}`);
|
|
2749
|
+
continue;
|
|
2750
|
+
}
|
|
2751
|
+
hasConflict = true;
|
|
2752
|
+
console.log(`- conflict (user modified): ${targetPath}`);
|
|
2753
|
+
}
|
|
2754
|
+
if (hasConflict) {
|
|
2755
|
+
console.log(
|
|
2756
|
+
"Update finished with conflicts. Review conflicted files before retrying."
|
|
2757
|
+
);
|
|
2758
|
+
return false;
|
|
2759
|
+
}
|
|
2760
|
+
console.log(`\u2714 ${item.canonicalName} updated successfully`);
|
|
2761
|
+
return true;
|
|
2762
|
+
};
|
|
2763
|
+
var checkItemUpdate = async (name, dryRun, force, sync = false) => {
|
|
2764
|
+
const item = await findItem(name);
|
|
2765
|
+
if (!item) {
|
|
2766
|
+
console.log(`Component "${name}" no longer exists in the registry.`);
|
|
2767
|
+
return false;
|
|
2768
|
+
}
|
|
2769
|
+
const driftStatus = await getComponentDriftStatus(name);
|
|
2770
|
+
if (driftStatus === "missing") {
|
|
2771
|
+
console.log(`Component "${name}" no longer exists in the registry.`);
|
|
2772
|
+
return false;
|
|
2773
|
+
}
|
|
2774
|
+
const hasDrift = driftStatus === "drift";
|
|
2775
|
+
if (!sync && !hasDrift) {
|
|
2776
|
+
console.log(`${item.canonicalName} is up to date with the registry.`);
|
|
2777
|
+
return false;
|
|
2778
|
+
}
|
|
2779
|
+
if (sync && !hasDrift) {
|
|
2780
|
+
console.log(
|
|
2781
|
+
`${item.canonicalName} template sync (already matches registry)`
|
|
2782
|
+
);
|
|
2783
|
+
} else {
|
|
2784
|
+
console.log(`${item.canonicalName} can be updated from registry templates`);
|
|
2785
|
+
}
|
|
2786
|
+
if (dryRun) {
|
|
2787
|
+
console.log("\nChanged file candidates:");
|
|
2788
|
+
for (const file of item.files) {
|
|
2789
|
+
console.log(`~ ${file}`);
|
|
2790
|
+
}
|
|
2791
|
+
console.log("\nDry run: no files will be changed.");
|
|
2792
|
+
console.log("Update plan:");
|
|
2793
|
+
if (force) {
|
|
2794
|
+
console.log(
|
|
2795
|
+
"- Force mode requested: conflicted files require backup before overwrite"
|
|
2796
|
+
);
|
|
2797
|
+
console.log(
|
|
2798
|
+
"- Dry run: backups would be created before forced overwrites"
|
|
2799
|
+
);
|
|
2800
|
+
}
|
|
2801
|
+
console.log(`- Check installed files for ${item.canonicalName}`);
|
|
2802
|
+
console.log("- Compare existing files with registry templates");
|
|
2803
|
+
console.log("- Report conflicts before writing changes");
|
|
2804
|
+
console.log("- Never overwrite user-modified files silently");
|
|
2805
|
+
await checkItemFiles(name);
|
|
2806
|
+
return false;
|
|
2807
|
+
}
|
|
2808
|
+
return await applyItemOverwrite(name, force);
|
|
2809
|
+
};
|
|
2810
|
+
var resetItem = async (name, dryRun) => {
|
|
2811
|
+
const item = await findItem(name);
|
|
2812
|
+
if (!item) {
|
|
2813
|
+
console.log(`Component "${name}" no longer exists in the registry.`);
|
|
2814
|
+
return false;
|
|
2815
|
+
}
|
|
2816
|
+
const hasDrift = await itemHasTemplateDrift(item);
|
|
2817
|
+
if (!hasDrift) {
|
|
2818
|
+
console.log(`${item.canonicalName} already matches registry templates.`);
|
|
2819
|
+
return false;
|
|
2820
|
+
}
|
|
2821
|
+
if (dryRun) {
|
|
2822
|
+
console.log(`Reset plan for ${item.canonicalName}:`);
|
|
2823
|
+
console.log("- Backups would be created before overwriting changed files");
|
|
2824
|
+
console.log("- Files would be restored from registry templates");
|
|
2825
|
+
for (const file of item.files) {
|
|
2826
|
+
console.log(`~ ${file}`);
|
|
2827
|
+
}
|
|
2828
|
+
console.log("\nDry run: no files will be changed.");
|
|
2829
|
+
await checkItemFiles(name);
|
|
2830
|
+
return false;
|
|
2831
|
+
}
|
|
2832
|
+
return await applyItemOverwrite(name, true);
|
|
2833
|
+
};
|
|
2834
|
+
|
|
2835
|
+
// src/commands/reset.ts
|
|
2836
|
+
var resolveInstalledKey = async (name, installed) => {
|
|
2837
|
+
const direct = findInstalledKey(installed, name);
|
|
2838
|
+
if (direct) {
|
|
2839
|
+
return direct;
|
|
2840
|
+
}
|
|
2841
|
+
const item = await findItem(name);
|
|
2842
|
+
if (!item) {
|
|
2843
|
+
return void 0;
|
|
2844
|
+
}
|
|
2845
|
+
return findInstalledKey(installed, item.name);
|
|
2846
|
+
};
|
|
2847
|
+
var runReset = async (args2) => {
|
|
2848
|
+
const dryRun = hasFlag(args2, "--dry-run", "-d");
|
|
2849
|
+
const withDeps = hasFlag(args2, "--with-deps", "-w");
|
|
2850
|
+
const noFallback = hasFlag(args2, "--no-fallback");
|
|
2851
|
+
const targetArgs = removeFlagsWithValues(
|
|
2852
|
+
removeFlags(args2, [
|
|
2853
|
+
"--dry-run",
|
|
2854
|
+
"-d",
|
|
2855
|
+
"--with-deps",
|
|
2856
|
+
"-w",
|
|
2857
|
+
"--no-fallback"
|
|
2858
|
+
]),
|
|
2859
|
+
["--cwd", "-C"]
|
|
2860
|
+
);
|
|
2861
|
+
const config = await loadConfig();
|
|
2862
|
+
const installed = [...config.installed ?? []];
|
|
2863
|
+
if (!installed.length) {
|
|
2864
|
+
console.log("No components installed.");
|
|
2865
|
+
return;
|
|
2866
|
+
}
|
|
2867
|
+
try {
|
|
2868
|
+
await getRegistryProviderResult({
|
|
2869
|
+
fallback: !noFallback
|
|
2870
|
+
});
|
|
2871
|
+
} catch (error) {
|
|
2872
|
+
console.log("Failed to resolve registry.");
|
|
2873
|
+
console.log(error instanceof Error ? error.message : String(error));
|
|
2874
|
+
process.exitCode = 1;
|
|
2875
|
+
return;
|
|
2876
|
+
}
|
|
2877
|
+
if (!targetArgs.length) {
|
|
2878
|
+
const selected = await promptMultiselect(
|
|
2879
|
+
"Select components to reset",
|
|
2880
|
+
installed.map((name) => ({ title: name, value: name })),
|
|
2881
|
+
{ min: 1 }
|
|
2882
|
+
);
|
|
2883
|
+
if (!selected.length) return;
|
|
2884
|
+
targetArgs.push(...selected);
|
|
2885
|
+
}
|
|
2886
|
+
const resetNames = /* @__PURE__ */ new Set();
|
|
2887
|
+
for (const name of targetArgs) {
|
|
2888
|
+
const installedKey = await resolveInstalledKey(name, installed);
|
|
2889
|
+
if (!installedKey) {
|
|
2890
|
+
console.log(`Component "${name}" is not tracked as installed.`);
|
|
2891
|
+
continue;
|
|
2892
|
+
}
|
|
2893
|
+
resetNames.add(installedKey);
|
|
2894
|
+
}
|
|
2895
|
+
if (!resetNames.size) {
|
|
2896
|
+
console.log("No installed components matched the request.");
|
|
2897
|
+
return;
|
|
2898
|
+
}
|
|
2899
|
+
if (withDeps) {
|
|
2900
|
+
const allItems = await getRegistryItems({ fallback: !noFallback });
|
|
2901
|
+
for (const rootName of [...resetNames]) {
|
|
2902
|
+
const closure = computeRegistryClosure([rootName], allItems);
|
|
2903
|
+
for (const dependencyName of closure) {
|
|
2904
|
+
if (isInstalled(installed, dependencyName)) {
|
|
2905
|
+
resetNames.add(dependencyName);
|
|
2906
|
+
}
|
|
2907
|
+
}
|
|
2908
|
+
}
|
|
2909
|
+
}
|
|
2910
|
+
const resetItems = await resolveRegistryItems([...resetNames], {
|
|
2911
|
+
fallback: !noFallback
|
|
2912
|
+
});
|
|
2913
|
+
if (dryRun) {
|
|
2914
|
+
console.log("Dry run: no files will be changed.\n");
|
|
2915
|
+
console.log("Components:");
|
|
2916
|
+
for (const item of resetItems) {
|
|
2917
|
+
console.log(`- ${item.canonicalName}`);
|
|
2918
|
+
}
|
|
2919
|
+
console.log("");
|
|
2920
|
+
}
|
|
2921
|
+
for (const item of resetItems) {
|
|
2922
|
+
await resetItem(item.name, dryRun);
|
|
2923
|
+
console.log("");
|
|
2924
|
+
}
|
|
2925
|
+
};
|
|
2926
|
+
|
|
2927
|
+
// src/commands/uninstall.ts
|
|
2928
|
+
var resolveInstalledItems = async (installed) => {
|
|
2929
|
+
if (!installed.length) {
|
|
2930
|
+
return [];
|
|
2931
|
+
}
|
|
2932
|
+
return resolveRegistryItems(installed);
|
|
2933
|
+
};
|
|
2934
|
+
var collectOrphanedSharedResources = (removedItems, remainingItems) => {
|
|
2935
|
+
const removedUtilities = collectUtilities(removedItems);
|
|
2936
|
+
const removedStyles = collectStyles(removedItems);
|
|
2937
|
+
const remainingUtilities = new Set(collectUtilities(remainingItems));
|
|
2938
|
+
const remainingStyles = new Set(collectStyles(remainingItems));
|
|
2939
|
+
return {
|
|
2940
|
+
utilities: removedUtilities.filter((utility) => {
|
|
2941
|
+
return !remainingUtilities.has(utility);
|
|
2942
|
+
}),
|
|
2943
|
+
styles: removedStyles.filter((style) => {
|
|
2944
|
+
return !remainingStyles.has(style);
|
|
2945
|
+
})
|
|
2946
|
+
};
|
|
2947
|
+
};
|
|
2948
|
+
var runUninstall = async (args2) => {
|
|
2949
|
+
const dryRun = hasFlag(args2, "--dry-run", "-d");
|
|
2950
|
+
const withDeps = hasFlag(args2, "--with-deps", "-w");
|
|
2671
2951
|
const noFallback = hasFlag(args2, "--no-fallback");
|
|
2672
2952
|
const targetArgs = removeFlagsWithValues(
|
|
2673
2953
|
removeFlags(args2, [
|
|
@@ -2681,26 +2961,21 @@ var runUninstall = async (args2) => {
|
|
|
2681
2961
|
);
|
|
2682
2962
|
if (!targetArgs.length) {
|
|
2683
2963
|
const preConfig = await loadConfig();
|
|
2684
|
-
const installedNames =
|
|
2964
|
+
const installedNames = preConfig.installed ?? [];
|
|
2685
2965
|
if (installedNames.length === 0) {
|
|
2686
2966
|
console.log("No components installed.");
|
|
2687
2967
|
return;
|
|
2688
2968
|
}
|
|
2689
|
-
const
|
|
2690
|
-
|
|
2691
|
-
name:
|
|
2692
|
-
|
|
2693
|
-
choices: installedNames.map((name) => ({ title: name, value: name })),
|
|
2694
|
-
min: 1
|
|
2695
|
-
});
|
|
2696
|
-
const selected = response.components;
|
|
2697
|
-
if (!Array.isArray(selected) || !selected.length) return;
|
|
2698
|
-
targetArgs.push(
|
|
2699
|
-
...selected.filter((c) => typeof c === "string")
|
|
2969
|
+
const selected = await promptMultiselect(
|
|
2970
|
+
"Select components to uninstall",
|
|
2971
|
+
installedNames.map((name) => ({ title: name, value: name })),
|
|
2972
|
+
{ min: 1 }
|
|
2700
2973
|
);
|
|
2974
|
+
if (!selected.length) return;
|
|
2975
|
+
targetArgs.push(...selected);
|
|
2701
2976
|
}
|
|
2702
2977
|
const config = await loadConfig();
|
|
2703
|
-
const installed = config.installed ??
|
|
2978
|
+
const installed = [...config.installed ?? []];
|
|
2704
2979
|
const resolvedTargets = [];
|
|
2705
2980
|
const notTracked = [];
|
|
2706
2981
|
for (const name of targetArgs) {
|
|
@@ -2709,10 +2984,7 @@ var runUninstall = async (args2) => {
|
|
|
2709
2984
|
console.log(`Component "${name}" not found in registry.`);
|
|
2710
2985
|
continue;
|
|
2711
2986
|
}
|
|
2712
|
-
|
|
2713
|
-
return normalizeInstalledKey(key) === normalizeInstalledKey(item.name);
|
|
2714
|
-
});
|
|
2715
|
-
if (!installedKey) {
|
|
2987
|
+
if (!isInstalled(installed, item.name)) {
|
|
2716
2988
|
notTracked.push(name);
|
|
2717
2989
|
console.log(`Component "${name}" is not tracked as installed.`);
|
|
2718
2990
|
continue;
|
|
@@ -2725,10 +2997,11 @@ var runUninstall = async (args2) => {
|
|
|
2725
2997
|
}
|
|
2726
2998
|
return;
|
|
2727
2999
|
}
|
|
2728
|
-
const remainingInstalled =
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
3000
|
+
const remainingInstalled = installed.filter((entry) => {
|
|
3001
|
+
return !resolvedTargets.some((item) => {
|
|
3002
|
+
return findInstalledKey([entry], item.name) !== void 0;
|
|
3003
|
+
});
|
|
3004
|
+
});
|
|
2732
3005
|
const allItems = await getRegistryItems({ fallback: !noFallback });
|
|
2733
3006
|
const orphanItems = withDeps ? findOrphanInstalledItems(
|
|
2734
3007
|
resolvedTargets.map((item) => item.name),
|
|
@@ -2750,9 +3023,7 @@ var runUninstall = async (args2) => {
|
|
|
2750
3023
|
console.log("Dry run: no files will be removed.\n");
|
|
2751
3024
|
console.log("Components:");
|
|
2752
3025
|
for (const item of resolvedTargets) {
|
|
2753
|
-
console.log(
|
|
2754
|
-
`- ${item.canonicalName} v${installed[item.name] ?? "unknown"}`
|
|
2755
|
-
);
|
|
3026
|
+
console.log(`- ${item.canonicalName}`);
|
|
2756
3027
|
}
|
|
2757
3028
|
if (withDeps && orphanItems.length) {
|
|
2758
3029
|
console.log("\nOrphan registry items (--with-deps):");
|
|
@@ -2768,10 +3039,12 @@ var runUninstall = async (args2) => {
|
|
|
2768
3039
|
console.log(`- ${item.canonicalName}`);
|
|
2769
3040
|
}
|
|
2770
3041
|
}
|
|
2771
|
-
const postOrphanRemaining =
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
3042
|
+
const postOrphanRemaining = remainingInstalled.filter((entry) => {
|
|
3043
|
+
if (!withDeps) {
|
|
3044
|
+
return true;
|
|
3045
|
+
}
|
|
3046
|
+
return !orphanItems.some((item) => isInstalled([entry], item.name));
|
|
3047
|
+
});
|
|
2775
3048
|
const dryRunOrphans = collectOrphanedSharedResources(
|
|
2776
3049
|
allRemovalTargets,
|
|
2777
3050
|
await resolveInstalledItems(postOrphanRemaining)
|
|
@@ -2805,11 +3078,11 @@ var runUninstall = async (args2) => {
|
|
|
2805
3078
|
}
|
|
2806
3079
|
console.log("");
|
|
2807
3080
|
}
|
|
2808
|
-
|
|
3081
|
+
let updatedInstalled = [...installed];
|
|
2809
3082
|
for (const item of successfullyUninstalled) {
|
|
2810
|
-
|
|
3083
|
+
updatedInstalled = removeInstalled(updatedInstalled, item.name);
|
|
2811
3084
|
}
|
|
2812
|
-
const remainingItems = await resolveInstalledItems(
|
|
3085
|
+
const remainingItems = await resolveInstalledItems(updatedInstalled);
|
|
2813
3086
|
const orphanedResources = collectOrphanedSharedResources(
|
|
2814
3087
|
successfullyUninstalled,
|
|
2815
3088
|
remainingItems
|
|
@@ -2829,12 +3102,6 @@ var runUninstall = async (args2) => {
|
|
|
2829
3102
|
}
|
|
2830
3103
|
const utilitiesResult = await uninstallUtilities(resolvedUtilities, config);
|
|
2831
3104
|
const stylesResult = await uninstallStyles(resolvedStyles, config);
|
|
2832
|
-
const updatedInstalled = {
|
|
2833
|
-
...installed
|
|
2834
|
-
};
|
|
2835
|
-
for (const item of successfullyUninstalled) {
|
|
2836
|
-
removeInstalledKey(updatedInstalled, item.name);
|
|
2837
|
-
}
|
|
2838
3105
|
await saveConfig({
|
|
2839
3106
|
...config,
|
|
2840
3107
|
installed: updatedInstalled
|
|
@@ -2854,172 +3121,18 @@ var runUninstall = async (args2) => {
|
|
|
2854
3121
|
}
|
|
2855
3122
|
};
|
|
2856
3123
|
|
|
2857
|
-
// src/utils/version.ts
|
|
2858
|
-
var compareVersions = (a, b) => {
|
|
2859
|
-
const pa = a.split(".").map(Number);
|
|
2860
|
-
const pb = b.split(".").map(Number);
|
|
2861
|
-
const length = Math.max(pa.length, pb.length);
|
|
2862
|
-
for (let i = 0; i < length; i++) {
|
|
2863
|
-
const va = pa[i] ?? 0;
|
|
2864
|
-
const vb = pb[i] ?? 0;
|
|
2865
|
-
if (va > vb) return 1;
|
|
2866
|
-
if (va < vb) return -1;
|
|
2867
|
-
}
|
|
2868
|
-
return 0;
|
|
2869
|
-
};
|
|
2870
|
-
var isUpdateAvailable = (installed, latest) => {
|
|
2871
|
-
return compareVersions(latest, installed) === 1;
|
|
2872
|
-
};
|
|
2873
|
-
|
|
2874
|
-
// src/install/update-engine.ts
|
|
2875
|
-
var checkItemFiles = async (name) => {
|
|
2876
|
-
const item = await findItem(name);
|
|
2877
|
-
const config = await loadConfig();
|
|
2878
|
-
if (!item) {
|
|
2879
|
-
console.log(`Component "${name}" no longer exists in the registry.`);
|
|
2880
|
-
return;
|
|
2881
|
-
}
|
|
2882
|
-
const installTarget = resolveItemInstallTarget(config, item);
|
|
2883
|
-
console.log(`File check for ${item.canonicalName}:`);
|
|
2884
|
-
for (const file of item.files) {
|
|
2885
|
-
const fileName = file.split("/").at(-1);
|
|
2886
|
-
if (!fileName) {
|
|
2887
|
-
console.log(`- invalid registry file path: ${file}`);
|
|
2888
|
-
continue;
|
|
2889
|
-
}
|
|
2890
|
-
const targetPath = join(getCwd(), installTarget, fileName);
|
|
2891
|
-
if (!await fileExists(targetPath)) {
|
|
2892
|
-
console.log(`- missing: ${targetPath}`);
|
|
2893
|
-
continue;
|
|
2894
|
-
}
|
|
2895
|
-
const preparedContent = prepareInstalledFileContent(
|
|
2896
|
-
await readFile(getRegistryTemplatePath(file), "utf-8"),
|
|
2897
|
-
item
|
|
2898
|
-
);
|
|
2899
|
-
const targetContent = await readFile(targetPath, "utf-8");
|
|
2900
|
-
if (hashesAreEqual(preparedContent, targetContent)) {
|
|
2901
|
-
console.log(`- identical: ${targetPath}`);
|
|
2902
|
-
continue;
|
|
2903
|
-
}
|
|
2904
|
-
console.log(`- conflict: ${targetPath}`);
|
|
2905
|
-
}
|
|
2906
|
-
};
|
|
2907
|
-
var applySafeItemUpdate = async (name, force) => {
|
|
2908
|
-
const item = await findItem(name);
|
|
2909
|
-
const config = await loadConfig();
|
|
2910
|
-
if (!item) {
|
|
2911
|
-
console.log(`Component "${name}" no longer exists in the registry.`);
|
|
2912
|
-
return false;
|
|
2913
|
-
}
|
|
2914
|
-
const installTarget = resolveItemInstallTarget(config, item);
|
|
2915
|
-
let hasConflict = false;
|
|
2916
|
-
console.log(`Applying update for ${item.canonicalName}:`);
|
|
2917
|
-
for (const file of item.files) {
|
|
2918
|
-
const sourcePath = getRegistryTemplatePath(file);
|
|
2919
|
-
const fileName = file.split("/").at(-1);
|
|
2920
|
-
if (!fileName) {
|
|
2921
|
-
console.log(`- invalid registry file path: ${file}`);
|
|
2922
|
-
hasConflict = true;
|
|
2923
|
-
continue;
|
|
2924
|
-
}
|
|
2925
|
-
const targetPath = join(getCwd(), installTarget, fileName);
|
|
2926
|
-
const preparedContent = prepareInstalledFileContent(
|
|
2927
|
-
await readFile(sourcePath, "utf-8"),
|
|
2928
|
-
item
|
|
2929
|
-
);
|
|
2930
|
-
await mkdir(dirname(targetPath), { recursive: true });
|
|
2931
|
-
if (!await fileExists(targetPath)) {
|
|
2932
|
-
await writeFile(targetPath, preparedContent, "utf-8");
|
|
2933
|
-
console.log(`- restored missing file: ${targetPath}`);
|
|
2934
|
-
continue;
|
|
2935
|
-
}
|
|
2936
|
-
const targetContent = await readFile(targetPath, "utf-8");
|
|
2937
|
-
if (hashesAreEqual(preparedContent, targetContent)) {
|
|
2938
|
-
console.log(`- identical: ${targetPath}`);
|
|
2939
|
-
continue;
|
|
2940
|
-
}
|
|
2941
|
-
if (force) {
|
|
2942
|
-
const backupPath = await createBackupFile(targetPath);
|
|
2943
|
-
if (backupPath) {
|
|
2944
|
-
console.log(`- backup created: ${backupPath}`);
|
|
2945
|
-
}
|
|
2946
|
-
await writeFile(targetPath, preparedContent, "utf-8");
|
|
2947
|
-
console.log(`- force updated file: ${targetPath}`);
|
|
2948
|
-
continue;
|
|
2949
|
-
}
|
|
2950
|
-
hasConflict = true;
|
|
2951
|
-
console.log(`- conflict (user modified): ${targetPath}`);
|
|
2952
|
-
}
|
|
2953
|
-
if (hasConflict) {
|
|
2954
|
-
console.log(
|
|
2955
|
-
"Update finished with conflicts. Installed version was not changed."
|
|
2956
|
-
);
|
|
2957
|
-
return false;
|
|
2958
|
-
}
|
|
2959
|
-
console.log(
|
|
2960
|
-
`\u2714 ${item.canonicalName} updated successfully to v${item.version}`
|
|
2961
|
-
);
|
|
2962
|
-
return true;
|
|
2963
|
-
};
|
|
2964
|
-
var checkItemUpdate = async (name, installedVersion, dryRun, force, sync = false) => {
|
|
2965
|
-
const item = await findItem(name);
|
|
2966
|
-
if (!item) {
|
|
2967
|
-
console.log(`Component "${name}" no longer exists in the registry.`);
|
|
2968
|
-
return false;
|
|
2969
|
-
}
|
|
2970
|
-
const versionUpdateAvailable = isUpdateAvailable(
|
|
2971
|
-
installedVersion,
|
|
2972
|
-
item.version
|
|
2973
|
-
);
|
|
2974
|
-
if (!sync && !versionUpdateAvailable) {
|
|
2975
|
-
console.log(`${item.canonicalName} is up to date (v${installedVersion}).`);
|
|
2976
|
-
return false;
|
|
2977
|
-
}
|
|
2978
|
-
if (sync && !versionUpdateAvailable) {
|
|
2979
|
-
console.log(
|
|
2980
|
-
`${item.canonicalName} template sync (installed v${installedVersion}, registry v${item.version})`
|
|
2981
|
-
);
|
|
2982
|
-
} else {
|
|
2983
|
-
console.log(
|
|
2984
|
-
`${item.canonicalName} can be updated: v${installedVersion} \u2192 v${item.version}`
|
|
2985
|
-
);
|
|
2986
|
-
}
|
|
2987
|
-
if (dryRun) {
|
|
2988
|
-
console.log("\nChanged file candidates:");
|
|
2989
|
-
for (const file of item.files) {
|
|
2990
|
-
console.log(`~ ${file}`);
|
|
2991
|
-
}
|
|
2992
|
-
console.log("\nDry run: no files will be changed.");
|
|
2993
|
-
console.log("Update plan:");
|
|
2994
|
-
if (force) {
|
|
2995
|
-
console.log(
|
|
2996
|
-
"- Force mode requested: conflicted files require backup before overwrite"
|
|
2997
|
-
);
|
|
2998
|
-
console.log(
|
|
2999
|
-
"- Dry run: backups would be created before forced overwrites"
|
|
3000
|
-
);
|
|
3001
|
-
}
|
|
3002
|
-
console.log(`- Check installed files for ${item.canonicalName}`);
|
|
3003
|
-
console.log("- Compare existing files with registry templates");
|
|
3004
|
-
console.log("- Report conflicts before writing changes");
|
|
3005
|
-
console.log("- Never overwrite user-modified files silently");
|
|
3006
|
-
await checkItemFiles(name);
|
|
3007
|
-
return false;
|
|
3008
|
-
}
|
|
3009
|
-
return await applySafeItemUpdate(name, force);
|
|
3010
|
-
};
|
|
3011
|
-
|
|
3012
3124
|
// src/commands/update.ts
|
|
3013
3125
|
var styleUpdateNames = ["theme"];
|
|
3014
|
-
var
|
|
3015
|
-
|
|
3016
|
-
|
|
3126
|
+
var resolveInstalledKey2 = async (name, installed) => {
|
|
3127
|
+
const direct = findInstalledKey(installed, name);
|
|
3128
|
+
if (direct) {
|
|
3129
|
+
return direct;
|
|
3017
3130
|
}
|
|
3018
3131
|
const item = await findItem(name);
|
|
3019
3132
|
if (!item) {
|
|
3020
3133
|
return void 0;
|
|
3021
3134
|
}
|
|
3022
|
-
return installed
|
|
3135
|
+
return findInstalledKey(installed, item.name);
|
|
3023
3136
|
};
|
|
3024
3137
|
var runStylesUpdate = async (config, dryRun) => {
|
|
3025
3138
|
const styles = resolveRegistryStyles(styleUpdateNames);
|
|
@@ -3046,9 +3159,7 @@ Tailwind CSS entrypoint: ${config.tailwind.css}`);
|
|
|
3046
3159
|
}
|
|
3047
3160
|
};
|
|
3048
3161
|
var runUtilitiesUpdate = async (config, installed, dryRun, force) => {
|
|
3049
|
-
const installedItems = (await Promise.all(
|
|
3050
|
-
Object.keys(installed).map(async (name) => findItem(name))
|
|
3051
|
-
)).filter((item) => Boolean(item));
|
|
3162
|
+
const installedItems = (await Promise.all(installed.map(async (name) => findItem(name)))).filter((item) => Boolean(item));
|
|
3052
3163
|
const utilityNames = collectUtilities(installedItems);
|
|
3053
3164
|
if (!utilityNames.length) {
|
|
3054
3165
|
console.log("No shared utilities are tracked for installed components.");
|
|
@@ -3073,26 +3184,18 @@ var runUtilitiesUpdate = async (config, installed, dryRun, force) => {
|
|
|
3073
3184
|
);
|
|
3074
3185
|
}
|
|
3075
3186
|
};
|
|
3076
|
-
var runComponentUpdates = async (
|
|
3077
|
-
|
|
3078
|
-
if (!Object.keys(installed).length) {
|
|
3187
|
+
var runComponentUpdates = async (installed, targetNames, dryRun, force, sync) => {
|
|
3188
|
+
if (!installed.length) {
|
|
3079
3189
|
console.log("No Lexsys components are currently tracked.");
|
|
3080
|
-
return
|
|
3190
|
+
return;
|
|
3081
3191
|
}
|
|
3082
3192
|
console.log("Checking installed Lexsys components:\n");
|
|
3083
3193
|
for (const name of targetNames) {
|
|
3084
|
-
|
|
3085
|
-
if (!version) {
|
|
3194
|
+
if (!isInstalled(installed, name)) {
|
|
3086
3195
|
continue;
|
|
3087
3196
|
}
|
|
3088
|
-
|
|
3089
|
-
const item = await findItem(name);
|
|
3090
|
-
if (didUpdate && item) {
|
|
3091
|
-
installed[name] = item.version;
|
|
3092
|
-
changed = true;
|
|
3093
|
-
}
|
|
3197
|
+
await checkItemUpdate(name, dryRun, force, sync);
|
|
3094
3198
|
}
|
|
3095
|
-
return changed;
|
|
3096
3199
|
};
|
|
3097
3200
|
var runUpdate = async (args2) => {
|
|
3098
3201
|
const dryRun = hasFlag(args2, "--dry-run", "-d");
|
|
@@ -3120,7 +3223,7 @@ var runUpdate = async (args2) => {
|
|
|
3120
3223
|
"-a"
|
|
3121
3224
|
]);
|
|
3122
3225
|
const config = await loadConfig();
|
|
3123
|
-
const installed =
|
|
3226
|
+
const installed = [...config.installed ?? []];
|
|
3124
3227
|
try {
|
|
3125
3228
|
await getRegistryProviderResult({
|
|
3126
3229
|
fallback: !noFallback
|
|
@@ -3131,29 +3234,24 @@ var runUpdate = async (args2) => {
|
|
|
3131
3234
|
process.exitCode = 1;
|
|
3132
3235
|
return;
|
|
3133
3236
|
}
|
|
3134
|
-
if (yes) {
|
|
3135
|
-
console.log("Auto-confirm mode is enabled.");
|
|
3136
|
-
}
|
|
3137
3237
|
if (!updateAll && !stylesFlag && !utilitiesFlag && targetArgs.length === 0) {
|
|
3138
|
-
|
|
3139
|
-
if (installedNames.length === 0) {
|
|
3238
|
+
if (installed.length === 0) {
|
|
3140
3239
|
console.log(
|
|
3141
3240
|
"No components installed. Run `lexsys add <component>` first."
|
|
3142
3241
|
);
|
|
3143
3242
|
return;
|
|
3144
3243
|
}
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
);
|
|
3244
|
+
if (yes) {
|
|
3245
|
+
targetArgs.push(...installed);
|
|
3246
|
+
} else {
|
|
3247
|
+
const selected = await promptMultiselect(
|
|
3248
|
+
"Select components to update",
|
|
3249
|
+
installed.map((name) => ({ title: name, value: name })),
|
|
3250
|
+
{ min: 1 }
|
|
3251
|
+
);
|
|
3252
|
+
if (!selected.length) return;
|
|
3253
|
+
targetArgs.push(...selected);
|
|
3254
|
+
}
|
|
3157
3255
|
}
|
|
3158
3256
|
const shouldUpdateComponents = updateAll || targetArgs.length > 0;
|
|
3159
3257
|
const resourcesOnly = (stylesFlag || utilitiesFlag) && !shouldUpdateComponents;
|
|
@@ -3175,42 +3273,18 @@ var runUpdate = async (args2) => {
|
|
|
3175
3273
|
if (!shouldUpdateComponents) {
|
|
3176
3274
|
return;
|
|
3177
3275
|
}
|
|
3178
|
-
let changed = false;
|
|
3179
3276
|
if (updateAll) {
|
|
3180
|
-
|
|
3181
|
-
config,
|
|
3182
|
-
installed,
|
|
3183
|
-
Object.keys(installed),
|
|
3184
|
-
dryRun,
|
|
3185
|
-
force,
|
|
3186
|
-
sync
|
|
3187
|
-
);
|
|
3277
|
+
await runComponentUpdates(installed, installed, dryRun, force, sync);
|
|
3188
3278
|
} else {
|
|
3189
3279
|
for (const name of targetArgs) {
|
|
3190
|
-
const installedKey = await
|
|
3280
|
+
const installedKey = await resolveInstalledKey2(name, installed);
|
|
3191
3281
|
if (!installedKey) {
|
|
3192
3282
|
console.log(`Component "${name}" is not tracked as installed.`);
|
|
3193
3283
|
continue;
|
|
3194
3284
|
}
|
|
3195
|
-
|
|
3196
|
-
config,
|
|
3197
|
-
installed,
|
|
3198
|
-
[installedKey],
|
|
3199
|
-
dryRun,
|
|
3200
|
-
force,
|
|
3201
|
-
sync
|
|
3202
|
-
);
|
|
3203
|
-
if (didUpdateOne) {
|
|
3204
|
-
changed = true;
|
|
3205
|
-
}
|
|
3285
|
+
await runComponentUpdates(installed, [installedKey], dryRun, force, sync);
|
|
3206
3286
|
}
|
|
3207
3287
|
}
|
|
3208
|
-
if (changed) {
|
|
3209
|
-
await saveConfig({
|
|
3210
|
-
...config,
|
|
3211
|
-
installed
|
|
3212
|
-
});
|
|
3213
|
-
}
|
|
3214
3288
|
};
|
|
3215
3289
|
var cliDistDir = dirname(fileURLToPath(import.meta.url));
|
|
3216
3290
|
var packageJsonPath = join(cliDistDir, "..", "package.json");
|
|
@@ -3317,6 +3391,14 @@ try {
|
|
|
3317
3391
|
});
|
|
3318
3392
|
process.exit(0);
|
|
3319
3393
|
}
|
|
3394
|
+
if (command === "reset") {
|
|
3395
|
+
if (hasFlag(args, "--help", "-h")) {
|
|
3396
|
+
runHelpFor("reset");
|
|
3397
|
+
process.exit(0);
|
|
3398
|
+
}
|
|
3399
|
+
await runReset(args);
|
|
3400
|
+
process.exit(0);
|
|
3401
|
+
}
|
|
3320
3402
|
if (command === "uninstall" || command === "rm") {
|
|
3321
3403
|
if (hasFlag(args, "--help", "-h")) {
|
|
3322
3404
|
runHelpFor("uninstall");
|
|
@@ -3329,5 +3411,3 @@ try {
|
|
|
3329
3411
|
} catch (error) {
|
|
3330
3412
|
handleCliError(error);
|
|
3331
3413
|
}
|
|
3332
|
-
runHelp();
|
|
3333
|
-
process.exit(1);
|