@nuvio/cli 0.5.1 → 0.5.3
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 +155 -27
- package/package.json +1 -1
package/dist/cli-entry.js
CHANGED
|
@@ -212,6 +212,75 @@ function hasNuvioPluginCall(ast) {
|
|
|
212
212
|
});
|
|
213
213
|
return found;
|
|
214
214
|
}
|
|
215
|
+
var OVERLAY_DEP = "@nuvio/overlay";
|
|
216
|
+
function excludeListsOverlay(expr) {
|
|
217
|
+
if (!expr || !t.isArrayExpression(expr)) return false;
|
|
218
|
+
return expr.elements.some(
|
|
219
|
+
(el) => t.isStringLiteral(el) && el.value === OVERLAY_DEP
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
function ensureOptimizeDepsExclude(ast) {
|
|
223
|
+
let patched = false;
|
|
224
|
+
babel_traverse_default(ast, {
|
|
225
|
+
CallExpression(path) {
|
|
226
|
+
const callee = path.node.callee;
|
|
227
|
+
if (!t.isIdentifier(callee, { name: "defineConfig" })) return;
|
|
228
|
+
const arg = path.node.arguments[0];
|
|
229
|
+
if (!t.isObjectExpression(arg)) return;
|
|
230
|
+
let optimizeDeps;
|
|
231
|
+
for (const prop of arg.properties) {
|
|
232
|
+
if (t.isObjectProperty(prop) && t.isIdentifier(prop.key, { name: "optimizeDeps" })) {
|
|
233
|
+
optimizeDeps = prop;
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (!optimizeDeps) {
|
|
238
|
+
arg.properties.push(
|
|
239
|
+
t.objectProperty(
|
|
240
|
+
t.identifier("optimizeDeps"),
|
|
241
|
+
t.objectExpression([
|
|
242
|
+
t.objectProperty(
|
|
243
|
+
t.identifier("exclude"),
|
|
244
|
+
t.arrayExpression([t.stringLiteral(OVERLAY_DEP)])
|
|
245
|
+
)
|
|
246
|
+
])
|
|
247
|
+
)
|
|
248
|
+
);
|
|
249
|
+
patched = true;
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
if (!t.isObjectExpression(optimizeDeps.value)) return;
|
|
253
|
+
let excludeProp;
|
|
254
|
+
for (const p of optimizeDeps.value.properties) {
|
|
255
|
+
if (t.isObjectProperty(p) && t.isIdentifier(p.key, { name: "exclude" })) {
|
|
256
|
+
excludeProp = p;
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (!excludeProp) {
|
|
261
|
+
optimizeDeps.value.properties.push(
|
|
262
|
+
t.objectProperty(
|
|
263
|
+
t.identifier("exclude"),
|
|
264
|
+
t.arrayExpression([t.stringLiteral(OVERLAY_DEP)])
|
|
265
|
+
)
|
|
266
|
+
);
|
|
267
|
+
patched = true;
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
if (t.isArrayExpression(excludeProp.value) && !excludeListsOverlay(excludeProp.value)) {
|
|
271
|
+
excludeProp.value.elements.push(t.stringLiteral(OVERLAY_DEP));
|
|
272
|
+
patched = true;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
return patched;
|
|
277
|
+
}
|
|
278
|
+
function viteConfigHasOverlayOptimizeExclude(filePath) {
|
|
279
|
+
const source = readFileSync3(filePath, "utf8");
|
|
280
|
+
return /optimizeDeps\s*:\s*\{[^}]*exclude\s*:\s*\[[^\]]*@nuvio\/overlay/.test(
|
|
281
|
+
source
|
|
282
|
+
) || /exclude\s*:\s*\[[^\]]*["']@nuvio\/overlay["']/.test(source);
|
|
283
|
+
}
|
|
215
284
|
function appendNuvioPlugin(ast) {
|
|
216
285
|
let patched = false;
|
|
217
286
|
babel_traverse_default(ast, {
|
|
@@ -232,7 +301,9 @@ function patchViteConfigFile(filePath) {
|
|
|
232
301
|
} catch {
|
|
233
302
|
return { ok: false, error: "parse failed" };
|
|
234
303
|
}
|
|
235
|
-
|
|
304
|
+
const depsPatched = ensureOptimizeDepsExclude(ast);
|
|
305
|
+
const alreadyPlugin = hasNuvioImport(ast) && hasNuvioPluginCall(ast);
|
|
306
|
+
if (alreadyPlugin && !depsPatched) {
|
|
236
307
|
return { ok: true, skipped: true };
|
|
237
308
|
}
|
|
238
309
|
if (!hasNuvioImport(ast)) {
|
|
@@ -249,7 +320,7 @@ function patchViteConfigFile(filePath) {
|
|
|
249
320
|
}
|
|
250
321
|
}
|
|
251
322
|
writeFileSync(filePath, printTs(ast, source), "utf8");
|
|
252
|
-
return { ok: true };
|
|
323
|
+
return { ok: true, skipped: alreadyPlugin && depsPatched };
|
|
253
324
|
}
|
|
254
325
|
function viteConfigHasNuvio(filePath) {
|
|
255
326
|
const source = readFileSync3(filePath, "utf8");
|
|
@@ -372,19 +443,61 @@ function appHasDevShell(filePath) {
|
|
|
372
443
|
}
|
|
373
444
|
}
|
|
374
445
|
|
|
446
|
+
// src/patch-main-styles.ts
|
|
447
|
+
import { existsSync as existsSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
448
|
+
import { join as join4 } from "path";
|
|
449
|
+
var MAIN_CANDIDATES = ["src/main.tsx", "src/main.jsx", "main.tsx", "main.jsx"];
|
|
450
|
+
var STYLE_IMPORT = 'import "@nuvio/overlay/style.css";';
|
|
451
|
+
function overlayInstalledFromNpm(packageJsonPath) {
|
|
452
|
+
const pkg = JSON.parse(readFileSync5(packageJsonPath, "utf8"));
|
|
453
|
+
const dev = pkg.devDependencies;
|
|
454
|
+
const raw = dev?.["@nuvio/overlay"];
|
|
455
|
+
if (!raw) return false;
|
|
456
|
+
return !raw.startsWith("workspace:") && !raw.startsWith("link:") && !raw.startsWith("file:");
|
|
457
|
+
}
|
|
458
|
+
function resolveMainEntry(root) {
|
|
459
|
+
for (const rel of MAIN_CANDIDATES) {
|
|
460
|
+
const p = join4(root, rel);
|
|
461
|
+
if (existsSync4(p)) return p;
|
|
462
|
+
}
|
|
463
|
+
return null;
|
|
464
|
+
}
|
|
465
|
+
function mainHasOverlayStyles(mainPath) {
|
|
466
|
+
const text = readFileSync5(mainPath, "utf8");
|
|
467
|
+
return text.includes("@nuvio/overlay/style.css") || text.includes("@nuvio/overlay/dist/style.css");
|
|
468
|
+
}
|
|
469
|
+
function patchMainOverlayStyles(mainPath) {
|
|
470
|
+
const text = readFileSync5(mainPath, "utf8");
|
|
471
|
+
if (text.includes("@nuvio/overlay/style.css") || text.includes("@nuvio/overlay/dist/style.css")) {
|
|
472
|
+
return { ok: true, skipped: true };
|
|
473
|
+
}
|
|
474
|
+
const lines = text.split("\n");
|
|
475
|
+
let lastImport = -1;
|
|
476
|
+
for (let i = 0; i < lines.length; i++) {
|
|
477
|
+
if (/^\s*import\s/.test(lines[i])) lastImport = i;
|
|
478
|
+
}
|
|
479
|
+
if (lastImport >= 0) {
|
|
480
|
+
lines.splice(lastImport + 1, 0, STYLE_IMPORT);
|
|
481
|
+
} else {
|
|
482
|
+
lines.unshift(STYLE_IMPORT, "");
|
|
483
|
+
}
|
|
484
|
+
writeFileSync3(mainPath, lines.join("\n"));
|
|
485
|
+
return { ok: true };
|
|
486
|
+
}
|
|
487
|
+
|
|
375
488
|
// src/patch-starter-id.ts
|
|
376
489
|
import * as t3 from "@babel/types";
|
|
377
|
-
import { readFileSync as
|
|
490
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
|
|
378
491
|
|
|
379
492
|
// src/scan-ids.ts
|
|
380
|
-
import { readFileSync as
|
|
381
|
-
import { join as
|
|
493
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
494
|
+
import { join as join5 } from "path";
|
|
382
495
|
import fg from "fast-glob";
|
|
383
496
|
var ID_GLOB = ["src/**/*.{tsx,jsx}"];
|
|
384
497
|
function projectHasPageTitleId(root) {
|
|
385
498
|
const files = fg.sync(ID_GLOB, { cwd: root, absolute: true });
|
|
386
499
|
for (const file of files) {
|
|
387
|
-
const text =
|
|
500
|
+
const text = readFileSync6(file, "utf8");
|
|
388
501
|
if (/data-nuvio-id=["']page\.title["']/.test(text)) {
|
|
389
502
|
return true;
|
|
390
503
|
}
|
|
@@ -394,8 +507,8 @@ function projectHasPageTitleId(root) {
|
|
|
394
507
|
function findHeadingFiles(root) {
|
|
395
508
|
const files = fg.sync(ID_GLOB, { cwd: root, absolute: true });
|
|
396
509
|
const ordered = [
|
|
397
|
-
|
|
398
|
-
|
|
510
|
+
join5(root, "src/App.tsx"),
|
|
511
|
+
join5(root, "src/App.jsx"),
|
|
399
512
|
...files.filter(
|
|
400
513
|
(f) => !f.endsWith("App.tsx") && !f.endsWith("App.jsx")
|
|
401
514
|
)
|
|
@@ -416,7 +529,7 @@ function findHeadingFiles(root) {
|
|
|
416
529
|
|
|
417
530
|
// src/patch-starter-id.ts
|
|
418
531
|
function patchFirstHeading(filePath) {
|
|
419
|
-
const source =
|
|
532
|
+
const source = readFileSync7(filePath, "utf8");
|
|
420
533
|
let ast;
|
|
421
534
|
try {
|
|
422
535
|
ast = parseTs(source, filePath);
|
|
@@ -445,13 +558,13 @@ function patchFirstHeading(filePath) {
|
|
|
445
558
|
}
|
|
446
559
|
});
|
|
447
560
|
if (!patched) return { ok: false, error: "no h1/h2" };
|
|
448
|
-
|
|
561
|
+
writeFileSync4(filePath, printTs(ast, source), "utf8");
|
|
449
562
|
return { ok: true };
|
|
450
563
|
}
|
|
451
564
|
function patchStarterId(root) {
|
|
452
565
|
const files = findHeadingFiles(root);
|
|
453
566
|
for (const file of files) {
|
|
454
|
-
const source =
|
|
567
|
+
const source = readFileSync7(file, "utf8");
|
|
455
568
|
if (!/<h[12][\s>]/.test(source) && !/<>[\s\S]*<h[12]/.test(source)) {
|
|
456
569
|
try {
|
|
457
570
|
const ast = parseTs(source, file);
|
|
@@ -496,12 +609,12 @@ var require2 = createRequire(import.meta.url);
|
|
|
496
609
|
var NUVIO_VERSION = require2("../package.json").version;
|
|
497
610
|
|
|
498
611
|
// src/write-nuvio-folder.ts
|
|
499
|
-
import { existsSync as
|
|
500
|
-
import { dirname, join as
|
|
612
|
+
import { existsSync as existsSync5, mkdirSync, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
|
|
613
|
+
import { dirname, join as join6 } from "path";
|
|
501
614
|
import { fileURLToPath } from "url";
|
|
502
|
-
var CLI_ROOT =
|
|
615
|
+
var CLI_ROOT = join6(dirname(fileURLToPath(import.meta.url)), "..");
|
|
503
616
|
function loadTemplate(name) {
|
|
504
|
-
return
|
|
617
|
+
return readFileSync8(join6(CLI_ROOT, "templates", name), "utf8");
|
|
505
618
|
}
|
|
506
619
|
function render(tpl, vars) {
|
|
507
620
|
let out = tpl;
|
|
@@ -511,7 +624,7 @@ function render(tpl, vars) {
|
|
|
511
624
|
return out;
|
|
512
625
|
}
|
|
513
626
|
function writeNuvioFolder(opts) {
|
|
514
|
-
const dir =
|
|
627
|
+
const dir = join6(opts.root, "nuvio");
|
|
515
628
|
const created = [];
|
|
516
629
|
mkdirSync(dir, { recursive: true });
|
|
517
630
|
const vars = {
|
|
@@ -519,28 +632,28 @@ function writeNuvioFolder(opts) {
|
|
|
519
632
|
PM_RUN: opts.pmRun,
|
|
520
633
|
FAILED_STEPS: opts.failedSteps.join(", ") || "(none)"
|
|
521
634
|
};
|
|
522
|
-
const startHere =
|
|
523
|
-
|
|
635
|
+
const startHere = join6(dir, "START_HERE.md");
|
|
636
|
+
writeFileSync5(
|
|
524
637
|
startHere,
|
|
525
638
|
render(loadTemplate("START_HERE.md.tpl"), vars),
|
|
526
639
|
"utf8"
|
|
527
640
|
);
|
|
528
641
|
created.push("nuvio/START_HERE.md");
|
|
529
|
-
const readme =
|
|
530
|
-
|
|
642
|
+
const readme = join6(dir, "README.md");
|
|
643
|
+
writeFileSync5(
|
|
531
644
|
readme,
|
|
532
645
|
render(loadTemplate("README.pointer.md.tpl"), vars),
|
|
533
646
|
"utf8"
|
|
534
647
|
);
|
|
535
648
|
created.push("nuvio/README.md");
|
|
536
|
-
const agent =
|
|
537
|
-
if (!
|
|
538
|
-
|
|
649
|
+
const agent = join6(dir, "AGENT.md");
|
|
650
|
+
if (!existsSync5(agent) || opts.forceAgent) {
|
|
651
|
+
writeFileSync5(agent, render(loadTemplate("AGENT.md.tpl"), vars), "utf8");
|
|
539
652
|
created.push("nuvio/AGENT.md");
|
|
540
653
|
}
|
|
541
654
|
if (opts.failedSteps.length > 0) {
|
|
542
|
-
const todo =
|
|
543
|
-
|
|
655
|
+
const todo = join6(dir, "SETUP_TODO.md");
|
|
656
|
+
writeFileSync5(
|
|
544
657
|
todo,
|
|
545
658
|
render(loadTemplate("SETUP_TODO.md.tpl"), vars),
|
|
546
659
|
"utf8"
|
|
@@ -551,15 +664,18 @@ function writeNuvioFolder(opts) {
|
|
|
551
664
|
}
|
|
552
665
|
|
|
553
666
|
// src/verify.ts
|
|
554
|
-
import { readFileSync as
|
|
667
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
555
668
|
function verifyProject(root, packageJsonPath, viteConfigPath) {
|
|
556
|
-
const pkg = JSON.parse(
|
|
669
|
+
const pkg = JSON.parse(readFileSync9(packageJsonPath, "utf8"));
|
|
557
670
|
const dev = pkg.devDependencies;
|
|
558
671
|
const depsOk = Boolean(dev?.["@nuvio/vite-plugin"]) && Boolean(dev?.["@nuvio/overlay"]);
|
|
559
672
|
const appFile = resolveAppFile(root);
|
|
673
|
+
const mainEntry = resolveMainEntry(root);
|
|
560
674
|
return {
|
|
561
675
|
deps: depsOk ? "OK" : "MISSING",
|
|
562
676
|
vite: viteConfigHasNuvio(viteConfigPath) ? "OK" : "TODO",
|
|
677
|
+
overlayCss: mainEntry && (mainHasOverlayStyles(mainEntry) || !overlayInstalledFromNpm(packageJsonPath)) ? "OK" : "TODO",
|
|
678
|
+
optimizeDeps: viteConfigHasOverlayOptimizeExclude(viteConfigPath) ? "OK" : "TODO",
|
|
563
679
|
shell: appFile && appHasDevShell(appFile) ? "OK" : "TODO",
|
|
564
680
|
starterId: projectHasPageTitleId(root) ? "OK" : "MISSING"
|
|
565
681
|
};
|
|
@@ -570,6 +686,8 @@ function printVerification(v) {
|
|
|
570
686
|
` devDependencies: @nuvio/vite-plugin, @nuvio/overlay \u2014 ${v.deps}`
|
|
571
687
|
);
|
|
572
688
|
console.log(` vite.config: nuvio() \u2014 ${v.vite}`);
|
|
689
|
+
console.log(` main.tsx: @nuvio/overlay/style.css \u2014 ${v.overlayCss}`);
|
|
690
|
+
console.log(` vite.config: optimizeDeps exclude overlay \u2014 ${v.optimizeDeps}`);
|
|
573
691
|
console.log(` App shell: NuvioDevShell \u2014 ${v.shell}`);
|
|
574
692
|
console.log(` Starter id page.title \u2014 ${v.starterId}`);
|
|
575
693
|
}
|
|
@@ -665,7 +783,11 @@ async function runInit(opts) {
|
|
|
665
783
|
plan.warnings.push(msg);
|
|
666
784
|
}
|
|
667
785
|
const appFile = resolveAppFile(root);
|
|
786
|
+
const mainEntry = resolveMainEntry(root);
|
|
668
787
|
if (appFile) plan.modify.push(appFile.replace(`${root}/`, ""));
|
|
788
|
+
if (mainEntry && overlayInstalledFromNpm(project.packageJsonPath)) {
|
|
789
|
+
plan.modify.push(mainEntry.replace(`${root}/`, ""));
|
|
790
|
+
}
|
|
669
791
|
plan.modify.push(project.viteConfigName);
|
|
670
792
|
plan.create.push(
|
|
671
793
|
"nuvio/START_HERE.md",
|
|
@@ -724,6 +846,12 @@ async function runInit(opts) {
|
|
|
724
846
|
} else {
|
|
725
847
|
plan.failedSteps.push("app (no App.tsx/main.tsx)");
|
|
726
848
|
}
|
|
849
|
+
if (mainEntry && overlayInstalledFromNpm(project.packageJsonPath)) {
|
|
850
|
+
const mainStyles = patchMainOverlayStyles(mainEntry);
|
|
851
|
+
if (mainStyles.ok && !mainStyles.skipped) {
|
|
852
|
+
plan.modify.push(mainEntry.replace(`${root}/`, ""));
|
|
853
|
+
}
|
|
854
|
+
}
|
|
727
855
|
let starterOk = false;
|
|
728
856
|
let starterFile;
|
|
729
857
|
if (!projectHasPageTitleId(root)) {
|