orbit-rpc 0.2.0 → 1.0.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 +157 -0
- package/dist/index.mjs +2 -2
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Orbit RPC
|
|
2
|
+
|
|
3
|
+
Auto-converts `server.ts` functions to type-safe RPC endpoints — designed for the AI era.
|
|
4
|
+
|
|
5
|
+
> Part of the [Orbit](../../) frontend toolkit — designed so that AI-generated code and human-written code always look the same.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Zero boilerplate** — Export a function from `server.ts`, it becomes an RPC endpoint
|
|
10
|
+
- **Automatic Zod validation** — Link a Zod schema in `schema.ts`, get runtime validation for free
|
|
11
|
+
- **Vite plugin** — Dev middleware with HMR, production build generates a Hono app
|
|
12
|
+
- **Cloudflare Workers ready** — `import app from "virtual:orbit-rpc/server"` and deploy
|
|
13
|
+
- **Type-safe end-to-end** — TypeScript types flow from schema to server to client
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm add orbit-rpc hono
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
// vite.config.ts
|
|
23
|
+
import { orbitRpc } from "orbit-rpc";
|
|
24
|
+
|
|
25
|
+
export default defineConfig({
|
|
26
|
+
plugins: [orbitRpc()],
|
|
27
|
+
});
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Write a server function:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
// src/routes/tasks/server.ts
|
|
34
|
+
export async function getTasks(signal?: AbortSignal) {
|
|
35
|
+
const res = await fetch("https://api.example.com/tasks", { signal });
|
|
36
|
+
return res.json();
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Import it from the client — the plugin replaces the import with an HTTP fetch stub:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
// src/routes/tasks/hooks.ts
|
|
44
|
+
import { getTasks } from "./server";
|
|
45
|
+
|
|
46
|
+
export function useTasks() {
|
|
47
|
+
return useQuery(["tasks"], getTasks);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
That's it. `getTasks()` on the client calls `POST /rpc/tasks/getTasks` under the hood.
|
|
52
|
+
|
|
53
|
+
## How It Works
|
|
54
|
+
|
|
55
|
+
The Vite plugin does two things:
|
|
56
|
+
|
|
57
|
+
1. **Client-side transform** — `server.ts` imports are replaced with `fetch()` stubs that call `POST /rpc/{route}/{function}`
|
|
58
|
+
2. **Server-side handler** — Dev middleware (or production Hono app) receives those requests and executes the real function
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
Client Server
|
|
62
|
+
───── ──────
|
|
63
|
+
import { getTasks } server.ts (real function)
|
|
64
|
+
from "./server" ↑
|
|
65
|
+
│ │
|
|
66
|
+
↓ │
|
|
67
|
+
fetch("/rpc/tasks/getTasks") ──→ getTasks()
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Automatic Zod Validation
|
|
71
|
+
|
|
72
|
+
When `schema.ts` sits next to `server.ts`, the plugin automatically validates function arguments using the linked Zod schema.
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
// src/routes/bookmarks/schema.ts
|
|
76
|
+
import { z } from "zod";
|
|
77
|
+
|
|
78
|
+
export const bookmarkInputSchema = z.object({
|
|
79
|
+
url: z.string().url(),
|
|
80
|
+
title: z.string().min(1),
|
|
81
|
+
description: z.string(),
|
|
82
|
+
tags: z.array(z.string()),
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
export type BookmarkInput = z.infer<typeof bookmarkInputSchema>;
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
// src/routes/bookmarks/server.ts
|
|
90
|
+
import type { BookmarkInput } from "./schema";
|
|
91
|
+
|
|
92
|
+
export async function createBookmark(data: BookmarkInput) {
|
|
93
|
+
// `data` is already validated by Zod — invalid requests get a 400 response
|
|
94
|
+
return db.insert(bookmarks).values(data);
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The plugin detects `export type X = z.infer<typeof ySchema>` patterns in `schema.ts` and binds `ySchema` to the matching parameter type in `server.ts`. No manual wiring needed.
|
|
99
|
+
|
|
100
|
+
### Validation errors
|
|
101
|
+
|
|
102
|
+
Invalid requests receive a `400` response with structured error messages:
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"error": "Validation error on \"data\": url: Invalid url, title: String must contain at least 1 character(s)"
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Production Build
|
|
111
|
+
|
|
112
|
+
Import the virtual module to get a Hono app with all RPC routes pre-registered:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
// worker.ts (Cloudflare Workers entry)
|
|
116
|
+
import app from "virtual:orbit-rpc/server";
|
|
117
|
+
|
|
118
|
+
export default app;
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The generated Hono app includes:
|
|
122
|
+
- All `server.ts` functions as `POST` routes
|
|
123
|
+
- Zod validation (using `safeParse`) for validated parameters
|
|
124
|
+
- JSON parsing with error handling
|
|
125
|
+
- 1MB payload size limit
|
|
126
|
+
|
|
127
|
+
## Plugin Options
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
orbitRpc({
|
|
131
|
+
routesDir: "src/routes", // Where to scan for server.ts files (default: "src/routes")
|
|
132
|
+
rpcBase: "/rpc", // URL prefix for RPC endpoints (default: "/rpc")
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Type Flow
|
|
137
|
+
|
|
138
|
+
`schema.ts` is the single source of truth. One change propagates through all layers:
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
schema.ts Define Zod schema + export type
|
|
142
|
+
│
|
|
143
|
+
├─→ server.ts Function params use the type → auto-validated
|
|
144
|
+
├─→ hooks.ts (useForm) Form binds to the same schema → client validation
|
|
145
|
+
└─→ hooks.ts (useQuery) Return type inferred from server function
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Conventions
|
|
149
|
+
|
|
150
|
+
- `server.ts` — Export `async function` or `export const fn = async () => {}`
|
|
151
|
+
- `schema.ts` — Export Zod schemas and `z.infer` types for automatic validation
|
|
152
|
+
- `AbortSignal` parameters are automatically detected and passed through from `fetch`
|
|
153
|
+
- Dynamic route segments (`[id]`) in directory names become part of the URL prefix
|
|
154
|
+
|
|
155
|
+
## License
|
|
156
|
+
|
|
157
|
+
MIT
|
package/dist/index.mjs
CHANGED
|
@@ -347,10 +347,10 @@ function generateHonoApp(modules, root, rpcBase) {
|
|
|
347
347
|
continue;
|
|
348
348
|
}
|
|
349
349
|
validModules.push([i, mod]);
|
|
350
|
-
const importPath = mod.filePath.split(path.sep).join("/");
|
|
350
|
+
const importPath = mod.filePath.split(path.sep).join("/").replace(/[\\"]/g, "\\$&");
|
|
351
351
|
lines.push(`import * as mod${i} from "${importPath}";`);
|
|
352
352
|
if (mod.schemaFilePath) {
|
|
353
|
-
const schemaPath = mod.schemaFilePath.split(path.sep).join("/");
|
|
353
|
+
const schemaPath = mod.schemaFilePath.split(path.sep).join("/").replace(/[\\"]/g, "\\$&");
|
|
354
354
|
lines.push(`import * as schema${i} from "${schemaPath}";`);
|
|
355
355
|
}
|
|
356
356
|
}
|