@nuvio/cli 1.0.0 → 1.1.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/dist/cli-entry.js +887 -117
- package/package.json +4 -3
package/dist/cli-entry.js
CHANGED
|
@@ -1,37 +1,29 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { resolve } from "path";
|
|
4
|
+
import { resolve as resolve4 } from "path";
|
|
5
5
|
|
|
6
|
-
// src/
|
|
7
|
-
import { existsSync } from "fs";
|
|
8
|
-
import { join } from "path";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
case "yarn":
|
|
24
|
-
return `yarn add -D ${pkgs}`;
|
|
25
|
-
case "bun":
|
|
26
|
-
return `bun add -d ${pkgs}`;
|
|
27
|
-
default:
|
|
28
|
-
return `npm install -D ${pkgs}`;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
6
|
+
// src/brand-apply.ts
|
|
7
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
8
|
+
import { join as join2, resolve } from "path";
|
|
9
|
+
import { applyPatchToSource } from "@nuvio/ast-engine";
|
|
10
|
+
import {
|
|
11
|
+
buildBrandPatchOps,
|
|
12
|
+
brandFragmentHostHint,
|
|
13
|
+
DEFAULT_BRAND_CONFIG,
|
|
14
|
+
isHostPatchable,
|
|
15
|
+
isPccBrandableCategory,
|
|
16
|
+
normalizeBrandConfig
|
|
17
|
+
} from "@nuvio/shared";
|
|
18
|
+
import {
|
|
19
|
+
listPccManifestFiles,
|
|
20
|
+
loadPccManifestFromFile,
|
|
21
|
+
resolvePccManifestPath
|
|
22
|
+
} from "@nuvio/shared/load-pcc-manifest";
|
|
31
23
|
|
|
32
24
|
// src/detect-project.ts
|
|
33
|
-
import { existsSync
|
|
34
|
-
import { join
|
|
25
|
+
import { existsSync, readFileSync } from "fs";
|
|
26
|
+
import { join } from "path";
|
|
35
27
|
|
|
36
28
|
// src/messages.ts
|
|
37
29
|
var MSG = {
|
|
@@ -73,8 +65,8 @@ function detectTailwind(root, pkg) {
|
|
|
73
65
|
if (hasDep(pkg, "tailwindcss")) return true;
|
|
74
66
|
const cssCandidates = ["src/index.css", "src/App.css"];
|
|
75
67
|
for (const rel of cssCandidates) {
|
|
76
|
-
const p =
|
|
77
|
-
if (!
|
|
68
|
+
const p = join(root, rel);
|
|
69
|
+
if (!existsSync(p)) continue;
|
|
78
70
|
const text = readFileSync(p, "utf8");
|
|
79
71
|
if (text.includes("@tailwind") || text.includes('@import "tailwindcss"') || text.includes("@import 'tailwindcss'")) {
|
|
80
72
|
return true;
|
|
@@ -83,8 +75,8 @@ function detectTailwind(root, pkg) {
|
|
|
83
75
|
return false;
|
|
84
76
|
}
|
|
85
77
|
function detectProject(root) {
|
|
86
|
-
const packageJsonPath =
|
|
87
|
-
if (!
|
|
78
|
+
const packageJsonPath = join(root, "package.json");
|
|
79
|
+
if (!existsSync(packageJsonPath)) {
|
|
88
80
|
throw new PreflightError(MSG.noPackageJson);
|
|
89
81
|
}
|
|
90
82
|
const packageJson = JSON.parse(
|
|
@@ -99,8 +91,8 @@ function detectProject(root) {
|
|
|
99
91
|
let viteConfigPath = "";
|
|
100
92
|
let viteConfigName = "";
|
|
101
93
|
for (const name of VITE_CONFIGS) {
|
|
102
|
-
const p =
|
|
103
|
-
if (
|
|
94
|
+
const p = join(root, name);
|
|
95
|
+
if (existsSync(p)) {
|
|
104
96
|
viteConfigPath = p;
|
|
105
97
|
viteConfigName = name;
|
|
106
98
|
break;
|
|
@@ -127,32 +119,6 @@ function detectProject(root) {
|
|
|
127
119
|
};
|
|
128
120
|
}
|
|
129
121
|
|
|
130
|
-
// src/nuvio-deps.ts
|
|
131
|
-
import { readFileSync as readFileSync2 } from "fs";
|
|
132
|
-
function readPackageJson(packageJsonPath) {
|
|
133
|
-
return JSON.parse(readFileSync2(packageJsonPath, "utf8"));
|
|
134
|
-
}
|
|
135
|
-
function getDependencyVersion(pkg, name) {
|
|
136
|
-
const deps = pkg.dependencies;
|
|
137
|
-
const devDeps = pkg.devDependencies;
|
|
138
|
-
return deps?.[name] ?? devDeps?.[name];
|
|
139
|
-
}
|
|
140
|
-
function hasNuvioDependency(pkg, name) {
|
|
141
|
-
return Boolean(getDependencyVersion(pkg, name));
|
|
142
|
-
}
|
|
143
|
-
function hasNuvioPackages(pkg) {
|
|
144
|
-
return hasNuvioDependency(pkg, "@nuvio/vite-plugin") && hasNuvioDependency(pkg, "@nuvio/overlay");
|
|
145
|
-
}
|
|
146
|
-
function isWorkspaceLinkedVersion(version) {
|
|
147
|
-
if (!version) return false;
|
|
148
|
-
return version.startsWith("workspace:") || version.startsWith("link:") || version.startsWith("file:");
|
|
149
|
-
}
|
|
150
|
-
function nuvioOverlayLinkKind(pkg) {
|
|
151
|
-
const raw = getDependencyVersion(pkg, "@nuvio/overlay");
|
|
152
|
-
if (!raw) return "missing";
|
|
153
|
-
return isWorkspaceLinkedVersion(raw) ? "workspace" : "npm";
|
|
154
|
-
}
|
|
155
|
-
|
|
156
122
|
// src/project-scan.ts
|
|
157
123
|
import { relative } from "path";
|
|
158
124
|
import {
|
|
@@ -182,10 +148,639 @@ function aggregateClassNameModes(entries) {
|
|
|
182
148
|
return counts;
|
|
183
149
|
}
|
|
184
150
|
|
|
151
|
+
// src/brand-apply.ts
|
|
152
|
+
var BRAND_RELATIVE = "nuvio/brand.json";
|
|
153
|
+
function readProjectBrandConfig(cwd) {
|
|
154
|
+
const filePath = join2(resolve(cwd), BRAND_RELATIVE);
|
|
155
|
+
if (!existsSync2(filePath)) {
|
|
156
|
+
return { ...DEFAULT_BRAND_CONFIG };
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
const raw = readFileSync2(filePath, "utf8");
|
|
160
|
+
return normalizeBrandConfig(JSON.parse(raw));
|
|
161
|
+
} catch {
|
|
162
|
+
return { ...DEFAULT_BRAND_CONFIG };
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function duplicateIdSet(errors) {
|
|
166
|
+
return new Set(errors.map((error) => error.id));
|
|
167
|
+
}
|
|
168
|
+
function collectApplyTargets(manifest, entries, duplicateIds) {
|
|
169
|
+
const byId = new Map(entries.map((entry) => [entry.id, entry]));
|
|
170
|
+
const targets = [];
|
|
171
|
+
let skipped = 0;
|
|
172
|
+
for (const category of Object.keys(manifest.categories)) {
|
|
173
|
+
if (!isPccBrandableCategory(category)) {
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
const config = manifest.categories[category];
|
|
177
|
+
if (!config) {
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
for (const hostId of config.hosts) {
|
|
181
|
+
const entry = byId.get(hostId);
|
|
182
|
+
if (!entry) {
|
|
183
|
+
skipped += 1;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
const patch = isHostPatchable(entry, duplicateIds);
|
|
187
|
+
if (!patch.patchable) {
|
|
188
|
+
skipped += 1;
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
targets.push({
|
|
192
|
+
hostId,
|
|
193
|
+
category,
|
|
194
|
+
action: category,
|
|
195
|
+
entry
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return { targets, skipped };
|
|
200
|
+
}
|
|
201
|
+
async function applyTargetsToProject(projectRoot, targets, brand, dryRun) {
|
|
202
|
+
const root = resolve(projectRoot);
|
|
203
|
+
const byFile = /* @__PURE__ */ new Map();
|
|
204
|
+
for (const target of targets) {
|
|
205
|
+
const filePath = resolve(root, target.entry.file);
|
|
206
|
+
const list = byFile.get(filePath) ?? [];
|
|
207
|
+
list.push(target);
|
|
208
|
+
byFile.set(filePath, list);
|
|
209
|
+
}
|
|
210
|
+
let applied = 0;
|
|
211
|
+
const failed = [];
|
|
212
|
+
for (const [filePath, fileTargets] of byFile) {
|
|
213
|
+
if (!existsSync2(filePath)) {
|
|
214
|
+
for (const target of fileTargets) {
|
|
215
|
+
failed.push({ hostId: target.hostId, reason: "file_missing" });
|
|
216
|
+
}
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
if (dryRun) {
|
|
220
|
+
applied += fileTargets.length;
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
let source = readFileSync2(filePath, "utf8");
|
|
224
|
+
for (const target of fileTargets) {
|
|
225
|
+
const ops = buildBrandPatchOps(
|
|
226
|
+
target.action,
|
|
227
|
+
brand,
|
|
228
|
+
brandFragmentHostHint(target.entry)
|
|
229
|
+
);
|
|
230
|
+
const result = await applyPatchToSource(source, filePath, target.hostId, ops, {
|
|
231
|
+
classNameMode: target.entry.classNameMode
|
|
232
|
+
});
|
|
233
|
+
if (!result.ok) {
|
|
234
|
+
failed.push({ hostId: target.hostId, reason: result.message ?? result.code });
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
source = result.source;
|
|
238
|
+
applied += 1;
|
|
239
|
+
}
|
|
240
|
+
writeFileSync(filePath, source, "utf8");
|
|
241
|
+
}
|
|
242
|
+
return { applied, failed };
|
|
243
|
+
}
|
|
244
|
+
function printHumanReport(result) {
|
|
245
|
+
console.log(`Page: ${result.page}`);
|
|
246
|
+
console.log(`Route: ${result.route}`);
|
|
247
|
+
console.log(`Manifest: ${result.manifestPath}`);
|
|
248
|
+
console.log(`Applied: ${result.applied}`);
|
|
249
|
+
console.log(`Skipped: ${result.skipped}`);
|
|
250
|
+
if (result.failed.length > 0) {
|
|
251
|
+
console.log("Failed:");
|
|
252
|
+
for (const failure of result.failed) {
|
|
253
|
+
console.log(`- ${failure.hostId}: ${failure.reason}`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
async function applyLoadedManifest(manifestPath, manifest, entries, duplicateIds, brand, projectRoot, opts) {
|
|
258
|
+
const { targets, skipped } = collectApplyTargets(manifest, entries, duplicateIds);
|
|
259
|
+
const { applied, failed } = await applyTargetsToProject(
|
|
260
|
+
projectRoot,
|
|
261
|
+
targets,
|
|
262
|
+
brand,
|
|
263
|
+
opts.dryRun === true
|
|
264
|
+
);
|
|
265
|
+
return {
|
|
266
|
+
page: manifest.page,
|
|
267
|
+
route: manifest.route,
|
|
268
|
+
manifestPath,
|
|
269
|
+
applied,
|
|
270
|
+
skipped,
|
|
271
|
+
failed
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
async function runBrandApplyAll(opts) {
|
|
275
|
+
const manifestPaths = listPccManifestFiles(opts.cwd);
|
|
276
|
+
if (manifestPaths.length === 0) {
|
|
277
|
+
console.error(`No PCC manifests found under ${resolve(opts.cwd)}/nuvio/pages`);
|
|
278
|
+
return 2;
|
|
279
|
+
}
|
|
280
|
+
const brand = readProjectBrandConfig(opts.cwd);
|
|
281
|
+
let scan;
|
|
282
|
+
try {
|
|
283
|
+
scan = scanProject(opts.cwd);
|
|
284
|
+
} catch (e) {
|
|
285
|
+
if (e instanceof PreflightError) {
|
|
286
|
+
console.error(e.message);
|
|
287
|
+
return 3;
|
|
288
|
+
}
|
|
289
|
+
throw e;
|
|
290
|
+
}
|
|
291
|
+
const duplicateIds = duplicateIdSet(scan.index.duplicateErrors);
|
|
292
|
+
const pages = [];
|
|
293
|
+
for (const manifestPath of manifestPaths) {
|
|
294
|
+
const loaded = loadPccManifestFromFile(manifestPath);
|
|
295
|
+
if (!loaded.ok) {
|
|
296
|
+
console.error(`Invalid PCC manifest (${manifestPath}): ${loaded.error.message}`);
|
|
297
|
+
return 2;
|
|
298
|
+
}
|
|
299
|
+
pages.push(
|
|
300
|
+
await applyLoadedManifest(
|
|
301
|
+
manifestPath,
|
|
302
|
+
loaded.manifest,
|
|
303
|
+
scan.index.entries,
|
|
304
|
+
duplicateIds,
|
|
305
|
+
brand,
|
|
306
|
+
scan.ctx.root,
|
|
307
|
+
opts
|
|
308
|
+
)
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
const pass = pages.every((page) => page.failed.length === 0);
|
|
312
|
+
if (opts.json) {
|
|
313
|
+
console.log(JSON.stringify({ pass, dryRun: opts.dryRun === true, pages }, null, 2));
|
|
314
|
+
return pass ? 0 : 1;
|
|
315
|
+
}
|
|
316
|
+
console.log(`Nuvio Brand Apply${opts.dryRun ? " (dry run)" : ""}
|
|
317
|
+
`);
|
|
318
|
+
for (const page of pages) {
|
|
319
|
+
printHumanReport(page);
|
|
320
|
+
console.log("");
|
|
321
|
+
}
|
|
322
|
+
console.log(`Result: ${pass ? "PASS" : "FAIL"}`);
|
|
323
|
+
return pass ? 0 : 1;
|
|
324
|
+
}
|
|
325
|
+
async function runBrandApply(opts) {
|
|
326
|
+
if (opts.all) {
|
|
327
|
+
return runBrandApplyAll(opts);
|
|
328
|
+
}
|
|
329
|
+
let manifestPath;
|
|
330
|
+
try {
|
|
331
|
+
manifestPath = resolve(
|
|
332
|
+
resolvePccManifestPath(opts.cwd, { page: opts.page, manifest: opts.manifest })
|
|
333
|
+
);
|
|
334
|
+
} catch (e) {
|
|
335
|
+
console.error(e instanceof Error ? e.message : String(e));
|
|
336
|
+
return 2;
|
|
337
|
+
}
|
|
338
|
+
const loaded = loadPccManifestFromFile(manifestPath);
|
|
339
|
+
if (!loaded.ok) {
|
|
340
|
+
console.error(`Invalid PCC manifest (${manifestPath}): ${loaded.error.message}`);
|
|
341
|
+
return 2;
|
|
342
|
+
}
|
|
343
|
+
const brand = readProjectBrandConfig(opts.cwd);
|
|
344
|
+
let scan;
|
|
345
|
+
try {
|
|
346
|
+
scan = scanProject(opts.cwd);
|
|
347
|
+
} catch (e) {
|
|
348
|
+
if (e instanceof PreflightError) {
|
|
349
|
+
console.error(e.message);
|
|
350
|
+
return 3;
|
|
351
|
+
}
|
|
352
|
+
throw e;
|
|
353
|
+
}
|
|
354
|
+
const duplicateIds = duplicateIdSet(scan.index.duplicateErrors);
|
|
355
|
+
const result = await applyLoadedManifest(
|
|
356
|
+
manifestPath,
|
|
357
|
+
loaded.manifest,
|
|
358
|
+
scan.index.entries,
|
|
359
|
+
duplicateIds,
|
|
360
|
+
brand,
|
|
361
|
+
scan.ctx.root,
|
|
362
|
+
opts
|
|
363
|
+
);
|
|
364
|
+
const pass = result.failed.length === 0;
|
|
365
|
+
if (opts.json) {
|
|
366
|
+
console.log(JSON.stringify({ pass, dryRun: opts.dryRun === true, ...result }, null, 2));
|
|
367
|
+
return pass ? 0 : 1;
|
|
368
|
+
}
|
|
369
|
+
console.log(`Nuvio Brand Apply${opts.dryRun ? " (dry run)" : ""}
|
|
370
|
+
`);
|
|
371
|
+
printHumanReport(result);
|
|
372
|
+
console.log(`
|
|
373
|
+
Result: ${pass ? "PASS" : "FAIL"}`);
|
|
374
|
+
return pass ? 0 : 1;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// src/brand-scan.ts
|
|
378
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
379
|
+
import { join as join3, resolve as resolve2 } from "path";
|
|
380
|
+
import {
|
|
381
|
+
DEFAULT_BRAND_CONFIG as DEFAULT_BRAND_CONFIG2,
|
|
382
|
+
evaluateBrandPageScan,
|
|
383
|
+
getBrandColorLabel,
|
|
384
|
+
getBrandDensityLabel,
|
|
385
|
+
getBrandRadiusLabel,
|
|
386
|
+
getBrandTypographyLabel,
|
|
387
|
+
normalizeBrandConfig as normalizeBrandConfig2,
|
|
388
|
+
pccCategoryLabel
|
|
389
|
+
} from "@nuvio/shared";
|
|
390
|
+
import {
|
|
391
|
+
listPccManifestFiles as listPccManifestFiles2,
|
|
392
|
+
loadPccManifestFromFile as loadPccManifestFromFile2,
|
|
393
|
+
resolvePccManifestPath as resolvePccManifestPath2
|
|
394
|
+
} from "@nuvio/shared/load-pcc-manifest";
|
|
395
|
+
var BRAND_RELATIVE2 = "nuvio/brand.json";
|
|
396
|
+
function readProjectBrandConfig2(cwd) {
|
|
397
|
+
const filePath = join3(resolve2(cwd), BRAND_RELATIVE2);
|
|
398
|
+
if (!existsSync3(filePath)) {
|
|
399
|
+
return { ...DEFAULT_BRAND_CONFIG2 };
|
|
400
|
+
}
|
|
401
|
+
try {
|
|
402
|
+
const raw = readFileSync3(filePath, "utf8");
|
|
403
|
+
return normalizeBrandConfig2(JSON.parse(raw));
|
|
404
|
+
} catch {
|
|
405
|
+
return { ...DEFAULT_BRAND_CONFIG2 };
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
function formatBrandSummary(brand) {
|
|
409
|
+
return [
|
|
410
|
+
getBrandColorLabel(brand.color),
|
|
411
|
+
getBrandRadiusLabel(brand.radius),
|
|
412
|
+
getBrandDensityLabel(brand.density),
|
|
413
|
+
getBrandTypographyLabel(brand.typography)
|
|
414
|
+
].join(" \xB7 ");
|
|
415
|
+
}
|
|
416
|
+
function printHumanReport2(result, manifestPath) {
|
|
417
|
+
console.log("Nuvio Brand Scan\n");
|
|
418
|
+
console.log(`Page: ${result.page}`);
|
|
419
|
+
console.log(`Route: ${result.route}`);
|
|
420
|
+
console.log(`Manifest: ${manifestPath}`);
|
|
421
|
+
console.log(`Saved brand: ${formatBrandSummary(result.brand)}
|
|
422
|
+
`);
|
|
423
|
+
console.log("Category summary:");
|
|
424
|
+
for (const category of result.categories) {
|
|
425
|
+
const label = pccCategoryLabel(category.category).padEnd(10);
|
|
426
|
+
const status = category.pass ? "PASS" : "FAIL";
|
|
427
|
+
console.log(
|
|
428
|
+
`${label} ${status} on-brand ${category.onBrand}/${category.expected} \xB7 off-brand ${category.offBrand} \xB7 no-traits ${category.noTraits}`
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
console.log("\nTotals:");
|
|
432
|
+
console.log(`On-brand ${result.onBrandCount}`);
|
|
433
|
+
console.log(`Off-brand ${result.offBrandCount}`);
|
|
434
|
+
console.log(`No traits ${result.noTraitsCount}`);
|
|
435
|
+
console.log(`Missing ${result.missingCount}`);
|
|
436
|
+
const offBrandHosts = result.hosts.filter((host) => host.status === "off_brand");
|
|
437
|
+
if (offBrandHosts.length > 0) {
|
|
438
|
+
console.log("\nOff-brand hosts:");
|
|
439
|
+
for (const host of offBrandHosts.slice(0, 12)) {
|
|
440
|
+
const headline = host.inspect?.headline ?? "Off-brand";
|
|
441
|
+
console.log(`- ${host.hostId} (${host.category}) \u2014 ${headline}`);
|
|
442
|
+
}
|
|
443
|
+
if (offBrandHosts.length > 12) {
|
|
444
|
+
console.log(`\u2026and ${offBrandHosts.length - 12} more`);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
console.log(`
|
|
448
|
+
Result: ${result.pass ? "PASS" : "FAIL"}`);
|
|
449
|
+
}
|
|
450
|
+
function printAllHumanReport(pages) {
|
|
451
|
+
console.log("Nuvio Brand Scan (all pages)\n");
|
|
452
|
+
for (const page of pages) {
|
|
453
|
+
const status = page.result.pass ? "PASS" : "FAIL";
|
|
454
|
+
const summary = `${page.result.onBrandCount} on-brand \xB7 ${page.result.offBrandCount} off-brand`;
|
|
455
|
+
console.log(`${page.result.page.padEnd(16)} ${status} ${summary}`);
|
|
456
|
+
}
|
|
457
|
+
const pass = pages.every((page) => page.result.pass);
|
|
458
|
+
console.log(`
|
|
459
|
+
Result: ${pass ? "PASS" : "FAIL"}`);
|
|
460
|
+
}
|
|
461
|
+
function scanLoadedManifest(manifestPath, entries, brand) {
|
|
462
|
+
const loaded = loadPccManifestFromFile2(manifestPath);
|
|
463
|
+
if (!loaded.ok) {
|
|
464
|
+
return {
|
|
465
|
+
ok: false,
|
|
466
|
+
code: 2,
|
|
467
|
+
message: `Invalid PCC manifest (${manifestPath}): ${loaded.error.message}`
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
return {
|
|
471
|
+
ok: true,
|
|
472
|
+
result: evaluateBrandPageScan(loaded.manifest, entries, brand)
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
function runBrandScanAll(opts) {
|
|
476
|
+
const manifestPaths = listPccManifestFiles2(opts.cwd);
|
|
477
|
+
if (manifestPaths.length === 0) {
|
|
478
|
+
console.error(`No PCC manifests found under ${resolve2(opts.cwd)}/nuvio/pages`);
|
|
479
|
+
return 2;
|
|
480
|
+
}
|
|
481
|
+
const brand = readProjectBrandConfig2(opts.cwd);
|
|
482
|
+
let scan;
|
|
483
|
+
try {
|
|
484
|
+
scan = scanProject(opts.cwd);
|
|
485
|
+
} catch (e) {
|
|
486
|
+
if (e instanceof PreflightError) {
|
|
487
|
+
console.error(e.message);
|
|
488
|
+
return 3;
|
|
489
|
+
}
|
|
490
|
+
throw e;
|
|
491
|
+
}
|
|
492
|
+
const pages = [];
|
|
493
|
+
for (const manifestPath of manifestPaths) {
|
|
494
|
+
const scanned = scanLoadedManifest(manifestPath, scan.index.entries, brand);
|
|
495
|
+
if (!scanned.ok) {
|
|
496
|
+
console.error(scanned.message);
|
|
497
|
+
return scanned.code;
|
|
498
|
+
}
|
|
499
|
+
pages.push({ manifestPath, result: scanned.result });
|
|
500
|
+
}
|
|
501
|
+
const pass = pages.every((page) => page.result.pass);
|
|
502
|
+
if (opts.json) {
|
|
503
|
+
console.log(JSON.stringify({ pass, brand, pages }, null, 2));
|
|
504
|
+
return pass ? 0 : 1;
|
|
505
|
+
}
|
|
506
|
+
printAllHumanReport(pages);
|
|
507
|
+
return pass ? 0 : 1;
|
|
508
|
+
}
|
|
509
|
+
function runBrandScan(opts) {
|
|
510
|
+
if (opts.all) {
|
|
511
|
+
return runBrandScanAll(opts);
|
|
512
|
+
}
|
|
513
|
+
let manifestPath;
|
|
514
|
+
try {
|
|
515
|
+
manifestPath = resolve2(
|
|
516
|
+
resolvePccManifestPath2(opts.cwd, { page: opts.page, manifest: opts.manifest })
|
|
517
|
+
);
|
|
518
|
+
} catch (e) {
|
|
519
|
+
console.error(e instanceof Error ? e.message : String(e));
|
|
520
|
+
return 2;
|
|
521
|
+
}
|
|
522
|
+
const brand = readProjectBrandConfig2(opts.cwd);
|
|
523
|
+
let scan;
|
|
524
|
+
try {
|
|
525
|
+
scan = scanProject(opts.cwd);
|
|
526
|
+
} catch (e) {
|
|
527
|
+
if (e instanceof PreflightError) {
|
|
528
|
+
console.error(e.message);
|
|
529
|
+
return 3;
|
|
530
|
+
}
|
|
531
|
+
throw e;
|
|
532
|
+
}
|
|
533
|
+
const scanned = scanLoadedManifest(manifestPath, scan.index.entries, brand);
|
|
534
|
+
if (!scanned.ok) {
|
|
535
|
+
console.error(scanned.message);
|
|
536
|
+
return scanned.code;
|
|
537
|
+
}
|
|
538
|
+
if (opts.json) {
|
|
539
|
+
console.log(
|
|
540
|
+
JSON.stringify(
|
|
541
|
+
{
|
|
542
|
+
manifestPath,
|
|
543
|
+
...scanned.result
|
|
544
|
+
},
|
|
545
|
+
null,
|
|
546
|
+
2
|
|
547
|
+
)
|
|
548
|
+
);
|
|
549
|
+
return scanned.result.pass ? 0 : 1;
|
|
550
|
+
}
|
|
551
|
+
printHumanReport2(scanned.result, manifestPath);
|
|
552
|
+
return scanned.result.pass ? 0 : 1;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// src/coverage-verify.ts
|
|
556
|
+
import { resolve as resolve3 } from "path";
|
|
557
|
+
import {
|
|
558
|
+
evaluatePageCoverage,
|
|
559
|
+
pccCategoryLabel as pccCategoryLabel2
|
|
560
|
+
} from "@nuvio/shared";
|
|
561
|
+
import {
|
|
562
|
+
listPccManifestFiles as listPccManifestFiles3,
|
|
563
|
+
loadPccManifestFromFile as loadPccManifestFromFile3,
|
|
564
|
+
resolvePccManifestPath as resolvePccManifestPath3
|
|
565
|
+
} from "@nuvio/shared/load-pcc-manifest";
|
|
566
|
+
function formatCategoryLine(summary) {
|
|
567
|
+
const label = pccCategoryLabel2(summary.category).padEnd(10);
|
|
568
|
+
const status = summary.pass ? "PASS" : "FAIL";
|
|
569
|
+
return `${label} ${status} ${summary.indexed}/${summary.expected}`;
|
|
570
|
+
}
|
|
571
|
+
function printHumanReport3(result, manifestPath) {
|
|
572
|
+
console.log("Nuvio Coverage Report\n");
|
|
573
|
+
console.log(`Page: ${result.page}`);
|
|
574
|
+
console.log(`Route: ${result.route}`);
|
|
575
|
+
console.log(`Manifest: ${manifestPath}
|
|
576
|
+
`);
|
|
577
|
+
console.log("Category summary:");
|
|
578
|
+
for (const category of result.categories) {
|
|
579
|
+
console.log(formatCategoryLine(category));
|
|
580
|
+
}
|
|
581
|
+
console.log("\nCoverage gates:");
|
|
582
|
+
const g = result.gates;
|
|
583
|
+
console.log(`Indexed ${g.indexed}/${g.expected}`);
|
|
584
|
+
console.log(`Patchable ${g.patchable}/${g.expected}`);
|
|
585
|
+
console.log(`Categorized ${g.categorized}/${g.expected}`);
|
|
586
|
+
console.log(`Editable ${g.editable}/${g.expected}`);
|
|
587
|
+
console.log(`Brandable ${g.brandable}/${g.expected}`);
|
|
588
|
+
console.log("\nBrandability:");
|
|
589
|
+
console.log(`Brandable ${result.brandableCount}`);
|
|
590
|
+
console.log(`Editable-only ${result.editableOnlyCount}`);
|
|
591
|
+
const missing = result.issues.filter((i) => i.kind === "missing");
|
|
592
|
+
const unpatchable = result.issues.filter((i) => i.kind === "unpatchable");
|
|
593
|
+
const duplicates = result.issues.filter((i) => i.kind === "duplicate_id");
|
|
594
|
+
if (missing.length > 0) {
|
|
595
|
+
console.log("\nMissing hosts:");
|
|
596
|
+
for (const issue of missing) {
|
|
597
|
+
console.log(`- ${issue.hostId} (${issue.category})`);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
if (unpatchable.length > 0) {
|
|
601
|
+
console.log("\nUnpatchable hosts:");
|
|
602
|
+
for (const issue of unpatchable) {
|
|
603
|
+
console.log(`- ${issue.hostId}`);
|
|
604
|
+
if (issue.reason) {
|
|
605
|
+
console.log(` reason: ${issue.reason}`);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
if (duplicates.length > 0) {
|
|
610
|
+
console.log("\nDuplicate id hosts:");
|
|
611
|
+
for (const issue of duplicates) {
|
|
612
|
+
console.log(`- ${issue.hostId}`);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
console.log(`
|
|
616
|
+
Result: ${result.pass ? "PASS" : "FAIL"}`);
|
|
617
|
+
}
|
|
618
|
+
function printAllHumanReport2(summary) {
|
|
619
|
+
console.log("Nuvio Coverage Report (all pages)\n");
|
|
620
|
+
for (const entry of summary.pages) {
|
|
621
|
+
const status = entry.result.pass ? "PASS" : "FAIL";
|
|
622
|
+
console.log(`${entry.result.page.padEnd(16)} ${status} ${entry.manifestPath}`);
|
|
623
|
+
}
|
|
624
|
+
console.log(`
|
|
625
|
+
Result: ${summary.pass ? "PASS" : "FAIL"}`);
|
|
626
|
+
}
|
|
627
|
+
function verifyLoadedManifest(manifestPath, entries, duplicateErrors) {
|
|
628
|
+
const loaded = loadPccManifestFromFile3(manifestPath);
|
|
629
|
+
if (!loaded.ok) {
|
|
630
|
+
return {
|
|
631
|
+
ok: false,
|
|
632
|
+
code: 2,
|
|
633
|
+
message: `Invalid PCC manifest (${manifestPath}): ${loaded.error.message}`
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
const result = evaluatePageCoverage(loaded.manifest, entries, duplicateErrors);
|
|
637
|
+
return { ok: true, result };
|
|
638
|
+
}
|
|
639
|
+
function runCoverageVerifyAll(opts) {
|
|
640
|
+
const manifestPaths = listPccManifestFiles3(opts.cwd);
|
|
641
|
+
if (manifestPaths.length === 0) {
|
|
642
|
+
console.error(`No PCC manifests found under ${resolve3(opts.cwd)}/nuvio/pages`);
|
|
643
|
+
return 2;
|
|
644
|
+
}
|
|
645
|
+
let scan;
|
|
646
|
+
try {
|
|
647
|
+
scan = scanProject(opts.cwd);
|
|
648
|
+
} catch (e) {
|
|
649
|
+
if (e instanceof PreflightError) {
|
|
650
|
+
console.error(e.message);
|
|
651
|
+
return 3;
|
|
652
|
+
}
|
|
653
|
+
throw e;
|
|
654
|
+
}
|
|
655
|
+
const pages = [];
|
|
656
|
+
for (const manifestPath of manifestPaths) {
|
|
657
|
+
const verified = verifyLoadedManifest(
|
|
658
|
+
manifestPath,
|
|
659
|
+
scan.index.entries,
|
|
660
|
+
scan.index.duplicateErrors
|
|
661
|
+
);
|
|
662
|
+
if (!verified.ok) {
|
|
663
|
+
console.error(verified.message);
|
|
664
|
+
return verified.code;
|
|
665
|
+
}
|
|
666
|
+
pages.push({ manifestPath, result: verified.result });
|
|
667
|
+
}
|
|
668
|
+
const summary = {
|
|
669
|
+
pass: pages.every((page) => page.result.pass),
|
|
670
|
+
pages
|
|
671
|
+
};
|
|
672
|
+
if (opts.json) {
|
|
673
|
+
console.log(JSON.stringify(summary, null, 2));
|
|
674
|
+
return summary.pass ? 0 : 1;
|
|
675
|
+
}
|
|
676
|
+
printAllHumanReport2(summary);
|
|
677
|
+
return summary.pass ? 0 : 1;
|
|
678
|
+
}
|
|
679
|
+
function runCoverageVerify(opts) {
|
|
680
|
+
if (opts.all) {
|
|
681
|
+
return runCoverageVerifyAll(opts);
|
|
682
|
+
}
|
|
683
|
+
let manifestPath;
|
|
684
|
+
try {
|
|
685
|
+
manifestPath = resolve3(
|
|
686
|
+
resolvePccManifestPath3(opts.cwd, { page: opts.page, manifest: opts.manifest })
|
|
687
|
+
);
|
|
688
|
+
} catch (e) {
|
|
689
|
+
console.error(e instanceof Error ? e.message : String(e));
|
|
690
|
+
return 2;
|
|
691
|
+
}
|
|
692
|
+
let scan;
|
|
693
|
+
try {
|
|
694
|
+
scan = scanProject(opts.cwd);
|
|
695
|
+
} catch (e) {
|
|
696
|
+
if (e instanceof PreflightError) {
|
|
697
|
+
console.error(e.message);
|
|
698
|
+
return 3;
|
|
699
|
+
}
|
|
700
|
+
throw e;
|
|
701
|
+
}
|
|
702
|
+
const verified = verifyLoadedManifest(
|
|
703
|
+
manifestPath,
|
|
704
|
+
scan.index.entries,
|
|
705
|
+
scan.index.duplicateErrors
|
|
706
|
+
);
|
|
707
|
+
if (!verified.ok) {
|
|
708
|
+
console.error(verified.message);
|
|
709
|
+
return verified.code;
|
|
710
|
+
}
|
|
711
|
+
if (opts.json) {
|
|
712
|
+
console.log(
|
|
713
|
+
JSON.stringify(
|
|
714
|
+
{
|
|
715
|
+
manifestPath,
|
|
716
|
+
...verified.result
|
|
717
|
+
},
|
|
718
|
+
null,
|
|
719
|
+
2
|
|
720
|
+
)
|
|
721
|
+
);
|
|
722
|
+
return verified.result.pass ? 0 : 1;
|
|
723
|
+
}
|
|
724
|
+
printHumanReport3(verified.result, manifestPath);
|
|
725
|
+
return verified.result.pass ? 0 : 1;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
// src/detect-pm.ts
|
|
729
|
+
import { existsSync as existsSync4 } from "fs";
|
|
730
|
+
import { join as join4 } from "path";
|
|
731
|
+
function detectPackageManager(root, override) {
|
|
732
|
+
if (override) return override;
|
|
733
|
+
if (existsSync4(join4(root, "pnpm-lock.yaml"))) return "pnpm";
|
|
734
|
+
if (existsSync4(join4(root, "package-lock.json"))) return "npm";
|
|
735
|
+
if (existsSync4(join4(root, "yarn.lock"))) return "yarn";
|
|
736
|
+
if (existsSync4(join4(root, "bun.lockb")) || existsSync4(join4(root, "bun.lock")))
|
|
737
|
+
return "bun";
|
|
738
|
+
return "npm";
|
|
739
|
+
}
|
|
740
|
+
function installCommand(pm, version) {
|
|
741
|
+
const pkgs = `@nuvio/vite-plugin@${version} @nuvio/overlay@${version}`;
|
|
742
|
+
switch (pm) {
|
|
743
|
+
case "pnpm":
|
|
744
|
+
return `pnpm add -D ${pkgs}`;
|
|
745
|
+
case "yarn":
|
|
746
|
+
return `yarn add -D ${pkgs}`;
|
|
747
|
+
case "bun":
|
|
748
|
+
return `bun add -d ${pkgs}`;
|
|
749
|
+
default:
|
|
750
|
+
return `npm install -D ${pkgs}`;
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
// src/nuvio-deps.ts
|
|
755
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
756
|
+
function readPackageJson(packageJsonPath) {
|
|
757
|
+
return JSON.parse(readFileSync4(packageJsonPath, "utf8"));
|
|
758
|
+
}
|
|
759
|
+
function getDependencyVersion(pkg, name) {
|
|
760
|
+
const deps = pkg.dependencies;
|
|
761
|
+
const devDeps = pkg.devDependencies;
|
|
762
|
+
return deps?.[name] ?? devDeps?.[name];
|
|
763
|
+
}
|
|
764
|
+
function hasNuvioDependency(pkg, name) {
|
|
765
|
+
return Boolean(getDependencyVersion(pkg, name));
|
|
766
|
+
}
|
|
767
|
+
function hasNuvioPackages(pkg) {
|
|
768
|
+
return hasNuvioDependency(pkg, "@nuvio/vite-plugin") && hasNuvioDependency(pkg, "@nuvio/overlay");
|
|
769
|
+
}
|
|
770
|
+
function isWorkspaceLinkedVersion(version) {
|
|
771
|
+
if (!version) return false;
|
|
772
|
+
return version.startsWith("workspace:") || version.startsWith("link:") || version.startsWith("file:");
|
|
773
|
+
}
|
|
774
|
+
function nuvioOverlayLinkKind(pkg) {
|
|
775
|
+
const raw = getDependencyVersion(pkg, "@nuvio/overlay");
|
|
776
|
+
if (!raw) return "missing";
|
|
777
|
+
return isWorkspaceLinkedVersion(raw) ? "workspace" : "npm";
|
|
778
|
+
}
|
|
779
|
+
|
|
185
780
|
// src/telemetry.ts
|
|
186
|
-
import { mkdirSync, readFileSync as
|
|
781
|
+
import { mkdirSync, readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
|
|
187
782
|
import { homedir } from "os";
|
|
188
|
-
import { join as
|
|
783
|
+
import { join as join5 } from "path";
|
|
189
784
|
import { randomUUID } from "crypto";
|
|
190
785
|
import os from "os";
|
|
191
786
|
import { PostHog } from "posthog-node";
|
|
@@ -201,7 +796,7 @@ var NUVIO_VERSION = require2("../package.json").version;
|
|
|
201
796
|
// src/telemetry.ts
|
|
202
797
|
var POSTHOG_HOST = "https://us.i.posthog.com";
|
|
203
798
|
function telemetryFilePath() {
|
|
204
|
-
return
|
|
799
|
+
return join5(homedir(), ".nuvio", "telemetry.json");
|
|
205
800
|
}
|
|
206
801
|
var FORBIDDEN_PROP_KEYS = /* @__PURE__ */ new Set([
|
|
207
802
|
"cwd",
|
|
@@ -240,7 +835,7 @@ function tokenIsConfigured(token) {
|
|
|
240
835
|
function readOrCreateAnonymousId() {
|
|
241
836
|
if (sessionAnonymousId) return sessionAnonymousId;
|
|
242
837
|
try {
|
|
243
|
-
const raw =
|
|
838
|
+
const raw = readFileSync5(telemetryFilePath(), "utf8");
|
|
244
839
|
const parsed = JSON.parse(raw);
|
|
245
840
|
if (parsed.anonymousId) {
|
|
246
841
|
sessionAnonymousId = parsed.anonymousId;
|
|
@@ -251,8 +846,8 @@ function readOrCreateAnonymousId() {
|
|
|
251
846
|
const id = randomUUID();
|
|
252
847
|
sessionAnonymousId = id;
|
|
253
848
|
try {
|
|
254
|
-
mkdirSync(
|
|
255
|
-
|
|
849
|
+
mkdirSync(join5(homedir(), ".nuvio"), { recursive: true, mode: 448 });
|
|
850
|
+
writeFileSync2(
|
|
256
851
|
telemetryFilePath(),
|
|
257
852
|
JSON.stringify({ anonymousId: id }, null, 2),
|
|
258
853
|
{ mode: 384 }
|
|
@@ -408,8 +1003,8 @@ var babel_traverse_default = traverse;
|
|
|
408
1003
|
// src/patch-app-root.ts
|
|
409
1004
|
import * as t from "@babel/types";
|
|
410
1005
|
import fg from "fast-glob";
|
|
411
|
-
import { existsSync as
|
|
412
|
-
import { join as
|
|
1006
|
+
import { existsSync as existsSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync3 } from "fs";
|
|
1007
|
+
import { join as join6 } from "path";
|
|
413
1008
|
|
|
414
1009
|
// src/babel-generator.ts
|
|
415
1010
|
import generateImport from "@babel/generator";
|
|
@@ -443,8 +1038,8 @@ var APP_CANDIDATES = [
|
|
|
443
1038
|
];
|
|
444
1039
|
function resolveAppFile(root) {
|
|
445
1040
|
for (const rel of APP_CANDIDATES) {
|
|
446
|
-
const p =
|
|
447
|
-
if (
|
|
1041
|
+
const p = join6(root, rel);
|
|
1042
|
+
if (existsSync5(p)) return p;
|
|
448
1043
|
}
|
|
449
1044
|
return null;
|
|
450
1045
|
}
|
|
@@ -502,7 +1097,7 @@ function appendDevShell(ast) {
|
|
|
502
1097
|
return patched;
|
|
503
1098
|
}
|
|
504
1099
|
function patchAppRootFile(filePath) {
|
|
505
|
-
const source =
|
|
1100
|
+
const source = readFileSync6(filePath, "utf8");
|
|
506
1101
|
let ast;
|
|
507
1102
|
try {
|
|
508
1103
|
ast = parseTs(source, filePath);
|
|
@@ -528,12 +1123,12 @@ function patchAppRootFile(filePath) {
|
|
|
528
1123
|
if (!hasDevShell(ast) && !appendDevShell(ast)) {
|
|
529
1124
|
return { ok: false, error: "no JSX return to patch" };
|
|
530
1125
|
}
|
|
531
|
-
|
|
1126
|
+
writeFileSync3(filePath, printTs(ast, source), "utf8");
|
|
532
1127
|
return { ok: true };
|
|
533
1128
|
}
|
|
534
1129
|
function appHasDevShell(filePath) {
|
|
535
|
-
if (!
|
|
536
|
-
const source =
|
|
1130
|
+
if (!existsSync5(filePath)) return false;
|
|
1131
|
+
const source = readFileSync6(filePath, "utf8");
|
|
537
1132
|
try {
|
|
538
1133
|
const ast = parseTs(source, filePath);
|
|
539
1134
|
return hasOverlayImport(ast) && hasDevShell(ast);
|
|
@@ -556,8 +1151,8 @@ function projectHasDevShell(root) {
|
|
|
556
1151
|
}
|
|
557
1152
|
|
|
558
1153
|
// src/patch-main-styles.ts
|
|
559
|
-
import { existsSync as
|
|
560
|
-
import { join as
|
|
1154
|
+
import { existsSync as existsSync6, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
|
|
1155
|
+
import { join as join7 } from "path";
|
|
561
1156
|
var MAIN_CANDIDATES = ["src/main.tsx", "src/main.jsx", "main.tsx", "main.jsx"];
|
|
562
1157
|
var STYLE_IMPORT = 'import "@nuvio/overlay/style.css";';
|
|
563
1158
|
function overlayInstalledFromNpm(packageJsonPath) {
|
|
@@ -566,17 +1161,17 @@ function overlayInstalledFromNpm(packageJsonPath) {
|
|
|
566
1161
|
}
|
|
567
1162
|
function resolveMainEntry(root) {
|
|
568
1163
|
for (const rel of MAIN_CANDIDATES) {
|
|
569
|
-
const p =
|
|
570
|
-
if (
|
|
1164
|
+
const p = join7(root, rel);
|
|
1165
|
+
if (existsSync6(p)) return p;
|
|
571
1166
|
}
|
|
572
1167
|
return null;
|
|
573
1168
|
}
|
|
574
1169
|
function mainHasOverlayStyles(mainPath) {
|
|
575
|
-
const text =
|
|
1170
|
+
const text = readFileSync7(mainPath, "utf8");
|
|
576
1171
|
return text.includes("@nuvio/overlay/style.css") || text.includes("@nuvio/overlay/dist/style.css");
|
|
577
1172
|
}
|
|
578
1173
|
function patchMainOverlayStyles(mainPath) {
|
|
579
|
-
const text =
|
|
1174
|
+
const text = readFileSync7(mainPath, "utf8");
|
|
580
1175
|
if (text.includes("@nuvio/overlay/style.css") || text.includes("@nuvio/overlay/dist/style.css")) {
|
|
581
1176
|
return { ok: true, skipped: true };
|
|
582
1177
|
}
|
|
@@ -590,13 +1185,13 @@ function patchMainOverlayStyles(mainPath) {
|
|
|
590
1185
|
} else {
|
|
591
1186
|
lines.unshift(STYLE_IMPORT, "");
|
|
592
1187
|
}
|
|
593
|
-
|
|
1188
|
+
writeFileSync4(mainPath, lines.join("\n"));
|
|
594
1189
|
return { ok: true };
|
|
595
1190
|
}
|
|
596
1191
|
|
|
597
1192
|
// src/patch-vite-config.ts
|
|
598
1193
|
import * as t2 from "@babel/types";
|
|
599
|
-
import { readFileSync as
|
|
1194
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
|
|
600
1195
|
function hasNuvioImport(ast) {
|
|
601
1196
|
let found = false;
|
|
602
1197
|
babel_traverse_default(ast, {
|
|
@@ -679,7 +1274,7 @@ function ensureOptimizeDepsExclude(ast) {
|
|
|
679
1274
|
return patched;
|
|
680
1275
|
}
|
|
681
1276
|
function viteConfigHasOverlayOptimizeExclude(filePath) {
|
|
682
|
-
const source =
|
|
1277
|
+
const source = readFileSync8(filePath, "utf8");
|
|
683
1278
|
return /optimizeDeps\s*:\s*\{[^}]*exclude\s*:\s*\[[^\]]*@nuvio\/overlay/.test(
|
|
684
1279
|
source
|
|
685
1280
|
) || /exclude\s*:\s*\[[^\]]*["']@nuvio\/overlay["']/.test(source);
|
|
@@ -697,7 +1292,7 @@ function appendNuvioPlugin(ast) {
|
|
|
697
1292
|
return patched;
|
|
698
1293
|
}
|
|
699
1294
|
function patchViteConfigFile(filePath) {
|
|
700
|
-
const source =
|
|
1295
|
+
const source = readFileSync8(filePath, "utf8");
|
|
701
1296
|
let ast;
|
|
702
1297
|
try {
|
|
703
1298
|
ast = parseTs(source, filePath);
|
|
@@ -722,11 +1317,11 @@ function patchViteConfigFile(filePath) {
|
|
|
722
1317
|
return { ok: false, error: "no static plugins array" };
|
|
723
1318
|
}
|
|
724
1319
|
}
|
|
725
|
-
|
|
1320
|
+
writeFileSync5(filePath, printTs(ast, source), "utf8");
|
|
726
1321
|
return { ok: true, skipped: alreadyPlugin && depsPatched };
|
|
727
1322
|
}
|
|
728
1323
|
function viteConfigHasNuvio(filePath) {
|
|
729
|
-
const source =
|
|
1324
|
+
const source = readFileSync8(filePath, "utf8");
|
|
730
1325
|
try {
|
|
731
1326
|
const ast = parseTs(source, filePath);
|
|
732
1327
|
return hasNuvioImport(ast) && hasNuvioPluginCall(ast);
|
|
@@ -736,14 +1331,14 @@ function viteConfigHasNuvio(filePath) {
|
|
|
736
1331
|
}
|
|
737
1332
|
|
|
738
1333
|
// src/scan-ids.ts
|
|
739
|
-
import { readFileSync as
|
|
740
|
-
import { join as
|
|
1334
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
1335
|
+
import { join as join8 } from "path";
|
|
741
1336
|
import fg2 from "fast-glob";
|
|
742
1337
|
var ID_GLOB = ["src/**/*.{tsx,jsx}"];
|
|
743
1338
|
function projectHasPageTitleId(root) {
|
|
744
1339
|
const files = fg2.sync(ID_GLOB, { cwd: root, absolute: true });
|
|
745
1340
|
for (const file of files) {
|
|
746
|
-
const text =
|
|
1341
|
+
const text = readFileSync9(file, "utf8");
|
|
747
1342
|
if (/data-nuvio-id=["']page\.title["']/.test(text)) {
|
|
748
1343
|
return true;
|
|
749
1344
|
}
|
|
@@ -753,8 +1348,8 @@ function projectHasPageTitleId(root) {
|
|
|
753
1348
|
function findHeadingFiles(root) {
|
|
754
1349
|
const files = fg2.sync(ID_GLOB, { cwd: root, absolute: true });
|
|
755
1350
|
const ordered = [
|
|
756
|
-
|
|
757
|
-
|
|
1351
|
+
join8(root, "src/App.tsx"),
|
|
1352
|
+
join8(root, "src/App.jsx"),
|
|
758
1353
|
...files.filter(
|
|
759
1354
|
(f) => !f.endsWith("App.tsx") && !f.endsWith("App.jsx")
|
|
760
1355
|
)
|
|
@@ -967,7 +1562,7 @@ import { createInterface } from "readline";
|
|
|
967
1562
|
|
|
968
1563
|
// src/install-packages.ts
|
|
969
1564
|
import { spawnSync } from "child_process";
|
|
970
|
-
import { readFileSync as
|
|
1565
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
971
1566
|
function parseInstalledVersion(pkg, name) {
|
|
972
1567
|
const dev = pkg.devDependencies;
|
|
973
1568
|
const deps = pkg.dependencies;
|
|
@@ -976,7 +1571,7 @@ function parseInstalledVersion(pkg, name) {
|
|
|
976
1571
|
return raw.replace(/^[\^~]/, "");
|
|
977
1572
|
}
|
|
978
1573
|
function packagesNeedInstall(packageJsonPath, targetVersion) {
|
|
979
|
-
const pkg = JSON.parse(
|
|
1574
|
+
const pkg = JSON.parse(readFileSync10(packageJsonPath, "utf8"));
|
|
980
1575
|
for (const name of ["@nuvio/vite-plugin", "@nuvio/overlay"]) {
|
|
981
1576
|
const v = parseInstalledVersion(pkg, name);
|
|
982
1577
|
if (v !== targetVersion) return true;
|
|
@@ -1003,9 +1598,9 @@ function runInstall(root, pm, version) {
|
|
|
1003
1598
|
|
|
1004
1599
|
// src/patch-starter-id.ts
|
|
1005
1600
|
import * as t3 from "@babel/types";
|
|
1006
|
-
import { readFileSync as
|
|
1601
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync6 } from "fs";
|
|
1007
1602
|
function patchFirstHeading(filePath) {
|
|
1008
|
-
const source =
|
|
1603
|
+
const source = readFileSync11(filePath, "utf8");
|
|
1009
1604
|
let ast;
|
|
1010
1605
|
try {
|
|
1011
1606
|
ast = parseTs(source, filePath);
|
|
@@ -1034,13 +1629,13 @@ function patchFirstHeading(filePath) {
|
|
|
1034
1629
|
}
|
|
1035
1630
|
});
|
|
1036
1631
|
if (!patched) return { ok: false, error: "no h1/h2" };
|
|
1037
|
-
|
|
1632
|
+
writeFileSync6(filePath, printTs(ast, source), "utf8");
|
|
1038
1633
|
return { ok: true };
|
|
1039
1634
|
}
|
|
1040
1635
|
function patchStarterId(root) {
|
|
1041
1636
|
const files = findHeadingFiles(root);
|
|
1042
1637
|
for (const file of files) {
|
|
1043
|
-
const source =
|
|
1638
|
+
const source = readFileSync11(file, "utf8");
|
|
1044
1639
|
if (!/<h[12][\s>]/.test(source) && !/<>[\s\S]*<h[12]/.test(source)) {
|
|
1045
1640
|
try {
|
|
1046
1641
|
const ast = parseTs(source, file);
|
|
@@ -1080,12 +1675,13 @@ function createPlan(root, pm) {
|
|
|
1080
1675
|
}
|
|
1081
1676
|
|
|
1082
1677
|
// src/write-nuvio-folder.ts
|
|
1083
|
-
import { existsSync as
|
|
1084
|
-
import { dirname, join as
|
|
1678
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "fs";
|
|
1679
|
+
import { dirname, join as join9 } from "path";
|
|
1085
1680
|
import { fileURLToPath } from "url";
|
|
1086
|
-
|
|
1681
|
+
import { DEFAULT_BRAND_CONFIG as DEFAULT_BRAND_CONFIG3, serializeBrandConfig } from "@nuvio/shared";
|
|
1682
|
+
var CLI_ROOT = join9(dirname(fileURLToPath(import.meta.url)), "..");
|
|
1087
1683
|
function loadTemplate(name) {
|
|
1088
|
-
return
|
|
1684
|
+
return readFileSync12(join9(CLI_ROOT, "templates", name), "utf8");
|
|
1089
1685
|
}
|
|
1090
1686
|
function render(tpl, vars) {
|
|
1091
1687
|
let out = tpl;
|
|
@@ -1095,7 +1691,7 @@ function render(tpl, vars) {
|
|
|
1095
1691
|
return out;
|
|
1096
1692
|
}
|
|
1097
1693
|
function writeNuvioFolder(opts) {
|
|
1098
|
-
const dir =
|
|
1694
|
+
const dir = join9(opts.root, "nuvio");
|
|
1099
1695
|
const created = [];
|
|
1100
1696
|
mkdirSync2(dir, { recursive: true });
|
|
1101
1697
|
const vars = {
|
|
@@ -1103,34 +1699,40 @@ function writeNuvioFolder(opts) {
|
|
|
1103
1699
|
PM_RUN: opts.pmRun,
|
|
1104
1700
|
FAILED_STEPS: opts.failedSteps.join(", ") || "(none)"
|
|
1105
1701
|
};
|
|
1106
|
-
const startHere =
|
|
1107
|
-
|
|
1702
|
+
const startHere = join9(dir, "START_HERE.md");
|
|
1703
|
+
writeFileSync7(
|
|
1108
1704
|
startHere,
|
|
1109
1705
|
render(loadTemplate("START_HERE.md.tpl"), vars),
|
|
1110
1706
|
"utf8"
|
|
1111
1707
|
);
|
|
1112
1708
|
created.push("nuvio/START_HERE.md");
|
|
1113
|
-
const readme =
|
|
1114
|
-
|
|
1709
|
+
const readme = join9(dir, "README.md");
|
|
1710
|
+
writeFileSync7(
|
|
1115
1711
|
readme,
|
|
1116
1712
|
render(loadTemplate("README.pointer.md.tpl"), vars),
|
|
1117
1713
|
"utf8"
|
|
1118
1714
|
);
|
|
1119
1715
|
created.push("nuvio/README.md");
|
|
1120
|
-
const agent =
|
|
1121
|
-
if (!
|
|
1122
|
-
|
|
1716
|
+
const agent = join9(dir, "AGENT.md");
|
|
1717
|
+
if (!existsSync7(agent) || opts.forceAgent) {
|
|
1718
|
+
writeFileSync7(agent, render(loadTemplate("AGENT.md.tpl"), vars), "utf8");
|
|
1123
1719
|
created.push("nuvio/AGENT.md");
|
|
1124
1720
|
}
|
|
1125
1721
|
if (opts.failedSteps.length > 0) {
|
|
1126
|
-
const todo =
|
|
1127
|
-
|
|
1722
|
+
const todo = join9(dir, "SETUP_TODO.md");
|
|
1723
|
+
writeFileSync7(
|
|
1128
1724
|
todo,
|
|
1129
1725
|
render(loadTemplate("SETUP_TODO.md.tpl"), vars),
|
|
1130
1726
|
"utf8"
|
|
1131
1727
|
);
|
|
1132
1728
|
created.push("nuvio/SETUP_TODO.md");
|
|
1133
1729
|
}
|
|
1730
|
+
const brand = join9(dir, "brand.json");
|
|
1731
|
+
if (!existsSync7(brand)) {
|
|
1732
|
+
writeFileSync7(brand, `${JSON.stringify(serializeBrandConfig(DEFAULT_BRAND_CONFIG3), null, 2)}
|
|
1733
|
+
`, "utf8");
|
|
1734
|
+
created.push("nuvio/brand.json");
|
|
1735
|
+
}
|
|
1134
1736
|
return created;
|
|
1135
1737
|
}
|
|
1136
1738
|
|
|
@@ -1151,10 +1753,10 @@ async function confirm(plan) {
|
|
|
1151
1753
|
console.log(`
|
|
1152
1754
|
Install: ${plan.installCommand || "(skip)"}`);
|
|
1153
1755
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
1154
|
-
return new Promise((
|
|
1756
|
+
return new Promise((resolve5) => {
|
|
1155
1757
|
rl.question("\nProceed? [y/N] ", (answer) => {
|
|
1156
1758
|
rl.close();
|
|
1157
|
-
|
|
1759
|
+
resolve5(/^y(es)?$/i.test(answer.trim()));
|
|
1158
1760
|
});
|
|
1159
1761
|
});
|
|
1160
1762
|
}
|
|
@@ -1527,6 +2129,9 @@ Usage:
|
|
|
1527
2129
|
nuvio doctor [options]
|
|
1528
2130
|
nuvio scan [options]
|
|
1529
2131
|
nuvio stats [options]
|
|
2132
|
+
nuvio coverage verify [options]
|
|
2133
|
+
nuvio brand scan [options]
|
|
2134
|
+
nuvio brand apply [options]
|
|
1530
2135
|
|
|
1531
2136
|
Common options:
|
|
1532
2137
|
--cwd <path> Project root (default: current directory)
|
|
@@ -1546,11 +2151,32 @@ Init options:
|
|
|
1546
2151
|
Doctor options:
|
|
1547
2152
|
--skip-dev-server Skip localhost dev-server health check
|
|
1548
2153
|
|
|
2154
|
+
Coverage verify options:
|
|
2155
|
+
--page <slug> Page slug (loads nuvio/pages/<slug>.pcc.yaml)
|
|
2156
|
+
--manifest <path> Explicit PCC manifest path (overrides --page)
|
|
2157
|
+
--all Verify every manifest in nuvio/pages/
|
|
2158
|
+
|
|
2159
|
+
Brand scan options:
|
|
2160
|
+
--page <slug> Page slug (loads nuvio/pages/<slug>.pcc.yaml)
|
|
2161
|
+
--manifest <path> Explicit PCC manifest path (overrides --page)
|
|
2162
|
+
--all Scan every manifest in nuvio/pages/
|
|
2163
|
+
|
|
2164
|
+
Brand apply options:
|
|
2165
|
+
--page <slug> Page slug (loads nuvio/pages/<slug>.pcc.yaml)
|
|
2166
|
+
--manifest <path> Explicit PCC manifest path (overrides --page)
|
|
2167
|
+
--all Apply to every manifest in nuvio/pages/
|
|
2168
|
+
--dry-run Report targets without writing source files
|
|
2169
|
+
|
|
1549
2170
|
Examples:
|
|
1550
2171
|
pnpm dlx @nuvio/cli init --yes
|
|
1551
2172
|
pnpm dlx @nuvio/cli doctor
|
|
1552
2173
|
pnpm dlx @nuvio/cli scan --json
|
|
1553
2174
|
pnpm dlx @nuvio/cli stats
|
|
2175
|
+
pnpm dlx @nuvio/cli coverage verify --page dashboard --cwd apps/tailadmin-dogfood
|
|
2176
|
+
pnpm dlx @nuvio/cli coverage verify --all --cwd apps/tailadmin-dogfood
|
|
2177
|
+
pnpm dlx @nuvio/cli brand scan --page dashboard --cwd apps/tailadmin-dogfood
|
|
2178
|
+
pnpm dlx @nuvio/cli brand scan --all --cwd apps/tailadmin-dogfood
|
|
2179
|
+
pnpm dlx @nuvio/cli brand apply --all --cwd apps/tailadmin-dogfood
|
|
1554
2180
|
`);
|
|
1555
2181
|
}
|
|
1556
2182
|
function parseInitArgs(argv) {
|
|
@@ -1578,7 +2204,7 @@ function parseInitArgs(argv) {
|
|
|
1578
2204
|
else if (arg === "--pm") {
|
|
1579
2205
|
opts.pm = args[++i];
|
|
1580
2206
|
} else if (arg === "--cwd") {
|
|
1581
|
-
opts.cwd =
|
|
2207
|
+
opts.cwd = resolve4(args[++i] ?? ".");
|
|
1582
2208
|
} else if (arg.startsWith("-")) {
|
|
1583
2209
|
console.error(`Unknown option: ${arg}`);
|
|
1584
2210
|
help = true;
|
|
@@ -1605,7 +2231,7 @@ function parseProjectCommandArgs(argv, command) {
|
|
|
1605
2231
|
common.verbose = true;
|
|
1606
2232
|
doctor.verbose = true;
|
|
1607
2233
|
} else if (arg === "--cwd") {
|
|
1608
|
-
const cwd =
|
|
2234
|
+
const cwd = resolve4(args[++i] ?? ".");
|
|
1609
2235
|
common.cwd = cwd;
|
|
1610
2236
|
doctor.cwd = cwd;
|
|
1611
2237
|
} else if (arg === "--skip-dev-server") {
|
|
@@ -1617,16 +2243,114 @@ function parseProjectCommandArgs(argv, command) {
|
|
|
1617
2243
|
}
|
|
1618
2244
|
return { command, common, doctor, help };
|
|
1619
2245
|
}
|
|
2246
|
+
function parseCoverageVerifyArgs(argv) {
|
|
2247
|
+
const args = argv.slice(2);
|
|
2248
|
+
const common = { cwd: process.cwd() };
|
|
2249
|
+
let help = false;
|
|
2250
|
+
let page;
|
|
2251
|
+
let manifest;
|
|
2252
|
+
let all = false;
|
|
2253
|
+
let i = 0;
|
|
2254
|
+
if (args[0] === "coverage") {
|
|
2255
|
+
i = 1;
|
|
2256
|
+
}
|
|
2257
|
+
const subcommand = args[i] === "verify" ? "verify" : "";
|
|
2258
|
+
if (subcommand) {
|
|
2259
|
+
i += 1;
|
|
2260
|
+
}
|
|
2261
|
+
for (; i < args.length; i++) {
|
|
2262
|
+
const arg = args[i];
|
|
2263
|
+
if (arg === "-h" || arg === "--help") {
|
|
2264
|
+
help = true;
|
|
2265
|
+
continue;
|
|
2266
|
+
}
|
|
2267
|
+
if (arg === "--json") {
|
|
2268
|
+
common.json = true;
|
|
2269
|
+
} else if (arg === "--verbose") {
|
|
2270
|
+
common.verbose = true;
|
|
2271
|
+
} else if (arg === "--cwd") {
|
|
2272
|
+
common.cwd = resolve4(args[++i] ?? ".");
|
|
2273
|
+
} else if (arg === "--page") {
|
|
2274
|
+
page = args[++i];
|
|
2275
|
+
} else if (arg === "--manifest") {
|
|
2276
|
+
manifest = resolve4(args[++i] ?? "");
|
|
2277
|
+
} else if (arg === "--all") {
|
|
2278
|
+
all = true;
|
|
2279
|
+
} else if (arg.startsWith("-")) {
|
|
2280
|
+
console.error(`Unknown option: ${arg}`);
|
|
2281
|
+
help = true;
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
return { command: "coverage", subcommand, common, page, manifest, all, help };
|
|
2285
|
+
}
|
|
2286
|
+
function parseBrandArgs(argv) {
|
|
2287
|
+
const args = argv.slice(2);
|
|
2288
|
+
const common = { cwd: process.cwd() };
|
|
2289
|
+
let help = false;
|
|
2290
|
+
let page;
|
|
2291
|
+
let manifest;
|
|
2292
|
+
let all = false;
|
|
2293
|
+
let dryRun = false;
|
|
2294
|
+
let i = 0;
|
|
2295
|
+
if (args[0] === "brand") {
|
|
2296
|
+
i = 1;
|
|
2297
|
+
}
|
|
2298
|
+
const subArg = args[i];
|
|
2299
|
+
const subcommand = subArg === "scan" || subArg === "apply" ? subArg : "";
|
|
2300
|
+
if (subcommand) {
|
|
2301
|
+
i += 1;
|
|
2302
|
+
}
|
|
2303
|
+
for (; i < args.length; i++) {
|
|
2304
|
+
const arg = args[i];
|
|
2305
|
+
if (arg === "-h" || arg === "--help") {
|
|
2306
|
+
help = true;
|
|
2307
|
+
continue;
|
|
2308
|
+
}
|
|
2309
|
+
if (arg === "--json") {
|
|
2310
|
+
common.json = true;
|
|
2311
|
+
} else if (arg === "--verbose") {
|
|
2312
|
+
common.verbose = true;
|
|
2313
|
+
} else if (arg === "--cwd") {
|
|
2314
|
+
common.cwd = resolve4(args[++i] ?? ".");
|
|
2315
|
+
} else if (arg === "--page") {
|
|
2316
|
+
page = args[++i];
|
|
2317
|
+
} else if (arg === "--manifest") {
|
|
2318
|
+
manifest = resolve4(args[++i] ?? "");
|
|
2319
|
+
} else if (arg === "--all") {
|
|
2320
|
+
all = true;
|
|
2321
|
+
} else if (arg === "--dry-run") {
|
|
2322
|
+
dryRun = true;
|
|
2323
|
+
} else if (arg.startsWith("-")) {
|
|
2324
|
+
console.error(`Unknown option: ${arg}`);
|
|
2325
|
+
help = true;
|
|
2326
|
+
}
|
|
2327
|
+
}
|
|
2328
|
+
return { command: "brand", subcommand, common, page, manifest, all, dryRun, help };
|
|
2329
|
+
}
|
|
1620
2330
|
async function runCli(argv) {
|
|
1621
2331
|
registerTelemetrySignalHandlers();
|
|
1622
2332
|
const rawCommand = argv[2] ?? null;
|
|
1623
|
-
const
|
|
2333
|
+
const isCoverageCmd = rawCommand === "coverage";
|
|
2334
|
+
const isBrandCmd = rawCommand === "brand";
|
|
2335
|
+
const isProjectCmd = rawCommand === "doctor" || rawCommand === "scan" || rawCommand === "stats" || isCoverageCmd || isBrandCmd;
|
|
1624
2336
|
let help = false;
|
|
1625
2337
|
let command = rawCommand;
|
|
1626
2338
|
let initOpts = { cwd: process.cwd() };
|
|
1627
2339
|
let commonOpts = { cwd: process.cwd() };
|
|
1628
2340
|
let doctorOpts = { cwd: process.cwd() };
|
|
1629
|
-
|
|
2341
|
+
let coverageOpts = null;
|
|
2342
|
+
let brandOpts = null;
|
|
2343
|
+
if (isBrandCmd) {
|
|
2344
|
+
brandOpts = parseBrandArgs(argv);
|
|
2345
|
+
help = brandOpts.help;
|
|
2346
|
+
command = brandOpts.command;
|
|
2347
|
+
commonOpts = brandOpts.common;
|
|
2348
|
+
} else if (isCoverageCmd) {
|
|
2349
|
+
coverageOpts = parseCoverageVerifyArgs(argv);
|
|
2350
|
+
help = coverageOpts.help;
|
|
2351
|
+
command = coverageOpts.command;
|
|
2352
|
+
commonOpts = coverageOpts.common;
|
|
2353
|
+
} else if (isProjectCmd) {
|
|
1630
2354
|
const parsed = parseProjectCommandArgs(argv, rawCommand);
|
|
1631
2355
|
help = parsed.help;
|
|
1632
2356
|
command = parsed.command;
|
|
@@ -1665,6 +2389,52 @@ async function runCli(argv) {
|
|
|
1665
2389
|
return runScan({ cwd: commonOpts.cwd, json: commonOpts.json });
|
|
1666
2390
|
case "stats":
|
|
1667
2391
|
return runStats({ cwd: commonOpts.cwd, json: commonOpts.json });
|
|
2392
|
+
case "coverage": {
|
|
2393
|
+
if (!coverageOpts || coverageOpts.subcommand !== "verify") {
|
|
2394
|
+
console.error("Usage: nuvio coverage verify --page <slug>");
|
|
2395
|
+
printHelp();
|
|
2396
|
+
return 1;
|
|
2397
|
+
}
|
|
2398
|
+
if (!coverageOpts.page && !coverageOpts.manifest && !coverageOpts.all) {
|
|
2399
|
+
console.error("Either --page, --manifest, or --all is required");
|
|
2400
|
+
return 2;
|
|
2401
|
+
}
|
|
2402
|
+
return runCoverageVerify({
|
|
2403
|
+
cwd: coverageOpts.common.cwd,
|
|
2404
|
+
page: coverageOpts.page,
|
|
2405
|
+
manifest: coverageOpts.manifest,
|
|
2406
|
+
all: coverageOpts.all,
|
|
2407
|
+
json: coverageOpts.common.json
|
|
2408
|
+
});
|
|
2409
|
+
}
|
|
2410
|
+
case "brand": {
|
|
2411
|
+
if (!brandOpts || brandOpts.subcommand !== "scan" && brandOpts.subcommand !== "apply") {
|
|
2412
|
+
console.error("Usage: nuvio brand scan|apply --page <slug>");
|
|
2413
|
+
printHelp();
|
|
2414
|
+
return 1;
|
|
2415
|
+
}
|
|
2416
|
+
if (!brandOpts.page && !brandOpts.manifest && !brandOpts.all) {
|
|
2417
|
+
console.error("Either --page, --manifest, or --all is required");
|
|
2418
|
+
return 2;
|
|
2419
|
+
}
|
|
2420
|
+
if (brandOpts.subcommand === "scan") {
|
|
2421
|
+
return runBrandScan({
|
|
2422
|
+
cwd: brandOpts.common.cwd,
|
|
2423
|
+
page: brandOpts.page,
|
|
2424
|
+
manifest: brandOpts.manifest,
|
|
2425
|
+
all: brandOpts.all,
|
|
2426
|
+
json: brandOpts.common.json
|
|
2427
|
+
});
|
|
2428
|
+
}
|
|
2429
|
+
return runBrandApply({
|
|
2430
|
+
cwd: brandOpts.common.cwd,
|
|
2431
|
+
page: brandOpts.page,
|
|
2432
|
+
manifest: brandOpts.manifest,
|
|
2433
|
+
all: brandOpts.all,
|
|
2434
|
+
dryRun: brandOpts.dryRun,
|
|
2435
|
+
json: brandOpts.common.json
|
|
2436
|
+
});
|
|
2437
|
+
}
|
|
1668
2438
|
default:
|
|
1669
2439
|
console.error(`Unknown command: ${command}`);
|
|
1670
2440
|
printHelp();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuvio/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Nuvio CLI 1.0 — Vite + Tailwind onboarding and diagnostics (init, doctor, scan, stats).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -41,8 +41,9 @@
|
|
|
41
41
|
"@babel/types": "^7.26.9",
|
|
42
42
|
"fast-glob": "^3.3.3",
|
|
43
43
|
"posthog-node": "^5.36.2",
|
|
44
|
-
"@nuvio/shared": "1.
|
|
45
|
-
"@nuvio/
|
|
44
|
+
"@nuvio/shared": "1.1.0",
|
|
45
|
+
"@nuvio/ast-engine": "1.1.0",
|
|
46
|
+
"@nuvio/vite-plugin": "1.1.0"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
48
49
|
"@types/babel__generator": "^7.6.8",
|