@irpclib/irpc 0.0.2 → 1.0.0-beta.16
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/dist/cache.d.ts +20 -0
- package/dist/cache.js +55 -0
- package/dist/call.d.ts +2 -1
- package/dist/call.js +4 -3
- package/dist/error.d.ts +50 -0
- package/dist/error.js +50 -0
- package/dist/index.d.ts +7 -5
- package/dist/index.js +6 -5
- package/dist/module.d.ts +97 -11
- package/dist/module.js +142 -134
- package/dist/resolver.d.ts +61 -0
- package/dist/resolver.js +143 -0
- package/dist/transport.d.ts +45 -0
- package/dist/transport.js +74 -0
- package/dist/types.d.ts +45 -76
- package/dist/types.js +1 -8
- package/dist/uuid.d.ts +21 -0
- package/dist/uuid.js +45 -0
- package/package.json +10 -14
- package/readme.md +139 -111
- package/dist/batch.d.ts +0 -18
- package/dist/batch.js +0 -23
- package/dist/utils.d.ts +0 -17
- package/dist/utils.js +0 -26
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ErrorCode } from "./error.js";
|
|
2
|
+
import { IRPCTransport } from "./transport.js";
|
|
2
3
|
import { ZodArray, ZodBoolean, ZodNull, ZodNumber, ZodObject, ZodSafeParseResult, ZodString, ZodUndefined } from "zod/v4";
|
|
3
4
|
|
|
4
5
|
//#region src/types.d.ts
|
|
@@ -7,17 +8,12 @@ import { ZodArray, ZodBoolean, ZodNull, ZodNumber, ZodObject, ZodSafeParseResult
|
|
|
7
8
|
* A registry that maps IRPCHandlers to their corresponding IRPCHosts.
|
|
8
9
|
* Uses WeakMap to avoid memory leaks by not preventing garbage collection of handlers.
|
|
9
10
|
*/
|
|
10
|
-
type
|
|
11
|
+
type IRPCStubStore = WeakMap<IRPCHandler, IRPCSpec<IRPCInputs, IRPCOutput>>;
|
|
11
12
|
/**
|
|
12
13
|
* A store that maps string identifiers to IRPCHosts.
|
|
13
14
|
* Used to keep track of available RPC hosts by their names.
|
|
14
15
|
*/
|
|
15
|
-
type
|
|
16
|
-
/**
|
|
17
|
-
* A function that authorizes RPC requests.
|
|
18
|
-
* Takes a Request object and returns a boolean (sync or async) indicating authorization status.
|
|
19
|
-
*/
|
|
20
|
-
type IRPCAuthorizer = (req: Request) => Promise<boolean> | boolean;
|
|
16
|
+
type IRPCSpecStore = Map<string, IRPCSpec<IRPCInputs, IRPCOutput>>;
|
|
21
17
|
/**
|
|
22
18
|
* Represents primitive data types that can be used in IRPC communications.
|
|
23
19
|
* Includes string, number, boolean, null, and undefined.
|
|
@@ -66,7 +62,7 @@ type IRPCOutput = IRPCDataSchema;
|
|
|
66
62
|
/**
|
|
67
63
|
* Defines the basic information about an RPC namespace.
|
|
68
64
|
*/
|
|
69
|
-
type
|
|
65
|
+
type IRPCPackageInfo = {
|
|
70
66
|
/** The name of the namespace */
|
|
71
67
|
name: string;
|
|
72
68
|
/** The version of the namespace */
|
|
@@ -74,12 +70,14 @@ type IRPCNamespace = {
|
|
|
74
70
|
/** Optional description of the namespace */
|
|
75
71
|
description?: string;
|
|
76
72
|
};
|
|
73
|
+
type IRPCPackageConfig = IRPCPackageInfo & {
|
|
74
|
+
timeout?: number;
|
|
75
|
+
transport?: IRPCTransport;
|
|
76
|
+
};
|
|
77
77
|
/**
|
|
78
78
|
* Defines an RPC module which extends a namespace with execution capabilities.
|
|
79
79
|
*/
|
|
80
|
-
type IRPCModule =
|
|
81
|
-
/** Optional function to submit RPC calls */
|
|
82
|
-
submit?: (calls: IRPCCall[]) => Promise<IRPCResponse[]>;
|
|
80
|
+
type IRPCModule = IRPCPackageInfo & {
|
|
83
81
|
/** Optional timeout for RPC calls */
|
|
84
82
|
timeout?: number;
|
|
85
83
|
/** Optional transport mechanism for RPC communications */
|
|
@@ -107,73 +105,37 @@ type IRPCSchema<I extends IRPCInputs, O extends IRPCOutput> = {
|
|
|
107
105
|
* Type definition for an RPC handler function.
|
|
108
106
|
* Takes IRPCData arguments and returns a Promise resolving to IRPCData.
|
|
109
107
|
*/
|
|
110
|
-
type IRPCHandler =
|
|
108
|
+
type IRPCHandler = Function;
|
|
111
109
|
/**
|
|
112
|
-
*
|
|
110
|
+
* Configuration options for initializing an RPC function.
|
|
111
|
+
* Contains metadata and constraints for the RPC function.
|
|
112
|
+
*
|
|
113
|
+
* @template I - Tuple of input validation schemas
|
|
114
|
+
* @template O - Output validation schema
|
|
113
115
|
*/
|
|
114
|
-
type
|
|
116
|
+
type IRPCInit<I extends IRPCInputs, O extends IRPCOutput> = {
|
|
115
117
|
/** The name of the RPC function */
|
|
116
118
|
name: string;
|
|
117
119
|
/** Optional schema for input/output validation */
|
|
118
120
|
schema?: IRPCSchema<I, O>;
|
|
119
121
|
/** Optional description of the RPC function */
|
|
120
122
|
description?: string;
|
|
123
|
+
/** Optional maximum age of a call in milliseconds */
|
|
124
|
+
maxAge?: number;
|
|
125
|
+
/** Optional timeout for RPC calls */
|
|
126
|
+
timeout?: number;
|
|
121
127
|
};
|
|
122
128
|
/**
|
|
123
|
-
*
|
|
129
|
+
* Complete specification for an RPC function including its implementation.
|
|
130
|
+
* Extends IRPCInit with the actual handler function.
|
|
131
|
+
*
|
|
132
|
+
* @template I - Tuple of input validation schemas
|
|
133
|
+
* @template O - Output validation schema
|
|
124
134
|
*/
|
|
125
|
-
type
|
|
135
|
+
type IRPCSpec<I extends IRPCInputs, O extends IRPCOutput> = IRPCInit<I, O> & {
|
|
126
136
|
/** The actual handler function that implements the RPC */
|
|
127
137
|
handler: IRPCHandler;
|
|
128
138
|
};
|
|
129
|
-
/**
|
|
130
|
-
* Factory interface for creating and managing RPC functions.
|
|
131
|
-
*/
|
|
132
|
-
interface IRPCFactory {
|
|
133
|
-
/**
|
|
134
|
-
* Creates a new RPC function with the given specification.
|
|
135
|
-
* @param spec The specification for the RPC function
|
|
136
|
-
*/
|
|
137
|
-
<F, I extends IRPCInputs = IRPCInputs, O extends IRPCOutput = IRPCOutput>(spec: IRPCSpec<I, O>): F;
|
|
138
|
-
/** The namespace associated with this factory */
|
|
139
|
-
get namespace(): IRPCNamespace;
|
|
140
|
-
/**
|
|
141
|
-
* Gets the endpoint URL for this factory.
|
|
142
|
-
* @param prefix Optional prefix to prepend to the endpoint, default to '/irpc'
|
|
143
|
-
*/
|
|
144
|
-
endpoint(prefix?: string): string;
|
|
145
|
-
/**
|
|
146
|
-
* Sets the transport mechanism for this factory.
|
|
147
|
-
* @param transport The transport to use
|
|
148
|
-
*/
|
|
149
|
-
use(transport: IRPCTransport): IRPCFactory;
|
|
150
|
-
/**
|
|
151
|
-
* Gets the specification for an RPC function by name.
|
|
152
|
-
* @param name The name of the RPC function
|
|
153
|
-
*/
|
|
154
|
-
get<I extends IRPCInputs, O extends IRPCOutput>(name: string): IRPCSpec<I, O>;
|
|
155
|
-
/**
|
|
156
|
-
* Configures the module settings for this factory.
|
|
157
|
-
* @param config Partial configuration for the module
|
|
158
|
-
*/
|
|
159
|
-
configure(config: Partial<IRPCModule>): IRPCFactory;
|
|
160
|
-
/**
|
|
161
|
-
* Constructs an RPC function with its handler.
|
|
162
|
-
* @param irpc The RPC function
|
|
163
|
-
* @param handler The handler that implements the RPC function
|
|
164
|
-
*/
|
|
165
|
-
construct<F>(irpc: F, handler: F): IRPCFactory;
|
|
166
|
-
/**
|
|
167
|
-
* Gets information about an RPC request.
|
|
168
|
-
* @param req The RPC request
|
|
169
|
-
*/
|
|
170
|
-
info<I extends IRPCInputs, O extends IRPCOutput>(req: IRPCRequest): IRPCSpec<I, O>;
|
|
171
|
-
/**
|
|
172
|
-
* Resolves an RPC request.
|
|
173
|
-
* @param req The RPC request to resolve
|
|
174
|
-
*/
|
|
175
|
-
resolve<R>(req: IRPCRequest): Promise<R>;
|
|
176
|
-
}
|
|
177
139
|
/**
|
|
178
140
|
* Represents an incoming RPC request.
|
|
179
141
|
*/
|
|
@@ -185,6 +147,10 @@ type IRPCRequest = {
|
|
|
185
147
|
/** Arguments for the RPC function */
|
|
186
148
|
args: unknown[];
|
|
187
149
|
};
|
|
150
|
+
type IRPCError = {
|
|
151
|
+
code: ErrorCode;
|
|
152
|
+
message: string;
|
|
153
|
+
};
|
|
188
154
|
/**
|
|
189
155
|
* Represents an RPC response.
|
|
190
156
|
*/
|
|
@@ -194,24 +160,23 @@ type IRPCResponse = {
|
|
|
194
160
|
/** Name of the RPC function that was called */
|
|
195
161
|
name: string;
|
|
196
162
|
/** Error message if the call failed */
|
|
197
|
-
error?:
|
|
163
|
+
error?: IRPCError;
|
|
198
164
|
/** Result of the RPC call if successful */
|
|
199
165
|
result?: unknown;
|
|
200
166
|
};
|
|
167
|
+
type IRPCCache = {
|
|
168
|
+
data: IRPCData;
|
|
169
|
+
expiresAt: number;
|
|
170
|
+
timestamp: number;
|
|
171
|
+
};
|
|
201
172
|
/**
|
|
202
|
-
*
|
|
173
|
+
* Represents a cache for RPC responses.
|
|
203
174
|
*/
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Sends RPC calls and returns the responses.
|
|
207
|
-
* @param calls Array of RPC calls to send
|
|
208
|
-
*/
|
|
209
|
-
abstract send(calls: IRPCCall[]): Promise<IRPCResponse[]>;
|
|
210
|
-
}
|
|
175
|
+
type IRPCCaches = Map<string, IRPCCache>;
|
|
211
176
|
/**
|
|
212
177
|
* Context storage mechanism for RPC operations.
|
|
213
178
|
*/
|
|
214
|
-
type IRPCContext<K, V> = Map<K, V>;
|
|
179
|
+
type IRPCContext<K$1, V$1> = Map<K$1, V$1>;
|
|
215
180
|
/**
|
|
216
181
|
* Interface for managing RPC context stores.
|
|
217
182
|
*/
|
|
@@ -225,5 +190,9 @@ type IRPCContextProvider = {
|
|
|
225
190
|
/** Gets the current context store */
|
|
226
191
|
getStore<K, V>(): IRPCContext<K, V>;
|
|
227
192
|
};
|
|
193
|
+
type TransportConfig = {
|
|
194
|
+
timeout?: number;
|
|
195
|
+
debounce?: number;
|
|
196
|
+
};
|
|
228
197
|
//#endregion
|
|
229
|
-
export { IRPCArraySchema,
|
|
198
|
+
export { IRPCArraySchema, IRPCCache, IRPCCaches, IRPCContext, IRPCContextProvider, IRPCData, IRPCDataSchema, IRPCError, IRPCHandler, IRPCInit, IRPCInputs, IRPCModule, IRPCObject, IRPCObjectSchema, IRPCOutput, IRPCPackageConfig, IRPCPackageInfo, IRPCParseResult, IRPCPayload, IRPCPrimitive, IRPCPrimitiveSchema, IRPCRequest, IRPCResponse, IRPCSchema, IRPCSpec, IRPCSpecStore, IRPCStubStore, TransportConfig };
|
package/dist/types.js
CHANGED
package/dist/uuid.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region src/uuid.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* A function that generates a random UUID string.
|
|
4
|
+
*
|
|
5
|
+
* @returns A UUID v4 string in the format xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
|
|
6
|
+
*/
|
|
7
|
+
type UUIDProvider = () => string;
|
|
8
|
+
/**
|
|
9
|
+
* Generates a new UUID using the currently configured provider.
|
|
10
|
+
*
|
|
11
|
+
* @returns A UUID string generated by the current provider
|
|
12
|
+
*/
|
|
13
|
+
declare function uuid(): string;
|
|
14
|
+
/**
|
|
15
|
+
* Sets a custom UUID provider function to be used by the uuid() function.
|
|
16
|
+
*
|
|
17
|
+
* @param provider - A function that returns a UUID string when called
|
|
18
|
+
*/
|
|
19
|
+
declare function setUUIDProvider(provider: UUIDProvider): void;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { UUIDProvider, setUUIDProvider, uuid };
|
package/dist/uuid.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//#region src/uuid.ts
|
|
2
|
+
/**
|
|
3
|
+
* Generates a random UUID v4 string using a simple algorithm.
|
|
4
|
+
*
|
|
5
|
+
* @returns A UUID v4 string in the format xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
|
|
6
|
+
*/
|
|
7
|
+
function simpleId() {
|
|
8
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
9
|
+
const r = Math.random() * 16 | 0;
|
|
10
|
+
return (c === "x" ? r : r & 3 | 8).toString(16);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Default UUID provider that attempts to use the crypto API if available,
|
|
15
|
+
* otherwise falls back to a simpler implementation.
|
|
16
|
+
*
|
|
17
|
+
* @returns A UUID v4 string
|
|
18
|
+
*/
|
|
19
|
+
function defaultUUIDProvider() {
|
|
20
|
+
if (typeof crypto.randomUUID === "function") return crypto.randomUUID();
|
|
21
|
+
return simpleId();
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The currently active UUID provider function.
|
|
25
|
+
*/
|
|
26
|
+
let uuidProvider = defaultUUIDProvider;
|
|
27
|
+
/**
|
|
28
|
+
* Generates a new UUID using the currently configured provider.
|
|
29
|
+
*
|
|
30
|
+
* @returns A UUID string generated by the current provider
|
|
31
|
+
*/
|
|
32
|
+
function uuid() {
|
|
33
|
+
return (uuidProvider ?? defaultUUIDProvider)();
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Sets a custom UUID provider function to be used by the uuid() function.
|
|
37
|
+
*
|
|
38
|
+
* @param provider - A function that returns a UUID string when called
|
|
39
|
+
*/
|
|
40
|
+
function setUUIDProvider(provider) {
|
|
41
|
+
uuidProvider = provider;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
//#endregion
|
|
45
|
+
export { setUUIDProvider, uuid };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@irpclib/irpc",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "1.0.0-beta.16",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"module": "./dist/index.js",
|
|
7
7
|
"exports": {
|
|
@@ -10,9 +10,7 @@
|
|
|
10
10
|
"import": "./dist/index.js"
|
|
11
11
|
}
|
|
12
12
|
},
|
|
13
|
-
"files": [
|
|
14
|
-
"dist"
|
|
15
|
-
],
|
|
13
|
+
"files": ["dist"],
|
|
16
14
|
"directories": {
|
|
17
15
|
"dist": "./dist"
|
|
18
16
|
},
|
|
@@ -21,20 +19,18 @@
|
|
|
21
19
|
},
|
|
22
20
|
"devDependencies": {
|
|
23
21
|
"@biomejs/biome": "2.3.3",
|
|
22
|
+
"@types/bun": "1.3.1",
|
|
24
23
|
"@vitest/coverage-v8": "^3.2.4",
|
|
25
24
|
"@vitest/ui": "^3.2.4",
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"tsdown": "^0.15.9",
|
|
31
|
-
"vite": "^7.1.10",
|
|
25
|
+
"publint": "0.3.15",
|
|
26
|
+
"rimraf": "6.0.1",
|
|
27
|
+
"tsdown": "0.15.9",
|
|
28
|
+
"vite": "7.1.12",
|
|
32
29
|
"vitest": "^3.2.4",
|
|
33
|
-
"zod": "^4.1.5"
|
|
34
|
-
"@types/bun": "1.3.1"
|
|
30
|
+
"zod": "^4.1.5"
|
|
35
31
|
},
|
|
36
32
|
"peerDependencies": {
|
|
37
|
-
"typescript": "^5.9.
|
|
33
|
+
"typescript": "^5.9.3"
|
|
38
34
|
},
|
|
39
35
|
"optionalDependencies": {
|
|
40
36
|
"zod": "^4.1.5"
|
|
@@ -49,4 +45,4 @@
|
|
|
49
45
|
"prepublish": "bun run format && bun run clean && tsdown && publint"
|
|
50
46
|
},
|
|
51
47
|
"license": "MIT"
|
|
52
|
-
}
|
|
48
|
+
}
|
package/readme.md
CHANGED
|
@@ -1,166 +1,194 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @irpclib/irpc
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Isomorphic Remote Procedure Call** - Call remote functions like local functions.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
```typescript
|
|
6
|
+
// Instead of this:
|
|
7
|
+
const response = await fetch('/api/hello');
|
|
8
|
+
const data = await response.json();
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
// Just do this:
|
|
11
|
+
const message = await hello('John');
|
|
12
|
+
```
|
|
8
13
|
|
|
9
|
-
|
|
14
|
+
---
|
|
10
15
|
|
|
11
|
-
##
|
|
16
|
+
## Why IRPC?
|
|
12
17
|
|
|
13
|
-
|
|
18
|
+
**Beside the simplicity**, this is what you get:
|
|
14
19
|
|
|
15
|
-
|
|
16
|
-
|
|
20
|
+
### Benchmark Results
|
|
21
|
+
**Scenario:** 100,000 users, 10 calls each (1,000,000 total calls)
|
|
17
22
|
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
| Framework | Total Time | HTTP Requests | Speedup |
|
|
24
|
+
|-----------|------------|---------------|---------|
|
|
25
|
+
| **IRPC** | **3,617ms** | **100,000** | **6.96x** 🚀 |
|
|
26
|
+
| Bun Native | 25,180ms | 1,000,000 | 1.00x |
|
|
27
|
+
| Hono | 18,004ms | 1,000,000 | 1.40x |
|
|
28
|
+
| Elysia | 36,993ms | 1,000,000 | 0.68x |
|
|
20
29
|
|
|
21
|
-
|
|
30
|
+
**IRPC handled 1 million API calls in 3.6 seconds with 10x fewer HTTP connections.**
|
|
22
31
|
|
|
23
|
-
|
|
24
|
-
export const greet = irpc<(name: string) => Promise<string>>({
|
|
25
|
-
name: 'greet'
|
|
26
|
-
});
|
|
27
|
-
```
|
|
32
|
+
---
|
|
28
33
|
|
|
29
|
-
|
|
34
|
+
## Features
|
|
30
35
|
|
|
31
|
-
|
|
32
|
-
|
|
36
|
+
- ✅ **6.96x faster** than traditional REST
|
|
37
|
+
- ✅ **10x fewer HTTP connections** (automatic batching)
|
|
38
|
+
- ✅ **Type-safe** (end-to-end TypeScript)
|
|
39
|
+
- ✅ **Zero boilerplate** (no routes, no endpoints)
|
|
40
|
+
- ✅ **Transport agnostic** (HTTP, WebSocket, etc.)
|
|
41
|
+
- ✅ **Built-in caching** (configurable per-call)
|
|
42
|
+
- ✅ **Retry & timeout** (automatic error handling)
|
|
33
43
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
endpoint: '/rpc',
|
|
38
|
-
},
|
|
39
|
-
irpc
|
|
40
|
-
);
|
|
41
|
-
```
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Quick Start
|
|
42
47
|
|
|
43
|
-
###
|
|
48
|
+
### Create New Project
|
|
44
49
|
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
```bash
|
|
51
|
+
npx degit beerush/anchor/templates/irpc-bun-app my-api
|
|
52
|
+
cd my-api
|
|
53
|
+
bun install
|
|
54
|
+
bun run serve
|
|
49
55
|
```
|
|
50
56
|
|
|
51
|
-
|
|
57
|
+
Server runs on `http://localhost:3000`
|
|
52
58
|
|
|
53
|
-
|
|
54
|
-
import { setContextStore } from '@irpclib/irpc';
|
|
55
|
-
import { AsyncLocalStorage } from 'async_hooks';
|
|
59
|
+
---
|
|
56
60
|
|
|
57
|
-
|
|
61
|
+
## Manual Setup
|
|
58
62
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
POST: (req) => transport.respond(req),
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
|
-
});
|
|
63
|
+
### Installation
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npm install @irpclib/irpc @irpclib/http
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
###
|
|
69
|
+
### 1. Create Package
|
|
70
70
|
|
|
71
|
-
```
|
|
72
|
-
|
|
71
|
+
```typescript
|
|
72
|
+
// lib/module.ts
|
|
73
|
+
import { createPackage } from '@irpclib/irpc';
|
|
74
|
+
import { HTTPTransport } from '@irpclib/http';
|
|
73
75
|
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
export const irpc = createPackage({
|
|
77
|
+
name: 'my-api',
|
|
78
|
+
version: '1.0.0'
|
|
79
|
+
});
|
|
77
80
|
|
|
78
|
-
|
|
81
|
+
export const transport = new HTTPTransport({
|
|
82
|
+
endpoint: `/irpc/${irpc.href}`,
|
|
83
|
+
});
|
|
79
84
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
- **Transport Agnostic**: Switch between HTTP, WebSockets, and other transports without changing your business logic
|
|
83
|
-
- **End-to-End Type Safety**: Compile-time validation from client to server
|
|
84
|
-
- **Performance Optimized**: Intelligent batching and connection reuse
|
|
85
|
+
irpc.use(transport);
|
|
86
|
+
```
|
|
85
87
|
|
|
86
|
-
|
|
88
|
+
### 2. Declare Functions
|
|
87
89
|
|
|
88
|
-
|
|
90
|
+
```typescript
|
|
91
|
+
// rpc/hello/index.ts
|
|
92
|
+
import { irpc } from '../lib/module.js';
|
|
89
93
|
|
|
90
|
-
|
|
94
|
+
export type HelloFn = (name: string) => Promise<string>;
|
|
91
95
|
|
|
92
|
-
|
|
93
|
-
|
|
96
|
+
export const hello = irpc.declare<HelloFn>({
|
|
97
|
+
name: 'hello'
|
|
98
|
+
});
|
|
94
99
|
```
|
|
95
100
|
|
|
96
|
-
###
|
|
101
|
+
### 3. Implement Handlers (Server)
|
|
97
102
|
|
|
98
|
-
|
|
103
|
+
```typescript
|
|
104
|
+
// rpc/hello/constructor.ts
|
|
105
|
+
import { irpc } from '../lib/module.js';
|
|
106
|
+
import { hello } from './index.js';
|
|
99
107
|
|
|
100
|
-
|
|
101
|
-
|
|
108
|
+
irpc.construct(hello, async (name) => {
|
|
109
|
+
return `Hello ${name}`;
|
|
110
|
+
});
|
|
102
111
|
```
|
|
103
112
|
|
|
104
|
-
###
|
|
105
|
-
|
|
106
|
-
Transports handle the actual communication between client and server. IRPC is transport-agnostic, allowing you to switch between different communication protocols.
|
|
113
|
+
### 4. Setup Server
|
|
107
114
|
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
'Content-Type': 'application/json',
|
|
116
|
-
},
|
|
117
|
-
},
|
|
118
|
-
irpc
|
|
119
|
-
);
|
|
120
|
-
```
|
|
115
|
+
```typescript
|
|
116
|
+
// server.ts
|
|
117
|
+
import { setContextProvider } from '@irpclib/irpc';
|
|
118
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
119
|
+
import { HTTPRouter } from '@irpclib/http';
|
|
120
|
+
import { irpc, transport } from './lib/module.js';
|
|
121
|
+
import './rpc/hello/constructor.js'; // Import handlers
|
|
121
122
|
|
|
122
|
-
|
|
123
|
+
setContextProvider(new AsyncLocalStorage());
|
|
123
124
|
|
|
124
|
-
|
|
125
|
+
const router = new HTTPRouter(irpc, transport);
|
|
125
126
|
|
|
126
|
-
|
|
127
|
+
Bun.serve({
|
|
128
|
+
port: 3000,
|
|
129
|
+
routes: {
|
|
130
|
+
[transport.endpoint]: {
|
|
131
|
+
POST: (req) => router.resolve(req),
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
```
|
|
127
136
|
|
|
128
|
-
|
|
137
|
+
### 5. Use on Client
|
|
129
138
|
|
|
130
|
-
```
|
|
131
|
-
import {
|
|
139
|
+
```typescript
|
|
140
|
+
import { hello } from './rpc/hello/index.js';
|
|
132
141
|
|
|
133
|
-
|
|
142
|
+
const message = await hello('John');
|
|
143
|
+
console.log(message); // "Hello John"
|
|
134
144
|
```
|
|
135
145
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
On the server side, you implement the actual functionality for your functions:
|
|
146
|
+
---
|
|
139
147
|
|
|
140
|
-
|
|
141
|
-
import { transport } from './fs';
|
|
142
|
-
import { setContextStore } from '@irpclib/irpc';
|
|
148
|
+
## Advanced Features
|
|
143
149
|
|
|
144
|
-
|
|
150
|
+
### Caching
|
|
145
151
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
return new Response('Ok!');
|
|
151
|
-
},
|
|
152
|
-
POST: (req) => transport.respond(req),
|
|
153
|
-
}
|
|
154
|
-
},
|
|
152
|
+
```typescript
|
|
153
|
+
export const getUser = irpc.declare<GetUserFn>({
|
|
154
|
+
name: 'getUser',
|
|
155
|
+
maxAge: 60000, // Cache for 60 seconds
|
|
155
156
|
});
|
|
156
157
|
```
|
|
157
158
|
|
|
158
|
-
|
|
159
|
+
### Timeout
|
|
159
160
|
|
|
160
|
-
|
|
161
|
+
```typescript
|
|
162
|
+
export const slowQuery = irpc.declare<SlowQueryFn>({
|
|
163
|
+
name: 'slowQuery',
|
|
164
|
+
timeout: 30000, // 30 second timeout
|
|
165
|
+
});
|
|
166
|
+
```
|
|
161
167
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
168
|
+
### Validation (Optional Zod)
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import { z } from 'zod';
|
|
172
|
+
|
|
173
|
+
export const createUser = irpc.declare({
|
|
174
|
+
name: 'createUser',
|
|
175
|
+
input: [z.object({
|
|
176
|
+
name: z.string(),
|
|
177
|
+
email: z.string().email(),
|
|
178
|
+
})],
|
|
179
|
+
output: z.object({
|
|
180
|
+
id: z.string(),
|
|
181
|
+
name: z.string(),
|
|
182
|
+
}),
|
|
165
183
|
});
|
|
166
184
|
```
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Documentation
|
|
189
|
+
|
|
190
|
+
For detailed documentation, visit [https://anchorlib.dev/docs/irpc](https://anchorlib.dev/docs/irpc)
|
|
191
|
+
|
|
192
|
+
## License
|
|
193
|
+
|
|
194
|
+
MIT
|
package/dist/batch.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { IRPCCall } from "./call.js";
|
|
2
|
-
|
|
3
|
-
//#region src/batch.d.ts
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Batches multiple IRPC calls together and executes them with a specified delay.
|
|
7
|
-
*
|
|
8
|
-
* This function collects IRPC calls in a queue and executes them all at once after
|
|
9
|
-
* a specified delay has passed. If multiple calls are made within the delay period,
|
|
10
|
-
* they will be grouped together in a single batch execution.
|
|
11
|
-
*
|
|
12
|
-
* @param call - The IRPC call to be added to the current batch
|
|
13
|
-
* @param handler - A function that will be called with all queued calls when the batch executes
|
|
14
|
-
* @param delay - The delay in milliseconds before executing the batch (default: 0)
|
|
15
|
-
*/
|
|
16
|
-
declare function batch(call: IRPCCall, handler: (calls: IRPCCall[]) => void, delay?: number): void;
|
|
17
|
-
//#endregion
|
|
18
|
-
export { batch };
|
package/dist/batch.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
//#region src/batch.ts
|
|
2
|
-
const IRPC_QUEUE = /* @__PURE__ */ new Set();
|
|
3
|
-
/**
|
|
4
|
-
* Batches multiple IRPC calls together and executes them with a specified delay.
|
|
5
|
-
*
|
|
6
|
-
* This function collects IRPC calls in a queue and executes them all at once after
|
|
7
|
-
* a specified delay has passed. If multiple calls are made within the delay period,
|
|
8
|
-
* they will be grouped together in a single batch execution.
|
|
9
|
-
*
|
|
10
|
-
* @param call - The IRPC call to be added to the current batch
|
|
11
|
-
* @param handler - A function that will be called with all queued calls when the batch executes
|
|
12
|
-
* @param delay - The delay in milliseconds before executing the batch (default: 0)
|
|
13
|
-
*/
|
|
14
|
-
function batch(call, handler, delay = 0) {
|
|
15
|
-
if (!IRPC_QUEUE.size) setTimeout(() => {
|
|
16
|
-
handler([...IRPC_QUEUE.values()]);
|
|
17
|
-
IRPC_QUEUE.clear();
|
|
18
|
-
}, delay);
|
|
19
|
-
IRPC_QUEUE.add(call);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
//#endregion
|
|
23
|
-
export { batch };
|