vaderjs 2.3.4 → 2.3.5
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/main.js +101 -52
- package/package.json +1 -1
package/main.js
CHANGED
|
@@ -1,15 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
|
|
3
|
-
* VaderJS Build & Development Script
|
|
4
|
-
*
|
|
5
|
-
* This script handles building the VaderJS framework, your application code,
|
|
6
|
-
* and serving it in a local development environment with live reloading.
|
|
7
|
-
*
|
|
8
|
-
* Commands:
|
|
9
|
-
* bun run vaderjs build - Builds the project for production.
|
|
10
|
-
* bun run vaderjs dev - Starts the dev server with HMR and file watching.
|
|
11
|
-
* bun run vaderjs serve - Builds and serves the production output.
|
|
12
|
-
*/
|
|
2
|
+
|
|
13
3
|
|
|
14
4
|
import { build, serve } from "bun";
|
|
15
5
|
import fs from "fs/promises";
|
|
@@ -93,9 +83,10 @@ const vaderAPI = {
|
|
|
93
83
|
|
|
94
84
|
async function loadConfig() {
|
|
95
85
|
try {
|
|
96
|
-
const configModule = await import(path.join(PROJECT_ROOT, "vaderjs.config.js"));
|
|
86
|
+
const configModule = await import(path.join(PROJECT_ROOT, "vaderjs.config.js"));
|
|
97
87
|
return configModule.default || configModule;
|
|
98
88
|
} catch {
|
|
89
|
+
console.log(path.join(PROJECT_ROOT, "vaderjs.config.js"))
|
|
99
90
|
logger.warn("No 'vader.config.js' found, using defaults.");
|
|
100
91
|
return {};
|
|
101
92
|
}
|
|
@@ -149,10 +140,43 @@ async function buildVaderCore() {
|
|
|
149
140
|
function patchHooksUsage(code) {
|
|
150
141
|
return code.replace(/import\s+{[^}]*use(State|Effect|Memo|Navigation)[^}]*}\s+from\s+['"]vaderjs['"];?\n?/g, "");
|
|
151
142
|
}
|
|
143
|
+
function publicAssetPlugin() {
|
|
144
|
+
return {
|
|
145
|
+
name: "public-asset-replacer",
|
|
146
|
+
setup(build) {
|
|
147
|
+
build.onLoad({ filter: /\.(js|ts|jsx|tsx|html)$/ }, async (args) => {
|
|
148
|
+
let code = await fs.readFile(args.path, "utf8");
|
|
149
|
+
|
|
150
|
+
code = code.replace(/\{\{public:(.+?)\}\}/g, (_, relPath) => {
|
|
151
|
+
const absPath = path.join(PUBLIC_DIR, relPath.trim());
|
|
152
|
+
if (fsSync.existsSync(absPath)) {
|
|
153
|
+
return "/" + relPath.trim().replace(/\\/g, "/");
|
|
154
|
+
}
|
|
155
|
+
logger.warn(`Public asset not found: ${relPath}`);
|
|
156
|
+
return relPath;
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
contents: code,
|
|
161
|
+
loader: args.path.endsWith(".html")
|
|
162
|
+
? "text"
|
|
163
|
+
: args.path.endsWith(".tsx")
|
|
164
|
+
? "tsx"
|
|
165
|
+
: args.path.endsWith(".jsx")
|
|
166
|
+
? "jsx"
|
|
167
|
+
: args.path.endsWith(".ts")
|
|
168
|
+
? "ts"
|
|
169
|
+
: "js",
|
|
170
|
+
};
|
|
171
|
+
});
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
}
|
|
152
175
|
|
|
153
176
|
/**
|
|
154
177
|
* Step 3: Pre-processes all files in `/src` into a temporary directory.
|
|
155
178
|
*/
|
|
179
|
+
|
|
156
180
|
async function preprocessSources(srcDir, tempDir) {
|
|
157
181
|
await fs.mkdir(tempDir, { recursive: true });
|
|
158
182
|
for (const entry of await fs.readdir(srcDir, { withFileTypes: true })) {
|
|
@@ -163,7 +187,7 @@ async function preprocessSources(srcDir, tempDir) {
|
|
|
163
187
|
await preprocessSources(srcPath, destPath);
|
|
164
188
|
} else if (/\.(tsx|jsx|ts|js)$/.test(entry.name)) {
|
|
165
189
|
let content = await fs.readFile(srcPath, "utf8");
|
|
166
|
-
content = patchHooksUsage(content);
|
|
190
|
+
content = patchHooksUsage(content);
|
|
167
191
|
await fs.writeFile(destPath, content);
|
|
168
192
|
} else {
|
|
169
193
|
await fs.copyFile(srcPath, destPath);
|
|
@@ -201,6 +225,9 @@ async function buildSrc() {
|
|
|
201
225
|
jsxImportSource: "vaderjs",
|
|
202
226
|
target: "browser",
|
|
203
227
|
minify: false,
|
|
228
|
+
plugins: [
|
|
229
|
+
publicAssetPlugin(),
|
|
230
|
+
],
|
|
204
231
|
external: ["vaderjs"],
|
|
205
232
|
});
|
|
206
233
|
}
|
|
@@ -222,57 +249,61 @@ async function copyPublicAssets() {
|
|
|
222
249
|
return;
|
|
223
250
|
}
|
|
224
251
|
|
|
225
|
-
// Ensure the dist directory exists
|
|
226
252
|
if (!fsSync.existsSync(DIST_DIR)) {
|
|
227
253
|
await fs.mkdir(DIST_DIR, { recursive: true });
|
|
228
254
|
}
|
|
229
255
|
|
|
230
|
-
const devClientScript = isDev
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
256
|
+
const devClientScript = isDev
|
|
257
|
+
? `<script>
|
|
258
|
+
new WebSocket("ws://" + location.host + "/__hmr").onmessage = (msg) => {
|
|
259
|
+
if (msg.data === "reload") location.reload();
|
|
260
|
+
};
|
|
261
|
+
</script>`
|
|
262
|
+
: "";
|
|
236
263
|
|
|
237
264
|
const entries = fsSync.readdirSync(APP_DIR, { recursive: true })
|
|
238
265
|
.filter(file => /index\.(jsx|tsx)$/.test(file))
|
|
239
266
|
.map(file => ({
|
|
240
|
-
|
|
241
|
-
|
|
267
|
+
name: path.dirname(file) === '.' ? 'index' : path.dirname(file).replace(/\\/g, '/'),
|
|
268
|
+
path: path.join(APP_DIR, file)
|
|
242
269
|
}));
|
|
243
270
|
|
|
271
|
+
// Helper to resolve any asset path from /public
|
|
272
|
+
function resolvePublicPath(p) {
|
|
273
|
+
const assetPath = p.replace(/^(\.\/|\/)/, ""); // strip leading ./ or /
|
|
274
|
+
const absPath = path.join(PUBLIC_DIR, assetPath);
|
|
275
|
+
if (fsSync.existsSync(absPath)) {
|
|
276
|
+
return "/" + assetPath.replace(/\\/g, "/");
|
|
277
|
+
}
|
|
278
|
+
return p; // leave unchanged if not in public
|
|
279
|
+
}
|
|
280
|
+
|
|
244
281
|
for (const { name, path: entryPath } of entries) {
|
|
245
|
-
// Check for the specific case where 'name' could be 'index.js' and prevent duplication
|
|
246
282
|
const outDir = path.join(DIST_DIR, name === 'index' ? '' : name);
|
|
247
|
-
const outJsPath = path.join(outDir, 'index.js');
|
|
248
|
-
|
|
249
|
-
// Ensure the output directory exists
|
|
283
|
+
const outJsPath = path.join(outDir, 'index.js');
|
|
250
284
|
await fs.mkdir(outDir, { recursive: true });
|
|
251
285
|
|
|
252
|
-
//
|
|
286
|
+
// --- CSS HANDLING ---
|
|
253
287
|
const cssLinks = [];
|
|
254
|
-
|
|
255
|
-
const cssImports = [...
|
|
256
|
-
|
|
288
|
+
let content = await fs.readFile(entryPath, "utf8");
|
|
289
|
+
const cssImports = [...content.matchAll(/import\s+['"](.*\.css)['"]/g)];
|
|
257
290
|
for (const match of cssImports) {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
logger.warn(`CSS file not found: ${sourceCssPath}`);
|
|
271
|
-
}
|
|
291
|
+
const cssImportPath = match[1];
|
|
292
|
+
const sourceCssPath = path.resolve(path.dirname(entryPath), cssImportPath);
|
|
293
|
+
if (fsSync.existsSync(sourceCssPath)) {
|
|
294
|
+
const relativeCssPath = path.relative(APP_DIR, sourceCssPath);
|
|
295
|
+
const destCssPath = path.join(DIST_DIR, relativeCssPath);
|
|
296
|
+
await fs.mkdir(path.dirname(destCssPath), { recursive: true });
|
|
297
|
+
await fs.copyFile(sourceCssPath, destCssPath);
|
|
298
|
+
const htmlRelativePath = path.relative(outDir, destCssPath).replace(/\\/g, '/');
|
|
299
|
+
cssLinks.push(`<link rel="stylesheet" href="${htmlRelativePath}">`);
|
|
300
|
+
} else {
|
|
301
|
+
logger.warn(`CSS file not found: ${sourceCssPath}`);
|
|
302
|
+
}
|
|
272
303
|
}
|
|
273
304
|
|
|
274
|
-
//
|
|
275
|
-
|
|
305
|
+
// --- HTML GENERATION ---
|
|
306
|
+
let htmlContent = `<!DOCTYPE html>
|
|
276
307
|
<html lang="en">
|
|
277
308
|
<head>
|
|
278
309
|
<meta charset="UTF-8" />
|
|
@@ -286,37 +317,54 @@ async function copyPublicAssets() {
|
|
|
286
317
|
<script type="module">
|
|
287
318
|
import App from '${name !== 'index' ? "/" + name : ''}/index.js';
|
|
288
319
|
import * as Vader from '/src/vader/index.js';
|
|
289
|
-
window.Vader = Vader
|
|
320
|
+
window.Vader = Vader;
|
|
290
321
|
Vader.render(Vader.createElement(App, null), document.getElementById("app"));
|
|
291
322
|
</script>
|
|
292
323
|
${devClientScript}
|
|
293
324
|
</body>
|
|
294
325
|
</html>`;
|
|
295
326
|
|
|
296
|
-
|
|
327
|
+
// --- FIX ASSET PATHS IN HTML ---
|
|
328
|
+
htmlContent = htmlContent.replace(
|
|
329
|
+
/(["'(])([^"'()]+?\.(png|jpe?g|gif|svg|webp|ico))(["')])/gi,
|
|
330
|
+
(match, p1, assetPath, ext, p4) => p1 + resolvePublicPath(assetPath) + p4
|
|
331
|
+
);
|
|
297
332
|
|
|
298
|
-
|
|
333
|
+
await fs.writeFile(path.join(outDir, "index.html"), htmlContent);
|
|
299
334
|
|
|
300
|
-
//
|
|
335
|
+
// --- JS BUILD ---
|
|
301
336
|
await build({
|
|
302
337
|
entrypoints: [entryPath],
|
|
303
|
-
outdir: outDir,
|
|
338
|
+
outdir: outDir,
|
|
304
339
|
target: "browser",
|
|
305
340
|
minify: false,
|
|
306
341
|
sourcemap: "external",
|
|
307
342
|
external: ["vaderjs"],
|
|
308
343
|
jsxFactory: "e",
|
|
309
344
|
jsxFragment: "Fragment",
|
|
345
|
+
plugins: [
|
|
346
|
+
publicAssetPlugin(),
|
|
347
|
+
],
|
|
310
348
|
jsxImportSource: "vaderjs",
|
|
311
349
|
});
|
|
312
350
|
|
|
313
|
-
//
|
|
351
|
+
// --- FIX IMPORT PATHS IN JS ---
|
|
314
352
|
let jsContent = await fs.readFile(outJsPath, "utf8");
|
|
353
|
+
|
|
354
|
+
// Vader import fix
|
|
315
355
|
jsContent = jsContent.replace(/from\s+['"]vaderjs['"]/g, `from '/src/vader/index.js'`);
|
|
356
|
+
|
|
357
|
+
// Asset path fix for JS
|
|
358
|
+
jsContent = jsContent.replace(
|
|
359
|
+
/(["'(])([^"'()]+?\.(png|jpe?g|gif|svg|webp|ico))(["')])/gi,
|
|
360
|
+
(match, p1, assetPath, ext, p4) => p1 + resolvePublicPath(assetPath) + p4
|
|
361
|
+
);
|
|
362
|
+
|
|
316
363
|
await fs.writeFile(outJsPath, jsContent);
|
|
317
364
|
}
|
|
318
365
|
}
|
|
319
366
|
|
|
367
|
+
|
|
320
368
|
|
|
321
369
|
|
|
322
370
|
async function buildAll(isDev = false) {
|
|
@@ -442,6 +490,7 @@ console.log(banner);
|
|
|
442
490
|
const command = process.argv[2];
|
|
443
491
|
|
|
444
492
|
if (command === "dev") {
|
|
493
|
+
globalThis.isDev = true
|
|
445
494
|
await runDevServer();
|
|
446
495
|
} else if (command === "build") {
|
|
447
496
|
await buildAll(false);
|