@elurjs/kit 2.4.4
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/CHANGELOG.md +874 -0
- package/LICENSE +21 -0
- package/README.md +1330 -0
- package/bin/elur-kit.js +54 -0
- package/dist/lib/action/define.d.cts +72 -0
- package/dist/lib/action/define.d.ts +72 -0
- package/dist/lib/action/error-store.d.cts +29 -0
- package/dist/lib/action/error-store.d.ts +29 -0
- package/dist/lib/action/index.cjs +1 -0
- package/dist/lib/action/index.d.cts +64 -0
- package/dist/lib/action/index.d.ts +64 -0
- package/dist/lib/action/index.js +2 -0
- package/dist/lib/action/origin.d.cts +20 -0
- package/dist/lib/action/origin.d.ts +20 -0
- package/dist/lib/action/scan.d.cts +28 -0
- package/dist/lib/action/scan.d.ts +28 -0
- package/dist/lib/action/server.d.cts +30 -0
- package/dist/lib/action/server.d.ts +30 -0
- package/dist/lib/action-BB6N5yD-.js +111 -0
- package/dist/lib/action-BB6N5yD-.js.map +1 -0
- package/dist/lib/action-DZHihU3Z.cjs +2 -0
- package/dist/lib/action-DZHihU3Z.cjs.map +1 -0
- package/dist/lib/adapters/bun.cjs +30 -0
- package/dist/lib/adapters/bun.cjs.map +1 -0
- package/dist/lib/adapters/bun.d.cts +13 -0
- package/dist/lib/adapters/bun.d.ts +13 -0
- package/dist/lib/adapters/bun.js +65 -0
- package/dist/lib/adapters/bun.js.map +1 -0
- package/dist/lib/adapters/index.cjs +0 -0
- package/dist/lib/adapters/index.d.cts +30 -0
- package/dist/lib/adapters/index.d.ts +30 -0
- package/dist/lib/adapters/index.js +0 -0
- package/dist/lib/adapters/netlify.cjs +10 -0
- package/dist/lib/adapters/netlify.cjs.map +1 -0
- package/dist/lib/adapters/netlify.d.cts +13 -0
- package/dist/lib/adapters/netlify.d.ts +13 -0
- package/dist/lib/adapters/netlify.js +51 -0
- package/dist/lib/adapters/netlify.js.map +1 -0
- package/dist/lib/adapters/node.cjs +46 -0
- package/dist/lib/adapters/node.cjs.map +1 -0
- package/dist/lib/adapters/node.d.cts +13 -0
- package/dist/lib/adapters/node.d.ts +13 -0
- package/dist/lib/adapters/node.js +105 -0
- package/dist/lib/adapters/node.js.map +1 -0
- package/dist/lib/adapters/shared.d.cts +17 -0
- package/dist/lib/adapters/shared.d.ts +17 -0
- package/dist/lib/adapters/vercel.cjs +2 -0
- package/dist/lib/adapters/vercel.cjs.map +1 -0
- package/dist/lib/adapters/vercel.d.cts +9 -0
- package/dist/lib/adapters/vercel.d.ts +9 -0
- package/dist/lib/adapters/vercel.js +62 -0
- package/dist/lib/adapters/vercel.js.map +1 -0
- package/dist/lib/build/build.d.cts +83 -0
- package/dist/lib/build/build.d.ts +83 -0
- package/dist/lib/build/document-shell.d.cts +48 -0
- package/dist/lib/build/document-shell.d.ts +48 -0
- package/dist/lib/build/transform-source.d.cts +26 -0
- package/dist/lib/build/transform-source.d.ts +26 -0
- package/dist/lib/build/vite-build.d.cts +78 -0
- package/dist/lib/build/vite-build.d.ts +78 -0
- package/dist/lib/cache/policy.d.cts +25 -0
- package/dist/lib/cache/policy.d.ts +25 -0
- package/dist/lib/cache.d.cts +13 -0
- package/dist/lib/cache.d.ts +13 -0
- package/dist/lib/capabilities-C0TDQoMY.cjs +2 -0
- package/dist/lib/capabilities-C0TDQoMY.cjs.map +1 -0
- package/dist/lib/capabilities-C7txofmY.js +45 -0
- package/dist/lib/capabilities-C7txofmY.js.map +1 -0
- package/dist/lib/cli/commands.d.cts +15 -0
- package/dist/lib/cli/commands.d.ts +15 -0
- package/dist/lib/cli.cjs +5132 -0
- package/dist/lib/cli.cjs.map +1 -0
- package/dist/lib/cli.d.cts +30 -0
- package/dist/lib/cli.d.ts +30 -0
- package/dist/lib/cli.js +5131 -0
- package/dist/lib/cli.js.map +1 -0
- package/dist/lib/collections-Dbc8aRLf.js +233 -0
- package/dist/lib/collections-Dbc8aRLf.js.map +1 -0
- package/dist/lib/collections-VDy5g9p8.cjs +13 -0
- package/dist/lib/collections-VDy5g9p8.cjs.map +1 -0
- package/dist/lib/config/index.cjs +2 -0
- package/dist/lib/config/index.cjs.map +1 -0
- package/dist/lib/config/index.d.cts +100 -0
- package/dist/lib/config/index.d.ts +100 -0
- package/dist/lib/config/index.js +122 -0
- package/dist/lib/config/index.js.map +1 -0
- package/dist/lib/content/collections.d.cts +69 -0
- package/dist/lib/content/collections.d.ts +69 -0
- package/dist/lib/content/frontmatter.d.cts +20 -0
- package/dist/lib/content/frontmatter.d.ts +20 -0
- package/dist/lib/content/index.cjs +2 -0
- package/dist/lib/content/index.cjs.map +1 -0
- package/dist/lib/content/index.d.cts +5 -0
- package/dist/lib/content/index.d.ts +5 -0
- package/dist/lib/content/index.js +28 -0
- package/dist/lib/content/index.js.map +1 -0
- package/dist/lib/content/markdown.d.cts +6 -0
- package/dist/lib/content/markdown.d.ts +6 -0
- package/dist/lib/content/raw.d.cts +9 -0
- package/dist/lib/content/raw.d.ts +9 -0
- package/dist/lib/content/schema.d.cts +14 -0
- package/dist/lib/content/schema.d.ts +14 -0
- package/dist/lib/errors-0X7pCFNU.cjs +2 -0
- package/dist/lib/errors-0X7pCFNU.cjs.map +1 -0
- package/dist/lib/errors-ePYxDlhU.js +70 -0
- package/dist/lib/errors-ePYxDlhU.js.map +1 -0
- package/dist/lib/errors.d.cts +84 -0
- package/dist/lib/errors.d.ts +84 -0
- package/dist/lib/hydrate-8a3TbQbs.cjs +2 -0
- package/dist/lib/hydrate-8a3TbQbs.cjs.map +1 -0
- package/dist/lib/hydrate-CgZGrTxF.js +126 -0
- package/dist/lib/hydrate-CgZGrTxF.js.map +1 -0
- package/dist/lib/image/index.cjs +2 -0
- package/dist/lib/image/index.cjs.map +1 -0
- package/dist/lib/image/index.d.cts +37 -0
- package/dist/lib/image/index.d.ts +37 -0
- package/dist/lib/image/index.js +49 -0
- package/dist/lib/image/index.js.map +1 -0
- package/dist/lib/image/pipeline.d.cts +37 -0
- package/dist/lib/image/pipeline.d.ts +37 -0
- package/dist/lib/image/registry.cjs +2 -0
- package/dist/lib/image/registry.cjs.map +1 -0
- package/dist/lib/image/registry.d.cts +26 -0
- package/dist/lib/image/registry.d.ts +26 -0
- package/dist/lib/image/registry.js +23 -0
- package/dist/lib/image/registry.js.map +1 -0
- package/dist/lib/image/service.cjs +2 -0
- package/dist/lib/image/service.cjs.map +1 -0
- package/dist/lib/image/service.d.cts +164 -0
- package/dist/lib/image/service.d.ts +164 -0
- package/dist/lib/image/service.js +308 -0
- package/dist/lib/image/service.js.map +1 -0
- package/dist/lib/index.cjs +1 -0
- package/dist/lib/index.cjs.map +1 -0
- package/dist/lib/index.d.cts +38 -0
- package/dist/lib/index.d.ts +38 -0
- package/dist/lib/index.js +1 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/integrations/hooks.d.cts +58 -0
- package/dist/lib/integrations/hooks.d.ts +58 -0
- package/dist/lib/integrations/index.cjs +1 -0
- package/dist/lib/integrations/index.d.cts +18 -0
- package/dist/lib/integrations/index.d.ts +18 -0
- package/dist/lib/integrations/index.js +2 -0
- package/dist/lib/integrations-7dpN1RYB.js +35 -0
- package/dist/lib/integrations-7dpN1RYB.js.map +1 -0
- package/dist/lib/integrations-DDqfWjvH.cjs +2 -0
- package/dist/lib/integrations-DDqfWjvH.cjs.map +1 -0
- package/dist/lib/interpolation-plugin-Bt-KRKVY.js +365 -0
- package/dist/lib/interpolation-plugin-Bt-KRKVY.js.map +1 -0
- package/dist/lib/interpolation-plugin-CMPCDlVJ.cjs +31 -0
- package/dist/lib/interpolation-plugin-CMPCDlVJ.cjs.map +1 -0
- package/dist/lib/island/generate-entry.d.cts +27 -0
- package/dist/lib/island/generate-entry.d.ts +27 -0
- package/dist/lib/island/hydrate.d.cts +33 -0
- package/dist/lib/island/hydrate.d.ts +33 -0
- package/dist/lib/island/index.cjs +1 -0
- package/dist/lib/island/index.d.cts +2 -0
- package/dist/lib/island/index.d.ts +2 -0
- package/dist/lib/island/index.js +1 -0
- package/dist/lib/island/island.d.cts +32 -0
- package/dist/lib/island/island.d.ts +32 -0
- package/dist/lib/island/scan.d.cts +14 -0
- package/dist/lib/island/scan.d.ts +14 -0
- package/dist/lib/manifest/index.cjs +3 -0
- package/dist/lib/manifest/index.cjs.map +1 -0
- package/dist/lib/manifest/index.d.cts +18 -0
- package/dist/lib/manifest/index.d.ts +18 -0
- package/dist/lib/manifest/index.js +110 -0
- package/dist/lib/manifest/index.js.map +1 -0
- package/dist/lib/middleware/index.d.cts +56 -0
- package/dist/lib/middleware/index.d.ts +56 -0
- package/dist/lib/middleware/stream-boundary.d.cts +53 -0
- package/dist/lib/middleware/stream-boundary.d.ts +53 -0
- package/dist/lib/node-http-DRAUhO0c.js +617 -0
- package/dist/lib/node-http-DRAUhO0c.js.map +1 -0
- package/dist/lib/node-http-DhxguYyz.cjs +13 -0
- package/dist/lib/node-http-DhxguYyz.cjs.map +1 -0
- package/dist/lib/render/render-to-string.d.cts +12 -0
- package/dist/lib/render/render-to-string.d.ts +12 -0
- package/dist/lib/render/ssr-flag.d.cts +4 -0
- package/dist/lib/render/ssr-flag.d.ts +4 -0
- package/dist/lib/route-scanner-JY6YrNH5.cjs +2 -0
- package/dist/lib/route-scanner-JY6YrNH5.cjs.map +1 -0
- package/dist/lib/route-scanner-XcLId7lK.js +100 -0
- package/dist/lib/route-scanner-XcLId7lK.js.map +1 -0
- package/dist/lib/router/client.cjs +2 -0
- package/dist/lib/router/client.cjs.map +1 -0
- package/dist/lib/router/client.d.cts +47 -0
- package/dist/lib/router/client.d.ts +47 -0
- package/dist/lib/router/client.js +298 -0
- package/dist/lib/router/client.js.map +1 -0
- package/dist/lib/router/route-scanner.d.cts +50 -0
- package/dist/lib/router/route-scanner.d.ts +50 -0
- package/dist/lib/runtime/capabilities.d.cts +47 -0
- package/dist/lib/runtime/capabilities.d.ts +47 -0
- package/dist/lib/runtime/context.d.cts +140 -0
- package/dist/lib/runtime/context.d.ts +140 -0
- package/dist/lib/runtime/handler.d.cts +39 -0
- package/dist/lib/runtime/handler.d.ts +39 -0
- package/dist/lib/runtime/index.cjs +1 -0
- package/dist/lib/runtime/index.d.cts +6 -0
- package/dist/lib/runtime/index.d.ts +6 -0
- package/dist/lib/runtime/index.js +4 -0
- package/dist/lib/runtime/node-http.d.cts +2 -0
- package/dist/lib/runtime/node-http.d.ts +2 -0
- package/dist/lib/runtime/security-headers.d.cts +13 -0
- package/dist/lib/runtime/security-headers.d.ts +13 -0
- package/dist/lib/runtime/static.d.cts +1 -0
- package/dist/lib/runtime/static.d.ts +1 -0
- package/dist/lib/runtime-CrH5X-Es.cjs +2 -0
- package/dist/lib/runtime-CrH5X-Es.cjs.map +1 -0
- package/dist/lib/runtime-Ds2-wH6P.js +520 -0
- package/dist/lib/runtime-Ds2-wH6P.js.map +1 -0
- package/dist/lib/scan-CY2O9ty6.cjs +2 -0
- package/dist/lib/scan-CY2O9ty6.cjs.map +1 -0
- package/dist/lib/scan-CjMUgnsd.js +22 -0
- package/dist/lib/scan-CjMUgnsd.js.map +1 -0
- package/dist/lib/scan-DXzYtmRQ.cjs +2 -0
- package/dist/lib/scan-DXzYtmRQ.cjs.map +1 -0
- package/dist/lib/scan-Dn93ycXG.js +33 -0
- package/dist/lib/scan-Dn93ycXG.js.map +1 -0
- package/dist/lib/seo/index.cjs +10 -0
- package/dist/lib/seo/index.cjs.map +1 -0
- package/dist/lib/seo/index.d.cts +99 -0
- package/dist/lib/seo/index.d.ts +99 -0
- package/dist/lib/seo/index.js +41 -0
- package/dist/lib/seo/index.js.map +1 -0
- package/dist/lib/shared-CfqOLsKj.cjs +183 -0
- package/dist/lib/shared-CfqOLsKj.cjs.map +1 -0
- package/dist/lib/shared-DU3iQgr7.js +236 -0
- package/dist/lib/shared-DU3iQgr7.js.map +1 -0
- package/dist/lib/ssr/match.d.cts +25 -0
- package/dist/lib/ssr/match.d.ts +25 -0
- package/dist/lib/ssr/render.d.cts +62 -0
- package/dist/lib/ssr/render.d.ts +62 -0
- package/dist/lib/ssr/server.d.cts +41 -0
- package/dist/lib/ssr/server.d.ts +41 -0
- package/dist/lib/ssr/stream.d.cts +48 -0
- package/dist/lib/ssr/stream.d.ts +48 -0
- package/dist/lib/stream-CpOG052V.js +104 -0
- package/dist/lib/stream-CpOG052V.js.map +1 -0
- package/dist/lib/stream-DmZjYqHm.cjs +17 -0
- package/dist/lib/stream-DmZjYqHm.cjs.map +1 -0
- package/dist/lib/types.d.cts +97 -0
- package/dist/lib/types.d.ts +97 -0
- package/dist/lib/vite/index.cjs +2 -0
- package/dist/lib/vite/index.cjs.map +1 -0
- package/dist/lib/vite/index.d.cts +41 -0
- package/dist/lib/vite/index.d.ts +41 -0
- package/dist/lib/vite/index.js +229 -0
- package/dist/lib/vite/index.js.map +1 -0
- package/dist/lib/vite/interpolation-plugin.d.cts +64 -0
- package/dist/lib/vite/interpolation-plugin.d.ts +64 -0
- package/package.json +292 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-BB6N5yD-.js","names":[],"sources":["../../src/action/define.ts","../../src/action/index.ts"],"sourcesContent":["// --- defineAction(): typed server action definition (plan §9.2) ---\n//\n// Provides a typed wrapper for server actions with:\n// - optional input schema validation (without requiring Zod)\n// - AbortSignal propagation from the request\n// - idempotency key support\n// - concurrency modes (latest, queue, parallel)\n//\n// Legacy exported async functions continue to work: `defineAction()` is an\n// opt-in upgrade path, not a replacement.\n\nimport type { ActionFailure } from \"../errors.js\";\n\n// Capture AbortController at module load time — tests may temporarily remove\n// it from the global scope.\nconst AbortControllerCtor = globalThis.AbortController;\n\n/** Concurrency mode for actions called multiple times in rapid succession. */\nexport type ActionConcurrencyMode = \"latest\" | \"queue\" | \"parallel\";\n\n/** Options for defining a typed server action. */\nexport interface DefineActionOptions<TInput> {\n /**\n * Optional input validator. Can be a Zod schema, a plain function, or any\n * object with a `.parse()` method. If validation fails, the action returns\n * a 400 ActionFailure with the validation error.\n */\n input?: ActionInputValidator<TInput>;\n /** Concurrency mode when the same action is called multiple times. */\n concurrency?: ActionConcurrencyMode;\n /** Whether the action is idempotent (safe to retry). */\n idempotent?: boolean;\n /** Tags to invalidate from the cache after a successful action (§9.4). */\n invalidateTags?: string[];\n /** Paths to invalidate from the cache after a successful action (§9.4). */\n invalidatePaths?: string[];\n}\n\n/** A validator that has a `.parse()` method (Zod-compatible) or is a function. */\nexport interface ActionInputValidator<T> {\n parse(input: unknown): T;\n}\n\n/** Context passed to a defined action. */\nexport interface ActionContext {\n /** The original Web Request. */\n request: Request;\n /** AbortSignal from the request — aborts if the client disconnects. */\n signal: AbortSignal;\n /** Idempotency key from the request header, if present. */\n idempotencyKey?: string;\n /** Route params (for page-scoped actions). */\n params: Record<string, string | string[]>;\n /** Per-request locals (populated by middleware). */\n locals: Record<string, unknown>;\n}\n\n/** A defined action function. */\nexport type DefinedActionFn<TInput, TOutput> = (\n input: TInput,\n ctx: ActionContext,\n) => Promise<TOutput | ActionFailure<TOutput>>;\n\n/** The return type of defineAction(): a callable with metadata. */\nexport interface DefinedAction<TInput, TOutput> {\n (input: TInput, ctx: ActionContext): Promise<TOutput | ActionFailure<TOutput>>;\n /** Metadata for the action (used by the runtime/manifest). */\n __elurAction: {\n name: string;\n concurrency: ActionConcurrencyMode;\n idempotent: boolean;\n invalidateTags: readonly string[];\n invalidatePaths: readonly string[];\n };\n}\n\n/**\n * Defines a typed server action with validation, abort support, and cache\n * invalidation metadata.\n *\n * ```ts\n * import { defineAction, fail } from \"@elurjs/kit/action\";\n *\n * export const submitContact = defineAction({\n * input: { parse: (v) => v as { name: string; email: string } },\n * invalidateTags: [\"contacts\"],\n * }, async (input, ctx) => {\n * if (!input.email.includes(\"@\")) return fail(400, { email: \"Invalid\" });\n * await saveContact(input);\n * return { success: true };\n * });\n * ```\n *\n * Legacy exported async functions (without `defineAction`) continue to work\n * as before — this is an opt-in upgrade.\n */\nexport function defineAction<TInput = unknown, TOutput = unknown>(\n options: DefineActionOptions<TInput>,\n handler: DefinedActionFn<TInput, TOutput>,\n): DefinedAction<TInput, TOutput> {\n const concurrency = options.concurrency ?? \"latest\";\n const idempotent = options.idempotent ?? false;\n const invalidateTags = options.invalidateTags ?? [];\n const invalidatePaths = options.invalidatePaths ?? [];\n\n // Track in-flight calls for concurrency control.\n let latestController: InstanceType<typeof AbortControllerCtor> | null = null;\n const queue: Array<() => void> = [];\n let running = 0;\n\n async function run(\n input: TInput,\n ctx: ActionContext,\n ): Promise<TOutput | ActionFailure<TOutput>> {\n // Validate input if a validator is configured.\n if (options.input) {\n try {\n const validated = options.input.parse(input);\n input = validated;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const { fail } = await import(\"../errors.js\");\n return fail(400, { validation: message }) as ActionFailure<TOutput>;\n }\n }\n\n return handler(input, ctx);\n }\n\n const fn = async (input: TInput, ctx: ActionContext): Promise<TOutput | ActionFailure<TOutput>> => {\n if (concurrency === \"latest\") {\n // Cancel any previous in-flight call.\n if (latestController) latestController.abort();\n latestController = new AbortControllerCtor();\n // Combine the request signal with our cancellation signal.\n const combinedSignal = combineSignals(ctx.signal, latestController.signal);\n return run(input, { ...ctx, signal: combinedSignal });\n }\n\n if (concurrency === \"queue\") {\n // Wait for previous calls to finish.\n if (running > 0) {\n await new Promise<void>((resolve) => queue.push(resolve));\n }\n running++;\n try {\n return await run(input, ctx);\n } finally {\n running--;\n const next = queue.shift();\n if (next) next();\n }\n }\n\n // parallel: just run it.\n return run(input, ctx);\n };\n\n // Attach metadata.\n (fn as DefinedAction<TInput, TOutput>).__elurAction = {\n name: handler.name || \"anonymous\",\n concurrency,\n idempotent,\n invalidateTags,\n invalidatePaths,\n };\n\n return fn as DefinedAction<TInput, TOutput>;\n}\n\n/** Combines two AbortSignals into one that aborts when either does. */\nfunction combineSignals(...signals: (AbortSignal | undefined)[]): AbortSignal {\n const controller = new AbortControllerCtor();\n for (const signal of signals) {\n if (!signal) continue;\n if (signal.aborted) {\n controller.abort();\n break;\n }\n signal.addEventListener(\"abort\", () => controller.abort(), { once: true });\n }\n return controller.signal;\n}\n","/**\n * Client-side helpers for invoking server actions.\n *\n * Server actions are defined in `page.action.ts` files next to `page.ts`.\n * They export async functions that run on the server. On the client, call them\n * by name using `callAction` or the higher-level `elurJsAction` helper:\n *\n * ```ts\n * import { callAction } from \"@elurjs/kit/action\";\n *\n * const result = await callAction(\"submitContact\", { name: \"Ada\" }, { page: \"/contact\" });\n * ```\n *\n * ```ts\n * import { elurJsAction } from \"@elurjs/kit/action\";\n *\n * const contact = elurJsAction(\"submitContact\", { page: \"/contact\" });\n * await contact.submit({ name: \"Ada\" });\n * console.log(contact.data.value, contact.error.value, contact.pending.value);\n * ```\n */\n\nimport { signal } from \"@elurjs/core\";\nimport { ActionFailure, RedirectResponse } from \"../errors.js\";\n\ninterface ActionFailurePayload {\n __elur_js_action_failure?: boolean;\n status?: number;\n data?: unknown;\n}\n\ninterface RedirectPayload {\n __elur_js_action_redirect?: boolean;\n status?: number;\n location?: string;\n}\n\nfunction isActionFailurePayload(value: unknown): value is ActionFailurePayload & { __elur_js_action_failure: true } {\n return typeof value === \"object\" && value !== null && (value as Record<string, unknown>).__elur_js_action_failure === true;\n}\n\nfunction isRedirectPayload(value: unknown): value is RedirectPayload & { __elur_js_action_redirect: true } {\n return typeof value === \"object\" && value !== null && (value as Record<string, unknown>).__elur_js_action_redirect === true;\n}\n\nexport interface ActionRequest {\n name: string;\n page?: string;\n args: unknown[];\n}\n\nexport interface CallActionOptions {\n /** Page URL path that scopes the action, e.g. `/contact`. */\n page?: string;\n}\n\n/**\n * Call a server action by name.\n *\n * The request is sent as a POST to `/__elur-js/actions` with the action name,\n * optional page scope, and serialized arguments. The server executes the\n * matching exported function from the scanned `page.action.ts` modules and\n * returns its JSON result.\n */\nexport async function callAction<T = unknown>(\n name: string,\n args: unknown = [],\n options: CallActionOptions = {},\n): Promise<T | ActionFailure<T> | RedirectResponse> {\n const argsArray = Array.isArray(args) ? args : [args];\n const res = await fetch(\"/__elur-js/actions\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n },\n body: JSON.stringify({ name, page: options.page, args: argsArray } as ActionRequest),\n });\n\n const text = await res.text();\n if (!res.ok) {\n let payload: unknown;\n try {\n payload = JSON.parse(text);\n } catch {\n // not JSON, treat as plain error\n }\n if (isActionFailurePayload(payload) && payload.status !== undefined) {\n return new ActionFailure(payload.status, payload.data as T);\n }\n throw new Error(`Action \"${name}\" failed: ${text}`);\n }\n\n const payload: unknown = JSON.parse(text);\n if (isRedirectPayload(payload) && payload.status !== undefined && payload.location !== undefined) {\n return new RedirectResponse(payload.status, payload.location);\n }\n\n return payload as T;\n}\n\nexport interface ElurJsAction<TInput = unknown, TOutput = unknown> {\n /** Submit the action with the given input. */\n submit(input: TInput): Promise<TOutput | ActionFailure<TOutput> | RedirectResponse>;\n /** Signal that is true while the action is running. */\n pending: { value: boolean };\n /** Signal with the last successful result, action failure, redirect, or null. */\n data: { value: TOutput | ActionFailure<TOutput> | RedirectResponse | null };\n /** Signal with the last error, or null. */\n error: { value: Error | null };\n}\n\n/**\n * Create a reactive handle for a server action.\n *\n * Returns a `submit` function and signals for `pending`, `data`, and `error`.\n * Useful for wiring actions to forms and islands without manual signal boilerplate.\n */\nexport function elurJsAction<TInput = unknown, TOutput = unknown>(\n name: string,\n options: CallActionOptions = {},\n): ElurJsAction<TInput, TOutput> {\n const pending = signal(false);\n const error = signal<Error | null>(null);\n const data = signal<TOutput | ActionFailure<TOutput> | RedirectResponse | null>(null);\n\n async function submit(input: TInput): Promise<TOutput | ActionFailure<TOutput> | RedirectResponse> {\n pending.value = true;\n error.value = null;\n try {\n const result = await callAction<TOutput>(name, input, options);\n data.value = result;\n return result;\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err));\n throw err;\n } finally {\n pending.value = false;\n }\n }\n\n return {\n submit,\n pending,\n data,\n error,\n };\n}\n\n// Server-side: defineAction() for typed actions with validation/abort/cache.\nexport {\n defineAction,\n type DefineActionOptions,\n type DefinedAction,\n type DefinedActionFn,\n type ActionContext,\n type ActionInputValidator,\n type ActionConcurrencyMode,\n} from \"./define.js\";\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("./errors-0X7pCFNU.cjs");let t=require("@elurjs/core");var n=globalThis.AbortController;function r(e,t){let r=e.concurrency??`latest`,a=e.idempotent??!1,o=e.invalidateTags??[],s=e.invalidatePaths??[],c=null,l=[],u=0;async function d(n,r){if(e.input)try{n=e.input.parse(n)}catch(e){let t=e instanceof Error?e.message:String(e),{fail:n}=await Promise.resolve().then(()=>require("./errors-0X7pCFNU.cjs")).then(e=>e.r);return n(400,{validation:t})}return t(n,r)}let f=async(e,t)=>{if(r===`latest`){c&&c.abort(),c=new n;let r=i(t.signal,c.signal);return d(e,{...t,signal:r})}if(r===`queue`){u>0&&await new Promise(e=>l.push(e)),u++;try{return await d(e,t)}finally{u--;let e=l.shift();e&&e()}}return d(e,t)};return f.__elurAction={name:t.name||`anonymous`,concurrency:r,idempotent:a,invalidateTags:o,invalidatePaths:s},f}function i(...e){let t=new n;for(let n of e)if(n){if(n.aborted){t.abort();break}n.addEventListener(`abort`,()=>t.abort(),{once:!0})}return t.signal}function a(e){return typeof e==`object`&&!!e&&e.__elur_js_action_failure===!0}function o(e){return typeof e==`object`&&!!e&&e.__elur_js_action_redirect===!0}async function s(t,n=[],r={}){let i=Array.isArray(n)?n:[n],s=await fetch(`/__elur-js/actions`,{method:`POST`,headers:{"Content-Type":`application/json`,Accept:`application/json`},body:JSON.stringify({name:t,page:r.page,args:i})}),c=await s.text();if(!s.ok){let n;try{n=JSON.parse(c)}catch{}if(a(n)&&n.status!==void 0)return new e.t(n.status,n.data);throw Error(`Action "${t}" failed: ${c}`)}let l=JSON.parse(c);return o(l)&&l.status!==void 0&&l.location!==void 0?new e.n(l.status,l.location):l}function c(e,n={}){let r=(0,t.signal)(!1),i=(0,t.signal)(null),a=(0,t.signal)(null);async function o(t){r.value=!0,i.value=null;try{let r=await s(e,t,n);return a.value=r,r}catch(e){throw i.value=e instanceof Error?e:Error(String(e)),e}finally{r.value=!1}}return{submit:o,pending:r,data:a,error:i}}Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return s}});
|
|
2
|
+
//# sourceMappingURL=action-DZHihU3Z.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-DZHihU3Z.cjs","names":[],"sources":["../../src/action/define.ts","../../src/action/index.ts"],"sourcesContent":["// --- defineAction(): typed server action definition (plan §9.2) ---\n//\n// Provides a typed wrapper for server actions with:\n// - optional input schema validation (without requiring Zod)\n// - AbortSignal propagation from the request\n// - idempotency key support\n// - concurrency modes (latest, queue, parallel)\n//\n// Legacy exported async functions continue to work: `defineAction()` is an\n// opt-in upgrade path, not a replacement.\n\nimport type { ActionFailure } from \"../errors.js\";\n\n// Capture AbortController at module load time — tests may temporarily remove\n// it from the global scope.\nconst AbortControllerCtor = globalThis.AbortController;\n\n/** Concurrency mode for actions called multiple times in rapid succession. */\nexport type ActionConcurrencyMode = \"latest\" | \"queue\" | \"parallel\";\n\n/** Options for defining a typed server action. */\nexport interface DefineActionOptions<TInput> {\n /**\n * Optional input validator. Can be a Zod schema, a plain function, or any\n * object with a `.parse()` method. If validation fails, the action returns\n * a 400 ActionFailure with the validation error.\n */\n input?: ActionInputValidator<TInput>;\n /** Concurrency mode when the same action is called multiple times. */\n concurrency?: ActionConcurrencyMode;\n /** Whether the action is idempotent (safe to retry). */\n idempotent?: boolean;\n /** Tags to invalidate from the cache after a successful action (§9.4). */\n invalidateTags?: string[];\n /** Paths to invalidate from the cache after a successful action (§9.4). */\n invalidatePaths?: string[];\n}\n\n/** A validator that has a `.parse()` method (Zod-compatible) or is a function. */\nexport interface ActionInputValidator<T> {\n parse(input: unknown): T;\n}\n\n/** Context passed to a defined action. */\nexport interface ActionContext {\n /** The original Web Request. */\n request: Request;\n /** AbortSignal from the request — aborts if the client disconnects. */\n signal: AbortSignal;\n /** Idempotency key from the request header, if present. */\n idempotencyKey?: string;\n /** Route params (for page-scoped actions). */\n params: Record<string, string | string[]>;\n /** Per-request locals (populated by middleware). */\n locals: Record<string, unknown>;\n}\n\n/** A defined action function. */\nexport type DefinedActionFn<TInput, TOutput> = (\n input: TInput,\n ctx: ActionContext,\n) => Promise<TOutput | ActionFailure<TOutput>>;\n\n/** The return type of defineAction(): a callable with metadata. */\nexport interface DefinedAction<TInput, TOutput> {\n (input: TInput, ctx: ActionContext): Promise<TOutput | ActionFailure<TOutput>>;\n /** Metadata for the action (used by the runtime/manifest). */\n __elurAction: {\n name: string;\n concurrency: ActionConcurrencyMode;\n idempotent: boolean;\n invalidateTags: readonly string[];\n invalidatePaths: readonly string[];\n };\n}\n\n/**\n * Defines a typed server action with validation, abort support, and cache\n * invalidation metadata.\n *\n * ```ts\n * import { defineAction, fail } from \"@elurjs/kit/action\";\n *\n * export const submitContact = defineAction({\n * input: { parse: (v) => v as { name: string; email: string } },\n * invalidateTags: [\"contacts\"],\n * }, async (input, ctx) => {\n * if (!input.email.includes(\"@\")) return fail(400, { email: \"Invalid\" });\n * await saveContact(input);\n * return { success: true };\n * });\n * ```\n *\n * Legacy exported async functions (without `defineAction`) continue to work\n * as before — this is an opt-in upgrade.\n */\nexport function defineAction<TInput = unknown, TOutput = unknown>(\n options: DefineActionOptions<TInput>,\n handler: DefinedActionFn<TInput, TOutput>,\n): DefinedAction<TInput, TOutput> {\n const concurrency = options.concurrency ?? \"latest\";\n const idempotent = options.idempotent ?? false;\n const invalidateTags = options.invalidateTags ?? [];\n const invalidatePaths = options.invalidatePaths ?? [];\n\n // Track in-flight calls for concurrency control.\n let latestController: InstanceType<typeof AbortControllerCtor> | null = null;\n const queue: Array<() => void> = [];\n let running = 0;\n\n async function run(\n input: TInput,\n ctx: ActionContext,\n ): Promise<TOutput | ActionFailure<TOutput>> {\n // Validate input if a validator is configured.\n if (options.input) {\n try {\n const validated = options.input.parse(input);\n input = validated;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const { fail } = await import(\"../errors.js\");\n return fail(400, { validation: message }) as ActionFailure<TOutput>;\n }\n }\n\n return handler(input, ctx);\n }\n\n const fn = async (input: TInput, ctx: ActionContext): Promise<TOutput | ActionFailure<TOutput>> => {\n if (concurrency === \"latest\") {\n // Cancel any previous in-flight call.\n if (latestController) latestController.abort();\n latestController = new AbortControllerCtor();\n // Combine the request signal with our cancellation signal.\n const combinedSignal = combineSignals(ctx.signal, latestController.signal);\n return run(input, { ...ctx, signal: combinedSignal });\n }\n\n if (concurrency === \"queue\") {\n // Wait for previous calls to finish.\n if (running > 0) {\n await new Promise<void>((resolve) => queue.push(resolve));\n }\n running++;\n try {\n return await run(input, ctx);\n } finally {\n running--;\n const next = queue.shift();\n if (next) next();\n }\n }\n\n // parallel: just run it.\n return run(input, ctx);\n };\n\n // Attach metadata.\n (fn as DefinedAction<TInput, TOutput>).__elurAction = {\n name: handler.name || \"anonymous\",\n concurrency,\n idempotent,\n invalidateTags,\n invalidatePaths,\n };\n\n return fn as DefinedAction<TInput, TOutput>;\n}\n\n/** Combines two AbortSignals into one that aborts when either does. */\nfunction combineSignals(...signals: (AbortSignal | undefined)[]): AbortSignal {\n const controller = new AbortControllerCtor();\n for (const signal of signals) {\n if (!signal) continue;\n if (signal.aborted) {\n controller.abort();\n break;\n }\n signal.addEventListener(\"abort\", () => controller.abort(), { once: true });\n }\n return controller.signal;\n}\n","/**\n * Client-side helpers for invoking server actions.\n *\n * Server actions are defined in `page.action.ts` files next to `page.ts`.\n * They export async functions that run on the server. On the client, call them\n * by name using `callAction` or the higher-level `elurJsAction` helper:\n *\n * ```ts\n * import { callAction } from \"@elurjs/kit/action\";\n *\n * const result = await callAction(\"submitContact\", { name: \"Ada\" }, { page: \"/contact\" });\n * ```\n *\n * ```ts\n * import { elurJsAction } from \"@elurjs/kit/action\";\n *\n * const contact = elurJsAction(\"submitContact\", { page: \"/contact\" });\n * await contact.submit({ name: \"Ada\" });\n * console.log(contact.data.value, contact.error.value, contact.pending.value);\n * ```\n */\n\nimport { signal } from \"@elurjs/core\";\nimport { ActionFailure, RedirectResponse } from \"../errors.js\";\n\ninterface ActionFailurePayload {\n __elur_js_action_failure?: boolean;\n status?: number;\n data?: unknown;\n}\n\ninterface RedirectPayload {\n __elur_js_action_redirect?: boolean;\n status?: number;\n location?: string;\n}\n\nfunction isActionFailurePayload(value: unknown): value is ActionFailurePayload & { __elur_js_action_failure: true } {\n return typeof value === \"object\" && value !== null && (value as Record<string, unknown>).__elur_js_action_failure === true;\n}\n\nfunction isRedirectPayload(value: unknown): value is RedirectPayload & { __elur_js_action_redirect: true } {\n return typeof value === \"object\" && value !== null && (value as Record<string, unknown>).__elur_js_action_redirect === true;\n}\n\nexport interface ActionRequest {\n name: string;\n page?: string;\n args: unknown[];\n}\n\nexport interface CallActionOptions {\n /** Page URL path that scopes the action, e.g. `/contact`. */\n page?: string;\n}\n\n/**\n * Call a server action by name.\n *\n * The request is sent as a POST to `/__elur-js/actions` with the action name,\n * optional page scope, and serialized arguments. The server executes the\n * matching exported function from the scanned `page.action.ts` modules and\n * returns its JSON result.\n */\nexport async function callAction<T = unknown>(\n name: string,\n args: unknown = [],\n options: CallActionOptions = {},\n): Promise<T | ActionFailure<T> | RedirectResponse> {\n const argsArray = Array.isArray(args) ? args : [args];\n const res = await fetch(\"/__elur-js/actions\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n },\n body: JSON.stringify({ name, page: options.page, args: argsArray } as ActionRequest),\n });\n\n const text = await res.text();\n if (!res.ok) {\n let payload: unknown;\n try {\n payload = JSON.parse(text);\n } catch {\n // not JSON, treat as plain error\n }\n if (isActionFailurePayload(payload) && payload.status !== undefined) {\n return new ActionFailure(payload.status, payload.data as T);\n }\n throw new Error(`Action \"${name}\" failed: ${text}`);\n }\n\n const payload: unknown = JSON.parse(text);\n if (isRedirectPayload(payload) && payload.status !== undefined && payload.location !== undefined) {\n return new RedirectResponse(payload.status, payload.location);\n }\n\n return payload as T;\n}\n\nexport interface ElurJsAction<TInput = unknown, TOutput = unknown> {\n /** Submit the action with the given input. */\n submit(input: TInput): Promise<TOutput | ActionFailure<TOutput> | RedirectResponse>;\n /** Signal that is true while the action is running. */\n pending: { value: boolean };\n /** Signal with the last successful result, action failure, redirect, or null. */\n data: { value: TOutput | ActionFailure<TOutput> | RedirectResponse | null };\n /** Signal with the last error, or null. */\n error: { value: Error | null };\n}\n\n/**\n * Create a reactive handle for a server action.\n *\n * Returns a `submit` function and signals for `pending`, `data`, and `error`.\n * Useful for wiring actions to forms and islands without manual signal boilerplate.\n */\nexport function elurJsAction<TInput = unknown, TOutput = unknown>(\n name: string,\n options: CallActionOptions = {},\n): ElurJsAction<TInput, TOutput> {\n const pending = signal(false);\n const error = signal<Error | null>(null);\n const data = signal<TOutput | ActionFailure<TOutput> | RedirectResponse | null>(null);\n\n async function submit(input: TInput): Promise<TOutput | ActionFailure<TOutput> | RedirectResponse> {\n pending.value = true;\n error.value = null;\n try {\n const result = await callAction<TOutput>(name, input, options);\n data.value = result;\n return result;\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err));\n throw err;\n } finally {\n pending.value = false;\n }\n }\n\n return {\n submit,\n pending,\n data,\n error,\n };\n}\n\n// Server-side: defineAction() for typed actions with validation/abort/cache.\nexport {\n defineAction,\n type DefineActionOptions,\n type DefinedAction,\n type DefinedActionFn,\n type ActionContext,\n type ActionInputValidator,\n type ActionConcurrencyMode,\n} from \"./define.js\";\n"],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../route-scanner-JY6YrNH5.cjs"),t=require("../shared-CfqOLsKj.cjs"),n=require("../capabilities-C0TDQoMY.cjs");let r=require("node:fs/promises"),i=require("node:path");var a={name:`bun`,capabilities:n.t,async build(n){let a=(0,i.resolve)(n.root),c=(0,i.resolve)(a,n.outDir),l=(0,i.resolve)(a,`.elur`);try{await(0,r.stat)(c)}catch{throw Error(`Output directory not found: ${c}. Run "elur-kit build" first.`)}await(0,r.rm)(l,{recursive:!0,force:!0}),await(0,r.mkdir)(l,{recursive:!0});let u=(0,i.resolve)(a,n.appDir),d=await e.t(u),f=(0,i.resolve)(l,`bun-index.ts`);await t.n(f,d,n);let p=(0,i.resolve)(l,`bun-server.ts`);await(0,r.writeFile)(p,o(s(l,c),n),`utf8`)}};function o(e,t){return`// AUTO-GENERATED by @elurjs/kit. Do not edit.
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { createWebHandler } from "@elurjs/kit/runtime";
|
|
4
|
+
import handler from "./bun-index.ts";
|
|
5
|
+
|
|
6
|
+
const outDir = fileURLToPath(new URL(${JSON.stringify(e)}, import.meta.url));
|
|
7
|
+
const port = Number(process.env.PORT) || ${t.port??3e3};
|
|
8
|
+
|
|
9
|
+
const webHandler = createWebHandler(
|
|
10
|
+
{ pages: [], api: [], error404: undefined, error500: undefined },
|
|
11
|
+
{},
|
|
12
|
+
{ staticRoot: outDir, lang: ${JSON.stringify(t.lang)}, clientEntry: ${JSON.stringify(t.clientEntry)} },
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
Bun.serve({
|
|
16
|
+
port,
|
|
17
|
+
async fetch(request) {
|
|
18
|
+
// Try static files first via the unified handler, then fall back to the
|
|
19
|
+
// bundled SSR handler for dynamic routes.
|
|
20
|
+
let response = await webHandler(request);
|
|
21
|
+
if (response.status === 404) {
|
|
22
|
+
response = await handler(request);
|
|
23
|
+
}
|
|
24
|
+
return response;
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
console.log(\`Bun server running at http://localhost:\${port}\`);
|
|
29
|
+
`}function s(e,t){let n=(0,i.relative)(e,t).split(`\\`).join(`/`);return`${n.startsWith(`.`)?n:`./${n}`}/`}exports.bunAdapter=a;
|
|
30
|
+
//# sourceMappingURL=bun.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bun.cjs","names":[],"sources":["../../../src/adapters/bun.ts"],"sourcesContent":["import { mkdir, rm, stat, writeFile } from \"node:fs/promises\";\nimport { relative, resolve } from \"node:path\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport type { Adapter } from \"./index.js\";\nimport { writeSsrEntry } from \"./shared.js\";\nimport { DEFAULT_CAPABILITIES } from \"../runtime/capabilities.js\";\n\n/**\n * Bun adapter for elur-kit.\n *\n * Produces a self-contained Bun server entry at `.elur/bun-server.ts`.\n * Run it with:\n *\n * bun run .elur/bun-server.ts\n *\n * The server serves static files from `dist/` and renders pages on demand for\n * unmatched routes.\n */\nexport const bunAdapter: Adapter = {\n name: \"bun\",\n capabilities: DEFAULT_CAPABILITIES,\n\n async build(options) {\n const root = resolve(options.root);\n const outDir = resolve(root, options.outDir);\n const generatedDir = resolve(root, \".elur\");\n\n // Verify the production build exists.\n try {\n await stat(outDir);\n } catch {\n throw new Error(\n `Output directory not found: ${outDir}. Run \"elur-kit build\" first.`,\n );\n }\n\n // Clean previous adapter output.\n await rm(generatedDir, { recursive: true, force: true });\n await mkdir(generatedDir, { recursive: true });\n\n // Scan routes and generate a self-contained SSR handler entry.\n const appDir = resolve(root, options.appDir);\n const routes = await scanRoutes(appDir);\n\n const entryPath = resolve(generatedDir, \"bun-index.ts\");\n await writeSsrEntry(entryPath, routes, options);\n\n // Write the Bun server entry.\n const serverPath = resolve(generatedDir, \"bun-server.ts\");\n await writeFile(\n serverPath,\n buildBunServerSource(relativeToUrlPath(generatedDir, outDir), options),\n \"utf8\",\n );\n },\n};\n\nfunction buildBunServerSource(\n outDirUrl: string,\n options: {\n clientEntry: string;\n lang: string;\n port?: number;\n },\n): string {\n return `// AUTO-GENERATED by @elurjs/kit. Do not edit.\nimport { fileURLToPath } from \"node:url\";\nimport { createWebHandler } from \"@elurjs/kit/runtime\";\nimport handler from \"./bun-index.ts\";\n\nconst outDir = fileURLToPath(new URL(${JSON.stringify(outDirUrl)}, import.meta.url));\nconst port = Number(process.env.PORT) || ${options.port ?? 3000};\n\nconst webHandler = createWebHandler(\n { pages: [], api: [], error404: undefined, error500: undefined },\n {},\n { staticRoot: outDir, lang: ${JSON.stringify(options.lang)}, clientEntry: ${JSON.stringify(options.clientEntry)} },\n);\n\nBun.serve({\n port,\n async fetch(request) {\n // Try static files first via the unified handler, then fall back to the\n // bundled SSR handler for dynamic routes.\n let response = await webHandler(request);\n if (response.status === 404) {\n response = await handler(request);\n }\n return response;\n },\n});\n\nconsole.log(\\`Bun server running at http://localhost:\\${port}\\`);\n`;\n}\n\nfunction relativeToUrlPath(from: string, to: string): string {\n const path = relative(from, to).split(\"\\\\\").join(\"/\");\n return `${path.startsWith(\".\") ? path : `./${path}`}/`;\n}\n"],"mappings":"2PAkBA,IAAa,EAAsB,CACjC,KAAM,MACN,aAAc,EAAA,EAEd,MAAM,MAAM,EAAS,CACnB,IAAM,GAAA,EAAO,EAAA,QAAA,CAAQ,EAAQ,IAAI,EAC3B,GAAA,EAAS,EAAA,QAAA,CAAQ,EAAM,EAAQ,MAAM,EACrC,GAAA,EAAe,EAAA,QAAA,CAAQ,EAAM,OAAO,EAG1C,GAAI,CACF,MAAA,EAAM,EAAA,KAAA,CAAK,CAAM,CACnB,MAAQ,CACN,MAAU,MACR,+BAA+B,EAAO,8BACxC,CACF,CAGA,MAAA,EAAM,EAAA,GAAA,CAAG,EAAc,CAAE,UAAW,GAAM,MAAO,EAAK,CAAC,EACvD,MAAA,EAAM,EAAA,MAAA,CAAM,EAAc,CAAE,UAAW,EAAK,CAAC,EAG7C,IAAM,GAAA,EAAS,EAAA,QAAA,CAAQ,EAAM,EAAQ,MAAM,EACrC,EAAS,MAAM,EAAA,EAAW,CAAM,EAEhC,GAAA,EAAY,EAAA,QAAA,CAAQ,EAAc,cAAc,EACtD,MAAM,EAAA,EAAc,EAAW,EAAQ,CAAO,EAG9C,IAAM,GAAA,EAAa,EAAA,QAAA,CAAQ,EAAc,eAAe,EACxD,MAAA,EAAM,EAAA,UAAA,CACJ,EACA,EAAqB,EAAkB,EAAc,CAAM,EAAG,CAAO,EACrE,MACF,CACF,CACF,EAEA,SAAS,EACP,EACA,EAKQ,CACR,MAAO;;;;;uCAK8B,KAAK,UAAU,CAAS,EAAE;2CACtB,EAAQ,MAAQ,IAAK;;;;;gCAKhC,KAAK,UAAU,EAAQ,IAAI,EAAE,iBAAiB,KAAK,UAAU,EAAQ,WAAW,EAAE;;;;;;;;;;;;;;;;;CAkBlH,CAEA,SAAS,EAAkB,EAAc,EAAoB,CAC3D,IAAM,GAAA,EAAO,EAAA,SAAA,CAAS,EAAM,CAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,GAAG,EACpD,MAAO,GAAG,EAAK,WAAW,GAAG,EAAI,EAAO,KAAK,IAAO,EACtD"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Adapter } from "./index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Bun adapter for elur-kit.
|
|
4
|
+
*
|
|
5
|
+
* Produces a self-contained Bun server entry at `.elur/bun-server.ts`.
|
|
6
|
+
* Run it with:
|
|
7
|
+
*
|
|
8
|
+
* bun run .elur/bun-server.ts
|
|
9
|
+
*
|
|
10
|
+
* The server serves static files from `dist/` and renders pages on demand for
|
|
11
|
+
* unmatched routes.
|
|
12
|
+
*/
|
|
13
|
+
export declare const bunAdapter: Adapter;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Adapter } from "./index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Bun adapter for elur-kit.
|
|
4
|
+
*
|
|
5
|
+
* Produces a self-contained Bun server entry at `.elur/bun-server.ts`.
|
|
6
|
+
* Run it with:
|
|
7
|
+
*
|
|
8
|
+
* bun run .elur/bun-server.ts
|
|
9
|
+
*
|
|
10
|
+
* The server serves static files from `dist/` and renders pages on demand for
|
|
11
|
+
* unmatched routes.
|
|
12
|
+
*/
|
|
13
|
+
export declare const bunAdapter: Adapter;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { t as e } from "../route-scanner-XcLId7lK.js";
|
|
2
|
+
import { n as t } from "../shared-DU3iQgr7.js";
|
|
3
|
+
import { t as n } from "../capabilities-C7txofmY.js";
|
|
4
|
+
import { mkdir as r, rm as i, stat as a, writeFile as o } from "node:fs/promises";
|
|
5
|
+
import { relative as s, resolve as c } from "node:path";
|
|
6
|
+
//#region src/adapters/bun.ts
|
|
7
|
+
var l = {
|
|
8
|
+
name: "bun",
|
|
9
|
+
capabilities: n,
|
|
10
|
+
async build(n) {
|
|
11
|
+
let s = c(n.root), l = c(s, n.outDir), f = c(s, ".elur");
|
|
12
|
+
try {
|
|
13
|
+
await a(l);
|
|
14
|
+
} catch {
|
|
15
|
+
throw Error(`Output directory not found: ${l}. Run "elur-kit build" first.`);
|
|
16
|
+
}
|
|
17
|
+
await i(f, {
|
|
18
|
+
recursive: !0,
|
|
19
|
+
force: !0
|
|
20
|
+
}), await r(f, { recursive: !0 });
|
|
21
|
+
let p = c(s, n.appDir), m = await e(p), h = c(f, "bun-index.ts");
|
|
22
|
+
await t(h, m, n);
|
|
23
|
+
let g = c(f, "bun-server.ts");
|
|
24
|
+
await o(g, u(d(f, l), n), "utf8");
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
function u(e, t) {
|
|
28
|
+
return `// AUTO-GENERATED by @elurjs/kit. Do not edit.
|
|
29
|
+
import { fileURLToPath } from "node:url";
|
|
30
|
+
import { createWebHandler } from "@elurjs/kit/runtime";
|
|
31
|
+
import handler from "./bun-index.ts";
|
|
32
|
+
|
|
33
|
+
const outDir = fileURLToPath(new URL(${JSON.stringify(e)}, import.meta.url));
|
|
34
|
+
const port = Number(process.env.PORT) || ${t.port ?? 3e3};
|
|
35
|
+
|
|
36
|
+
const webHandler = createWebHandler(
|
|
37
|
+
{ pages: [], api: [], error404: undefined, error500: undefined },
|
|
38
|
+
{},
|
|
39
|
+
{ staticRoot: outDir, lang: ${JSON.stringify(t.lang)}, clientEntry: ${JSON.stringify(t.clientEntry)} },
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
Bun.serve({
|
|
43
|
+
port,
|
|
44
|
+
async fetch(request) {
|
|
45
|
+
// Try static files first via the unified handler, then fall back to the
|
|
46
|
+
// bundled SSR handler for dynamic routes.
|
|
47
|
+
let response = await webHandler(request);
|
|
48
|
+
if (response.status === 404) {
|
|
49
|
+
response = await handler(request);
|
|
50
|
+
}
|
|
51
|
+
return response;
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
console.log(\`Bun server running at http://localhost:\${port}\`);
|
|
56
|
+
`;
|
|
57
|
+
}
|
|
58
|
+
function d(e, t) {
|
|
59
|
+
let n = s(e, t).split("\\").join("/");
|
|
60
|
+
return `${n.startsWith(".") ? n : `./${n}`}/`;
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
export { l as bunAdapter };
|
|
64
|
+
|
|
65
|
+
//# sourceMappingURL=bun.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bun.js","names":[],"sources":["../../../src/adapters/bun.ts"],"sourcesContent":["import { mkdir, rm, stat, writeFile } from \"node:fs/promises\";\nimport { relative, resolve } from \"node:path\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport type { Adapter } from \"./index.js\";\nimport { writeSsrEntry } from \"./shared.js\";\nimport { DEFAULT_CAPABILITIES } from \"../runtime/capabilities.js\";\n\n/**\n * Bun adapter for elur-kit.\n *\n * Produces a self-contained Bun server entry at `.elur/bun-server.ts`.\n * Run it with:\n *\n * bun run .elur/bun-server.ts\n *\n * The server serves static files from `dist/` and renders pages on demand for\n * unmatched routes.\n */\nexport const bunAdapter: Adapter = {\n name: \"bun\",\n capabilities: DEFAULT_CAPABILITIES,\n\n async build(options) {\n const root = resolve(options.root);\n const outDir = resolve(root, options.outDir);\n const generatedDir = resolve(root, \".elur\");\n\n // Verify the production build exists.\n try {\n await stat(outDir);\n } catch {\n throw new Error(\n `Output directory not found: ${outDir}. Run \"elur-kit build\" first.`,\n );\n }\n\n // Clean previous adapter output.\n await rm(generatedDir, { recursive: true, force: true });\n await mkdir(generatedDir, { recursive: true });\n\n // Scan routes and generate a self-contained SSR handler entry.\n const appDir = resolve(root, options.appDir);\n const routes = await scanRoutes(appDir);\n\n const entryPath = resolve(generatedDir, \"bun-index.ts\");\n await writeSsrEntry(entryPath, routes, options);\n\n // Write the Bun server entry.\n const serverPath = resolve(generatedDir, \"bun-server.ts\");\n await writeFile(\n serverPath,\n buildBunServerSource(relativeToUrlPath(generatedDir, outDir), options),\n \"utf8\",\n );\n },\n};\n\nfunction buildBunServerSource(\n outDirUrl: string,\n options: {\n clientEntry: string;\n lang: string;\n port?: number;\n },\n): string {\n return `// AUTO-GENERATED by @elurjs/kit. Do not edit.\nimport { fileURLToPath } from \"node:url\";\nimport { createWebHandler } from \"@elurjs/kit/runtime\";\nimport handler from \"./bun-index.ts\";\n\nconst outDir = fileURLToPath(new URL(${JSON.stringify(outDirUrl)}, import.meta.url));\nconst port = Number(process.env.PORT) || ${options.port ?? 3000};\n\nconst webHandler = createWebHandler(\n { pages: [], api: [], error404: undefined, error500: undefined },\n {},\n { staticRoot: outDir, lang: ${JSON.stringify(options.lang)}, clientEntry: ${JSON.stringify(options.clientEntry)} },\n);\n\nBun.serve({\n port,\n async fetch(request) {\n // Try static files first via the unified handler, then fall back to the\n // bundled SSR handler for dynamic routes.\n let response = await webHandler(request);\n if (response.status === 404) {\n response = await handler(request);\n }\n return response;\n },\n});\n\nconsole.log(\\`Bun server running at http://localhost:\\${port}\\`);\n`;\n}\n\nfunction relativeToUrlPath(from: string, to: string): string {\n const path = relative(from, to).split(\"\\\\\").join(\"/\");\n return `${path.startsWith(\".\") ? path : `./${path}`}/`;\n}\n"],"mappings":";;;;;;AAkBA,IAAa,IAAsB;CACjC,MAAM;CACN,cAAc;CAEd,MAAM,MAAM,GAAS;EACnB,IAAM,IAAO,EAAQ,EAAQ,IAAI,GAC3B,IAAS,EAAQ,GAAM,EAAQ,MAAM,GACrC,IAAe,EAAQ,GAAM,OAAO;EAG1C,IAAI;GACF,MAAM,EAAK,CAAM;EACnB,QAAQ;GACN,MAAU,MACR,+BAA+B,EAAO,8BACxC;EACF;EAIA,AADA,MAAM,EAAG,GAAc;GAAE,WAAW;GAAM,OAAO;EAAK,CAAC,GACvD,MAAM,EAAM,GAAc,EAAE,WAAW,GAAK,CAAC;EAG7C,IAAM,IAAS,EAAQ,GAAM,EAAQ,MAAM,GACrC,IAAS,MAAM,EAAW,CAAM,GAEhC,IAAY,EAAQ,GAAc,cAAc;EACtD,MAAM,EAAc,GAAW,GAAQ,CAAO;EAG9C,IAAM,IAAa,EAAQ,GAAc,eAAe;EACxD,MAAM,EACJ,GACA,EAAqB,EAAkB,GAAc,CAAM,GAAG,CAAO,GACrE,MACF;CACF;AACF;AAEA,SAAS,EACP,GACA,GAKQ;CACR,OAAO;;;;;uCAK8B,KAAK,UAAU,CAAS,EAAE;2CACtB,EAAQ,QAAQ,IAAK;;;;;gCAKhC,KAAK,UAAU,EAAQ,IAAI,EAAE,iBAAiB,KAAK,UAAU,EAAQ,WAAW,EAAE;;;;;;;;;;;;;;;;;;AAkBlH;AAEA,SAAS,EAAkB,GAAc,GAAoB;CAC3D,IAAM,IAAO,EAAS,GAAM,CAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,GAAG;CACpD,OAAO,GAAG,EAAK,WAAW,GAAG,IAAI,IAAO,KAAK,IAAO;AACtD"}
|
|
File without changes
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common options shared by all elur-kit deployment adapters.
|
|
3
|
+
*/
|
|
4
|
+
export interface AdapterOptions {
|
|
5
|
+
/** Project root directory. */
|
|
6
|
+
root: string;
|
|
7
|
+
/** Pages directory relative to root (default: src/app). */
|
|
8
|
+
appDir: string;
|
|
9
|
+
/** Islands directory relative to root (default: src/islands). */
|
|
10
|
+
islandsDir: string;
|
|
11
|
+
/** Output directory relative to root (default: dist). */
|
|
12
|
+
outDir: string;
|
|
13
|
+
/** Public directory relative to root (default: public). */
|
|
14
|
+
publicDir?: string;
|
|
15
|
+
/** Public path for the client entry module (default: /_elur/entry-client.js). */
|
|
16
|
+
clientEntry: string;
|
|
17
|
+
/** HTML lang attribute (default: es). */
|
|
18
|
+
lang: string;
|
|
19
|
+
/** Import specifier for hydrateIslands in the generated client entry. */
|
|
20
|
+
hydrateImport?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* An adapter turns a elur-kit build into a deployment target output.
|
|
24
|
+
*/
|
|
25
|
+
export interface Adapter {
|
|
26
|
+
name: string;
|
|
27
|
+
build(options: AdapterOptions): Promise<void>;
|
|
28
|
+
/** Declared host capabilities used for build-time diagnostics (§8.5). */
|
|
29
|
+
capabilities?: import("../runtime/capabilities.js").AdapterCapabilities;
|
|
30
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common options shared by all elur-kit deployment adapters.
|
|
3
|
+
*/
|
|
4
|
+
export interface AdapterOptions {
|
|
5
|
+
/** Project root directory. */
|
|
6
|
+
root: string;
|
|
7
|
+
/** Pages directory relative to root (default: src/app). */
|
|
8
|
+
appDir: string;
|
|
9
|
+
/** Islands directory relative to root (default: src/islands). */
|
|
10
|
+
islandsDir: string;
|
|
11
|
+
/** Output directory relative to root (default: dist). */
|
|
12
|
+
outDir: string;
|
|
13
|
+
/** Public directory relative to root (default: public). */
|
|
14
|
+
publicDir?: string;
|
|
15
|
+
/** Public path for the client entry module (default: /_elur/entry-client.js). */
|
|
16
|
+
clientEntry: string;
|
|
17
|
+
/** HTML lang attribute (default: es). */
|
|
18
|
+
lang: string;
|
|
19
|
+
/** Import specifier for hydrateIslands in the generated client entry. */
|
|
20
|
+
hydrateImport?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* An adapter turns a elur-kit build into a deployment target output.
|
|
24
|
+
*/
|
|
25
|
+
export interface Adapter {
|
|
26
|
+
name: string;
|
|
27
|
+
build(options: AdapterOptions): Promise<void>;
|
|
28
|
+
/** Declared host capabilities used for build-time diagnostics (§8.5). */
|
|
29
|
+
capabilities?: import("../runtime/capabilities.js").AdapterCapabilities;
|
|
30
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../route-scanner-JY6YrNH5.cjs"),t=require("../shared-CfqOLsKj.cjs"),n=require("../capabilities-C0TDQoMY.cjs");let r=require("node:fs/promises"),i=require("node:path"),a=require("vite");var o={name:`netlify`,capabilities:n.r,async build(n){let o=(0,i.resolve)(n.root),s=(0,i.resolve)(o,n.outDir),c=(0,i.resolve)(o,`netlify`),l=(0,i.join)(c,`functions`),u=(0,i.resolve)(o,`.elur`);try{await(0,r.stat)(s)}catch{throw Error(`Output directory not found: ${s}. Run "elur-kit build" first.`)}await(0,r.rm)(l,{recursive:!0,force:!0}),await(0,r.mkdir)(l,{recursive:!0}),await(0,r.mkdir)(u,{recursive:!0});let d=(0,i.resolve)(o,n.appDir),f=await e.t(d),p=(0,i.resolve)(u,`netlify-index.ts`);await t.n(p,f,n),await(0,a.build)({configFile:!1,root:o,build:{outDir:l,emptyOutDir:!0,ssr:!0,lib:{entry:p,formats:[`es`],fileName:()=>`__elur-js-kit.mjs`},rollupOptions:{external:[],output:{inlineDynamicImports:!0}}}});let m=(0,i.join)(l,`netlify-index.js`),h=(0,i.join)(l,`__elur-js-kit.mjs`);try{await(0,r.stat)(m),await(0,r.rename)(m,h)}catch{}await(0,r.writeFile)((0,i.join)(o,`netlify.toml`),`[build]
|
|
2
|
+
command = "elur-kit build"
|
|
3
|
+
publish = "dist"
|
|
4
|
+
|
|
5
|
+
[[redirects]]
|
|
6
|
+
from = "/*"
|
|
7
|
+
to = "/.netlify/functions/__elur-js-kit"
|
|
8
|
+
status = 200
|
|
9
|
+
`,`utf8`)}};exports.netlifyAdapter=o;
|
|
10
|
+
//# sourceMappingURL=netlify.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"netlify.cjs","names":[],"sources":["../../../src/adapters/netlify.ts"],"sourcesContent":["import { mkdir, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { build } from \"vite\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport type { Adapter } from \"./index.js\";\nimport { writeSsrEntry } from \"./shared.js\";\nimport { SERVERLESS_CAPABILITIES } from \"../runtime/capabilities.js\";\n\n/**\n * Netlify adapter for elur-kit.\n *\n * Produces the files expected by Netlify Functions v2:\n * - `netlify/functions/__elur-js-kit.mjs` — bundled SSR function.\n * - `netlify.toml` — redirects unmatched routes to the function.\n *\n * Run this after `elur-kit build`. The static files are left in `dist/` and\n * served directly by Netlify; the function only handles routes that have no\n * matching static file.\n */\nexport const netlifyAdapter: Adapter = {\n name: \"netlify\",\n capabilities: SERVERLESS_CAPABILITIES,\n\n async build(options) {\n const root = resolve(options.root);\n const outDir = resolve(root, options.outDir);\n const netlifyDir = resolve(root, \"netlify\");\n const functionsDir = join(netlifyDir, \"functions\");\n const generatedDir = resolve(root, \".elur\");\n\n // Verify the production build exists.\n try {\n await stat(outDir);\n } catch {\n throw new Error(\n `Output directory not found: ${outDir}. Run \"elur-kit build\" first.`,\n );\n }\n\n // Clean previous adapter output.\n await rm(functionsDir, { recursive: true, force: true });\n await mkdir(functionsDir, { recursive: true });\n await mkdir(generatedDir, { recursive: true });\n\n // Scan routes and generate a self-contained function entry.\n const appDir = resolve(root, options.appDir);\n const routes = await scanRoutes(appDir);\n\n const entryPath = resolve(generatedDir, \"netlify-index.ts\");\n await writeSsrEntry(entryPath, routes, options);\n\n // Bundle the function entry.\n await build({\n configFile: false,\n root,\n build: {\n outDir: functionsDir,\n emptyOutDir: true,\n ssr: true,\n lib: {\n entry: entryPath,\n formats: [\"es\"],\n fileName: () => \"__elur-js-kit.mjs\",\n },\n rollupOptions: {\n external: [],\n output: {\n inlineDynamicImports: true,\n },\n },\n },\n });\n\n // Vite SSR lib builds may use the entry file name, so force the expected handler name.\n const generatedHandler = join(functionsDir, \"netlify-index.js\");\n const targetHandler = join(functionsDir, \"__elur-js-kit.mjs\");\n try {\n await stat(generatedHandler);\n await rename(generatedHandler, targetHandler);\n } catch {\n // If the file is already named __elur-js-kit.mjs, nothing to do.\n }\n\n // Write Netlify redirects config.\n await writeFile(\n join(root, \"netlify.toml\"),\n `[build]\n command = \"elur-kit build\"\n publish = \"dist\"\n\n[[redirects]]\n from = \"/*\"\n to = \"/.netlify/functions/__elur-js-kit\"\n status = 200\n`,\n \"utf8\",\n );\n },\n};\n"],"mappings":"6QAmBA,IAAa,EAA0B,CACrC,KAAM,UACN,aAAc,EAAA,EAEd,MAAM,MAAM,EAAS,CACnB,IAAM,GAAA,EAAO,EAAA,QAAA,CAAQ,EAAQ,IAAI,EAC3B,GAAA,EAAS,EAAA,QAAA,CAAQ,EAAM,EAAQ,MAAM,EACrC,GAAA,EAAa,EAAA,QAAA,CAAQ,EAAM,SAAS,EACpC,GAAA,EAAe,EAAA,KAAA,CAAK,EAAY,WAAW,EAC3C,GAAA,EAAe,EAAA,QAAA,CAAQ,EAAM,OAAO,EAG1C,GAAI,CACF,MAAA,EAAM,EAAA,KAAA,CAAK,CAAM,CACnB,MAAQ,CACN,MAAU,MACR,+BAA+B,EAAO,8BACxC,CACF,CAGA,MAAA,EAAM,EAAA,GAAA,CAAG,EAAc,CAAE,UAAW,GAAM,MAAO,EAAK,CAAC,EACvD,MAAA,EAAM,EAAA,MAAA,CAAM,EAAc,CAAE,UAAW,EAAK,CAAC,EAC7C,MAAA,EAAM,EAAA,MAAA,CAAM,EAAc,CAAE,UAAW,EAAK,CAAC,EAG7C,IAAM,GAAA,EAAS,EAAA,QAAA,CAAQ,EAAM,EAAQ,MAAM,EACrC,EAAS,MAAM,EAAA,EAAW,CAAM,EAEhC,GAAA,EAAY,EAAA,QAAA,CAAQ,EAAc,kBAAkB,EAC1D,MAAM,EAAA,EAAc,EAAW,EAAQ,CAAO,EAG9C,MAAA,EAAM,EAAA,MAAA,CAAM,CACV,WAAY,GACZ,OACA,MAAO,CACL,OAAQ,EACR,YAAa,GACb,IAAK,GACL,IAAK,CACH,MAAO,EACP,QAAS,CAAC,IAAI,EACd,aAAgB,mBAClB,EACA,cAAe,CACb,SAAU,CAAC,EACX,OAAQ,CACN,qBAAsB,EACxB,CACF,CACF,CACF,CAAC,EAGD,IAAM,GAAA,EAAmB,EAAA,KAAA,CAAK,EAAc,kBAAkB,EACxD,GAAA,EAAgB,EAAA,KAAA,CAAK,EAAc,mBAAmB,EAC5D,GAAI,CACF,MAAA,EAAM,EAAA,KAAA,CAAK,CAAgB,EAC3B,MAAA,EAAM,EAAA,OAAA,CAAO,EAAkB,CAAa,CAC9C,MAAQ,CAER,CAGA,MAAA,EAAM,EAAA,UAAA,EAAA,EACJ,EAAA,KAAA,CAAK,EAAM,cAAc,EACzB;;;;;;;;EASA,MACF,CACF,CACF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Adapter } from "./index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Netlify adapter for elur-kit.
|
|
4
|
+
*
|
|
5
|
+
* Produces the files expected by Netlify Functions v2:
|
|
6
|
+
* - `netlify/functions/__elur-js-kit.mjs` — bundled SSR function.
|
|
7
|
+
* - `netlify.toml` — redirects unmatched routes to the function.
|
|
8
|
+
*
|
|
9
|
+
* Run this after `elur-kit build`. The static files are left in `dist/` and
|
|
10
|
+
* served directly by Netlify; the function only handles routes that have no
|
|
11
|
+
* matching static file.
|
|
12
|
+
*/
|
|
13
|
+
export declare const netlifyAdapter: Adapter;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Adapter } from "./index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Netlify adapter for elur-kit.
|
|
4
|
+
*
|
|
5
|
+
* Produces the files expected by Netlify Functions v2:
|
|
6
|
+
* - `netlify/functions/__elur-js-kit.mjs` — bundled SSR function.
|
|
7
|
+
* - `netlify.toml` — redirects unmatched routes to the function.
|
|
8
|
+
*
|
|
9
|
+
* Run this after `elur-kit build`. The static files are left in `dist/` and
|
|
10
|
+
* served directly by Netlify; the function only handles routes that have no
|
|
11
|
+
* matching static file.
|
|
12
|
+
*/
|
|
13
|
+
export declare const netlifyAdapter: Adapter;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { t as e } from "../route-scanner-XcLId7lK.js";
|
|
2
|
+
import { n as t } from "../shared-DU3iQgr7.js";
|
|
3
|
+
import { r as n } from "../capabilities-C7txofmY.js";
|
|
4
|
+
import { mkdir as r, rename as i, rm as a, stat as o, writeFile as s } from "node:fs/promises";
|
|
5
|
+
import { join as c, resolve as l } from "node:path";
|
|
6
|
+
import { build as u } from "vite";
|
|
7
|
+
//#region src/adapters/netlify.ts
|
|
8
|
+
var d = {
|
|
9
|
+
name: "netlify",
|
|
10
|
+
capabilities: n,
|
|
11
|
+
async build(n) {
|
|
12
|
+
let d = l(n.root), f = l(d, n.outDir), p = l(d, "netlify"), m = c(p, "functions"), h = l(d, ".elur");
|
|
13
|
+
try {
|
|
14
|
+
await o(f);
|
|
15
|
+
} catch {
|
|
16
|
+
throw Error(`Output directory not found: ${f}. Run "elur-kit build" first.`);
|
|
17
|
+
}
|
|
18
|
+
await a(m, {
|
|
19
|
+
recursive: !0,
|
|
20
|
+
force: !0
|
|
21
|
+
}), await r(m, { recursive: !0 }), await r(h, { recursive: !0 });
|
|
22
|
+
let g = l(d, n.appDir), _ = await e(g), v = l(h, "netlify-index.ts");
|
|
23
|
+
await t(v, _, n), await u({
|
|
24
|
+
configFile: !1,
|
|
25
|
+
root: d,
|
|
26
|
+
build: {
|
|
27
|
+
outDir: m,
|
|
28
|
+
emptyOutDir: !0,
|
|
29
|
+
ssr: !0,
|
|
30
|
+
lib: {
|
|
31
|
+
entry: v,
|
|
32
|
+
formats: ["es"],
|
|
33
|
+
fileName: () => "__elur-js-kit.mjs"
|
|
34
|
+
},
|
|
35
|
+
rollupOptions: {
|
|
36
|
+
external: [],
|
|
37
|
+
output: { inlineDynamicImports: !0 }
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
let y = c(m, "netlify-index.js"), b = c(m, "__elur-js-kit.mjs");
|
|
42
|
+
try {
|
|
43
|
+
await o(y), await i(y, b);
|
|
44
|
+
} catch {}
|
|
45
|
+
await s(c(d, "netlify.toml"), "[build]\n command = \"elur-kit build\"\n publish = \"dist\"\n\n[[redirects]]\n from = \"/*\"\n to = \"/.netlify/functions/__elur-js-kit\"\n status = 200\n", "utf8");
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
//#endregion
|
|
49
|
+
export { d as netlifyAdapter };
|
|
50
|
+
|
|
51
|
+
//# sourceMappingURL=netlify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"netlify.js","names":[],"sources":["../../../src/adapters/netlify.ts"],"sourcesContent":["import { mkdir, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { build } from \"vite\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport type { Adapter } from \"./index.js\";\nimport { writeSsrEntry } from \"./shared.js\";\nimport { SERVERLESS_CAPABILITIES } from \"../runtime/capabilities.js\";\n\n/**\n * Netlify adapter for elur-kit.\n *\n * Produces the files expected by Netlify Functions v2:\n * - `netlify/functions/__elur-js-kit.mjs` — bundled SSR function.\n * - `netlify.toml` — redirects unmatched routes to the function.\n *\n * Run this after `elur-kit build`. The static files are left in `dist/` and\n * served directly by Netlify; the function only handles routes that have no\n * matching static file.\n */\nexport const netlifyAdapter: Adapter = {\n name: \"netlify\",\n capabilities: SERVERLESS_CAPABILITIES,\n\n async build(options) {\n const root = resolve(options.root);\n const outDir = resolve(root, options.outDir);\n const netlifyDir = resolve(root, \"netlify\");\n const functionsDir = join(netlifyDir, \"functions\");\n const generatedDir = resolve(root, \".elur\");\n\n // Verify the production build exists.\n try {\n await stat(outDir);\n } catch {\n throw new Error(\n `Output directory not found: ${outDir}. Run \"elur-kit build\" first.`,\n );\n }\n\n // Clean previous adapter output.\n await rm(functionsDir, { recursive: true, force: true });\n await mkdir(functionsDir, { recursive: true });\n await mkdir(generatedDir, { recursive: true });\n\n // Scan routes and generate a self-contained function entry.\n const appDir = resolve(root, options.appDir);\n const routes = await scanRoutes(appDir);\n\n const entryPath = resolve(generatedDir, \"netlify-index.ts\");\n await writeSsrEntry(entryPath, routes, options);\n\n // Bundle the function entry.\n await build({\n configFile: false,\n root,\n build: {\n outDir: functionsDir,\n emptyOutDir: true,\n ssr: true,\n lib: {\n entry: entryPath,\n formats: [\"es\"],\n fileName: () => \"__elur-js-kit.mjs\",\n },\n rollupOptions: {\n external: [],\n output: {\n inlineDynamicImports: true,\n },\n },\n },\n });\n\n // Vite SSR lib builds may use the entry file name, so force the expected handler name.\n const generatedHandler = join(functionsDir, \"netlify-index.js\");\n const targetHandler = join(functionsDir, \"__elur-js-kit.mjs\");\n try {\n await stat(generatedHandler);\n await rename(generatedHandler, targetHandler);\n } catch {\n // If the file is already named __elur-js-kit.mjs, nothing to do.\n }\n\n // Write Netlify redirects config.\n await writeFile(\n join(root, \"netlify.toml\"),\n `[build]\n command = \"elur-kit build\"\n publish = \"dist\"\n\n[[redirects]]\n from = \"/*\"\n to = \"/.netlify/functions/__elur-js-kit\"\n status = 200\n`,\n \"utf8\",\n );\n },\n};\n"],"mappings":";;;;;;;AAmBA,IAAa,IAA0B;CACrC,MAAM;CACN,cAAc;CAEd,MAAM,MAAM,GAAS;EACnB,IAAM,IAAO,EAAQ,EAAQ,IAAI,GAC3B,IAAS,EAAQ,GAAM,EAAQ,MAAM,GACrC,IAAa,EAAQ,GAAM,SAAS,GACpC,IAAe,EAAK,GAAY,WAAW,GAC3C,IAAe,EAAQ,GAAM,OAAO;EAG1C,IAAI;GACF,MAAM,EAAK,CAAM;EACnB,QAAQ;GACN,MAAU,MACR,+BAA+B,EAAO,8BACxC;EACF;EAKA,AAFA,MAAM,EAAG,GAAc;GAAE,WAAW;GAAM,OAAO;EAAK,CAAC,GACvD,MAAM,EAAM,GAAc,EAAE,WAAW,GAAK,CAAC,GAC7C,MAAM,EAAM,GAAc,EAAE,WAAW,GAAK,CAAC;EAG7C,IAAM,IAAS,EAAQ,GAAM,EAAQ,MAAM,GACrC,IAAS,MAAM,EAAW,CAAM,GAEhC,IAAY,EAAQ,GAAc,kBAAkB;EAI1D,AAHA,MAAM,EAAc,GAAW,GAAQ,CAAO,GAG9C,MAAM,EAAM;GACV,YAAY;GACZ;GACA,OAAO;IACL,QAAQ;IACR,aAAa;IACb,KAAK;IACL,KAAK;KACH,OAAO;KACP,SAAS,CAAC,IAAI;KACd,gBAAgB;IAClB;IACA,eAAe;KACb,UAAU,CAAC;KACX,QAAQ,EACN,sBAAsB,GACxB;IACF;GACF;EACF,CAAC;EAGD,IAAM,IAAmB,EAAK,GAAc,kBAAkB,GACxD,IAAgB,EAAK,GAAc,mBAAmB;EAC5D,IAAI;GAEF,AADA,MAAM,EAAK,CAAgB,GAC3B,MAAM,EAAO,GAAkB,CAAa;EAC9C,QAAQ,CAER;EAGA,MAAM,EACJ,EAAK,GAAM,cAAc,GACzB,mKASA,MACF;CACF;AACF"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../route-scanner-JY6YrNH5.cjs"),t=require("../shared-CfqOLsKj.cjs"),n=require("../capabilities-C0TDQoMY.cjs");let r=require("node:fs/promises"),i=require("node:path"),a=require("vite");var o={name:`node`,capabilities:n.t,async build(n){let o=(0,i.resolve)(n.root),l=(0,i.resolve)(o,n.outDir),u=(0,i.resolve)(o,`.elur`);try{await(0,r.stat)(l)}catch{throw Error(`Output directory not found: ${l}. Run "elur-kit build" first.`)}await(0,r.rm)(u,{recursive:!0,force:!0}),await(0,r.mkdir)(u,{recursive:!0});let d=(0,i.resolve)(o,n.appDir),f=await e.t(d),p=(0,i.resolve)(u,`node-index.ts`);await t.n(p,f,n);let m=(0,i.resolve)(u,`node-server.ts`);await(0,r.writeFile)(m,s(c(u,l),n),`utf8`),await(0,a.build)({configFile:!1,root:o,build:{outDir:u,emptyOutDir:!1,ssr:!0,lib:{entry:m,formats:[`es`]},rollupOptions:{external:[/^@elurjs\/kit(?:\/.*)?$/,/^@elurjs\/core(?:\/.*)?$/,/^node:/],output:{entryFileNames:`node-server.mjs`,inlineDynamicImports:!0}}}})}};function s(e,t){return`// AUTO-GENERATED by @elurjs/kit. Do not edit.
|
|
2
|
+
import { createServer } from "node:http";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { createWebHandler } from "@elurjs/kit/runtime";
|
|
5
|
+
import { incomingMessageToRequest } from "@elurjs/kit/runtime";
|
|
6
|
+
import handler from "./node-index.ts";
|
|
7
|
+
|
|
8
|
+
const outDir = fileURLToPath(new URL(${JSON.stringify(e)}, import.meta.url));
|
|
9
|
+
const port = Number(process.env.PORT) || ${t.port??3e3};
|
|
10
|
+
|
|
11
|
+
// The adapter-bundled handler already handles actions, API routes, render
|
|
12
|
+
// endpoint and dynamic SSR. We only need to add static file serving from
|
|
13
|
+
// the output directory, then fall through to the bundled handler.
|
|
14
|
+
const webHandler = createWebHandler(
|
|
15
|
+
{ pages: [], api: [], error404: undefined, error500: undefined },
|
|
16
|
+
{},
|
|
17
|
+
{ staticRoot: outDir, lang: ${JSON.stringify(t.lang)}, clientEntry: ${JSON.stringify(t.clientEntry)} },
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
createServer(async (req, res) => {
|
|
21
|
+
const body = req.method !== "GET" && req.method !== "HEAD"
|
|
22
|
+
? await readBody(req)
|
|
23
|
+
: undefined;
|
|
24
|
+
const request = incomingMessageToRequest(req, body);
|
|
25
|
+
// Try static files first via the unified handler, then fall back to the
|
|
26
|
+
// bundled SSR handler for dynamic routes.
|
|
27
|
+
let response = await webHandler(request);
|
|
28
|
+
if (response.status === 404) {
|
|
29
|
+
response = await handler(request);
|
|
30
|
+
}
|
|
31
|
+
res.writeHead(response.status, Object.fromEntries(response.headers.entries()));
|
|
32
|
+
res.end(Buffer.from(await response.arrayBuffer()));
|
|
33
|
+
}).listen(port, () => {
|
|
34
|
+
console.log(\`Node server running at http://localhost:\${port}\`);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
function readBody(req: import("node:http").IncomingMessage): Promise<Buffer> {
|
|
38
|
+
return new Promise((resolve, reject) => {
|
|
39
|
+
const chunks: Buffer[] = [];
|
|
40
|
+
req.on("data", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
|
|
41
|
+
req.on("end", () => resolve(Buffer.concat(chunks)));
|
|
42
|
+
req.on("error", reject);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
`}function c(e,t){let n=(0,i.relative)(e,t).split(`\\`).join(`/`);return`${n.startsWith(`.`)?n:`./${n}`}/`}exports.nodeAdapter=o;
|
|
46
|
+
//# sourceMappingURL=node.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.cjs","names":[],"sources":["../../../src/adapters/node.ts"],"sourcesContent":["import { mkdir, rm, stat, writeFile } from \"node:fs/promises\";\nimport { relative, resolve } from \"node:path\";\nimport { build } from \"vite\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport type { Adapter } from \"./index.js\";\nimport { writeSsrEntry } from \"./shared.js\";\nimport { DEFAULT_CAPABILITIES } from \"../runtime/capabilities.js\";\n\n/**\n * Node adapter for elur-kit.\n *\n * Produces a self-contained Node server entry at `.elur/node-server.mjs`.\n * Run it with:\n *\n * node .elur/node-server.mjs\n *\n * The server serves static files from `dist/` and renders pages on demand for\n * unmatched routes.\n */\nexport const nodeAdapter: Adapter = {\n name: \"node\",\n capabilities: DEFAULT_CAPABILITIES,\n\n async build(options) {\n const root = resolve(options.root);\n const outDir = resolve(root, options.outDir);\n const generatedDir = resolve(root, \".elur\");\n\n try {\n await stat(outDir);\n } catch {\n throw new Error(\n `Output directory not found: ${outDir}. Run \"elur-kit build\" first.`,\n );\n }\n\n await rm(generatedDir, { recursive: true, force: true });\n await mkdir(generatedDir, { recursive: true });\n\n const appDir = resolve(root, options.appDir);\n const routes = await scanRoutes(appDir);\n\n const entryPath = resolve(generatedDir, \"node-index.ts\");\n await writeSsrEntry(entryPath, routes, options);\n\n const serverPath = resolve(generatedDir, \"node-server.ts\");\n await writeFile(\n serverPath,\n buildNodeServerSource(relativeToUrlPath(generatedDir, outDir), options),\n \"utf8\",\n );\n\n await build({\n configFile: false,\n root,\n build: {\n outDir: generatedDir,\n emptyOutDir: false,\n ssr: true,\n lib: {\n entry: serverPath,\n formats: [\"es\"],\n },\n rollupOptions: {\n external: [/^@elurjs\\/kit(?:\\/.*)?$/, /^@elurjs\\/core(?:\\/.*)?$/, /^node:/],\n output: {\n entryFileNames: \"node-server.mjs\",\n inlineDynamicImports: true,\n },\n },\n },\n });\n },\n};\n\nfunction buildNodeServerSource(\n outDirUrl: string,\n options: {\n clientEntry: string;\n lang: string;\n port?: number;\n },\n): string {\n return `// AUTO-GENERATED by @elurjs/kit. Do not edit.\nimport { createServer } from \"node:http\";\nimport { fileURLToPath } from \"node:url\";\nimport { createWebHandler } from \"@elurjs/kit/runtime\";\nimport { incomingMessageToRequest } from \"@elurjs/kit/runtime\";\nimport handler from \"./node-index.ts\";\n\nconst outDir = fileURLToPath(new URL(${JSON.stringify(outDirUrl)}, import.meta.url));\nconst port = Number(process.env.PORT) || ${options.port ?? 3000};\n\n// The adapter-bundled handler already handles actions, API routes, render\n// endpoint and dynamic SSR. We only need to add static file serving from\n// the output directory, then fall through to the bundled handler.\nconst webHandler = createWebHandler(\n { pages: [], api: [], error404: undefined, error500: undefined },\n {},\n { staticRoot: outDir, lang: ${JSON.stringify(options.lang)}, clientEntry: ${JSON.stringify(options.clientEntry)} },\n);\n\ncreateServer(async (req, res) => {\n const body = req.method !== \"GET\" && req.method !== \"HEAD\"\n ? await readBody(req)\n : undefined;\n const request = incomingMessageToRequest(req, body);\n // Try static files first via the unified handler, then fall back to the\n // bundled SSR handler for dynamic routes.\n let response = await webHandler(request);\n if (response.status === 404) {\n response = await handler(request);\n }\n res.writeHead(response.status, Object.fromEntries(response.headers.entries()));\n res.end(Buffer.from(await response.arrayBuffer()));\n}).listen(port, () => {\n console.log(\\`Node server running at http://localhost:\\${port}\\`);\n});\n\nfunction readBody(req: import(\"node:http\").IncomingMessage): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on(\"data\", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));\n req.on(\"end\", () => resolve(Buffer.concat(chunks)));\n req.on(\"error\", reject);\n });\n}\n`;\n}\n\nfunction relativeToUrlPath(from: string, to: string): string {\n const path = relative(from, to).split(\"\\\\\").join(\"/\");\n return `${path.startsWith(\".\") ? path : `./${path}`}/`;\n}\n"],"mappings":"6QAmBA,IAAa,EAAuB,CAClC,KAAM,OACN,aAAc,EAAA,EAEd,MAAM,MAAM,EAAS,CACnB,IAAM,GAAA,EAAO,EAAA,QAAA,CAAQ,EAAQ,IAAI,EAC3B,GAAA,EAAS,EAAA,QAAA,CAAQ,EAAM,EAAQ,MAAM,EACrC,GAAA,EAAe,EAAA,QAAA,CAAQ,EAAM,OAAO,EAE1C,GAAI,CACF,MAAA,EAAM,EAAA,KAAA,CAAK,CAAM,CACnB,MAAQ,CACN,MAAU,MACR,+BAA+B,EAAO,8BACxC,CACF,CAEA,MAAA,EAAM,EAAA,GAAA,CAAG,EAAc,CAAE,UAAW,GAAM,MAAO,EAAK,CAAC,EACvD,MAAA,EAAM,EAAA,MAAA,CAAM,EAAc,CAAE,UAAW,EAAK,CAAC,EAE7C,IAAM,GAAA,EAAS,EAAA,QAAA,CAAQ,EAAM,EAAQ,MAAM,EACrC,EAAS,MAAM,EAAA,EAAW,CAAM,EAEhC,GAAA,EAAY,EAAA,QAAA,CAAQ,EAAc,eAAe,EACvD,MAAM,EAAA,EAAc,EAAW,EAAQ,CAAO,EAE9C,IAAM,GAAA,EAAa,EAAA,QAAA,CAAQ,EAAc,gBAAgB,EACzD,MAAA,EAAM,EAAA,UAAA,CACJ,EACA,EAAsB,EAAkB,EAAc,CAAM,EAAG,CAAO,EACtE,MACF,EAEA,MAAA,EAAM,EAAA,MAAA,CAAM,CACV,WAAY,GACZ,OACA,MAAO,CACL,OAAQ,EACR,YAAa,GACb,IAAK,GACL,IAAK,CACH,MAAO,EACP,QAAS,CAAC,IAAI,CAChB,EACA,cAAe,CACb,SAAU,CAAC,0BAA2B,2BAA4B,QAAQ,EAC1E,OAAQ,CACN,eAAgB,kBAChB,qBAAsB,EACxB,CACF,CACF,CACF,CAAC,CACH,CACF,EAEA,SAAS,EACP,EACA,EAKQ,CACR,MAAO;;;;;;;uCAO8B,KAAK,UAAU,CAAS,EAAE;2CACtB,EAAQ,MAAQ,IAAK;;;;;;;;gCAQhC,KAAK,UAAU,EAAQ,IAAI,EAAE,iBAAiB,KAAK,UAAU,EAAQ,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BlH,CAEA,SAAS,EAAkB,EAAc,EAAoB,CAC3D,IAAM,GAAA,EAAO,EAAA,SAAA,CAAS,EAAM,CAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,GAAG,EACpD,MAAO,GAAG,EAAK,WAAW,GAAG,EAAI,EAAO,KAAK,IAAO,EACtD"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Adapter } from "./index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Node adapter for elur-kit.
|
|
4
|
+
*
|
|
5
|
+
* Produces a self-contained Node server entry at `.elur/node-server.mjs`.
|
|
6
|
+
* Run it with:
|
|
7
|
+
*
|
|
8
|
+
* node .elur/node-server.mjs
|
|
9
|
+
*
|
|
10
|
+
* The server serves static files from `dist/` and renders pages on demand for
|
|
11
|
+
* unmatched routes.
|
|
12
|
+
*/
|
|
13
|
+
export declare const nodeAdapter: Adapter;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Adapter } from "./index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Node adapter for elur-kit.
|
|
4
|
+
*
|
|
5
|
+
* Produces a self-contained Node server entry at `.elur/node-server.mjs`.
|
|
6
|
+
* Run it with:
|
|
7
|
+
*
|
|
8
|
+
* node .elur/node-server.mjs
|
|
9
|
+
*
|
|
10
|
+
* The server serves static files from `dist/` and renders pages on demand for
|
|
11
|
+
* unmatched routes.
|
|
12
|
+
*/
|
|
13
|
+
export declare const nodeAdapter: Adapter;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { t as e } from "../route-scanner-XcLId7lK.js";
|
|
2
|
+
import { n as t } from "../shared-DU3iQgr7.js";
|
|
3
|
+
import { t as n } from "../capabilities-C7txofmY.js";
|
|
4
|
+
import { mkdir as r, rm as i, stat as a, writeFile as o } from "node:fs/promises";
|
|
5
|
+
import { relative as s, resolve as c } from "node:path";
|
|
6
|
+
import { build as l } from "vite";
|
|
7
|
+
//#region src/adapters/node.ts
|
|
8
|
+
var u = {
|
|
9
|
+
name: "node",
|
|
10
|
+
capabilities: n,
|
|
11
|
+
async build(n) {
|
|
12
|
+
let s = c(n.root), u = c(s, n.outDir), p = c(s, ".elur");
|
|
13
|
+
try {
|
|
14
|
+
await a(u);
|
|
15
|
+
} catch {
|
|
16
|
+
throw Error(`Output directory not found: ${u}. Run "elur-kit build" first.`);
|
|
17
|
+
}
|
|
18
|
+
await i(p, {
|
|
19
|
+
recursive: !0,
|
|
20
|
+
force: !0
|
|
21
|
+
}), await r(p, { recursive: !0 });
|
|
22
|
+
let m = c(s, n.appDir), h = await e(m), g = c(p, "node-index.ts");
|
|
23
|
+
await t(g, h, n);
|
|
24
|
+
let _ = c(p, "node-server.ts");
|
|
25
|
+
await o(_, d(f(p, u), n), "utf8"), await l({
|
|
26
|
+
configFile: !1,
|
|
27
|
+
root: s,
|
|
28
|
+
build: {
|
|
29
|
+
outDir: p,
|
|
30
|
+
emptyOutDir: !1,
|
|
31
|
+
ssr: !0,
|
|
32
|
+
lib: {
|
|
33
|
+
entry: _,
|
|
34
|
+
formats: ["es"]
|
|
35
|
+
},
|
|
36
|
+
rollupOptions: {
|
|
37
|
+
external: [
|
|
38
|
+
/^@elurjs\/kit(?:\/.*)?$/,
|
|
39
|
+
/^@elurjs\/core(?:\/.*)?$/,
|
|
40
|
+
/^node:/
|
|
41
|
+
],
|
|
42
|
+
output: {
|
|
43
|
+
entryFileNames: "node-server.mjs",
|
|
44
|
+
inlineDynamicImports: !0
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
function d(e, t) {
|
|
52
|
+
return `// AUTO-GENERATED by @elurjs/kit. Do not edit.
|
|
53
|
+
import { createServer } from "node:http";
|
|
54
|
+
import { fileURLToPath } from "node:url";
|
|
55
|
+
import { createWebHandler } from "@elurjs/kit/runtime";
|
|
56
|
+
import { incomingMessageToRequest } from "@elurjs/kit/runtime";
|
|
57
|
+
import handler from "./node-index.ts";
|
|
58
|
+
|
|
59
|
+
const outDir = fileURLToPath(new URL(${JSON.stringify(e)}, import.meta.url));
|
|
60
|
+
const port = Number(process.env.PORT) || ${t.port ?? 3e3};
|
|
61
|
+
|
|
62
|
+
// The adapter-bundled handler already handles actions, API routes, render
|
|
63
|
+
// endpoint and dynamic SSR. We only need to add static file serving from
|
|
64
|
+
// the output directory, then fall through to the bundled handler.
|
|
65
|
+
const webHandler = createWebHandler(
|
|
66
|
+
{ pages: [], api: [], error404: undefined, error500: undefined },
|
|
67
|
+
{},
|
|
68
|
+
{ staticRoot: outDir, lang: ${JSON.stringify(t.lang)}, clientEntry: ${JSON.stringify(t.clientEntry)} },
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
createServer(async (req, res) => {
|
|
72
|
+
const body = req.method !== "GET" && req.method !== "HEAD"
|
|
73
|
+
? await readBody(req)
|
|
74
|
+
: undefined;
|
|
75
|
+
const request = incomingMessageToRequest(req, body);
|
|
76
|
+
// Try static files first via the unified handler, then fall back to the
|
|
77
|
+
// bundled SSR handler for dynamic routes.
|
|
78
|
+
let response = await webHandler(request);
|
|
79
|
+
if (response.status === 404) {
|
|
80
|
+
response = await handler(request);
|
|
81
|
+
}
|
|
82
|
+
res.writeHead(response.status, Object.fromEntries(response.headers.entries()));
|
|
83
|
+
res.end(Buffer.from(await response.arrayBuffer()));
|
|
84
|
+
}).listen(port, () => {
|
|
85
|
+
console.log(\`Node server running at http://localhost:\${port}\`);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
function readBody(req: import("node:http").IncomingMessage): Promise<Buffer> {
|
|
89
|
+
return new Promise((resolve, reject) => {
|
|
90
|
+
const chunks: Buffer[] = [];
|
|
91
|
+
req.on("data", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
|
|
92
|
+
req.on("end", () => resolve(Buffer.concat(chunks)));
|
|
93
|
+
req.on("error", reject);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
`;
|
|
97
|
+
}
|
|
98
|
+
function f(e, t) {
|
|
99
|
+
let n = s(e, t).split("\\").join("/");
|
|
100
|
+
return `${n.startsWith(".") ? n : `./${n}`}/`;
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
export { u as nodeAdapter };
|
|
104
|
+
|
|
105
|
+
//# sourceMappingURL=node.js.map
|