@deneb-ui/cli 2.0.21 → 2.0.23
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 +62 -114
- package/bin/index.js +101 -207
- package/package.json +20 -5
- package/src/arc/__fixtures__/next-app-basic/package.json +10 -0
- package/src/arc/__fixtures__/next-app-basic/src/app/globals.css +3 -0
- package/src/arc/__fixtures__/next-app-basic/src/app/layout.tsx +9 -0
- package/src/arc/__fixtures__/next-app-basic/src/app/page.tsx +11 -0
- package/src/arc/__fixtures__/next-app-basic/src/components/Header.tsx +13 -0
- package/src/arc/__fixtures__/next-app-basic/src/components/Hero.tsx +12 -0
- package/src/arc/__fixtures__/next-app-basic/src/components/PromoBanner.tsx +10 -0
- package/src/arc/__fixtures__/next-app-basic/tsconfig.json +12 -0
- package/src/arc/__fixtures__/next-app-storefront/components.json +14 -0
- package/src/arc/__fixtures__/next-app-storefront/package.json +22 -0
- package/src/arc/__fixtures__/next-app-storefront/src/app/about/page.tsx +13 -0
- package/src/arc/__fixtures__/next-app-storefront/src/app/globals.css +5 -0
- package/src/arc/__fixtures__/next-app-storefront/src/app/layout.tsx +19 -0
- package/src/arc/__fixtures__/next-app-storefront/src/app/page.tsx +13 -0
- package/src/arc/__fixtures__/next-app-storefront/src/components/Features.tsx +31 -0
- package/src/arc/__fixtures__/next-app-storefront/src/components/Hero.tsx +45 -0
- package/src/arc/__fixtures__/next-app-storefront/src/components/ProductGrid.tsx +49 -0
- package/src/arc/__fixtures__/next-app-storefront/src/components/SiteFooter.tsx +22 -0
- package/src/arc/__fixtures__/next-app-storefront/src/components/SiteHeader.tsx +21 -0
- package/src/arc/__fixtures__/next-app-storefront/src/components/ui/button.tsx +36 -0
- package/src/arc/__fixtures__/next-app-storefront/tsconfig.json +15 -0
- package/src/arc/__fixtures__/next-pages-basic/package.json +10 -0
- package/src/arc/__fixtures__/next-pages-basic/pages/_app.jsx +5 -0
- package/src/arc/__fixtures__/next-pages-basic/pages/contact.jsx +9 -0
- package/src/arc/__fixtures__/next-pages-basic/pages/index.jsx +11 -0
- package/src/arc/__fixtures__/next-pages-basic/styles/globals.css +9 -0
- package/src/arc/__tests__/arc.test.cjs +458 -0
- package/src/arc/adapters.cjs +184 -0
- package/src/arc/ast.cjs +323 -0
- package/src/arc/field-paths.cjs +165 -0
- package/src/arc/fivora-contract.cjs +521 -0
- package/src/arc/fs-utils.cjs +170 -0
- package/src/arc/index.cjs +628 -0
- package/src/arc/learning.cjs +185 -0
- package/src/arc/manifest.cjs +421 -0
- package/src/arc/next-config.cjs +279 -0
- package/src/arc/planner.cjs +227 -0
- package/src/arc/printer.cjs +153 -0
- package/src/arc/recipes-v2.cjs +49 -0
- package/src/arc/scanner.cjs +613 -0
- package/src/arc/semantic.cjs +651 -0
- package/src/arc/transformer.cjs +646 -0
- package/src/arc/validator.cjs +173 -0
- package/src/arc/version.cjs +22 -0
- package/src/recipes/cosmetics-beauty-store.json +1097 -0
- package/src/recipes/electronics-gadgets-store.json +1080 -0
- package/src/recipes/fashion-apparel-store.json +1074 -0
- package/src/tools/deneb-doctor.cjs +646 -0
- package/src/tools/recipe-engine.cjs +30 -0
- package/src/tools/template-converter.cjs +19 -6
package/README.md
CHANGED
|
@@ -1,138 +1,86 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
>
|
|
6
|
-
|
|
7
|
-
>
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
npm install -D @deneb-ui/cli
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
Or install globally:
|
|
27
|
-
```bash
|
|
28
|
-
npm install -g @deneb-ui/cli
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
The CLI command is available as `deneb` (with alias `denebui`).
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://deneb.fivora.site">
|
|
3
|
+
<img src="https://img.shields.io/badge/DENEB_CLI-Storefront_Authoring_Toolkit-6366F1?style=for-the-badge&labelColor=0f172a" alt="DENEB CLI" />
|
|
4
|
+
</a>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://www.npmjs.com/package/@deneb-ui/cli"><img src="https://img.shields.io/npm/v/@deneb-ui/cli.svg?style=flat-square&color=6366F1" alt="npm version" /></a>
|
|
9
|
+
<a href="https://www.npmjs.com/package/@deneb-ui/cli"><img src="https://img.shields.io/npm/dm/@deneb-ui/cli.svg?style=flat-square&color=6366F1" alt="npm downloads" /></a>
|
|
10
|
+
<img src="https://img.shields.io/badge/Node-%3E%3D18-339933?style=flat-square&logo=node.js&logoColor=white" alt="Node.js" />
|
|
11
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-emerald?style=flat-square" alt="MIT License" /></a>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
<p align="center">
|
|
15
|
+
<strong>Scaffold, convert, validate, and ship Fivora-ready storefront templates.</strong>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<p align="center">
|
|
19
|
+
<a href="https://deneb.fivora.site/docs/cli"><strong>CLI Reference</strong></a> ·
|
|
20
|
+
<a href="https://deneb.fivora.site/docs/installation"><strong>Installation</strong></a> ·
|
|
21
|
+
<a href="https://github.com/deneb-ui/core"><strong>GitHub</strong></a>
|
|
22
|
+
</p>
|
|
32
23
|
|
|
33
24
|
---
|
|
34
25
|
|
|
35
|
-
##
|
|
36
|
-
|
|
37
|
-
### 1. `deneb add <component>` (Component Registry)
|
|
38
|
-
Add production-ready DENEB UI components into `src/components/ui/`:
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
# List available components:
|
|
42
|
-
npx @deneb-ui/cli add list
|
|
43
|
-
|
|
44
|
-
# Add specific components:
|
|
45
|
-
npx @deneb-ui/cli add product-card
|
|
46
|
-
npx @deneb-ui/cli add contact-actions
|
|
47
|
-
npx @deneb-ui/cli add location-card
|
|
48
|
-
npx @deneb-ui/cli add whatsapp-button
|
|
49
|
-
npx @deneb-ui/cli add dialog
|
|
50
|
-
npx @deneb-ui/cli add all
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### 1. `deneb init` (Initialize Existing Project)
|
|
54
|
-
Converts and configures any **ongoing Next.js project** for the Fivora platform:
|
|
55
|
-
- Generates `fivora-template.json` (Version 2 contract with strict visual editing)
|
|
56
|
-
- Creates `src/data/site-data.json` with merchant defaults
|
|
57
|
-
- Injects npm scripts (`lab`, `validate`, `zip`, `validate-and-zip`, `update:deneb`)
|
|
58
|
-
- Installs `@deneb-ui/ui` and `@deneb-ui/cli`
|
|
26
|
+
## Quick start
|
|
59
27
|
|
|
60
28
|
```bash
|
|
29
|
+
# Convert an existing Next.js app (Deneb ARC — default engine)
|
|
61
30
|
npx @deneb-ui/cli init
|
|
62
|
-
# Or: deneb init
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### 2. `deneb update` (Update Packages & DENEB Components)
|
|
66
|
-
Keeps your project up to date by updating both npm packages and installed DENEB components:
|
|
67
|
-
- Updates `@deneb-ui/ui` and `@deneb-ui/cli` to the latest releases
|
|
68
|
-
- Automatically scans `src/components/ui/` and synchronizes existing DENEB UI components with the latest definitions
|
|
69
31
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
# Or: deneb update
|
|
73
|
-
```
|
|
32
|
+
# Preview the transformation plan without writing files
|
|
33
|
+
npx @deneb-ui/cli init --explain
|
|
74
34
|
|
|
75
|
-
|
|
76
|
-
|
|
35
|
+
# Validate Fivora contract compliance
|
|
36
|
+
npx @deneb-ui/cli validate .
|
|
77
37
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
# Or: deneb validate .
|
|
81
|
-
# Or validate and immediately bundle on success:
|
|
82
|
-
deneb validate --zip
|
|
38
|
+
# Package a clean upload ZIP
|
|
39
|
+
npx @deneb-ui/cli validate --zip
|
|
83
40
|
```
|
|
84
41
|
|
|
85
|
-
|
|
86
|
-
Creates a clean, upload-ready `fivora-template.zip` excluding unnecessary directories and secret files (`node_modules`, `.next`, `.git`, `.env*`, `.cache`, `.turbo`, logs):
|
|
42
|
+
Install as a dev dependency:
|
|
87
43
|
|
|
88
44
|
```bash
|
|
89
|
-
npm
|
|
90
|
-
#
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
### 5. `deneb validate-and-zip` (One-Step Preflight Check & Clean ZIP)
|
|
94
|
-
The safest, recommended command for releasing templates. Runs full preflight validation; if and only if all platform checks pass 100%, it bundles a clean `fivora-template.zip`:
|
|
95
|
-
|
|
96
|
-
```bash
|
|
97
|
-
npm run validate-and-zip
|
|
98
|
-
# Or: deneb validate-and-zip .
|
|
99
|
-
# Or: deneb validate and zip
|
|
45
|
+
npm install -D @deneb-ui/cli
|
|
46
|
+
# Command: deneb
|
|
100
47
|
```
|
|
101
48
|
|
|
102
|
-
|
|
103
|
-
Add or update production-ready DENEB UI components into `src/components/ui/`:
|
|
49
|
+
---
|
|
104
50
|
|
|
105
|
-
|
|
106
|
-
# List available components:
|
|
107
|
-
npx @deneb-ui/cli add list
|
|
108
|
-
|
|
109
|
-
# Add specific components:
|
|
110
|
-
npx @deneb-ui/cli add product-card
|
|
111
|
-
npx @deneb-ui/cli add contact-actions
|
|
112
|
-
npx @deneb-ui/cli add location-card
|
|
113
|
-
npx @deneb-ui/cli add whatsapp-button
|
|
114
|
-
npx @deneb-ui/cli add dialog
|
|
115
|
-
npx @deneb-ui/cli add all
|
|
116
|
-
```
|
|
51
|
+
## Commands
|
|
117
52
|
|
|
118
|
-
|
|
119
|
-
|
|
53
|
+
| Command | Description |
|
|
54
|
+
| :--- | :--- |
|
|
55
|
+
| `deneb init` | Run **Deneb ARC** — AST conversion of React/Next.js apps into Fivora-editable templates |
|
|
56
|
+
| `deneb init --legacy` | Use the legacy regex converter instead of ARC |
|
|
57
|
+
| `deneb init --dry-run` | Simulate conversion; print field paths without writing |
|
|
58
|
+
| `deneb init --explain` | Show transformation plan with confidence scores |
|
|
59
|
+
| `deneb validate` | Preflight manifest + visual editing contract checks |
|
|
60
|
+
| `deneb zip` | Create upload-ready `fivora-template.zip` |
|
|
61
|
+
| `deneb doctor` | Environment, dependency, and export diagnostics |
|
|
62
|
+
| `deneb add <component>` | Copy DENEB UI components into your project |
|
|
63
|
+
| `deneb lab` | Launch local visual editing preview lab |
|
|
64
|
+
| `deneb update` | Update `@deneb-ui/*` packages and synced components |
|
|
65
|
+
|
|
66
|
+
Full reference: [deneb.fivora.site/docs/cli](https://deneb.fivora.site/docs/cli)
|
|
120
67
|
|
|
121
|
-
|
|
122
|
-
npx @deneb-ui/cli create my-store
|
|
123
|
-
```
|
|
68
|
+
---
|
|
124
69
|
|
|
125
|
-
|
|
126
|
-
Launches the interactive visual editing test lab simulating Fivora editor messages:
|
|
70
|
+
## What `deneb init` does (ARC)
|
|
127
71
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
72
|
+
1. **Scans** your Next.js project — routes, dependencies, reachable pages
|
|
73
|
+
2. **Analyzes** JSX for editable text, images, URLs, collections, CTAs
|
|
74
|
+
3. **Transforms** source via AST — injects preview markers and `site-data` bindings
|
|
75
|
+
4. **Generates** `fivora-template.json` + `site-data.json` with strict self-validation
|
|
76
|
+
5. **Backs up** changed files to `.deneb-backup-*` for safe rollback
|
|
132
77
|
|
|
133
78
|
---
|
|
134
79
|
|
|
135
|
-
##
|
|
80
|
+
## Authors
|
|
81
|
+
|
|
82
|
+
Created and maintained by **[Chamika Gayashan](https://github.com/chamikathereal)** and **[Induranga Kawishwara](https://github.com/Induranga-kawishwara)**.
|
|
136
83
|
|
|
137
|
-
|
|
138
|
-
|
|
84
|
+
<p align="center">
|
|
85
|
+
<sub>MIT © DENEB UI</sub>
|
|
86
|
+
</p>
|
package/bin/index.js
CHANGED
|
@@ -444,6 +444,31 @@ function getComponentRegistry(importPkg) {
|
|
|
444
444
|
component: 'EditableProductCard',
|
|
445
445
|
code: `'use client';\n\nimport { EditableProductCard, type EditableProductCardProps } from '${importPkg}';\n\nexport function ProductCard(props: EditableProductCardProps) {\n return <EditableProductCard {...props} />;\n}\n`,
|
|
446
446
|
},
|
|
447
|
+
'product-grid': {
|
|
448
|
+
file: 'ProductGrid.tsx',
|
|
449
|
+
component: 'EditableProductGrid',
|
|
450
|
+
code: `'use client';\n\nimport { EditableProductGrid, ProductGrid, type EditableProductGridProps, type ProductGridItem } from '${importPkg}';\n\nexport { EditableProductGrid, ProductGrid, type EditableProductGridProps, type ProductGridItem };\n`,
|
|
451
|
+
},
|
|
452
|
+
'product-detail': {
|
|
453
|
+
file: 'ProductDetail.tsx',
|
|
454
|
+
component: 'EditableProductDetail',
|
|
455
|
+
code: `'use client';\n\nimport { EditableProductDetail, ProductDetail, type EditableProductDetailProps, type ProductDetailItem } from '${importPkg}';\n\nexport { EditableProductDetail, ProductDetail, type EditableProductDetailProps, type ProductDetailItem };\n`,
|
|
456
|
+
},
|
|
457
|
+
'customer-reviews': {
|
|
458
|
+
file: 'CustomerReviews.tsx',
|
|
459
|
+
component: 'EditableCustomerReviews',
|
|
460
|
+
code: `'use client';\n\nimport { EditableCustomerReviews, CustomerReviews, type EditableCustomerReviewsProps, type CustomerReviewItem } from '${importPkg}';\n\nexport { EditableCustomerReviews, CustomerReviews, type EditableCustomerReviewsProps, type CustomerReviewItem };\n`,
|
|
461
|
+
},
|
|
462
|
+
'cart-drawer': {
|
|
463
|
+
file: 'CartDrawer.tsx',
|
|
464
|
+
component: 'EditableCartDrawer',
|
|
465
|
+
code: `'use client';\n\nimport { EditableCartDrawer, CartDrawer, type EditableCartDrawerProps } from '${importPkg}';\n\nexport { EditableCartDrawer, CartDrawer, type EditableCartDrawerProps };\n`,
|
|
466
|
+
},
|
|
467
|
+
'filter-sidebar': {
|
|
468
|
+
file: 'FilterSidebar.tsx',
|
|
469
|
+
component: 'EditableFilterSidebar',
|
|
470
|
+
code: `'use client';\n\nimport { EditableFilterSidebar, FilterSidebar, type EditableFilterSidebarProps, type FilterOptionGroup } from '${importPkg}';\n\nexport { EditableFilterSidebar, FilterSidebar, type EditableFilterSidebarProps, type FilterOptionGroup };\n`,
|
|
471
|
+
},
|
|
447
472
|
'pricing-card': {
|
|
448
473
|
file: 'PricingCard.tsx',
|
|
449
474
|
component: 'EditablePricingCard',
|
|
@@ -572,13 +597,13 @@ function getComponentRegistry(importPkg) {
|
|
|
572
597
|
};
|
|
573
598
|
}
|
|
574
599
|
|
|
575
|
-
function initProject(targetInput) {
|
|
600
|
+
function initProject(targetInput, options = {}) {
|
|
576
601
|
const targetDir = path.resolve(process.cwd(), targetInput || '.');
|
|
577
602
|
const pkgPath = path.join(targetDir, 'package.json');
|
|
578
603
|
|
|
579
604
|
console.log('\n' + createBox([
|
|
580
|
-
'\x1b[1m\x1b[37mDENEB
|
|
581
|
-
'\x1b[
|
|
605
|
+
'\x1b[1m\x1b[37mDENEB ARC\x1b[0m',
|
|
606
|
+
'\x1b[90mAdaptive Refactoring Compiler for Fivora-editable UI\x1b[0m',
|
|
582
607
|
'\x1b[90mPowered by DENEB-UI Collaborate with FIVORA\x1b[0m'
|
|
583
608
|
], 58) + '\n');
|
|
584
609
|
|
|
@@ -612,20 +637,27 @@ function initProject(targetInput) {
|
|
|
612
637
|
// 1. Scan / Detect Pages
|
|
613
638
|
const detectedPages = detectPages(targetDir);
|
|
614
639
|
|
|
615
|
-
// 2.
|
|
616
|
-
// Automatically detects CSS/UI frameworks (shadcn/ui, HeroUI, Tailwind CSS),
|
|
617
|
-
// creates safe backup, instruments Root Layout with SiteDataProvider,
|
|
618
|
-
// extracts hardcoded text/images/buttons/placeholders,
|
|
619
|
-
// injects data-preview-field-path markers, harmonizes UI components,
|
|
620
|
-
// and builds synchronized site-data.json & fivora-template.json.
|
|
640
|
+
// 2. Deneb ARC (default) or legacy regex converter (--legacy)
|
|
621
641
|
let conversionRes = null;
|
|
622
642
|
try {
|
|
623
|
-
|
|
624
|
-
|
|
643
|
+
if (options.legacy) {
|
|
644
|
+
const { runUniversalTemplateConversion } = require('../src/tools/template-converter.cjs');
|
|
645
|
+
conversionRes = runUniversalTemplateConversion(targetDir, projectName, detectedPages, options);
|
|
646
|
+
} else {
|
|
647
|
+
const { runDenebArc } = require('../src/arc/index.cjs');
|
|
648
|
+
conversionRes = runDenebArc(targetDir, projectName, {
|
|
649
|
+
...options,
|
|
650
|
+
detectedPages,
|
|
651
|
+
});
|
|
652
|
+
}
|
|
625
653
|
} catch (err) {
|
|
626
654
|
console.error(`\x1b[33m⚠ Note:\x1b[0m Automated conversion encountered an issue: ${err.message}. Falling back to default generation.`);
|
|
627
655
|
}
|
|
628
656
|
|
|
657
|
+
if (options.dryRun) {
|
|
658
|
+
return conversionRes;
|
|
659
|
+
}
|
|
660
|
+
|
|
629
661
|
// 3. Fallback: Generate fivora-template.json if not yet present
|
|
630
662
|
const manifestPath = path.join(targetDir, 'fivora-template.json');
|
|
631
663
|
if (!fs.existsSync(manifestPath)) {
|
|
@@ -957,198 +989,9 @@ Options:
|
|
|
957
989
|
], 58) + '\n');
|
|
958
990
|
}
|
|
959
991
|
|
|
960
|
-
function runDoctor(targetDirInput) {
|
|
961
|
-
const
|
|
962
|
-
|
|
963
|
-
console.log('\n' + createBox([
|
|
964
|
-
'\x1b[1m\x1b[36m🩺 DENEB SYSTEM & TEMPLATE DOCTOR\x1b[0m',
|
|
965
|
-
'\x1b[90mComprehensive diagnostic analysis for Fivora & Next.js\x1b[0m',
|
|
966
|
-
`\x1b[37mTarget:\x1b[0m ${targetDir}`
|
|
967
|
-
], 60) + '\n');
|
|
968
|
-
|
|
969
|
-
let passed = 0;
|
|
970
|
-
let warnings = 0;
|
|
971
|
-
let errors = 0;
|
|
972
|
-
|
|
973
|
-
function report(type, title, detail) {
|
|
974
|
-
if (type === 'pass') {
|
|
975
|
-
passed++;
|
|
976
|
-
console.log(` \x1b[32m✔\x1b[0m \x1b[1m${title}\x1b[0m${detail ? ` \x1b[90m(${detail})\x1b[0m` : ''}`);
|
|
977
|
-
} else if (type === 'warn') {
|
|
978
|
-
warnings++;
|
|
979
|
-
console.log(` \x1b[33m⚠\x1b[0m \x1b[33m${title}\x1b[0m${detail ? ` \x1b[90m- ${detail}\x1b[0m` : ''}`);
|
|
980
|
-
} else {
|
|
981
|
-
errors++;
|
|
982
|
-
console.log(` \x1b[31m✖\x1b[0m \x1b[31m${title}\x1b[0m${detail ? ` \x1b[90m- ${detail}\x1b[0m` : ''}`);
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
console.log('\x1b[1m[1/6] System & Runtime Environment:\x1b[0m');
|
|
987
|
-
const nodeVersion = process.version;
|
|
988
|
-
const majorNode = parseInt(nodeVersion.replace(/^v/, '').split('.')[0], 10);
|
|
989
|
-
if (majorNode >= 18) {
|
|
990
|
-
report('pass', 'Node.js Runtime', `${nodeVersion} (Supported)`);
|
|
991
|
-
} else {
|
|
992
|
-
report('err', 'Node.js Runtime', `${nodeVersion} (Requires Node.js >= 18.0.0)`);
|
|
993
|
-
}
|
|
994
|
-
|
|
995
|
-
const npmBin = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
996
|
-
const npmCheck = spawnSync(npmBin, ['--version'], { encoding: 'utf-8', shell: process.platform === 'win32' });
|
|
997
|
-
if (!npmCheck.error && npmCheck.status === 0) {
|
|
998
|
-
report('pass', 'Package Manager', `npm v${npmCheck.stdout.trim()}`);
|
|
999
|
-
} else {
|
|
1000
|
-
report('warn', 'Package Manager', 'npm not found in system PATH');
|
|
1001
|
-
}
|
|
1002
|
-
|
|
1003
|
-
console.log('\n\x1b[1m[2/6] Project Package Configuration:\x1b[0m');
|
|
1004
|
-
const pkgPath = path.join(targetDir, 'package.json');
|
|
1005
|
-
let pkg = null;
|
|
1006
|
-
if (fs.existsSync(pkgPath)) {
|
|
1007
|
-
try {
|
|
1008
|
-
pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
1009
|
-
report('pass', 'package.json', `Found "${pkg.name || 'unnamed'}"`);
|
|
1010
|
-
const allDeps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
|
|
1011
|
-
|
|
1012
|
-
if (allDeps['next']) {
|
|
1013
|
-
report('pass', 'Next.js Framework', allDeps['next']);
|
|
1014
|
-
} else {
|
|
1015
|
-
report('err', 'Next.js Framework', 'next dependency missing in package.json');
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
if (allDeps['@deneb-ui/ui']) {
|
|
1019
|
-
report('pass', '@deneb-ui/ui Library', allDeps['@deneb-ui/ui']);
|
|
1020
|
-
} else {
|
|
1021
|
-
report('warn', '@deneb-ui/ui Library', 'Not installed (run "npm i @deneb-ui/ui")');
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
|
-
if (allDeps['@deneb-ui/cli']) {
|
|
1025
|
-
report('pass', '@deneb-ui/cli Tooling', allDeps['@deneb-ui/cli']);
|
|
1026
|
-
} else {
|
|
1027
|
-
report('warn', '@deneb-ui/cli Tooling', 'Recommended for local CLI scripts');
|
|
1028
|
-
}
|
|
1029
|
-
} catch (e) {
|
|
1030
|
-
report('err', 'package.json Syntax', e.message);
|
|
1031
|
-
}
|
|
1032
|
-
} else {
|
|
1033
|
-
report('err', 'package.json', `Not found at ${pkgPath}`);
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
console.log('\n\x1b[1m[3/6] Static Export Configuration:\x1b[0m');
|
|
1037
|
-
const nextConfigTs = path.join(targetDir, 'next.config.ts');
|
|
1038
|
-
const nextConfigMjs = path.join(targetDir, 'next.config.mjs');
|
|
1039
|
-
const nextConfigJs = path.join(targetDir, 'next.config.js');
|
|
1040
|
-
let nextConfigFile = [nextConfigTs, nextConfigMjs, nextConfigJs].find((p) => fs.existsSync(p));
|
|
1041
|
-
|
|
1042
|
-
if (nextConfigFile) {
|
|
1043
|
-
const content = fs.readFileSync(nextConfigFile, 'utf-8');
|
|
1044
|
-
if (content.includes("output: 'export'") || content.includes('output: "export"')) {
|
|
1045
|
-
report('pass', 'Next.js Static Export', `output: 'export' verified in ${path.basename(nextConfigFile)}`);
|
|
1046
|
-
} else {
|
|
1047
|
-
report('err', 'Next.js Static Export', `Missing output: 'export' in ${path.basename(nextConfigFile)} (Required by Fivora)`);
|
|
1048
|
-
}
|
|
1049
|
-
} else {
|
|
1050
|
-
report('err', 'Next.js Config', 'No next.config.ts, next.config.mjs, or next.config.js found');
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
console.log('\n\x1b[1m[4/6] Fivora Manifest v2 Contract:\x1b[0m');
|
|
1054
|
-
const manifestPath = path.join(targetDir, 'fivora-template.json');
|
|
1055
|
-
let manifestData = null;
|
|
1056
|
-
if (fs.existsSync(manifestPath)) {
|
|
1057
|
-
try {
|
|
1058
|
-
manifestData = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
|
|
1059
|
-
report('pass', 'fivora-template.json', `Valid JSON (strict=${manifestData.strict !== false})`);
|
|
1060
|
-
|
|
1061
|
-
if (manifestData.version === 2 || manifestData.version === '2') {
|
|
1062
|
-
report('pass', 'Manifest Version', 'Version 2 (Current standard)');
|
|
1063
|
-
} else {
|
|
1064
|
-
report('warn', 'Manifest Version', `Version ${manifestData.version} detected (Recommend version 2)`);
|
|
1065
|
-
}
|
|
1066
|
-
|
|
1067
|
-
const hasHome = Array.isArray(manifestData.pages) && manifestData.pages.some((p) =>
|
|
1068
|
-
p.route === '/' || p.slug === '/' || p.path === '/' || p.id === 'home'
|
|
1069
|
-
);
|
|
1070
|
-
if (hasHome) {
|
|
1071
|
-
report('pass', 'Home Page Entry', 'Home page ("/") declared in manifest');
|
|
1072
|
-
} else {
|
|
1073
|
-
report('err', 'Home Page Entry', 'Manifest pages array missing root slug or route: "/"');
|
|
1074
|
-
}
|
|
1075
|
-
|
|
1076
|
-
if (manifestData.theme && (manifestData.theme.primary || manifestData.theme.accent)) {
|
|
1077
|
-
report('pass', 'Theme Configuration', 'Primary and accent color tokens declared');
|
|
1078
|
-
} else {
|
|
1079
|
-
// Will check site-data.json below as alternative
|
|
1080
|
-
}
|
|
1081
|
-
} catch (e) {
|
|
1082
|
-
report('err', 'fivora-template.json Syntax', e.message);
|
|
1083
|
-
}
|
|
1084
|
-
} else {
|
|
1085
|
-
report('err', 'fivora-template.json', 'File not found. Run "deneb init" to generate it');
|
|
1086
|
-
}
|
|
1087
|
-
|
|
1088
|
-
console.log('\n\x1b[1m[5/6] Reactive Site Data & Visual Editing:\x1b[0m');
|
|
1089
|
-
const siteDataPath = path.join(targetDir, 'src', 'data', 'site-data.json');
|
|
1090
|
-
if (fs.existsSync(siteDataPath)) {
|
|
1091
|
-
try {
|
|
1092
|
-
const siteData = JSON.parse(fs.readFileSync(siteDataPath, 'utf-8'));
|
|
1093
|
-
report('pass', 'site-data.json', 'src/data/site-data.json exists & valid');
|
|
1094
|
-
const merchantName = (siteData.merchant && (siteData.merchant.businessName || siteData.merchant.name)) || null;
|
|
1095
|
-
if (merchantName) {
|
|
1096
|
-
report('pass', 'Merchant Metadata', `Name: "${merchantName}"`);
|
|
1097
|
-
} else {
|
|
1098
|
-
report('warn', 'Merchant Metadata', 'Missing merchant name in site-data.json');
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
|
-
const themeTokens = manifestData?.theme || siteData?.template?.structure?.theme;
|
|
1102
|
-
if (themeTokens && (themeTokens.primaryColor || themeTokens.primary || themeTokens.accentColor || themeTokens.accent)) {
|
|
1103
|
-
report('pass', 'Theme Design Tokens', 'Theme color tokens declared');
|
|
1104
|
-
} else {
|
|
1105
|
-
report('warn', 'Theme Design Tokens', 'No theme color tokens found in manifest or site-data.json');
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
if (siteData.content) {
|
|
1109
|
-
report('pass', 'Visual Content Bindings', 'Content section ready for live sync');
|
|
1110
|
-
} else {
|
|
1111
|
-
report('warn', 'Visual Content Bindings', 'Missing content section in site-data.json');
|
|
1112
|
-
}
|
|
1113
|
-
} catch (e) {
|
|
1114
|
-
report('err', 'site-data.json Syntax', e.message);
|
|
1115
|
-
}
|
|
1116
|
-
} else {
|
|
1117
|
-
report('warn', 'site-data.json', 'src/data/site-data.json not found. Recommended for Fivora live editor');
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
console.log('\n\x1b[1m[6/6] Cleanliness & Security Check:\x1b[0m');
|
|
1121
|
-
const envFiles = ['.env', '.env.local', '.env.production', '.env.development'];
|
|
1122
|
-
const foundEnv = envFiles.filter((f) => fs.existsSync(path.join(targetDir, f)));
|
|
1123
|
-
if (foundEnv.length === 0) {
|
|
1124
|
-
report('pass', 'Secrets Isolation', 'No raw .env files detected in root directory');
|
|
1125
|
-
} else {
|
|
1126
|
-
report('warn', 'Secrets Isolation', `Active env files: ${foundEnv.join(', ')} (Excluded during packaging)`);
|
|
1127
|
-
}
|
|
1128
|
-
|
|
1129
|
-
const previewExists = fs.existsSync(path.join(targetDir, 'preview.png')) ||
|
|
1130
|
-
fs.existsSync(path.join(targetDir, 'thumbnail.png')) ||
|
|
1131
|
-
fs.existsSync(path.join(targetDir, 'public', 'fivora-logo.png'));
|
|
1132
|
-
if (previewExists) {
|
|
1133
|
-
report('pass', 'Storefront Assets', 'Brand/preview graphics verified');
|
|
1134
|
-
} else {
|
|
1135
|
-
report('warn', 'Storefront Assets', 'preview.png not found in template root');
|
|
1136
|
-
}
|
|
1137
|
-
|
|
1138
|
-
// Summary
|
|
1139
|
-
console.log('\n' + createBox([
|
|
1140
|
-
'\x1b[1mDOCTOR DIAGNOSTIC SUMMARY\x1b[0m',
|
|
1141
|
-
`\x1b[32m✔ Passed:\x1b[0m ${passed}`,
|
|
1142
|
-
`\x1b[33m⚠ Warnings:\x1b[0m ${warnings}`,
|
|
1143
|
-
`\x1b[31m✖ Errors:\x1b[0m ${errors}`,
|
|
1144
|
-
errors === 0
|
|
1145
|
-
? '\x1b[32mStatus: HEALTHY — Ready for Fivora packaging & build!\x1b[0m'
|
|
1146
|
-
: '\x1b[31mStatus: ATTENTION REQUIRED — Fix errors before deployment\x1b[0m'
|
|
1147
|
-
], 58) + '\n');
|
|
1148
|
-
|
|
1149
|
-
if (errors > 0) {
|
|
1150
|
-
process.exit(1);
|
|
1151
|
-
}
|
|
992
|
+
function runDoctor(targetDirInput, options = {}) {
|
|
993
|
+
const { runDoctor: executeDoctor } = require('../src/tools/deneb-doctor.cjs');
|
|
994
|
+
return executeDoctor(targetDirInput, options);
|
|
1152
995
|
}
|
|
1153
996
|
|
|
1154
997
|
// Normalize multi-word "validate and zip" or "validate & zip"
|
|
@@ -1161,13 +1004,55 @@ if (command === 'validate' && (commandArgs[0] === 'and' || commandArgs[0] === '&
|
|
|
1161
1004
|
}
|
|
1162
1005
|
|
|
1163
1006
|
if (command === 'init') {
|
|
1164
|
-
|
|
1007
|
+
let targetInput = '.';
|
|
1008
|
+
let recipeName = null;
|
|
1009
|
+
let dryRun = false;
|
|
1010
|
+
let explain = false;
|
|
1011
|
+
let legacy = false;
|
|
1012
|
+
let telemetry = 'off';
|
|
1013
|
+
for (let i = 0; i < commandArgs.length; i++) {
|
|
1014
|
+
const arg = commandArgs[i];
|
|
1015
|
+
if (arg === '--recipe' || arg === '-r') {
|
|
1016
|
+
recipeName = commandArgs[++i];
|
|
1017
|
+
} else if (arg.startsWith('--recipe=')) {
|
|
1018
|
+
recipeName = arg.split('=')[1];
|
|
1019
|
+
} else if (arg === '--dry-run' || arg === '--dryrun') {
|
|
1020
|
+
dryRun = true;
|
|
1021
|
+
} else if (arg === '--explain') {
|
|
1022
|
+
explain = true;
|
|
1023
|
+
} else if (arg === '--legacy') {
|
|
1024
|
+
legacy = true;
|
|
1025
|
+
} else if (arg === '--telemetry' && commandArgs[i + 1]) {
|
|
1026
|
+
telemetry = commandArgs[++i];
|
|
1027
|
+
} else if (arg.startsWith('--telemetry=')) {
|
|
1028
|
+
telemetry = arg.split('=')[1] || 'off';
|
|
1029
|
+
} else if (!arg.startsWith('-')) {
|
|
1030
|
+
targetInput = arg;
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
initProject(targetInput, { recipeName, dryRun, explain, legacy, telemetry });
|
|
1165
1034
|
} else if (command === 'create') {
|
|
1166
1035
|
createTemplate(commandArgs[0]);
|
|
1167
1036
|
} else if (command === 'add') {
|
|
1168
1037
|
addComponent(commandArgs[0], commandArgs[1]);
|
|
1169
1038
|
} else if (command === 'doctor' || command === 'check') {
|
|
1170
|
-
|
|
1039
|
+
let targetInput = '.';
|
|
1040
|
+
let fix = false;
|
|
1041
|
+
let json = false;
|
|
1042
|
+
for (let i = 0; i < commandArgs.length; i++) {
|
|
1043
|
+
const arg = commandArgs[i];
|
|
1044
|
+
if (arg === '--fix' || arg === '-f') {
|
|
1045
|
+
fix = true;
|
|
1046
|
+
} else if (arg === '--json') {
|
|
1047
|
+
json = true;
|
|
1048
|
+
} else if (!arg.startsWith('-')) {
|
|
1049
|
+
targetInput = arg;
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
const res = runDoctor(targetInput, { fix, json });
|
|
1053
|
+
if (res && res.errors > 0) {
|
|
1054
|
+
process.exit(1);
|
|
1055
|
+
}
|
|
1171
1056
|
} else if (command === 'lab') {
|
|
1172
1057
|
const script = path.join(toolsDir, 'local-template-lab.cjs');
|
|
1173
1058
|
const res = spawnSync(process.execPath, [script, ...commandArgs], { stdio: 'inherit' });
|
|
@@ -1208,12 +1093,13 @@ if (command === 'init') {
|
|
|
1208
1093
|
DENEB UI Framework — Powered by DENEB-UI Collaborate with FIVORA
|
|
1209
1094
|
|
|
1210
1095
|
Core Commands:
|
|
1211
|
-
init
|
|
1096
|
+
init Deneb ARC: convert an existing React/Next.js app into a Fivora-editable storefront
|
|
1097
|
+
flags: --dry-run --explain --recipe <name> --legacy --telemetry off|anonymous|enhanced
|
|
1098
|
+
doctor Run comprehensive environment, manifest, visual editing AST & asset diagnostic checks (flags: --fix, --json)
|
|
1212
1099
|
save-recipe Learn and save calibrated fixes & schemas into reusable recipe bank (e.g. deneb save-recipe . shoes-store)
|
|
1213
1100
|
learn Alias for save-recipe
|
|
1214
1101
|
update Update DENEB packages (@deneb-ui/ui, @deneb-ui/cli) and UI components
|
|
1215
1102
|
validate Validate website configuration and visual editing contracts with Fivora platform
|
|
1216
|
-
doctor Run comprehensive environment, manifest & asset diagnostic checks
|
|
1217
1103
|
zip Zip the project without unnecessary folders or files (node_modules, .next, .git, .env)
|
|
1218
1104
|
validate-and-zip Validate website configuration and immediately package clean upload-ready ZIP
|
|
1219
1105
|
|
|
@@ -1226,7 +1112,15 @@ Development & Scaffolding:
|
|
|
1226
1112
|
|
|
1227
1113
|
Examples:
|
|
1228
1114
|
deneb doctor
|
|
1115
|
+
deneb doctor --fix
|
|
1116
|
+
deneb doctor --json
|
|
1229
1117
|
deneb init
|
|
1118
|
+
deneb init --dry-run
|
|
1119
|
+
deneb init --explain
|
|
1120
|
+
deneb init --recipe fashion
|
|
1121
|
+
deneb init --recipe electronics
|
|
1122
|
+
deneb init --recipe cosmetics
|
|
1123
|
+
deneb init --legacy
|
|
1230
1124
|
deneb update
|
|
1231
1125
|
deneb validate .
|
|
1232
1126
|
deneb validate --zip
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deneb-ui/cli",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "Official
|
|
3
|
+
"version": "2.0.23",
|
|
4
|
+
"description": "Official DENEB CLI — scaffold, convert, validate, and package Fivora-ready storefront templates.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"deneb": "bin/index.js",
|
|
7
7
|
"denebui": "bin/index.js",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"url": "git+https://github.com/deneb-ui/core.git",
|
|
16
16
|
"directory": "cli/deneb-cli"
|
|
17
17
|
},
|
|
18
|
-
"homepage": "https://
|
|
18
|
+
"homepage": "https://deneb.fivora.site/docs/cli",
|
|
19
19
|
"bugs": {
|
|
20
20
|
"url": "https://github.com/deneb-ui/core/issues"
|
|
21
21
|
},
|
|
@@ -24,16 +24,31 @@
|
|
|
24
24
|
"src",
|
|
25
25
|
"README.md"
|
|
26
26
|
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"test": "node --test src/arc/__tests__/arc.test.cjs"
|
|
29
|
+
},
|
|
27
30
|
"keywords": [
|
|
28
31
|
"deneb",
|
|
29
32
|
"deneb-ui",
|
|
30
33
|
"cli",
|
|
34
|
+
"fivora",
|
|
35
|
+
"nextjs",
|
|
36
|
+
"template",
|
|
31
37
|
"validator",
|
|
32
|
-
"packager"
|
|
38
|
+
"packager",
|
|
39
|
+
"visual-editing",
|
|
40
|
+
"storefront",
|
|
41
|
+
"scaffold"
|
|
33
42
|
],
|
|
34
43
|
"author": "Chamika Gayashan & Induranga Kawishwara",
|
|
44
|
+
"contributors": [
|
|
45
|
+
"Chamika Gayashan <https://github.com/chamikathereal>",
|
|
46
|
+
"Induranga Kawishwara <https://github.com/Induranga-kawishwara>"
|
|
47
|
+
],
|
|
35
48
|
"license": "MIT",
|
|
36
49
|
"dependencies": {
|
|
37
|
-
"
|
|
50
|
+
"@babel/parser": "^7.28.0",
|
|
51
|
+
"adm-zip": "^0.6.0",
|
|
52
|
+
"recast": "^0.23.11"
|
|
38
53
|
}
|
|
39
54
|
}
|