@jsonpages/cli 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +24 -0
- package/src/index.js +216 -0
- package/tsconfig.json +13 -0
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jsonpages/cli",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "JsonPages CLI - Sovereign Projection Engine",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"jsonpages": "./src/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc -p ."
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"chalk": "^5.3.0",
|
|
14
|
+
"commander": "^12.1.0",
|
|
15
|
+
"execa": "^9.0.2",
|
|
16
|
+
"fs-extra": "^11.2.0",
|
|
17
|
+
"ora": "^8.0.1"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@types/fs-extra": "^11.0.4",
|
|
21
|
+
"@types/node": "^22.13.1",
|
|
22
|
+
"typescript": "^5.7.3"
|
|
23
|
+
}
|
|
24
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import fs from 'fs-extra';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { execa } from 'execa';
|
|
7
|
+
import ora from 'ora';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
|
|
10
|
+
// š”ļø Risoluzione path per rendere la CLI shippable
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = path.dirname(__filename);
|
|
13
|
+
|
|
14
|
+
const program = new Command();
|
|
15
|
+
|
|
16
|
+
program
|
|
17
|
+
.name('jsonpages')
|
|
18
|
+
.description('JsonPages CLI - Sovereign Projection Engine')
|
|
19
|
+
.version('2.2.0');
|
|
20
|
+
|
|
21
|
+
program
|
|
22
|
+
.command('new')
|
|
23
|
+
.argument('<type>', 'Type of artifact (tenant)')
|
|
24
|
+
.argument('<name>', 'Name of the new tenant')
|
|
25
|
+
.option('--script <path>', 'Override default deterministic script path')
|
|
26
|
+
.action(async (type, name, options) => {
|
|
27
|
+
if (type !== 'tenant') {
|
|
28
|
+
console.log(chalk.red('ā Error: Only "tenant" type is supported.'));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const targetDir = path.join(process.cwd(), name);
|
|
33
|
+
|
|
34
|
+
// š Logica Asset Interno:
|
|
35
|
+
// Se l'utente non fornisce uno script, usa quello dentro packages/cli/assets/
|
|
36
|
+
const defaultScriptPath = path.resolve(__dirname, '../assets/src_tenant_alpha.sh');
|
|
37
|
+
const scriptPath = options.script ? path.resolve(process.cwd(), options.script) : defaultScriptPath;
|
|
38
|
+
|
|
39
|
+
if (!fs.existsSync(scriptPath)) {
|
|
40
|
+
console.log(chalk.red(`ā Error: Deterministic script not found at ${scriptPath}`));
|
|
41
|
+
console.log(chalk.yellow(`Expected internal asset at: ${defaultScriptPath}`));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
console.log(chalk.blue.bold(`\nš Projecting Sovereign Tenant: ${name}\n`));
|
|
46
|
+
const spinner = ora();
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
// 1. SCAFFOLDING INFRA
|
|
50
|
+
spinner.start('Setting up environment (Vite + TS)...');
|
|
51
|
+
await fs.ensureDir(targetDir);
|
|
52
|
+
await execa('npm', ['create', 'vite@latest', '.', '--', '--template', 'react-ts'], { cwd: targetDir });
|
|
53
|
+
spinner.succeed('Environment scaffolded.');
|
|
54
|
+
|
|
55
|
+
// 2. CLEANUP (Piazza pulita per il determinismo)
|
|
56
|
+
spinner.start('Wiping default boilerplate...');
|
|
57
|
+
await fs.emptyDir(path.join(targetDir, 'src'));
|
|
58
|
+
const junk = ['App.css', 'App.tsx', 'main.tsx', 'vite-env.d.ts', 'favicon.ico', 'index.html'];
|
|
59
|
+
for (const file of junk) {
|
|
60
|
+
await fs.remove(path.join(targetDir, file)).catch(() => {});
|
|
61
|
+
await fs.remove(path.join(targetDir, 'src', file)).catch(() => {});
|
|
62
|
+
}
|
|
63
|
+
spinner.succeed('Clean slate achieved.');
|
|
64
|
+
|
|
65
|
+
// 3. INJECTION
|
|
66
|
+
spinner.start('Injecting Sovereign Configurations...');
|
|
67
|
+
await injectInfraFiles(targetDir, name);
|
|
68
|
+
spinner.succeed('Infrastructure configured.');
|
|
69
|
+
|
|
70
|
+
// 4. DETERMINISTIC SRC (Proiezione dal DNA interno)
|
|
71
|
+
spinner.start('Executing deterministic src projection...');
|
|
72
|
+
const localScript = path.join(targetDir, 'setup_src.sh');
|
|
73
|
+
await fs.copy(scriptPath, localScript);
|
|
74
|
+
await fs.chmod(localScript, '755');
|
|
75
|
+
|
|
76
|
+
// Esecuzione dello script (che ora crea anche index.html se incluso)
|
|
77
|
+
await execa('./setup_src.sh', [], { cwd: targetDir, shell: true });
|
|
78
|
+
await fs.remove(localScript);
|
|
79
|
+
spinner.succeed('Source code and assets projected successfully.');
|
|
80
|
+
|
|
81
|
+
// 5. DEPENDENCY RESOLUTION (Green Build Enforcement)
|
|
82
|
+
spinner.start('Installing dependencies (this may take a minute)...');
|
|
83
|
+
|
|
84
|
+
// 5a. Runtime Dependencies (Risolve Radix, CVA e Animations)
|
|
85
|
+
await execa('npm', ['install',
|
|
86
|
+
'react',
|
|
87
|
+
'react-dom',
|
|
88
|
+
'zod',
|
|
89
|
+
'react-router-dom',
|
|
90
|
+
'lucide-react',
|
|
91
|
+
'radix-ui', // š”ļø Risolve TS2307
|
|
92
|
+
'@base-ui/react', // Supporto componenti headless
|
|
93
|
+
'class-variance-authority', // Supporto varianti componenti
|
|
94
|
+
'tailwind-merge',
|
|
95
|
+
'clsx',
|
|
96
|
+
'tw-animate-css', // Supporto animazioni tenant
|
|
97
|
+
'file-saver',
|
|
98
|
+
'jszip'
|
|
99
|
+
], { cwd: targetDir });
|
|
100
|
+
|
|
101
|
+
// 5b. Dev Dependencies
|
|
102
|
+
await execa('npm', ['install', '-D',
|
|
103
|
+
'vite',
|
|
104
|
+
'@vitejs/plugin-react',
|
|
105
|
+
'typescript',
|
|
106
|
+
'@tailwindcss/vite',
|
|
107
|
+
'tailwindcss',
|
|
108
|
+
'@types/node',
|
|
109
|
+
'@types/react',
|
|
110
|
+
'@types/react-dom',
|
|
111
|
+
'@types/file-saver'
|
|
112
|
+
], { cwd: targetDir });
|
|
113
|
+
|
|
114
|
+
// 5c. Linking Core via yalc
|
|
115
|
+
spinner.text = 'Linking @jsonpages/core via yalc...';
|
|
116
|
+
try {
|
|
117
|
+
await execa('yalc', ['add', '@jsonpages/core'], { cwd: targetDir });
|
|
118
|
+
} catch (e) {
|
|
119
|
+
spinner.warn(chalk.yellow('Yalc link failed. Ensure "@jsonpages/core" is published in yalc.'));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
spinner.succeed(chalk.green.bold('⨠Tenant Ready!'));
|
|
123
|
+
|
|
124
|
+
console.log(`\n${chalk.white.bgBlue(' NEXT STEPS ')}`);
|
|
125
|
+
console.log(` ${chalk.cyan(`cd ${name}`)}`);
|
|
126
|
+
console.log(` ${chalk.cyan(`npm run dev`)} <- Start development`);
|
|
127
|
+
console.log(` ${chalk.cyan(`npm run build`)} <- Validate Green Build`);
|
|
128
|
+
console.log(`\nGovernance enforced. Build is now safe.\n`);
|
|
129
|
+
|
|
130
|
+
} catch (error) {
|
|
131
|
+
spinner.fail(chalk.red('Projection failed.'));
|
|
132
|
+
console.error(error);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
async function injectInfraFiles(targetDir, name) {
|
|
137
|
+
const pkg = {
|
|
138
|
+
name: name,
|
|
139
|
+
private: true,
|
|
140
|
+
version: "1.0.0",
|
|
141
|
+
type: "module",
|
|
142
|
+
scripts: {
|
|
143
|
+
"dev": "vite",
|
|
144
|
+
"build": "tsc && vite build",
|
|
145
|
+
"preview": "vite preview"
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
await fs.writeJson(path.join(targetDir, 'package.json'), pkg, { spaces: 2 });
|
|
149
|
+
|
|
150
|
+
const viteConfig = `
|
|
151
|
+
import { defineConfig } from 'vite';
|
|
152
|
+
import react from '@vitejs/plugin-react';
|
|
153
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
154
|
+
import path from 'path';
|
|
155
|
+
|
|
156
|
+
export default defineConfig({
|
|
157
|
+
plugins: [react(), tailwindcss()],
|
|
158
|
+
resolve: {
|
|
159
|
+
alias: {
|
|
160
|
+
'@': path.resolve(__dirname, './src'),
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
});`;
|
|
164
|
+
await fs.writeFile(path.join(targetDir, 'vite.config.ts'), viteConfig.trim());
|
|
165
|
+
|
|
166
|
+
const tsConfig = `
|
|
167
|
+
{
|
|
168
|
+
"compilerOptions": {
|
|
169
|
+
"target": "ES2020",
|
|
170
|
+
"useDefineForClassFields": true,
|
|
171
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
172
|
+
"module": "ESNext",
|
|
173
|
+
"skipLibCheck": true,
|
|
174
|
+
"moduleResolution": "bundler",
|
|
175
|
+
"allowImportingTsExtensions": true,
|
|
176
|
+
"resolveJsonModule": true,
|
|
177
|
+
"isolatedModules": true,
|
|
178
|
+
"noEmit": true,
|
|
179
|
+
"jsx": "react-jsx",
|
|
180
|
+
"strict": true,
|
|
181
|
+
"noUnusedLocals": true,
|
|
182
|
+
"noUnusedParameters": true,
|
|
183
|
+
"noFallthroughCasesInSwitch": true,
|
|
184
|
+
"baseUrl": ".",
|
|
185
|
+
"paths": {
|
|
186
|
+
"@/*": ["./src/*"]
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
"include": ["src"]
|
|
190
|
+
}`;
|
|
191
|
+
await fs.writeFile(path.join(targetDir, 'tsconfig.json'), tsConfig.trim());
|
|
192
|
+
|
|
193
|
+
const shadcnConfig = {
|
|
194
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
195
|
+
"style": "radix-nova",
|
|
196
|
+
"rsc": false,
|
|
197
|
+
"tsx": true,
|
|
198
|
+
"tailwind": {
|
|
199
|
+
"config": "",
|
|
200
|
+
"css": "src/index.css",
|
|
201
|
+
"baseColor": "zinc",
|
|
202
|
+
"cssVariables": true,
|
|
203
|
+
"prefix": ""
|
|
204
|
+
},
|
|
205
|
+
"aliases": {
|
|
206
|
+
"components": "@/components",
|
|
207
|
+
"utils": "@/lib/utils",
|
|
208
|
+
"ui": "@/components/ui",
|
|
209
|
+
"lib": "@/lib",
|
|
210
|
+
"hooks": "@/hooks"
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
await fs.writeJson(path.join(targetDir, 'components.json'), shadcnConfig, { spaces: 2 });
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
program.parse();
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
"noEmit": true
|
|
11
|
+
},
|
|
12
|
+
"include": ["src/**/*.ts", "src/**/*.js"]
|
|
13
|
+
}
|