@procedures/peer 0.0.0-stage → 0.1.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/CHANGELOG.md +5 -0
- package/LICENSE +21 -0
- package/README.md +725 -2
- package/dist/.tsbuildinfo +1 -0
- package/dist/connection/index.d.ts +45 -0
- package/dist/connection/index.d.ts.map +1 -0
- package/dist/connection/index.js +148 -0
- package/dist/connection/index.js.map +1 -0
- package/dist/discovery/index.d.ts +30 -0
- package/dist/discovery/index.d.ts.map +1 -0
- package/dist/discovery/index.js +101 -0
- package/dist/discovery/index.js.map +1 -0
- package/dist/expose.d.ts +14 -0
- package/dist/expose.d.ts.map +1 -0
- package/dist/expose.js +16 -0
- package/dist/expose.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/input-schemas.d.ts +21 -0
- package/dist/input-schemas.d.ts.map +1 -0
- package/dist/input-schemas.js +80 -0
- package/dist/input-schemas.js.map +1 -0
- package/dist/lockfile.d.ts +48 -0
- package/dist/lockfile.d.ts.map +1 -0
- package/dist/lockfile.js +115 -0
- package/dist/lockfile.js.map +1 -0
- package/dist/manifest/index.d.ts +8 -0
- package/dist/manifest/index.d.ts.map +1 -0
- package/dist/manifest/index.js +8 -0
- package/dist/manifest/index.js.map +1 -0
- package/dist/manifest/json.d.ts +27 -0
- package/dist/manifest/json.d.ts.map +1 -0
- package/dist/manifest/json.js +24 -0
- package/dist/manifest/json.js.map +1 -0
- package/dist/manifest/typescript.d.ts +17 -0
- package/dist/manifest/typescript.d.ts.map +1 -0
- package/dist/manifest/typescript.js +123 -0
- package/dist/manifest/typescript.js.map +1 -0
- package/dist/module.d.ts +20 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +42 -0
- package/dist/module.js.map +1 -0
- package/dist/output-schemas.d.ts +21 -0
- package/dist/output-schemas.d.ts.map +1 -0
- package/dist/output-schemas.js +85 -0
- package/dist/output-schemas.js.map +1 -0
- package/dist/peer/index.d.ts +47 -0
- package/dist/peer/index.d.ts.map +1 -0
- package/dist/peer/index.js +234 -0
- package/dist/peer/index.js.map +1 -0
- package/dist/peer/security.d.ts +25 -0
- package/dist/peer/security.d.ts.map +1 -0
- package/dist/peer/security.js +58 -0
- package/dist/peer/security.js.map +1 -0
- package/dist/procedures/index.d.ts +24 -0
- package/dist/procedures/index.d.ts.map +1 -0
- package/dist/procedures/index.js +15 -0
- package/dist/procedures/index.js.map +1 -0
- package/dist/procedures/manifest.generate.d.ts +11 -0
- package/dist/procedures/manifest.generate.d.ts.map +1 -0
- package/dist/procedures/manifest.generate.js +97 -0
- package/dist/procedures/manifest.generate.js.map +1 -0
- package/dist/procedures/server.call.d.ts +30 -0
- package/dist/procedures/server.call.d.ts.map +1 -0
- package/dist/procedures/server.call.js +60 -0
- package/dist/procedures/server.call.js.map +1 -0
- package/dist/procedures/server.connect.d.ts +11 -0
- package/dist/procedures/server.connect.d.ts.map +1 -0
- package/dist/procedures/server.connect.js +35 -0
- package/dist/procedures/server.connect.js.map +1 -0
- package/dist/procedures/server.connections.d.ts +22 -0
- package/dist/procedures/server.connections.d.ts.map +1 -0
- package/dist/procedures/server.connections.js +38 -0
- package/dist/procedures/server.connections.js.map +1 -0
- package/dist/procedures/server.create.d.ts +20 -0
- package/dist/procedures/server.create.d.ts.map +1 -0
- package/dist/procedures/server.create.js +64 -0
- package/dist/procedures/server.create.js.map +1 -0
- package/dist/procedures/server.disconnect.d.ts +11 -0
- package/dist/procedures/server.disconnect.d.ts.map +1 -0
- package/dist/procedures/server.disconnect.js +22 -0
- package/dist/procedures/server.disconnect.js.map +1 -0
- package/dist/procedures/server.start.d.ts +13 -0
- package/dist/procedures/server.start.d.ts.map +1 -0
- package/dist/procedures/server.start.js +179 -0
- package/dist/procedures/server.start.js.map +1 -0
- package/dist/procedures/server.status.d.ts +12 -0
- package/dist/procedures/server.status.d.ts.map +1 -0
- package/dist/procedures/server.status.js +116 -0
- package/dist/procedures/server.status.js.map +1 -0
- package/dist/procedures/server.stop.d.ts +11 -0
- package/dist/procedures/server.stop.d.ts.map +1 -0
- package/dist/procedures/server.stop.js +96 -0
- package/dist/procedures/server.stop.js.map +1 -0
- package/dist/register.d.ts +8 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +14 -0
- package/dist/register.js.map +1 -0
- package/dist/schema.d.ts +14 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +14 -0
- package/dist/schema.js.map +1 -0
- package/dist/types.d.ts +192 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +87 -3
- package/src/connection/index.ts +219 -0
- package/src/discovery/index.ts +137 -0
- package/src/expose.ts +17 -0
- package/src/index.ts +69 -0
- package/src/input-schemas.ts +121 -0
- package/src/lockfile.ts +129 -0
- package/src/manifest/index.ts +8 -0
- package/src/manifest/json.ts +39 -0
- package/src/manifest/typescript.ts +148 -0
- package/src/module.ts +46 -0
- package/src/output-schemas.ts +110 -0
- package/src/peer/index.ts +325 -0
- package/src/peer/security.ts +58 -0
- package/src/procedures/index.ts +32 -0
- package/src/procedures/manifest.generate.ts +113 -0
- package/src/procedures/server.call.ts +96 -0
- package/src/procedures/server.connect.ts +45 -0
- package/src/procedures/server.connections.ts +64 -0
- package/src/procedures/server.create.ts +84 -0
- package/src/procedures/server.disconnect.ts +31 -0
- package/src/procedures/server.start.ts +209 -0
- package/src/procedures/server.status.ts +139 -0
- package/src/procedures/server.stop.ts +121 -0
- package/src/register.ts +17 -0
- package/src/schema.ts +15 -0
- package/src/types.ts +257 -0
package/README.md
CHANGED
|
@@ -1,3 +1,726 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @procedures/peer
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@procedures/peer)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://nodejs.org)
|
|
6
|
+
|
|
7
|
+
> Transport-agnostic peer for bidirectional RPC - exposes procedures and generates manifests
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
`client-server` is a comprehensive server infrastructure package that enables transport-agnostic bidirectional RPC communication. It provides a peer-to-peer architecture where each peer can both expose procedures and call procedures on remote peers. The package supports multiple transport layers (HTTP, WebSocket, local) and includes automatic procedure discovery and manifest generation.
|
|
12
|
+
|
|
13
|
+
### Key Features
|
|
14
|
+
|
|
15
|
+
- **Transport-Agnostic**: Supports HTTP, WebSocket, and in-process transports
|
|
16
|
+
- **Bidirectional RPC**: Peers can both expose and call procedures
|
|
17
|
+
- **Automatic Discovery**: Peers exchange procedure manifests on connection
|
|
18
|
+
- **Manifest Generation**: Generate TypeScript and JSON manifests from registered procedures
|
|
19
|
+
- **Connection Management**: Track and manage multiple peer connections
|
|
20
|
+
- **Express Integration**: Optional Express.js integration for HTTP transport
|
|
21
|
+
- **Zero Configuration**: Auto-register all procedures from the global registry
|
|
22
|
+
|
|
23
|
+
## Architecture
|
|
24
|
+
|
|
25
|
+
```mermaid
|
|
26
|
+
graph TB
|
|
27
|
+
subgraph "Peer A"
|
|
28
|
+
PA[Peer Instance]
|
|
29
|
+
PS[Procedure Server]
|
|
30
|
+
REG[Procedure Registry]
|
|
31
|
+
HT[HTTP Transport]
|
|
32
|
+
WT[WebSocket Transport]
|
|
33
|
+
|
|
34
|
+
PA --> PS
|
|
35
|
+
PS --> REG
|
|
36
|
+
PS --> HT
|
|
37
|
+
PS --> WT
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
subgraph "Peer B"
|
|
41
|
+
PB[Peer Instance]
|
|
42
|
+
CL[Client]
|
|
43
|
+
CT[Client Transport]
|
|
44
|
+
DISC[Discovery]
|
|
45
|
+
|
|
46
|
+
PB --> CL
|
|
47
|
+
CL --> CT
|
|
48
|
+
CL --> DISC
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
HT -.HTTP.-> CT
|
|
52
|
+
WT -.WebSocket.-> CT
|
|
53
|
+
DISC -.Discovery Protocol.-> PS
|
|
54
|
+
|
|
55
|
+
style PA fill:#e1f5ff
|
|
56
|
+
style PB fill:#ffe1f5
|
|
57
|
+
style DISC fill:#fff4e1
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Component Hierarchy
|
|
61
|
+
|
|
62
|
+
```mermaid
|
|
63
|
+
graph TD
|
|
64
|
+
SERVER[client-server] --> PEER[Peer]
|
|
65
|
+
SERVER --> CONN[Connection Manager]
|
|
66
|
+
SERVER --> DISC[Discovery System]
|
|
67
|
+
SERVER --> MAN[Manifest Generator]
|
|
68
|
+
|
|
69
|
+
PEER --> PSERV[Procedure Server]
|
|
70
|
+
PEER --> TRANS[Transports]
|
|
71
|
+
|
|
72
|
+
TRANS --> HTTP[HTTP Transport]
|
|
73
|
+
TRANS --> WS[WebSocket Transport]
|
|
74
|
+
TRANS --> LOCAL[Local Transport]
|
|
75
|
+
|
|
76
|
+
CONN --> CLIENT[Client]
|
|
77
|
+
CONN --> CTRANS[Client Transports]
|
|
78
|
+
|
|
79
|
+
DISC --> ANNOUNCE[Announce Procedure]
|
|
80
|
+
DISC --> WATCH[Procedure Watcher]
|
|
81
|
+
|
|
82
|
+
MAN --> TS[TypeScript Generator]
|
|
83
|
+
MAN --> JSON[JSON Generator]
|
|
84
|
+
|
|
85
|
+
style SERVER fill:#4a90e2
|
|
86
|
+
style PEER fill:#7ed321
|
|
87
|
+
style CONN fill:#f5a623
|
|
88
|
+
style DISC fill:#bd10e0
|
|
89
|
+
style MAN fill:#50e3c2
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Installation
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
npm install @procedures/peer
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Or with pnpm:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
pnpm add @procedures/peer
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Dependencies
|
|
105
|
+
|
|
106
|
+
This package depends on:
|
|
107
|
+
- `@procedures/client` - Core client/procedure system
|
|
108
|
+
- `zod` - Schema validation
|
|
109
|
+
- `zod-to-json-schema` - JSON schema generation
|
|
110
|
+
- `express` (optional) - HTTP server for HTTP transport
|
|
111
|
+
|
|
112
|
+
## Usage
|
|
113
|
+
|
|
114
|
+
### Creating a Server Peer
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import { createPeer } from "@procedures/peer";
|
|
118
|
+
|
|
119
|
+
// Create a peer with HTTP and WebSocket transports
|
|
120
|
+
const peer = await createPeer({
|
|
121
|
+
id: "my-server",
|
|
122
|
+
transports: [
|
|
123
|
+
{
|
|
124
|
+
type: "http",
|
|
125
|
+
port: 3000,
|
|
126
|
+
host: "0.0.0.0",
|
|
127
|
+
basePath: "/api",
|
|
128
|
+
cors: true,
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
type: "websocket",
|
|
132
|
+
port: 3001,
|
|
133
|
+
host: "0.0.0.0",
|
|
134
|
+
path: "/ws",
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
autoRegister: true, // Auto-register all procedures from global registry
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// Start all transports
|
|
141
|
+
await peer.start();
|
|
142
|
+
|
|
143
|
+
// Get active endpoints
|
|
144
|
+
console.log(peer.getEndpoints());
|
|
145
|
+
// [
|
|
146
|
+
// { type: "http", address: "http://localhost:3000/api" },
|
|
147
|
+
// { type: "websocket", address: "ws://localhost:3001/ws" }
|
|
148
|
+
// ]
|
|
149
|
+
|
|
150
|
+
// Stop the peer
|
|
151
|
+
await peer.stop();
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Using Server Procedures
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
import { Client, LocalTransport, PROCEDURE_REGISTRY } from "@procedures/client";
|
|
158
|
+
import "@procedures/peer"; // registers its procedures
|
|
159
|
+
|
|
160
|
+
const client = new Client(new LocalTransport({ registry: PROCEDURE_REGISTRY }));
|
|
161
|
+
|
|
162
|
+
// Create a server
|
|
163
|
+
const result = await client.exec(["server", "create"], {
|
|
164
|
+
transports: [
|
|
165
|
+
{ type: "http", port: 3000 },
|
|
166
|
+
{ type: "websocket", port: 3001 },
|
|
167
|
+
],
|
|
168
|
+
autoRegister: true,
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
console.log(result);
|
|
172
|
+
// {
|
|
173
|
+
// serverId: "peer-1234567890-abc123",
|
|
174
|
+
// endpoints: [
|
|
175
|
+
// { type: "http", address: "http://localhost:3000/api" },
|
|
176
|
+
// { type: "websocket", address: "ws://localhost:3001/ws" }
|
|
177
|
+
// ],
|
|
178
|
+
// procedureCount: 42
|
|
179
|
+
// }
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Connecting to Remote Peers
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
import { connect } from "@procedures/peer";
|
|
186
|
+
|
|
187
|
+
// Connect to a remote peer
|
|
188
|
+
const connection = await connect({
|
|
189
|
+
address: "http://localhost:3000/api",
|
|
190
|
+
transport: "http", // Auto-detected from URL if omitted
|
|
191
|
+
timeout: 10000,
|
|
192
|
+
localPeerId: "my-client",
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
console.log(connection.remote);
|
|
196
|
+
// {
|
|
197
|
+
// id: "conn-1234567890-xyz789",
|
|
198
|
+
// remotePeerId: "peer-1234567890-abc123",
|
|
199
|
+
// transport: "http",
|
|
200
|
+
// state: "connected",
|
|
201
|
+
// remoteProcedures: [
|
|
202
|
+
// { path: ["git", "status"], description: "Get git status" },
|
|
203
|
+
// { path: ["git", "add"], description: "Stage files" },
|
|
204
|
+
// // ...
|
|
205
|
+
// ],
|
|
206
|
+
// connectedAt: Date
|
|
207
|
+
// }
|
|
208
|
+
|
|
209
|
+
// Call procedures on the remote peer
|
|
210
|
+
const gitStatus = await connection.client.call(["git", "status"], { cwd: "/path" });
|
|
211
|
+
|
|
212
|
+
// Disconnect
|
|
213
|
+
await connection.disconnect();
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Procedure Discovery
|
|
217
|
+
|
|
218
|
+
The discovery system automatically exchanges procedure manifests when peers connect:
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
import { discoveryAnnounceProcedure, getProcedureInfos, watchProcedures } from "@procedures/peer";
|
|
222
|
+
|
|
223
|
+
// Get all registered procedures
|
|
224
|
+
const procedures = getProcedureInfos();
|
|
225
|
+
console.log(procedures);
|
|
226
|
+
// [
|
|
227
|
+
// { path: ["git", "status"], description: "Get git status" },
|
|
228
|
+
// { path: ["git", "add"], description: "Stage files" },
|
|
229
|
+
// // ...
|
|
230
|
+
// ]
|
|
231
|
+
|
|
232
|
+
// Watch for procedure changes
|
|
233
|
+
const unwatch = watchProcedures((event, info) => {
|
|
234
|
+
console.log(`Procedure ${event}:`, info.path.join("."));
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// Stop watching
|
|
238
|
+
unwatch();
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Manifest Generation
|
|
242
|
+
|
|
243
|
+
Generate TypeScript declarations or JSON manifests from registered procedures:
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
import { generateTypeScript, generateJson, generateJsonString } from "@procedures/peer";
|
|
247
|
+
|
|
248
|
+
// Generate TypeScript declaration
|
|
249
|
+
const tsDeclaration = generateTypeScript({
|
|
250
|
+
namespace: ["git"], // Only include git.* procedures
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
console.log(tsDeclaration);
|
|
254
|
+
// export interface Procedures {
|
|
255
|
+
// "git.status": { input: { cwd?: string }, output: { ... } };
|
|
256
|
+
// "git.add": { input: { files: string[], all?: boolean }, output: { ... } };
|
|
257
|
+
// // ...
|
|
258
|
+
// }
|
|
259
|
+
|
|
260
|
+
// Generate JSON manifest
|
|
261
|
+
const manifest = generateJson({
|
|
262
|
+
namespace: ["git"],
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
console.log(manifest);
|
|
266
|
+
// {
|
|
267
|
+
// procedures: [
|
|
268
|
+
// {
|
|
269
|
+
// path: ["git", "status"],
|
|
270
|
+
// description: "Get git status",
|
|
271
|
+
// inputSchema: { ... },
|
|
272
|
+
// outputSchema: { ... }
|
|
273
|
+
// },
|
|
274
|
+
// // ...
|
|
275
|
+
// ],
|
|
276
|
+
// generatedAt: "2025-01-15T10:30:00.000Z",
|
|
277
|
+
// version: "1.0.0"
|
|
278
|
+
// }
|
|
279
|
+
|
|
280
|
+
// Generate JSON string
|
|
281
|
+
const jsonString = generateJsonString({ namespace: ["git"] });
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Using with Procedure Calls
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
// Connect to remote server
|
|
288
|
+
await client.exec(["server", "connect"], {
|
|
289
|
+
address: "http://localhost:3000/api",
|
|
290
|
+
transport: "http",
|
|
291
|
+
timeout: 10000,
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
// Disconnect from server
|
|
295
|
+
await client.exec(["server", "disconnect"], {
|
|
296
|
+
connectionId: "conn-1234567890-xyz789",
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
// Generate manifest
|
|
300
|
+
const manifest = await client.exec(["manifest", "generate"], {
|
|
301
|
+
formats: ["json", "typescript"],
|
|
302
|
+
namespace: ["git"],
|
|
303
|
+
outputDir: "./generated",
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
console.log(manifest);
|
|
307
|
+
// {
|
|
308
|
+
// json: { procedures: [...], generatedAt: "...", version: "..." },
|
|
309
|
+
// typescript: "export interface Procedures { ... }",
|
|
310
|
+
// filesWritten: ["./generated/manifest.json", "./generated/manifest.d.ts"]
|
|
311
|
+
// }
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
## API Reference
|
|
315
|
+
|
|
316
|
+
### Peer
|
|
317
|
+
|
|
318
|
+
#### `createPeer(options: PeerOptions): Promise<Peer>`
|
|
319
|
+
|
|
320
|
+
Create a new peer instance.
|
|
321
|
+
|
|
322
|
+
**Options:**
|
|
323
|
+
- `id: string` - Unique peer ID
|
|
324
|
+
- `transports: TransportConfig[]` - Transports to enable
|
|
325
|
+
- `autoRegister?: boolean` - Auto-register procedures from registry (default: true)
|
|
326
|
+
- `registry?: ProcedureRegistry` - Custom procedure registry (default: global)
|
|
327
|
+
|
|
328
|
+
**Returns:** Peer instance with methods:
|
|
329
|
+
- `start(): Promise<void>` - Start all transports
|
|
330
|
+
- `stop(): Promise<void>` - Stop all transports
|
|
331
|
+
- `getEndpoints(): PeerEndpoint[]` - Get active endpoints
|
|
332
|
+
- `getServer(): ProcedureServer` - Get underlying procedure server
|
|
333
|
+
|
|
334
|
+
#### Transport Configurations
|
|
335
|
+
|
|
336
|
+
##### HTTP Transport
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
{
|
|
340
|
+
type: "http",
|
|
341
|
+
port?: number, // Default: 3000
|
|
342
|
+
host?: string, // Default: "0.0.0.0"
|
|
343
|
+
basePath?: string, // Default: "/api"
|
|
344
|
+
cors?: boolean, // Default: true
|
|
345
|
+
corsOrigins?: string[] // Allowed origins
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
##### WebSocket Transport
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
{
|
|
353
|
+
type: "websocket",
|
|
354
|
+
port?: number, // Default: 3001
|
|
355
|
+
host?: string, // Default: "0.0.0.0"
|
|
356
|
+
path?: string // Default: "/ws"
|
|
357
|
+
}
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
##### Local Transport
|
|
361
|
+
|
|
362
|
+
```typescript
|
|
363
|
+
{
|
|
364
|
+
type: "local" // In-process communication
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Connection
|
|
369
|
+
|
|
370
|
+
#### `connect(options: ConnectOptions): Promise<Connection>`
|
|
371
|
+
|
|
372
|
+
Connect to a remote peer.
|
|
373
|
+
|
|
374
|
+
**Options:**
|
|
375
|
+
- `address: string` - Remote server URL
|
|
376
|
+
- `transport?: TransportType` - Transport type (auto-detected from URL)
|
|
377
|
+
- `timeout?: number` - Connection timeout in ms
|
|
378
|
+
- `localPeerId?: string` - Local peer ID to identify ourselves
|
|
379
|
+
|
|
380
|
+
**Returns:** Connection object with:
|
|
381
|
+
- `id: string` - Connection ID
|
|
382
|
+
- `remote: PeerConnection` - Remote peer info
|
|
383
|
+
- `client: Client` - Client for calling remote procedures
|
|
384
|
+
- `disconnect(): Promise<void>` - Disconnect from peer
|
|
385
|
+
|
|
386
|
+
#### `disconnect(connectionId: string): Promise<boolean>`
|
|
387
|
+
|
|
388
|
+
Disconnect a connection by ID.
|
|
389
|
+
|
|
390
|
+
#### `getConnection(connectionId: string): Connection | undefined`
|
|
391
|
+
|
|
392
|
+
Get connection by ID.
|
|
393
|
+
|
|
394
|
+
#### `getConnectionIds(): string[]`
|
|
395
|
+
|
|
396
|
+
Get all active connection IDs.
|
|
397
|
+
|
|
398
|
+
### Discovery
|
|
399
|
+
|
|
400
|
+
#### `discoveryAnnounceProcedure`
|
|
401
|
+
|
|
402
|
+
Internal procedure for procedure discovery. Automatically called when peers connect.
|
|
403
|
+
|
|
404
|
+
#### `getProcedureInfos(): ProcedureInfo[]`
|
|
405
|
+
|
|
406
|
+
Get information about all registered procedures.
|
|
407
|
+
|
|
408
|
+
#### `watchProcedures(callback: (event, info) => void): () => void`
|
|
409
|
+
|
|
410
|
+
Watch for procedure registration/unregistration events.
|
|
411
|
+
|
|
412
|
+
### Manifest Generation
|
|
413
|
+
|
|
414
|
+
#### `generateTypeScript(options?): string`
|
|
415
|
+
|
|
416
|
+
Generate TypeScript declaration from registered procedures.
|
|
417
|
+
|
|
418
|
+
**Options:**
|
|
419
|
+
- `namespace?: string[]` - Filter procedures by namespace
|
|
420
|
+
|
|
421
|
+
#### `generateJson(options?): ProcedureManifest`
|
|
422
|
+
|
|
423
|
+
Generate JSON manifest from registered procedures.
|
|
424
|
+
|
|
425
|
+
**Options:**
|
|
426
|
+
- `namespace?: string[]` - Filter procedures by namespace
|
|
427
|
+
|
|
428
|
+
**Returns:**
|
|
429
|
+
```typescript
|
|
430
|
+
{
|
|
431
|
+
procedures: ProcedureInfo[],
|
|
432
|
+
generatedAt: string,
|
|
433
|
+
version: string
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
#### `generateJsonString(options?): string`
|
|
438
|
+
|
|
439
|
+
Generate JSON manifest as string.
|
|
440
|
+
|
|
441
|
+
## Procedures
|
|
442
|
+
|
|
443
|
+
### `server.create`
|
|
444
|
+
|
|
445
|
+
Create a transport-agnostic peer that exposes procedures.
|
|
446
|
+
|
|
447
|
+
**Input:**
|
|
448
|
+
```typescript
|
|
449
|
+
{
|
|
450
|
+
transports?: TransportConfig[], // Default: [{ type: "http", port: 3000 }]
|
|
451
|
+
autoRegister?: boolean // Default: true
|
|
452
|
+
}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
**Output:**
|
|
456
|
+
```typescript
|
|
457
|
+
{
|
|
458
|
+
serverId: string,
|
|
459
|
+
endpoints: Array<{ type: TransportType, address: string }>,
|
|
460
|
+
procedureCount: number
|
|
461
|
+
}
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### `server.connect`
|
|
465
|
+
|
|
466
|
+
Connect to a remote server and discover procedures.
|
|
467
|
+
|
|
468
|
+
**Input:**
|
|
469
|
+
```typescript
|
|
470
|
+
{
|
|
471
|
+
address: string,
|
|
472
|
+
transport?: TransportType, // Auto-detected from URL
|
|
473
|
+
timeout?: number // Default: 10000
|
|
474
|
+
}
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
**Output:**
|
|
478
|
+
```typescript
|
|
479
|
+
{
|
|
480
|
+
connectionId: string,
|
|
481
|
+
remotePeerId: string,
|
|
482
|
+
remoteProcedures: ProcedureInfo[]
|
|
483
|
+
}
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
### `server.disconnect`
|
|
487
|
+
|
|
488
|
+
Disconnect from a remote server.
|
|
489
|
+
|
|
490
|
+
**Input:**
|
|
491
|
+
```typescript
|
|
492
|
+
{
|
|
493
|
+
connectionId: string
|
|
494
|
+
}
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
**Output:**
|
|
498
|
+
```typescript
|
|
499
|
+
{
|
|
500
|
+
success: boolean
|
|
501
|
+
}
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### `manifest.generate`
|
|
505
|
+
|
|
506
|
+
Generate procedure manifests in various formats.
|
|
507
|
+
|
|
508
|
+
**Input:**
|
|
509
|
+
```typescript
|
|
510
|
+
{
|
|
511
|
+
formats?: ("json" | "typescript")[], // Default: ["json"]
|
|
512
|
+
namespace?: string[], // Filter by namespace
|
|
513
|
+
outputDir?: string // Write files to directory
|
|
514
|
+
}
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
**Output:**
|
|
518
|
+
```typescript
|
|
519
|
+
{
|
|
520
|
+
json?: {
|
|
521
|
+
procedures: ProcedureInfo[],
|
|
522
|
+
generatedAt: string,
|
|
523
|
+
version: string
|
|
524
|
+
},
|
|
525
|
+
typescript?: string,
|
|
526
|
+
filesWritten?: string[]
|
|
527
|
+
}
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
### `_discovery.announce`
|
|
531
|
+
|
|
532
|
+
Internal procedure for exchanging procedure manifests (used by connection system).
|
|
533
|
+
|
|
534
|
+
## Types
|
|
535
|
+
|
|
536
|
+
### Core Types
|
|
537
|
+
|
|
538
|
+
```typescript
|
|
539
|
+
export type TransportType = "http" | "websocket" | "local";
|
|
540
|
+
|
|
541
|
+
export interface ProcedureInfo {
|
|
542
|
+
path: string[];
|
|
543
|
+
description?: string;
|
|
544
|
+
inputSchema?: Record<string, unknown>;
|
|
545
|
+
outputSchema?: Record<string, unknown>;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
export interface PeerConnection {
|
|
549
|
+
id: string;
|
|
550
|
+
remotePeerId: string;
|
|
551
|
+
transport: TransportType;
|
|
552
|
+
state: "connecting" | "connected" | "disconnected" | "error";
|
|
553
|
+
remoteProcedures: ProcedureInfo[];
|
|
554
|
+
connectedAt?: Date;
|
|
555
|
+
}
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
## Configuration
|
|
559
|
+
|
|
560
|
+
### Auto-Registration
|
|
561
|
+
|
|
562
|
+
By default, peers auto-register all procedures from the global `PROCEDURE_REGISTRY`. Disable this for manual control:
|
|
563
|
+
|
|
564
|
+
```typescript
|
|
565
|
+
const peer = await createPeer({
|
|
566
|
+
id: "my-server",
|
|
567
|
+
transports: [{ type: "http" }],
|
|
568
|
+
autoRegister: false,
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
// Manually register procedures
|
|
572
|
+
peer.getServer().register(myProcedure);
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
### CORS Configuration
|
|
576
|
+
|
|
577
|
+
Configure CORS for HTTP transport:
|
|
578
|
+
|
|
579
|
+
```typescript
|
|
580
|
+
{
|
|
581
|
+
type: "http",
|
|
582
|
+
cors: true,
|
|
583
|
+
corsOrigins: ["http://localhost:3000", "https://example.com"]
|
|
584
|
+
}
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
## Integration with Ecosystem
|
|
588
|
+
|
|
589
|
+
### With bundle-dev
|
|
590
|
+
|
|
591
|
+
The `bundle-dev` package includes `client-server` for development workflows:
|
|
592
|
+
|
|
593
|
+
```typescript
|
|
594
|
+
import "@procedures/bundle-dev"; // registers its procedures
|
|
595
|
+
|
|
596
|
+
// server.* procedures are now available
|
|
597
|
+
await client.exec(["server", "create"], { ... });
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
### With client packages
|
|
601
|
+
|
|
602
|
+
Combine with other client packages for complete functionality:
|
|
603
|
+
|
|
604
|
+
```typescript
|
|
605
|
+
// Start a server that exposes git procedures
|
|
606
|
+
import "@procedures/git"; // registers its procedures
|
|
607
|
+
import { createPeer } from "@procedures/peer";
|
|
608
|
+
|
|
609
|
+
const peer = await createPeer({
|
|
610
|
+
id: "git-server",
|
|
611
|
+
transports: [{ type: "http", port: 3000 }],
|
|
612
|
+
autoRegister: true, // Includes all git.* procedures
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
await peer.start();
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
## Advanced Usage
|
|
619
|
+
|
|
620
|
+
### Custom Transport Configuration
|
|
621
|
+
|
|
622
|
+
```typescript
|
|
623
|
+
import express from "express";
|
|
624
|
+
import { createPeer } from "@procedures/peer";
|
|
625
|
+
|
|
626
|
+
// Use existing Express app
|
|
627
|
+
const app = express();
|
|
628
|
+
|
|
629
|
+
const peer = await createPeer({
|
|
630
|
+
id: "custom-server",
|
|
631
|
+
transports: [
|
|
632
|
+
{
|
|
633
|
+
type: "http",
|
|
634
|
+
port: 4000,
|
|
635
|
+
basePath: "/rpc",
|
|
636
|
+
cors: {
|
|
637
|
+
origin: ["http://localhost:3000"],
|
|
638
|
+
credentials: true,
|
|
639
|
+
},
|
|
640
|
+
},
|
|
641
|
+
],
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
await peer.start();
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
### Multiple Peers
|
|
648
|
+
|
|
649
|
+
Run multiple peers in the same process:
|
|
650
|
+
|
|
651
|
+
```typescript
|
|
652
|
+
import { createPeer } from "@procedures/peer";
|
|
653
|
+
|
|
654
|
+
const publicPeer = await createPeer({
|
|
655
|
+
id: "public-api",
|
|
656
|
+
transports: [{ type: "http", port: 3000 }],
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
const privatePeer = await createPeer({
|
|
660
|
+
id: "private-api",
|
|
661
|
+
transports: [{ type: "http", port: 4000 }],
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
await publicPeer.start();
|
|
665
|
+
await privatePeer.start();
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
### Procedure Filtering
|
|
669
|
+
|
|
670
|
+
Generate manifests for specific namespaces:
|
|
671
|
+
|
|
672
|
+
```typescript
|
|
673
|
+
import { generateJson } from "@procedures/peer";
|
|
674
|
+
|
|
675
|
+
// Only git procedures
|
|
676
|
+
const gitManifest = generateJson({ namespace: ["git"] });
|
|
677
|
+
|
|
678
|
+
// Only fs procedures
|
|
679
|
+
const fsManifest = generateJson({ namespace: ["fs"] });
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
## Error Handling
|
|
683
|
+
|
|
684
|
+
```typescript
|
|
685
|
+
import { connect } from "@procedures/peer";
|
|
686
|
+
|
|
687
|
+
try {
|
|
688
|
+
const connection = await connect({
|
|
689
|
+
address: "http://localhost:3000/api",
|
|
690
|
+
timeout: 5000,
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
// Use connection
|
|
694
|
+
} catch (error) {
|
|
695
|
+
if (error.code === "ECONNREFUSED") {
|
|
696
|
+
console.error("Server is not running");
|
|
697
|
+
} else if (error.message.includes("timeout")) {
|
|
698
|
+
console.error("Connection timed out");
|
|
699
|
+
} else {
|
|
700
|
+
console.error("Connection failed:", error);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
## Performance Considerations
|
|
706
|
+
|
|
707
|
+
- **HTTP Transport**: Best for RESTful APIs and simple request/response patterns
|
|
708
|
+
- **WebSocket Transport**: Best for real-time, bidirectional communication with low latency
|
|
709
|
+
- **Local Transport**: Best for in-process communication with zero network overhead
|
|
710
|
+
- **Auto-Registration**: Minimal overhead - procedures are registered once at startup
|
|
711
|
+
- **Discovery**: Procedures are announced once per connection, then cached
|
|
712
|
+
|
|
713
|
+
## License
|
|
714
|
+
|
|
715
|
+
MIT
|
|
716
|
+
|
|
717
|
+
## Repository
|
|
718
|
+
|
|
719
|
+
https://github.com/mark1russell7/client-server
|
|
720
|
+
|
|
721
|
+
## Related Packages
|
|
722
|
+
|
|
723
|
+
- `@procedures/client` - Core client/procedure system
|
|
724
|
+
- `@procedures/bundle-dev` - Development bundle including server procedures
|
|
725
|
+
- `@procedures/git` - Git procedure implementations
|
|
726
|
+
- `@procedures/fs` - Filesystem procedure implementations
|