@untrustnova/nova-cli 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -33,7 +33,8 @@ npm run dev
|
|
|
33
33
|
## Struktur Template
|
|
34
34
|
|
|
35
35
|
Template menggunakan:
|
|
36
|
-
- `nova.config.js` sebagai konfigurasi utama
|
|
36
|
+
- `nova.config.js` sebagai konfigurasi utama
|
|
37
|
+
- `vite.config.js` di-generate dari `nova.config.js`
|
|
37
38
|
- Routing hybrid (object + file-based)
|
|
38
39
|
- Folder `app/` untuk server-side
|
|
39
40
|
- Folder `web/` untuk frontend React
|
|
@@ -44,7 +45,11 @@ Template menggunakan:
|
|
|
44
45
|
(`@untrustnova/nova-framework` termasuk). Gunakan `--no-install` jika ingin skip instalasi,
|
|
45
46
|
atau set `NOVA_TEMPLATE_REPO` untuk mengganti repo template.
|
|
46
47
|
|
|
47
|
-
`nova dev`
|
|
48
|
+
`nova dev` menjalankan `server.js` dan Vite dev server secara bersamaan.
|
|
49
|
+
|
|
50
|
+
Dev URLs:
|
|
51
|
+
- Backend API: `http://localhost:3000`
|
|
52
|
+
- Frontend (Vite): `http://localhost:5173`
|
|
48
53
|
|
|
49
54
|
Perintah `db:*` adalah pembungkus untuk `drizzle-kit`.
|
|
50
55
|
Jika belum terpasang, install: `npm install -D drizzle-kit`.
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -17,7 +17,7 @@ export async function run(args) {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
if (command === '--version' || command === '-v') {
|
|
20
|
-
|
|
20
|
+
logInfo('Nova CLI v1.1.0');
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -48,17 +48,19 @@ export async function run(args) {
|
|
|
48
48
|
await createMigration(rest[0]);
|
|
49
49
|
break;
|
|
50
50
|
default:
|
|
51
|
-
|
|
51
|
+
logError(`Unknown command "${command}"`);
|
|
52
52
|
printHelp();
|
|
53
53
|
}
|
|
54
54
|
} catch (error) {
|
|
55
|
-
|
|
55
|
+
logError(error.message);
|
|
56
56
|
process.exitCode = 1;
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
function printHelp() {
|
|
61
|
-
console.log(`Nova CLI
|
|
61
|
+
console.log(`[nova] Nova CLI
|
|
62
|
+
Version: 1.1.0
|
|
63
|
+
Node: ${process.version}
|
|
62
64
|
|
|
63
65
|
Usage:
|
|
64
66
|
nova new <name> [--no-install]
|
|
@@ -91,7 +93,7 @@ async function scaffoldProject(args) {
|
|
|
91
93
|
}
|
|
92
94
|
|
|
93
95
|
const remoteTemplate = await tryFetchTemplate(
|
|
94
|
-
process.env.NOVA_TEMPLATE_REPO || 'https://github.com/
|
|
96
|
+
process.env.NOVA_TEMPLATE_REPO || 'https://github.com/untrustnova/nova',
|
|
95
97
|
);
|
|
96
98
|
|
|
97
99
|
const source = remoteTemplate?.path || templateRoot;
|
|
@@ -99,7 +101,9 @@ async function scaffoldProject(args) {
|
|
|
99
101
|
'__APP_NAME__': name,
|
|
100
102
|
});
|
|
101
103
|
|
|
102
|
-
|
|
104
|
+
await ensureViteConfig(target);
|
|
105
|
+
|
|
106
|
+
logSuccess(`Project created at ${target}`);
|
|
103
107
|
|
|
104
108
|
if (remoteTemplate?.cleanup) {
|
|
105
109
|
await remoteTemplate.cleanup();
|
|
@@ -107,7 +111,7 @@ async function scaffoldProject(args) {
|
|
|
107
111
|
|
|
108
112
|
if (shouldInstall) {
|
|
109
113
|
await runCommand('npm', ['install'], { cwd: target });
|
|
110
|
-
|
|
114
|
+
logSuccess('Dependencies installed');
|
|
111
115
|
}
|
|
112
116
|
}
|
|
113
117
|
|
|
@@ -133,7 +137,7 @@ export default class ${className}Controller extends Controller {
|
|
|
133
137
|
`;
|
|
134
138
|
|
|
135
139
|
await writeFile(target, body, 'utf8');
|
|
136
|
-
|
|
140
|
+
logSuccess(`Controller created: ${relativePath(target)}`);
|
|
137
141
|
}
|
|
138
142
|
|
|
139
143
|
async function createMiddleware(name) {
|
|
@@ -156,7 +160,7 @@ async function createMiddleware(name) {
|
|
|
156
160
|
`;
|
|
157
161
|
|
|
158
162
|
await writeFile(target, body, 'utf8');
|
|
159
|
-
|
|
163
|
+
logSuccess(`Middleware created: ${relativePath(target)}`);
|
|
160
164
|
}
|
|
161
165
|
|
|
162
166
|
async function createMigration(name) {
|
|
@@ -181,7 +185,7 @@ export async function down(db) {
|
|
|
181
185
|
`;
|
|
182
186
|
|
|
183
187
|
await writeFile(target, body, 'utf8');
|
|
184
|
-
|
|
188
|
+
logSuccess(`Migration created: ${relativePath(target)}`);
|
|
185
189
|
}
|
|
186
190
|
|
|
187
191
|
async function runDrizzle(command) {
|
|
@@ -198,16 +202,35 @@ async function runDev() {
|
|
|
198
202
|
shell: process.platform === 'win32',
|
|
199
203
|
});
|
|
200
204
|
|
|
201
|
-
|
|
202
|
-
|
|
205
|
+
let viteServer = null;
|
|
206
|
+
let shuttingDown = false;
|
|
207
|
+
|
|
208
|
+
const shutdown = async (signal) => {
|
|
209
|
+
if (shuttingDown) return;
|
|
210
|
+
shuttingDown = true;
|
|
211
|
+
server.kill(signal);
|
|
212
|
+
if (viteServer) {
|
|
213
|
+
await viteServer.close();
|
|
214
|
+
}
|
|
215
|
+
process.exit(0);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
219
|
+
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
203
220
|
|
|
204
|
-
|
|
221
|
+
try {
|
|
222
|
+
viteServer = await runViteDev(config);
|
|
223
|
+
} catch (error) {
|
|
224
|
+
logError(error.message);
|
|
225
|
+
await shutdown('SIGTERM');
|
|
226
|
+
}
|
|
205
227
|
}
|
|
206
228
|
|
|
207
229
|
async function runBuild() {
|
|
208
230
|
const config = await loadNovaConfig();
|
|
209
231
|
const { runBuild: runViteBuild } = await loadFrameworkModule('dev');
|
|
210
232
|
await runViteBuild(config);
|
|
233
|
+
logSuccess('Build completed');
|
|
211
234
|
}
|
|
212
235
|
|
|
213
236
|
async function runCommand(command, args, options = {}) {
|
|
@@ -333,6 +356,27 @@ function relativePath(path) {
|
|
|
333
356
|
return path.replace(process.cwd() + '/', '');
|
|
334
357
|
}
|
|
335
358
|
|
|
359
|
+
async function ensureViteConfig(targetRoot) {
|
|
360
|
+
const viteConfigPath = resolve(targetRoot, 'vite.config.js');
|
|
361
|
+
if (await pathExists(viteConfigPath)) return;
|
|
362
|
+
|
|
363
|
+
const contents = `import { defineConfig } from 'vite';\nimport novaConfig from './nova.config.js';\nimport { resolveViteConfig } from '@untrustnova/nova-framework/config/resolveVite';\n\nexport default defineConfig(async () => resolveViteConfig(novaConfig));\n`;
|
|
364
|
+
await writeFile(viteConfigPath, contents, 'utf8');
|
|
365
|
+
logSuccess('vite.config.js generated from nova.config.js');
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function logInfo(message) {
|
|
369
|
+
console.log(`[nova] ${message}`);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function logSuccess(message) {
|
|
373
|
+
console.log(`[nova] ${message}`);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function logError(message) {
|
|
377
|
+
console.error(`[nova] ${message}`);
|
|
378
|
+
}
|
|
379
|
+
|
|
336
380
|
async function loadNovaConfig() {
|
|
337
381
|
const configPath = resolve(process.cwd(), 'nova.config.js');
|
|
338
382
|
const module = await import(pathToFileURL(configPath));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "__APP_NAME__",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -12,15 +12,19 @@
|
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"dotenv": "^16.4.5",
|
|
14
14
|
"drizzle-orm": "^0.40.0",
|
|
15
|
-
"@untrustnova/nova-framework": "^
|
|
15
|
+
"@untrustnova/nova-framework": "^1.1.0",
|
|
16
16
|
"react": "^19.0.0",
|
|
17
17
|
"react-dom": "^19.0.0"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
|
+
"@tailwindcss/postcss": "^4.0.0",
|
|
20
21
|
"@vitejs/plugin-react": "^4.3.4",
|
|
22
|
+
"autoprefixer": "^10.4.20",
|
|
21
23
|
"eslint": "^9.18.0",
|
|
22
24
|
"eslint-config-prettier": "^9.1.0",
|
|
23
25
|
"eslint-plugin-react": "^7.37.3",
|
|
26
|
+
"postcss": "^8.4.41",
|
|
27
|
+
"tailwindcss": "^4.0.0",
|
|
24
28
|
"vite": "^6.0.0"
|
|
25
29
|
}
|
|
26
|
-
}
|
|
30
|
+
}
|