@thednp/rpc 0.0.1 → 0.0.5

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.
Files changed (45) hide show
  1. package/AGENTS.md +5 -5
  2. package/CLAUDE.md +1 -0
  3. package/README.md +195 -47
  4. package/dist/express/express.d.mts +110 -16
  5. package/dist/express/express.d.mts.map +1 -1
  6. package/dist/express/express.mjs +113 -20
  7. package/dist/express/express.mjs.map +1 -1
  8. package/dist/fastify/fastify.d.mts +83 -5
  9. package/dist/fastify/fastify.d.mts.map +1 -1
  10. package/dist/fastify/fastify.mjs +84 -18
  11. package/dist/fastify/fastify.mjs.map +1 -1
  12. package/dist/fastify/plugin/fastify/plugin.d.mts +64 -9
  13. package/dist/fastify/plugin/fastify/plugin.d.mts.map +1 -1
  14. package/dist/fastify/plugin/fastify/plugin.mjs +73 -18
  15. package/dist/fastify/plugin/fastify/plugin.mjs.map +1 -1
  16. package/dist/helpers/helpers.d.mts +66 -4
  17. package/dist/helpers/helpers.d.mts.map +1 -1
  18. package/dist/helpers/helpers.mjs +34 -7
  19. package/dist/helpers/helpers.mjs.map +1 -1
  20. package/dist/hono/hono.d.mts +75 -6
  21. package/dist/hono/hono.d.mts.map +1 -1
  22. package/dist/hono/hono.mjs +84 -24
  23. package/dist/hono/hono.mjs.map +1 -1
  24. package/dist/index.d.mts +210 -19
  25. package/dist/index.d.mts.map +1 -1
  26. package/dist/index.mjs +137 -31
  27. package/dist/index.mjs.map +1 -1
  28. package/dist/koa/koa.d.mts +52 -0
  29. package/dist/koa/koa.d.mts.map +1 -1
  30. package/dist/koa/koa.mjs +86 -16
  31. package/dist/koa/koa.mjs.map +1 -1
  32. package/dist/server/server.d.mts +111 -10
  33. package/dist/server/server.d.mts.map +1 -1
  34. package/dist/server/server.mjs +117 -17
  35. package/dist/server/server.mjs.map +1 -1
  36. package/package.json +48 -31
  37. package/wiki/adapters.md +0 -143
  38. package/wiki/best-practices.md +0 -201
  39. package/wiki/client-usage.md +0 -62
  40. package/wiki/configuration.md +0 -77
  41. package/wiki/getting-started.md +0 -76
  42. package/wiki/index.md +0 -26
  43. package/wiki/security.md +0 -54
  44. package/wiki/server-functions.md +0 -93
  45. package/wiki/setup.md +0 -77
