@celsian/vura-cli 0.6.0 → 0.6.1
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/dist/commands/build.js +63 -19
- package/dist/commands/dev.js +4 -1
- package/package.json +4 -4
package/dist/commands/build.js
CHANGED
|
@@ -11,9 +11,11 @@
|
|
|
11
11
|
* 8. Write manifest.json
|
|
12
12
|
* 9. Emit hot deploy templates (Dockerfile, fly.toml, package.json) when hot routes present
|
|
13
13
|
*/
|
|
14
|
-
import { buildManifest, build, renderStaticPages, generateClientPageEntry } from '@celsian/vura-core';
|
|
14
|
+
import { buildManifest, build, renderStaticPages, generateClientPageEntry, vuraBrowserResolvePlugin } from '@celsian/vura-core';
|
|
15
15
|
import { createRequire } from 'node:module';
|
|
16
|
-
import {
|
|
16
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
17
|
+
import { join as pathJoin, resolve as pathResolve } from 'node:path';
|
|
18
|
+
import { pathToFileURL } from 'node:url';
|
|
17
19
|
import { loadConfig } from '../config-loader.js';
|
|
18
20
|
// ---------------------------------------------------------------------------
|
|
19
21
|
// Deploy template strings — inlined so they survive tsc compilation (tsc does
|
|
@@ -60,7 +62,6 @@ kill_timeout = "30s"
|
|
|
60
62
|
min_machines_running = 1
|
|
61
63
|
`;
|
|
62
64
|
const nativeImport = (specifier) => import(/* @vite-ignore */ specifier);
|
|
63
|
-
const moduleSourceToDataUrl = (source) => `data:text/javascript;base64,${Buffer.from(source).toString('base64')}`;
|
|
64
65
|
/**
|
|
65
66
|
* Write dist/package.json.
|
|
66
67
|
*
|
|
@@ -86,7 +87,6 @@ async function emitDeployPackageJson(distDir, projectRoot, hasWsRoutes) {
|
|
|
86
87
|
const { writeFile, readFile, mkdir } = await import('node:fs/promises');
|
|
87
88
|
const { existsSync } = await import('node:fs');
|
|
88
89
|
const { join } = await import('node:path');
|
|
89
|
-
const { createRequire } = await import('node:module');
|
|
90
90
|
await mkdir(distDir, { recursive: true });
|
|
91
91
|
const pkgPath = join(distDir, 'package.json');
|
|
92
92
|
let existing = {};
|
|
@@ -99,7 +99,7 @@ async function emitDeployPackageJson(distDir, projectRoot, hasWsRoutes) {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
const deps = { ...(existing.dependencies ?? {}) };
|
|
102
|
-
const whatVersion = resolveWhatFrameworkVersion(
|
|
102
|
+
const whatVersion = resolveWhatFrameworkVersion(projectRoot);
|
|
103
103
|
if (whatVersion) {
|
|
104
104
|
deps['what-framework'] = whatVersion;
|
|
105
105
|
}
|
|
@@ -116,14 +116,34 @@ async function emitDeployPackageJson(distDir, projectRoot, hasWsRoutes) {
|
|
|
116
116
|
await writeFile(pkgPath, JSON.stringify(merged, null, 2) + '\n', 'utf8');
|
|
117
117
|
}
|
|
118
118
|
/** The exact what-framework version installed in the project, or null. */
|
|
119
|
-
function resolveWhatFrameworkVersion(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
119
|
+
function resolveWhatFrameworkVersion(projectRoot) {
|
|
120
|
+
// Read the installed package.json off disk instead of resolving the
|
|
121
|
+
// specifier. `require('what-framework/package.json')` looks like the obvious
|
|
122
|
+
// way to do this and cannot work: what-framework's `exports` map lists `.`,
|
|
123
|
+
// `./server`, `./router` and friends, and Node refuses any subpath an
|
|
124
|
+
// exports map does not name — including './package.json'. Every real install
|
|
125
|
+
// therefore threw ERR_PACKAGE_PATH_NOT_EXPORTED, the version came back null,
|
|
126
|
+
// and dist/package.json shipped without the dependency the container needs.
|
|
127
|
+
let dir = projectRoot;
|
|
128
|
+
for (let depth = 0; depth < 10; depth++) {
|
|
129
|
+
const candidate = pathJoin(dir, 'node_modules', 'what-framework', 'package.json');
|
|
130
|
+
if (existsSync(candidate)) {
|
|
131
|
+
try {
|
|
132
|
+
const manifest = JSON.parse(readFileSync(candidate, 'utf8'));
|
|
133
|
+
if (typeof manifest.version === 'string')
|
|
134
|
+
return manifest.version;
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
const parent = pathResolve(dir, '..');
|
|
142
|
+
if (parent === dir)
|
|
143
|
+
break;
|
|
144
|
+
dir = parent;
|
|
126
145
|
}
|
|
146
|
+
return null;
|
|
127
147
|
}
|
|
128
148
|
/**
|
|
129
149
|
* Emit Dockerfile and fly.toml into dist/ when the project has hot routes.
|
|
@@ -327,7 +347,10 @@ export async function buildCommand(_args) {
|
|
|
327
347
|
outfile: outPath,
|
|
328
348
|
jsx: 'automatic',
|
|
329
349
|
jsxImportSource,
|
|
330
|
-
|
|
350
|
+
// Browser-resolve first: a page that imports `@celsian/vura-core` for
|
|
351
|
+
// useLoaderData must get the pure client module here, not the package
|
|
352
|
+
// root, which reaches node:fs and cannot be bundled for a browser.
|
|
353
|
+
plugins: [vuraBrowserResolvePlugin(), esmResolvePlugin],
|
|
331
354
|
external: [],
|
|
332
355
|
});
|
|
333
356
|
const bundleHash = createHash('sha256')
|
|
@@ -355,23 +378,44 @@ export async function buildCommand(_args) {
|
|
|
355
378
|
console.log(` Rendering ${staticPages.length} build-time pages...`);
|
|
356
379
|
const tmpDir = join(root, 'dist', '.page-tmp');
|
|
357
380
|
await mkdir(tmpDir, { recursive: true });
|
|
381
|
+
// A build-time page is imported into THIS process and rendered by core's
|
|
382
|
+
// own `renderToString`. Two rules follow, and breaking either one produces
|
|
383
|
+
// a failure that looks like a framework bug rather than a bundling one:
|
|
384
|
+
//
|
|
385
|
+
// 1. `what-framework` and `@celsian/vura-core` stay external. Inlining
|
|
386
|
+
// them gives the page a second copy of the framework, with its own
|
|
387
|
+
// "currently rendering component" and its own context registry — so
|
|
388
|
+
// every hook the page calls, `useLoaderData` included, reads a
|
|
389
|
+
// registry that the renderer never wrote to and reports being called
|
|
390
|
+
// outside a render.
|
|
391
|
+
// 2. The bundle is written to a real file rather than imported as a
|
|
392
|
+
// `data:` URL. A data: module has no parent path, so it cannot resolve
|
|
393
|
+
// the bare specifiers rule 1 just created, and anything it does inline
|
|
394
|
+
// that calls `fileURLToPath(import.meta.url)` at module scope throws
|
|
395
|
+
// "The URL must be of scheme file".
|
|
396
|
+
const sharedRuntimeExternals = [
|
|
397
|
+
'what-framework',
|
|
398
|
+
'what-framework/*',
|
|
399
|
+
'@celsian/vura-core',
|
|
400
|
+
'@celsian/vura-core/*',
|
|
401
|
+
];
|
|
402
|
+
let pageModuleSeq = 0;
|
|
358
403
|
const loadModule = async (filePath) => {
|
|
359
404
|
const absPath = resolve(root, filePath);
|
|
360
|
-
const
|
|
405
|
+
const tmpFile = join(tmpDir, `page-${pageModuleSeq++}.mjs`);
|
|
406
|
+
await esbuild({
|
|
361
407
|
entryPoints: [absPath],
|
|
362
408
|
bundle: true,
|
|
363
409
|
format: 'esm',
|
|
364
410
|
target: 'es2022',
|
|
365
411
|
platform: 'node',
|
|
366
|
-
|
|
367
|
-
outfile: 'page.mjs',
|
|
412
|
+
outfile: tmpFile,
|
|
368
413
|
jsx: 'automatic',
|
|
369
414
|
jsxImportSource,
|
|
370
415
|
plugins: [esmResolvePlugin],
|
|
371
|
-
external:
|
|
416
|
+
external: sharedRuntimeExternals,
|
|
372
417
|
});
|
|
373
|
-
|
|
374
|
-
return nativeImport(moduleSourceToDataUrl(bundledSource));
|
|
418
|
+
return nativeImport(pathToFileURL(tmpFile).href);
|
|
375
419
|
};
|
|
376
420
|
const outDir = join(root, 'dist');
|
|
377
421
|
const rendered = await renderStaticPages(staticPages, loadModule, outDir, { clientScripts });
|
package/dist/commands/dev.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { renderToString as builtinRenderToString } from 'what-framework/server';
|
|
16
16
|
import { importRouteModule } from './shared.js';
|
|
17
|
-
import { buildManifest, compilePageRoutes, matchPageRoute, compileRoutes, matchApiPath, getLogger, wrapDocument, escapeHtml, parseNodeBody, reportError, getMimeType, runTaskOnce, buildTaskEnvelope, createApiApp, createWsUpgradeHandler, createNoServerWebSocketServer, GLOBAL_HOOKS_FILENAMES, nodeToWebRequest, writeWebResponse, generateClientPageEntry, } from '@celsian/vura-core';
|
|
17
|
+
import { buildManifest, compilePageRoutes, matchPageRoute, compileRoutes, matchApiPath, getLogger, wrapDocument, escapeHtml, parseNodeBody, reportError, getMimeType, runTaskOnce, buildTaskEnvelope, createApiApp, createWsUpgradeHandler, createNoServerWebSocketServer, GLOBAL_HOOKS_FILENAMES, nodeToWebRequest, writeWebResponse, generateClientPageEntry, vuraBrowserResolvePlugin, } from '@celsian/vura-core';
|
|
18
18
|
export function parseDevOptions(args, projectRoot = process.cwd()) {
|
|
19
19
|
const portArg = args.find((_, i) => args[i - 1] === '--port');
|
|
20
20
|
const hostArg = args.find((_, i) => args[i - 1] === '--host');
|
|
@@ -276,6 +276,9 @@ export async function startStandaloneServer(manifest, opts) {
|
|
|
276
276
|
outfile: 'page.js',
|
|
277
277
|
jsx: 'automatic',
|
|
278
278
|
jsxImportSource,
|
|
279
|
+
// Same redirect the production build applies: `@celsian/vura-core` in a
|
|
280
|
+
// browser bundle resolves to the pure client module.
|
|
281
|
+
plugins: [vuraBrowserResolvePlugin()],
|
|
279
282
|
nodePaths: [join(opts.projectRoot, 'node_modules')],
|
|
280
283
|
});
|
|
281
284
|
const text = result.outputFiles[0].text;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@celsian/vura-cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Vura CLI — build and deploy full-stack apps",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -15,12 +15,12 @@
|
|
|
15
15
|
"!dist/**/*.map"
|
|
16
16
|
],
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@celsian/vura-core": "0.6.
|
|
18
|
+
"@celsian/vura-core": "0.6.1",
|
|
19
19
|
"esbuild": "^0.28.1",
|
|
20
20
|
"what-framework": "^0.13.2"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
|
-
"@celsian/vura-adapter-vura": "0.6.
|
|
23
|
+
"@celsian/vura-adapter-vura": "0.6.1",
|
|
24
24
|
"ws": "^8.0.0"
|
|
25
25
|
},
|
|
26
26
|
"peerDependenciesMeta": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@celsian/vura-adapter-vura": "0.6.
|
|
35
|
+
"@celsian/vura-adapter-vura": "0.6.1",
|
|
36
36
|
"@types/ws": "^8.18.1",
|
|
37
37
|
"ws": "^8.21.0"
|
|
38
38
|
},
|