@astrojs/cloudflare 13.0.0-alpha.1 → 13.0.0-alpha.3

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.
@@ -6,28 +6,20 @@ import { cloudflare as cfVitePlugin } from "@cloudflare/vite-plugin";
6
6
  import colors from "piccolore";
7
7
  import { performance } from "node:perf_hooks";
8
8
  import { hasWranglerConfig, defaultCloudflareConfig } from "../wrangler.js";
9
- import { copyFileSync, existsSync } from "node:fs";
10
9
  const createPreviewServer = async ({
11
10
  logger,
12
11
  base,
13
- outDir,
12
+ server,
14
13
  headers,
15
14
  port,
16
15
  host,
17
- createCodegenDir,
18
16
  root
19
17
  }) => {
20
18
  const startServerTime = performance.now();
21
19
  let previewServer;
22
20
  let cfPluginConfig = { viteEnvironment: { name: "ssr" } };
23
- if (!hasWranglerConfig(outDir)) {
21
+ if (!hasWranglerConfig(server)) {
24
22
  cfPluginConfig.config = defaultCloudflareConfig();
25
- const codegenDir = createCodegenDir();
26
- const devVarsPath = new URL(".dev.vars", outDir);
27
- const devVarsCodegenPath = new URL(".dev.vars", codegenDir);
28
- if (existsSync(devVarsPath)) {
29
- copyFileSync(devVarsPath, devVarsCodegenPath);
30
- }
31
23
  }
32
24
  try {
33
25
  previewServer = await preview({
@@ -35,7 +27,7 @@ const createPreviewServer = async ({
35
27
  base,
36
28
  appType: "mpa",
37
29
  build: {
38
- outDir: fileURLToPath(outDir)
30
+ outDir: fileURLToPath(server)
39
31
  },
40
32
  root: fileURLToPath(root),
41
33
  preview: {
@@ -91,7 +83,7 @@ function serverStart({
91
83
  host,
92
84
  base
93
85
  }) {
94
- const version = "13.0.0-alpha.1";
86
+ const version = "13.0.0-alpha.3";
95
87
  const localPrefix = `${colors.dim("\u2503")} Local `;
96
88
  const networkPrefix = `${colors.dim("\u2503")} Network `;
97
89
  const emptyPrefix = " ".repeat(11);
package/dist/index.js CHANGED
@@ -1,13 +1,9 @@
1
- import { createReadStream, copyFileSync, existsSync, readFileSync } from "node:fs";
1
+ import { createReadStream, existsSync, readFileSync } from "node:fs";
2
2
  import { appendFile, stat } from "node:fs/promises";
3
3
  import { createRequire } from "node:module";
4
4
  import { createInterface } from "node:readline/promises";
5
5
  import { pathToFileURL } from "node:url";
6
- import {
7
- appendForwardSlash,
8
- prependForwardSlash,
9
- removeLeadingForwardSlash
10
- } from "@astrojs/internal-helpers/path";
6
+ import { removeLeadingForwardSlash } from "@astrojs/internal-helpers/path";
11
7
  import { createRedirectsFromAstroRoutes, printAsRedirects } from "@astrojs/underscore-redirects";
12
8
  import { cloudflare as cfVitePlugin } from "@cloudflare/vite-plugin";
13
9
  import { cloudflareModuleLoader } from "./utils/cloudflare-module-loader.js";
@@ -16,9 +12,7 @@ import { setImageConfig } from "./utils/image-config.js";
16
12
  import { createConfigPlugin } from "./vite-plugin-config.js";
17
13
  import { hasWranglerConfig, defaultCloudflareConfig } from "./wrangler.js";
18
14
  import { parse } from "dotenv";
19
- function wrapWithSlashes(path) {
20
- return prependForwardSlash(appendForwardSlash(path));
21
- }
15
+ import { sessionDrivers } from "astro/config";
22
16
  function createIntegration(args) {
23
17
  let _config;
24
18
  let finalBuildOutput;
@@ -30,53 +24,33 @@ function createIntegration(args) {
30
24
  return {
31
25
  name: "@astrojs/cloudflare",
32
26
  hooks: {
33
- "astro:config:setup": ({
34
- command,
35
- config,
36
- updateConfig,
37
- logger,
38
- addWatchFile,
39
- createCodegenDir
40
- }) => {
27
+ "astro:config:setup": ({ command, config, updateConfig, logger, addWatchFile }) => {
41
28
  let session = config.session;
42
29
  if (args?.imageService === "cloudflare-binding") {
43
30
  const bindingName = args?.imagesBindingName ?? "IMAGES";
44
31
  logger.info(
45
32
  `Enabling image processing with Cloudflare Images for production with the "${bindingName}" Images binding.`
46
33
  );
47
- logger.info(
48
- `If you see the error "Invalid binding \`${bindingName}\`" in your build output, you need to add the binding to your wrangler config file.`
49
- );
50
34
  }
51
35
  if (!session?.driver) {
52
36
  logger.info(
53
37
  `Enabling sessions with Cloudflare KV with the "${SESSION_KV_BINDING_NAME}" KV binding.`
54
38
  );
55
- logger.info(
56
- `If you see the error "Invalid binding \`${SESSION_KV_BINDING_NAME}\`" in your build output, you need to add the binding to your wrangler config file.`
57
- );
58
39
  session = {
59
- ...session,
60
- driver: "cloudflare-kv-binding",
61
- options: {
62
- binding: SESSION_KV_BINDING_NAME,
63
- ...session?.options
64
- }
40
+ driver: sessionDrivers.cloudflareKVBinding({
41
+ binding: SESSION_KV_BINDING_NAME
42
+ }),
43
+ cookie: session?.cookie,
44
+ ttl: session?.ttl
65
45
  };
66
46
  }
67
47
  const cfPluginConfig = { viteEnvironment: { name: "ssr" } };
68
48
  if (!hasWranglerConfig(config.root)) {
69
49
  cfPluginConfig.config = defaultCloudflareConfig();
70
- const codegenDir = createCodegenDir();
71
- const devVarsPath = new URL(".dev.vars", config.root);
72
- const devVarsCodegenPath = new URL(".dev.vars", codegenDir);
73
- if (existsSync(devVarsPath)) {
74
- copyFileSync(devVarsPath, devVarsCodegenPath);
75
- }
76
50
  }
77
51
  updateConfig({
78
52
  build: {
79
- client: new URL(`.${wrapWithSlashes(config.base)}`, config.outDir),
53
+ client: new URL(`./client/`, config.outDir),
80
54
  server: new URL("./_worker.js/", config.outDir),
81
55
  serverEntry: "index.js",
82
56
  redirects: false
@@ -91,11 +65,13 @@ function createIntegration(args) {
91
65
  {
92
66
  name: "@astrojs/cloudflare:cf-imports",
93
67
  enforce: "pre",
94
- resolveId(source) {
95
- if (source.startsWith("cloudflare:")) {
96
- return { id: source, external: true };
68
+ resolveId: {
69
+ filter: {
70
+ id: /^cloudflare:/
71
+ },
72
+ handler(id) {
73
+ return { id, external: true };
97
74
  }
98
- return null;
99
75
  }
100
76
  },
101
77
  {
@@ -119,15 +95,25 @@ function createIntegration(args) {
119
95
  "astro > @oslojs/encoding",
120
96
  "astro > es-module-lexer",
121
97
  "astro > unstorage",
122
- "astro > neotraverse/modern"
98
+ "astro > neotraverse/modern",
99
+ "astro > piccolore",
100
+ "astro/app",
101
+ "astro/compiler-runtime"
123
102
  ],
124
103
  exclude: [
125
104
  "unstorage/drivers/cloudflare-kv-binding",
126
- "astro:toolbar:internal",
127
- "virtual:astro:middleware"
105
+ "astro:*",
106
+ "virtual:astro:*",
107
+ "virtual:astro-cloudflare:*"
128
108
  ]
129
109
  }
130
110
  };
111
+ } else if (environmentName === "client") {
112
+ return {
113
+ optimizeDeps: {
114
+ include: ["astro/runtime/client/dev-toolbar/entrypoint.js"]
115
+ }
116
+ };
131
117
  }
132
118
  }
133
119
  },
@@ -232,7 +218,7 @@ function createIntegration(args) {
232
218
  "astro:build:done": async ({ pages, dir, logger, assets }) => {
233
219
  let redirectsExists = false;
234
220
  try {
235
- const redirectsStat = await stat(new URL("./_redirects", _config.outDir));
221
+ const redirectsStat = await stat(new URL("./_redirects", _config.build.client));
236
222
  if (redirectsStat.isFile()) {
237
223
  redirectsExists = true;
238
224
  }
@@ -242,7 +228,7 @@ function createIntegration(args) {
242
228
  const redirects = [];
243
229
  if (redirectsExists) {
244
230
  const rl = createInterface({
245
- input: createReadStream(new URL("./_redirects", _config.outDir)),
231
+ input: createReadStream(new URL("./_redirects", _config.build.client)),
246
232
  crlfDelay: Number.POSITIVE_INFINITY
247
233
  });
248
234
  for await (const line of rl) {
@@ -258,7 +244,7 @@ function createIntegration(args) {
258
244
  }
259
245
  let routesExists = false;
260
246
  try {
261
- const routesStat = await stat(new URL("./_routes.json", _config.outDir));
247
+ const routesStat = await stat(new URL("./_routes.json", _config.build.client));
262
248
  if (routesStat.isFile()) {
263
249
  routesExists = true;
264
250
  }
@@ -290,7 +276,7 @@ function createIntegration(args) {
290
276
  if (!trueRedirects.empty()) {
291
277
  try {
292
278
  await appendFile(
293
- new URL("./_redirects", _config.outDir),
279
+ new URL("./_redirects", _config.build.client),
294
280
  printAsRedirects(trueRedirects)
295
281
  );
296
282
  } catch (_error) {
@@ -28,42 +28,45 @@ function cloudflareModuleLoader(enabled) {
28
28
  }
29
29
  };
30
30
  },
31
- async load(id, _) {
32
- const maybeExtension = extensions.find((x) => id.endsWith(x));
33
- const moduleType = maybeExtension && adaptersByExtension[maybeExtension] || void 0;
34
- if (!moduleType || !maybeExtension) {
35
- return;
36
- }
37
- if (!enabled) {
38
- throw new Error(
39
- `Cloudflare module loading is experimental. The ${maybeExtension} module cannot be loaded unless you add \`cloudflareModules: true\` to your astro config.`
40
- );
41
- }
42
- const moduleLoader = renderers[moduleType];
43
- const filePath = id.replace(/\?\w+$/, "");
44
- const extension = maybeExtension.replace(/\?\w+$/, "");
45
- const data = await fs.readFile(filePath);
46
- const base64 = data.toString("base64");
47
- const inlineModule = moduleLoader(data);
48
- if (isDev) {
49
- return inlineModule;
31
+ load: {
32
+ filter: {
33
+ // Escape the dot in the regex
34
+ id: new RegExp(`.(${extensions.map((ext) => ext.slice(1)).join("|")})$`)
35
+ },
36
+ async handler(id, _) {
37
+ const maybeExtension = extensions.find((x) => id.endsWith(x));
38
+ const moduleType = adaptersByExtension[maybeExtension];
39
+ if (!enabled) {
40
+ throw new Error(
41
+ `Cloudflare module loading is experimental. The ${maybeExtension} module cannot be loaded unless you add \`cloudflareModules: true\` to your astro config.`
42
+ );
43
+ }
44
+ const moduleLoader = renderers[moduleType];
45
+ const filePath = id.replace(/\?\w+$/, "");
46
+ const extension = maybeExtension.replace(/\?\w+$/, "");
47
+ const data = await fs.readFile(filePath);
48
+ const base64 = data.toString("base64");
49
+ const inlineModule = moduleLoader(data);
50
+ if (isDev) {
51
+ return inlineModule;
52
+ }
53
+ const hash = hashString(base64);
54
+ const assetName = `${path.basename(filePath).split(".")[0]}.${hash}${extension}`;
55
+ this.emitFile({
56
+ type: "asset",
57
+ // emit the data explicitly as an asset with `fileName` rather than `name` so that
58
+ // vite doesn't give it a random hash-id in its name--We need to be able to easily rewrite from
59
+ // the loader and the actual asset later in the build for the worker
60
+ fileName: assetName,
61
+ source: data
62
+ });
63
+ const chunkId = this.emitFile({
64
+ type: "prebuilt-chunk",
65
+ fileName: assetName,
66
+ code: inlineModule
67
+ });
68
+ return `import module from "${MAGIC_STRING}${chunkId}${extension}";export default module;`;
50
69
  }
51
- const hash = hashString(base64);
52
- const assetName = `${path.basename(filePath).split(".")[0]}.${hash}${extension}`;
53
- this.emitFile({
54
- type: "asset",
55
- // emit the data explicitly as an asset with `fileName` rather than `name` so that
56
- // vite doesn't give it a random hash-id in its name--We need to be able to easily rewrite from
57
- // the loader and the actual asset later in the build for the worker
58
- fileName: assetName,
59
- source: data
60
- });
61
- const chunkId = this.emitFile({
62
- type: "prebuilt-chunk",
63
- fileName: assetName,
64
- code: inlineModule
65
- });
66
- return `import module from "${MAGIC_STRING}${chunkId}${extension}";export default module;`;
67
70
  },
68
71
  // output original wasm file relative to the chunk now that chunking has been achieved
69
72
  renderChunk(code, chunk, _) {
@@ -3,13 +3,19 @@ const RESOLVED_VIRTUAL_CONFIG_ID = "\0" + VIRTUAL_CONFIG_ID;
3
3
  function createConfigPlugin(config) {
4
4
  return {
5
5
  name: "vite:astro-cloudflare-config",
6
- resolveId(id) {
7
- if (id === VIRTUAL_CONFIG_ID) {
6
+ resolveId: {
7
+ filter: {
8
+ id: new RegExp(`^${VIRTUAL_CONFIG_ID}$`)
9
+ },
10
+ handler() {
8
11
  return RESOLVED_VIRTUAL_CONFIG_ID;
9
12
  }
10
13
  },
11
- load(id) {
12
- if (id === RESOLVED_VIRTUAL_CONFIG_ID) {
14
+ load: {
15
+ filter: {
16
+ id: new RegExp(`^${RESOLVED_VIRTUAL_CONFIG_ID}$`)
17
+ },
18
+ handler() {
13
19
  return `export const sessionKVBindingName = ${JSON.stringify(config.sessionKVBindingName)};`;
14
20
  }
15
21
  }
package/dist/wrangler.js CHANGED
@@ -7,6 +7,7 @@ function defaultCloudflareConfig() {
7
7
  // TODO: better way to handle name, maybe package.json#name ?
8
8
  name: "test-application",
9
9
  compatibility_date: "2025-05-21",
10
+ compatibility_flags: ["global_fetch_strictly_public"],
10
11
  main: "@astrojs/cloudflare/entrypoints/server",
11
12
  assets: {
12
13
  directory: "./dist",
@@ -17,8 +18,8 @@ function defaultCloudflareConfig() {
17
18
  },
18
19
  kv_namespaces: [
19
20
  {
20
- binding: "SESSION",
21
- id: "SESSION"
21
+ binding: "SESSION"
22
+ // KV with no binding gets automatically created
22
23
  }
23
24
  ]
24
25
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@astrojs/cloudflare",
3
3
  "description": "Deploy your site to Cloudflare Workers/Pages",
4
- "version": "13.0.0-alpha.1",
4
+ "version": "13.0.0-alpha.3",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",
7
7
  "author": "withastro",
@@ -51,7 +51,7 @@
51
51
  "cheerio": "1.1.2",
52
52
  "devalue": "^5.5.0",
53
53
  "rollup": "^4.53.3",
54
- "astro": "6.0.0-alpha.1",
54
+ "astro": "6.0.0-alpha.3",
55
55
  "astro-scripts": "0.0.14"
56
56
  },
57
57
  "publishConfig": {