`void/kv` and `void/storage` for `target: 'node'`, backed by Redis and S3
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 35/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- postgresql, redis, typescript
Hướng nghiên cứu
Start with packages/void/src/plugin-node-target.ts and the Node route setup in packages/void/src/router/compile.ts, then read the existing remote KV and storage adapters. The proposal leaves core versus plugin placement and backend configuration format open, so first get maintainer direction before implementation. Done means configured Redis and S3-compatible bindings work through the existing APIs on Node, with a Compose example and guide updates.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Parts of the text were generated using an LLM, but the core purpose and intent of the proposal were written by a human.
Summary
I'd like to use void/kv and void/storage with target: 'node' (and bun / deno), backed by Redis and S3-compatible storage, so the same app code runs on Cloudflare and on our own servers.
This would extend what Void already does for databases. void/db isn't limited to D1: with database: 'pg' or 'mysql' and a DATABASE_URL, the same API works with your own PostgreSQL or MySQL server (Choosing a Dialect). This proposal applies the same idea to KV and Storage: the API stays the same, and the app brings its own Redis or S3-compatible service.
Since Void is built for Cloudflare Workers, I'd like to check the direction before writing code: would you accept this in Void core, or should it live in an external plugin or a fork?
"Self-hosting" here means running the app on a Node.js server or container, not the self-hosted Void Platform.
Motivation
I believe solid self-hosting is important for Void to become a first-class choice for full-stack apps. Many teams can't run everything on a single provider: they have existing infrastructure, data residency or compliance requirements, or want to avoid lock-in. Next.js, for comparison, supports all of its features on a Node.js server or in a Docker container (Deploying).
What sets Void apart from other frameworks is its built-in, typed server APIs: void/db, void/kv, void/storage, void/auth and void/env, with types carried from database queries to the UI. With target: 'node', none of these are available today. What remains is mostly routing and pages, which many frameworks already provide, so a self-hosted Void app loses most of its advantage as a full-stack framework.
void/ai and void/sandbox probably don't need self-hosted support. They wrap Cloudflare services (Workers AI and Containers), and a self-hosted app can call a model provider or run containers directly.
This issue starts with KV and Storage. If the direction works, void/db, void/auth and void/env could follow with the same approach.
Current behavior
void/kvandvoid/storageare inCF_ONLY_IMPORTS, so importing them withtarget: 'node'fails at build time (plugin-node-target.ts).- The docs suggest using an external provider through standard Node.js libraries instead (No Cloudflare bindings).
So an app that uses kv or storage can't move to target: 'node' by changing config. Every call site has to be rewritten against another client, and an app that also deploys to Cloudflare ends up with two code paths.
Proposal
1. Adapters behind the existing APIs
void/storage(R2Bucket) → S3 API: AWS S3, R2's S3 API, Garage, SeaweedFS, …void/kv(theKVNamespacemethods thekvclient calls) → Redis protocol: Redis, Valkey, …
The generated Node entry creates them at startup and provides them as KV / STORAGE. kv, storage, createKV() and createStorage() keep their types, so app code stays the same on both targets.
remote: true already works this way: ProxyKVNamespace / ProxyR2Bucket implement these interfaces over another transport and throw a clear error for unsupported features (runtime/remote). Full parity with Cloudflare isn't a goal: differences such as list() ordering, consistency and size limits would be documented. Client libraries would be optional dependencies, so the Cloudflare target and its install size stay unchanged.
2. Config
This mirrors database: 'pg' + DATABASE_URL (config):
// void.config.ts
export default defineConfig({
target: 'node',
kv: 'redis', // KV_URL=redis://valkey:6379
storage: 's3', // STORAGE_URL=s3://<key>:<secret>@object-store:8333/uploads (format TBD)
});
The server reads these URLs from the environment when it starts, not at build time. That keeps credentials out of dist/ and lets the same image run in several environments.
3. Docker Compose example
A playground app (e.g. playground/node-self-hosted/) with a compose.yaml that runs the app, Valkey and an S3-compatible server such as SeaweedFS or Garage, plus a short section in the Node.js, Bun, and Deno guide. The same setup could back integration tests for the adapters.
Cloudflare-target behavior and defaults don't change.
Where it would touch
plugin-node-target.ts: allowvoid/kv/void/storagewhen a backend is configured.router/compile.ts: the Node route table uses a no-opwithRuntimeEnv(L159-L163), andcompileNodeAppadds onlyASSETSto the env it passes to the routes (L1349). Both would need to provideKV/STORAGE.- New adapter modules, config schema and types, and docs.
Question: where should this live?
-
Void core. The adapters ship with Void, either in
voidwith optional peer dependencies or as@void/*packages in this repo. They're configured invoid.config.ts, documented in the guides and tested in CI here. -
External plugin. The adapters live in a separate package, and core gets only the small extension points it needs. I'd send PRs for:
- a supported way to give the generated Node, Bun and Deno entries bindings created at startup, for example a module path in
void.config.tsthat exports{ KV, STORAGE }; - letting the guard allow
void/kv/void/storagewhen those bindings are provided.
There's a similar precedent in
void/database-provider, which lets third-party packages add providers tovoid db connect. - a supported way to give the generated Node, Bun and Deno entries bindings created at startup, for example a module path in
-
Fork. Running these APIs outside Cloudflare is out of scope for Void, and this should be maintained separately.
If 1 or 2 works for you, I'd be happy to implement it, starting with Storage (S3), and I'll follow your preference on details such as config shape and which methods to support.
- Ngôn ngữ chính
- TypeScript
- Star
- 402
- Fork
- 32
- Merge trung bình
- 12 giờ 28 phút
- Pull request đã merge (30 ngày)
- 77
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của voidzero-dev/void
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
voidzero-dev/void#478 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
voidzero-dev/void#463 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Deploy after a secret change fails for Workers over ~750 KB: source read-back capped at 1 MiBĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
voidzero-dev/void#459 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 1/5 1-3 giờ Mức phù hợp với người mới 78/100
voidzero-dev/void#428 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 68/100
voidzero-dev/void#480 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của voidzero-dev/void
Issue tương tự
-
freshness freshness:observed-only
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
thoroc/context-radar#280 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
-
documentation story
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Billing: computeBundleEconomicsFrom treats a NULL component cost as 0, inflating bundle marginĐang mởbug category:billing priority:p3 track:fast
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
LanternOps/breeze#9223 ·
Maintainer thường phản hồi trong vòng 1 ngày