@rshono/core 1.0.0-rc.19 → 1.0.0-rc.20
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 +93 -2
- package/dist/builder/env-shadow-loader.cjs +41 -1
- package/dist/builder/page-entry-loader.cjs +28 -1
- package/dist/builder/page-files.d.ts +0 -1
- package/dist/builder/public-env.d.ts +0 -1
- package/dist/builder/react-versions.d.ts +0 -1
- package/dist/builder/rspack-config.d.ts +0 -1
- package/dist/builder/rspack-config.js +4 -0
- package/dist/builder/rspack-config.js.map +1 -1
- package/dist/builder/server-only-imports.d.ts +0 -1
- package/dist/cli/build.d.ts +0 -1
- package/dist/cli/build.js +37 -35
- package/dist/cli/build.js.map +1 -1
- package/dist/cli/dev.d.ts +0 -1
- package/dist/cli/dev.js +15 -1
- package/dist/cli/dev.js.map +1 -1
- package/dist/cli/exit.d.ts +12 -0
- package/dist/cli/exit.js +16 -0
- package/dist/cli/exit.js.map +1 -0
- package/dist/cli/index.d.ts +0 -1
- package/dist/cli/index.js +74 -20
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/start.d.ts +0 -1
- package/dist/cli/start.js +3 -2
- package/dist/cli/start.js.map +1 -1
- package/dist/config.d.ts +0 -1
- package/dist/deploy/aws-lambda/runtime.d.ts +0 -1
- package/dist/deploy/build-marker.d.ts +7 -2
- package/dist/deploy/build-marker.js +6 -0
- package/dist/deploy/build-marker.js.map +1 -1
- package/dist/deploy/cloudflare/build.d.ts +0 -1
- package/dist/deploy/cloudflare/build.js +6 -0
- package/dist/deploy/cloudflare/build.js.map +1 -1
- package/dist/deploy/cloudflare/runtime.d.ts +0 -1
- package/dist/deploy/cloudflare/runtime.js +24 -2
- package/dist/deploy/cloudflare/runtime.js.map +1 -1
- package/dist/deploy/contract.d.ts +20 -2
- package/dist/deploy/contract.js.map +1 -1
- package/dist/deploy/filesystem.d.ts +0 -1
- package/dist/deploy/node/runtime.d.ts +0 -1
- package/dist/deploy/presets.d.ts +7 -1
- package/dist/deploy/presets.js +13 -2
- package/dist/deploy/presets.js.map +1 -1
- package/dist/deploy/public-paths.d.ts +42 -0
- package/dist/deploy/public-paths.js +66 -0
- package/dist/deploy/public-paths.js.map +1 -0
- package/dist/deploy/vercel/build.d.ts +0 -1
- package/dist/deploy/vercel/build.js +6 -0
- package/dist/deploy/vercel/build.js.map +1 -1
- package/dist/deploy/vercel/runtime.d.ts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/router.d.ts +20 -5
- package/dist/router.js.map +1 -1
- package/dist/runtime/boundaries.d.ts +0 -1
- package/dist/runtime/client.d.ts +0 -1
- package/dist/runtime/context.d.ts +15 -2
- package/dist/runtime/context.js +15 -1
- package/dist/runtime/context.js.map +1 -1
- package/dist/runtime/control.d.ts +15 -1
- package/dist/runtime/control.js +17 -0
- package/dist/runtime/control.js.map +1 -1
- package/dist/runtime/dev-protocol.d.ts +0 -1
- package/dist/runtime/empty-server-app.d.ts +0 -1
- package/dist/runtime/entry.client.d.ts +0 -1
- package/dist/runtime/entry.client.js +31 -4
- package/dist/runtime/entry.client.js.map +1 -1
- package/dist/runtime/entry.rsc.d.ts +6 -4
- package/dist/runtime/entry.rsc.js +473 -56
- package/dist/runtime/entry.rsc.js.map +1 -1
- package/dist/runtime/entry.ssr.d.ts +19 -5
- package/dist/runtime/entry.ssr.js +22 -47
- package/dist/runtime/entry.ssr.js.map +1 -1
- package/dist/runtime/failure-document.d.ts +11 -0
- package/dist/runtime/failure-document.js +35 -0
- package/dist/runtime/failure-document.js.map +1 -0
- package/dist/runtime/flight-inject.d.ts +0 -1
- package/dist/runtime/flight-inject.js +15 -9
- package/dist/runtime/flight-inject.js.map +1 -1
- package/dist/runtime/hot-update.d.ts +0 -1
- package/dist/runtime/navigation.d.ts +6 -1
- package/dist/runtime/navigation.js +6 -0
- package/dist/runtime/navigation.js.map +1 -1
- package/dist/runtime/request.d.ts +23 -1
- package/dist/runtime/request.js +39 -0
- package/dist/runtime/request.js.map +1 -1
- package/dist/runtime/server.d.ts +0 -1
- package/dist/runtime/validate-entries.d.ts +0 -1
- package/dist/runtime/validate-entries.js +114 -10
- package/dist/runtime/validate-entries.js.map +1 -1
- package/dist/server/headers.d.ts +37 -4
- package/dist/server/headers.js +49 -13
- package/dist/server/headers.js.map +1 -1
- package/dist/server/load-config.d.ts +0 -1
- package/dist/server/load-env.d.ts +0 -1
- package/dist/server/prerendered.d.ts +14 -2
- package/dist/server/prerendered.js +42 -4
- package/dist/server/prerendered.js.map +1 -1
- package/dist/server/server-config.d.ts +0 -1
- package/dist/server/shutdown.d.ts +0 -1
- package/dist/server/ssg.d.ts +6 -1
- package/dist/server/ssg.js +30 -7
- package/dist/server/ssg.js.map +1 -1
- package/dist/server/static.d.ts +0 -1
- package/dist/server/static.js +5 -5
- package/dist/server/static.js.map +1 -1
- package/package.json +1 -1
- package/dist/builder/page-files.d.ts.map +0 -1
- package/dist/builder/public-env.d.ts.map +0 -1
- package/dist/builder/react-versions.d.ts.map +0 -1
- package/dist/builder/rspack-config.d.ts.map +0 -1
- package/dist/builder/server-only-imports.d.ts.map +0 -1
- package/dist/cli/build.d.ts.map +0 -1
- package/dist/cli/dev.d.ts.map +0 -1
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/start.d.ts.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/deploy/aws-lambda/runtime.d.ts.map +0 -1
- package/dist/deploy/build-marker.d.ts.map +0 -1
- package/dist/deploy/cloudflare/build.d.ts.map +0 -1
- package/dist/deploy/cloudflare/runtime.d.ts.map +0 -1
- package/dist/deploy/contract.d.ts.map +0 -1
- package/dist/deploy/filesystem.d.ts.map +0 -1
- package/dist/deploy/node/runtime.d.ts.map +0 -1
- package/dist/deploy/presets.d.ts.map +0 -1
- package/dist/deploy/vercel/build.d.ts.map +0 -1
- package/dist/deploy/vercel/runtime.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/router.d.ts.map +0 -1
- package/dist/runtime/boundaries.d.ts.map +0 -1
- package/dist/runtime/client.d.ts.map +0 -1
- package/dist/runtime/context.d.ts.map +0 -1
- package/dist/runtime/control.d.ts.map +0 -1
- package/dist/runtime/dev-protocol.d.ts.map +0 -1
- package/dist/runtime/empty-server-app.d.ts.map +0 -1
- package/dist/runtime/entry.client.d.ts.map +0 -1
- package/dist/runtime/entry.rsc.d.ts.map +0 -1
- package/dist/runtime/entry.ssr.d.ts.map +0 -1
- package/dist/runtime/flight-inject.d.ts.map +0 -1
- package/dist/runtime/hot-update.d.ts.map +0 -1
- package/dist/runtime/navigation.d.ts.map +0 -1
- package/dist/runtime/request.d.ts.map +0 -1
- package/dist/runtime/server.d.ts.map +0 -1
- package/dist/runtime/validate-entries.d.ts.map +0 -1
- package/dist/server/headers.d.ts.map +0 -1
- package/dist/server/load-config.d.ts.map +0 -1
- package/dist/server/load-env.d.ts.map +0 -1
- package/dist/server/prerendered.d.ts.map +0 -1
- package/dist/server/server-config.d.ts.map +0 -1
- package/dist/server/shutdown.d.ts.map +0 -1
- package/dist/server/ssg.d.ts.map +0 -1
- package/dist/server/static.d.ts.map +0 -1
package/dist/cli/dev.d.ts
CHANGED
package/dist/cli/dev.js
CHANGED
|
@@ -11,6 +11,7 @@ import { DEV_OUT_DIR, createConfigs } from '../builder/rspack-config.js';
|
|
|
11
11
|
import { NODE_PRESET } from '../deploy/presets.js';
|
|
12
12
|
import { SERVER_DEFAULTS } from '../server/server-config.js';
|
|
13
13
|
import { createStaticAssetsApp } from '../server/static.js';
|
|
14
|
+
import { exit } from './exit.js';
|
|
14
15
|
const WORKER_READY_TIMEOUT_MS = 15_000;
|
|
15
16
|
/**
|
|
16
17
|
* Files whose contents are *compiled into* a build rather than read per request, so no rebuild picks a change
|
|
@@ -80,7 +81,7 @@ export async function devCommand(options) {
|
|
|
80
81
|
// Before the `rm` below, not at `serve` where the bind happens — see {@link portAvailable}.
|
|
81
82
|
if (!(await portAvailable(port, '127.0.0.1'))) {
|
|
82
83
|
console.error(` ✗ port ${port} is already in use`);
|
|
83
|
-
|
|
84
|
+
return exit(1);
|
|
84
85
|
}
|
|
85
86
|
await rm(outDir, { recursive: true, force: true });
|
|
86
87
|
await mkdir(join(outDir, 'static'), { recursive: true });
|
|
@@ -235,6 +236,19 @@ export async function devCommand(options) {
|
|
|
235
236
|
}
|
|
236
237
|
});
|
|
237
238
|
const front = new Hono();
|
|
239
|
+
// **Answered here, not proxied — so the app's own middleware does not see an asset request in dev.**
|
|
240
|
+
// That is a divergence from a build, where `/_static` is mounted *inside* the app so an asset carries
|
|
241
|
+
// HSTS, the app's CSP and anything else its middleware sets (`prod-config.test.mjs` asserts it). It is
|
|
242
|
+
// kept deliberately, and the reason is the gate below: every request the front-end proxies first awaits
|
|
243
|
+
// `workerGate.promise`. The client bundle is built by a compiler that finishes independently of the
|
|
244
|
+
// server one, so proxying assets would park the browser's JS and CSS behind the *server* rebuild — a save
|
|
245
|
+
// touching one server component would stall the whole page's assets, and a server bundle that failed to
|
|
246
|
+
// build would take them down with it. A worse dev experience than the divergence.
|
|
247
|
+
//
|
|
248
|
+
// What it costs is real and worth knowing: a CSP is developed against a policy that does not apply to the
|
|
249
|
+
// files it is most likely to break, so the first time it does is in a build. If this ever has to go, the
|
|
250
|
+
// shape that keeps both properties is narrower than a plain move — proxy `/_static` only while a worker
|
|
251
|
+
// is live, and answer locally while the gate is closed.
|
|
238
252
|
front.route('/_static', createStaticAssetsApp({ root: join(outDir, 'static'), isDev: true }));
|
|
239
253
|
front.get('/_rshono/hmr', () => {
|
|
240
254
|
let ctrl;
|
package/dist/cli/dev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"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","sourcesContent":["import { serve } from '@hono/node-server';\nimport { rspack, type Stats } from '@rspack/core';\nimport { Hono } from 'hono';\nimport { proxy } from 'hono/proxy';\nimport { watch } from 'node:fs';\nimport { mkdir, rm } from 'node:fs/promises';\nimport { createServer } from 'node:net';\nimport { join } from 'node:path';\nimport { Worker } from 'node:worker_threads';\nimport { DEV_OUT_DIR, createConfigs } from '../builder/rspack-config.js';\nimport type { RshonoConfig } from '../config.js';\nimport { NODE_PRESET } from '../deploy/presets.js';\nimport type { DevMessage } from '../runtime/dev-protocol.js';\nimport { SERVER_DEFAULTS } from '../server/server-config.js';\nimport { createStaticAssetsApp } from '../server/static.js';\n\nconst WORKER_READY_TIMEOUT_MS = 15_000;\n\n/**\n * Files whose contents are *compiled into* a build rather than read per request, so no rebuild picks a change\n * to them up: `.env` because the `PUBLIC_` view of it is baked into the client bundle by DefinePlugin and into\n * the SSR layer by the env-shadow prelude, and `rshono.config.ts` because `ServerConfig` is a DefinePlugin\n * literal too. `.env` is worse than the config, which the docs at least describe as build-time: a page that\n * reads `process.env` rebuilds, serves, and shows the old value.\n */\nconst BAKED_IN_FILES = ['.env.local', '.env', 'rshono.config.ts', 'rshono.config.js', 'rshono.config.mjs'];\n\n/**\n * Watches those files, only to say that a restart is needed.\n *\n * Reloading them for real means re-exec'ing this process: `process.loadEnvFile` does not override a variable\n * that is already set, so the copy this process took at startup would survive an in-place reload — and the\n * worker is spawned with `env: process.env`, so it would inherit the stale value too. Choreographing that\n * against a bound port and a live SSE connection is a great deal of machinery to save one Ctrl-C; a line\n * saying which key to press costs nothing and loses nobody an afternoon.\n *\n * The directory is watched rather than each file, so a file that does not exist yet is still covered — and\n * because an editor's atomic save replaces the file, which a watch on the file itself does not survive. An\n * explicit `--config` outside the project root is not covered: this is a convenience, not a contract.\n */\nfunction warnOnBakedInFileChanges(rootDir: string): void {\n const warnedAt = new Map<string, number>();\n try {\n // `persistent: false`: the dev server is kept alive by its listener, and a watcher that outlived it\n // would hold the process open with nothing left to report to.\n watch(rootDir, { persistent: false }, (_event, filename) => {\n if (!filename || !BAKED_IN_FILES.includes(filename)) return;\n // One save fires several events — a write, a rename, an attribute change — and they are all the same\n // save. The window is short enough that a second real edit still gets its own line.\n const now = Date.now();\n if (now - (warnedAt.get(filename) ?? 0) < 250) return;\n warnedAt.set(filename, now);\n console.warn(` ⚠ ${filename} changed — restart \\`rshono dev\\` to pick it up. It is compiled into the build, not read per request.`);\n });\n } catch {\n // No watcher available: a filesystem that cannot, or a platform limit reached. Rebuilding still works,\n // so the dev server goes on without the reminder rather than refusing to start over one.\n }\n}\n\n/** An error as the dev server shows it in the browser: the stack where there is one, since this is dev. */\nfunction describe(error: unknown): string {\n return error instanceof Error ? (error.stack ?? error.message) : String(error);\n}\n\n/**\n * Whether nothing is listening on the port yet — checked before the output directory is emptied, because a\n * second `rshono dev` would otherwise wipe the chunks the running one is still importing and only then exit\n * on EADDRINUSE.\n */\nfunction portAvailable(port: number, hostname: string): Promise<boolean> {\n const { promise, resolve } = Promise.withResolvers<boolean>();\n const probe = createServer();\n probe.once('error', () => resolve(false));\n probe.listen(port, hostname, () => probe.close(() => resolve(true)));\n return promise;\n}\n\ninterface DevOptions {\n rootDir: string;\n port?: number;\n config: RshonoConfig;\n}\n\nexport async function devCommand(options: DevOptions): Promise<void> {\n const { rootDir, config } = options;\n const port = options.port ?? SERVER_DEFAULTS.port;\n // Its own directory, never `dist/`: a `rshono build` in another terminal must not be able to delete the\n // chunks this server is still importing.\n const outDir = join(rootDir, DEV_OUT_DIR);\n\n // Before the `rm` below, not at `serve` where the bind happens — see {@link portAvailable}.\n if (!(await portAvailable(port, '127.0.0.1'))) {\n console.error(` ✗ port ${port} is already in use`);\n process.exit(1);\n }\n\n await rm(outDir, { recursive: true, force: true });\n await mkdir(join(outDir, 'static'), { recursive: true });\n\n const encoder = new TextEncoder();\n const sseClients = new Set<ReadableStreamDefaultController<Uint8Array>>();\n let clientHash: string | undefined;\n\n const sseChunk = (data: unknown) => encoder.encode(`data: ${JSON.stringify(data)}\\n\\n`);\n\n /**\n * Writes one already-encoded SSE frame to every open client. A failed write is what retires a client:\n * `cancel` is not always reached first when a browser navigates away.\n */\n function sendToAll(chunk: Uint8Array): void {\n for (const controller of sseClients) {\n try {\n controller.enqueue(chunk);\n } catch {\n sseClients.delete(controller);\n }\n }\n }\n\n function broadcast(message: DevMessage): void {\n sendToAll(sseChunk(message));\n }\n\n let serverComponentsChanged = false;\n const [clientConfig, serverConfig] = createConfigs({\n rootDir,\n isDev: true,\n config,\n // Always Node, whatever `deploy` says: that is a property of `build` output, and the dev server runs the\n // bundle in a worker thread of this process.\n preset: NODE_PRESET,\n onServerComponentChanges: () => {\n serverComponentsChanged = true;\n },\n });\n const compiler = rspack([clientConfig, serverConfig]);\n const [clientCompiler, serverCompiler] = compiler.compilers;\n\n let currentWorker: Worker | null = null;\n let workerPort: number | null = null;\n let workerGate = createGate();\n let restartChain: Promise<void> = Promise.resolve();\n\n function createGate() {\n const { promise, resolve } = Promise.withResolvers<{ error?: string }>();\n return { promise, open: resolve };\n }\n\n function spawnWorker(): Promise<{ worker: Worker; port: number }> {\n return new Promise((resolve, reject) => {\n const worker = new Worker(join(outDir, 'server', 'main.mjs'), {\n workerData: { port: 0, hostname: '127.0.0.1' },\n execArgv: ['--enable-source-maps'],\n env: process.env as Record<string, string>,\n });\n const timeout = setTimeout(() => {\n // Nothing waits on the termination: the promise below is already being rejected, and a worker that\n // never reported ready has no state left worth draining.\n void worker.terminate();\n reject(new Error(`server worker did not become ready within ${WORKER_READY_TIMEOUT_MS / 1000}s`));\n }, WORKER_READY_TIMEOUT_MS);\n\n let ready = false;\n worker.once('message', (message: { type?: string; port?: number }) => {\n if (message?.type === 'ready' && typeof message.port === 'number') {\n ready = true;\n clearTimeout(timeout);\n resolve({ worker, port: message.port });\n }\n });\n // `on`, not `once`: an error after the worker is ready has no pending promise left to reject, and a\n // consumed `once` would leave it unlistened — which Node turns into an uncaught exception here.\n worker.on('error', (error: Error) => {\n if (ready) {\n console.error(' ✗ server worker crashed:', error);\n return;\n }\n clearTimeout(timeout);\n reject(error);\n });\n worker.on('exit', (code) => {\n if (worker === currentWorker && code !== 0) {\n console.error(` ✗ server worker exited with code ${code} — waiting for the next rebuild`);\n currentWorker = null;\n // Opened with the reason rather than left closed, so a request arriving before the next rebuild sees\n // it instead of hanging. `hooks.invalid` installs a fresh closed gate as soon as a file changes.\n workerGate = createGate();\n workerGate.open({ error: `The server worker exited with code ${code}. See the terminal for the error it crashed with.` });\n }\n });\n });\n }\n\n serverCompiler.hooks.invalid.tap('rshono/gate', () => {\n workerGate = createGate();\n });\n\n serverCompiler.hooks.done.tapPromise('rshono/worker', async (stats: Stats) => {\n const gate = workerGate;\n restartChain = restartChain.then(async () => {\n if (stats.hasErrors()) {\n console.error(stats.toString({ preset: 'errors-warnings', colors: true }));\n gate.open({ error: stats.toString({ preset: 'errors-only', colors: false }) });\n return;\n }\n try {\n if (currentWorker) {\n const old = currentWorker;\n currentWorker = null;\n await old.terminate();\n }\n const { worker, port: newPort } = await spawnWorker();\n currentWorker = worker;\n workerPort = newPort;\n gate.open({});\n if (serverComponentsChanged) {\n serverComponentsChanged = false;\n broadcast({ type: 'rsc-update' });\n }\n } catch (error) {\n console.error(' ✗ failed to start server worker:', error);\n gate.open({ error: describe(error) });\n }\n });\n // No link in this queue may be left rejected: `.then` on a rejected promise short-circuits, and from there\n // no worker is spawned and no gate is opened again.\n restartChain = restartChain.catch((error) => {\n console.error(' ✗ dev server restart failed:', error);\n gate.open({ error: describe(error) });\n });\n await restartChain;\n });\n\n clientCompiler.hooks.done.tap('rshono/hmr', (stats: Stats) => {\n if (stats.hasErrors()) {\n console.error(stats.toString({ preset: 'errors-warnings', colors: true }));\n return;\n }\n clientHash = stats.hash ?? undefined;\n if (clientHash) broadcast({ type: 'client-built', hash: clientHash });\n });\n\n let firstBuild = true;\n compiler.watch([{}, {}] as never, (err, multiStats) => {\n if (err) {\n console.error(' ✗ build failed:', err);\n return;\n }\n if (multiStats && !multiStats.hasErrors()) {\n // Errors print themselves through the per-compiler `done` hooks; a warning has nowhere else to go, and\n // the env shadow reports what it cannot cover that way. See `env-shadow-loader.cjs`.\n if (multiStats.hasWarnings()) console.warn(multiStats.toString({ preset: 'errors-warnings', colors: true }));\n const seconds = Math.max(...multiStats.stats.map((s) => (s.endTime ?? 0) - (s.startTime ?? 0))) / 1000;\n console.log(` ${firstBuild ? '✓ built' : '✓ rebuilt'} in ${seconds.toFixed(1)}s`);\n firstBuild = false;\n }\n });\n\n const front = new Hono();\n\n front.route('/_static', createStaticAssetsApp({ root: join(outDir, 'static'), isDev: true }));\n\n front.get('/_rshono/hmr', () => {\n let ctrl: ReadableStreamDefaultController<Uint8Array>;\n const stream = new ReadableStream<Uint8Array>({\n start(controller) {\n ctrl = controller;\n sseClients.add(controller);\n controller.enqueue(encoder.encode('retry: 500\\n\\n'));\n controller.enqueue(sseChunk({ type: 'hello', hash: clientHash } satisfies DevMessage));\n },\n cancel() {\n sseClients.delete(ctrl);\n },\n });\n return new Response(stream, {\n headers: {\n 'content-type': 'text/event-stream',\n 'cache-control': 'no-cache',\n connection: 'keep-alive',\n },\n });\n });\n\n // An SSE comment, not a message: it keeps an idle connection off a proxy's timeout without the client\n // having to know a frame type that means nothing.\n const ping = encoder.encode(': ping\\n\\n');\n setInterval(() => sendToAll(ping), 15_000).unref();\n\n front.all('*', async (c) => {\n const { error } = await workerGate.promise;\n if (error || workerPort === null) {\n return c.text(`Build failed:\\n\\n${error ?? 'server not running'}`, 500);\n }\n\n const incoming = new URL(c.req.url);\n const target = `http://127.0.0.1:${workerPort}${incoming.pathname}${incoming.search}`;\n\n // Hono's proxy helper rather than a hand-rolled `fetch`: it carries the method, the streamed body (with\n // the `duplex` Node requires) and the client's abort signal, and strips the hop-by-hop headers on the way\n // back. `headers` replaces the set wholesale, so the request's own are spread back in first.\n const response = await proxy(target, {\n raw: c.req.raw,\n // The worker's redirects are the app's answer to this request, to be rewritten below and passed on.\n redirect: 'manual',\n headers: {\n ...c.req.header(),\n // This front-end *is* the proxy the app sits behind, which is why `trustProxy` is forced on in dev:\n // without these the app resolves every URL against the worker's random 127.0.0.1 port.\n 'x-forwarded-host': incoming.host,\n 'x-forwarded-proto': incoming.protocol.replace(':', ''),\n },\n });\n\n // A redirect to the worker's own address has to become a relative one, or the browser leaves the dev\n // server for a random port only this process knows about.\n const location = response.headers.get('location');\n const loc = location ? URL.parse(location, target) : null;\n if (loc && loc.host === `127.0.0.1:${workerPort}`) {\n response.headers.set('location', `${loc.pathname}${loc.search}${loc.hash}`);\n }\n return response;\n });\n\n warnOnBakedInFileChanges(rootDir);\n\n serve({ fetch: front.fetch, port, hostname: '127.0.0.1' }, (info) => {\n console.log(` ➜ rshono dev server: http://localhost:${info.port}`);\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"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","sourcesContent":["import { serve } from '@hono/node-server';\nimport { rspack, type Stats } from '@rspack/core';\nimport { Hono } from 'hono';\nimport { proxy } from 'hono/proxy';\nimport { watch } from 'node:fs';\nimport { mkdir, rm } from 'node:fs/promises';\nimport { createServer } from 'node:net';\nimport { join } from 'node:path';\nimport { Worker } from 'node:worker_threads';\nimport { DEV_OUT_DIR, createConfigs } from '../builder/rspack-config.js';\nimport type { RshonoConfig } from '../config.js';\nimport { NODE_PRESET } from '../deploy/presets.js';\nimport type { DevMessage } from '../runtime/dev-protocol.js';\nimport { SERVER_DEFAULTS } from '../server/server-config.js';\nimport { createStaticAssetsApp } from '../server/static.js';\nimport { exit } from './exit.js';\n\nconst WORKER_READY_TIMEOUT_MS = 15_000;\n\n/**\n * Files whose contents are *compiled into* a build rather than read per request, so no rebuild picks a change\n * to them up: `.env` because the `PUBLIC_` view of it is baked into the client bundle by DefinePlugin and into\n * the SSR layer by the env-shadow prelude, and `rshono.config.ts` because `ServerConfig` is a DefinePlugin\n * literal too. `.env` is worse than the config, which the docs at least describe as build-time: a page that\n * reads `process.env` rebuilds, serves, and shows the old value.\n */\nconst BAKED_IN_FILES = ['.env.local', '.env', 'rshono.config.ts', 'rshono.config.js', 'rshono.config.mjs'];\n\n/**\n * Watches those files, only to say that a restart is needed.\n *\n * Reloading them for real means re-exec'ing this process: `process.loadEnvFile` does not override a variable\n * that is already set, so the copy this process took at startup would survive an in-place reload — and the\n * worker is spawned with `env: process.env`, so it would inherit the stale value too. Choreographing that\n * against a bound port and a live SSE connection is a great deal of machinery to save one Ctrl-C; a line\n * saying which key to press costs nothing and loses nobody an afternoon.\n *\n * The directory is watched rather than each file, so a file that does not exist yet is still covered — and\n * because an editor's atomic save replaces the file, which a watch on the file itself does not survive. An\n * explicit `--config` outside the project root is not covered: this is a convenience, not a contract.\n */\nfunction warnOnBakedInFileChanges(rootDir: string): void {\n const warnedAt = new Map<string, number>();\n try {\n // `persistent: false`: the dev server is kept alive by its listener, and a watcher that outlived it\n // would hold the process open with nothing left to report to.\n watch(rootDir, { persistent: false }, (_event, filename) => {\n if (!filename || !BAKED_IN_FILES.includes(filename)) return;\n // One save fires several events — a write, a rename, an attribute change — and they are all the same\n // save. The window is short enough that a second real edit still gets its own line.\n const now = Date.now();\n if (now - (warnedAt.get(filename) ?? 0) < 250) return;\n warnedAt.set(filename, now);\n console.warn(` ⚠ ${filename} changed — restart \\`rshono dev\\` to pick it up. It is compiled into the build, not read per request.`);\n });\n } catch {\n // No watcher available: a filesystem that cannot, or a platform limit reached. Rebuilding still works,\n // so the dev server goes on without the reminder rather than refusing to start over one.\n }\n}\n\n/** An error as the dev server shows it in the browser: the stack where there is one, since this is dev. */\nfunction describe(error: unknown): string {\n return error instanceof Error ? (error.stack ?? error.message) : String(error);\n}\n\n/**\n * Whether nothing is listening on the port yet — checked before the output directory is emptied, because a\n * second `rshono dev` would otherwise wipe the chunks the running one is still importing and only then exit\n * on EADDRINUSE.\n */\nfunction portAvailable(port: number, hostname: string): Promise<boolean> {\n const { promise, resolve } = Promise.withResolvers<boolean>();\n const probe = createServer();\n probe.once('error', () => resolve(false));\n probe.listen(port, hostname, () => probe.close(() => resolve(true)));\n return promise;\n}\n\ninterface DevOptions {\n rootDir: string;\n port?: number;\n config: RshonoConfig;\n}\n\nexport async function devCommand(options: DevOptions): Promise<void> {\n const { rootDir, config } = options;\n const port = options.port ?? SERVER_DEFAULTS.port;\n // Its own directory, never `dist/`: a `rshono build` in another terminal must not be able to delete the\n // chunks this server is still importing.\n const outDir = join(rootDir, DEV_OUT_DIR);\n\n // Before the `rm` below, not at `serve` where the bind happens — see {@link portAvailable}.\n if (!(await portAvailable(port, '127.0.0.1'))) {\n console.error(` ✗ port ${port} is already in use`);\n return exit(1);\n }\n\n await rm(outDir, { recursive: true, force: true });\n await mkdir(join(outDir, 'static'), { recursive: true });\n\n const encoder = new TextEncoder();\n const sseClients = new Set<ReadableStreamDefaultController<Uint8Array>>();\n let clientHash: string | undefined;\n\n const sseChunk = (data: unknown) => encoder.encode(`data: ${JSON.stringify(data)}\\n\\n`);\n\n /**\n * Writes one already-encoded SSE frame to every open client. A failed write is what retires a client:\n * `cancel` is not always reached first when a browser navigates away.\n */\n function sendToAll(chunk: Uint8Array): void {\n for (const controller of sseClients) {\n try {\n controller.enqueue(chunk);\n } catch {\n sseClients.delete(controller);\n }\n }\n }\n\n function broadcast(message: DevMessage): void {\n sendToAll(sseChunk(message));\n }\n\n let serverComponentsChanged = false;\n const [clientConfig, serverConfig] = createConfigs({\n rootDir,\n isDev: true,\n config,\n // Always Node, whatever `deploy` says: that is a property of `build` output, and the dev server runs the\n // bundle in a worker thread of this process.\n preset: NODE_PRESET,\n onServerComponentChanges: () => {\n serverComponentsChanged = true;\n },\n });\n const compiler = rspack([clientConfig, serverConfig]);\n const [clientCompiler, serverCompiler] = compiler.compilers;\n\n let currentWorker: Worker | null = null;\n let workerPort: number | null = null;\n let workerGate = createGate();\n let restartChain: Promise<void> = Promise.resolve();\n\n function createGate() {\n const { promise, resolve } = Promise.withResolvers<{ error?: string }>();\n return { promise, open: resolve };\n }\n\n function spawnWorker(): Promise<{ worker: Worker; port: number }> {\n return new Promise((resolve, reject) => {\n const worker = new Worker(join(outDir, 'server', 'main.mjs'), {\n workerData: { port: 0, hostname: '127.0.0.1' },\n execArgv: ['--enable-source-maps'],\n env: process.env as Record<string, string>,\n });\n const timeout = setTimeout(() => {\n // Nothing waits on the termination: the promise below is already being rejected, and a worker that\n // never reported ready has no state left worth draining.\n void worker.terminate();\n reject(new Error(`server worker did not become ready within ${WORKER_READY_TIMEOUT_MS / 1000}s`));\n }, WORKER_READY_TIMEOUT_MS);\n\n let ready = false;\n worker.once('message', (message: { type?: string; port?: number }) => {\n if (message?.type === 'ready' && typeof message.port === 'number') {\n ready = true;\n clearTimeout(timeout);\n resolve({ worker, port: message.port });\n }\n });\n // `on`, not `once`: an error after the worker is ready has no pending promise left to reject, and a\n // consumed `once` would leave it unlistened — which Node turns into an uncaught exception here.\n worker.on('error', (error: Error) => {\n if (ready) {\n console.error(' ✗ server worker crashed:', error);\n return;\n }\n clearTimeout(timeout);\n reject(error);\n });\n worker.on('exit', (code) => {\n if (worker === currentWorker && code !== 0) {\n console.error(` ✗ server worker exited with code ${code} — waiting for the next rebuild`);\n currentWorker = null;\n // Opened with the reason rather than left closed, so a request arriving before the next rebuild sees\n // it instead of hanging. `hooks.invalid` installs a fresh closed gate as soon as a file changes.\n workerGate = createGate();\n workerGate.open({ error: `The server worker exited with code ${code}. See the terminal for the error it crashed with.` });\n }\n });\n });\n }\n\n serverCompiler.hooks.invalid.tap('rshono/gate', () => {\n workerGate = createGate();\n });\n\n serverCompiler.hooks.done.tapPromise('rshono/worker', async (stats: Stats) => {\n const gate = workerGate;\n restartChain = restartChain.then(async () => {\n if (stats.hasErrors()) {\n console.error(stats.toString({ preset: 'errors-warnings', colors: true }));\n gate.open({ error: stats.toString({ preset: 'errors-only', colors: false }) });\n return;\n }\n try {\n if (currentWorker) {\n const old = currentWorker;\n currentWorker = null;\n await old.terminate();\n }\n const { worker, port: newPort } = await spawnWorker();\n currentWorker = worker;\n workerPort = newPort;\n gate.open({});\n if (serverComponentsChanged) {\n serverComponentsChanged = false;\n broadcast({ type: 'rsc-update' });\n }\n } catch (error) {\n console.error(' ✗ failed to start server worker:', error);\n gate.open({ error: describe(error) });\n }\n });\n // No link in this queue may be left rejected: `.then` on a rejected promise short-circuits, and from there\n // no worker is spawned and no gate is opened again.\n restartChain = restartChain.catch((error) => {\n console.error(' ✗ dev server restart failed:', error);\n gate.open({ error: describe(error) });\n });\n await restartChain;\n });\n\n clientCompiler.hooks.done.tap('rshono/hmr', (stats: Stats) => {\n if (stats.hasErrors()) {\n console.error(stats.toString({ preset: 'errors-warnings', colors: true }));\n return;\n }\n clientHash = stats.hash ?? undefined;\n if (clientHash) broadcast({ type: 'client-built', hash: clientHash });\n });\n\n let firstBuild = true;\n compiler.watch([{}, {}] as never, (err, multiStats) => {\n if (err) {\n console.error(' ✗ build failed:', err);\n return;\n }\n if (multiStats && !multiStats.hasErrors()) {\n // Errors print themselves through the per-compiler `done` hooks; a warning has nowhere else to go, and\n // the env shadow reports what it cannot cover that way. See `env-shadow-loader.cjs`.\n if (multiStats.hasWarnings()) console.warn(multiStats.toString({ preset: 'errors-warnings', colors: true }));\n const seconds = Math.max(...multiStats.stats.map((s) => (s.endTime ?? 0) - (s.startTime ?? 0))) / 1000;\n console.log(` ${firstBuild ? '✓ built' : '✓ rebuilt'} in ${seconds.toFixed(1)}s`);\n firstBuild = false;\n }\n });\n\n const front = new Hono();\n\n // **Answered here, not proxied — so the app's own middleware does not see an asset request in dev.**\n // That is a divergence from a build, where `/_static` is mounted *inside* the app so an asset carries\n // HSTS, the app's CSP and anything else its middleware sets (`prod-config.test.mjs` asserts it). It is\n // kept deliberately, and the reason is the gate below: every request the front-end proxies first awaits\n // `workerGate.promise`. The client bundle is built by a compiler that finishes independently of the\n // server one, so proxying assets would park the browser's JS and CSS behind the *server* rebuild — a save\n // touching one server component would stall the whole page's assets, and a server bundle that failed to\n // build would take them down with it. A worse dev experience than the divergence.\n //\n // What it costs is real and worth knowing: a CSP is developed against a policy that does not apply to the\n // files it is most likely to break, so the first time it does is in a build. If this ever has to go, the\n // shape that keeps both properties is narrower than a plain move — proxy `/_static` only while a worker\n // is live, and answer locally while the gate is closed.\n front.route('/_static', createStaticAssetsApp({ root: join(outDir, 'static'), isDev: true }));\n\n front.get('/_rshono/hmr', () => {\n let ctrl: ReadableStreamDefaultController<Uint8Array>;\n const stream = new ReadableStream<Uint8Array>({\n start(controller) {\n ctrl = controller;\n sseClients.add(controller);\n controller.enqueue(encoder.encode('retry: 500\\n\\n'));\n controller.enqueue(sseChunk({ type: 'hello', hash: clientHash } satisfies DevMessage));\n },\n cancel() {\n sseClients.delete(ctrl);\n },\n });\n return new Response(stream, {\n headers: {\n 'content-type': 'text/event-stream',\n 'cache-control': 'no-cache',\n connection: 'keep-alive',\n },\n });\n });\n\n // An SSE comment, not a message: it keeps an idle connection off a proxy's timeout without the client\n // having to know a frame type that means nothing.\n const ping = encoder.encode(': ping\\n\\n');\n setInterval(() => sendToAll(ping), 15_000).unref();\n\n front.all('*', async (c) => {\n const { error } = await workerGate.promise;\n if (error || workerPort === null) {\n return c.text(`Build failed:\\n\\n${error ?? 'server not running'}`, 500);\n }\n\n const incoming = new URL(c.req.url);\n const target = `http://127.0.0.1:${workerPort}${incoming.pathname}${incoming.search}`;\n\n // Hono's proxy helper rather than a hand-rolled `fetch`: it carries the method, the streamed body (with\n // the `duplex` Node requires) and the client's abort signal, and strips the hop-by-hop headers on the way\n // back. `headers` replaces the set wholesale, so the request's own are spread back in first.\n const response = await proxy(target, {\n raw: c.req.raw,\n // The worker's redirects are the app's answer to this request, to be rewritten below and passed on.\n redirect: 'manual',\n headers: {\n ...c.req.header(),\n // This front-end *is* the proxy the app sits behind, which is why `trustProxy` is forced on in dev:\n // without these the app resolves every URL against the worker's random 127.0.0.1 port.\n 'x-forwarded-host': incoming.host,\n 'x-forwarded-proto': incoming.protocol.replace(':', ''),\n },\n });\n\n // A redirect to the worker's own address has to become a relative one, or the browser leaves the dev\n // server for a random port only this process knows about.\n const location = response.headers.get('location');\n const loc = location ? URL.parse(location, target) : null;\n if (loc && loc.host === `127.0.0.1:${workerPort}`) {\n response.headers.set('location', `${loc.pathname}${loc.search}${loc.hash}`);\n }\n return response;\n });\n\n warnOnBakedInFileChanges(rootDir);\n\n serve({ fetch: front.fetch, port, hostname: '127.0.0.1' }, (info) => {\n console.log(` ➜ rshono dev server: http://localhost:${info.port}`);\n });\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `process.exit`, once both output streams have drained.
|
|
3
|
+
*
|
|
4
|
+
* A piped stdout/stderr — every CI job, and any `rshono build | tee` — is asynchronous on POSIX, and exiting
|
|
5
|
+
* drops whatever has not left the pipe buffer (64 KiB on Linux and macOS; a pipe write on Windows is
|
|
6
|
+
* synchronous, so there the drain is a no-op). On the failure paths that is the report saying *why* the build
|
|
7
|
+
* failed, cut mid-error. A zero-length write's callback fires behind the real ones, so awaiting one per stream
|
|
8
|
+
* is enough.
|
|
9
|
+
*
|
|
10
|
+
* `Promise<never>`, so a caller can `return exit(1)` and keep the branch terminal for control-flow analysis.
|
|
11
|
+
*/
|
|
12
|
+
export declare function exit(code: number): Promise<never>;
|
package/dist/cli/exit.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `process.exit`, once both output streams have drained.
|
|
3
|
+
*
|
|
4
|
+
* A piped stdout/stderr — every CI job, and any `rshono build | tee` — is asynchronous on POSIX, and exiting
|
|
5
|
+
* drops whatever has not left the pipe buffer (64 KiB on Linux and macOS; a pipe write on Windows is
|
|
6
|
+
* synchronous, so there the drain is a no-op). On the failure paths that is the report saying *why* the build
|
|
7
|
+
* failed, cut mid-error. A zero-length write's callback fires behind the real ones, so awaiting one per stream
|
|
8
|
+
* is enough.
|
|
9
|
+
*
|
|
10
|
+
* `Promise<never>`, so a caller can `return exit(1)` and keep the branch terminal for control-flow analysis.
|
|
11
|
+
*/
|
|
12
|
+
export async function exit(code) {
|
|
13
|
+
await Promise.all([process.stdout, process.stderr].map((stream) => new Promise((resolve) => stream.write('', () => resolve()))));
|
|
14
|
+
process.exit(code);
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=exit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exit.js","sourceRoot":"","sources":["../../src/cli/exit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAY;IACrC,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACvI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC","sourcesContent":["/**\n * `process.exit`, once both output streams have drained.\n *\n * A piped stdout/stderr — every CI job, and any `rshono build | tee` — is asynchronous on POSIX, and exiting\n * drops whatever has not left the pipe buffer (64 KiB on Linux and macOS; a pipe write on Windows is\n * synchronous, so there the drain is a no-op). On the failure paths that is the report saying *why* the build\n * failed, cut mid-error. A zero-length write's callback fires behind the real ones, so awaiting one per stream\n * is enough.\n *\n * `Promise<never>`, so a caller can `return exit(1)` and keep the branch terminal for control-flow analysis.\n */\nexport async function exit(code: number): Promise<never> {\n await Promise.all([process.stdout, process.stderr].map((stream) => new Promise<void>((resolve) => stream.write('', () => resolve()))));\n process.exit(code);\n}\n"]}
|
package/dist/cli/index.d.ts
CHANGED
package/dist/cli/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { DEPLOY_TARGETS, resolveDeployPreset } from '../deploy/presets.js';
|
|
|
4
4
|
import { loadConfig } from '../server/load-config.js';
|
|
5
5
|
import { loadEnvFiles } from '../server/load-env.js';
|
|
6
6
|
import { parsePort } from '../server/server-config.js';
|
|
7
|
+
import { exit } from './exit.js';
|
|
7
8
|
// The commands are imported where they are dispatched: `build` and `dev` pull in Rspack, and a static import
|
|
8
9
|
// would load it for `start` too — ~30 MB of RSS and ~70ms of startup that would then sit in the server's own
|
|
9
10
|
// process for its whole life, since `start` imports the bundle rather than spawning it.
|
|
@@ -20,28 +21,44 @@ Options:
|
|
|
20
21
|
-d, --deploy <name> platform to build for: ${DEPLOY_TARGETS.join(' | ')} (default: node)
|
|
21
22
|
-h, --help show this help
|
|
22
23
|
-v, --version print the version
|
|
24
|
+
|
|
25
|
+
Environment:
|
|
26
|
+
PORT port to listen on, unless --port is given
|
|
27
|
+
HOST address \`start\` binds to (default 0.0.0.0); \`dev\` always binds 127.0.0.1
|
|
28
|
+
RSHONO_DEPLOY platform to build for, unless --deploy is given
|
|
23
29
|
`;
|
|
24
|
-
/**
|
|
25
|
-
|
|
30
|
+
/** `as const` so `parseArgs` can type `values` off the literal `type` fields rather than widening them. */
|
|
31
|
+
const CLI_OPTIONS = {
|
|
32
|
+
port: { type: 'string', short: 'p' },
|
|
33
|
+
config: { type: 'string', short: 'c' },
|
|
34
|
+
deploy: { type: 'string', short: 'd' },
|
|
35
|
+
help: { type: 'boolean', short: 'h' },
|
|
36
|
+
version: { type: 'boolean', short: 'v' },
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* {@link parseArgs}, reported the way the CLI reports every other bad input: one line, then the help.
|
|
40
|
+
*
|
|
41
|
+
* A typo'd flag is the likeliest of the three bad inputs and used to get by far the worst output. `parseArgs`
|
|
42
|
+
* was the first statement of `main`, with nothing between it and the `main().catch` that prints the raw error
|
|
43
|
+
* object — so `rshono build --porf 3000` answered with nine frames of Node internals, where an unknown
|
|
44
|
+
* command and an unparseable `--port` each answered with a sentence.
|
|
45
|
+
*
|
|
46
|
+
* Node's own message is kept: it names the offending flag, which is the whole content of the error, and
|
|
47
|
+
* `HELP` beneath it lists the ones that exist. Through {@link exit} rather than `process.exit`, because that
|
|
48
|
+
* help goes to stdout and a piped stdout drops whatever has not left the buffer.
|
|
49
|
+
*/
|
|
50
|
+
async function readArgs() {
|
|
26
51
|
try {
|
|
27
|
-
return
|
|
52
|
+
return parseArgs({ options: CLI_OPTIONS, allowPositionals: true });
|
|
28
53
|
}
|
|
29
54
|
catch (error) {
|
|
30
|
-
console.error(`rshono: ${error instanceof Error ? error.message : String(error)}`);
|
|
31
|
-
|
|
55
|
+
console.error(`rshono: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
56
|
+
console.log(HELP);
|
|
57
|
+
return exit(1);
|
|
32
58
|
}
|
|
33
59
|
}
|
|
34
60
|
async function main() {
|
|
35
|
-
const { values, positionals } =
|
|
36
|
-
options: {
|
|
37
|
-
port: { type: 'string', short: 'p' },
|
|
38
|
-
config: { type: 'string', short: 'c' },
|
|
39
|
-
deploy: { type: 'string', short: 'd' },
|
|
40
|
-
help: { type: 'boolean', short: 'h' },
|
|
41
|
-
version: { type: 'boolean', short: 'v' },
|
|
42
|
-
},
|
|
43
|
-
allowPositionals: true,
|
|
44
|
-
});
|
|
61
|
+
const { values, positionals } = await readArgs();
|
|
45
62
|
if (values.version) {
|
|
46
63
|
const require = createRequire(import.meta.url);
|
|
47
64
|
const { version } = require('@rshono/core/package.json');
|
|
@@ -58,10 +75,31 @@ async function main() {
|
|
|
58
75
|
const config = await loadConfig(rootDir, values.config);
|
|
59
76
|
// Precedence: --port flag > PORT env > the command's built-in default. Both sources go through the same
|
|
60
77
|
// parse as the bundle's own, so `PORT=""` means "unset" in the CLI and in the server it starts alike.
|
|
61
|
-
|
|
78
|
+
//
|
|
79
|
+
// The parse stays synchronous and the exit is here, where the other flag errors are answered, rather than
|
|
80
|
+
// inside a `readPort` helper of its own. That helper had to reach `process.exit` directly — it is not
|
|
81
|
+
// `async`, and `exit()` returns a promise — so it was the one bad-input path in the CLI that did not
|
|
82
|
+
// drain a piped stderr. Making it `async` instead is the trap: `??` on a `Promise` is never nullish, so
|
|
83
|
+
// `--port` would resolve to a pending promise and `PORT` would stop being read at all.
|
|
84
|
+
let port;
|
|
85
|
+
try {
|
|
86
|
+
port = parsePort(values.port, '--port') ?? parsePort(process.env.PORT, 'PORT');
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
console.error(`rshono: ${error instanceof Error ? error.message : String(error)}`);
|
|
90
|
+
return exit(1);
|
|
91
|
+
}
|
|
62
92
|
const host = process.env.HOST;
|
|
63
93
|
switch (command) {
|
|
64
94
|
case 'dev':
|
|
95
|
+
// `HOST` belongs to `start`. The dev server binds loopback unconditionally — its source maps embed the
|
|
96
|
+
// original source of `'use server'` modules — and `DevOptions` has no `host` field to pass one to, so
|
|
97
|
+
// the drop is structural rather than conditional. Said out loud because the variable is read a few
|
|
98
|
+
// lines up and the README lists it under all three commands: `HOST=0.0.0.0 rshono dev` used to do
|
|
99
|
+
// nothing, with nothing to notice.
|
|
100
|
+
if (host !== undefined) {
|
|
101
|
+
console.warn('rshono: HOST is ignored by `rshono dev`, which always binds 127.0.0.1 — it applies to `rshono start`.');
|
|
102
|
+
}
|
|
65
103
|
return (await import('./dev.js')).devCommand({ rootDir, port, config });
|
|
66
104
|
case 'build':
|
|
67
105
|
return (await import('./build.js')).buildCommand({
|
|
@@ -74,11 +112,27 @@ async function main() {
|
|
|
74
112
|
default:
|
|
75
113
|
console.error(`rshono: unknown command "${command}"\n`);
|
|
76
114
|
console.log(HELP);
|
|
77
|
-
|
|
115
|
+
return exit(1);
|
|
78
116
|
}
|
|
79
117
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
118
|
+
/**
|
|
119
|
+
* The one place a failure becomes output, for every command.
|
|
120
|
+
*
|
|
121
|
+
* A `[rshono]` message was written for whoever is running the command, so it is printed as the one line it
|
|
122
|
+
* is; anything else is a bug in the framework and keeps its stack, because that stack is the report.
|
|
123
|
+
*
|
|
124
|
+
* This rule used to live in `build.ts`, as a `phase()` wrapper around three stages of one command — which
|
|
125
|
+
* left everything outside those three going out through a bare `console.error(error)`: the whole of
|
|
126
|
+
* `rshono dev`, and `build`'s own `createConfigs`, which is where a missing `src/routes.ts` is found. So the
|
|
127
|
+
* likeliest first-run mistake there is answered with a raw `Error` object and two frames of framework
|
|
128
|
+
* internals, which is the same shape of problem an unknown CLI flag had.
|
|
129
|
+
*/
|
|
130
|
+
main().catch(async (error) => {
|
|
131
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
132
|
+
if (message.startsWith('[rshono]'))
|
|
133
|
+
console.error(`\n ✗ ${message}\n`);
|
|
134
|
+
else
|
|
135
|
+
console.error(error);
|
|
136
|
+
await exit(1);
|
|
83
137
|
});
|
|
84
138
|
//# sourceMappingURL=index.js.map
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { createRequire } from 'node:module';\nimport { parseArgs } from 'node:util';\nimport { DEPLOY_TARGETS, resolveDeployPreset } from '../deploy/presets.js';\nimport { loadConfig } from '../server/load-config.js';\nimport { loadEnvFiles } from '../server/load-env.js';\nimport { parsePort } from '../server/server-config.js';\n\n// The commands are imported where they are dispatched: `build` and `dev` pull in Rspack, and a static import\n// would load it for `start` too — ~30 MB of RSS and ~70ms of startup that would then sit in the server's own\n// process for its whole life, since `start` imports the bundle rather than spawning it.\n\nconst HELP = `rshono — Hono + Rspack + React Server Components\n\nUsage:\n rshono dev [--port 3000] start the dev server\n rshono build build for production (client + server + SSG)\n rshono start [--port 3000] run the production build\n\nOptions:\n -p, --port <n> port to listen on (default: PORT env or 3000)\n -c, --config <path> path to a config file (default: rshono.config.{ts,js,mjs})\n -d, --deploy <name> platform to build for: ${DEPLOY_TARGETS.join(' | ')} (default: node)\n -h, --help show this help\n -v, --version print the version\n`;\n\n/** {@link parsePort}, reported the way the CLI reports every other bad input: one line, no stack. */\nfunction readPort(value: string | undefined, source: string): number | undefined {\n try {\n return parsePort(value, source);\n } catch (error) {\n console.error(`rshono: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n}\n\nasync function main(): Promise<void> {\n const { values, positionals } = parseArgs({\n options: {\n port: { type: 'string', short: 'p' },\n config: { type: 'string', short: 'c' },\n deploy: { type: 'string', short: 'd' },\n help: { type: 'boolean', short: 'h' },\n version: { type: 'boolean', short: 'v' },\n },\n allowPositionals: true,\n });\n\n if (values.version) {\n const require = createRequire(import.meta.url);\n const { version } = require('@rshono/core/package.json') as { version: string };\n console.log(version);\n return;\n }\n\n const command = positionals[0];\n if (values.help || !command) {\n console.log(HELP);\n return;\n }\n\n const rootDir = process.cwd();\n loadEnvFiles(rootDir);\n const config = await loadConfig(rootDir, values.config);\n\n // Precedence: --port flag > PORT env > the command's built-in default. Both sources go through the same\n // parse as the bundle's own, so `PORT=\"\"` means \"unset\" in the CLI and in the server it starts alike.\n const port = readPort(values.port, '--port') ?? readPort(process.env.PORT, 'PORT');\n const host = process.env.HOST;\n\n switch (command) {\n case 'dev':\n return (await import('./dev.js')).devCommand({ rootDir, port, config });\n case 'build':\n return (await import('./build.js')).buildCommand({\n rootDir,\n config,\n preset: resolveDeployPreset({ flag: values.deploy, env: process.env.RSHONO_DEPLOY, config: config.deploy }),\n });\n case 'start':\n return (await import('./start.js')).startCommand({ rootDir, port, host });\n default:\n console.error(`rshono: unknown command \"${command}\"\\n`);\n console.log(HELP);\n process.exit(1);\n }\n}\n\nmain().catch((error) => {\n console.error(error);\n process.exit(1);\n});\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { createRequire } from 'node:module';\nimport { parseArgs } from 'node:util';\nimport { DEPLOY_TARGETS, resolveDeployPreset } from '../deploy/presets.js';\nimport { loadConfig } from '../server/load-config.js';\nimport { loadEnvFiles } from '../server/load-env.js';\nimport { parsePort } from '../server/server-config.js';\nimport { exit } from './exit.js';\n\n// The commands are imported where they are dispatched: `build` and `dev` pull in Rspack, and a static import\n// would load it for `start` too — ~30 MB of RSS and ~70ms of startup that would then sit in the server's own\n// process for its whole life, since `start` imports the bundle rather than spawning it.\n\nconst HELP = `rshono — Hono + Rspack + React Server Components\n\nUsage:\n rshono dev [--port 3000] start the dev server\n rshono build build for production (client + server + SSG)\n rshono start [--port 3000] run the production build\n\nOptions:\n -p, --port <n> port to listen on (default: PORT env or 3000)\n -c, --config <path> path to a config file (default: rshono.config.{ts,js,mjs})\n -d, --deploy <name> platform to build for: ${DEPLOY_TARGETS.join(' | ')} (default: node)\n -h, --help show this help\n -v, --version print the version\n\nEnvironment:\n PORT port to listen on, unless --port is given\n HOST address \\`start\\` binds to (default 0.0.0.0); \\`dev\\` always binds 127.0.0.1\n RSHONO_DEPLOY platform to build for, unless --deploy is given\n`;\n\n/** `as const` so `parseArgs` can type `values` off the literal `type` fields rather than widening them. */\nconst CLI_OPTIONS = {\n port: { type: 'string', short: 'p' },\n config: { type: 'string', short: 'c' },\n deploy: { type: 'string', short: 'd' },\n help: { type: 'boolean', short: 'h' },\n version: { type: 'boolean', short: 'v' },\n} as const;\n\n/**\n * {@link parseArgs}, reported the way the CLI reports every other bad input: one line, then the help.\n *\n * A typo'd flag is the likeliest of the three bad inputs and used to get by far the worst output. `parseArgs`\n * was the first statement of `main`, with nothing between it and the `main().catch` that prints the raw error\n * object — so `rshono build --porf 3000` answered with nine frames of Node internals, where an unknown\n * command and an unparseable `--port` each answered with a sentence.\n *\n * Node's own message is kept: it names the offending flag, which is the whole content of the error, and\n * `HELP` beneath it lists the ones that exist. Through {@link exit} rather than `process.exit`, because that\n * help goes to stdout and a piped stdout drops whatever has not left the buffer.\n */\nasync function readArgs(): Promise<ReturnType<typeof parseArgs<{ options: typeof CLI_OPTIONS; allowPositionals: true }>>> {\n try {\n return parseArgs({ options: CLI_OPTIONS, allowPositionals: true });\n } catch (error) {\n console.error(`rshono: ${error instanceof Error ? error.message : String(error)}\\n`);\n console.log(HELP);\n return exit(1);\n }\n}\n\nasync function main(): Promise<void> {\n const { values, positionals } = await readArgs();\n\n if (values.version) {\n const require = createRequire(import.meta.url);\n const { version } = require('@rshono/core/package.json') as { version: string };\n console.log(version);\n return;\n }\n\n const command = positionals[0];\n if (values.help || !command) {\n console.log(HELP);\n return;\n }\n\n const rootDir = process.cwd();\n loadEnvFiles(rootDir);\n const config = await loadConfig(rootDir, values.config);\n\n // Precedence: --port flag > PORT env > the command's built-in default. Both sources go through the same\n // parse as the bundle's own, so `PORT=\"\"` means \"unset\" in the CLI and in the server it starts alike.\n //\n // The parse stays synchronous and the exit is here, where the other flag errors are answered, rather than\n // inside a `readPort` helper of its own. That helper had to reach `process.exit` directly — it is not\n // `async`, and `exit()` returns a promise — so it was the one bad-input path in the CLI that did not\n // drain a piped stderr. Making it `async` instead is the trap: `??` on a `Promise` is never nullish, so\n // `--port` would resolve to a pending promise and `PORT` would stop being read at all.\n let port: number | undefined;\n try {\n port = parsePort(values.port, '--port') ?? parsePort(process.env.PORT, 'PORT');\n } catch (error) {\n console.error(`rshono: ${error instanceof Error ? error.message : String(error)}`);\n return exit(1);\n }\n const host = process.env.HOST;\n\n switch (command) {\n case 'dev':\n // `HOST` belongs to `start`. The dev server binds loopback unconditionally — its source maps embed the\n // original source of `'use server'` modules — and `DevOptions` has no `host` field to pass one to, so\n // the drop is structural rather than conditional. Said out loud because the variable is read a few\n // lines up and the README lists it under all three commands: `HOST=0.0.0.0 rshono dev` used to do\n // nothing, with nothing to notice.\n if (host !== undefined) {\n console.warn('rshono: HOST is ignored by `rshono dev`, which always binds 127.0.0.1 — it applies to `rshono start`.');\n }\n return (await import('./dev.js')).devCommand({ rootDir, port, config });\n case 'build':\n return (await import('./build.js')).buildCommand({\n rootDir,\n config,\n preset: resolveDeployPreset({ flag: values.deploy, env: process.env.RSHONO_DEPLOY, config: config.deploy }),\n });\n case 'start':\n return (await import('./start.js')).startCommand({ rootDir, port, host });\n default:\n console.error(`rshono: unknown command \"${command}\"\\n`);\n console.log(HELP);\n return exit(1);\n }\n}\n\n/**\n * The one place a failure becomes output, for every command.\n *\n * A `[rshono]` message was written for whoever is running the command, so it is printed as the one line it\n * is; anything else is a bug in the framework and keeps its stack, because that stack is the report.\n *\n * This rule used to live in `build.ts`, as a `phase()` wrapper around three stages of one command — which\n * left everything outside those three going out through a bare `console.error(error)`: the whole of\n * `rshono dev`, and `build`'s own `createConfigs`, which is where a missing `src/routes.ts` is found. So the\n * likeliest first-run mistake there is answered with a raw `Error` object and two frames of framework\n * internals, which is the same shape of problem an unknown CLI flag had.\n */\nmain().catch(async (error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n if (message.startsWith('[rshono]')) console.error(`\\n ✗ ${message}\\n`);\n else console.error(error);\n await exit(1);\n});\n"]}
|
package/dist/cli/start.d.ts
CHANGED
package/dist/cli/start.js
CHANGED
|
@@ -3,13 +3,14 @@ import { join } from 'node:path';
|
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
4
|
import { readBuildMarker } from '../deploy/build-marker.js';
|
|
5
5
|
import { deployHintFor } from '../deploy/presets.js';
|
|
6
|
+
import { exit } from './exit.js';
|
|
6
7
|
export async function startCommand(options) {
|
|
7
8
|
const { rootDir, port, host } = options;
|
|
8
9
|
const distDir = join(rootDir, 'dist');
|
|
9
10
|
const mainPath = join(distDir, 'server', 'main.mjs');
|
|
10
11
|
if (!existsSync(mainPath)) {
|
|
11
12
|
console.error('rshono: no production build found — run `rshono build` first.');
|
|
12
|
-
|
|
13
|
+
return exit(1);
|
|
13
14
|
}
|
|
14
15
|
// A bundle built for a hosting platform has no listener in it, so starting one here would exit silently the
|
|
15
16
|
// moment the module finished evaluating.
|
|
@@ -18,7 +19,7 @@ export async function startCommand(options) {
|
|
|
18
19
|
const hint = deployHintFor(target);
|
|
19
20
|
console.error(`rshono: this build targets ${target}, which \`rshono start\` cannot run${hint ? ` — ${hint}` : '.'}`);
|
|
20
21
|
console.error(' Rebuild for a server with `rshono build --deploy node` to run it here.');
|
|
21
|
-
|
|
22
|
+
return exit(1);
|
|
22
23
|
}
|
|
23
24
|
// Read by the bundle as it evaluates, which is what binds the port — so they have to be set first.
|
|
24
25
|
if (port !== undefined)
|
package/dist/cli/start.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/cli/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/cli/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAQjC,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAqB;IACtD,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IACxC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;IACrD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,+DAA+D,CAAC,CAAC;QAC/E,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;IAED,4GAA4G;IAC5G,yCAAyC;IACzC,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACxC,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;QACnC,OAAO,CAAC,KAAK,CAAC,8BAA8B,MAAM,sCAAsC,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;QACrH,OAAO,CAAC,KAAK,CAAC,0EAA0E,CAAC,CAAC;QAC1F,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;IAED,mGAAmG;IACnG,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IACxD,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;IAEhD,mGAAmG;IACnG,wGAAwG;IACxG,2GAA2G;IAC3G,2GAA2G;IAC3G,mGAAmG;IACnG,MAAM,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC;AAC7C,CAAC","sourcesContent":["import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { readBuildMarker } from '../deploy/build-marker.js';\nimport { deployHintFor } from '../deploy/presets.js';\nimport { exit } from './exit.js';\n\ninterface StartOptions {\n rootDir: string;\n port?: number;\n host?: string;\n}\n\nexport async function startCommand(options: StartOptions): Promise<void> {\n const { rootDir, port, host } = options;\n const distDir = join(rootDir, 'dist');\n const mainPath = join(distDir, 'server', 'main.mjs');\n if (!existsSync(mainPath)) {\n console.error('rshono: no production build found — run `rshono build` first.');\n return exit(1);\n }\n\n // A bundle built for a hosting platform has no listener in it, so starting one here would exit silently the\n // moment the module finished evaluating.\n const target = readBuildMarker(distDir);\n if (target !== null && target !== 'node') {\n const hint = deployHintFor(target);\n console.error(`rshono: this build targets ${target}, which \\`rshono start\\` cannot run${hint ? ` — ${hint}` : '.'}`);\n console.error(' Rebuild for a server with `rshono build --deploy node` to run it here.');\n return exit(1);\n }\n\n // Read by the bundle as it evaluates, which is what binds the port — so they have to be set first.\n if (port !== undefined) process.env.PORT = String(port);\n if (host !== undefined) process.env.HOST = host;\n\n // Imported into this process rather than spawned into a child. The child only ever existed to pass\n // `--enable-source-maps`, and `bin/rshono.mjs` already enables the same thing in-process before the CLI\n // loads — so a supervisor bought a second PID and its own heap in every container, an extra frame in every\n // stack, and signal forwarding for signals the bundle already handles itself through `onShutdown`. `start`\n // deliberately imports no Rspack, so the process this leaves behind is the server and little else.\n await import(pathToFileURL(mainPath).href);\n}\n"]}
|
package/dist/config.d.ts
CHANGED
|
@@ -8,6 +8,11 @@ export declare function writeBuildMarker(distDir: string, deploy: DeployTarget):
|
|
|
8
8
|
* The target the build in `distDir` was produced for, or `null` when there is nothing to go on — a missing
|
|
9
9
|
* marker is not an error, since a build from an older rshono has none and refusing to start one that would
|
|
10
10
|
* have worked is worse than the failure this guards against.
|
|
11
|
+
*
|
|
12
|
+
* `string`, not {@link DeployTarget}: the file is on disk and whoever wrote it may be a *newer* rshono with
|
|
13
|
+
* a target this one has never heard of. Narrowing an unrecognised name to `null` would be the wrong repair —
|
|
14
|
+
* `rshono start`'s only use for this is refusing anything that is not `'node'`, so a `null` would let it
|
|
15
|
+
* start a build with no listener in it and exit silently, which is the failure the marker exists to prevent.
|
|
16
|
+
* Reporting the name it does not know is the deliberate behaviour; the return type now says so.
|
|
11
17
|
*/
|
|
12
|
-
export declare function readBuildMarker(distDir: string):
|
|
13
|
-
//# sourceMappingURL=build-marker.d.ts.map
|
|
18
|
+
export declare function readBuildMarker(distDir: string): string | null;
|
|
@@ -8,6 +8,12 @@ export function writeBuildMarker(distDir, deploy) {
|
|
|
8
8
|
* The target the build in `distDir` was produced for, or `null` when there is nothing to go on — a missing
|
|
9
9
|
* marker is not an error, since a build from an older rshono has none and refusing to start one that would
|
|
10
10
|
* have worked is worse than the failure this guards against.
|
|
11
|
+
*
|
|
12
|
+
* `string`, not {@link DeployTarget}: the file is on disk and whoever wrote it may be a *newer* rshono with
|
|
13
|
+
* a target this one has never heard of. Narrowing an unrecognised name to `null` would be the wrong repair —
|
|
14
|
+
* `rshono start`'s only use for this is refusing anything that is not `'node'`, so a `null` would let it
|
|
15
|
+
* start a build with no listener in it and exit silently, which is the failure the marker exists to prevent.
|
|
16
|
+
* Reporting the name it does not know is the deliberate behaviour; the return type now says so.
|
|
11
17
|
*/
|
|
12
18
|
export function readBuildMarker(distDir) {
|
|
13
19
|
const file = join(distDir, MARKER_FILE);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-marker.js","sourceRoot":"","sources":["../../src/deploy/build-marker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAQjC,MAAM,WAAW,GAAG,mBAAmB,CAAC;AAExC,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,MAAoB;IACpE,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAwB,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AAC9G,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"build-marker.js","sourceRoot":"","sources":["../../src/deploy/build-marker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAQjC,MAAM,WAAW,GAAG,mBAAmB,CAAC;AAExC,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,MAAoB;IACpE,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAwB,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AAC9G,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACxC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAyB,CAAC;QAC9E,OAAO,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IAClE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC","sourcesContent":["import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { DeployTarget } from './contract.js';\n\n/** Records which platform a build was for, so `rshono start` can refuse one it cannot run. */\nexport interface BuildMarker {\n deploy: DeployTarget;\n}\n\nconst MARKER_FILE = 'rshono-build.json';\n\nexport function writeBuildMarker(distDir: string, deploy: DeployTarget): void {\n writeFileSync(join(distDir, MARKER_FILE), `${JSON.stringify({ deploy } satisfies BuildMarker, null, 2)}\\n`);\n}\n\n/**\n * The target the build in `distDir` was produced for, or `null` when there is nothing to go on — a missing\n * marker is not an error, since a build from an older rshono has none and refusing to start one that would\n * have worked is worse than the failure this guards against.\n *\n * `string`, not {@link DeployTarget}: the file is on disk and whoever wrote it may be a *newer* rshono with\n * a target this one has never heard of. Narrowing an unrecognised name to `null` would be the wrong repair —\n * `rshono start`'s only use for this is refusing anything that is not `'node'`, so a `null` would let it\n * start a build with no listener in it and exit silently, which is the failure the marker exists to prevent.\n * Reporting the name it does not know is the deliberate behaviour; the return type now says so.\n */\nexport function readBuildMarker(distDir: string): string | null {\n const file = join(distDir, MARKER_FILE);\n if (!existsSync(file)) return null;\n try {\n const parsed = JSON.parse(readFileSync(file, 'utf8')) as Partial<BuildMarker>;\n return typeof parsed.deploy === 'string' ? parsed.deploy : null;\n } catch {\n return null;\n }\n}\n"]}
|
|
@@ -4,4 +4,3 @@ import type { DeployBuildContext } from '../presets.js';
|
|
|
4
4
|
* `wrangler.jsonc` to deploy with if the project has no Wrangler config of its own.
|
|
5
5
|
*/
|
|
6
6
|
export declare function finalizeCloudflareBuild(ctx: DeployBuildContext): Promise<void>;
|
|
7
|
-
//# sourceMappingURL=build.d.ts.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { cpSync, existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { rm } from 'node:fs/promises';
|
|
3
3
|
import { basename, join } from 'node:path';
|
|
4
|
+
import { publicRouteCollisions, warnAboutPublicCollisions } from '../public-paths.js';
|
|
4
5
|
/** Wrangler serves one directory, so the three kinds of asset the build produces are assembled into it. */
|
|
5
6
|
const ASSETS_DIR = join('cloudflare', 'assets');
|
|
6
7
|
const WRANGLER_FILES = ['wrangler.jsonc', 'wrangler.json', 'wrangler.toml'];
|
|
@@ -55,6 +56,11 @@ export async function finalizeCloudflareBuild(ctx) {
|
|
|
55
56
|
cpSync(ctx.publicDir, assetsDir, { recursive: true });
|
|
56
57
|
if (existsSync(ctx.ssgDir))
|
|
57
58
|
cpSync(ctx.ssgDir, join(assetsDir, '__ssg'), { recursive: true });
|
|
59
|
+
// Workers Assets is checked before the worker runs, so a `public/` file on a route's path answers instead
|
|
60
|
+
// of the route — the same collision Vercel has, and neither `node` nor `aws-lambda` does.
|
|
61
|
+
// `htmlExtensionless: true`: the binding's default HTML handling is `auto-trailing-slash`, so
|
|
62
|
+
// `about.html` answers `/about` here as well as `/about.html`.
|
|
63
|
+
warnAboutPublicCollisions(publicRouteCollisions(ctx.publicDir, ctx.routes, { htmlExtensionless: true }), 'cloudflare');
|
|
58
64
|
const headersFile = join(assetsDir, '_headers');
|
|
59
65
|
if (existsSync(headersFile)) {
|
|
60
66
|
console.warn(` ⚠ public/_headers is in the way of the generated one — /_static/* will not be marked immutable.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/deploy/cloudflare/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACvE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/deploy/cloudflare/build.ts"],"names":[],"mappings":"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","sourcesContent":["import { cpSync, existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { rm } from 'node:fs/promises';\nimport { basename, join } from 'node:path';\nimport type { DeployBuildContext } from '../presets.js';\nimport { publicRouteCollisions, warnAboutPublicCollisions } from '../public-paths.js';\n\n/** Wrangler serves one directory, so the three kinds of asset the build produces are assembled into it. */\nconst ASSETS_DIR = join('cloudflare', 'assets');\n\nconst WRANGLER_FILES = ['wrangler.jsonc', 'wrangler.json', 'wrangler.toml'];\n\n/**\n * Caching and crawler rules for the assembled tree, in the file Workers Assets reads them from: the hashed\n * bundle is immutable by construction, which the CDN cannot infer, and the prerender tree holds a second copy\n * of pages that already have real URLs — so it is marked `noindex`.\n */\nconst HEADERS_FILE = `/_static/*\n Cache-Control: public, max-age=31536000, immutable\n\n/__ssg/*\n X-Robots-Tag: noindex\n`;\n\n/** A Wrangler worker name: lowercase, and only the characters it accepts. */\nfunction workerName(rootDir: string): string {\n const name = basename(rootDir)\n .toLowerCase()\n .replace(/[^a-z0-9-]+/g, '-')\n .replace(/^-+|-+$/g, '');\n return name || 'rshono-app';\n}\n\n// Fixed, not the day the build ran: wrangler's bundled workerd refuses a date newer than its own, so a config\n// dated today would deploy fine and never start under `wrangler dev`.\nconst COMPATIBILITY_DATE = '2026-07-01';\n\nfunction wranglerConfig(rootDir: string): string {\n return `${JSON.stringify(\n {\n $schema: 'node_modules/wrangler/config-schema.json',\n name: workerName(rootDir),\n main: 'dist/server/main.mjs',\n compatibility_date: COMPATIBILITY_DATE,\n // For AsyncLocalStorage, which is how the request context behind `getRequestContext()` is bound.\n compatibility_flags: ['nodejs_compat'],\n assets: {\n directory: `dist/${ASSETS_DIR.split(/[\\\\/]/).join('/')}`,\n // Read by the worker for `public/` files and prerendered pages; the CDN still answers first.\n binding: 'ASSETS',\n },\n },\n null,\n 2,\n )}\\n`;\n}\n\n/**\n * Arranges a Workers deployment: one assets directory holding everything the CDN should serve, and a\n * `wrangler.jsonc` to deploy with if the project has no Wrangler config of its own.\n */\nexport async function finalizeCloudflareBuild(ctx: DeployBuildContext): Promise<void> {\n const assetsDir = join(ctx.distDir, ASSETS_DIR);\n // From scratch, so a deleted `public/` file or a route that stopped being static does not survive here.\n await rm(assetsDir, { recursive: true, force: true });\n mkdirSync(assetsDir, { recursive: true });\n\n cpSync(ctx.staticDir, join(assetsDir, '_static'), { recursive: true });\n if (ctx.publicDir) cpSync(ctx.publicDir, assetsDir, { recursive: true });\n if (existsSync(ctx.ssgDir)) cpSync(ctx.ssgDir, join(assetsDir, '__ssg'), { recursive: true });\n\n // Workers Assets is checked before the worker runs, so a `public/` file on a route's path answers instead\n // of the route — the same collision Vercel has, and neither `node` nor `aws-lambda` does.\n // `htmlExtensionless: true`: the binding's default HTML handling is `auto-trailing-slash`, so\n // `about.html` answers `/about` here as well as `/about.html`.\n warnAboutPublicCollisions(publicRouteCollisions(ctx.publicDir, ctx.routes, { htmlExtensionless: true }), 'cloudflare');\n\n const headersFile = join(assetsDir, '_headers');\n if (existsSync(headersFile)) {\n console.warn(` ⚠ public/_headers is in the way of the generated one — /_static/* will not be marked immutable.`);\n } else {\n writeFileSync(headersFile, HEADERS_FILE);\n }\n\n const existing = WRANGLER_FILES.find((file) => existsSync(join(ctx.rootDir, file)));\n if (!existing) {\n writeFileSync(join(ctx.rootDir, 'wrangler.jsonc'), wranglerConfig(ctx.rootDir));\n console.log(' • wrote wrangler.jsonc (yours now — edit freely, the build will not touch it again)');\n }\n\n console.log(` • assembled ${join('dist', ASSETS_DIR)} for Workers Assets`);\n}\n"]}
|