@bascik/adapter-cloudflare 1.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,95 @@
1
+ Elastic License 2.0
2
+
3
+ URL: https://www.elastic.co/licensing/elastic-license
4
+
5
+ Copyright (c) 2026 Collin Thomas
6
+
7
+ ## Acceptance
8
+
9
+ By using the software, you agree to all of the terms and conditions below.
10
+
11
+ ## Copyright License
12
+
13
+ The licensor grants you a non-exclusive, royalty-free, worldwide,
14
+ non-sublicensable, non-transferable license to use, copy, distribute, make
15
+ available, and prepare derivative works of the software, in each case subject to
16
+ the limitations and conditions below.
17
+
18
+ ## Limitations
19
+
20
+ You may not provide the software to third parties as a hosted or managed
21
+ service, where the service provides users with access to any substantial set of
22
+ the features or functionality of the software.
23
+
24
+ You may not move, change, disable, or circumvent the license key functionality
25
+ in the software, and you may not remove or obscure any functionality in the
26
+ software that is protected by the license key.
27
+
28
+ You may not alter, remove, or obscure any licensing, copyright, or other notices
29
+ of the licensor in the software. Any use of the licensor's trademarks is subject
30
+ to applicable law.
31
+
32
+ ## Patents
33
+
34
+ The licensor grants you a license, under any patent claims the licensor can
35
+ license, or becomes able to license, to make, have made, use, sell, offer for
36
+ sale, import and have imported the software, in each case subject to the
37
+ limitations and conditions in this license. This license does not cover any
38
+ patent claims that you cause to be infringed by modifications or additions to
39
+ the software. If you or your company make any written claim that the software
40
+ infringes or contributes to infringement of any patent, your patent license for
41
+ the software granted under these terms ends immediately. If your company makes
42
+ such a claim, your patent license ends immediately for work on behalf of your
43
+ company.
44
+
45
+ ## Notices
46
+
47
+ You must ensure that anyone who gets a copy of any part of the software from you
48
+ also gets a copy of these terms.
49
+
50
+ If you modify the software, you must include in any modified copies of the
51
+ software prominent notices stating that you have modified the software.
52
+
53
+ ## No Other Rights
54
+
55
+ These terms do not imply any licenses other than those expressly granted in
56
+ these terms.
57
+
58
+ ## Termination
59
+
60
+ If you use the software in violation of these terms, such use is not licensed,
61
+ and your licenses will automatically terminate. If the licensor provides you
62
+ with a notice of your violation, and you cease all violation of this license no
63
+ later than 30 days after you receive that notice, your licenses will be
64
+ reinstated retroactively. However, if you violate these terms after such
65
+ reinstatement, any additional violation of these terms will cause your licenses
66
+ to terminate automatically and permanently.
67
+
68
+ ## No Liability
69
+
70
+ As far as the law allows, the software comes as is, without any warranty or
71
+ condition, and the licensor will not be liable to you for any damages arising
72
+ out of these terms or the use or nature of the software, under any kind of legal
73
+ claim.
74
+
75
+ ## Definitions
76
+
77
+ The **licensor** is the entity offering these terms, and the **software** is the
78
+ software the licensor makes available under these terms, including any portion
79
+ of it.
80
+
81
+ **you** refers to the individual or entity agreeing to these terms.
82
+
83
+ **your company** is any legal entity, sole proprietorship, or other kind of
84
+ organization that you work for, plus all organizations that have control over,
85
+ are under the control of, or are under common control with that organization.
86
+ **control** means ownership of substantially all the assets of an entity, or the
87
+ power to direct its management and policies by vote, contract, or otherwise.
88
+ Control can be direct or indirect.
89
+
90
+ **your licenses** are all the licenses granted to you for the software under
91
+ these terms.
92
+
93
+ **use** means anything you do with the software requiring one of your licenses.
94
+
95
+ **trademark** means trademarks, service marks, and similar rights.
package/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # @bascik/adapter-cloudflare
2
+
3
+ [![Unit lines](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fbascikdev%2Fbascik%2Fmain%2Fadapters%2Fcloudflare%2Ftest-coverage.json&query=%24.total.lines.pct&label=unit%20lines&suffix=%25&color=brightgreen)](https://github.com/bascikdev/bascik/blob/main/adapters/cloudflare/test-coverage.json)
4
+ [![Unit functions](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fbascikdev%2Fbascik%2Fmain%2Fadapters%2Fcloudflare%2Ftest-coverage.json&query=%24.total.functions.pct&label=unit%20functions&suffix=%25&color=brightgreen)](https://github.com/bascikdev/bascik/blob/main/adapters/cloudflare/test-coverage.json)
5
+
6
+ Cloudflare Workers with Static Assets and Cloudflare Pages hosting adapter for [Bascik](https://bascik.dev).
7
+
8
+ ## Overview
9
+
10
+ This adapter compiles Bascik request-time scripts and API routes into a Cloudflare Workers deployment bundle with static asset routing.
11
+
12
+ See the [Cloudflare deployment guide](https://bascik.dev/deployment/cloudflare) for setup instructions, recipes, and limits.
13
+
14
+ ## Targets and Variants
15
+
16
+ - `cloudflare` / `cloudflare-workers` (Default): Outputs `worker.js`, `wrangler.jsonc`, and `public/` for Cloudflare Workers with Static Assets.
17
+ - `cloudflare-pages` (Legacy): Outputs `public/_worker.js` and `public/_routes.json` for Cloudflare Pages.
18
+
19
+ ## Quickstart
20
+
21
+ Build for Cloudflare Workers with Static Assets:
22
+
23
+ ```sh
24
+ bascik --build --target cloudflare
25
+ ```
26
+
27
+ Preview locally with Wrangler from the emitted target directory:
28
+
29
+ ```sh
30
+ cd dist/.bascik/cloudflare
31
+ npx wrangler dev
32
+ ```
33
+
34
+ Deploy with Wrangler:
35
+
36
+ ```sh
37
+ cd dist/.bascik/cloudflare
38
+ npx wrangler deploy
39
+ ```
40
+
41
+ ## Compatibility Date
42
+
43
+ The adapter pins a supported Cloudflare compatibility date and `nodejs_compat` compatibility flag to ensure local workerd testing parity.
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @module build
3
+ *
4
+ * Cloudflare adapter build implementation.
5
+ */
6
+ import { pageAliasesFor, type AdapterBuildContext, type AdapterBuildResult } from "@bascik/bascik/adapter";
7
+ export { pageAliasesFor };
8
+ export interface InvocationRoutes {
9
+ include: string[];
10
+ exclude: string[];
11
+ overflowed: boolean;
12
+ }
13
+ export declare const buildInvocationRoutes: (input: {
14
+ base: string;
15
+ dynamicPagePaths: string[];
16
+ hasApiRoutes: boolean;
17
+ }) => InvocationRoutes;
18
+ export declare const detectControlCollisions: (publicPaths: string[], variant: string) => string[];
19
+ export declare const build: (context: AdapterBuildContext) => Promise<AdapterBuildResult>;
package/dist/build.js ADDED
@@ -0,0 +1,225 @@
1
+ /**
2
+ * @module build
3
+ *
4
+ * Cloudflare adapter build implementation.
5
+ */
6
+ import { pageAliasesFor } from "@bascik/bascik/adapter";
7
+ import { resolve, dirname, join, relative, sep } from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
+ import { mkdir, copyFile, writeFile } from "node:fs/promises";
10
+ import { CLOUDFLARE_COMPATIBILITY_DATE, CLOUDFLARE_COMPATIBILITY_FLAGS, PAGES_ROUTES_LIMIT, classifyNodeBuiltin, formatUnsupportedImport, } from "./compat.js";
11
+ import { resolveWorkerName } from "./config.js";
12
+ import { build as esbuildBuild } from "esbuild";
13
+ export { pageAliasesFor };
14
+ const withBasePath = (path, base) => {
15
+ if (base === "/" || !base)
16
+ return path;
17
+ const cleanBase = base.replace(/\/$/, "");
18
+ return path.startsWith("/") ? `${cleanBase}${path}` : `${cleanBase}/${path}`;
19
+ };
20
+ export const buildInvocationRoutes = (input) => {
21
+ const include = new Set();
22
+ for (const path of input.dynamicPagePaths)
23
+ for (const alias of pageAliasesFor(path, input.base))
24
+ include.add(alias);
25
+ if (input.hasApiRoutes)
26
+ include.add(withBasePath("/api/*", input.base));
27
+ include.add(withBasePath("/_routes.json", input.base));
28
+ include.add(withBasePath("/_worker.js", input.base));
29
+ const sorted = Array.from(include).sort();
30
+ if (sorted.length > PAGES_ROUTES_LIMIT) {
31
+ return { include: [withBasePath("/*", input.base)], exclude: [], overflowed: true };
32
+ }
33
+ return { include: sorted, exclude: [], overflowed: false };
34
+ };
35
+ const CONTROL_FILES = {
36
+ pages: ["_worker.js", "_routes.json"],
37
+ workers: ["wrangler.jsonc", "worker.js"],
38
+ };
39
+ export const detectControlCollisions = (publicPaths, variant) => {
40
+ const control = new Set(CONTROL_FILES[variant] ?? []);
41
+ const problems = [];
42
+ for (const path of [...publicPaths].sort()) {
43
+ if (control.has(path)) {
44
+ problems.push(`[bascik] --target cloudflare-${variant}: authored file "${path}" collides with a generated control file. Rename it or remove it from directory.pages.`);
45
+ }
46
+ }
47
+ return problems;
48
+ };
49
+ export const build = async (context) => {
50
+ const { graph, distDir, outDir, projectRoot, variant = "workers" } = context;
51
+ if (variant !== "pages" && variant !== "workers") {
52
+ throw new Error(`[bascik] --target cloudflare: unknown variant "${variant}". Valid variants are "pages" and "workers".`);
53
+ }
54
+ const publicDir = join(outDir, "public");
55
+ await mkdir(publicDir, { recursive: true });
56
+ const collisions = detectControlCollisions(graph.publicFiles, variant);
57
+ if (collisions.length)
58
+ throw new Error(collisions.join("\n"));
59
+ const owners = new Map();
60
+ const addOwner = (file, owner) => {
61
+ let set = owners.get(file);
62
+ if (!set) {
63
+ set = new Set();
64
+ owners.set(file, set);
65
+ }
66
+ set.add(owner);
67
+ };
68
+ const here = fileURLToPath(import.meta.url);
69
+ const runtimeFile = resolve(here, `../runtime${here.endsWith(".ts") ? ".ts" : ".js"}`);
70
+ const lines = [];
71
+ lines.push(`import { createCloudflareWorker } from ${JSON.stringify(runtimeFile)};`);
72
+ const pageLiterals = [];
73
+ for (const [httpPath, page] of Object.entries(graph.pages).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))) {
74
+ const jobLiterals = [];
75
+ for (const [id, job] of Object.entries(page.jobs)) {
76
+ let specifier;
77
+ if (job.source.kind === "module") {
78
+ specifier = job.source.path;
79
+ }
80
+ else {
81
+ specifier = job.source.stagedPath;
82
+ }
83
+ addOwner(specifier, job.owner);
84
+ jobLiterals.push(`${JSON.stringify(id)}: { id: ${JSON.stringify(id)}, mode: ${JSON.stringify(job.mode)}, load: () => import(${JSON.stringify(specifier)}) }`);
85
+ }
86
+ pageLiterals.push(`${JSON.stringify(httpPath)}: { path: ${JSON.stringify(httpPath)}, is404: ${page.is404}, segments: ${JSON.stringify(page.segments)}, jobs: { ${jobLiterals.join(", ")} } }`);
87
+ }
88
+ const routeLiterals = graph.apiRoutes.map((r) => {
89
+ addOwner(r.filePath, `API route ${r.path}`);
90
+ return `{ path: ${JSON.stringify(r.path)}, filePath: ${JSON.stringify(relative(projectRoot, r.filePath).replace(/\\/g, "/"))}, paramNames: ${JSON.stringify(r.paramNames)}, isDynamic: ${r.isDynamic}, load: () => import(${JSON.stringify(r.filePath)}) }`;
91
+ });
92
+ lines.push(`const graph = {`);
93
+ lines.push(` base: ${JSON.stringify(graph.base)},`);
94
+ lines.push(` scriptTimeoutMs: ${graph.scriptTimeoutMs},`);
95
+ lines.push(` apiTimeoutMs: ${graph.apiTimeoutMs},`);
96
+ lines.push(` onServerScriptError: ${JSON.stringify(graph.onServerScriptError)},`);
97
+ lines.push(` release: ${JSON.stringify(graph.release)},`);
98
+ if (graph.custom500 !== undefined)
99
+ lines.push(` custom500: ${JSON.stringify(graph.custom500)},`);
100
+ lines.push(` pages: { ${pageLiterals.join(",\n ")} },`);
101
+ lines.push(` apiRoutes: [ ${routeLiterals.join(",\n ")} ],`);
102
+ lines.push(`};`);
103
+ lines.push(`export default createCloudflareWorker(graph);`);
104
+ const stagingDir = join(outDir, ".staging");
105
+ await mkdir(stagingDir, { recursive: true });
106
+ const entryPath = join(stagingDir, "worker-entry.mjs");
107
+ await writeFile(entryPath, lines.join("\n"), "utf8");
108
+ // Bundle with esbuild owned by this adapter
109
+ const unsupported = [];
110
+ const result = await esbuildBuild({
111
+ entryPoints: [entryPath],
112
+ bundle: true,
113
+ write: false,
114
+ format: "esm",
115
+ platform: "neutral",
116
+ target: "es2022",
117
+ mainFields: ["workerd", "worker", "browser", "module", "main"],
118
+ conditions: ["workerd", "worker", "browser", "import", "module", "default"],
119
+ logLevel: "silent",
120
+ metafile: true,
121
+ absWorkingDir: projectRoot,
122
+ plugins: [
123
+ {
124
+ name: "bascik-request-time-graph",
125
+ setup(buildInstance) {
126
+ buildInstance.onResolve({ filter: /^@\// }, (args) => ({
127
+ errors: [
128
+ {
129
+ text: `"${args.path}" cannot be resolved from a module file. The @/ alias is available inside ` +
130
+ `<script> blocks only; in ${relative(projectRoot, args.importer).replace(/\\/g, "/")} use a relative import.`,
131
+ },
132
+ ],
133
+ }));
134
+ buildInstance.onResolve({ filter: /^file:/ }, (args) => {
135
+ const resolved = fileURLToPath(args.path);
136
+ for (const owner of owners.get(args.importer) ?? [])
137
+ addOwner(resolved, owner);
138
+ return { path: resolved };
139
+ });
140
+ buildInstance.onResolve({ filter: /^\.\.?\// }, (args) => {
141
+ const resolved = resolve(dirname(args.importer), args.path);
142
+ for (const owner of owners.get(args.importer) ?? [])
143
+ addOwner(resolved, owner);
144
+ return undefined;
145
+ });
146
+ buildInstance.onResolve({ filter: /^(node:)?[a-z_/]+$/ }, (args) => {
147
+ const kind = classifyNodeBuiltin(args.path);
148
+ if (kind === "not-builtin")
149
+ return undefined;
150
+ if (kind === "provided")
151
+ return { path: args.path.startsWith("node:") ? args.path : `node:${args.path}`, external: true };
152
+ const ownerList = [...(owners.get(args.importer) ?? [])];
153
+ unsupported.push(formatUnsupportedImport({ specifier: args.path, importer: args.importer, projectRoot, owners: ownerList }));
154
+ return { path: args.path, external: true };
155
+ });
156
+ },
157
+ },
158
+ ],
159
+ });
160
+ if (unsupported.length)
161
+ throw new Error([...new Set(unsupported)].join("\n"));
162
+ if (result.errors.length) {
163
+ throw new Error(`[bascik] --target cloudflare-${variant}: bundling failed:\n${result.errors.map((e) => ` ${e.location?.file ? `${e.location.file}: ` : ""}${e.text}`).join("\n")}`);
164
+ }
165
+ const workerCode = result.outputFiles?.[0]?.text ?? "";
166
+ // Copy public files
167
+ for (const rel of graph.publicFiles) {
168
+ const from = join(distDir, rel);
169
+ const to = join(publicDir, rel);
170
+ if (!resolve(to).startsWith(publicDir + sep))
171
+ continue;
172
+ await mkdir(dirname(to), { recursive: true });
173
+ await copyFile(from, to);
174
+ }
175
+ const invocationRoutes = buildInvocationRoutes({
176
+ base: graph.base,
177
+ dynamicPagePaths: Object.keys(graph.pages),
178
+ hasApiRoutes: graph.apiRoutes.length > 0,
179
+ });
180
+ let workerPath;
181
+ if (variant === "pages") {
182
+ workerPath = join(publicDir, "_worker.js");
183
+ await writeFile(workerPath, workerCode, "utf8");
184
+ await writeFile(join(publicDir, "_routes.json"), JSON.stringify({ version: 1, include: invocationRoutes.include, exclude: invocationRoutes.exclude }, null, 2), "utf8");
185
+ }
186
+ else {
187
+ workerPath = join(outDir, "worker.js");
188
+ await writeFile(workerPath, workerCode, "utf8");
189
+ // Discover authored user config and resolve worker name in priority order:
190
+ // 1. Environment variables (CLOUDFLARE_WORKER_NAME, WORKER_NAME, CF_PAGES_PROJECT_NAME)
191
+ // 2. Authored wrangler.jsonc / wrangler.json / wrangler.toml in project root
192
+ // 3. Project package.json "name"
193
+ // 4. Fallback to "bascik-site"
194
+ const { workerName, discoveredConfig } = await resolveWorkerName(projectRoot);
195
+ const authoredFlags = Array.isArray(discoveredConfig?.values?.compatibility_flags)
196
+ ? discoveredConfig.values.compatibility_flags.filter((f) => typeof f === "string" && f.trim().length > 0)
197
+ : [];
198
+ const wrangler = {
199
+ $schema: "node_modules/wrangler/config-schema.json",
200
+ name: workerName,
201
+ main: "worker.js",
202
+ compatibility_date: discoveredConfig?.values?.compatibility_date ?? CLOUDFLARE_COMPATIBILITY_DATE,
203
+ compatibility_flags: [...new Set([...authoredFlags, ...CLOUDFLARE_COMPATIBILITY_FLAGS])],
204
+ assets: {
205
+ directory: "./public",
206
+ binding: "ASSETS",
207
+ not_found_handling: "404-page",
208
+ run_worker_first: invocationRoutes.include,
209
+ },
210
+ };
211
+ await writeFile(join(outDir, "wrangler.jsonc"), `${JSON.stringify(wrangler, null, 2)}\n`, "utf8");
212
+ }
213
+ const bundleBytes = Buffer.byteLength(workerCode, "utf8");
214
+ return {
215
+ workerPath,
216
+ publicDir,
217
+ bundleBytes,
218
+ notes: [
219
+ `compatibility date: ${CLOUDFLARE_COMPATIBILITY_DATE}`,
220
+ `compatibility flags: ${CLOUDFLARE_COMPATIBILITY_FLAGS.join(", ")}`,
221
+ `invocation routes: ${invocationRoutes.include.length} rules`,
222
+ ],
223
+ };
224
+ };
225
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @module compat
3
+ *
4
+ * Pinned Cloudflare runtime constants and node builtin classifications.
5
+ */
6
+ export declare const CLOUDFLARE_COMPATIBILITY_DATE = "2026-08-01";
7
+ export declare const CLOUDFLARE_COMPATIBILITY_FLAGS: readonly ["nodejs_compat"];
8
+ export declare const PAGES_ROUTES_LIMIT = 100;
9
+ export declare const WORKERS_SUPPORTED_NODE_BUILTINS: ReadonlySet<string>;
10
+ export type NodeBuiltinClass = "provided" | "unsupported" | "not-builtin";
11
+ export declare const classifyNodeBuiltin: (specifier: string) => NodeBuiltinClass;
12
+ export declare const formatUnsupportedImport: (input: {
13
+ specifier: string;
14
+ importer: string;
15
+ projectRoot: string;
16
+ owners: string[];
17
+ }) => string;
package/dist/compat.js ADDED
@@ -0,0 +1,80 @@
1
+ /**
2
+ * @module compat
3
+ *
4
+ * Pinned Cloudflare runtime constants and node builtin classifications.
5
+ */
6
+ import { relative } from "node:path";
7
+ export const CLOUDFLARE_COMPATIBILITY_DATE = "2026-08-01";
8
+ export const CLOUDFLARE_COMPATIBILITY_FLAGS = ["nodejs_compat"];
9
+ export const PAGES_ROUTES_LIMIT = 100;
10
+ export const WORKERS_SUPPORTED_NODE_BUILTINS = new Set([
11
+ "assert",
12
+ "async_hooks",
13
+ "buffer",
14
+ "crypto",
15
+ "diagnostics_channel",
16
+ "dns",
17
+ "events",
18
+ "fs",
19
+ "fs/promises",
20
+ "http",
21
+ "https",
22
+ "net",
23
+ "os",
24
+ "path",
25
+ "path/posix",
26
+ "path/win32",
27
+ "perf_hooks",
28
+ "process",
29
+ "querystring",
30
+ "stream",
31
+ "stream/consumers",
32
+ "stream/promises",
33
+ "stream/web",
34
+ "string_decoder",
35
+ "timers",
36
+ "timers/promises",
37
+ "tls",
38
+ "url",
39
+ "util",
40
+ "util/types",
41
+ "zlib",
42
+ ]);
43
+ const ALL_NODE_BUILTINS = new Set([
44
+ ...WORKERS_SUPPORTED_NODE_BUILTINS,
45
+ "child_process",
46
+ "cluster",
47
+ "console",
48
+ "constants",
49
+ "dgram",
50
+ "domain",
51
+ "http2",
52
+ "inspector",
53
+ "module",
54
+ "punycode",
55
+ "readline",
56
+ "readline/promises",
57
+ "repl",
58
+ "sys",
59
+ "trace_events",
60
+ "tty",
61
+ "v8",
62
+ "vm",
63
+ "wasi",
64
+ "worker_threads",
65
+ ]);
66
+ export const classifyNodeBuiltin = (specifier) => {
67
+ const bare = specifier.startsWith("node:") ? specifier.slice(5) : specifier;
68
+ if (!ALL_NODE_BUILTINS.has(bare))
69
+ return "not-builtin";
70
+ return WORKERS_SUPPORTED_NODE_BUILTINS.has(bare) ? "provided" : "unsupported";
71
+ };
72
+ export const formatUnsupportedImport = (input) => {
73
+ const rel = relative(input.projectRoot, input.importer).replace(/\\/g, "/");
74
+ const owners = input.owners.length ? `\n Reached from: ${input.owners.join(", ")}` : "";
75
+ return (`[bascik] --target: "${input.specifier}" (imported by ${rel}) is not available in the Cloudflare Workers runtime ` +
76
+ `for compatibility date ${CLOUDFLARE_COMPATIBILITY_DATE}.${owners}\n` +
77
+ ` Supported node:* modules are: ${Array.from(WORKERS_SUPPORTED_NODE_BUILTINS).sort().join(", ")}.\n` +
78
+ ` Replace it with a Web standard API or a pure-JS package.`);
79
+ };
80
+ //# sourceMappingURL=compat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compat.js","sourceRoot":"","sources":["../src/compat.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,MAAM,CAAC,MAAM,6BAA6B,GAAG,YAAY,CAAC;AAC1D,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,eAAe,CAAU,CAAC;AACzE,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAEtC,MAAM,CAAC,MAAM,+BAA+B,GAAwB,IAAI,GAAG,CAAC;IAC1E,QAAQ;IACR,aAAa;IACb,QAAQ;IACR,QAAQ;IACR,qBAAqB;IACrB,KAAK;IACL,QAAQ;IACR,IAAI;IACJ,aAAa;IACb,MAAM;IACN,OAAO;IACP,KAAK;IACL,IAAI;IACJ,MAAM;IACN,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,SAAS;IACT,aAAa;IACb,QAAQ;IACR,kBAAkB;IAClB,iBAAiB;IACjB,YAAY;IACZ,gBAAgB;IAChB,QAAQ;IACR,iBAAiB;IACjB,KAAK;IACL,KAAK;IACL,MAAM;IACN,YAAY;IACZ,MAAM;CACP,CAAC,CAAC;AAEH,MAAM,iBAAiB,GAAwB,IAAI,GAAG,CAAC;IACrD,GAAG,+BAA+B;IAClC,eAAe;IACf,SAAS;IACT,SAAS;IACT,WAAW;IACX,OAAO;IACP,QAAQ;IACR,OAAO;IACP,WAAW;IACX,QAAQ;IACR,UAAU;IACV,UAAU;IACV,mBAAmB;IACnB,MAAM;IACN,KAAK;IACL,cAAc;IACd,KAAK;IACL,IAAI;IACJ,IAAI;IACJ,MAAM;IACN,gBAAgB;CACjB,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,SAAiB,EAAoB,EAAE;IACzE,MAAM,IAAI,GAAG,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5E,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,aAAa,CAAC;IACvD,OAAO,+BAA+B,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC;AAChF,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,KAKvC,EAAU,EAAE;IACX,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC5E,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,qBAAqB,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACzF,OAAO,CACL,uBAAuB,KAAK,CAAC,SAAS,kBAAkB,GAAG,uDAAuD;QAClH,0BAA0B,6BAA6B,IAAI,MAAM,IAAI;QACrE,mCAAmC,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;QACrG,4DAA4D,CAC7D,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * @module config
3
+ *
4
+ * Structured configuration discovery and parsing for Cloudflare Wrangler configuration files.
5
+ * Supports jsonc (comments and trailing commas), json, and toml with safe error reporting.
6
+ */
7
+ /**
8
+ * Wrangler configuration file discovery order according to Cloudflare Wrangler documentation:
9
+ * 1. wrangler.jsonc
10
+ * 2. wrangler.json
11
+ * 3. wrangler.toml
12
+ */
13
+ export declare const WRANGLER_CONFIG_FILES: readonly ["wrangler.jsonc", "wrangler.json", "wrangler.toml"];
14
+ export type WranglerConfigFile = (typeof WRANGLER_CONFIG_FILES)[number];
15
+ export interface ParsedWranglerConfig {
16
+ name?: string;
17
+ compatibility_date?: string;
18
+ compatibility_flags?: string[];
19
+ [key: string]: unknown;
20
+ }
21
+ export interface DiscoveredConfig {
22
+ filename: WranglerConfigFile;
23
+ filePath: string;
24
+ values: ParsedWranglerConfig;
25
+ }
26
+ /**
27
+ * Parses JSONC (JSON with comments and trailing commas) using the maintained
28
+ * jsonc-parser library (Microsoft, used by VS Code). The parser is fault
29
+ * tolerant and returns partial data on errors, so the errors array is always
30
+ * checked and any parse error rejects the input.
31
+ */
32
+ export declare function parseJsonc(text: string, filename?: string): ParsedWranglerConfig;
33
+ /**
34
+ * Parses TOML syntax using the maintained smol-toml library (BSD-3-Clause).
35
+ * The parser is strict: duplicate keys, duplicate tables, malformed values,
36
+ * and unclosed constructs all throw. Error messages are built from the first
37
+ * line of the parser message only, which never contains source excerpts or
38
+ * raw configuration values.
39
+ */
40
+ export declare function parseToml(text: string, filename?: string): ParsedWranglerConfig;
41
+ /**
42
+ * Discovers and parses the highest precedence Wrangler configuration file in the project root.
43
+ * Returns null if no Wrangler configuration file exists.
44
+ * Throws an actionable error if the discovered configuration file is malformed.
45
+ */
46
+ export declare function discoverWranglerConfig(projectRoot: string): Promise<DiscoveredConfig | null>;
47
+ /**
48
+ * Resolves the Worker name from candidate sources in strict priority order:
49
+ * 1. Environment variables (CLOUDFLARE_WORKER_NAME, WORKER_NAME, CF_PAGES_PROJECT_NAME)
50
+ * 2. Authored Wrangler config (wrangler.jsonc, wrangler.json, wrangler.toml in discovery order)
51
+ * 3. Root package.json "name" field (with @scope/ stripped)
52
+ * 4. Fallback default: "bascik-site"
53
+ */
54
+ export declare function resolveWorkerName(projectRoot: string, discoveredConfig?: DiscoveredConfig | null): Promise<{
55
+ workerName: string;
56
+ source: "env" | "config" | "package" | "default";
57
+ discoveredConfig?: DiscoveredConfig | null;
58
+ }>;
package/dist/config.js ADDED
@@ -0,0 +1,152 @@
1
+ /**
2
+ * @module config
3
+ *
4
+ * Structured configuration discovery and parsing for Cloudflare Wrangler configuration files.
5
+ * Supports jsonc (comments and trailing commas), json, and toml with safe error reporting.
6
+ */
7
+ import { join } from "node:path";
8
+ import { readFile } from "node:fs/promises";
9
+ import { parse as parseJsoncRaw, printParseErrorCode } from "jsonc-parser";
10
+ import { parse as parseTomlRaw, TomlError } from "smol-toml";
11
+ /**
12
+ * Wrangler configuration file discovery order according to Cloudflare Wrangler documentation:
13
+ * 1. wrangler.jsonc
14
+ * 2. wrangler.json
15
+ * 3. wrangler.toml
16
+ */
17
+ export const WRANGLER_CONFIG_FILES = [
18
+ "wrangler.jsonc",
19
+ "wrangler.json",
20
+ "wrangler.toml",
21
+ ];
22
+ /**
23
+ * Parses JSONC (JSON with comments and trailing commas) using the maintained
24
+ * jsonc-parser library (Microsoft, used by VS Code). The parser is fault
25
+ * tolerant and returns partial data on errors, so the errors array is always
26
+ * checked and any parse error rejects the input.
27
+ */
28
+ export function parseJsonc(text, filename = "wrangler.jsonc") {
29
+ const errors = [];
30
+ const parsed = parseJsoncRaw(text, errors, { allowTrailingComma: true });
31
+ if (errors.length > 0) {
32
+ const first = errors[0];
33
+ const { line, character } = lineAndCharacterAt(text, first.offset);
34
+ const reason = printParseErrorCode(first.error);
35
+ throw new Error(`[bascik] Failed to parse ${filename} at line ${line}, column ${character}: ${reason}.`);
36
+ }
37
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
38
+ throw new Error(`[bascik] Failed to parse ${filename}: expected a top-level JSON object.`);
39
+ }
40
+ return parsed;
41
+ }
42
+ /**
43
+ * Computes a 1-based line and column for a character offset within text.
44
+ */
45
+ function lineAndCharacterAt(text, offset) {
46
+ let line = 1;
47
+ let character = 1;
48
+ const end = Math.min(offset, text.length);
49
+ for (let i = 0; i < end; i++) {
50
+ if (text[i] === "\n") {
51
+ line++;
52
+ character = 1;
53
+ }
54
+ else {
55
+ character++;
56
+ }
57
+ }
58
+ return { line, character };
59
+ }
60
+ /**
61
+ * Parses TOML syntax using the maintained smol-toml library (BSD-3-Clause).
62
+ * The parser is strict: duplicate keys, duplicate tables, malformed values,
63
+ * and unclosed constructs all throw. Error messages are built from the first
64
+ * line of the parser message only, which never contains source excerpts or
65
+ * raw configuration values.
66
+ */
67
+ export function parseToml(text, filename = "wrangler.toml") {
68
+ try {
69
+ const parsed = parseTomlRaw(text);
70
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
71
+ throw new Error(`[bascik] Failed to parse ${filename}: expected a top-level TOML table.`);
72
+ }
73
+ return parsed;
74
+ }
75
+ catch (err) {
76
+ if (err instanceof TomlError) {
77
+ // TomlError.message includes a codeblock with source excerpts and raw
78
+ // values. Only the first line is safe to surface.
79
+ const reason = err.message.split("\n")[0];
80
+ throw new Error(`[bascik] Failed to parse ${filename} at line ${err.line}: ${reason}.`);
81
+ }
82
+ const msg = err instanceof Error ? err.message : String(err);
83
+ throw new Error(`[bascik] Failed to parse ${filename}: ${msg}`);
84
+ }
85
+ }
86
+ /**
87
+ * Discovers and parses the highest precedence Wrangler configuration file in the project root.
88
+ * Returns null if no Wrangler configuration file exists.
89
+ * Throws an actionable error if the discovered configuration file is malformed.
90
+ */
91
+ export async function discoverWranglerConfig(projectRoot) {
92
+ for (const filename of WRANGLER_CONFIG_FILES) {
93
+ const filePath = join(projectRoot, filename);
94
+ let raw;
95
+ try {
96
+ raw = await readFile(filePath, "utf8");
97
+ }
98
+ catch (err) {
99
+ if (err.code === "ENOENT") {
100
+ continue;
101
+ }
102
+ throw err;
103
+ }
104
+ // The file exists: parse it according to its extension
105
+ if (filename.endsWith(".toml")) {
106
+ const values = parseToml(raw, filename);
107
+ return { filename, filePath, values };
108
+ }
109
+ else {
110
+ const values = parseJsonc(raw, filename);
111
+ return { filename, filePath, values };
112
+ }
113
+ }
114
+ return null;
115
+ }
116
+ /**
117
+ * Resolves the Worker name from candidate sources in strict priority order:
118
+ * 1. Environment variables (CLOUDFLARE_WORKER_NAME, WORKER_NAME, CF_PAGES_PROJECT_NAME)
119
+ * 2. Authored Wrangler config (wrangler.jsonc, wrangler.json, wrangler.toml in discovery order)
120
+ * 3. Root package.json "name" field (with @scope/ stripped)
121
+ * 4. Fallback default: "bascik-site"
122
+ */
123
+ export async function resolveWorkerName(projectRoot, discoveredConfig) {
124
+ const envName = process.env.CLOUDFLARE_WORKER_NAME ||
125
+ process.env.WORKER_NAME ||
126
+ process.env.CF_PAGES_PROJECT_NAME;
127
+ if (envName && envName.trim()) {
128
+ return { workerName: envName.trim(), source: "env", discoveredConfig };
129
+ }
130
+ const discovered = discoveredConfig !== undefined ? discoveredConfig : await discoverWranglerConfig(projectRoot);
131
+ if (discovered && discovered.values.name && typeof discovered.values.name === "string" && discovered.values.name.trim()) {
132
+ return { workerName: discovered.values.name.trim(), source: "config", discoveredConfig: discovered };
133
+ }
134
+ try {
135
+ const pkgJsonRaw = await readFile(join(projectRoot, "package.json"), "utf8");
136
+ const pkgJson = JSON.parse(pkgJsonRaw);
137
+ if (pkgJson.name && typeof pkgJson.name === "string" && pkgJson.name.trim()) {
138
+ const name = pkgJson.name.replace(/^@[^/]+\//, "").trim();
139
+ if (name) {
140
+ return { workerName: name, source: "package", discoveredConfig: discovered };
141
+ }
142
+ }
143
+ }
144
+ catch (err) {
145
+ if (err.code !== "ENOENT") {
146
+ const msg = err instanceof Error ? err.message : String(err);
147
+ throw new Error(`[bascik] Failed to parse package.json: ${msg}`);
148
+ }
149
+ }
150
+ return { workerName: "bascik-site", source: "default", discoveredConfig: discovered };
151
+ }
152
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @module index
3
+ *
4
+ * Default export of @bascik/adapter-cloudflare.
5
+ */
6
+ export { CLOUDFLARE_COMPATIBILITY_DATE, CLOUDFLARE_COMPATIBILITY_FLAGS } from "./compat.js";
7
+ export { buildInvocationRoutes } from "./build.js";
8
+ declare const _default: import("@bascik/bascik/adapter").HostingAdapter;
9
+ export default _default;
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @module index
3
+ *
4
+ * Default export of @bascik/adapter-cloudflare.
5
+ */
6
+ import { defineAdapter } from "@bascik/bascik/adapter";
7
+ import { build } from "./build.js";
8
+ export { CLOUDFLARE_COMPATIBILITY_DATE, CLOUDFLARE_COMPATIBILITY_FLAGS } from "./compat.js";
9
+ export { buildInvocationRoutes } from "./build.js";
10
+ export default defineAdapter({
11
+ name: "cloudflare",
12
+ build,
13
+ });
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,6BAA6B,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAC5F,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEnD,eAAe,aAAa,CAAC;IAC3B,IAAI,EAAE,YAAY;IAClB,KAAK;CACN,CAAC,CAAC"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * @module adapters/cloudflare-runtime
3
+ *
4
+ * The request handler that runs inside a Cloudflare Worker (prompt 134).
5
+ * ─────────────────────────────────────────────────────────────────────────────
6
+ *
7
+ * Portable: no Node imports. It is bundled into the generated `_worker.js`
8
+ * together with the site graph emitted by `serverless-artifacts.ts`, and it
9
+ * drives the same execution core the Node server uses
10
+ * (`lib/request-execution.ts`).
11
+ *
12
+ * Request flow inside the Worker:
13
+ *
14
+ * fetch(request, env, ctx)
15
+ * ├─ unsafe or hidden path -> 400 / 404
16
+ * ├─ outside `base` -> 404
17
+ * ├─ API route match -> dispatchApiHandler(...)
18
+ * ├─ dynamic page alias match -> compose from private template
19
+ * │ ├─ no stream jobs or HEAD -> buffered body, content-length
20
+ * │ └─ stream jobs -> Response(ReadableStream) before body completes
21
+ * └─ anything else -> env.ASSETS.fetch(request)
22
+ *
23
+ * Every dynamic page template lives in the private graph, never in the public
24
+ * asset tree, so a routing failure that lets a request fall through to assets
25
+ * yields a 404, not an inert-placeholder document.
26
+ *
27
+ * Bindings and execution context reach handlers as `context.platform`
28
+ * (`{ name: "cloudflare", env, waitUntil }`). Nothing is copied onto globals
29
+ * and `process.env` is never touched.
30
+ */
31
+ import { type ApiHandlerModule, type PlatformContext, type ScriptJobRunner, type ApiRouteDefinition } from "@bascik/bascik/runtime";
32
+ /** A request-time script job inside a dynamic page template. */
33
+ export interface GraphScriptJob {
34
+ id: string;
35
+ mode: "server" | "stream";
36
+ /** Loader for the compiled module; `default` is the handler. */
37
+ load: () => Promise<{
38
+ default: unknown;
39
+ }>;
40
+ }
41
+ export interface GraphPageSegment {
42
+ kind: "static" | "script";
43
+ /** UTF-8 text for static segments. */
44
+ text?: string;
45
+ /** Job id for script segments. */
46
+ id?: string;
47
+ }
48
+ export interface GraphPage {
49
+ /** Canonical HTTP path (`/`, `/blog/`, `/about`). */
50
+ path: string;
51
+ /** Whether this page is the authored 404 page. */
52
+ is404: boolean;
53
+ segments: GraphPageSegment[];
54
+ jobs: Record<string, GraphScriptJob>;
55
+ }
56
+ export interface GraphApiRoute extends ApiRouteDefinition {
57
+ load: () => Promise<ApiHandlerModule>;
58
+ }
59
+ export interface SiteGraph {
60
+ /** Normalized base path, always starting and ending with `/`. */
61
+ base: string;
62
+ /** Script deadline for server/stream jobs, ms. */
63
+ scriptTimeoutMs: number;
64
+ /** Deadline for API handlers, ms. */
65
+ apiTimeoutMs: number;
66
+ /** `scripts.onServerScriptError` at build time. */
67
+ onServerScriptError: "error" | "warn" | "ignore";
68
+ /** Dynamic pages by canonical path. */
69
+ pages: Record<string, GraphPage>;
70
+ /** Sorted API routes (static before dynamic). */
71
+ apiRoutes: GraphApiRoute[];
72
+ /** Optional authored 500 page body. */
73
+ custom500?: string;
74
+ /** Release identity for diagnostics headers. */
75
+ release: string;
76
+ }
77
+ export interface CloudflareAssetsBinding {
78
+ fetch(request: Request): Promise<Response>;
79
+ }
80
+ export interface CloudflareEnv {
81
+ ASSETS?: CloudflareAssetsBinding;
82
+ [binding: string]: unknown;
83
+ }
84
+ export interface CloudflareExecutionContext {
85
+ waitUntil(promise: Promise<unknown>): void;
86
+ passThroughOnException?(): void;
87
+ }
88
+ export interface CloudflareWorker {
89
+ fetch(request: Request, env: CloudflareEnv, ctx: CloudflareExecutionContext): Promise<Response>;
90
+ }
91
+ /** `stripBasePath` from `lib/base-path.ts`, inlined to keep this graph free of the shielding import. */
92
+ export declare const stripBase: (pathname: string, base: string) => string | null;
93
+ /** Derive the client IP from Cloudflare's trusted header; never from X-Forwarded-For. */
94
+ export declare const cloudflareRemoteIp: (request: Request) => string;
95
+ /**
96
+ * Build a `ScriptJobRunner` for one request. Output handling mirrors
97
+ * `runServerScriptJob`: a string or stringifiable value is the fragment;
98
+ * failure under `onServerScriptError: "error"` throws (500 before commit,
99
+ * empty after), `warn` logs and yields empty, `ignore` yields empty.
100
+ */
101
+ export declare const createGraphJobRunner: (page: GraphPage, graph: SiteGraph, request: Request, context: {
102
+ remoteIp: string;
103
+ platform: PlatformContext;
104
+ }, log: (message: string) => void) => ScriptJobRunner;
105
+ export interface CreateWorkerOptions {
106
+ /** Diagnostics sink; defaults to `console.error`. Never reaches the client. */
107
+ log?: (message: string) => void;
108
+ }
109
+ /**
110
+ * Build the Module Worker `fetch` handler for a site graph. The returned
111
+ * object is what `_worker.js` exports as `default`.
112
+ */
113
+ export declare const createCloudflareWorker: (graph: SiteGraph, options?: CreateWorkerOptions) => CloudflareWorker;
@@ -0,0 +1,217 @@
1
+ /**
2
+ * @module adapters/cloudflare-runtime
3
+ *
4
+ * The request handler that runs inside a Cloudflare Worker (prompt 134).
5
+ * ─────────────────────────────────────────────────────────────────────────────
6
+ *
7
+ * Portable: no Node imports. It is bundled into the generated `_worker.js`
8
+ * together with the site graph emitted by `serverless-artifacts.ts`, and it
9
+ * drives the same execution core the Node server uses
10
+ * (`lib/request-execution.ts`).
11
+ *
12
+ * Request flow inside the Worker:
13
+ *
14
+ * fetch(request, env, ctx)
15
+ * ├─ unsafe or hidden path -> 400 / 404
16
+ * ├─ outside `base` -> 404
17
+ * ├─ API route match -> dispatchApiHandler(...)
18
+ * ├─ dynamic page alias match -> compose from private template
19
+ * │ ├─ no stream jobs or HEAD -> buffered body, content-length
20
+ * │ └─ stream jobs -> Response(ReadableStream) before body completes
21
+ * └─ anything else -> env.ASSETS.fetch(request)
22
+ *
23
+ * Every dynamic page template lives in the private graph, never in the public
24
+ * asset tree, so a routing failure that lets a request fall through to assets
25
+ * yields a 404, not an inert-placeholder document.
26
+ *
27
+ * Bindings and execution context reach handlers as `context.platform`
28
+ * (`{ name: "cloudflare", env, waitUntil }`). Nothing is copied onto globals
29
+ * and `process.env` is never touched.
30
+ */
31
+ import { composeBufferedResponse, dispatchApiHandler, invokeWithDeadline, streamComposedResponse, dynamicPageHeaders, errorResponse, internalErrorPage, mergeHandlerHeaders, stripRepresentationHeaders, GENERATED_CONTROL_PATHS, hasHiddenSegment, isUnsafePathname, matchApiRoute, pageLookupCandidates, } from "@bascik/bascik/runtime";
32
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
33
+ const encoder = new TextEncoder();
34
+ const CONTROL_PATHS = new Set(GENERATED_CONTROL_PATHS);
35
+ /** `stripBasePath` from `lib/base-path.ts`, inlined to keep this graph free of the shielding import. */
36
+ export const stripBase = (pathname, base) => {
37
+ if (base === "/")
38
+ return pathname;
39
+ const prefix = base.endsWith("/") ? base.slice(0, -1) : base;
40
+ if (pathname === prefix)
41
+ return "/";
42
+ if (!pathname.startsWith(`${prefix}/`))
43
+ return null;
44
+ return pathname.slice(prefix.length);
45
+ };
46
+ /** Derive the client IP from Cloudflare's trusted header; never from X-Forwarded-For. */
47
+ export const cloudflareRemoteIp = (request) => request.headers.get("cf-connecting-ip") ?? "";
48
+ const isHttps = (request) => new URL(request.url).protocol === "https:";
49
+ const toExecutionPlan = (page) => {
50
+ const segments = page.segments.map((segment) => segment.kind === "static"
51
+ ? { kind: "static", bytes: encoder.encode(segment.text ?? "") }
52
+ : { kind: "script", mode: page.jobs[segment.id].mode, id: segment.id });
53
+ return { segments, firstStreamIndex: segments.findIndex((s) => s.kind === "script" && s.mode === "stream") };
54
+ };
55
+ const findPage = (graph, pathname) => {
56
+ for (const candidate of pageLookupCandidates(pathname)) {
57
+ const page = graph.pages[candidate];
58
+ if (page)
59
+ return page;
60
+ }
61
+ return undefined;
62
+ };
63
+ /**
64
+ * Build a `ScriptJobRunner` for one request. Output handling mirrors
65
+ * `runServerScriptJob`: a string or stringifiable value is the fragment;
66
+ * failure under `onServerScriptError: "error"` throws (500 before commit,
67
+ * empty after), `warn` logs and yields empty, `ignore` yields empty.
68
+ */
69
+ export const createGraphJobRunner = (page, graph, request, context, log) => {
70
+ return async (id, signal) => {
71
+ const job = page.jobs[id];
72
+ if (!job)
73
+ throw new Error(`[bascik] server script job "${id}" is missing from the deployment graph.`);
74
+ const result = await invokeWithDeadline(async ({ signal: jobSignal }) => {
75
+ const mod = await job.load();
76
+ const handler = mod.default;
77
+ if (typeof handler !== "function") {
78
+ throw new TypeError(`Server script "${id}" does not export a default function.`);
79
+ }
80
+ return handler(request, context, { signal: jobSignal });
81
+ }, { timeoutMs: graph.scriptTimeoutMs, signal });
82
+ if (result.ok) {
83
+ const value = result.value;
84
+ return typeof value === "string" ? value : value !== undefined && value !== null ? String(value) : "";
85
+ }
86
+ if (result.aborted && !result.timedOut)
87
+ return "";
88
+ const error = result.error ?? new Error("Server script failed");
89
+ const message = `[bascik] server script error at "${new URL(request.url).pathname}":\n${error.stack ?? error.message}`;
90
+ if (graph.onServerScriptError === "error")
91
+ throw new Error(message);
92
+ if (graph.onServerScriptError === "warn")
93
+ log(message);
94
+ return "";
95
+ };
96
+ };
97
+ /**
98
+ * Build the Module Worker `fetch` handler for a site graph. The returned
99
+ * object is what `_worker.js` exports as `default`.
100
+ */
101
+ export const createCloudflareWorker = (graph, options = {}) => {
102
+ const log = options.log ?? ((message) => console.error(message));
103
+ const forwardToAssets = async (request, env) => {
104
+ if (!env.ASSETS) {
105
+ log("[bascik] ASSETS binding is missing: static requests cannot be served.");
106
+ return errorResponse(500, "Internal Server Error", { https: isHttps(request) });
107
+ }
108
+ return env.ASSETS.fetch(request);
109
+ };
110
+ const fetchHandler = async (request, env, ctx) => {
111
+ const https = isHttps(request);
112
+ const url = new URL(request.url);
113
+ let pathname;
114
+ try {
115
+ pathname = decodeURIComponent(url.pathname);
116
+ }
117
+ catch {
118
+ return errorResponse(400, "Bad Request", { https });
119
+ }
120
+ if (isUnsafePathname(pathname))
121
+ return errorResponse(400, "Bad Request", { https });
122
+ if (hasHiddenSegment(pathname))
123
+ return errorResponse(404, "Not Found", { https });
124
+ const baseRelative = stripBase(pathname, graph.base);
125
+ if (baseRelative === null)
126
+ return errorResponse(404, "Not Found", { https });
127
+ // The bundle and its routing table are deployment control files, never
128
+ // content. Refusing them here makes the guarantee independent of how a
129
+ // host treats underscore-prefixed uploads.
130
+ if (CONTROL_PATHS.has(baseRelative))
131
+ return errorResponse(404, "Not Found", { https });
132
+ const platform = {
133
+ name: "cloudflare",
134
+ env,
135
+ waitUntil: (promise) => ctx.waitUntil(promise),
136
+ };
137
+ const remoteIp = cloudflareRemoteIp(request);
138
+ // ── API routes (before the method guard so every method reaches them) ──
139
+ const apiMatch = matchApiRoute(graph.apiRoutes, pathname);
140
+ if (apiMatch) {
141
+ const route = apiMatch.route;
142
+ let mod;
143
+ try {
144
+ mod = await route.load();
145
+ }
146
+ catch (err) {
147
+ log(`[bascik] Failed to load API route module ${route.filePath}: ${err.stack ?? String(err)}`);
148
+ return errorResponse(500, "Internal Server Error", { https });
149
+ }
150
+ const context = { params: apiMatch.params, remoteIp, platform };
151
+ const response = await dispatchApiHandler(mod, request, context, {
152
+ timeoutMs: graph.apiTimeoutMs,
153
+ signal: request.signal,
154
+ onError: (message, error) => log(`[bascik] ${message}${error ? `\n${error.stack ?? String(error)}` : ""}`),
155
+ });
156
+ const headers = mergeHandlerHeaders(response.headers, { https });
157
+ return new Response(request.method === "HEAD" ? null : response.body, {
158
+ status: response.status,
159
+ statusText: response.statusText,
160
+ headers,
161
+ });
162
+ }
163
+ // ── Dynamic pages ─────────────────────────────────────────────────────
164
+ const page = findPage(graph, baseRelative);
165
+ if (!page)
166
+ return forwardToAssets(request, env);
167
+ const isHead = request.method === "HEAD";
168
+ if (request.method !== "GET" && !isHead) {
169
+ const headers = new Headers(errorResponse(405, "", { https }).headers);
170
+ headers.set("allow", "GET, HEAD");
171
+ return new Response("Method Not Allowed", { status: 405, headers });
172
+ }
173
+ const status = page.is404 ? 404 : 200;
174
+ const plan = toExecutionPlan(page);
175
+ const run = createGraphJobRunner(page, graph, request, { remoteIp, platform }, log);
176
+ if (plan.firstStreamIndex === -1 || isHead) {
177
+ let body;
178
+ try {
179
+ body = await composeBufferedResponse(plan, run, request.signal);
180
+ }
181
+ catch (err) {
182
+ log(err instanceof Error ? err.message : String(err));
183
+ return internalErrorPage(graph.custom500, { https });
184
+ }
185
+ const headers = dynamicPageHeaders({ https, contentLength: body.byteLength });
186
+ return new Response(isHead ? null : body, { status, headers });
187
+ }
188
+ // Early flush: every `server` job settles before headers commit; the
189
+ // Response carries a demand-gated ReadableStream and is returned BEFORE
190
+ // the body completes. Stream failures are logged, never a status change.
191
+ const streamer = streamComposedResponse(plan, run, undefined, {
192
+ signal: request.signal,
193
+ onStreamError: (err) => log(err instanceof Error ? err.message : String(err)),
194
+ });
195
+ try {
196
+ await streamer.ready;
197
+ }
198
+ catch (err) {
199
+ log(err instanceof Error ? err.message : String(err));
200
+ return internalErrorPage(graph.custom500, { https });
201
+ }
202
+ const headers = stripRepresentationHeaders(dynamicPageHeaders({ https }));
203
+ // The edge compresses Worker responses on the fly and, for a streamed
204
+ // body, holds every byte until the stream closes (observed in workerd:
205
+ // only the gzip header leaves early). An explicit identity encoding opts
206
+ // this response out so the static prefix reaches the browser now. Static
207
+ // assets keep edge compression; only progressively rendered documents pay
208
+ // the uncompressed cost, which is the price of early paint.
209
+ headers.set("content-encoding", "identity");
210
+ // Keep the isolate alive until the last fragment is written even if the
211
+ // platform would otherwise consider the request finished.
212
+ ctx.waitUntil(streamer.done);
213
+ return new Response(streamer.toReadableStream(), { status, headers });
214
+ };
215
+ return { fetch: fetchHandler };
216
+ };
217
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@bascik/adapter-cloudflare",
3
+ "version": "1.0.0-rc.1",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/bascikdev/bascik.git",
7
+ "directory": "adapters/cloudflare"
8
+ },
9
+ "description": "Cloudflare Pages and Workers adapter for Bascik",
10
+ "license": "Elastic-2.0",
11
+ "type": "module",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "default": "./dist/index.js"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist/",
20
+ "LICENSE",
21
+ "README.md"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsc -p tsconfig.build.json",
25
+ "cover": "yarn coverage",
26
+ "coverage": "vitest run --coverage.enabled && node bin/update-coverage.ts",
27
+ "prepack": "cp ../../LICENSE LICENSE",
28
+ "prepare": "tsc -p tsconfig.build.json",
29
+ "test:ci": "vitest run",
30
+ "typecheck": "tsc --noEmit",
31
+ "unit": "vitest run",
32
+ "update-coverage": "yarn coverage",
33
+ "e2e": "playwright test --config e2e/playwright.config.ts"
34
+ },
35
+ "dependencies": {
36
+ "esbuild": "^0.28.2",
37
+ "jsonc-parser": "^3.3.1",
38
+ "smol-toml": "^1.8.0"
39
+ },
40
+ "peerDependencies": {
41
+ "@bascik/bascik": "^1.0.0-rc.1"
42
+ },
43
+ "devDependencies": {
44
+ "@bascik/bascik": "workspace:*",
45
+ "@playwright/test": "^1.58.2",
46
+ "@types/node": "^24.0.0",
47
+ "@vitest/coverage-v8": "^4.1.10",
48
+ "miniflare": "4.20260730.0",
49
+ "typescript": "^7.0.2",
50
+ "vitest": "^4.1.10"
51
+ },
52
+ "publishConfig": {
53
+ "access": "public"
54
+ },
55
+ "engines": {
56
+ "node": ">=22.18.0"
57
+ }
58
+ }