vaderjs 2.3.13 → 2.3.15
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/LICENSE +21 -21
- package/README.md +89 -0
- package/cli.ts +227 -227
- package/config/index.ts +3 -0
- package/index.ts +59 -48
- package/jsconfig.json +7 -7
- package/main.ts +535 -0
- package/package.json +16 -16
- package/plugins/index.ts +72 -72
- package/README.MD +0 -99
- package/main.js +0 -750
package/main.ts
ADDED
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { build, serve } from "bun";
|
|
4
|
+
import fs from "fs/promises";
|
|
5
|
+
import fsSync from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { initProject } from "vaderjs/cli";
|
|
8
|
+
|
|
9
|
+
const colors = {
|
|
10
|
+
reset: "\x1b[0m",
|
|
11
|
+
red: "\x1b[31m",
|
|
12
|
+
green: "\x1b[32m",
|
|
13
|
+
yellow: "\x1b[33m",
|
|
14
|
+
blue: "\x1b[34m",
|
|
15
|
+
magenta: "\x1b[35m",
|
|
16
|
+
cyan: "\x1b[36m",
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
globalThis.isDev = process.argv[2] === "dev";
|
|
20
|
+
|
|
21
|
+
const logger = {
|
|
22
|
+
_log: (color, ...args) => console.log(color, ...args, colors.reset),
|
|
23
|
+
info: (...args) => logger._log(colors.cyan, "ℹ", ...args),
|
|
24
|
+
success: (...args) => logger._log(colors.green, "✅", ...args),
|
|
25
|
+
warn: (...args) => logger._log(colors.yellow, "⚠️", ...args),
|
|
26
|
+
error: (...args) => logger._log(colors.red, "❌", ...args),
|
|
27
|
+
step: (...args) => logger._log(colors.magenta, "\n🚀", ...args),
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
async function timedStep(name, fn) {
|
|
31
|
+
logger.step(`${name}...`);
|
|
32
|
+
const start = performance.now();
|
|
33
|
+
try {
|
|
34
|
+
await fn();
|
|
35
|
+
const duration = (performance.now() - start).toFixed(2);
|
|
36
|
+
logger.success(`Finished '${name}' in ${duration}ms`);
|
|
37
|
+
} catch (e) {
|
|
38
|
+
logger.error(`Error during '${name}':`, e);
|
|
39
|
+
if (!isDev) process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// --- CONSTANTS ---
|
|
44
|
+
|
|
45
|
+
const PROJECT_ROOT = process.cwd();
|
|
46
|
+
const PUBLIC_DIR = path.join(PROJECT_ROOT, "public");
|
|
47
|
+
const DIST_DIR = path.join(PROJECT_ROOT, "dist");
|
|
48
|
+
const SRC_DIR = path.join(PROJECT_ROOT, "src");
|
|
49
|
+
const APP_DIR = path.join(PROJECT_ROOT, "app");
|
|
50
|
+
|
|
51
|
+
const VADER_SRC_PATH = path.join(
|
|
52
|
+
PROJECT_ROOT,
|
|
53
|
+
"node_modules",
|
|
54
|
+
"vaderjs",
|
|
55
|
+
"index.ts"
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const TEMP_SRC_DIR = path.join(PROJECT_ROOT, ".vader_temp_src");
|
|
59
|
+
|
|
60
|
+
let config: any = {};
|
|
61
|
+
let htmlInjections: string[] = [];
|
|
62
|
+
|
|
63
|
+
// --- JSConfig Setup ---
|
|
64
|
+
|
|
65
|
+
async function ensureJSConfig() {
|
|
66
|
+
const jsconfigPath = path.join(PROJECT_ROOT, "jsconfig.json");
|
|
67
|
+
|
|
68
|
+
// Check if jsconfig.json already exists
|
|
69
|
+
let existingConfig = {};
|
|
70
|
+
if (fsSync.existsSync(jsconfigPath)) {
|
|
71
|
+
try {
|
|
72
|
+
const content = await fs.readFile(jsconfigPath, "utf8");
|
|
73
|
+
existingConfig = JSON.parse(content);
|
|
74
|
+
} catch (e) {
|
|
75
|
+
logger.warn("Existing jsconfig.json is invalid, will overwrite");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Define the required VaderJS configuration
|
|
80
|
+
const vaderConfig = {
|
|
81
|
+
compilerOptions: {
|
|
82
|
+
jsx: "react",
|
|
83
|
+
jsxFactory: "Vader.createElement",
|
|
84
|
+
jsxFragmentFactory: "Fragment"
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// Merge with existing config (preserve other settings)
|
|
89
|
+
const mergedConfig = {
|
|
90
|
+
...existingConfig,
|
|
91
|
+
compilerOptions: {
|
|
92
|
+
...(existingConfig.compilerOptions || {}),
|
|
93
|
+
...vaderConfig.compilerOptions
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// Write the config
|
|
98
|
+
await fs.writeFile(jsconfigPath, JSON.stringify(mergedConfig, null, 2));
|
|
99
|
+
logger.success(`jsconfig.json created/updated at ${jsconfigPath}`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// --- FILE WATCHER ---
|
|
103
|
+
|
|
104
|
+
class FileWatcher {
|
|
105
|
+
watchers = new Map<string, any>();
|
|
106
|
+
callbacks: ((file: string) => void)[] = [];
|
|
107
|
+
|
|
108
|
+
watch(dir: string) {
|
|
109
|
+
if (!fsSync.existsSync(dir)) return;
|
|
110
|
+
|
|
111
|
+
const watcher = fsSync.watch(dir, { recursive: true }, (_, filename) => {
|
|
112
|
+
if (!filename) return;
|
|
113
|
+
|
|
114
|
+
const file = path.join(dir, filename);
|
|
115
|
+
|
|
116
|
+
if (
|
|
117
|
+
file.includes("node_modules") ||
|
|
118
|
+
file.includes("dist") ||
|
|
119
|
+
file.includes(".git")
|
|
120
|
+
)
|
|
121
|
+
return;
|
|
122
|
+
|
|
123
|
+
this.callbacks.forEach((cb) => cb(file));
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
this.watchers.set(dir, watcher);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
onChange(cb: (file: string) => void) {
|
|
130
|
+
this.callbacks.push(cb);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
clear() {
|
|
134
|
+
this.watchers.forEach((w) => w.close());
|
|
135
|
+
this.watchers.clear();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const watcher = new FileWatcher();
|
|
140
|
+
|
|
141
|
+
// --- CONFIG ---
|
|
142
|
+
|
|
143
|
+
export async function loadConfig() {
|
|
144
|
+
try {
|
|
145
|
+
const mod = await import(path.join(PROJECT_ROOT, "vaderjs.config.js"));
|
|
146
|
+
return mod.default || mod;
|
|
147
|
+
} catch {
|
|
148
|
+
return {};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function defineConfig(cfg: any) {
|
|
153
|
+
return cfg;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// --- BUILD HELPERS ---
|
|
157
|
+
|
|
158
|
+
function patchHooksUsage(code: string) {
|
|
159
|
+
return code.replace(
|
|
160
|
+
/import\s+{[^}]*use(State|Effect|Memo)[^}]*}\s+from\s+['"]vaderjs['"];?\n?/g,
|
|
161
|
+
""
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async function preprocessSources(src: string, dest: string) {
|
|
166
|
+
await fs.mkdir(dest, { recursive: true });
|
|
167
|
+
|
|
168
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
169
|
+
|
|
170
|
+
for (const entry of entries) {
|
|
171
|
+
const srcPath = path.join(src, entry.name);
|
|
172
|
+
const destPath = path.join(dest, entry.name);
|
|
173
|
+
|
|
174
|
+
if (entry.isDirectory()) {
|
|
175
|
+
await preprocessSources(srcPath, destPath);
|
|
176
|
+
} else if (/\.(ts|tsx|js|jsx)$/.test(entry.name)) {
|
|
177
|
+
let content = await fs.readFile(srcPath, "utf8");
|
|
178
|
+
content = patchHooksUsage(content);
|
|
179
|
+
await fs.writeFile(destPath, content);
|
|
180
|
+
} else {
|
|
181
|
+
await fs.copyFile(srcPath, destPath);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async function buildVaderCore() {
|
|
187
|
+
if (!fsSync.existsSync(VADER_SRC_PATH)) {
|
|
188
|
+
throw new Error("Missing vaderjs dependency");
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
await build({
|
|
192
|
+
entrypoints: [VADER_SRC_PATH],
|
|
193
|
+
outdir: path.join(DIST_DIR, "src", "vader"),
|
|
194
|
+
target: "browser",
|
|
195
|
+
jsxFactory: "e",
|
|
196
|
+
jsxFragment: "Fragment",
|
|
197
|
+
jsxImportSource: "vaderjs",
|
|
198
|
+
sourcemap: "external",
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
async function buildSrc() {
|
|
203
|
+
if (!fsSync.existsSync(SRC_DIR)) return;
|
|
204
|
+
|
|
205
|
+
if (fsSync.existsSync(TEMP_SRC_DIR)) {
|
|
206
|
+
await fs.rm(TEMP_SRC_DIR, { recursive: true, force: true });
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
await preprocessSources(SRC_DIR, TEMP_SRC_DIR);
|
|
210
|
+
|
|
211
|
+
const entrypoints: string[] = [];
|
|
212
|
+
|
|
213
|
+
function collect(dir: string) {
|
|
214
|
+
const files = fsSync.readdirSync(dir, { withFileTypes: true });
|
|
215
|
+
|
|
216
|
+
for (const f of files) {
|
|
217
|
+
const full = path.join(dir, f.name);
|
|
218
|
+
|
|
219
|
+
if (f.isDirectory()) collect(full);
|
|
220
|
+
else if (/\.(ts|tsx|js|jsx)$/.test(f.name)) entrypoints.push(full);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
collect(TEMP_SRC_DIR);
|
|
225
|
+
|
|
226
|
+
if (!entrypoints.length) return;
|
|
227
|
+
|
|
228
|
+
await build({
|
|
229
|
+
entrypoints,
|
|
230
|
+
outdir: path.join(DIST_DIR, "src"),
|
|
231
|
+
root: TEMP_SRC_DIR,
|
|
232
|
+
naming: { entry: "[dir]/[name].js" },
|
|
233
|
+
jsxFactory: "e",
|
|
234
|
+
jsxFragment: "Fragment",
|
|
235
|
+
jsxImportSource: "vaderjs",
|
|
236
|
+
target: "browser",
|
|
237
|
+
external: ["vaderjs"],
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
async function copyPublicAssets() {
|
|
242
|
+
if (!fsSync.existsSync(PUBLIC_DIR)) return;
|
|
243
|
+
|
|
244
|
+
const items = await fs.readdir(PUBLIC_DIR);
|
|
245
|
+
|
|
246
|
+
for (const item of items) {
|
|
247
|
+
await fs.cp(
|
|
248
|
+
path.join(PUBLIC_DIR, item),
|
|
249
|
+
path.join(DIST_DIR, item),
|
|
250
|
+
{ recursive: true }
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Helper function to find App file
|
|
256
|
+
function findAppFile(): string | null {
|
|
257
|
+
const possiblePaths = [
|
|
258
|
+
path.join(PROJECT_ROOT, "App.tsx"),
|
|
259
|
+
path.join(PROJECT_ROOT, "App.jsx"),
|
|
260
|
+
path.join(PROJECT_ROOT, "App.ts"),
|
|
261
|
+
path.join(PROJECT_ROOT, "App.js"),
|
|
262
|
+
path.join(APP_DIR, "index.tsx"),
|
|
263
|
+
path.join(APP_DIR, "index.jsx"),
|
|
264
|
+
];
|
|
265
|
+
|
|
266
|
+
for (const appPath of possiblePaths) {
|
|
267
|
+
if (fsSync.existsSync(appPath)) {
|
|
268
|
+
return appPath;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
async function buildAppEntrypoints() {
|
|
276
|
+
// First check for root App file (VaderJS standard)
|
|
277
|
+
const appFile = findAppFile();
|
|
278
|
+
|
|
279
|
+
if (appFile) {
|
|
280
|
+
logger.info(`Building App from: ${appFile}`);
|
|
281
|
+
|
|
282
|
+
await build({
|
|
283
|
+
entrypoints: [appFile],
|
|
284
|
+
outdir: DIST_DIR,
|
|
285
|
+
target: "browser",
|
|
286
|
+
jsxFactory: "e",
|
|
287
|
+
jsxFragment: "Fragment",
|
|
288
|
+
jsxImportSource: "vaderjs",
|
|
289
|
+
naming: "index.js",
|
|
290
|
+
external: [], // Bundle everything for website
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
const html = `<!DOCTYPE html>
|
|
294
|
+
<html>
|
|
295
|
+
<head>
|
|
296
|
+
<meta charset="UTF-8"/>
|
|
297
|
+
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
|
298
|
+
<title>Vader App</title>
|
|
299
|
+
</head>
|
|
300
|
+
<body>
|
|
301
|
+
<div id="app"></div>
|
|
302
|
+
<script type="module" src="/index.js"></script>
|
|
303
|
+
</body>
|
|
304
|
+
</html>`;
|
|
305
|
+
|
|
306
|
+
await fs.writeFile(path.join(DIST_DIR, "index.html"), html);
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Fallback to app directory structure
|
|
311
|
+
if (!fsSync.existsSync(APP_DIR)) {
|
|
312
|
+
logger.warn("No App.tsx or app directory found");
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const entries = fsSync
|
|
317
|
+
.readdirSync(APP_DIR, { recursive: true })
|
|
318
|
+
.filter((f) => /index\.(tsx|jsx)$/.test(f as string))
|
|
319
|
+
.map((f) => ({
|
|
320
|
+
name:
|
|
321
|
+
path.dirname(f as string) === "."
|
|
322
|
+
? "index"
|
|
323
|
+
: path.dirname(f as string),
|
|
324
|
+
path: path.join(APP_DIR, f as string),
|
|
325
|
+
}));
|
|
326
|
+
|
|
327
|
+
for (const entry of entries) {
|
|
328
|
+
var outDir = path.join(DIST_DIR, entry.name === "index" ? "" : entry.name);
|
|
329
|
+
|
|
330
|
+
await fs.mkdir(outDir, { recursive: true });
|
|
331
|
+
console.log("Building entrypoint:", entry.path);
|
|
332
|
+
await build({
|
|
333
|
+
entrypoints: [entry.path],
|
|
334
|
+
outdir: outDir,
|
|
335
|
+
target: "browser",
|
|
336
|
+
jsxFactory: "e",
|
|
337
|
+
jsxFragment: "Fragment",
|
|
338
|
+
jsxImportSource: "vaderjs",
|
|
339
|
+
external: [], // Bundle everything for website
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
const html = `<!DOCTYPE html>
|
|
343
|
+
<html>
|
|
344
|
+
<head>
|
|
345
|
+
<meta charset="UTF-8"/>
|
|
346
|
+
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
|
347
|
+
<title>Vader App</title>
|
|
348
|
+
</head>
|
|
349
|
+
<body>
|
|
350
|
+
<div id="app"></div>
|
|
351
|
+
<script type="module" src="/index.js"></script>
|
|
352
|
+
</body>
|
|
353
|
+
</html>`;
|
|
354
|
+
|
|
355
|
+
await fs.writeFile(path.join(outDir, "index.html"), html);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
async function buildAll(dev = false) {
|
|
360
|
+
const start = performance.now();
|
|
361
|
+
|
|
362
|
+
// Ensure jsconfig.json exists before building
|
|
363
|
+
await ensureJSConfig();
|
|
364
|
+
|
|
365
|
+
if (fsSync.existsSync(DIST_DIR)) {
|
|
366
|
+
await fs.rm(DIST_DIR, { recursive: true, force: true });
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
await fs.mkdir(DIST_DIR, { recursive: true });
|
|
370
|
+
|
|
371
|
+
await timedStep("Build Vader Core", buildVaderCore);
|
|
372
|
+
await timedStep("Build Src", buildSrc);
|
|
373
|
+
await timedStep("Copy Public", copyPublicAssets);
|
|
374
|
+
await timedStep("Build App", buildAppEntrypoints);
|
|
375
|
+
|
|
376
|
+
logger.success(
|
|
377
|
+
`Build finished in ${(performance.now() - start).toFixed(1)}ms`
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// --- DEV SERVER ---
|
|
382
|
+
|
|
383
|
+
async function runDevServer() {
|
|
384
|
+
await buildAll(true);
|
|
385
|
+
|
|
386
|
+
const clients = new Set<any>();
|
|
387
|
+
|
|
388
|
+
const port = config.port || 3000;
|
|
389
|
+
|
|
390
|
+
const server = serve({
|
|
391
|
+
port,
|
|
392
|
+
|
|
393
|
+
fetch(req, server) {
|
|
394
|
+
const url = new URL(req.url);
|
|
395
|
+
|
|
396
|
+
if (url.pathname === "/__hmr" && server.upgrade(req)) return;
|
|
397
|
+
|
|
398
|
+
let filePath = path.join(DIST_DIR, url.pathname);
|
|
399
|
+
|
|
400
|
+
if (!path.extname(filePath)) {
|
|
401
|
+
filePath = path.join(filePath, "index.html");
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// Ensure we're serving from dist directory
|
|
405
|
+
if (url.pathname === "/" || url.pathname === "") {
|
|
406
|
+
filePath = path.join(DIST_DIR, "index.html");
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
console.log("Serving:", filePath);
|
|
410
|
+
|
|
411
|
+
const file = Bun.file(filePath);
|
|
412
|
+
|
|
413
|
+
return file.exists().then((exists) =>
|
|
414
|
+
exists
|
|
415
|
+
? new Response(file)
|
|
416
|
+
: new Response("Not Found", { status: 404 })
|
|
417
|
+
);
|
|
418
|
+
},
|
|
419
|
+
|
|
420
|
+
websocket: {
|
|
421
|
+
open(ws) {
|
|
422
|
+
clients.add(ws);
|
|
423
|
+
},
|
|
424
|
+
close(ws) {
|
|
425
|
+
clients.delete(ws);
|
|
426
|
+
},
|
|
427
|
+
},
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
watcher.watch(APP_DIR);
|
|
431
|
+
watcher.watch(SRC_DIR);
|
|
432
|
+
watcher.watch(PUBLIC_DIR);
|
|
433
|
+
|
|
434
|
+
// Also watch for root App file
|
|
435
|
+
const rootAppDir = path.dirname(findAppFile() || "");
|
|
436
|
+
if (rootAppDir && rootAppDir !== PROJECT_ROOT) {
|
|
437
|
+
watcher.watch(rootAppDir);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
watcher.onChange(async () => {
|
|
441
|
+
logger.info("Changes detected, rebuilding...");
|
|
442
|
+
await buildAll(true);
|
|
443
|
+
|
|
444
|
+
for (const c of clients) c.send("reload");
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
logger.success(`Dev server running http://localhost:${port}`);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// --- PROD SERVER ---
|
|
451
|
+
|
|
452
|
+
async function runProdServer() {
|
|
453
|
+
const port = config.port || 3000;
|
|
454
|
+
|
|
455
|
+
const server = serve({
|
|
456
|
+
port,
|
|
457
|
+
fetch(req) {
|
|
458
|
+
const url = new URL(req.url);
|
|
459
|
+
let filePath = path.join(DIST_DIR, url.pathname);
|
|
460
|
+
|
|
461
|
+
if (!path.extname(filePath)) {
|
|
462
|
+
filePath = path.join(filePath, "index.html");
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
if (url.pathname === "/" || url.pathname === "") {
|
|
466
|
+
filePath = path.join(DIST_DIR, "index.html");
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
const file = Bun.file(filePath);
|
|
470
|
+
|
|
471
|
+
return file.exists().then((exists) =>
|
|
472
|
+
exists
|
|
473
|
+
? new Response(file)
|
|
474
|
+
: new Response("Not Found", { status: 404 })
|
|
475
|
+
);
|
|
476
|
+
},
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
logger.success(`Serving production http://localhost:${port}`);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// --- CLI ENTRY ---
|
|
483
|
+
|
|
484
|
+
async function main() {
|
|
485
|
+
console.log(`${colors.magenta}
|
|
486
|
+
__ __ ____ ____ _______ __
|
|
487
|
+
| | / |/ __ \\ / __ \\ / ____/ |/ /
|
|
488
|
+
| | / / / / // /_/ // /___ | /
|
|
489
|
+
| | / / /_/ / \\____// /___ / |
|
|
490
|
+
|____/____/_____/ /_____/ |_| |_|
|
|
491
|
+
${colors.reset}`);
|
|
492
|
+
|
|
493
|
+
const cmd = process.argv[2];
|
|
494
|
+
|
|
495
|
+
if (cmd === "init") {
|
|
496
|
+
await initProject(process.argv[3]);
|
|
497
|
+
// Also create jsconfig.json when initializing a new project
|
|
498
|
+
await ensureJSConfig();
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
config = await loadConfig();
|
|
503
|
+
config.port ||= 3000;
|
|
504
|
+
|
|
505
|
+
switch (cmd) {
|
|
506
|
+
case "dev":
|
|
507
|
+
await runDevServer();
|
|
508
|
+
break;
|
|
509
|
+
|
|
510
|
+
case "build":
|
|
511
|
+
await buildAll(false);
|
|
512
|
+
break;
|
|
513
|
+
|
|
514
|
+
case "serve":
|
|
515
|
+
await buildAll(false);
|
|
516
|
+
await runProdServer();
|
|
517
|
+
break;
|
|
518
|
+
|
|
519
|
+
default:
|
|
520
|
+
logger.info(`
|
|
521
|
+
Commands:
|
|
522
|
+
dev Start development server with hot reload
|
|
523
|
+
build Build for production
|
|
524
|
+
serve Build and serve production build
|
|
525
|
+
init Initialize a new VaderJS project
|
|
526
|
+
|
|
527
|
+
Make sure you have:
|
|
528
|
+
- App.tsx or App.jsx in your project root
|
|
529
|
+
- OR an app/ directory with index.tsx/jsx files
|
|
530
|
+
- vaderjs installed as a dependency
|
|
531
|
+
`);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
main();
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "vaderjs",
|
|
3
|
-
"version": "2.3.
|
|
4
|
-
"description": "A simple and powerful JavaScript library for building modern web applications.",
|
|
5
|
-
"bin": {
|
|
6
|
-
"vaderjs": "./main.
|
|
7
|
-
},
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "https://github.com/Postr-Inc/Vader.js"
|
|
11
|
-
},
|
|
12
|
-
"license": "MIT",
|
|
13
|
-
"dependencies": {
|
|
14
|
-
"ansi-colors": "latest"
|
|
15
|
-
}
|
|
16
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "vaderjs",
|
|
3
|
+
"version": "2.3.15",
|
|
4
|
+
"description": "A simple and powerful JavaScript library for building modern web applications.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"vaderjs": "./main.ts"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/Postr-Inc/Vader.js"
|
|
11
|
+
},
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"ansi-colors": "latest"
|
|
15
|
+
}
|
|
16
|
+
}
|
package/plugins/index.ts
CHANGED
|
@@ -1,72 +1,72 @@
|
|
|
1
|
-
// vaderPlugin.d.ts
|
|
2
|
-
|
|
3
|
-
/** The API object passed to plugin hooks */
|
|
4
|
-
export interface VaderAPI {
|
|
5
|
-
/** Run a shell command (string or string[]) and wait for it to finish */
|
|
6
|
-
runCommand(cmd: string | string[]): Promise<void>;
|
|
7
|
-
|
|
8
|
-
/** Inject arbitrary HTML into the <head> of generated index.html files */
|
|
9
|
-
injectHTML(content: string): void;
|
|
10
|
-
|
|
11
|
-
/** Log a message prefixed with [Vader Plugin] */
|
|
12
|
-
log : {
|
|
13
|
-
warn: (msg: any) => void,
|
|
14
|
-
info: (msg: any) => void,
|
|
15
|
-
error: (msg: any) => void,
|
|
16
|
-
success: (msg: any) => void,
|
|
17
|
-
step: (msg: any) => void
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** Get absolute path to the project root */
|
|
21
|
-
getProjectRoot(): string;
|
|
22
|
-
|
|
23
|
-
/** Get absolute path to the dist output directory */
|
|
24
|
-
getDistDir(): string;
|
|
25
|
-
|
|
26
|
-
/** Get absolute path to the public assets directory */
|
|
27
|
-
getPublicDir(): string;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/** Supported plugin hook names */
|
|
31
|
-
export type PluginHookName =
|
|
32
|
-
| "onBuildStart"
|
|
33
|
-
| "onBuildFinish"
|
|
34
|
-
| "onWatchStart"
|
|
35
|
-
| "onWatchStop"
|
|
36
|
-
| "onServeStart"
|
|
37
|
-
| "onServeStop"
|
|
38
|
-
| "onFileChange";
|
|
39
|
-
|
|
40
|
-
/** Interface for a single plugin */
|
|
41
|
-
export interface VaderPlugin {
|
|
42
|
-
name: string;
|
|
43
|
-
description: string;
|
|
44
|
-
version: string;
|
|
45
|
-
/** Called before build starts */
|
|
46
|
-
onBuildStart?(api: VaderAPI): Promise<void> | void;
|
|
47
|
-
|
|
48
|
-
/** Called after build finishes */
|
|
49
|
-
onBuildFinish?(api: VaderAPI): Promise<void> | void;
|
|
50
|
-
|
|
51
|
-
/** Called when watcher starts (dev mode) */
|
|
52
|
-
onWatchStart?(api: VaderAPI): Promise<void> | void;
|
|
53
|
-
|
|
54
|
-
/** Called when watcher stops (dev mode) */
|
|
55
|
-
onWatchStop?(api: VaderAPI): Promise<void> | void;
|
|
56
|
-
|
|
57
|
-
/** Called when dev server starts */
|
|
58
|
-
onServeStart?(api: VaderAPI): Promise<void> | void;
|
|
59
|
-
|
|
60
|
-
/** Called when dev server stops */
|
|
61
|
-
onServeStop?(api: VaderAPI): Promise<void> | void;
|
|
62
|
-
|
|
63
|
-
/** Called on file change during watch, with changed file path */
|
|
64
|
-
onFileChange?(api: VaderAPI, filePath: string): Promise<void> | void;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/** User config type */
|
|
68
|
-
export interface VaderConfig {
|
|
69
|
-
port?: number;
|
|
70
|
-
host_provider?: string;
|
|
71
|
-
plugins?: VaderPlugin[];
|
|
72
|
-
}
|
|
1
|
+
// vaderPlugin.d.ts
|
|
2
|
+
|
|
3
|
+
/** The API object passed to plugin hooks */
|
|
4
|
+
export interface VaderAPI {
|
|
5
|
+
/** Run a shell command (string or string[]) and wait for it to finish */
|
|
6
|
+
runCommand(cmd: string | string[]): Promise<void>;
|
|
7
|
+
|
|
8
|
+
/** Inject arbitrary HTML into the <head> of generated index.html files */
|
|
9
|
+
injectHTML(content: string): void;
|
|
10
|
+
|
|
11
|
+
/** Log a message prefixed with [Vader Plugin] */
|
|
12
|
+
log : {
|
|
13
|
+
warn: (msg: any) => void,
|
|
14
|
+
info: (msg: any) => void,
|
|
15
|
+
error: (msg: any) => void,
|
|
16
|
+
success: (msg: any) => void,
|
|
17
|
+
step: (msg: any) => void
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Get absolute path to the project root */
|
|
21
|
+
getProjectRoot(): string;
|
|
22
|
+
|
|
23
|
+
/** Get absolute path to the dist output directory */
|
|
24
|
+
getDistDir(): string;
|
|
25
|
+
|
|
26
|
+
/** Get absolute path to the public assets directory */
|
|
27
|
+
getPublicDir(): string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Supported plugin hook names */
|
|
31
|
+
export type PluginHookName =
|
|
32
|
+
| "onBuildStart"
|
|
33
|
+
| "onBuildFinish"
|
|
34
|
+
| "onWatchStart"
|
|
35
|
+
| "onWatchStop"
|
|
36
|
+
| "onServeStart"
|
|
37
|
+
| "onServeStop"
|
|
38
|
+
| "onFileChange";
|
|
39
|
+
|
|
40
|
+
/** Interface for a single plugin */
|
|
41
|
+
export interface VaderPlugin {
|
|
42
|
+
name: string;
|
|
43
|
+
description: string;
|
|
44
|
+
version: string;
|
|
45
|
+
/** Called before build starts */
|
|
46
|
+
onBuildStart?(api: VaderAPI): Promise<void> | void;
|
|
47
|
+
|
|
48
|
+
/** Called after build finishes */
|
|
49
|
+
onBuildFinish?(api: VaderAPI): Promise<void> | void;
|
|
50
|
+
|
|
51
|
+
/** Called when watcher starts (dev mode) */
|
|
52
|
+
onWatchStart?(api: VaderAPI): Promise<void> | void;
|
|
53
|
+
|
|
54
|
+
/** Called when watcher stops (dev mode) */
|
|
55
|
+
onWatchStop?(api: VaderAPI): Promise<void> | void;
|
|
56
|
+
|
|
57
|
+
/** Called when dev server starts */
|
|
58
|
+
onServeStart?(api: VaderAPI): Promise<void> | void;
|
|
59
|
+
|
|
60
|
+
/** Called when dev server stops */
|
|
61
|
+
onServeStop?(api: VaderAPI): Promise<void> | void;
|
|
62
|
+
|
|
63
|
+
/** Called on file change during watch, with changed file path */
|
|
64
|
+
onFileChange?(api: VaderAPI, filePath: string): Promise<void> | void;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** User config type */
|
|
68
|
+
export interface VaderConfig {
|
|
69
|
+
port?: number;
|
|
70
|
+
host_provider?: string;
|
|
71
|
+
plugins?: VaderPlugin[];
|
|
72
|
+
}
|