Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Commit 7f35bdd

Browse files
authored
r2 implementation (#289)
* r2 first up * update undici to current * fix the way I handle head * list working; adjustments for cleaner code * fixed ava * bucket tests complete * fixes wrong implementations; adds r2 to miniflare api * see if windows is mad at larger than size * see if windows is mad at larger than size * improve code clarity; improve comments; cleaning * add startAfter support; setup for range return * range in R2Object; test cases for range & startAfter * setup delimitedPrefixes test * improve get->range validation * first changeset * improve storage system * improve readability * fix durable-objects shadow-storage & recorder-storage * exportable _valueToArray; internal list function has object for params * storage finished; update R2 tests * get redis tests working * add proper suffix larger than size support * simplify range; better stream handling in R2ObjectBody * remove dump * throw for durable object shadow storage -> getRange & head * fix recorder storage * update delimitedPrefixes * drop dead code * simplify limit * fix ava
1 parent 76bc1a6 commit 7f35bdd

File tree

27 files changed

+4415
-50
lines changed

27 files changed

+4415
-50
lines changed

package-lock.json

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/durable-objects/src/shadow.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ export class ShadowStorage extends Storage {
4444
return count;
4545
}
4646

47+
async head(_key: string): Promise<undefined> {
48+
throw new Error('"head" is not supported in Durable Object shadow storage');
49+
}
50+
4751
async get(key: string): Promise<StoredValue | undefined> {
4852
return (await this.getMany([key]))[0];
4953
}
@@ -82,6 +86,12 @@ export class ShadowStorage extends Storage {
8286
return result;
8387
}
8488

89+
async getRange(_key: string): Promise<undefined> {
90+
throw new Error(
91+
'"getRange" is not supported in Durable Object shadow storage'
92+
);
93+
}
94+
8595
put(key: string, value: StoredValue): void {
8696
// Store fresh copy so further mutations from caller aren't stored
8797
this.copies.set(key, { value: value.value.slice() });

packages/miniflare/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ workers in a sandbox implementing Workers' runtime APIs.
2222
- 🔑 Variables and Secrets with `.env` Files
2323
- 📚 Modules Support
2424
- 📦 KV (with optional persistence)
25+
- 🪣 R2 (with optional persistence)
2526
- ✨ Cache (with optional persistence)
2627
- 📌 Durable Objects (with optional persistence)
2728
- 🌐 Workers Sites
@@ -128,6 +129,10 @@ KV Options:
128129
-k, --kv KV namespace to bind [array]
129130
--kv-persist Persist KV data (to optional path) [boolean/string]
130131
132+
R2 Options:
133+
-r, --r2 R2 bucket to bind [array]
134+
--r2-persist Persist R2 data (to optional path) [boolean/string]
135+
131136
Durable Objects Options:
132137
-o, --do Durable Object to bind [array:NAME=CLASS[@MOUNT]]
133138
--do-persist Persist Durable Object data (to optional path) [boolean/string]

packages/miniflare/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"@miniflare/html-rewriter": "2.5.0",
5454
"@miniflare/http-server": "2.5.0",
5555
"@miniflare/kv": "2.5.0",
56+
"@miniflare/r2": "2.5.0",
5657
"@miniflare/runner-vm": "2.5.0",
5758
"@miniflare/scheduler": "2.5.0",
5859
"@miniflare/shared": "2.5.0",

packages/miniflare/src/api.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
startServer,
2323
} from "@miniflare/http-server";
2424
import { KVNamespace, KVPlugin } from "@miniflare/kv";
25+
import { R2Bucket, R2Plugin } from "@miniflare/r2";
2526
import { VMScriptRunner } from "@miniflare/runner-vm";
2627
import {
2728
CronScheduler,
@@ -46,6 +47,7 @@ export const PLUGINS = {
4647

4748
// Storage
4849
KVPlugin,
50+
R2Plugin,
4951
DurableObjectsPlugin,
5052
CachePlugin,
5153
SitesPlugin,
@@ -104,6 +106,12 @@ export class Miniflare extends MiniflareCore<Plugins> {
104106
return plugin.getNamespace(storage, namespace);
105107
}
106108

109+
async getR2Bucket(bucket: string): Promise<R2Bucket> {
110+
const plugin = (await this.getPlugins()).R2Plugin;
111+
const storage = this.getPluginStorage("R2Plugin");
112+
return plugin.getBucket(storage, bucket);
113+
}
114+
107115
async getCaches(): Promise<CacheStorage> {
108116
const plugin = (await this.getPlugins()).CachePlugin;
109117
return plugin.getCaches();

packages/r2/README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# `@miniflare/r2`
2+
3+
Workers R2 module for [Miniflare](https://github.com/cloudflare/miniflare): a
4+
fun, full-featured, fully-local simulator for Cloudflare Workers. See
5+
[🪣 R2](https://miniflare.dev/storage/r2) for more details.
6+
7+
## Example
8+
9+
```js
10+
import { R2Bucket } from "@miniflare/r2";
11+
import { MemoryStorage } from "@miniflare/storage-memory";
12+
13+
const r2 = new R2Bucket(new MemoryStorage());
14+
await r2.put("key", "value");
15+
const value = await r2.get("key");
16+
console.log(await value.text()); // "value"
17+
```

packages/r2/package.json

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"name": "@miniflare/r2",
3+
"version": "2.5.0",
4+
"description": "Workers R2 module for Miniflare: a fun, full-featured, fully-local simulator for Cloudflare Workers",
5+
"keywords": [
6+
"cloudflare",
7+
"workers",
8+
"worker",
9+
"local",
10+
"cloudworker"
11+
],
12+
"author": "CraigglesO <[email protected]>",
13+
"license": "MIT",
14+
"main": "./dist/src/index.js",
15+
"types": "./dist/src/index.d.ts",
16+
"files": [
17+
"dist/src"
18+
],
19+
"engines": {
20+
"node": ">=16.7"
21+
},
22+
"publishConfig": {
23+
"access": "public"
24+
},
25+
"repository": {
26+
"type": "git",
27+
"url": "git+https://github.com/cloudflare/miniflare.git",
28+
"directory": "packages/r2"
29+
},
30+
"bugs": {
31+
"url": "https://github.com/cloudflare/miniflare/issues"
32+
},
33+
"homepage": "https://github.com/cloudflare/miniflare/tree/master/packages/r2#readme",
34+
"volta": {
35+
"extends": "../../package.json"
36+
},
37+
"dependencies": {
38+
"@miniflare/shared": "2.5.0",
39+
"undici": "5.5.1"
40+
},
41+
"devDependencies": {
42+
"@miniflare/shared-test": "2.5.0"
43+
}
44+
}

0 commit comments

Comments
 (0)