devflare 1.0.0-next.1 → 1.0.0-next.11
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/LLM.md +1424 -610
- package/R2.md +200 -0
- package/README.md +302 -505
- package/bin/devflare.js +8 -8
- package/dist/{account-rvrj687w.js → account-8psavtg6.js} +27 -4
- package/dist/bridge/miniflare.d.ts +6 -0
- package/dist/bridge/miniflare.d.ts.map +1 -1
- package/dist/bridge/proxy.d.ts +5 -6
- package/dist/bridge/proxy.d.ts.map +1 -1
- package/dist/bridge/server.d.ts.map +1 -1
- package/dist/browser.d.ts +50 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/{build-mnf6v8gd.js → build-ezksv2dd.js} +26 -7
- package/dist/bundler/do-bundler.d.ts +7 -0
- package/dist/bundler/do-bundler.d.ts.map +1 -1
- package/dist/cli/commands/account.d.ts.map +1 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/deploy.d.ts.map +1 -1
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/types.d.ts.map +1 -1
- package/dist/cli/config-path.d.ts +5 -0
- package/dist/cli/config-path.d.ts.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/package-metadata.d.ts +16 -0
- package/dist/cli/package-metadata.d.ts.map +1 -0
- package/dist/config/compiler.d.ts +7 -0
- package/dist/config/compiler.d.ts.map +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/schema.d.ts +2594 -1234
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/{deploy-nhceck39.js → deploy-jdpy21t6.js} +33 -15
- package/dist/{dev-qnxet3j9.js → dev-9mq7zhww.js} +900 -234
- package/dist/dev-server/miniflare-log.d.ts +12 -0
- package/dist/dev-server/miniflare-log.d.ts.map +1 -0
- package/dist/dev-server/runtime-stdio.d.ts +8 -0
- package/dist/dev-server/runtime-stdio.d.ts.map +1 -0
- package/dist/dev-server/server.d.ts +2 -0
- package/dist/dev-server/server.d.ts.map +1 -1
- package/dist/dev-server/vite-utils.d.ts +37 -0
- package/dist/dev-server/vite-utils.d.ts.map +1 -0
- package/dist/{doctor-e8fy6fj5.js → doctor-z4ffybce.js} +73 -50
- package/dist/{durable-object-t4kbb0yt.js → durable-object-yt8v1dyn.js} +1 -1
- package/dist/index-1p814k7s.js +227 -0
- package/dist/{index-tk6ej9dj.js → index-2q3pmzrx.js} +12 -16
- package/dist/{index-67qcae0f.js → index-51s1hkw4.js} +16 -1
- package/dist/{index-ep3445yc.js → index-53xcakh8.js} +414 -171
- package/dist/{index-pf5s73n9.js → index-59df49vn.js} +11 -281
- package/dist/index-5yxg30va.js +304 -0
- package/dist/index-62b3gt2g.js +12 -0
- package/dist/index-6h8xbs75.js +44 -0
- package/dist/index-8gtqgb3q.js +529 -0
- package/dist/{index-gz1gndna.js → index-9wt9x09k.js} +42 -62
- package/dist/index-dr6sbp8d.js +39 -0
- package/dist/index-fef08w43.js +231 -0
- package/dist/index-k7r18na8.js +0 -0
- package/dist/{index-m2q41jwa.js → index-n932ytmq.js} +9 -1
- package/dist/{index-07q6yxyc.js → index-v8vvsn9x.js} +1 -0
- package/dist/index-vky23txa.js +70 -0
- package/dist/{index-z14anrqp.js → index-wfbfz02q.js} +14 -15
- package/dist/index-ws68xvq2.js +311 -0
- package/dist/{index-hcex3rgh.js → index-wyf3s77s.js} +85 -8
- package/dist/index-xqfbd9fx.js +195 -0
- package/dist/index-xxwbb2nt.js +322 -0
- package/dist/index-y1d8za14.js +196 -0
- package/dist/{init-f9mgmew3.js → init-na2atvz2.js} +42 -55
- package/dist/router/types.d.ts +24 -0
- package/dist/router/types.d.ts.map +1 -0
- package/dist/runtime/context.d.ts +249 -8
- package/dist/runtime/context.d.ts.map +1 -1
- package/dist/runtime/exports.d.ts +50 -55
- package/dist/runtime/exports.d.ts.map +1 -1
- package/dist/runtime/index.d.ts +8 -1
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/middleware.d.ts +77 -60
- package/dist/runtime/middleware.d.ts.map +1 -1
- package/dist/runtime/router.d.ts +7 -0
- package/dist/runtime/router.d.ts.map +1 -0
- package/dist/runtime/validation.d.ts +1 -1
- package/dist/runtime/validation.d.ts.map +1 -1
- package/dist/src/browser.js +150 -0
- package/dist/src/cli/index.js +10 -0
- package/dist/{cloudflare → src/cloudflare}/index.js +3 -3
- package/dist/{decorators → src/decorators}/index.js +2 -2
- package/dist/src/index.js +132 -0
- package/dist/src/runtime/index.js +111 -0
- package/dist/{sveltekit → src/sveltekit}/index.js +14 -6
- package/dist/{test → src/test}/index.js +22 -13
- package/dist/{vite → src/vite}/index.js +128 -59
- package/dist/sveltekit/platform.d.ts.map +1 -1
- package/dist/test/bridge-context.d.ts +5 -2
- package/dist/test/bridge-context.d.ts.map +1 -1
- package/dist/test/cf.d.ts +25 -11
- package/dist/test/cf.d.ts.map +1 -1
- package/dist/test/email.d.ts +16 -7
- package/dist/test/email.d.ts.map +1 -1
- package/dist/test/queue.d.ts.map +1 -1
- package/dist/test/resolve-service-bindings.d.ts.map +1 -1
- package/dist/test/scheduled.d.ts.map +1 -1
- package/dist/test/simple-context.d.ts +1 -1
- package/dist/test/simple-context.d.ts.map +1 -1
- package/dist/test/tail.d.ts +2 -1
- package/dist/test/tail.d.ts.map +1 -1
- package/dist/test/worker.d.ts +6 -0
- package/dist/test/worker.d.ts.map +1 -1
- package/dist/transform/durable-object.d.ts.map +1 -1
- package/dist/transform/worker-entrypoint.d.ts.map +1 -1
- package/dist/{types-5nyrz1sz.js → types-nq5acrwh.js} +30 -16
- package/dist/utils/entrypoint-discovery.d.ts +6 -3
- package/dist/utils/entrypoint-discovery.d.ts.map +1 -1
- package/dist/utils/send-email.d.ts +15 -0
- package/dist/utils/send-email.d.ts.map +1 -0
- package/dist/vite/plugin.d.ts.map +1 -1
- package/dist/worker-entry/composed-worker.d.ts +13 -0
- package/dist/worker-entry/composed-worker.d.ts.map +1 -0
- package/dist/worker-entry/routes.d.ts +22 -0
- package/dist/worker-entry/routes.d.ts.map +1 -0
- package/dist/{worker-entrypoint-m9th0rg0.js → worker-entrypoint-c259fmfs.js} +1 -1
- package/package.json +21 -19
- package/dist/index.js +0 -298
- package/dist/runtime/index.js +0 -111
package/R2.md
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# R2
|
|
2
|
+
|
|
3
|
+
A short guide for handling uploads and file delivery with Cloudflare R2.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Quick rules
|
|
8
|
+
|
|
9
|
+
- Use **presigned `PUT` URLs** for direct user uploads to R2
|
|
10
|
+
- Use a **public bucket on a custom domain** for truly public assets
|
|
11
|
+
- Use a **private bucket + Worker authorization** for authenticated/private assets
|
|
12
|
+
- Use **Cloudflare Access** for teammate/org-only buckets
|
|
13
|
+
- Use **WAF token auth / HMAC validation** or a **Worker** for expiring custom-domain media links
|
|
14
|
+
- Do **not** use `r2.dev` for production delivery
|
|
15
|
+
- If you protect a custom-domain bucket with Access or WAF, **disable `r2.dev`** or the bucket may still be reachable there
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Uploads
|
|
20
|
+
|
|
21
|
+
The usual safe upload flow is:
|
|
22
|
+
|
|
23
|
+
1. frontend asks your app for upload permission
|
|
24
|
+
2. your Worker/app authenticates the user and validates file type, size, and target key
|
|
25
|
+
3. your backend returns a short-lived **presigned `PUT` URL**
|
|
26
|
+
4. the browser uploads **directly to R2**
|
|
27
|
+
5. your app stores the **object key + metadata**, not the presigned URL
|
|
28
|
+
|
|
29
|
+
Good practice:
|
|
30
|
+
|
|
31
|
+
- generate keys server-side, for example `users/<userId>/<uuid>.jpg`
|
|
32
|
+
- restrict `Content-Type` when signing uploads
|
|
33
|
+
- keep upload URLs short-lived
|
|
34
|
+
- configure bucket **CORS** if the browser uploads directly
|
|
35
|
+
|
|
36
|
+
Cloudflare docs:
|
|
37
|
+
|
|
38
|
+
- [Presigned URLs](https://developers.cloudflare.com/r2/api/s3/presigned-urls/)
|
|
39
|
+
- [Configure CORS](https://developers.cloudflare.com/r2/buckets/cors/)
|
|
40
|
+
- [Storing user generated content](https://developers.cloudflare.com/reference-architecture/diagrams/storage/storing-user-generated-content/)
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Viewing / serving files
|
|
45
|
+
|
|
46
|
+
### Public files
|
|
47
|
+
|
|
48
|
+
For public images, media, and assets:
|
|
49
|
+
|
|
50
|
+
- use a **public bucket**
|
|
51
|
+
- attach a **custom domain**
|
|
52
|
+
- serve stable URLs from that domain
|
|
53
|
+
- let Cloudflare cache them
|
|
54
|
+
|
|
55
|
+
This is the best fit for avatars, product images, blog images, and other content that anyone may view.
|
|
56
|
+
|
|
57
|
+
Cloudflare docs:
|
|
58
|
+
|
|
59
|
+
- [Public buckets](https://developers.cloudflare.com/r2/buckets/public-buckets/)
|
|
60
|
+
|
|
61
|
+
### Private or authenticated files
|
|
62
|
+
|
|
63
|
+
For invoices, receipts, private user uploads, paid content, or tenant-scoped assets:
|
|
64
|
+
|
|
65
|
+
- keep the bucket **private**
|
|
66
|
+
- store only the object key in your database
|
|
67
|
+
- serve through a **Worker** that checks session/JWT/permissions before reading from R2
|
|
68
|
+
|
|
69
|
+
This is usually the best default when access depends on the current user.
|
|
70
|
+
|
|
71
|
+
Cloudflare docs:
|
|
72
|
+
|
|
73
|
+
- [Use R2 from Workers](https://developers.cloudflare.com/r2/api/workers/workers-api-usage/)
|
|
74
|
+
|
|
75
|
+
### Time-limited direct access
|
|
76
|
+
|
|
77
|
+
You can also mint a **presigned `GET` URL** for temporary direct viewing or download.
|
|
78
|
+
|
|
79
|
+
Important caveat:
|
|
80
|
+
|
|
81
|
+
- presigned URLs work on the **R2 S3 endpoint**
|
|
82
|
+
- they **do not work with custom domains**
|
|
83
|
+
- treat them as **bearer tokens**
|
|
84
|
+
|
|
85
|
+
So they are good for short-lived direct access, but not for polished custom-domain media delivery.
|
|
86
|
+
|
|
87
|
+
Cloudflare docs:
|
|
88
|
+
|
|
89
|
+
- [Presigned URLs](https://developers.cloudflare.com/r2/api/s3/presigned-urls/)
|
|
90
|
+
|
|
91
|
+
### Team-only / org-only files
|
|
92
|
+
|
|
93
|
+
If access should be limited to employees or teammates, protect the R2 custom domain with **Cloudflare Access**.
|
|
94
|
+
|
|
95
|
+
Cloudflare docs:
|
|
96
|
+
|
|
97
|
+
- [Protect an R2 Bucket with Cloudflare Access](https://developers.cloudflare.com/r2/tutorials/cloudflare-access/)
|
|
98
|
+
|
|
99
|
+
### Signed links on a custom domain
|
|
100
|
+
|
|
101
|
+
If you want expiring links on `https://cdn.example.com/...`, R2 presigned URLs are not the right tool.
|
|
102
|
+
|
|
103
|
+
Instead use:
|
|
104
|
+
|
|
105
|
+
- a **Worker** that signs and verifies access tokens, or
|
|
106
|
+
- **Cloudflare WAF token authentication / HMAC validation** on the custom domain
|
|
107
|
+
|
|
108
|
+
Cloudflare docs:
|
|
109
|
+
|
|
110
|
+
- [Configure token authentication](https://developers.cloudflare.com/waf/custom-rules/use-cases/configure-token-authentication/)
|
|
111
|
+
- [HMAC validation function](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/#hmac-validation)
|
|
112
|
+
- [Workers request signing example](https://developers.cloudflare.com/workers/examples/signing-requests/)
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Development vs production
|
|
117
|
+
|
|
118
|
+
### Development
|
|
119
|
+
|
|
120
|
+
By default, local Worker development uses **local simulated bindings**, including local R2-style storage.
|
|
121
|
+
|
|
122
|
+
Use this for normal development.
|
|
123
|
+
|
|
124
|
+
Devflare-specific local note:
|
|
125
|
+
|
|
126
|
+
- local R2 bindings are available to your Worker code, tests, and bridge helpers
|
|
127
|
+
- Devflare does **not** currently publish a stable browser-facing local bucket URL contract
|
|
128
|
+
- do **not** build frontend code around an assumed local bucket origin
|
|
129
|
+
- for browser-visible local flows, serve objects through your Worker or app routes instead
|
|
130
|
+
|
|
131
|
+
Practical local-serving example:
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
// src/routes/files/[...key].ts
|
|
135
|
+
import type { FetchEvent } from 'devflare/runtime'
|
|
136
|
+
|
|
137
|
+
export async function GET({ env, params }: FetchEvent<DevflareEnv>): Promise<Response> {
|
|
138
|
+
const object = await env.FILES.get(params.key)
|
|
139
|
+
if (!object) {
|
|
140
|
+
return new Response('Not Found', { status: 404 })
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return new Response(object.body, {
|
|
144
|
+
headers: {
|
|
145
|
+
'Content-Type': object.httpMetadata?.contentType ?? 'application/octet-stream',
|
|
146
|
+
'Cache-Control': 'private, max-age=0'
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
With that pattern, your browser talks to your app URL, not to an assumed local bucket URL. That keeps local behavior aligned with the Worker-auth or custom-domain patterns you are likely to use in production.
|
|
153
|
+
|
|
154
|
+
Only connect to real remote buckets when you intentionally need integration testing, and prefer **separate dev/staging buckets** instead of production buckets.
|
|
155
|
+
|
|
156
|
+
Important remote-dev reality:
|
|
157
|
+
|
|
158
|
+
- remote bindings touch **real data**
|
|
159
|
+
- remote bindings incur **real costs**
|
|
160
|
+
- avoid pointing local development at production uploads unless absolutely necessary
|
|
161
|
+
|
|
162
|
+
Cloudflare docs:
|
|
163
|
+
|
|
164
|
+
- [Workers development & testing](https://developers.cloudflare.com/workers/development-testing/)
|
|
165
|
+
- [Remote bindings](https://developers.cloudflare.com/workers/development-testing/#remote-bindings)
|
|
166
|
+
|
|
167
|
+
### Production
|
|
168
|
+
|
|
169
|
+
For production:
|
|
170
|
+
|
|
171
|
+
- use a **custom domain**, not `r2.dev`
|
|
172
|
+
- choose public vs private intentionally per bucket or per content class
|
|
173
|
+
- keep sensitive content private behind a Worker, Access, or token validation
|
|
174
|
+
- configure **CORS** intentionally for browser upload/download flows
|
|
175
|
+
- use separate **dev**, **staging**, and **prod** buckets
|
|
176
|
+
|
|
177
|
+
Optional performance feature:
|
|
178
|
+
|
|
179
|
+
- if users upload from many regions, consider **Local Uploads** for better upload performance
|
|
180
|
+
|
|
181
|
+
Cloudflare docs:
|
|
182
|
+
|
|
183
|
+
- [Public buckets](https://developers.cloudflare.com/r2/buckets/public-buckets/)
|
|
184
|
+
- [Local uploads](https://developers.cloudflare.com/r2/buckets/local-uploads/)
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Recommended defaults
|
|
189
|
+
|
|
190
|
+
If you need a sane default architecture:
|
|
191
|
+
|
|
192
|
+
- **public assets** → public bucket + custom domain
|
|
193
|
+
- **user uploads** → presigned `PUT` upload + object key stored in DB
|
|
194
|
+
- **private assets** → private bucket + Worker-gated reads
|
|
195
|
+
- **internal assets** → custom domain + Cloudflare Access
|
|
196
|
+
- **custom-domain expiring links** → Worker token auth or WAF HMAC validation
|
|
197
|
+
|
|
198
|
+
If you only remember one rule, remember this:
|
|
199
|
+
|
|
200
|
+
> Use **presigned URLs** for short-lived direct R2 access, but use a **Worker/custom domain auth layer** for polished private media delivery.
|