@decantr/cli 2.3.0 → 2.4.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/README.md +36 -4
- package/dist/bin.js +2 -2
- package/dist/chunk-AUQXYJ7T.js +316 -0
- package/dist/{chunk-FSZ6OIAC.js → chunk-H6TIXG5K.js} +896 -272
- package/dist/{chunk-3H3HWDJA.js → chunk-OD46PCR6.js} +354 -17
- package/dist/{chunk-WDA4SHIQ.js → chunk-PEGMSXDJ.js} +66 -7
- package/dist/{health-EENY3BFS.js → health-ZXOPGNBZ.js} +5 -1
- package/dist/index.js +2 -2
- package/dist/{studio-TBJPZZHA.js → studio-LHQXHBE7.js} +63 -1
- package/dist/{upgrade-PL755AF7.js → upgrade-XTTGHFG7.js} +1 -1
- package/dist/workspace-MOLAGT2B.js +21 -0
- package/package.json +22 -5
- package/src/templates/decantr-health.workflow.yml.template +2 -2
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
scaffoldProject,
|
|
15
15
|
syncRegistry,
|
|
16
16
|
writeExecutionPackBundleArtifacts
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-PEGMSXDJ.js";
|
|
18
18
|
import {
|
|
19
19
|
buildGuardRegistryContext,
|
|
20
20
|
createDoctrineMap,
|
|
@@ -247,119 +247,42 @@ function getApiKeyOrToken() {
|
|
|
247
247
|
import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
248
248
|
import { basename, join as join3 } from "path";
|
|
249
249
|
import { resolvePackAdapter } from "@decantr/core";
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
react: "^19.0.0",
|
|
287
|
-
"react-dom": "^19.0.0",
|
|
288
|
-
"react-router-dom": "^7.0.0",
|
|
289
|
-
"@decantr/css": "^1.0.4",
|
|
290
|
-
// P0-4: Lucide is the canonical icon library Decantr blueprints
|
|
291
|
-
// reference in personality prose ("Lucide icons"). Including it by
|
|
292
|
-
// default means cold scaffolds don't have to hand-roll inline SVGs.
|
|
293
|
-
// Tree-shaking eliminates unused imports, so the bundle cost is
|
|
294
|
-
// zero when unused and ~2KB per icon when used.
|
|
295
|
-
"lucide-react": "^0.468.0"
|
|
296
|
-
},
|
|
297
|
-
devDependencies: {
|
|
298
|
-
"@types/react": "^19.0.0",
|
|
299
|
-
"@types/react-dom": "^19.0.0",
|
|
300
|
-
"@vitejs/plugin-react": "^4.0.0",
|
|
301
|
-
typescript: "^5.7.0",
|
|
302
|
-
vite: "^6.0.0"
|
|
303
|
-
}
|
|
304
|
-
};
|
|
305
|
-
writeFileSync3(join3(projectDir, "package.json"), JSON.stringify(packageJson, null, 2) + "\n");
|
|
306
|
-
const viteConfig = `import { defineConfig } from 'vite';
|
|
307
|
-
import react from '@vitejs/plugin-react';
|
|
308
|
-
|
|
309
|
-
export default defineConfig({
|
|
310
|
-
plugins: [react()],
|
|
311
|
-
});
|
|
312
|
-
`;
|
|
313
|
-
writeFileSync3(join3(projectDir, "vite.config.ts"), viteConfig);
|
|
314
|
-
const tsconfig = {
|
|
315
|
-
compilerOptions: {
|
|
316
|
-
target: "ES2020",
|
|
317
|
-
useDefineForClassFields: true,
|
|
318
|
-
lib: ["ES2020", "DOM", "DOM.Iterable"],
|
|
319
|
-
module: "ESNext",
|
|
320
|
-
skipLibCheck: true,
|
|
321
|
-
moduleResolution: "bundler",
|
|
322
|
-
allowImportingTsExtensions: true,
|
|
323
|
-
isolatedModules: true,
|
|
324
|
-
moduleDetection: "force",
|
|
325
|
-
noEmit: true,
|
|
326
|
-
jsx: "react-jsx",
|
|
327
|
-
strict: true,
|
|
328
|
-
noUnusedLocals: true,
|
|
329
|
-
noUnusedParameters: true,
|
|
330
|
-
noFallthroughCasesInSwitch: true,
|
|
331
|
-
noUncheckedSideEffectImports: true
|
|
332
|
-
},
|
|
333
|
-
include: ["src"]
|
|
334
|
-
};
|
|
335
|
-
writeFileSync3(join3(projectDir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2) + "\n");
|
|
336
|
-
const tsconfigApp = {
|
|
337
|
-
compilerOptions: {
|
|
338
|
-
tsBuildInfoFile: "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
339
|
-
target: "ES2020",
|
|
340
|
-
useDefineForClassFields: true,
|
|
341
|
-
lib: ["ES2020", "DOM", "DOM.Iterable"],
|
|
342
|
-
module: "ESNext",
|
|
343
|
-
skipLibCheck: true,
|
|
344
|
-
moduleResolution: "bundler",
|
|
345
|
-
allowImportingTsExtensions: true,
|
|
346
|
-
isolatedModules: true,
|
|
347
|
-
moduleDetection: "force",
|
|
348
|
-
noEmit: true,
|
|
349
|
-
jsx: "react-jsx",
|
|
350
|
-
strict: true,
|
|
351
|
-
noUnusedLocals: true,
|
|
352
|
-
noUnusedParameters: true,
|
|
353
|
-
noFallthroughCasesInSwitch: true,
|
|
354
|
-
noUncheckedSideEffectImports: true
|
|
355
|
-
},
|
|
356
|
-
include: ["src"]
|
|
357
|
-
};
|
|
358
|
-
writeFileSync3(
|
|
359
|
-
join3(projectDir, "tsconfig.app.json"),
|
|
360
|
-
JSON.stringify(tsconfigApp, null, 2) + "\n"
|
|
361
|
-
);
|
|
362
|
-
const indexHtml = `<!doctype html>
|
|
250
|
+
function writeJson(path, value) {
|
|
251
|
+
writeFileSync3(path, JSON.stringify(value, null, 2) + "\n");
|
|
252
|
+
}
|
|
253
|
+
function mkdirp(path) {
|
|
254
|
+
mkdirSync3(path, { recursive: true });
|
|
255
|
+
}
|
|
256
|
+
function starterName(projectDir, fallback) {
|
|
257
|
+
return basename(projectDir) || fallback;
|
|
258
|
+
}
|
|
259
|
+
function writeViteTsConfig(projectDir, options = {}) {
|
|
260
|
+
writeJson(join3(projectDir, "tsconfig.json"), {
|
|
261
|
+
compilerOptions: {
|
|
262
|
+
target: "ES2020",
|
|
263
|
+
useDefineForClassFields: true,
|
|
264
|
+
lib: ["ES2020", "DOM", "DOM.Iterable"],
|
|
265
|
+
module: "ESNext",
|
|
266
|
+
skipLibCheck: true,
|
|
267
|
+
moduleResolution: "bundler",
|
|
268
|
+
allowImportingTsExtensions: true,
|
|
269
|
+
isolatedModules: true,
|
|
270
|
+
moduleDetection: "force",
|
|
271
|
+
noEmit: true,
|
|
272
|
+
...options.jsx ? { jsx: options.jsx } : {},
|
|
273
|
+
strict: true,
|
|
274
|
+
noUnusedLocals: true,
|
|
275
|
+
noUnusedParameters: true,
|
|
276
|
+
noFallthroughCasesInSwitch: true,
|
|
277
|
+
noUncheckedSideEffectImports: true
|
|
278
|
+
},
|
|
279
|
+
include: ["src"]
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
function writeIndexHtml(projectDir, title, entry) {
|
|
283
|
+
writeFileSync3(
|
|
284
|
+
join3(projectDir, "index.html"),
|
|
285
|
+
`<!doctype html>
|
|
363
286
|
<html lang="en">
|
|
364
287
|
<head>
|
|
365
288
|
<meta charset="UTF-8" />
|
|
@@ -368,13 +291,186 @@ export default defineConfig({
|
|
|
368
291
|
</head>
|
|
369
292
|
<body>
|
|
370
293
|
<div id="root"></div>
|
|
371
|
-
<script type="module" src="
|
|
294
|
+
<script type="module" src="${entry}"></script>
|
|
372
295
|
</body>
|
|
373
296
|
</html>
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
297
|
+
`
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
function ensureStyleDir(projectDir) {
|
|
301
|
+
mkdirp(join3(projectDir, "src", "styles"));
|
|
302
|
+
}
|
|
303
|
+
function packagePlanPackageJson(projectDir, fallbackName, packagePlan) {
|
|
304
|
+
return {
|
|
305
|
+
name: starterName(projectDir, fallbackName),
|
|
306
|
+
private: true,
|
|
307
|
+
version: "0.0.0",
|
|
308
|
+
type: "module",
|
|
309
|
+
scripts: packagePlan.scripts,
|
|
310
|
+
dependencies: packagePlan.dependencies,
|
|
311
|
+
devDependencies: packagePlan.devDependencies
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
var reactVitePackagePlan = {
|
|
315
|
+
scripts: {
|
|
316
|
+
dev: "vite",
|
|
317
|
+
build: "tsc -b && vite build",
|
|
318
|
+
preview: "vite preview"
|
|
319
|
+
},
|
|
320
|
+
dependencies: {
|
|
321
|
+
react: "^19.0.0",
|
|
322
|
+
"react-dom": "^19.0.0",
|
|
323
|
+
"react-router-dom": "^7.0.0",
|
|
324
|
+
"@decantr/css": "^1.0.4",
|
|
325
|
+
"lucide-react": "^0.468.0"
|
|
326
|
+
},
|
|
327
|
+
devDependencies: {
|
|
328
|
+
"@types/react": "^19.0.0",
|
|
329
|
+
"@types/react-dom": "^19.0.0",
|
|
330
|
+
"@vitejs/plugin-react": "^4.0.0",
|
|
331
|
+
typescript: "^5.7.0",
|
|
332
|
+
vite: "^6.0.0"
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
var nextPackagePlan = {
|
|
336
|
+
scripts: {
|
|
337
|
+
dev: "next dev",
|
|
338
|
+
build: "next build",
|
|
339
|
+
start: "next start"
|
|
340
|
+
},
|
|
341
|
+
dependencies: {
|
|
342
|
+
"@decantr/css": "^1.0.4",
|
|
343
|
+
"lucide-react": "^0.468.0",
|
|
344
|
+
next: "^16.0.0",
|
|
345
|
+
react: "^19.0.0",
|
|
346
|
+
"react-dom": "^19.0.0"
|
|
347
|
+
},
|
|
348
|
+
devDependencies: {
|
|
349
|
+
"@types/node": "^20.0.0",
|
|
350
|
+
"@types/react": "^19.0.0",
|
|
351
|
+
"@types/react-dom": "^19.0.0",
|
|
352
|
+
typescript: "^5.7.0"
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
var vanillaPackagePlan = {
|
|
356
|
+
scripts: {
|
|
357
|
+
dev: "vite",
|
|
358
|
+
build: "vite build",
|
|
359
|
+
preview: "vite preview"
|
|
360
|
+
},
|
|
361
|
+
dependencies: {
|
|
362
|
+
"@decantr/css": "^1.0.4",
|
|
363
|
+
lucide: "^0.468.0"
|
|
364
|
+
},
|
|
365
|
+
devDependencies: {
|
|
366
|
+
vite: "^6.0.0"
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
var vuePackagePlan = {
|
|
370
|
+
scripts: {
|
|
371
|
+
dev: "vite",
|
|
372
|
+
build: "vue-tsc -b && vite build",
|
|
373
|
+
preview: "vite preview"
|
|
374
|
+
},
|
|
375
|
+
dependencies: {
|
|
376
|
+
"@decantr/css": "^1.0.4",
|
|
377
|
+
"@vitejs/plugin-vue": "^5.0.0",
|
|
378
|
+
"@vue/compiler-sfc": "^3.5.0",
|
|
379
|
+
"lucide-vue-next": "^0.468.0",
|
|
380
|
+
vue: "^3.5.0",
|
|
381
|
+
"vue-router": "^4.4.0"
|
|
382
|
+
},
|
|
383
|
+
devDependencies: {
|
|
384
|
+
typescript: "^5.7.0",
|
|
385
|
+
vite: "^6.0.0",
|
|
386
|
+
"vue-tsc": "^2.1.0"
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
var sveltePackagePlan = {
|
|
390
|
+
scripts: {
|
|
391
|
+
dev: "vite dev",
|
|
392
|
+
build: "vite build",
|
|
393
|
+
preview: "vite preview"
|
|
394
|
+
},
|
|
395
|
+
dependencies: {
|
|
396
|
+
"@decantr/css": "^1.0.4",
|
|
397
|
+
"@sveltejs/adapter-auto": "^3.0.0",
|
|
398
|
+
"@sveltejs/kit": "^2.0.0",
|
|
399
|
+
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
|
400
|
+
lucide: "^0.468.0",
|
|
401
|
+
svelte: "^5.0.0"
|
|
402
|
+
},
|
|
403
|
+
devDependencies: {
|
|
404
|
+
typescript: "^5.7.0",
|
|
405
|
+
vite: "^6.0.0"
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
var angularPackagePlan = {
|
|
409
|
+
scripts: {
|
|
410
|
+
dev: "ng serve",
|
|
411
|
+
build: "ng build",
|
|
412
|
+
start: "ng serve"
|
|
413
|
+
},
|
|
414
|
+
dependencies: {
|
|
415
|
+
"@angular/animations": "^19.0.0",
|
|
416
|
+
"@angular/common": "^19.0.0",
|
|
417
|
+
"@angular/compiler": "^19.0.0",
|
|
418
|
+
"@angular/core": "^19.0.0",
|
|
419
|
+
"@angular/forms": "^19.0.0",
|
|
420
|
+
"@angular/platform-browser": "^19.0.0",
|
|
421
|
+
"@angular/router": "^19.0.0",
|
|
422
|
+
"@decantr/css": "^1.0.4",
|
|
423
|
+
lucide: "^0.468.0",
|
|
424
|
+
rxjs: "^7.8.0",
|
|
425
|
+
tslib: "^2.8.0",
|
|
426
|
+
"zone.js": "^0.15.0"
|
|
427
|
+
},
|
|
428
|
+
devDependencies: {
|
|
429
|
+
"@angular-devkit/build-angular": "^19.0.0",
|
|
430
|
+
"@angular/cli": "^19.0.0",
|
|
431
|
+
"@angular/compiler-cli": "^19.0.0",
|
|
432
|
+
typescript: "^5.7.0"
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
var solidPackagePlan = {
|
|
436
|
+
scripts: {
|
|
437
|
+
dev: "vite",
|
|
438
|
+
build: "tsc -b && vite build",
|
|
439
|
+
preview: "vite preview"
|
|
440
|
+
},
|
|
441
|
+
dependencies: {
|
|
442
|
+
"@decantr/css": "^1.0.4",
|
|
443
|
+
"@solidjs/router": "^0.15.0",
|
|
444
|
+
lucide: "^0.468.0",
|
|
445
|
+
"solid-js": "^1.9.0"
|
|
446
|
+
},
|
|
447
|
+
devDependencies: {
|
|
448
|
+
typescript: "^5.7.0",
|
|
449
|
+
vite: "^6.0.0",
|
|
450
|
+
"vite-plugin-solid": "^2.11.0"
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
function writeReactViteProject(projectDir, title, routingMode) {
|
|
454
|
+
const srcDir = join3(projectDir, "src");
|
|
455
|
+
const routerImport = routingMode === "hash" ? "HashRouter" : "BrowserRouter";
|
|
456
|
+
writeJson(join3(projectDir, "package.json"), packagePlanPackageJson(projectDir, "decantr-app", reactVitePackagePlan));
|
|
457
|
+
writeFileSync3(
|
|
458
|
+
join3(projectDir, "vite.config.ts"),
|
|
459
|
+
`import { defineConfig } from 'vite';
|
|
460
|
+
import react from '@vitejs/plugin-react';
|
|
461
|
+
|
|
462
|
+
export default defineConfig({
|
|
463
|
+
plugins: [react()],
|
|
464
|
+
});
|
|
465
|
+
`
|
|
466
|
+
);
|
|
467
|
+
writeViteTsConfig(projectDir, { jsx: "react-jsx" });
|
|
468
|
+
writeJson(join3(projectDir, "tsconfig.app.json"), JSON.parse(readFileSync3(join3(projectDir, "tsconfig.json"), "utf-8")));
|
|
469
|
+
writeIndexHtml(projectDir, title, "/src/main.tsx");
|
|
470
|
+
mkdirp(srcDir);
|
|
471
|
+
writeFileSync3(
|
|
472
|
+
join3(srcDir, "main.tsx"),
|
|
473
|
+
`import { StrictMode } from 'react';
|
|
378
474
|
import { createRoot } from 'react-dom/client';
|
|
379
475
|
import { ${routerImport} } from 'react-router-dom';
|
|
380
476
|
import { App } from './App';
|
|
@@ -389,9 +485,11 @@ createRoot(document.getElementById('root')!).render(
|
|
|
389
485
|
</${routerImport}>
|
|
390
486
|
</StrictMode>,
|
|
391
487
|
);
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
488
|
+
`
|
|
489
|
+
);
|
|
490
|
+
writeFileSync3(
|
|
491
|
+
join3(srcDir, "App.tsx"),
|
|
492
|
+
`import { css } from '@decantr/css';
|
|
395
493
|
import { Routes, Route } from 'react-router-dom';
|
|
396
494
|
|
|
397
495
|
function WelcomePage() {
|
|
@@ -403,9 +501,7 @@ function WelcomePage() {
|
|
|
403
501
|
<div className={css('_flex _col _aic _gap4 _textc') + ' d-surface'} data-elevation="raised">
|
|
404
502
|
<p className="d-label" data-anchor>Decantr starter</p>
|
|
405
503
|
<h1 className={css('_heading2')}>${title}</h1>
|
|
406
|
-
<p className={css('_textsm _fgmuted _mw[32rem]')}>
|
|
407
|
-
Scaffolded with Decantr. Read .decantr/context/scaffold-pack.md first, then use DECANTR.md as a lookup reference.
|
|
408
|
-
</p>
|
|
504
|
+
<p className={css('_textsm _fgmuted _mw[32rem]')}>Scaffolded with Decantr. Read .decantr/context/scaffold-pack.md first, then use DECANTR.md as a lookup reference.</p>
|
|
409
505
|
<div className={css('_flex _gap3 _wrap _jcc')}>
|
|
410
506
|
<span className="d-annotation" data-status="info">Runtime: @decantr/css</span>
|
|
411
507
|
<span className="d-annotation" data-status="success">Routing: ${routingMode}</span>
|
|
@@ -424,102 +520,42 @@ export function App() {
|
|
|
424
520
|
</Routes>
|
|
425
521
|
);
|
|
426
522
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
scripts: {
|
|
464
|
-
dev: "next dev",
|
|
465
|
-
build: "next build",
|
|
466
|
-
start: "next start"
|
|
467
|
-
},
|
|
468
|
-
dependencies: {
|
|
469
|
-
"@decantr/css": "^1.0.4",
|
|
470
|
-
"lucide-react": "^0.468.0",
|
|
471
|
-
next: "^16.0.0",
|
|
472
|
-
react: "^19.0.0",
|
|
473
|
-
"react-dom": "^19.0.0"
|
|
474
|
-
},
|
|
475
|
-
devDependencies: {
|
|
476
|
-
"@types/node": "^20.0.0",
|
|
477
|
-
"@types/react": "^19.0.0",
|
|
478
|
-
"@types/react-dom": "^19.0.0",
|
|
479
|
-
typescript: "^5.7.0"
|
|
480
|
-
}
|
|
481
|
-
};
|
|
482
|
-
writeFileSync3(join3(projectDir, "package.json"), JSON.stringify(packageJson, null, 2) + "\n");
|
|
483
|
-
writeFileSync3(
|
|
484
|
-
join3(projectDir, "next.config.ts"),
|
|
485
|
-
'import type { NextConfig } from "next";\n\nconst nextConfig: NextConfig = {};\n\nexport default nextConfig;\n'
|
|
486
|
-
);
|
|
487
|
-
writeFileSync3(
|
|
488
|
-
join3(projectDir, "next-env.d.ts"),
|
|
489
|
-
'/// <reference types="next" />\n/// <reference types="next/image-types/global" />\n\n// This file is generated by Next.js.\n'
|
|
490
|
-
);
|
|
491
|
-
writeFileSync3(
|
|
492
|
-
join3(projectDir, "tsconfig.json"),
|
|
493
|
-
JSON.stringify(
|
|
494
|
-
{
|
|
495
|
-
compilerOptions: {
|
|
496
|
-
target: "ES2017",
|
|
497
|
-
lib: ["dom", "dom.iterable", "esnext"],
|
|
498
|
-
allowJs: true,
|
|
499
|
-
skipLibCheck: true,
|
|
500
|
-
strict: true,
|
|
501
|
-
noEmit: true,
|
|
502
|
-
esModuleInterop: true,
|
|
503
|
-
module: "esnext",
|
|
504
|
-
moduleResolution: "bundler",
|
|
505
|
-
resolveJsonModule: true,
|
|
506
|
-
isolatedModules: true,
|
|
507
|
-
jsx: "preserve",
|
|
508
|
-
incremental: true,
|
|
509
|
-
plugins: [{ name: "next" }]
|
|
510
|
-
},
|
|
511
|
-
include: ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
512
|
-
exclude: ["node_modules"]
|
|
513
|
-
},
|
|
514
|
-
null,
|
|
515
|
-
2
|
|
516
|
-
) + "\n"
|
|
517
|
-
);
|
|
518
|
-
mkdirSync3(appDir, { recursive: true });
|
|
519
|
-
mkdirSync3(stylesDir, { recursive: true });
|
|
520
|
-
writeFileSync3(
|
|
521
|
-
join3(appDir, "layout.tsx"),
|
|
522
|
-
`import type { Metadata } from 'next';
|
|
523
|
+
`
|
|
524
|
+
);
|
|
525
|
+
writeFileSync3(join3(srcDir, "vite-env.d.ts"), '/// <reference types="vite/client" />\n');
|
|
526
|
+
ensureStyleDir(projectDir);
|
|
527
|
+
}
|
|
528
|
+
function writeNextProject(projectDir, title) {
|
|
529
|
+
const appDir = join3(projectDir, "app");
|
|
530
|
+
const stylesDir = join3(projectDir, "src", "styles");
|
|
531
|
+
writeJson(join3(projectDir, "package.json"), packagePlanPackageJson(projectDir, "decantr-next-app", nextPackagePlan));
|
|
532
|
+
writeFileSync3(join3(projectDir, "next.config.ts"), 'import type { NextConfig } from "next";\n\nconst nextConfig: NextConfig = {};\n\nexport default nextConfig;\n');
|
|
533
|
+
writeFileSync3(join3(projectDir, "next-env.d.ts"), '/// <reference types="next" />\n/// <reference types="next/image-types/global" />\n\n// This file is generated by Next.js.\n');
|
|
534
|
+
writeJson(join3(projectDir, "tsconfig.json"), {
|
|
535
|
+
compilerOptions: {
|
|
536
|
+
target: "ES2017",
|
|
537
|
+
lib: ["dom", "dom.iterable", "esnext"],
|
|
538
|
+
allowJs: true,
|
|
539
|
+
skipLibCheck: true,
|
|
540
|
+
strict: true,
|
|
541
|
+
noEmit: true,
|
|
542
|
+
esModuleInterop: true,
|
|
543
|
+
module: "esnext",
|
|
544
|
+
moduleResolution: "bundler",
|
|
545
|
+
resolveJsonModule: true,
|
|
546
|
+
isolatedModules: true,
|
|
547
|
+
jsx: "preserve",
|
|
548
|
+
incremental: true,
|
|
549
|
+
plugins: [{ name: "next" }]
|
|
550
|
+
},
|
|
551
|
+
include: ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
552
|
+
exclude: ["node_modules"]
|
|
553
|
+
});
|
|
554
|
+
mkdirp(appDir);
|
|
555
|
+
mkdirp(stylesDir);
|
|
556
|
+
writeFileSync3(
|
|
557
|
+
join3(appDir, "layout.tsx"),
|
|
558
|
+
`import type { Metadata } from 'next';
|
|
523
559
|
import '../src/styles/global.css';
|
|
524
560
|
import '../src/styles/tokens.css';
|
|
525
561
|
import '../src/styles/treatments.css';
|
|
@@ -537,10 +573,10 @@ export default function RootLayout({ children }: Readonly<{ children: React.Reac
|
|
|
537
573
|
);
|
|
538
574
|
}
|
|
539
575
|
`
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
576
|
+
);
|
|
577
|
+
writeFileSync3(
|
|
578
|
+
join3(appDir, "page.tsx"),
|
|
579
|
+
`import { css } from '@decantr/css';
|
|
544
580
|
|
|
545
581
|
export default function HomePage() {
|
|
546
582
|
return (
|
|
@@ -557,54 +593,486 @@ export default function HomePage() {
|
|
|
557
593
|
);
|
|
558
594
|
}
|
|
559
595
|
`
|
|
560
|
-
|
|
561
|
-
|
|
596
|
+
);
|
|
597
|
+
}
|
|
598
|
+
function writeVanillaProject(projectDir, title, routingMode) {
|
|
599
|
+
const srcDir = join3(projectDir, "src");
|
|
600
|
+
writeJson(join3(projectDir, "package.json"), packagePlanPackageJson(projectDir, "decantr-vanilla-app", vanillaPackagePlan));
|
|
601
|
+
writeIndexHtml(projectDir, title, "/src/main.js");
|
|
602
|
+
mkdirp(srcDir);
|
|
603
|
+
writeFileSync3(
|
|
604
|
+
join3(srcDir, "main.js"),
|
|
605
|
+
`import { css } from '@decantr/css';
|
|
606
|
+
import './styles/global.css';
|
|
607
|
+
import './styles/tokens.css';
|
|
608
|
+
import './styles/treatments.css';
|
|
609
|
+
|
|
610
|
+
const root = document.getElementById('root');
|
|
611
|
+
if (!root) throw new Error('Missing #root element.');
|
|
612
|
+
|
|
613
|
+
root.innerHTML = \`
|
|
614
|
+
<a href="#main-content" class="skip-link">Skip to content</a>
|
|
615
|
+
<main id="main-content" class="\${css('_minh[100vh] _flex _col _aic _jcc _p6 _gap4')}">
|
|
616
|
+
<section class="\${css('_wfull _mw[42rem]')} d-section" data-density="comfortable">
|
|
617
|
+
<div class="\${css('_flex _col _aic _gap4 _textc')} d-surface" data-elevation="raised">
|
|
618
|
+
<p class="d-label" data-anchor>Decantr starter</p>
|
|
619
|
+
<h1 class="\${css('_heading2')}">${title}</h1>
|
|
620
|
+
<p class="\${css('_textsm _fgmuted _mw[32rem]')}">Scaffolded with Decantr. Read .decantr/context/scaffold-pack.md first, then use DECANTR.md as a lookup reference.</p>
|
|
621
|
+
<div class="\${css('_flex _gap3 _wrap _jcc')}">
|
|
622
|
+
<span class="d-annotation" data-status="info">Runtime: vanilla Vite</span>
|
|
623
|
+
<span class="d-annotation" data-status="success">Routing: ${routingMode}</span>
|
|
624
|
+
</div>
|
|
625
|
+
</div>
|
|
626
|
+
</section>
|
|
627
|
+
</main>
|
|
628
|
+
\`;
|
|
629
|
+
`
|
|
630
|
+
);
|
|
631
|
+
ensureStyleDir(projectDir);
|
|
632
|
+
}
|
|
633
|
+
function writeVueProject(projectDir, title, routingMode) {
|
|
634
|
+
const srcDir = join3(projectDir, "src");
|
|
635
|
+
const historyFactory = routingMode === "hash" ? "createWebHashHistory" : "createWebHistory";
|
|
636
|
+
writeJson(join3(projectDir, "package.json"), packagePlanPackageJson(projectDir, "decantr-vue-app", vuePackagePlan));
|
|
637
|
+
writeFileSync3(join3(projectDir, "vite.config.ts"), `import { defineConfig } from 'vite';
|
|
638
|
+
import vue from '@vitejs/plugin-vue';
|
|
639
|
+
|
|
640
|
+
export default defineConfig({ plugins: [vue()] });
|
|
641
|
+
`);
|
|
642
|
+
writeViteTsConfig(projectDir);
|
|
643
|
+
writeFileSync3(join3(projectDir, "env.d.ts"), '/// <reference types="vite/client" />\n\ndeclare module "*.vue";\n');
|
|
644
|
+
writeIndexHtml(projectDir, title, "/src/main.ts");
|
|
645
|
+
mkdirp(srcDir);
|
|
646
|
+
writeFileSync3(
|
|
647
|
+
join3(srcDir, "main.ts"),
|
|
648
|
+
`import { createApp } from 'vue';
|
|
649
|
+
import { createRouter, ${historyFactory} } from 'vue-router';
|
|
650
|
+
import App from './App.vue';
|
|
651
|
+
import './styles/global.css';
|
|
652
|
+
import './styles/tokens.css';
|
|
653
|
+
import './styles/treatments.css';
|
|
654
|
+
|
|
655
|
+
const router = createRouter({
|
|
656
|
+
history: ${historyFactory}(),
|
|
657
|
+
routes: [{ path: '/', component: App }],
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
createApp(App).use(router).mount('#root');
|
|
661
|
+
`
|
|
662
|
+
);
|
|
663
|
+
writeFileSync3(
|
|
664
|
+
join3(srcDir, "App.vue"),
|
|
665
|
+
`<script setup lang="ts">
|
|
666
|
+
import { css } from '@decantr/css';
|
|
667
|
+
</script>
|
|
668
|
+
|
|
669
|
+
<template>
|
|
670
|
+
<a href="#main-content" class="skip-link">Skip to content</a>
|
|
671
|
+
<main id="main-content" :class="css('_minh[100vh] _flex _col _aic _jcc _p6 _gap4')">
|
|
672
|
+
<section :class="css('_wfull _mw[42rem]') + ' d-section'" data-density="comfortable">
|
|
673
|
+
<div :class="css('_flex _col _aic _gap4 _textc') + ' d-surface'" data-elevation="raised">
|
|
674
|
+
<p class="d-label" data-anchor>Decantr starter</p>
|
|
675
|
+
<h1 :class="css('_heading2')">${title}</h1>
|
|
676
|
+
<p :class="css('_textsm _fgmuted _mw[32rem]')">Scaffolded with Decantr. Read .decantr/context/scaffold-pack.md first, then use DECANTR.md as a lookup reference.</p>
|
|
677
|
+
<div :class="css('_flex _gap3 _wrap _jcc')">
|
|
678
|
+
<span class="d-annotation" data-status="info">Runtime: Vue + Vite</span>
|
|
679
|
+
<span class="d-annotation" data-status="success">Routing: ${routingMode}</span>
|
|
680
|
+
</div>
|
|
681
|
+
</div>
|
|
682
|
+
</section>
|
|
683
|
+
</main>
|
|
684
|
+
</template>
|
|
685
|
+
`
|
|
686
|
+
);
|
|
687
|
+
ensureStyleDir(projectDir);
|
|
688
|
+
}
|
|
689
|
+
function writeSvelteProject(projectDir, title) {
|
|
690
|
+
const routesDir = join3(projectDir, "src", "routes");
|
|
691
|
+
writeJson(join3(projectDir, "package.json"), packagePlanPackageJson(projectDir, "decantr-svelte-app", sveltePackagePlan));
|
|
692
|
+
writeFileSync3(join3(projectDir, "svelte.config.js"), `import adapter from '@sveltejs/adapter-auto';
|
|
693
|
+
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
|
694
|
+
|
|
695
|
+
export default { preprocess: vitePreprocess(), kit: { adapter: adapter() } };
|
|
696
|
+
`);
|
|
697
|
+
writeFileSync3(join3(projectDir, "vite.config.ts"), `import { sveltekit } from '@sveltejs/kit/vite';
|
|
698
|
+
import { defineConfig } from 'vite';
|
|
699
|
+
|
|
700
|
+
export default defineConfig({ plugins: [sveltekit()] });
|
|
701
|
+
`);
|
|
702
|
+
writeViteTsConfig(projectDir);
|
|
703
|
+
mkdirp(routesDir);
|
|
704
|
+
writeFileSync3(join3(projectDir, "src", "app.html"), '<!doctype html>\n<html lang="en">\n <head>\n <meta charset="utf-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1" />\n %sveltekit.head%\n </head>\n <body data-sveltekit-preload-data="hover">\n <div style="display: contents">%sveltekit.body%</div>\n </body>\n</html>\n');
|
|
705
|
+
writeFileSync3(join3(routesDir, "+layout.svelte"), `<script lang="ts">
|
|
706
|
+
import '../styles/global.css';
|
|
707
|
+
import '../styles/tokens.css';
|
|
708
|
+
import '../styles/treatments.css';
|
|
709
|
+
let { children } = $props();
|
|
710
|
+
</script>
|
|
711
|
+
|
|
712
|
+
{@render children()}
|
|
713
|
+
`);
|
|
714
|
+
writeFileSync3(
|
|
715
|
+
join3(routesDir, "+page.svelte"),
|
|
716
|
+
`<script lang="ts">
|
|
717
|
+
import { css } from '@decantr/css';
|
|
718
|
+
</script>
|
|
719
|
+
|
|
720
|
+
<svelte:head>
|
|
721
|
+
<title>${title}</title>
|
|
722
|
+
</svelte:head>
|
|
723
|
+
|
|
724
|
+
<a href="#main-content" class="skip-link">Skip to content</a>
|
|
725
|
+
<main id="main-content" class={css('_minh[100vh] _flex _col _aic _jcc _p6 _gap4')}>
|
|
726
|
+
<section class={css('_wfull _mw[42rem]') + ' d-section'} data-density="comfortable">
|
|
727
|
+
<div class={css('_flex _col _aic _gap4 _textc') + ' d-surface'} data-elevation="raised">
|
|
728
|
+
<p class="d-label" data-anchor>Decantr starter</p>
|
|
729
|
+
<h1 class={css('_heading2')}>${title}</h1>
|
|
730
|
+
<p class={css('_textsm _fgmuted _mw[32rem]')}>Scaffolded with Decantr. Read .decantr/context/scaffold-pack.md first, then use DECANTR.md as a lookup reference.</p>
|
|
731
|
+
<span class="d-annotation" data-status="info">Runtime: SvelteKit</span>
|
|
732
|
+
</div>
|
|
733
|
+
</section>
|
|
734
|
+
</main>
|
|
735
|
+
`
|
|
736
|
+
);
|
|
737
|
+
ensureStyleDir(projectDir);
|
|
738
|
+
}
|
|
739
|
+
function writeAngularProject(projectDir, title) {
|
|
740
|
+
const appDir = join3(projectDir, "src", "app");
|
|
741
|
+
writeJson(join3(projectDir, "package.json"), packagePlanPackageJson(projectDir, "decantr-angular-app", angularPackagePlan));
|
|
742
|
+
writeJson(join3(projectDir, "angular.json"), {
|
|
743
|
+
version: 1,
|
|
744
|
+
projects: {
|
|
745
|
+
app: {
|
|
746
|
+
projectType: "application",
|
|
747
|
+
root: "",
|
|
748
|
+
sourceRoot: "src",
|
|
749
|
+
architect: {
|
|
750
|
+
build: {
|
|
751
|
+
builder: "@angular-devkit/build-angular:application",
|
|
752
|
+
options: {
|
|
753
|
+
outputPath: "dist",
|
|
754
|
+
index: "src/index.html",
|
|
755
|
+
browser: "src/main.ts",
|
|
756
|
+
tsConfig: "tsconfig.app.json",
|
|
757
|
+
styles: ["src/styles.css", "src/styles/tokens.css", "src/styles/treatments.css"]
|
|
758
|
+
}
|
|
759
|
+
},
|
|
760
|
+
serve: {
|
|
761
|
+
builder: "@angular-devkit/build-angular:dev-server",
|
|
762
|
+
options: { buildTarget: "app:build" }
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
});
|
|
768
|
+
writeJson(join3(projectDir, "tsconfig.json"), {
|
|
769
|
+
compilerOptions: {
|
|
770
|
+
target: "ES2022",
|
|
771
|
+
module: "ES2022",
|
|
772
|
+
moduleResolution: "bundler",
|
|
773
|
+
strict: true,
|
|
774
|
+
skipLibCheck: true,
|
|
775
|
+
experimentalDecorators: true,
|
|
776
|
+
useDefineForClassFields: false,
|
|
777
|
+
lib: ["ES2022", "DOM"]
|
|
778
|
+
}
|
|
779
|
+
});
|
|
780
|
+
writeJson(join3(projectDir, "tsconfig.app.json"), { extends: "./tsconfig.json", files: ["src/main.ts"], include: ["src/**/*.d.ts"] });
|
|
781
|
+
mkdirp(appDir);
|
|
782
|
+
writeFileSync3(join3(projectDir, "src", "index.html"), `<!doctype html>
|
|
783
|
+
<html lang="en">
|
|
784
|
+
<head><meta charset="utf-8"><title>${title}</title><meta name="viewport" content="width=device-width, initial-scale=1"></head>
|
|
785
|
+
<body><app-root></app-root></body>
|
|
786
|
+
</html>
|
|
787
|
+
`);
|
|
788
|
+
writeFileSync3(join3(projectDir, "src", "main.ts"), `import { bootstrapApplication } from '@angular/platform-browser';
|
|
789
|
+
import { provideRouter } from '@angular/router';
|
|
790
|
+
import { AppComponent } from './app/app.component';
|
|
791
|
+
import { routes } from './app/app.routes';
|
|
792
|
+
|
|
793
|
+
bootstrapApplication(AppComponent, { providers: [provideRouter(routes)] }).catch((err) => console.error(err));
|
|
794
|
+
`);
|
|
795
|
+
writeFileSync3(join3(projectDir, "src", "styles.css"), '@import "./styles/global.css";\n');
|
|
796
|
+
writeFileSync3(join3(appDir, "app.routes.ts"), `import type { Routes } from '@angular/router';
|
|
797
|
+
import { AppComponent } from './app.component';
|
|
798
|
+
|
|
799
|
+
export const routes: Routes = [{ path: '', component: AppComponent }];
|
|
800
|
+
`);
|
|
801
|
+
writeFileSync3(
|
|
802
|
+
join3(appDir, "app.component.ts"),
|
|
803
|
+
`import { Component } from '@angular/core';
|
|
804
|
+
|
|
805
|
+
@Component({
|
|
806
|
+
selector: 'app-root',
|
|
807
|
+
standalone: true,
|
|
808
|
+
template: \`
|
|
809
|
+
<a href="#main-content" class="skip-link">Skip to content</a>
|
|
810
|
+
<main id="main-content" class="_minh[100vh] _flex _col _aic _jcc _p6 _gap4">
|
|
811
|
+
<section class="_wfull _mw[42rem] d-section" data-density="comfortable">
|
|
812
|
+
<div class="_flex _col _aic _gap4 _textc d-surface" data-elevation="raised">
|
|
813
|
+
<p class="d-label" data-anchor>Decantr starter</p>
|
|
814
|
+
<h1 class="_heading2">${title}</h1>
|
|
815
|
+
<p class="_textsm _fgmuted _mw[32rem]">Scaffolded with Decantr. Read .decantr/context/scaffold-pack.md first, then use DECANTR.md as a lookup reference.</p>
|
|
816
|
+
<span class="d-annotation" data-status="info">Runtime: Angular</span>
|
|
817
|
+
</div>
|
|
818
|
+
</section>
|
|
819
|
+
</main>
|
|
820
|
+
\`,
|
|
821
|
+
})
|
|
822
|
+
export class AppComponent {}
|
|
823
|
+
`
|
|
824
|
+
);
|
|
825
|
+
ensureStyleDir(projectDir);
|
|
826
|
+
}
|
|
827
|
+
function writeSolidProject(projectDir, title, routingMode) {
|
|
828
|
+
const srcDir = join3(projectDir, "src");
|
|
829
|
+
const routerImport = routingMode === "hash" ? "HashRouter" : "Router";
|
|
830
|
+
writeJson(join3(projectDir, "package.json"), packagePlanPackageJson(projectDir, "decantr-solid-app", solidPackagePlan));
|
|
831
|
+
writeFileSync3(join3(projectDir, "vite.config.ts"), `import { defineConfig } from 'vite';
|
|
832
|
+
import solid from 'vite-plugin-solid';
|
|
833
|
+
|
|
834
|
+
export default defineConfig({ plugins: [solid()] });
|
|
835
|
+
`);
|
|
836
|
+
writeViteTsConfig(projectDir, { jsx: "preserve" });
|
|
837
|
+
writeJson(join3(projectDir, "tsconfig.app.json"), JSON.parse(readFileSync3(join3(projectDir, "tsconfig.json"), "utf-8")));
|
|
838
|
+
writeIndexHtml(projectDir, title, "/src/main.tsx");
|
|
839
|
+
mkdirp(srcDir);
|
|
840
|
+
writeFileSync3(
|
|
841
|
+
join3(srcDir, "main.tsx"),
|
|
842
|
+
`import { render } from 'solid-js/web';
|
|
843
|
+
import { ${routerImport} } from '@solidjs/router';
|
|
844
|
+
import { App } from './App';
|
|
845
|
+
import './styles/global.css';
|
|
846
|
+
import './styles/tokens.css';
|
|
847
|
+
import './styles/treatments.css';
|
|
848
|
+
|
|
849
|
+
render(() => (
|
|
850
|
+
<${routerImport}>
|
|
851
|
+
<App />
|
|
852
|
+
</${routerImport}>
|
|
853
|
+
), document.getElementById('root')!);
|
|
854
|
+
`
|
|
855
|
+
);
|
|
856
|
+
writeFileSync3(
|
|
857
|
+
join3(srcDir, "App.tsx"),
|
|
858
|
+
`import { css } from '@decantr/css';
|
|
859
|
+
|
|
860
|
+
export function App() {
|
|
861
|
+
return (
|
|
862
|
+
<>
|
|
863
|
+
<a href="#main-content" class="skip-link">Skip to content</a>
|
|
864
|
+
<main id="main-content" class={css('_minh[100vh] _flex _col _aic _jcc _p6 _gap4')}>
|
|
865
|
+
<section class={css('_wfull _mw[42rem]') + ' d-section'} data-density="comfortable">
|
|
866
|
+
<div class={css('_flex _col _aic _gap4 _textc') + ' d-surface'} data-elevation="raised">
|
|
867
|
+
<p class="d-label" data-anchor>Decantr starter</p>
|
|
868
|
+
<h1 class={css('_heading2')}>${title}</h1>
|
|
869
|
+
<p class={css('_textsm _fgmuted _mw[32rem]')}>Scaffolded with Decantr. Read .decantr/context/scaffold-pack.md first, then use DECANTR.md as a lookup reference.</p>
|
|
870
|
+
<div class={css('_flex _gap3 _wrap _jcc')}>
|
|
871
|
+
<span class="d-annotation" data-status="info">Runtime: Solid + Vite</span>
|
|
872
|
+
<span class="d-annotation" data-status="success">Routing: ${routingMode}</span>
|
|
873
|
+
</div>
|
|
874
|
+
</div>
|
|
875
|
+
</section>
|
|
876
|
+
</main>
|
|
877
|
+
</>
|
|
878
|
+
);
|
|
879
|
+
}
|
|
880
|
+
`
|
|
881
|
+
);
|
|
882
|
+
ensureStyleDir(projectDir);
|
|
883
|
+
}
|
|
884
|
+
var certifiedCapabilities = {
|
|
885
|
+
bootstrap: true,
|
|
886
|
+
realize: true,
|
|
887
|
+
attach: true,
|
|
888
|
+
styling: true,
|
|
889
|
+
verify: true
|
|
562
890
|
};
|
|
563
|
-
var
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
891
|
+
var DECANTR_ADAPTERS = {
|
|
892
|
+
"react-vite": {
|
|
893
|
+
id: "react-vite",
|
|
894
|
+
label: "React + Vite starter",
|
|
895
|
+
target: "react",
|
|
896
|
+
aliases: ["react"],
|
|
897
|
+
status: "certified",
|
|
898
|
+
packAdapter: "react-vite",
|
|
899
|
+
routing: "history",
|
|
900
|
+
capabilities: certifiedCapabilities,
|
|
901
|
+
attach: {
|
|
902
|
+
routeRoots: ["src/App.tsx", "src/routes", "src/pages"],
|
|
903
|
+
layoutFiles: ["src/App.tsx", "src/main.tsx"],
|
|
904
|
+
componentRoots: ["src/components", "src/pages", "src/routes"]
|
|
905
|
+
},
|
|
906
|
+
verify: { devCommand: "npm run dev", buildCommand: "npm run build", distDir: "dist" },
|
|
907
|
+
packagePlan: reactVitePackagePlan,
|
|
908
|
+
docs: { summary: "React + Vite runnable starter.", notes: ["Uses React Router and @decantr/css."] },
|
|
909
|
+
writeProjectFiles: writeReactViteProject
|
|
910
|
+
},
|
|
911
|
+
"next-app": {
|
|
912
|
+
id: "next-app",
|
|
913
|
+
label: "Next.js App Router starter",
|
|
914
|
+
target: "nextjs",
|
|
915
|
+
aliases: ["next", "nextjs"],
|
|
916
|
+
status: "certified",
|
|
917
|
+
packAdapter: "nextjs",
|
|
918
|
+
routing: "pathname",
|
|
919
|
+
capabilities: certifiedCapabilities,
|
|
920
|
+
attach: {
|
|
921
|
+
routeRoots: ["app", "pages"],
|
|
922
|
+
layoutFiles: ["app/layout.tsx", "pages/_app.tsx"],
|
|
923
|
+
componentRoots: ["components", "src/components", "app"]
|
|
924
|
+
},
|
|
925
|
+
verify: { devCommand: "npm run dev", buildCommand: "npm run build", distDir: ".next" },
|
|
926
|
+
packagePlan: nextPackagePlan,
|
|
927
|
+
docs: { summary: "Next.js App Router runnable starter.", notes: ["Uses App Router for greenfield bootstraps."] },
|
|
928
|
+
writeProjectFiles: writeNextProject
|
|
929
|
+
},
|
|
930
|
+
"vanilla-vite": {
|
|
931
|
+
id: "vanilla-vite",
|
|
932
|
+
label: "Vanilla HTML/CSS/JS + Vite starter",
|
|
933
|
+
target: "html",
|
|
934
|
+
aliases: ["html", "vanilla", "javascript", "js"],
|
|
935
|
+
status: "certified",
|
|
936
|
+
packAdapter: "vanilla-vite",
|
|
937
|
+
routing: "history",
|
|
938
|
+
capabilities: certifiedCapabilities,
|
|
939
|
+
attach: {
|
|
940
|
+
routeRoots: ["index.html", "src/main.js", "src/routes"],
|
|
941
|
+
layoutFiles: ["index.html", "src/main.js"],
|
|
942
|
+
componentRoots: ["src/components", "src"]
|
|
943
|
+
},
|
|
944
|
+
verify: { devCommand: "npm run dev", buildCommand: "npm run build", distDir: "dist" },
|
|
945
|
+
packagePlan: vanillaPackagePlan,
|
|
946
|
+
docs: { summary: "Plain web runnable starter.", notes: ["Uses DOM APIs and @decantr/css without a UI framework."] },
|
|
947
|
+
writeProjectFiles: writeVanillaProject
|
|
948
|
+
},
|
|
949
|
+
"vue-vite": {
|
|
950
|
+
id: "vue-vite",
|
|
951
|
+
label: "Vue + Vite starter",
|
|
952
|
+
target: "vue",
|
|
953
|
+
aliases: ["vue", "vue3"],
|
|
954
|
+
status: "certified",
|
|
955
|
+
packAdapter: "vue-vite",
|
|
956
|
+
routing: "history",
|
|
957
|
+
capabilities: certifiedCapabilities,
|
|
958
|
+
attach: {
|
|
959
|
+
routeRoots: ["src/main.ts", "src/router.ts", "src/views"],
|
|
960
|
+
layoutFiles: ["src/App.vue", "src/main.ts"],
|
|
961
|
+
componentRoots: ["src/components", "src/views"]
|
|
962
|
+
},
|
|
963
|
+
verify: { devCommand: "npm run dev", buildCommand: "npm run build", distDir: "dist" },
|
|
964
|
+
packagePlan: vuePackagePlan,
|
|
965
|
+
docs: { summary: "Vue 3 + Vite runnable starter.", notes: ["Uses Vue Router and @decantr/css."] },
|
|
966
|
+
writeProjectFiles: writeVueProject
|
|
967
|
+
},
|
|
968
|
+
sveltekit: {
|
|
969
|
+
id: "sveltekit",
|
|
970
|
+
label: "SvelteKit starter",
|
|
971
|
+
target: "svelte",
|
|
972
|
+
aliases: ["svelte", "sveltekit"],
|
|
973
|
+
status: "certified",
|
|
974
|
+
packAdapter: "sveltekit",
|
|
975
|
+
routing: "framework-native",
|
|
976
|
+
capabilities: certifiedCapabilities,
|
|
977
|
+
attach: {
|
|
978
|
+
routeRoots: ["src/routes"],
|
|
979
|
+
layoutFiles: ["src/routes/+layout.svelte", "src/app.html"],
|
|
980
|
+
componentRoots: ["src/lib", "src/routes"]
|
|
981
|
+
},
|
|
982
|
+
verify: { devCommand: "npm run dev", buildCommand: "npm run build", distDir: ".svelte-kit" },
|
|
983
|
+
packagePlan: sveltePackagePlan,
|
|
984
|
+
docs: { summary: "SvelteKit runnable starter.", notes: ["Uses SvelteKit file routing and @decantr/css."] },
|
|
985
|
+
writeProjectFiles: writeSvelteProject
|
|
986
|
+
},
|
|
987
|
+
angular: {
|
|
988
|
+
id: "angular",
|
|
989
|
+
label: "Angular standalone starter",
|
|
990
|
+
target: "angular",
|
|
991
|
+
aliases: ["angular", "ng"],
|
|
992
|
+
status: "certified",
|
|
993
|
+
packAdapter: "angular",
|
|
994
|
+
routing: "framework-native",
|
|
995
|
+
capabilities: certifiedCapabilities,
|
|
996
|
+
attach: {
|
|
997
|
+
routeRoots: ["src/app/app.routes.ts"],
|
|
998
|
+
layoutFiles: ["src/app/app.component.ts", "src/main.ts"],
|
|
999
|
+
componentRoots: ["src/app"]
|
|
1000
|
+
},
|
|
1001
|
+
verify: { devCommand: "npm run dev", buildCommand: "npm run build", distDir: "dist" },
|
|
1002
|
+
packagePlan: angularPackagePlan,
|
|
1003
|
+
docs: { summary: "Angular standalone runnable starter.", notes: ["Uses Angular Router and global Decantr CSS files."] },
|
|
1004
|
+
writeProjectFiles: writeAngularProject
|
|
574
1005
|
},
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
1006
|
+
"solid-vite": {
|
|
1007
|
+
id: "solid-vite",
|
|
1008
|
+
label: "Solid + Vite starter",
|
|
1009
|
+
target: "solid",
|
|
1010
|
+
aliases: ["solid", "solidjs"],
|
|
1011
|
+
status: "certified",
|
|
1012
|
+
packAdapter: "solid-vite",
|
|
1013
|
+
routing: "history",
|
|
1014
|
+
capabilities: certifiedCapabilities,
|
|
1015
|
+
attach: {
|
|
1016
|
+
routeRoots: ["src/App.tsx", "src/routes", "src/pages"],
|
|
1017
|
+
layoutFiles: ["src/App.tsx", "src/main.tsx"],
|
|
1018
|
+
componentRoots: ["src/components", "src/pages", "src/routes"]
|
|
1019
|
+
},
|
|
1020
|
+
verify: { devCommand: "npm run dev", buildCommand: "npm run build", distDir: "dist" },
|
|
1021
|
+
packagePlan: solidPackagePlan,
|
|
1022
|
+
docs: { summary: "Solid + Vite runnable starter.", notes: ["Uses @solidjs/router and @decantr/css."] },
|
|
1023
|
+
writeProjectFiles: writeSolidProject
|
|
579
1024
|
},
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
1025
|
+
"generic-web": {
|
|
1026
|
+
id: "generic-web",
|
|
1027
|
+
label: "Generic web contract adapter",
|
|
1028
|
+
target: "generic",
|
|
1029
|
+
aliases: [],
|
|
1030
|
+
status: "contract-only",
|
|
1031
|
+
packAdapter: "generic-web",
|
|
1032
|
+
routing: "history",
|
|
1033
|
+
capabilities: { bootstrap: false, realize: false, attach: true, styling: true, verify: true },
|
|
1034
|
+
attach: {
|
|
1035
|
+
routeRoots: ["src", "app", "pages"],
|
|
1036
|
+
layoutFiles: ["index.html", "src/main.ts", "src/main.tsx"],
|
|
1037
|
+
componentRoots: ["src/components", "components"]
|
|
1038
|
+
},
|
|
1039
|
+
verify: { devCommand: "npm run dev", buildCommand: "npm run build", distDir: "dist" },
|
|
1040
|
+
docs: { summary: "Contract-only fallback for unsupported web targets.", notes: ["Does not write framework runtime files."] }
|
|
584
1041
|
}
|
|
585
1042
|
};
|
|
586
|
-
var
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
1043
|
+
var TARGET_ALIASES = /* @__PURE__ */ new Map();
|
|
1044
|
+
for (const adapter of Object.values(DECANTR_ADAPTERS)) {
|
|
1045
|
+
TARGET_ALIASES.set(adapter.target, adapter.id);
|
|
1046
|
+
TARGET_ALIASES.set(adapter.id, adapter.id);
|
|
1047
|
+
for (const alias of adapter.aliases) TARGET_ALIASES.set(alias, adapter.id);
|
|
1048
|
+
}
|
|
1049
|
+
function normalizeTarget(target) {
|
|
1050
|
+
return (target || "react").toLowerCase();
|
|
1051
|
+
}
|
|
1052
|
+
function platformTypeForTarget(target) {
|
|
1053
|
+
return target === "nextjs" || target === "next" || target === "sveltekit" ? "ssr" : "spa";
|
|
1054
|
+
}
|
|
1055
|
+
function adapterIdForTarget(target, packAdapter) {
|
|
1056
|
+
return TARGET_ALIASES.get(target) ?? (DECANTR_ADAPTERS[packAdapter] ? packAdapter : "generic-web");
|
|
1057
|
+
}
|
|
591
1058
|
function resolveBootstrapTarget(target) {
|
|
592
|
-
const normalizedTarget = (target
|
|
593
|
-
const
|
|
594
|
-
const
|
|
595
|
-
const
|
|
1059
|
+
const normalizedTarget = normalizeTarget(target);
|
|
1060
|
+
const adapterIdFromAlias = TARGET_ALIASES.get(normalizedTarget);
|
|
1061
|
+
const adapterTarget = adapterIdFromAlias ? DECANTR_ADAPTERS[adapterIdFromAlias].target : normalizedTarget;
|
|
1062
|
+
const platformType = platformTypeForTarget(adapterTarget);
|
|
1063
|
+
const packAdapter = resolvePackAdapter(adapterTarget, platformType);
|
|
1064
|
+
const adapterId = adapterIdForTarget(adapterTarget, packAdapter);
|
|
1065
|
+
const adapter = DECANTR_ADAPTERS[adapterId];
|
|
596
1066
|
return {
|
|
597
|
-
target:
|
|
1067
|
+
target: adapterTarget,
|
|
598
1068
|
platformType,
|
|
599
1069
|
packAdapter,
|
|
600
1070
|
adapterId,
|
|
601
|
-
bootstrapAdapterId:
|
|
1071
|
+
bootstrapAdapterId: adapter?.capabilities.bootstrap && adapter?.writeProjectFiles ? adapterId : null
|
|
602
1072
|
};
|
|
603
1073
|
}
|
|
604
1074
|
function getBootstrapAdapter(resolution) {
|
|
605
|
-
if (!resolution.bootstrapAdapterId)
|
|
606
|
-
return null;
|
|
607
|
-
}
|
|
1075
|
+
if (!resolution.bootstrapAdapterId) return null;
|
|
608
1076
|
const adapter = DECANTR_ADAPTERS[resolution.bootstrapAdapterId];
|
|
609
1077
|
return adapter?.writeProjectFiles ? adapter : null;
|
|
610
1078
|
}
|
|
@@ -612,9 +1080,7 @@ function detectRoutingMode(projectDir) {
|
|
|
612
1080
|
try {
|
|
613
1081
|
const essence = JSON.parse(readFileSync3(join3(projectDir, "decantr.essence.json"), "utf-8"));
|
|
614
1082
|
const routing = essence.meta?.platform?.routing;
|
|
615
|
-
if (routing === "history" || routing === "pathname")
|
|
616
|
-
return routing;
|
|
617
|
-
}
|
|
1083
|
+
if (routing === "history" || routing === "pathname") return routing;
|
|
618
1084
|
return "hash";
|
|
619
1085
|
} catch {
|
|
620
1086
|
return "hash";
|
|
@@ -1964,6 +2430,9 @@ function detectProject(projectRoot = process.cwd()) {
|
|
|
1964
2430
|
} else if (deps["@angular/core"]) {
|
|
1965
2431
|
result.framework = "angular";
|
|
1966
2432
|
result.version = deps["@angular/core"].replace(/^\^|~/, "");
|
|
2433
|
+
} else if (deps["solid-js"]) {
|
|
2434
|
+
result.framework = "solid";
|
|
2435
|
+
result.version = deps["solid-js"].replace(/^\^|~/, "");
|
|
1967
2436
|
} else if (deps.vue) {
|
|
1968
2437
|
result.framework = "vue";
|
|
1969
2438
|
result.version = deps.vue.replace(/^\^|~/, "");
|
|
@@ -2660,6 +3129,22 @@ function generateCSSVars(tokens) {
|
|
|
2660
3129
|
lines.push("}", "");
|
|
2661
3130
|
return lines.join("\n");
|
|
2662
3131
|
}
|
|
3132
|
+
function generateFigmaTokens(tokens) {
|
|
3133
|
+
const out = {};
|
|
3134
|
+
for (const [key, value] of tokens) {
|
|
3135
|
+
const name = key.replace(/^--/, "").replace(/-/g, ".");
|
|
3136
|
+
const type = /color|bg|surface|text|border|primary|secondary|accent|error|warning|success|info/.test(
|
|
3137
|
+
key
|
|
3138
|
+
) ? "color" : /radius/.test(key) ? "borderRadius" : /shadow/.test(key) ? "shadow" : /gap|space|spacing/.test(key) ? "dimension" : "string";
|
|
3139
|
+
out[name] = {
|
|
3140
|
+
$type: type,
|
|
3141
|
+
$value: value,
|
|
3142
|
+
$description: `Exported from ${key} by Decantr.`
|
|
3143
|
+
};
|
|
3144
|
+
}
|
|
3145
|
+
return `${JSON.stringify(out, null, 2)}
|
|
3146
|
+
`;
|
|
3147
|
+
}
|
|
2663
3148
|
async function cmdExport(target, projectRoot, options = {}) {
|
|
2664
3149
|
const essencePath = join14(projectRoot, "decantr.essence.json");
|
|
2665
3150
|
const tokensPath = join14(projectRoot, "src", "styles", "tokens.css");
|
|
@@ -2710,6 +3195,14 @@ async function cmdExport(target, projectRoot, options = {}) {
|
|
|
2710
3195
|
console.log(` ${DIM3}File:${RESET3} ${out}`);
|
|
2711
3196
|
break;
|
|
2712
3197
|
}
|
|
3198
|
+
case "figma-tokens": {
|
|
3199
|
+
const out = options.output ?? join14(projectRoot, ".decantr", "design", "figma-tokens.json");
|
|
3200
|
+
ensureDir(out);
|
|
3201
|
+
writeFileSync8(out, generateFigmaTokens(tokens), "utf-8");
|
|
3202
|
+
console.log(`${GREEN3}Exported Figma/Tokens Studio tokens:${RESET3}`);
|
|
3203
|
+
console.log(` ${DIM3}File:${RESET3} ${out}`);
|
|
3204
|
+
break;
|
|
3205
|
+
}
|
|
2713
3206
|
}
|
|
2714
3207
|
}
|
|
2715
3208
|
function ensureDir(filePath) {
|
|
@@ -4184,6 +4677,7 @@ function resolveDriftEntries(projectRoot, options) {
|
|
|
4184
4677
|
}
|
|
4185
4678
|
|
|
4186
4679
|
// src/commands/telemetry.ts
|
|
4680
|
+
import { DECANTR_TELEMETRY_EVENT_CATALOG } from "@decantr/telemetry";
|
|
4187
4681
|
var BOLD5 = "\x1B[1m";
|
|
4188
4682
|
var CYAN6 = "\x1B[36m";
|
|
4189
4683
|
var DIM11 = "\x1B[2m";
|
|
@@ -4201,6 +4695,10 @@ async function cmdTelemetry(args, projectRoot = process.cwd()) {
|
|
|
4201
4695
|
printTelemetryStatus(projectRoot, options);
|
|
4202
4696
|
return;
|
|
4203
4697
|
}
|
|
4698
|
+
if (subcommand === "explain") {
|
|
4699
|
+
printTelemetryExplain(projectRoot, options);
|
|
4700
|
+
return;
|
|
4701
|
+
}
|
|
4204
4702
|
if (subcommand === "link") {
|
|
4205
4703
|
await linkTelemetryIdentity(projectRoot, options);
|
|
4206
4704
|
return;
|
|
@@ -4213,11 +4711,13 @@ ${BOLD5}decantr telemetry${RESET11} \u2014 Inspect and link privacy-filtered CLI
|
|
|
4213
4711
|
|
|
4214
4712
|
${BOLD5}Usage:${RESET11}
|
|
4215
4713
|
decantr telemetry status [--json]
|
|
4714
|
+
decantr telemetry explain [--json]
|
|
4216
4715
|
decantr telemetry link [--enable] [--org <slug>] [--label <label>] [--api-key <key>] [--api-url <url>]
|
|
4217
4716
|
|
|
4218
4717
|
${BOLD5}Examples:${RESET11}
|
|
4219
4718
|
decantr init --telemetry
|
|
4220
4719
|
decantr telemetry status
|
|
4720
|
+
decantr telemetry explain
|
|
4221
4721
|
decantr login --api-key=<your-key>
|
|
4222
4722
|
decantr telemetry link --org my-team --label "CI runner"
|
|
4223
4723
|
`);
|
|
@@ -4242,6 +4742,82 @@ ${BOLD5}Decantr telemetry${RESET11}`);
|
|
|
4242
4742
|
console.log(DIM11 + "Run `decantr init --telemetry` or `decantr telemetry link --enable` to opt in." + RESET11);
|
|
4243
4743
|
}
|
|
4244
4744
|
}
|
|
4745
|
+
function printTelemetryExplain(projectRoot, options) {
|
|
4746
|
+
const status = getCliTelemetryIdentityStatus(projectRoot, { create: false });
|
|
4747
|
+
const cliEvents = DECANTR_TELEMETRY_EVENT_CATALOG.filter((entry) => entry.allowedSources.includes("cli")).map((entry) => ({
|
|
4748
|
+
name: entry.name,
|
|
4749
|
+
bucket: entry.bucket,
|
|
4750
|
+
privacy: entry.privacy,
|
|
4751
|
+
publicIngest: entry.publicIngest,
|
|
4752
|
+
notes: entry.privacyNotes
|
|
4753
|
+
}));
|
|
4754
|
+
const report = {
|
|
4755
|
+
source: "cli",
|
|
4756
|
+
enabled: status.enabled,
|
|
4757
|
+
hasProjectConfig: status.hasProjectConfig,
|
|
4758
|
+
identifiers: {
|
|
4759
|
+
installId: status.installId ?? null,
|
|
4760
|
+
projectId: status.projectId ?? null,
|
|
4761
|
+
meaning: "Opaque Decantr-generated ids used only when this project has opted into CLI telemetry."
|
|
4762
|
+
},
|
|
4763
|
+
endpoint: process.env.DECANTR_TELEMETRY_ENDPOINT ?? "https://api.decantr.ai/v1/telemetry/events",
|
|
4764
|
+
events: cliEvents,
|
|
4765
|
+
aggregateFields: [
|
|
4766
|
+
"command name",
|
|
4767
|
+
"success or failure",
|
|
4768
|
+
"duration",
|
|
4769
|
+
"workflow and adoption mode",
|
|
4770
|
+
"project scope",
|
|
4771
|
+
"registry source",
|
|
4772
|
+
"aggregate analyze counts",
|
|
4773
|
+
"Project Health status, score, and finding counts",
|
|
4774
|
+
"CI gate outcome",
|
|
4775
|
+
"Studio start and refresh activity",
|
|
4776
|
+
"remediation prompt request outcome"
|
|
4777
|
+
],
|
|
4778
|
+
neverCollected: [
|
|
4779
|
+
"source code",
|
|
4780
|
+
"prompt text",
|
|
4781
|
+
"local file paths",
|
|
4782
|
+
"repository names",
|
|
4783
|
+
"emails",
|
|
4784
|
+
"secrets",
|
|
4785
|
+
"raw route names",
|
|
4786
|
+
"private package slugs",
|
|
4787
|
+
"health report bodies",
|
|
4788
|
+
"finding evidence"
|
|
4789
|
+
],
|
|
4790
|
+
controls: {
|
|
4791
|
+
optIn: "Run decantr init --telemetry, decantr new --telemetry, or decantr telemetry link --enable.",
|
|
4792
|
+
optOut: 'Set "telemetry": false in .decantr/project.json.',
|
|
4793
|
+
link: "Run decantr telemetry link after login to attach opaque ids to your Decantr account/org."
|
|
4794
|
+
}
|
|
4795
|
+
};
|
|
4796
|
+
if (options.json) {
|
|
4797
|
+
console.log(JSON.stringify(report, null, 2));
|
|
4798
|
+
return;
|
|
4799
|
+
}
|
|
4800
|
+
console.log(`
|
|
4801
|
+
${BOLD5}Decantr telemetry explanation${RESET11}`);
|
|
4802
|
+
console.log(` Source: cli`);
|
|
4803
|
+
console.log(` Enabled: ${status.enabled ? `${GREEN11}yes${RESET11}` : "no"}`);
|
|
4804
|
+
console.log(` Install ID: ${status.installId ?? `${DIM11}not created yet${RESET11}`}`);
|
|
4805
|
+
console.log(` Project ID: ${status.projectId ?? `${DIM11}not created yet${RESET11}`}`);
|
|
4806
|
+
console.log(` Events: ${cliEvents.length} CLI event types in the public catalog`);
|
|
4807
|
+
console.log(`
|
|
4808
|
+
${BOLD5}Aggregate fields${RESET11}`);
|
|
4809
|
+
for (const field of report.aggregateFields) {
|
|
4810
|
+
console.log(` - ${field}`);
|
|
4811
|
+
}
|
|
4812
|
+
console.log(`
|
|
4813
|
+
${BOLD5}Never collected${RESET11}`);
|
|
4814
|
+
for (const field of report.neverCollected) {
|
|
4815
|
+
console.log(` - ${field}`);
|
|
4816
|
+
}
|
|
4817
|
+
console.log(`
|
|
4818
|
+
${DIM11}${report.controls.optOut}${RESET11}`);
|
|
4819
|
+
console.log(`${DIM11}${report.controls.link}${RESET11}`);
|
|
4820
|
+
}
|
|
4245
4821
|
async function linkTelemetryIdentity(projectRoot, options) {
|
|
4246
4822
|
if (options.enable && !isOptedIn(projectRoot)) {
|
|
4247
4823
|
optIn(projectRoot);
|
|
@@ -4549,6 +5125,7 @@ async function runInteractivePrompts(detected, archetypes, blueprints, themes, w
|
|
|
4549
5125
|
{ value: "svelte", label: "svelte", description: "Svelte / SvelteKit" },
|
|
4550
5126
|
{ value: "astro", label: "astro", description: "Astro" },
|
|
4551
5127
|
{ value: "angular", label: "angular", description: "Angular" },
|
|
5128
|
+
{ value: "solid", label: "solid", description: "SolidJS" },
|
|
4552
5129
|
{ value: "html", label: "html", description: "Plain HTML/CSS/JS" }
|
|
4553
5130
|
];
|
|
4554
5131
|
let defaultFrameworkIdx = frameworkOptions.findIndex(
|
|
@@ -7229,10 +7806,14 @@ ${BOLD7}Usage:${RESET14}
|
|
|
7229
7806
|
decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>]
|
|
7230
7807
|
decantr registry audit-project [--namespace <namespace>] [--json] [--essence <path>] [--dist <path>] [--sources <dir>]
|
|
7231
7808
|
decantr health [--format text|json|markdown] [--ci] [--fail-on error|warn|none]
|
|
7232
|
-
decantr health
|
|
7809
|
+
decantr health --evidence [--browser] [--design-tokens <path>]
|
|
7810
|
+
decantr health init-ci [--force] [--project <path>] [--workspace] [--fail-on <error|warn|none>] [--cli-version <version|latest>]
|
|
7811
|
+
decantr workspace list [--json]
|
|
7812
|
+
decantr workspace health [--json] [--changed --since origin/main]
|
|
7233
7813
|
decantr content-health [--json] [--markdown] [--ci]
|
|
7234
|
-
decantr studio [--port 4319] [--host 127.0.0.1] [--report decantr-health.json]
|
|
7814
|
+
decantr studio [--port 4319] [--host 127.0.0.1] [--report decantr-health.json] [--workspace]
|
|
7235
7815
|
decantr telemetry status [--json]
|
|
7816
|
+
decantr telemetry explain [--json]
|
|
7236
7817
|
decantr telemetry link [--enable] [--org <slug>]
|
|
7237
7818
|
decantr rules preview [--project=<path>]
|
|
7238
7819
|
decantr rules apply [--project=<path>]
|
|
@@ -7250,7 +7831,7 @@ ${BOLD7}Init Options:${RESET14}
|
|
|
7250
7831
|
--theme Theme ID
|
|
7251
7832
|
--mode Color mode: dark | light | auto
|
|
7252
7833
|
--shape Border shape: pill | rounded | sharp
|
|
7253
|
-
--target Framework: react | vue | svelte | angular | nextjs | nuxt | astro | html
|
|
7834
|
+
--target Framework: react | vue | svelte | angular | solid | nextjs | nuxt | astro | html
|
|
7254
7835
|
--guard Guard mode: creative | guided | strict
|
|
7255
7836
|
--density Spacing: compact | comfortable | spacious
|
|
7256
7837
|
--shell Default shell layout
|
|
@@ -7273,6 +7854,7 @@ ${BOLD7}Commands:${RESET14}
|
|
|
7273
7854
|
${cyan3("init")} Attach Decantr contract/context files to an existing project or empty workspace
|
|
7274
7855
|
${cyan3("status")} Show project status, DNA axioms, and blueprint info
|
|
7275
7856
|
${cyan3("health")} Generate a local Project Health report [--json] [--markdown] [--ci]; use health init-ci to install a GitHub Actions gate
|
|
7857
|
+
${cyan3("workspace")} Discover and aggregate health across Decantr projects in a monorepo
|
|
7276
7858
|
${cyan3("content-health")} Generate a local registry content health report [--json] [--markdown] [--ci]
|
|
7277
7859
|
${cyan3("studio")} Open a local Project Health dashboard backed by the same report
|
|
7278
7860
|
${cyan3("sync")} Sync registry content from API
|
|
@@ -7316,10 +7898,14 @@ ${BOLD7}Examples:${RESET14}
|
|
|
7316
7898
|
decantr health init-ci
|
|
7317
7899
|
decantr health init-ci --project apps/web
|
|
7318
7900
|
decantr health --ci --fail-on error
|
|
7901
|
+
decantr health --evidence --output .decantr/evidence/latest.json
|
|
7902
|
+
decantr workspace list
|
|
7903
|
+
decantr workspace health --changed --since origin/main
|
|
7319
7904
|
decantr content-health --ci --fail-on error
|
|
7320
7905
|
decantr studio
|
|
7321
7906
|
decantr studio --report decantr-health.json
|
|
7322
7907
|
decantr telemetry status
|
|
7908
|
+
decantr telemetry explain
|
|
7323
7909
|
decantr telemetry link --enable --org my-team
|
|
7324
7910
|
decantr audit
|
|
7325
7911
|
decantr audit src/pages/HomePage.tsx
|
|
@@ -7348,7 +7934,7 @@ ${BOLD7}Workflow Model:${RESET14}
|
|
|
7348
7934
|
${cyan3("Hybrid composition")} decantr add/remove, decantr theme switch, decantr registry, decantr upgrade
|
|
7349
7935
|
|
|
7350
7936
|
${BOLD7}Bootstrap adapters:${RESET14}
|
|
7351
|
-
Runnable starter adapters: ${cyan3("react-vite")}, ${cyan3("next-app")}
|
|
7937
|
+
Runnable starter adapters: ${cyan3("react-vite")}, ${cyan3("next-app")}, ${cyan3("vanilla-vite")}, ${cyan3("vue-vite")}, ${cyan3("sveltekit")}, ${cyan3("angular")}, ${cyan3("solid-vite")}
|
|
7352
7938
|
Unsupported targets resolve through ${cyan3("generic-web")} contract-only mode until their starter adapters land.
|
|
7353
7939
|
`);
|
|
7354
7940
|
}
|
|
@@ -7383,7 +7969,8 @@ ${BOLD7}Usage:${RESET14}
|
|
|
7383
7969
|
decantr health --markdown
|
|
7384
7970
|
decantr health --ci [--fail-on error|warn|none]
|
|
7385
7971
|
decantr health --prompt <finding-id>
|
|
7386
|
-
decantr health
|
|
7972
|
+
decantr health --evidence [--browser] [--design-tokens <path>]
|
|
7973
|
+
decantr health init-ci [--force] [--project <path>] [--workspace] [--fail-on error|warn|none] [--cli-version <version|latest>]
|
|
7387
7974
|
|
|
7388
7975
|
${BOLD7}Options:${RESET14}
|
|
7389
7976
|
--format Output format: text, json, or markdown
|
|
@@ -7393,6 +7980,9 @@ ${BOLD7}Options:${RESET14}
|
|
|
7393
7980
|
--ci Enable CI exit-code behavior
|
|
7394
7981
|
--fail-on CI threshold: error, warn, or none
|
|
7395
7982
|
--prompt Print an AI-ready remediation prompt for a finding
|
|
7983
|
+
--evidence Emit a local Evidence Bundle JSON artifact
|
|
7984
|
+
--browser Include optional rendered-browser setup/evidence checks
|
|
7985
|
+
--design-tokens Compare against a Figma/Tokens Studio JSON export
|
|
7396
7986
|
|
|
7397
7987
|
${BOLD7}Examples:${RESET14}
|
|
7398
7988
|
decantr health
|
|
@@ -7400,7 +7990,25 @@ ${BOLD7}Examples:${RESET14}
|
|
|
7400
7990
|
decantr health --markdown --output decantr-health.md
|
|
7401
7991
|
decantr health --ci --fail-on error
|
|
7402
7992
|
decantr health --prompt audit-essence-missing
|
|
7993
|
+
decantr health --evidence --output .decantr/evidence/latest.json
|
|
7403
7994
|
decantr health init-ci --project apps/web
|
|
7995
|
+
decantr health init-ci --workspace
|
|
7996
|
+
`);
|
|
7997
|
+
}
|
|
7998
|
+
function cmdWorkspaceHelp() {
|
|
7999
|
+
console.log(`
|
|
8000
|
+
${BOLD7}decantr workspace${RESET14} \u2014 Inspect Decantr projects across a monorepo
|
|
8001
|
+
|
|
8002
|
+
${BOLD7}Usage:${RESET14}
|
|
8003
|
+
decantr workspace list [--json]
|
|
8004
|
+
decantr workspace health [--json|--markdown] [--output <file>]
|
|
8005
|
+
decantr workspace health --changed --since origin/main
|
|
8006
|
+
|
|
8007
|
+
${BOLD7}Examples:${RESET14}
|
|
8008
|
+
decantr workspace list
|
|
8009
|
+
decantr workspace health
|
|
8010
|
+
decantr workspace health --json --output .decantr/workspace-health.json
|
|
8011
|
+
decantr workspace health --changed --since origin/main
|
|
7404
8012
|
`);
|
|
7405
8013
|
}
|
|
7406
8014
|
function cmdContentHealthHelp() {
|
|
@@ -7441,6 +8049,7 @@ ${BOLD7}Options:${RESET14}
|
|
|
7441
8049
|
--port Local port to bind; defaults to 4319
|
|
7442
8050
|
--host Local host to bind; defaults to 127.0.0.1
|
|
7443
8051
|
--report Serve a read-only Project Health JSON artifact instead of scanning the current project
|
|
8052
|
+
--workspace Serve a monorepo workspace health dashboard
|
|
7444
8053
|
|
|
7445
8054
|
${BOLD7}Endpoints:${RESET14}
|
|
7446
8055
|
GET /
|
|
@@ -7453,6 +8062,7 @@ ${BOLD7}Examples:${RESET14}
|
|
|
7453
8062
|
decantr studio --host 127.0.0.1 --port 4319
|
|
7454
8063
|
decantr health --json --output decantr-health.json
|
|
7455
8064
|
decantr studio --report decantr-health.json
|
|
8065
|
+
decantr studio --workspace
|
|
7456
8066
|
`);
|
|
7457
8067
|
}
|
|
7458
8068
|
async function main() {
|
|
@@ -7568,7 +8178,7 @@ async function main() {
|
|
|
7568
8178
|
break;
|
|
7569
8179
|
}
|
|
7570
8180
|
case "upgrade": {
|
|
7571
|
-
const { cmdUpgrade } = await import("./upgrade-
|
|
8181
|
+
const { cmdUpgrade } = await import("./upgrade-XTTGHFG7.js");
|
|
7572
8182
|
const applyFlag = args.includes("--apply");
|
|
7573
8183
|
await cmdUpgrade(process.cwd(), { apply: applyFlag });
|
|
7574
8184
|
break;
|
|
@@ -7592,7 +8202,7 @@ async function main() {
|
|
|
7592
8202
|
cmdHealthHelp();
|
|
7593
8203
|
break;
|
|
7594
8204
|
}
|
|
7595
|
-
const { cmdHealth, parseHealthArgs } = await import("./health-
|
|
8205
|
+
const { cmdHealth, parseHealthArgs } = await import("./health-ZXOPGNBZ.js");
|
|
7596
8206
|
await cmdHealth(process.cwd(), parseHealthArgs(args));
|
|
7597
8207
|
} catch (e) {
|
|
7598
8208
|
console.error(error3(e.message));
|
|
@@ -7620,7 +8230,7 @@ async function main() {
|
|
|
7620
8230
|
cmdStudioHelp();
|
|
7621
8231
|
break;
|
|
7622
8232
|
}
|
|
7623
|
-
const { cmdStudio, parseStudioArgs } = await import("./studio-
|
|
8233
|
+
const { cmdStudio, parseStudioArgs } = await import("./studio-LHQXHBE7.js");
|
|
7624
8234
|
await cmdStudio(process.cwd(), parseStudioArgs(args));
|
|
7625
8235
|
} catch (e) {
|
|
7626
8236
|
console.error(error3(e.message));
|
|
@@ -7628,6 +8238,20 @@ async function main() {
|
|
|
7628
8238
|
}
|
|
7629
8239
|
break;
|
|
7630
8240
|
}
|
|
8241
|
+
case "workspace": {
|
|
8242
|
+
try {
|
|
8243
|
+
if (isCommandHelpRequest(args)) {
|
|
8244
|
+
cmdWorkspaceHelp();
|
|
8245
|
+
break;
|
|
8246
|
+
}
|
|
8247
|
+
const { cmdWorkspace } = await import("./workspace-MOLAGT2B.js");
|
|
8248
|
+
await cmdWorkspace(process.cwd(), args);
|
|
8249
|
+
} catch (e) {
|
|
8250
|
+
console.error(error3(e.message));
|
|
8251
|
+
process.exitCode = 1;
|
|
8252
|
+
}
|
|
8253
|
+
break;
|
|
8254
|
+
}
|
|
7631
8255
|
case "migrate": {
|
|
7632
8256
|
await cmdMigrate(process.cwd(), args.slice(1));
|
|
7633
8257
|
break;
|
|
@@ -8114,7 +8738,7 @@ async function main() {
|
|
|
8114
8738
|
exportOutput = args[i].split("=")[1];
|
|
8115
8739
|
}
|
|
8116
8740
|
}
|
|
8117
|
-
const validTargets = ["shadcn", "tailwind", "css-vars"];
|
|
8741
|
+
const validTargets = ["shadcn", "tailwind", "css-vars", "figma-tokens"];
|
|
8118
8742
|
if (!exportTarget || !validTargets.includes(exportTarget)) {
|
|
8119
8743
|
console.error(error3(`Usage: decantr export --to <${validTargets.join("|")}>`));
|
|
8120
8744
|
process.exitCode = 1;
|