@@ -1,93 +0,0 @@
1
- # Server Functions
2
-
3
- ## `createServerFunction(name, handler, options?)`
4
-
5
- The core API for defining server-side functions.
6
-
7
- ### Signature
8
-
9
- ```ts
10
- function createServerFunction<T>(
11
- name: string,
12
- handler: (signal: AbortSignal, ...args: JsonArray) => Promise<T>,
13
- options?: { contentType: 'application/json' | 'text/plain'}
14
- ): ServerFunction<T>;
15
- ```
16
-
17
- ### Parameters
18
-
19
- - **`name`** (`string`) — The registered name used in RPC routing. Must match the name used when calling the function on the client.
20
- - **`handler`** (`(signal: AbortSignal, ...args: JsonArray) => Promise<T>`) — The actual implementation. The first argument is always an `AbortSignal`; remaining arguments come from the client. The return value must be JSON-serializable.
21
- - **`options`** (`{ contentType?: 'application/json' | 'text/plain' }`) — Optional serialization strategy. Defaults to `'application/json'`.
22
-
23
- ### AbortSignal
24
-
25
- The first argument to every server function is an `AbortSignal`. This allows the client to cancel a request:
26
-
27
- ```ts
28
- export const longTask = createServerFunction(
29
- 'long-task',
30
- async (signal: AbortSignal, id: string) => {
31
- signal.throwIfAborted(); // throws if client cancelled
32
- // ... do work ...
33
- signal.throwIfAborted(); // check again after each step
34
- return result;
35
- },
36
- );
37
- ```
38
-
39
- Use `signal.aborted` or `signal.throwIfAborted()` in long-running functions to respond to cancellation promptly.
40
-
41
- ### Registration
42
-
43
- When `createServerFunction` is called, it registers the function in a server-side map keyed by `name`. This map is used by the RPC middleware to route incoming requests to the correct implementation.
44
-
45
- ### Return Type
46
-
47
- The return value of `handler` is serialized to JSON and sent as the HTTP response body. Ensure your return type is JSON-serializable.
48
-
49
- ## Input Validation
50
-
51
- Server functions receive raw, untrusted client data. Always validate before use.
52
-
53
- **zod:**
54
-
55
- ```ts
56
- import { z } from 'zod';
57
- import { createServerFunction } from '@thednp/rpc/server';
58
-
59
- const AddSchema = z.object({
60
- a: z.number(),
61
- b: z.number(),
62
- });
63
-
64
- export const add = createServerFunction('add', async (signal, raw) => {
65
- const parsed = AddSchema.safeParse(raw);
66
- if (!parsed.success) {
67
- return { error: parsed.error.flatten() };
68
- }
69
- return parsed.data.a + parsed.data.b;
70
- });
71
- ```
72
-
73
- **valibot:**
74
-
75
- ```ts
76
- import * as v from 'valibot';
77
- import { createServerFunction } from '@thednp/rpc/server';
78
-
79
- const AddSchema = v.object({
80
- a: v.number(),
81
- b: v.number(),
82
- });
83
-
84
- export const add = createServerFunction('add', async (signal, raw) => {
85
- const parsed = v.safeParse(AddSchema, raw);
86
- if (parsed.issues) {
87
- return { error: v.flatten(parsed.issues).nested };
88
- }
89
- return parsed.output.a + parsed.output.b;
90
- });
91
- ```
92
-
93
- Validation errors return structured data instead of throwing — the client's auto-generated `handleResponse` receives `{ error: ... }` and surfaces it as an `Error`.
package/wiki/setup.md DELETED
@@ -1,77 +0,0 @@
1
- # Setup
2
-
3
- ## Required Project Structure
4
-
5
- ```
6
- project/
7
- ├── src/
8
- │ ├── api/
9
- │ │ └── server.ts # Auto-scanned server functions
10
- │ ├── entry-client.ts # Client entry (SSR projects)
11
- │ └── entry-server.ts # Server entry (SSR projects)
12
- ├── vite.config.ts # Add rpc() plugin here
13
- ├── rpc.config.ts # Optional config
14
- └── package.json
15
- ```
16
-
17
- ## Server Files
18
-
19
- The plugin looks in `src/api/` for files matching these names:
20
-
21
- - `server.ts`
22
- - `server.js`
23
- - `server.mjs`
24
- - `server.mts`
25
-
26
- Each matched file is loaded with `vite.ssrLoadModule`, and all named exports are mapped to client functions. Export each function individually for proper mapping.
27
-
28
- ## How Auto-Scanning Works
29
-
30
- 1. During `resolveId`, the plugin intercepts imports from `./api` (or paths under `src/api/`).
31
- 2. It scans `src/api/` for the server files listed above and loads them via `vite.ssrLoadModule`.
32
- 3. It builds a map of export names to their `createServerFunction` registration names.
33
- 4. During `transform`, it replaces the import with generated client modules that use `fetch` API under the hood.
34
-
35
- ## SSR vs SPA
36
-
37
- ### SSR Projects
38
-
39
- Create both `src/entry-client.ts` and `src/entry-server.ts`. The client bundle imports from `./api`, which gets transformed by the plugin. On the server, `createServerFunction` runs directly (not transformed).
40
-
41
- ### SPA Projects
42
-
43
- Import directly from `./api` in your client code. No server entry is needed.
44
-
45
- ## Production Adapters
46
-
47
- Use the appropriate adapter for your framework:
48
-
49
- ```ts
50
- // Express
51
- import { attachRPC, attachVite } from '@thednp/rpc/express';
52
- await attachRPC(app); // production
53
- attachVite(app, vite); // development
54
- ```
55
-
56
- ```ts
57
- // Fastify
58
- import { attachRPC, attachVite } from '@thednp/rpc/fastify';
59
- await attachRPC(app); // production
60
- attachVite(app, vite); // development
61
- ```
62
-
63
- ```ts
64
- // Hono
65
- import { attachRPC, attachVite } from '@thednp/rpc/hono';
66
- await attachRPC(app); // production
67
- attachVite(app, vite); // development
68
- ```
69
-
70
- ```ts
71
- // Koa
72
- import { attachRPC, attachVite } from '@thednp/rpc/koa';
73
- await attachRPC(app); // production
74
- attachVite(app, vite); // development
75
- ```
76
-
77
- See [Adapters](adapters.md) for full server setup examples.