@astrojs/cloudflare 7.3.1 → 7.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -169,7 +169,7 @@ default: `false`
169
169
 
170
170
  Whether or not to import `.wasm` files [directly as ES modules](https://github.com/WebAssembly/esm-integration/tree/main/proposals/esm-integration) using the `.wasm?module` import syntax.
171
171
 
172
- Add `wasmModuleImports: true` to `astro.config.mjs` to enable this functionality in both the Cloudflare build and the Astro dev server. [Read more](#use-wasm-modules)
172
+ Add `wasmModuleImports: true` to `astro.config.mjs` to enable this functionality in both the Cloudflare build and the Astro dev server. Read more about [using Wasm modules](#use-wasm-modules)
173
173
 
174
174
  ```diff lang="js"
175
175
  // astro.config.mjs
@@ -186,16 +186,15 @@ export default defineConfig({
186
186
 
187
187
  ### `runtime`
188
188
 
189
- `runtime: "off" | "local" | "remote"`
189
+ `runtime: "off" | "local"`
190
190
 
191
191
  default `"off"`
192
192
 
193
193
  Determines whether and how the Cloudflare Runtime is added to `astro dev`.
194
194
 
195
- The Cloudflare Runtime includes [Cloudflare bindings](https://developers.cloudflare.com/pages/platform/functions/bindings), [environment variables](https://developers.cloudflare.com/pages/platform/functions/bindings/#environment-variables), and the [cf object](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties). Read more about [accessing the Cloudflare Runtime](#access-to-the-cloudflare-runtime).
195
+ The Cloudflare Runtime includes [Cloudflare bindings](https://developers.cloudflare.com/pages/platform/functions/bindings), [environment variables](https://developers.cloudflare.com/pages/platform/functions/bindings/#environment-variables), and the [cf object](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties). Read more about [accessing the Cloudflare Runtime](#cloudflare-runtime).
196
196
 
197
- - `local`: uses bindings mocking and locally static placeholdes
198
- - `remote`: uses remote bindings and a live fetched cf object
197
+ - `local`: uses bindings mocking and locally static placeholders
199
198
  - `off`: no access to the Cloudflare runtime using `astro dev`. You can alternatively use [Preview with Wrangler](#preview-with-wrangler)
200
199
 
201
200
  ```diff lang="js"
@@ -213,7 +212,14 @@ export default defineConfig({
213
212
 
214
213
  ## Cloudflare runtime
215
214
 
216
- Gives you access to [environment variables](https://developers.cloudflare.com/pages/platform/functions/bindings/#environment-variables).
215
+ Gives you access to [environment variables](https://developers.cloudflare.com/pages/platform/functions/bindings/#environment-variables), and [Cloudflare bindings](https://developers.cloudflare.com/pages/platform/functions/bindings).
216
+
217
+ Currently supported bindings:
218
+
219
+ - [Cloudflare D1](https://developers.cloudflare.com/d1/)
220
+ - [Cloudflare R2](https://developers.cloudflare.com/r2/)
221
+ - [Cloudflare Workers KV](https://developers.cloudflare.com/kv/)
222
+ - [Cloudflare Durable Objects](https://developers.cloudflare.com/durable-objects/)
217
223
 
218
224
  You can access the runtime from Astro components through `Astro.locals` inside any .astro` file.
219
225
 
package/dist/index.js CHANGED
@@ -1,9 +1,7 @@
1
1
  import { createRedirectsFromAstroRoutes } from "@astrojs/underscore-redirects";
2
- import { CacheStorage } from "@miniflare/cache";
3
- import { NoOpLog } from "@miniflare/shared";
4
- import { MemoryStorage } from "@miniflare/storage-memory";
5
2
  import { AstroError } from "astro/errors";
6
3
  import esbuild from "esbuild";
4
+ import { Miniflare } from "miniflare";
7
5
  import * as fs from "node:fs";
8
6
  import * as os from "node:os";
9
7
  import { dirname, relative, sep } from "node:path";
@@ -12,23 +10,20 @@ import glob from "tiny-glob";
12
10
  import { getAdapter } from "./getAdapter.js";
13
11
  import { deduplicatePatterns } from "./utils/deduplicatePatterns.js";
14
12
  import { getCFObject } from "./utils/getCFObject.js";
15
- import { getEnvVars } from "./utils/parser.js";
13
+ import {
14
+ getD1Bindings,
15
+ getDOBindings,
16
+ getEnvVars,
17
+ getKVBindings,
18
+ getR2Bindings
19
+ } from "./utils/parser.js";
16
20
  import { prependForwardSlash } from "./utils/prependForwardSlash.js";
17
21
  import { rewriteWasmImportPath } from "./utils/rewriteWasmImportPath.js";
18
22
  import { wasmModuleLoader } from "./utils/wasm-module-loader.js";
19
- class StorageFactory {
20
- storages = /* @__PURE__ */ new Map();
21
- storage(namespace) {
22
- let storage = this.storages.get(namespace);
23
- if (storage)
24
- return storage;
25
- this.storages.set(namespace, storage = new MemoryStorage());
26
- return storage;
27
- }
28
- }
29
23
  function createIntegration(args) {
30
24
  let _config;
31
25
  let _buildConfig;
26
+ let _mf;
32
27
  let _entryPoints = /* @__PURE__ */ new Map();
33
28
  const SERVER_BUILD_FOLDER = "/$server_build/";
34
29
  const isModeDirectory = args?.mode === "directory";
@@ -77,6 +72,49 @@ function createIntegration(args) {
77
72
  try {
78
73
  const cf = await getCFObject(runtimeMode);
79
74
  const vars = await getEnvVars();
75
+ const D1Bindings = await getD1Bindings();
76
+ const R2Bindings = await getR2Bindings();
77
+ const KVBindings = await getKVBindings();
78
+ const DOBindings = await getDOBindings();
79
+ let bindingsEnv = new Object({});
80
+ const originalPWD = process.env.PWD;
81
+ process.env.PWD = process.cwd();
82
+ _mf = new Miniflare({
83
+ modules: true,
84
+ script: "",
85
+ cache: true,
86
+ cachePersist: true,
87
+ cacheWarnUsage: true,
88
+ d1Databases: D1Bindings,
89
+ d1Persist: true,
90
+ r2Buckets: R2Bindings,
91
+ r2Persist: true,
92
+ kvNamespaces: KVBindings,
93
+ kvPersist: true,
94
+ durableObjects: DOBindings,
95
+ durableObjectsPersist: true
96
+ });
97
+ await _mf.ready;
98
+ for (const D1Binding of D1Bindings) {
99
+ const db = await _mf.getD1Database(D1Binding);
100
+ Reflect.set(bindingsEnv, D1Binding, db);
101
+ }
102
+ for (const R2Binding of R2Bindings) {
103
+ const bucket = await _mf.getR2Bucket(R2Binding);
104
+ Reflect.set(bindingsEnv, R2Binding, bucket);
105
+ }
106
+ for (const KVBinding of KVBindings) {
107
+ const namespace = await _mf.getKVNamespace(KVBinding);
108
+ Reflect.set(bindingsEnv, KVBinding, namespace);
109
+ }
110
+ for (const key in DOBindings) {
111
+ if (Object.prototype.hasOwnProperty.call(DOBindings, key)) {
112
+ const DO = await _mf.getDurableObjectNamespace(key);
113
+ Reflect.set(bindingsEnv, key, DO);
114
+ }
115
+ }
116
+ const mfCache = await _mf.getCaches();
117
+ process.env.PWD = originalPWD;
80
118
  const clientLocalsSymbol = Symbol.for("astro.locals");
81
119
  Reflect.set(req, clientLocalsSymbol, {
82
120
  runtime: {
@@ -90,18 +128,14 @@ function createIntegration(args) {
90
128
  // will be fetched from git dynamically once we support mocking of bindings
91
129
  CF_PAGES_COMMIT_SHA: "TBA",
92
130
  CF_PAGES_URL: `http://${req.headers.host}`,
131
+ ...bindingsEnv,
93
132
  ...vars
94
133
  },
95
134
  cf,
96
135
  waitUntil: (_promise) => {
97
136
  return;
98
137
  },
99
- caches: new CacheStorage(
100
- { cache: true, cachePersist: false },
101
- new NoOpLog(),
102
- new StorageFactory(),
103
- {}
104
- )
138
+ caches: mfCache
105
139
  }
106
140
  });
107
141
  next();
@@ -111,6 +145,12 @@ function createIntegration(args) {
111
145
  });
112
146
  }
113
147
  },
148
+ "astro:server:done": async ({ logger }) => {
149
+ if (_mf) {
150
+ logger.info("Cleaning up the Miniflare instance, and shutting down the workerd server.");
151
+ await _mf.dispose();
152
+ }
153
+ },
114
154
  "astro:build:setup": ({ vite, target }) => {
115
155
  if (target === "server") {
116
156
  vite.resolve ||= {};
@@ -164,7 +204,7 @@ function createIntegration(args) {
164
204
  fileURLToPath(assetsUrl)
165
205
  );
166
206
  await esbuild.build({
167
- target: "es2020",
207
+ target: "es2022",
168
208
  platform: "browser",
169
209
  conditions: ["workerd", "worker", "browser"],
170
210
  external: [
@@ -228,7 +268,7 @@ function createIntegration(args) {
228
268
  const buildPath = fileURLToPath(entryUrl);
229
269
  const finalBuildUrl = pathToFileURL(buildPath.replace(/\.mjs$/, ".js"));
230
270
  await esbuild.build({
231
- target: "es2020",
271
+ target: "es2022",
232
272
  platform: "browser",
233
273
  conditions: ["workerd", "worker", "browser"],
234
274
  external: [
@@ -17,3 +17,11 @@ export interface DotEnv {
17
17
  */
18
18
  export declare function loadDotEnv(path: string): DotEnv | undefined;
19
19
  export declare function getEnvVars(): Promise<any>;
20
+ export declare function getD1Bindings(): Promise<string[]>;
21
+ export declare function getR2Bindings(): Promise<string[]>;
22
+ export declare function getKVBindings(): Promise<string[]>;
23
+ export declare function getDOBindings(): Record<string, {
24
+ scriptName?: string | undefined;
25
+ unsafeUniqueKey?: string | undefined;
26
+ className: string;
27
+ }>;
@@ -3,6 +3,7 @@ import dotenv from "dotenv";
3
3
  import { findUpSync } from "find-up";
4
4
  import * as fs from "node:fs";
5
5
  import { dirname, resolve } from "node:path";
6
+ let _wrangler;
6
7
  function findWranglerToml(referencePath = process.cwd(), preferJson = false) {
7
8
  if (preferJson) {
8
9
  return findUpSync(`wrangler.json`, { cwd: referencePath }) ?? findUpSync(`wrangler.toml`, { cwd: referencePath });
@@ -69,7 +70,9 @@ function getVarsForDev(config, configPath) {
69
70
  return config.vars;
70
71
  }
71
72
  }
72
- async function getEnvVars() {
73
+ function parseConfig() {
74
+ if (_wrangler)
75
+ return _wrangler;
73
76
  let rawConfig;
74
77
  const configPath = findWranglerToml(process.cwd(), false);
75
78
  if (!configPath) {
@@ -78,10 +81,64 @@ async function getEnvVars() {
78
81
  if (configPath?.endsWith("toml")) {
79
82
  rawConfig = parseTOML(fs.readFileSync(configPath).toString(), configPath);
80
83
  }
84
+ _wrangler = { rawConfig, configPath };
85
+ return { rawConfig, configPath };
86
+ }
87
+ async function getEnvVars() {
88
+ const { rawConfig, configPath } = parseConfig();
81
89
  const vars = getVarsForDev(rawConfig, configPath);
82
90
  return vars;
83
91
  }
92
+ async function getD1Bindings() {
93
+ const { rawConfig } = parseConfig();
94
+ if (!rawConfig)
95
+ return [];
96
+ if (!rawConfig?.d1_databases)
97
+ return [];
98
+ const bindings = (rawConfig?.d1_databases).map(
99
+ (binding) => binding.binding
100
+ );
101
+ return bindings;
102
+ }
103
+ async function getR2Bindings() {
104
+ const { rawConfig } = parseConfig();
105
+ if (!rawConfig)
106
+ return [];
107
+ if (!rawConfig?.r2_buckets)
108
+ return [];
109
+ const bindings = (rawConfig?.r2_buckets).map(
110
+ (binding) => binding.binding
111
+ );
112
+ return bindings;
113
+ }
114
+ async function getKVBindings() {
115
+ const { rawConfig } = parseConfig();
116
+ if (!rawConfig)
117
+ return [];
118
+ if (!rawConfig?.kv_namespaces)
119
+ return [];
120
+ const bindings = (rawConfig?.kv_namespaces).map(
121
+ (binding) => binding.binding
122
+ );
123
+ return bindings;
124
+ }
125
+ function getDOBindings() {
126
+ const { rawConfig } = parseConfig();
127
+ if (!rawConfig)
128
+ return {};
129
+ if (!rawConfig?.durable_objects)
130
+ return {};
131
+ const output = new Object({});
132
+ for (const binding of rawConfig?.durable_objects.bindings) {
133
+ Reflect.set(output, binding.name, { className: binding.class_name });
134
+ }
135
+ return output;
136
+ }
84
137
  export {
138
+ getD1Bindings,
139
+ getDOBindings,
85
140
  getEnvVars,
141
+ getKVBindings,
142
+ getR2Bindings,
86
143
  loadDotEnv
87
144
  };
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": "7.3.1",
4
+ "version": "7.5.0",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",
7
7
  "author": "withastro",
@@ -28,6 +28,7 @@
28
28
  ],
29
29
  "dependencies": {
30
30
  "@cloudflare/workers-types": "^4.20230821.0",
31
+ "miniflare": "^3.20230918.0",
31
32
  "@iarna/toml": "^2.2.5",
32
33
  "@miniflare/cache": "^2.14.1",
33
34
  "@miniflare/shared": "^2.14.1",
@@ -40,7 +41,7 @@
40
41
  "@astrojs/underscore-redirects": "0.3.0"
41
42
  },
42
43
  "peerDependencies": {
43
- "astro": "^3.2.0"
44
+ "astro": "^3.2.2"
44
45
  },
45
46
  "devDependencies": {
46
47
  "@types/iarna__toml": "^2.0.2",
@@ -48,7 +49,7 @@
48
49
  "cheerio": "1.0.0-rc.12",
49
50
  "mocha": "^10.2.0",
50
51
  "wrangler": "^3.5.1",
51
- "astro": "3.2.0",
52
+ "astro": "3.2.2",
52
53
  "astro-scripts": "0.0.14"
53
54
  },
54
55
  "scripts": {