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 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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orbit-rpc",
3
- "version": "0.2.0",
3
+ "version": "1.0.0",
4
4
  "description": "RPC layer for Orbit — auto-converts server.ts functions to Hono routes",
5
5
  "keywords": [
6
6
  "fullstack",