@decantr/cli 2.3.1 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -4
- package/dist/bin.js +2 -2
- package/dist/{chunk-2JWVKBNB.js → chunk-6BRD6DTB.js} +915 -327
- package/dist/chunk-AUQXYJ7T.js +316 -0
- package/dist/{chunk-3H3HWDJA.js → chunk-OD46PCR6.js} +354 -17
- package/dist/{chunk-WDA4SHIQ.js → chunk-P4NUDLWB.js} +109 -9
- 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-HSPWYROM.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-P4NUDLWB.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
|
|
574
929
|
},
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
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
|
|
579
986
|
},
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
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
|
|
1005
|
+
},
|
|
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
|
|
1024
|
+
},
|
|
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) {
|
|
@@ -4632,6 +5125,7 @@ async function runInteractivePrompts(detected, archetypes, blueprints, themes, w
|
|
|
4632
5125
|
{ value: "svelte", label: "svelte", description: "Svelte / SvelteKit" },
|
|
4633
5126
|
{ value: "astro", label: "astro", description: "Astro" },
|
|
4634
5127
|
{ value: "angular", label: "angular", description: "Angular" },
|
|
5128
|
+
{ value: "solid", label: "solid", description: "SolidJS" },
|
|
4635
5129
|
{ value: "html", label: "html", description: "Plain HTML/CSS/JS" }
|
|
4636
5130
|
];
|
|
4637
5131
|
let defaultFrameworkIdx = frameworkOptions.findIndex(
|
|
@@ -5130,6 +5624,7 @@ function extractPatternName(item) {
|
|
|
5130
5624
|
function generateGreenfieldPrompt(ctx) {
|
|
5131
5625
|
const lines = [];
|
|
5132
5626
|
const usesDecantrCss = ctx.adoptionMode === "decantr-css" || !ctx.adoptionMode;
|
|
5627
|
+
const hasCompiledPacks = ctx.hasCompiledPacks ?? true;
|
|
5133
5628
|
lines.push("Build this greenfield application using the Decantr design system.");
|
|
5134
5629
|
lines.push("");
|
|
5135
5630
|
if (ctx.blueprint) lines.push(`Blueprint: ${ctx.blueprint}`);
|
|
@@ -5146,44 +5641,66 @@ function generateGreenfieldPrompt(ctx) {
|
|
|
5146
5641
|
"This workspace is a new Decantr scaffold. Use the contract to create or extend the runtime deliberately, not to reverse-engineer a hidden starter."
|
|
5147
5642
|
);
|
|
5148
5643
|
lines.push("");
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5644
|
+
if (hasCompiledPacks) {
|
|
5645
|
+
lines.push("Treat the compiled execution-pack files as the primary source of truth.");
|
|
5646
|
+
lines.push(
|
|
5647
|
+
"Use narrative docs only as secondary explanation when the compiled packs are not enough."
|
|
5648
|
+
);
|
|
5649
|
+
} else {
|
|
5650
|
+
lines.push(
|
|
5651
|
+
"Compiled execution-pack files are not present in this scaffold. Treat narrative Decantr context as the temporary source of truth and run `decantr refresh` after fixing the reported validation issue."
|
|
5652
|
+
);
|
|
5653
|
+
}
|
|
5153
5654
|
lines.push(
|
|
5154
5655
|
"Use only files present in this workspace as the source of truth. If local scaffold files disagree, stop and report the mismatch instead of relying on external Decantr assumptions or prior examples."
|
|
5155
5656
|
);
|
|
5156
5657
|
lines.push("");
|
|
5157
5658
|
lines.push("Read in this order:");
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5659
|
+
if (hasCompiledPacks) {
|
|
5660
|
+
lines.push(
|
|
5661
|
+
"1. .decantr/context/scaffold-pack.md \u2014 the canonical compiled contract. Contains route plan, shell layouts, navigation, Required Theme Decorators, and project-wide execution rules."
|
|
5662
|
+
);
|
|
5663
|
+
lines.push(
|
|
5664
|
+
"2. Before section work, read the matching .decantr/context/section-*-pack.md first, then .decantr/context/section-*.md only for extra slot/layout detail."
|
|
5665
|
+
);
|
|
5666
|
+
lines.push(
|
|
5667
|
+
"3. Before route work, read the matching .decantr/context/page-*-pack.md file. Its pattern layout and interaction checklists are contract."
|
|
5668
|
+
);
|
|
5669
|
+
lines.push(
|
|
5670
|
+
"4. .decantr/context/scaffold.md for broader topology, route map, and voice guidance after the compact packs are understood."
|
|
5671
|
+
);
|
|
5672
|
+
lines.push(
|
|
5673
|
+
"5. DECANTR.md as a lookup reference for atoms, treatments, decorators, interaction implementations, and guard rules. Do not let narrative docs override compiled packs."
|
|
5674
|
+
);
|
|
5675
|
+
lines.push("");
|
|
5676
|
+
lines.push("\u2550\u2550\u2550 INTERACTIONS ARE CONTRACT, NOT GUIDANCE \u2550\u2550\u2550");
|
|
5677
|
+
lines.push("");
|
|
5678
|
+
lines.push(
|
|
5679
|
+
'Each page pack lists "Interactions (MUST implement each)" per pattern. Implement the actual behavior, not visible text saying it exists. Use DECANTR.md only to look up the canonical implementation shape when needed.'
|
|
5680
|
+
);
|
|
5681
|
+
lines.push(
|
|
5682
|
+
"Examples: pointer handlers for dragging/panning, onWheel for zoom, onKeyDown + tabIndex for keyboard navigation, IntersectionObserver for scroll reveal, state updates for real-time indicators, and d-* motion classes where the contract calls for animation."
|
|
5683
|
+
);
|
|
5684
|
+
lines.push("");
|
|
5685
|
+
lines.push(
|
|
5686
|
+
"`decantr check --strict` fails when a declared interaction has no matching implementation."
|
|
5687
|
+
);
|
|
5688
|
+
lines.push("");
|
|
5689
|
+
} else {
|
|
5690
|
+
lines.push(
|
|
5691
|
+
"1. .decantr/context/scaffold.md for topology, route map, voice, and section inventory."
|
|
5692
|
+
);
|
|
5693
|
+
lines.push(
|
|
5694
|
+
"2. The matching .decantr/context/section-*.md file before implementing each section."
|
|
5695
|
+
);
|
|
5696
|
+
lines.push(
|
|
5697
|
+
"3. DECANTR.md for atoms, treatments, decorators, interaction shapes, and guard rules."
|
|
5698
|
+
);
|
|
5699
|
+
lines.push(
|
|
5700
|
+
"4. Run `decantr refresh` and switch to compiled pack files once validation passes."
|
|
5701
|
+
);
|
|
5702
|
+
lines.push("");
|
|
5703
|
+
}
|
|
5187
5704
|
lines.push("\u2550\u2550\u2550 STYLING ADOPTION \u2550\u2550\u2550");
|
|
5188
5705
|
lines.push("");
|
|
5189
5706
|
if (ctx.adoptionMode === "contract-only") {
|
|
@@ -5270,12 +5787,18 @@ function generateGreenfieldPrompt(ctx) {
|
|
|
5270
5787
|
lines.push("");
|
|
5271
5788
|
lines.push("\u2550\u2550\u2550 THEME DECORATOR CONTRACT \u2014 APPLY OR THE THEME DOES NOT LAND \u2550\u2550\u2550");
|
|
5272
5789
|
lines.push("");
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5790
|
+
if (hasCompiledPacks) {
|
|
5791
|
+
lines.push(
|
|
5792
|
+
'Each theme ships namespaced decorator classes (`clean-card`, `lum-glass`, `carbon-canvas`, `paper-card`, etc.). Apply the scaffold-pack.md "Required Theme Decorators" as additive classes alongside d-* treatments so the theme lands as more than token colors.'
|
|
5793
|
+
);
|
|
5794
|
+
lines.push(
|
|
5795
|
+
"Section packs may point back to the scaffold-pack table; scaffold-pack.md is authoritative."
|
|
5796
|
+
);
|
|
5797
|
+
} else {
|
|
5798
|
+
lines.push(
|
|
5799
|
+
"Each theme ships namespaced decorator classes (`clean-card`, `lum-glass`, `carbon-canvas`, `paper-card`, etc.). Use DECANTR.md and section context to apply the theme, then rerun `decantr refresh` to restore the authoritative decorator table."
|
|
5800
|
+
);
|
|
5801
|
+
}
|
|
5279
5802
|
lines.push("");
|
|
5280
5803
|
lines.push("\u2550\u2550\u2550 HARD RULES (NON-NEGOTIABLE) \u2550\u2550\u2550");
|
|
5281
5804
|
lines.push("");
|
|
@@ -5296,7 +5819,7 @@ function generateGreenfieldPrompt(ctx) {
|
|
|
5296
5819
|
"- Use lucide-react for ALL iconography (already in package.json). Pick semantic icons (Bot, Activity, Database, Search) over generic ones. Do NOT inline SVGs for icons that have Lucide equivalents."
|
|
5297
5820
|
);
|
|
5298
5821
|
lines.push(
|
|
5299
|
-
"- Section Directives in section packs are execution rules for layout proportions, treatment stacks, copy conventions, and pattern fitness."
|
|
5822
|
+
hasCompiledPacks ? "- Section Directives in section packs are execution rules for layout proportions, treatment stacks, copy conventions, and pattern fitness." : "- Section context files are execution rules for layout proportions, treatment stacks, copy conventions, and pattern fitness until compiled packs are restored."
|
|
5300
5823
|
);
|
|
5301
5824
|
lines.push(
|
|
5302
5825
|
"- Filter chip rows / tab strips use `d-step-chip[data-step-state]`, not bare `d-interactive` buttons."
|
|
@@ -5310,9 +5833,11 @@ function generateGreenfieldPrompt(ctx) {
|
|
|
5310
5833
|
lines.push("");
|
|
5311
5834
|
lines.push("\u2550\u2550\u2550 IMPLEMENTATION RULES \u2550\u2550\u2550");
|
|
5312
5835
|
lines.push(
|
|
5313
|
-
"- Do not invent routes, sections, shells, themes, or features beyond the compiled packs."
|
|
5836
|
+
hasCompiledPacks ? "- Do not invent routes, sections, shells, themes, or features beyond the compiled packs." : "- Do not invent routes, sections, shells, themes, or features beyond decantr.essence.json and generated narrative context."
|
|
5837
|
+
);
|
|
5838
|
+
lines.push(
|
|
5839
|
+
hasCompiledPacks ? "- Prefer scaffold-pack, section-pack, and page-pack guidance over narrative docs." : "- Prefer decantr.essence.json and generated section context over assumptions from prior examples."
|
|
5314
5840
|
);
|
|
5315
|
-
lines.push("- Prefer scaffold-pack, section-pack, and page-pack guidance over narrative docs.");
|
|
5316
5841
|
lines.push(
|
|
5317
5842
|
"- Start with the shell layouts and route structure first, then build section pages route by route."
|
|
5318
5843
|
);
|
|
@@ -5356,7 +5881,9 @@ function generateGreenfieldPrompt(ctx) {
|
|
|
5356
5881
|
lines.push("");
|
|
5357
5882
|
lines.push("\u2550\u2550\u2550 EXECUTION FLOW \u2550\u2550\u2550");
|
|
5358
5883
|
lines.push("- Build the shell and shared layout first.");
|
|
5359
|
-
lines.push(
|
|
5884
|
+
lines.push(
|
|
5885
|
+
hasCompiledPacks ? "- Then implement each section's pages using the matching section and page packs." : "- Then implement each section's pages using decantr.essence.json and the matching section context."
|
|
5886
|
+
);
|
|
5360
5887
|
lines.push(
|
|
5361
5888
|
"- After implementation, run `decantr check` (primary gate) and `decantr audit` (supplementary diagnostics)."
|
|
5362
5889
|
);
|
|
@@ -6859,19 +7386,34 @@ ${YELLOW9}You're offline. Scaffolding Decantr default.${RESET14}`);
|
|
|
6859
7386
|
)
|
|
6860
7387
|
);
|
|
6861
7388
|
}
|
|
7389
|
+
const hasCompiledPacks = existsSync26(join27(projectRoot, ".decantr", "context", "scaffold-pack.md"));
|
|
6862
7390
|
console.log("");
|
|
6863
7391
|
console.log(" Next steps:");
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
7392
|
+
if (hasCompiledPacks) {
|
|
7393
|
+
console.log(
|
|
7394
|
+
" 1. Read .decantr/context/scaffold-pack.md first as the primary compiled contract"
|
|
7395
|
+
);
|
|
7396
|
+
console.log(
|
|
7397
|
+
" 2. Read .decantr/context/scaffold.md for broader topology, route map, and voice guidance"
|
|
7398
|
+
);
|
|
7399
|
+
console.log(" 3. Read the matching section and page packs before implementing each route");
|
|
7400
|
+
console.log(
|
|
7401
|
+
" 4. Use DECANTR.md as a lookup reference for atoms, treatments, and guard rules"
|
|
7402
|
+
);
|
|
7403
|
+
console.log(" 5. Build the shell and route structure first, then implement the pages");
|
|
7404
|
+
console.log(" 6. Run decantr check and decantr audit after implementation");
|
|
7405
|
+
console.log(" 7. Explore more at decantr.ai/registry");
|
|
7406
|
+
} else {
|
|
7407
|
+
console.log(" 1. Fix the validation issue reported above");
|
|
7408
|
+
console.log(" 2. Run decantr refresh to restore compiled execution packs");
|
|
7409
|
+
console.log(
|
|
7410
|
+
" 3. Until packs exist, read .decantr/context/scaffold.md and section context files"
|
|
7411
|
+
);
|
|
7412
|
+
console.log(
|
|
7413
|
+
" 4. Use DECANTR.md as a lookup reference for atoms, treatments, and guard rules"
|
|
7414
|
+
);
|
|
7415
|
+
console.log(" 5. Run decantr check and decantr audit after implementation");
|
|
7416
|
+
}
|
|
6875
7417
|
console.log("");
|
|
6876
7418
|
console.log(" Commands:");
|
|
6877
7419
|
console.log(` ${cyan3("decantr status")} Project health`);
|
|
@@ -6922,7 +7464,8 @@ Validation warnings: ${validation.errors.join(", ")}`));
|
|
|
6922
7464
|
pages: promptPages,
|
|
6923
7465
|
personality: options.personality,
|
|
6924
7466
|
features: options.features,
|
|
6925
|
-
guard: options.guard
|
|
7467
|
+
guard: options.guard,
|
|
7468
|
+
hasCompiledPacks
|
|
6926
7469
|
};
|
|
6927
7470
|
const curatedPrompt = generateCuratedPrompt(promptCtx);
|
|
6928
7471
|
console.log("");
|
|
@@ -7312,9 +7855,12 @@ ${BOLD7}Usage:${RESET14}
|
|
|
7312
7855
|
decantr registry critique-file <file> [--namespace <namespace>] [--json] [--essence <path>] [--treatments <path>]
|
|
7313
7856
|
decantr registry audit-project [--namespace <namespace>] [--json] [--essence <path>] [--dist <path>] [--sources <dir>]
|
|
7314
7857
|
decantr health [--format text|json|markdown] [--ci] [--fail-on error|warn|none]
|
|
7315
|
-
decantr health
|
|
7858
|
+
decantr health --evidence [--browser] [--design-tokens <path>]
|
|
7859
|
+
decantr health init-ci [--force] [--project <path>] [--workspace] [--fail-on <error|warn|none>] [--cli-version <version|latest>]
|
|
7860
|
+
decantr workspace list [--json]
|
|
7861
|
+
decantr workspace health [--json] [--changed --since origin/main]
|
|
7316
7862
|
decantr content-health [--json] [--markdown] [--ci]
|
|
7317
|
-
decantr studio [--port 4319] [--host 127.0.0.1] [--report decantr-health.json]
|
|
7863
|
+
decantr studio [--port 4319] [--host 127.0.0.1] [--report decantr-health.json] [--workspace]
|
|
7318
7864
|
decantr telemetry status [--json]
|
|
7319
7865
|
decantr telemetry explain [--json]
|
|
7320
7866
|
decantr telemetry link [--enable] [--org <slug>]
|
|
@@ -7334,7 +7880,7 @@ ${BOLD7}Init Options:${RESET14}
|
|
|
7334
7880
|
--theme Theme ID
|
|
7335
7881
|
--mode Color mode: dark | light | auto
|
|
7336
7882
|
--shape Border shape: pill | rounded | sharp
|
|
7337
|
-
--target Framework: react | vue | svelte | angular | nextjs | nuxt | astro | html
|
|
7883
|
+
--target Framework: react | vue | svelte | angular | solid | nextjs | nuxt | astro | html
|
|
7338
7884
|
--guard Guard mode: creative | guided | strict
|
|
7339
7885
|
--density Spacing: compact | comfortable | spacious
|
|
7340
7886
|
--shell Default shell layout
|
|
@@ -7357,6 +7903,7 @@ ${BOLD7}Commands:${RESET14}
|
|
|
7357
7903
|
${cyan3("init")} Attach Decantr contract/context files to an existing project or empty workspace
|
|
7358
7904
|
${cyan3("status")} Show project status, DNA axioms, and blueprint info
|
|
7359
7905
|
${cyan3("health")} Generate a local Project Health report [--json] [--markdown] [--ci]; use health init-ci to install a GitHub Actions gate
|
|
7906
|
+
${cyan3("workspace")} Discover and aggregate health across Decantr projects in a monorepo
|
|
7360
7907
|
${cyan3("content-health")} Generate a local registry content health report [--json] [--markdown] [--ci]
|
|
7361
7908
|
${cyan3("studio")} Open a local Project Health dashboard backed by the same report
|
|
7362
7909
|
${cyan3("sync")} Sync registry content from API
|
|
@@ -7400,6 +7947,9 @@ ${BOLD7}Examples:${RESET14}
|
|
|
7400
7947
|
decantr health init-ci
|
|
7401
7948
|
decantr health init-ci --project apps/web
|
|
7402
7949
|
decantr health --ci --fail-on error
|
|
7950
|
+
decantr health --evidence --output .decantr/evidence/latest.json
|
|
7951
|
+
decantr workspace list
|
|
7952
|
+
decantr workspace health --changed --since origin/main
|
|
7403
7953
|
decantr content-health --ci --fail-on error
|
|
7404
7954
|
decantr studio
|
|
7405
7955
|
decantr studio --report decantr-health.json
|
|
@@ -7433,7 +7983,7 @@ ${BOLD7}Workflow Model:${RESET14}
|
|
|
7433
7983
|
${cyan3("Hybrid composition")} decantr add/remove, decantr theme switch, decantr registry, decantr upgrade
|
|
7434
7984
|
|
|
7435
7985
|
${BOLD7}Bootstrap adapters:${RESET14}
|
|
7436
|
-
Runnable starter adapters: ${cyan3("react-vite")}, ${cyan3("next-app")}
|
|
7986
|
+
Runnable starter adapters: ${cyan3("react-vite")}, ${cyan3("next-app")}, ${cyan3("vanilla-vite")}, ${cyan3("vue-vite")}, ${cyan3("sveltekit")}, ${cyan3("angular")}, ${cyan3("solid-vite")}
|
|
7437
7987
|
Unsupported targets resolve through ${cyan3("generic-web")} contract-only mode until their starter adapters land.
|
|
7438
7988
|
`);
|
|
7439
7989
|
}
|
|
@@ -7468,7 +8018,8 @@ ${BOLD7}Usage:${RESET14}
|
|
|
7468
8018
|
decantr health --markdown
|
|
7469
8019
|
decantr health --ci [--fail-on error|warn|none]
|
|
7470
8020
|
decantr health --prompt <finding-id>
|
|
7471
|
-
decantr health
|
|
8021
|
+
decantr health --evidence [--browser] [--design-tokens <path>]
|
|
8022
|
+
decantr health init-ci [--force] [--project <path>] [--workspace] [--fail-on error|warn|none] [--cli-version <version|latest>]
|
|
7472
8023
|
|
|
7473
8024
|
${BOLD7}Options:${RESET14}
|
|
7474
8025
|
--format Output format: text, json, or markdown
|
|
@@ -7478,6 +8029,9 @@ ${BOLD7}Options:${RESET14}
|
|
|
7478
8029
|
--ci Enable CI exit-code behavior
|
|
7479
8030
|
--fail-on CI threshold: error, warn, or none
|
|
7480
8031
|
--prompt Print an AI-ready remediation prompt for a finding
|
|
8032
|
+
--evidence Emit a local Evidence Bundle JSON artifact
|
|
8033
|
+
--browser Include optional rendered-browser setup/evidence checks
|
|
8034
|
+
--design-tokens Compare against a Figma/Tokens Studio JSON export
|
|
7481
8035
|
|
|
7482
8036
|
${BOLD7}Examples:${RESET14}
|
|
7483
8037
|
decantr health
|
|
@@ -7485,7 +8039,25 @@ ${BOLD7}Examples:${RESET14}
|
|
|
7485
8039
|
decantr health --markdown --output decantr-health.md
|
|
7486
8040
|
decantr health --ci --fail-on error
|
|
7487
8041
|
decantr health --prompt audit-essence-missing
|
|
8042
|
+
decantr health --evidence --output .decantr/evidence/latest.json
|
|
7488
8043
|
decantr health init-ci --project apps/web
|
|
8044
|
+
decantr health init-ci --workspace
|
|
8045
|
+
`);
|
|
8046
|
+
}
|
|
8047
|
+
function cmdWorkspaceHelp() {
|
|
8048
|
+
console.log(`
|
|
8049
|
+
${BOLD7}decantr workspace${RESET14} \u2014 Inspect Decantr projects across a monorepo
|
|
8050
|
+
|
|
8051
|
+
${BOLD7}Usage:${RESET14}
|
|
8052
|
+
decantr workspace list [--json]
|
|
8053
|
+
decantr workspace health [--json|--markdown] [--output <file>]
|
|
8054
|
+
decantr workspace health --changed --since origin/main
|
|
8055
|
+
|
|
8056
|
+
${BOLD7}Examples:${RESET14}
|
|
8057
|
+
decantr workspace list
|
|
8058
|
+
decantr workspace health
|
|
8059
|
+
decantr workspace health --json --output .decantr/workspace-health.json
|
|
8060
|
+
decantr workspace health --changed --since origin/main
|
|
7489
8061
|
`);
|
|
7490
8062
|
}
|
|
7491
8063
|
function cmdContentHealthHelp() {
|
|
@@ -7526,6 +8098,7 @@ ${BOLD7}Options:${RESET14}
|
|
|
7526
8098
|
--port Local port to bind; defaults to 4319
|
|
7527
8099
|
--host Local host to bind; defaults to 127.0.0.1
|
|
7528
8100
|
--report Serve a read-only Project Health JSON artifact instead of scanning the current project
|
|
8101
|
+
--workspace Serve a monorepo workspace health dashboard
|
|
7529
8102
|
|
|
7530
8103
|
${BOLD7}Endpoints:${RESET14}
|
|
7531
8104
|
GET /
|
|
@@ -7538,6 +8111,7 @@ ${BOLD7}Examples:${RESET14}
|
|
|
7538
8111
|
decantr studio --host 127.0.0.1 --port 4319
|
|
7539
8112
|
decantr health --json --output decantr-health.json
|
|
7540
8113
|
decantr studio --report decantr-health.json
|
|
8114
|
+
decantr studio --workspace
|
|
7541
8115
|
`);
|
|
7542
8116
|
}
|
|
7543
8117
|
async function main() {
|
|
@@ -7653,7 +8227,7 @@ async function main() {
|
|
|
7653
8227
|
break;
|
|
7654
8228
|
}
|
|
7655
8229
|
case "upgrade": {
|
|
7656
|
-
const { cmdUpgrade } = await import("./upgrade-
|
|
8230
|
+
const { cmdUpgrade } = await import("./upgrade-HSPWYROM.js");
|
|
7657
8231
|
const applyFlag = args.includes("--apply");
|
|
7658
8232
|
await cmdUpgrade(process.cwd(), { apply: applyFlag });
|
|
7659
8233
|
break;
|
|
@@ -7677,7 +8251,7 @@ async function main() {
|
|
|
7677
8251
|
cmdHealthHelp();
|
|
7678
8252
|
break;
|
|
7679
8253
|
}
|
|
7680
|
-
const { cmdHealth, parseHealthArgs } = await import("./health-
|
|
8254
|
+
const { cmdHealth, parseHealthArgs } = await import("./health-ZXOPGNBZ.js");
|
|
7681
8255
|
await cmdHealth(process.cwd(), parseHealthArgs(args));
|
|
7682
8256
|
} catch (e) {
|
|
7683
8257
|
console.error(error3(e.message));
|
|
@@ -7705,7 +8279,7 @@ async function main() {
|
|
|
7705
8279
|
cmdStudioHelp();
|
|
7706
8280
|
break;
|
|
7707
8281
|
}
|
|
7708
|
-
const { cmdStudio, parseStudioArgs } = await import("./studio-
|
|
8282
|
+
const { cmdStudio, parseStudioArgs } = await import("./studio-LHQXHBE7.js");
|
|
7709
8283
|
await cmdStudio(process.cwd(), parseStudioArgs(args));
|
|
7710
8284
|
} catch (e) {
|
|
7711
8285
|
console.error(error3(e.message));
|
|
@@ -7713,6 +8287,20 @@ async function main() {
|
|
|
7713
8287
|
}
|
|
7714
8288
|
break;
|
|
7715
8289
|
}
|
|
8290
|
+
case "workspace": {
|
|
8291
|
+
try {
|
|
8292
|
+
if (isCommandHelpRequest(args)) {
|
|
8293
|
+
cmdWorkspaceHelp();
|
|
8294
|
+
break;
|
|
8295
|
+
}
|
|
8296
|
+
const { cmdWorkspace } = await import("./workspace-MOLAGT2B.js");
|
|
8297
|
+
await cmdWorkspace(process.cwd(), args);
|
|
8298
|
+
} catch (e) {
|
|
8299
|
+
console.error(error3(e.message));
|
|
8300
|
+
process.exitCode = 1;
|
|
8301
|
+
}
|
|
8302
|
+
break;
|
|
8303
|
+
}
|
|
7716
8304
|
case "migrate": {
|
|
7717
8305
|
await cmdMigrate(process.cwd(), args.slice(1));
|
|
7718
8306
|
break;
|
|
@@ -8199,7 +8787,7 @@ async function main() {
|
|
|
8199
8787
|
exportOutput = args[i].split("=")[1];
|
|
8200
8788
|
}
|
|
8201
8789
|
}
|
|
8202
|
-
const validTargets = ["shadcn", "tailwind", "css-vars"];
|
|
8790
|
+
const validTargets = ["shadcn", "tailwind", "css-vars", "figma-tokens"];
|
|
8203
8791
|
if (!exportTarget || !validTargets.includes(exportTarget)) {
|
|
8204
8792
|
console.error(error3(`Usage: decantr export --to <${validTargets.join("|")}>`));
|
|
8205
8793
|
process.exitCode = 1;
|