Skip to content

Commit

Permalink
feat(cloudflare): add support for r2 bindings
Browse files Browse the repository at this point in the history
This update provides users the ability to leverage Cloudflare's R2 storage within the system.
  • Loading branch information
alexanderniebuhr committed Sep 28, 2023
1 parent 5c21695 commit 56067c5
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/khaki-toes-exercise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@astrojs/cloudflare': minor
---

Introduce support for local R2 bindings. Enhance development experience by allowing direct integration with `astro dev`.
1 change: 1 addition & 0 deletions packages/integrations/cloudflare/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ Gives you access to [environment variables](https://developers.cloudflare.com/pa
Currently supported bindings:

- [Cloudflare D1](https://developers.cloudflare.com/d1/)
- [Cloudflare R2](https://developers.cloudflare.com/r2/)

You can access the runtime from Astro components through `Astro.locals` inside any .astro` file.

Expand Down
10 changes: 9 additions & 1 deletion packages/integrations/cloudflare/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import glob from 'tiny-glob';
import { getAdapter } from './getAdapter.js';
import { deduplicatePatterns } from './utils/deduplicatePatterns.js';
import { getCFObject } from './utils/getCFObject.js';
import { getD1Bindings, getEnvVars } from './utils/parser.js';
import { getD1Bindings, getEnvVars, getR2Bindings } from './utils/parser.js';
import { prependForwardSlash } from './utils/prependForwardSlash.js';
import { rewriteWasmImportPath } from './utils/rewriteWasmImportPath.js';
import { wasmModuleLoader } from './utils/wasm-module-loader.js';
Expand Down Expand Up @@ -125,6 +125,8 @@ export default function createIntegration(args?: Options): AstroIntegration {
const cf = await getCFObject(runtimeMode);
const vars = await getEnvVars();
const D1Bindings = await getD1Bindings();
const R2Bindings = await getR2Bindings();

let bindingsEnv = new Object({});

// fix for the error "kj/filesystem-disk-unix.c++:1709: warning: PWD environment variable doesn't match current directory."
Expand All @@ -139,13 +141,19 @@ export default function createIntegration(args?: Options): AstroIntegration {
cachePersist: true,
d1Databases: D1Bindings,
d1Persist: true,
r2Buckets: R2Bindings,
r2Persist: true,
});
await _mf.ready;

for (const D1Binding of D1Bindings) {
const db = await _mf.getD1Database(D1Binding);
Reflect.set(bindingsEnv, D1Binding, db);
}
for (const R2Binding of R2Bindings) {
const bucket = await _mf.getR2Bucket(R2Binding);
Reflect.set(bindingsEnv, R2Binding, bucket);
}

process.env.PWD = originalPWD;
const clientLocalsSymbol = Symbol.for('astro.locals');
Expand Down
10 changes: 10 additions & 0 deletions packages/integrations/cloudflare/src/utils/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,13 @@ export async function getD1Bindings() {
);
return bindings;
}

export async function getR2Bindings() {
const { rawConfig } = parseConfig();
if (!rawConfig) return [];
if (!rawConfig?.r2_buckets) return [];
const bindings = (rawConfig?.r2_buckets as []).map(
(binding: { binding: string }) => binding.binding
);
return bindings;
}
12 changes: 12 additions & 0 deletions packages/integrations/cloudflare/test/cf.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,16 @@ describe('Astro Cloudflare Runtime', () => {
expect($('#hasPRODDB').text()).to.equal('true');
expect($('#hasACCESS').text()).to.equal('true');
});

it('adds R2 mocking', async () => {
expect(await fixture.pathExists('../.mf/r2')).to.be.true;

let res = await fixture.fetch('/r2');
expect(res.status).to.equal(200);
let html = await res.text();
let $ = cheerio.load(html);
expect($('#hasBUCKET').text()).to.equal('true');
expect($('#hasPRODBUCKET').text()).to.equal('true');
expect($('#hasACCESS').text()).to.equal('true');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
const runtime = Astro.locals.runtime;
const bucket = runtime.env?.R2;
await bucket.put("test", "true");
const result = await (await bucket.get("test")).text()
---

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>R2</title>
</head>
<body>
<pre id="hasBUCKET">{!!runtime.env?.R2}</pre>
<pre id="hasPRODBUCKET">{!!runtime.env?.R2_PROD}</pre>
<pre id="hasACCESS">{!!result}</pre>
</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,11 @@ binding = "D1_PROD" # Should match preview_database_id
database_name = "<DATABASE_NAME>"
database_id = "<unique-ID-for-your-database>"
preview_database_id = "D1_PROD" # Required for Pages local development

[[r2_buckets]]
binding = 'R2' # <~ valid JavaScript variable name
bucket_name = '<YOUR_BUCKET_NAME>'

[[r2_buckets]]
binding = 'R2_PROD' # <~ valid JavaScript variable name
bucket_name = '<YOUR_BUCKET_NAME>'

0 comments on commit 56067c5

Please sign in to comment.