@spider-mesh/core 2.0.30 → 2.0.37

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 (79) hide show
  1. package/README.md +595 -0
  2. package/build/src/RemoteService.d.ts +1 -1
  3. package/build/src/RemoteService.js.map +1 -1
  4. package/build/src/SpiderMesh.d.ts +2 -2
  5. package/build/src/SpiderMesh.js +282 -115
  6. package/build/src/SpiderMesh.js.map +1 -1
  7. package/build/src/decorators/Microservice.d.ts +1 -1
  8. package/build/src/decorators/Microservice.js.map +1 -1
  9. package/build/src/helpers/GetIps.js +15 -8
  10. package/build/src/helpers/GetIps.js.map +1 -1
  11. package/build/src/helpers/LimitConcurrency.js +5 -2
  12. package/build/src/helpers/LimitConcurrency.js.map +1 -1
  13. package/build/src/helpers/randomUUID.d.ts +1 -1
  14. package/build/src/helpers/randomUUID.js +1 -1
  15. package/build/src/helpers/randomUUID.js.map +1 -1
  16. package/build/src/index.d.ts +1 -0
  17. package/build/src/types.d.ts +102 -0
  18. package/build/src/types.js +2 -0
  19. package/build/src/types.js.map +1 -0
  20. package/build/tsconfig.tsbuildinfo +1 -1
  21. package/package.json +4 -4
  22. package/tsconfig.json +3 -1
  23. package/build/src/abstract/DiscoveryTransporter.d.ts +0 -5
  24. package/build/src/abstract/DiscoveryTransporter.js +0 -3
  25. package/build/src/abstract/DiscoveryTransporter.js.map +0 -1
  26. package/build/src/abstract/PubsubTransporter.d.ts +0 -11
  27. package/build/src/abstract/PubsubTransporter.js +0 -3
  28. package/build/src/abstract/PubsubTransporter.js.map +0 -1
  29. package/build/src/abstract/RemoteService.d.ts +0 -35
  30. package/build/src/abstract/RemoteService.js +0 -107
  31. package/build/src/abstract/RemoteService.js.map +0 -1
  32. package/build/src/abstract/RpcTransporter.d.ts +0 -30
  33. package/build/src/abstract/RpcTransporter.js +0 -3
  34. package/build/src/abstract/RpcTransporter.js.map +0 -1
  35. package/build/src/abstract/SpiderMeshNode.d.ts +0 -18
  36. package/build/src/abstract/SpiderMeshNode.js +0 -2
  37. package/build/src/abstract/SpiderMeshNode.js.map +0 -1
  38. package/build/src/abstracts/DiscoveryTransporter.d.ts +0 -5
  39. package/build/src/abstracts/DiscoveryTransporter.js +0 -3
  40. package/build/src/abstracts/DiscoveryTransporter.js.map +0 -1
  41. package/build/src/abstracts/PubsubTransporter.d.ts +0 -11
  42. package/build/src/abstracts/PubsubTransporter.js +0 -3
  43. package/build/src/abstracts/PubsubTransporter.js.map +0 -1
  44. package/build/src/abstracts/RemoteService.d.ts +0 -38
  45. package/build/src/abstracts/RemoteService.js +0 -105
  46. package/build/src/abstracts/RemoteService.js.map +0 -1
  47. package/build/src/abstracts/RpcTransporter.d.ts +0 -30
  48. package/build/src/abstracts/RpcTransporter.js +0 -3
  49. package/build/src/abstracts/RpcTransporter.js.map +0 -1
  50. package/build/src/abstracts/SpiderMeshNode.d.ts +0 -18
  51. package/build/src/abstracts/SpiderMeshNode.js +0 -2
  52. package/build/src/abstracts/SpiderMeshNode.js.map +0 -1
  53. package/build/src/helpers/MicroserviceNotFound copy.d.ts +0 -5
  54. package/build/src/helpers/MicroserviceNotFound copy.js +0 -8
  55. package/build/src/helpers/MicroserviceNotFound copy.js.map +0 -1
  56. package/build/src/helpers/MicroserviceNotFound.d.ts +0 -5
  57. package/build/src/helpers/MicroserviceNotFound.js +0 -8
  58. package/build/src/helpers/MicroserviceNotFound.js.map +0 -1
  59. package/build/src/helpers/MicroserviceOfflineException.d.ts +0 -5
  60. package/build/src/helpers/MicroserviceOfflineException.js +0 -8
  61. package/build/src/helpers/MicroserviceOfflineException.js.map +0 -1
  62. package/build/src/helpers/MicroserviceRpcTimeout.d.ts +0 -5
  63. package/build/src/helpers/MicroserviceRpcTimeout.js +0 -8
  64. package/build/src/helpers/MicroserviceRpcTimeout.js.map +0 -1
  65. package/build/src/interfaces/DiscoveryTransporter.d.ts +0 -5
  66. package/build/src/interfaces/DiscoveryTransporter.js +0 -3
  67. package/build/src/interfaces/DiscoveryTransporter.js.map +0 -1
  68. package/build/src/interfaces/PubsubTransporter.d.ts +0 -11
  69. package/build/src/interfaces/PubsubTransporter.js +0 -3
  70. package/build/src/interfaces/PubsubTransporter.js.map +0 -1
  71. package/build/src/interfaces/RemoteService.d.ts +0 -35
  72. package/build/src/interfaces/RemoteService.js +0 -107
  73. package/build/src/interfaces/RemoteService.js.map +0 -1
  74. package/build/src/interfaces/RpcTransporter.d.ts +0 -30
  75. package/build/src/interfaces/RpcTransporter.js +0 -3
  76. package/build/src/interfaces/RpcTransporter.js.map +0 -1
  77. package/build/src/interfaces/SpiderMeshNode.d.ts +0 -18
  78. package/build/src/interfaces/SpiderMeshNode.js +0 -2
  79. package/build/src/interfaces/SpiderMeshNode.js.map +0 -1
package/README.md ADDED
@@ -0,0 +1,595 @@
1
+ # Spider Mesh Core
2
+
3
+ `@spider-mesh/core` is a lightweight TypeScript microservice core for service-to-service RPC, pubsub events, and node discovery with pluggable transporters.
4
+
5
+ It provides:
6
+
7
+ - Decorator-based local service registration
8
+ - Typed remote service linking through a Proxy
9
+ - Stream-first RPC over transporter-managed byte delivery
10
+ - Discovery and pubsub integration through simple transporter contracts
11
+ - Transporter contracts that can be implemented directly or consumed through companion transport packages such as `@spider-mesh/tcp` and `@spider-mesh/ws`
12
+ - NestJS adapters for exposing and consuming services
13
+
14
+ ## Package Boundary
15
+
16
+ Spider Mesh is now split into two main package layers:
17
+
18
+ - `@spider-mesh/core`: runtime-agnostic service runtime, decorators, linking, and shared contracts
19
+ - companion transport packages: concrete transport implementations such as `@spider-mesh/tcp` and `@spider-mesh/ws`
20
+
21
+ If you are reading this package first, the practical rule is simple:
22
+
23
+ - stay in `@spider-mesh/core` for service code and runtime code
24
+ - add a companion transport package only when you explicitly need a concrete transport implementation
25
+
26
+ ## Install
27
+
28
+ ```bash
29
+ bun add @spider-mesh/core rxjs reflect-metadata
30
+ ```
31
+
32
+ This package is ESM-only.
33
+
34
+ Practical implications:
35
+
36
+ - published output is loaded as ESM through the root export map
37
+ - repository TypeScript uses `module: NodeNext` and `moduleResolution: NodeNext`
38
+ - internal relative imports use emitted `.js` specifiers, for example `./SpiderMesh.js`
39
+ - avoid CommonJS patterns such as `require()` when adding new runtime code
40
+
41
+ ## AI Usage Guide
42
+
43
+ Use this section as the canonical decision guide when generating code with AI tools.
44
+
45
+ ### Environment support matrix
46
+
47
+ | Runtime | `@spider-mesh/core` | `@spider-mesh/tcp` | `@spider-mesh/ws` |
48
+ | --- | --- | --- | --- |
49
+ | Node.js | Supported | Supported | Supported |
50
+ | Bun | Supported | Supported | Supported |
51
+ | Browser | Partially supported, depends on your custom transporter | Not recommended | Not recommended |
52
+ | React Native | Supported for the core entry only | Not recommended | Not recommended |
53
+
54
+ ### Recommended imports
55
+
56
+ Use these imports exactly.
57
+
58
+ - Core runtime, decorators, RPC linking, NestJS helpers: `import { ... } from '@spider-mesh/core'`
59
+ - Shared transporter contracts and runtime APIs: `import { ... } from '@spider-mesh/core'`
60
+ - Companion TCP transport implementation when needed: `import { Http2Rpc, Http2Pubsub, UdpDiscovery } from '@spider-mesh/tcp'`
61
+ - Companion WebSocket transport implementation when needed: `import { WebsocketTransporter } from '@spider-mesh/ws'`
62
+
63
+ ### When to use what
64
+
65
+ - Use `SpiderMesh` when you need a local runtime that can expose services, discover nodes, publish events, or call remote services.
66
+ - Use `@Microservice()` on local classes that should be callable remotely.
67
+ - Use `RemoteServiceLinker.link()` when you need a typed remote proxy for another service.
68
+ - Use transporter contracts from `@spider-mesh/core` when you are implementing or typing your own transport.
69
+ - Use `@spider-mesh/tcp` or `@spider-mesh/ws` when you want a companion transport package.
70
+ - Use a custom transporter when the runtime is not Node.js or Bun, or when you need a different protocol.
71
+
72
+ ### Do and don't
73
+
74
+ Do:
75
+
76
+ - Import runtime-agnostic APIs from `@spider-mesh/core`.
77
+ - Import transporter contracts from `@spider-mesh/core` when you need transport typing.
78
+ - Use a companion transport package such as `@spider-mesh/tcp` or `@spider-mesh/ws` when you need a ready-made transport implementation.
79
+ - Wait for remote service availability with `wait()` before making calls in startup flows.
80
+ - Treat companion package examples and e2e tests as canonical usage references for concrete transport behavior.
81
+
82
+ Don't:
83
+
84
+ - Do not assume `@spider-mesh/core` exports every concrete transporter.
85
+ - Do not assume `@spider-mesh/tcp` is React Native-ready.
86
+ - Do not assume `@spider-mesh/ws` is React Native-ready.
87
+ - Do not couple service code to a single transport package unless that is intentional.
88
+ - Do not call remote services before the target service has been discovered unless you intentionally rely on retry behavior.
89
+
90
+ ### Canonical recipes
91
+
92
+ Provider recipe:
93
+
94
+ 1. Import `Microservice` and `SpiderMesh` from `@spider-mesh/core`.
95
+ 2. Choose a concrete transporter implementation, for example from `@spider-mesh/tcp` or `@spider-mesh/ws`.
96
+ 3. Define a class and decorate it with `@Microservice()`.
97
+ 4. Instantiate the service class.
98
+ 5. Create `new SpiderMesh({ transporters: [transporter] })`.
99
+
100
+ Client recipe:
101
+
102
+ 1. Import `SpiderMesh` and `RemoteServiceLinker` from `@spider-mesh/core`.
103
+ 2. Choose a concrete transporter implementation, for example from `@spider-mesh/tcp` or `@spider-mesh/ws`.
104
+ 3. Create `new SpiderMesh({ transporters: [transporter] })`.
105
+ 4. Create a typed remote proxy with `RemoteServiceLinker.link()`.
106
+ 5. Call `await proxy.wait()` before the first RPC call.
107
+
108
+ Companion transport package recipes:
109
+
110
+ TCP:
111
+
112
+ 1. Import `UdpDiscovery`, `Http2Rpc`, and `Http2Pubsub` from `@spider-mesh/tcp`.
113
+ 2. Add those transporters to `new SpiderMesh({ transporters: [...] })`.
114
+ 3. Let the TCP package handle discovery, RPC, and pubsub transport.
115
+
116
+ WebSocket:
117
+
118
+ 1. Import `WebsocketTransporter` from `@spider-mesh/ws`.
119
+ 2. Add that transporter to `new SpiderMesh({ transporters: [...] })`.
120
+ 3. Run `WebsocketRelayServer` from `@spider-mesh/ws/relay-server` when using the WebSocket companion package.
121
+
122
+ ### AI-safe assumptions
123
+
124
+ An AI agent should assume the following unless the codebase says otherwise:
125
+
126
+ - The root package entry is the safe default for shared runtime APIs.
127
+ - Concrete transports are opt-in through companion packages or custom implementations.
128
+ - Transporter contracts come from the core package.
129
+ - The companion TCP and WebSocket packages are sibling transport options for Node.js and Bun runtimes.
130
+ - If the target runtime is React Native, prefer the core APIs and a runtime-appropriate custom transporter.
131
+
132
+ ## Core Model
133
+
134
+ `SpiderMesh` is the runtime coordinator.
135
+
136
+ It keeps track of:
137
+
138
+ - The current node metadata
139
+ - Local service instances registered in the process
140
+ - Remote nodes discovered from discovery transporters
141
+ - RPC-capable nodes for each service
142
+ - RPC pending and running stream state
143
+ - Pubsub, RPC, and discovery transporters
144
+
145
+ ## Quick Start
146
+
147
+ ### 1. Define a local microservice
148
+
149
+ ```ts
150
+ import { BeforeMicroserviceOnline, Microservice } from '@spider-mesh/core'
151
+
152
+ @Microservice({ version: '1.0.0' })
153
+ export class UserService {
154
+ private ready = false
155
+
156
+ @BeforeMicroserviceOnline()
157
+ async warmup() {
158
+ this.ready = true
159
+ }
160
+
161
+ async getUser(id: string) {
162
+ if (!this.ready) throw new Error('Service not ready')
163
+ return { id, name: 'Ada' }
164
+ }
165
+ }
166
+ ```
167
+
168
+ `@Microservice()` registers the instance into Spider Mesh when the class is constructed.
169
+
170
+ `@BeforeMicroserviceOnline()` marks async setup methods that must complete before the service is exposed in local metadata.
171
+
172
+ ### 2. Create the runtime
173
+
174
+ ```ts
175
+ import { SpiderMesh } from '@spider-mesh/core'
176
+ import { AppDiscoveryTransporter } from './AppDiscoveryTransporter.js'
177
+ import { AppRpcTransporter } from './AppRpcTransporter.js'
178
+ import { AppPubsubTransporter } from './AppPubsubTransporter.js'
179
+
180
+ const mesh = new SpiderMesh({
181
+ transporters: [
182
+ AppDiscoveryTransporter,
183
+ AppRpcTransporter,
184
+ AppPubsubTransporter,
185
+ ],
186
+ })
187
+ ```
188
+
189
+ These transporter class names are application-local examples, not exports from `@spider-mesh/core`.
190
+
191
+ Transporter capability is inferred by method shape:
192
+
193
+ - `send()` means RPC transporter
194
+ - `publish()` means pubsub transporter
195
+ - `broadcast()` means discovery transporter
196
+
197
+ You can pass either transporter classes or already-created transporter instances into `transporters`.
198
+
199
+ ### 2a. Use companion transport packages
200
+
201
+ Spider Mesh can work with companion transport packages such as `@spider-mesh/tcp` and `@spider-mesh/ws`.
202
+
203
+ The root package entry exports the runtime-agnostic APIs and shared transporter contracts. Concrete transport implementations can be imported from companion packages when needed.
204
+
205
+ Create a runtime using the TCP package:
206
+
207
+ ```ts
208
+ import { SpiderMesh } from '@spider-mesh/core'
209
+ import { Http2Pubsub, Http2Rpc, UdpDiscovery } from '@spider-mesh/tcp'
210
+
211
+ const mesh = new SpiderMesh({
212
+ transporters: [
213
+ new UdpDiscovery(),
214
+ new Http2Rpc(),
215
+ new Http2Pubsub(),
216
+ ],
217
+ })
218
+ ```
219
+
220
+ Or use the WebSocket package:
221
+
222
+ ```ts
223
+ import { SpiderMesh } from '@spider-mesh/core'
224
+ import { WebsocketTransporter } from '@spider-mesh/ws'
225
+
226
+ const transporter = new WebsocketTransporter({
227
+ heartbeatIntervalMs: 5000,
228
+ reconnectIntervalMs: 1000,
229
+ })
230
+
231
+ transporter.connect('ws://127.0.0.1:8787')
232
+
233
+ const mesh = new SpiderMesh({
234
+ transporters: [transporter],
235
+ })
236
+ ```
237
+
238
+ Both patterns keep service/runtime code in `@spider-mesh/core` while delegating concrete transport behavior to a companion package.
239
+
240
+ ### 2b. Minimal working startup order
241
+
242
+ When using a discovery-based transport package, the canonical startup order is:
243
+
244
+ 1. Start one or more provider processes that register local `@Microservice()` classes.
245
+ 2. Start client processes.
246
+ 3. Wait for discovery to converge.
247
+ 4. In clients, call `await remote.wait()` before the first remote method call.
248
+
249
+ If an AI agent needs one default operational pattern, use this startup order.
250
+
251
+ ### 3. Call a remote service
252
+
253
+ ```ts
254
+ import { RemoteServiceLinker } from '@spider-mesh/core'
255
+
256
+ type UserServiceContract = {
257
+ getUser(id: string): Promise<{ id: string; name: string }>
258
+ }
259
+
260
+ const users = RemoteServiceLinker.link<UserServiceContract>(mesh, {
261
+ service: 'UserService',
262
+ })
263
+
264
+ await users.wait()
265
+
266
+ const user = await users.getUser('42')
267
+ console.log(user.name)
268
+ ```
269
+
270
+ Remote methods are exposed through a typed Proxy.
271
+
272
+ ## RPC Behavior
273
+
274
+ ### Awaitable observable calls
275
+
276
+ Remote method calls return an RxJS observable that is also awaitable.
277
+
278
+ ```ts
279
+ const user = await users.getUser('42')
280
+ ```
281
+
282
+ ```ts
283
+ users.getUser('42').subscribe(user => {
284
+ console.log(user)
285
+ })
286
+ ```
287
+
288
+ ### Stream-first RPC
289
+
290
+ Spider Mesh treats every RPC response as a stream.
291
+
292
+ - If a local method returns an `Observable`, each emission is forwarded to the caller.
293
+ - If a local method returns a `Promise` or plain value, it is sent as one `data` event with `completed: true`.
294
+ - If the caller unsubscribes early, Spider Mesh sends a `cancel` packet so the remote node can stop the running stream.
295
+
296
+ ### Per-link defaults
297
+
298
+ ```ts
299
+ const resilientUsers = users.set({
300
+ timeout: 3000,
301
+ retry: 2,
302
+ fallback: { id: 'fallback', name: 'Unknown' },
303
+ })
304
+
305
+ const user = await resilientUsers.getUser('42')
306
+ ```
307
+
308
+ Supported RPC options:
309
+
310
+ - `service`: remote service name
311
+ - `method`: remote method name
312
+ - `args`: positional arguments
313
+ - `timeout`: timeout per inactivity window in milliseconds
314
+ - `retry`: retry count for offline errors
315
+ - `fallback`: fallback value when the call fails
316
+ - `node_id`: force routing to a specific node
317
+ - `ip`: force routing to a specific node IP
318
+
319
+ ### Waiting and watching
320
+
321
+ ```ts
322
+ await users.wait(nodes => nodes.length >= 2)
323
+
324
+ users.watch().subscribe(nodes => {
325
+ console.log(nodes.map(node => node.node_id))
326
+ })
327
+
328
+ console.log(users.nodes)
329
+ ```
330
+
331
+ `wait()` resolves when a service availability condition is met.
332
+
333
+ `watch()` streams matching nodes whenever topology changes.
334
+
335
+ `nodes` returns the current RPC-capable node list for that service.
336
+
337
+ ### Fan-out calls across all nodes
338
+
339
+ ```ts
340
+ users.__batch__getUser('42').subscribe(result => {
341
+ console.log(result)
342
+ })
343
+ ```
344
+
345
+ Each emission is either:
346
+
347
+ - `{ node, data }`
348
+ - `{ node, error }`
349
+
350
+ ## Events
351
+
352
+ `SpiderMesh.linkEvent()` binds a topic using the event class name.
353
+
354
+ ```ts
355
+ class UserCreatedEvent {
356
+ constructor(
357
+ public readonly id: string,
358
+ public readonly email: string,
359
+ ) {}
360
+ }
361
+
362
+ const userCreated = mesh.linkEvent(UserCreatedEvent)
363
+
364
+ await userCreated.publish(new UserCreatedEvent('42', 'ada@example.com'))
365
+
366
+ userCreated.listen().subscribe(event => {
367
+ console.log(event.id)
368
+ })
369
+ ```
370
+
371
+ ## NestJS Integration
372
+
373
+ ### Register `SpiderMesh` as a provider
374
+
375
+ ```ts
376
+ import { Module } from '@nestjs/common'
377
+ import { SpiderMesh } from '@spider-mesh/core'
378
+ import { Http2Pubsub, Http2Rpc, UdpDiscovery } from '@spider-mesh/tcp'
379
+
380
+ @Module({
381
+ providers: [
382
+ SpiderMesh.asProvider({
383
+ transporters: [
384
+ UdpDiscovery,
385
+ Http2Rpc,
386
+ Http2Pubsub,
387
+ ],
388
+ }),
389
+ ],
390
+ exports: [SpiderMesh],
391
+ })
392
+ export class MeshModule {}
393
+ ```
394
+
395
+ ### Expose a NestJS service as a microservice
396
+
397
+ ```ts
398
+ import { Injectable, Module } from '@nestjs/common'
399
+ import { NestJSExposeMicroservice } from '@spider-mesh/core'
400
+
401
+ @Injectable()
402
+ export class BillingService {
403
+ async charge(orderId: string) {
404
+ return { orderId, status: 'ok' }
405
+ }
406
+ }
407
+
408
+ @Module({
409
+ providers: [
410
+ BillingService,
411
+ NestJSExposeMicroservice(BillingService, { boundedContext: 'billing' }),
412
+ ],
413
+ })
414
+ export class BillingModule {}
415
+ ```
416
+
417
+ ### Inject a remote service proxy in NestJS
418
+
419
+ ```ts
420
+ import { Inject, Injectable, Module } from '@nestjs/common'
421
+ import { NestJSLinkMicroservice } from '@spider-mesh/core'
422
+
423
+ class BillingService {
424
+ charge(orderId: string): Promise<{ orderId: string; status: string }> {
425
+ throw new Error('typing only')
426
+ }
427
+ }
428
+
429
+ @Injectable()
430
+ export class CheckoutService {
431
+ constructor(
432
+ @Inject(BillingService)
433
+ private readonly billing: BillingService,
434
+ ) {}
435
+
436
+ async checkout(orderId: string) {
437
+ return this.billing.charge(orderId)
438
+ }
439
+ }
440
+
441
+ @Module({
442
+ providers: [
443
+ NestJSLinkMicroservice(BillingService),
444
+ CheckoutService,
445
+ ],
446
+ })
447
+ export class CheckoutModule {}
448
+ ```
449
+
450
+ ### Inject an event binding in NestJS
451
+
452
+ ```ts
453
+ import { Inject, Injectable, Module } from '@nestjs/common'
454
+ import { NestJSLinkEvent } from '@spider-mesh/core'
455
+
456
+ class UserCreatedEvent {
457
+ constructor(public readonly id: string) {}
458
+ }
459
+
460
+ @Injectable()
461
+ export class AuditService {
462
+ constructor(
463
+ @Inject(UserCreatedEvent)
464
+ private readonly userCreated: {
465
+ publish(data: UserCreatedEvent): Promise<void>
466
+ listen(): any
467
+ },
468
+ ) {}
469
+ }
470
+
471
+ @Module({
472
+ providers: [
473
+ NestJSLinkEvent(UserCreatedEvent),
474
+ AuditService,
475
+ ],
476
+ })
477
+ export class AuditModule {}
478
+ ```
479
+
480
+ ## Transporter Contract
481
+
482
+ Concrete transport implementations can live in companion packages such as `@spider-mesh/tcp` and `@spider-mesh/ws`, or in your own application code.
483
+
484
+ You can also provide your own classes that implement one or more transporter contracts exported by `@spider-mesh/core`.
485
+
486
+ ### Public API map
487
+
488
+ - `SpiderMesh`: runtime coordinator for services, events, discovery, and transporters
489
+ - `RemoteServiceLinker.link()`: creates a typed remote proxy
490
+ - `@Microservice()`: exposes a local class instance as a remote service
491
+ - `SpiderMesh.linkEvent()`: creates a topic binding for publish and subscribe
492
+ - `RpcTransporter`: RPC transporter contract
493
+ - `DiscoveryTransporter`: discovery transporter contract
494
+ - `PubsubTransporter`: pubsub transporter contract
495
+
496
+ ### RPC transporter
497
+
498
+ ```ts
499
+ type RpcMessage = {
500
+ node_id: string
501
+ packet: RpcPacket
502
+ }
503
+
504
+ type RpcEvent = Partial<{
505
+ rpc: RpcMessage
506
+ offline: string
507
+ endpoints: Record<string, string | boolean | number>
508
+ }>
509
+
510
+ type RpcTransporter = Observable<RpcEvent> & {
511
+ send(data: RpcPacket, node: SpiderMeshNode): Promise<void>
512
+ }
513
+ ```
514
+
515
+ The RPC observable can emit:
516
+
517
+ - `rpc`: inbound RPC message shaped as `{ node_id, packet }`
518
+ - `offline`: node offline event
519
+ - `endpoints`: transporter metadata to attach to the current node
520
+
521
+ The internal RPC wire protocol supports:
522
+
523
+ - `request`
524
+ - `response`
525
+ - `cancel`
526
+
527
+ `response` packets can carry:
528
+
529
+ - `data`
530
+ - `error`
531
+ - `completed`
532
+
533
+ ### Discovery transporter
534
+
535
+ ```ts
536
+ type DiscoveryEvent = {
537
+ discovered: SpiderMeshNode
538
+ }
539
+
540
+ type DiscoveryTransporter = Observable<DiscoveryEvent> & {
541
+ broadcast(
542
+ data: MdnsMessage<NodeMetadata>,
543
+ ips: string[],
544
+ ): Promise<void>
545
+ }
546
+ ```
547
+
548
+ Discovery transporters stream remote node snapshots into the mesh, and `SpiderMesh` itself calls `broadcast()` whenever local node metadata changes.
549
+
550
+ ### Pubsub transporter
551
+
552
+ ```ts
553
+ type PubsubTransporter = {
554
+ publish<T>(topic: string, data: T): Promise<void>
555
+ listen<T>(topic: string): Observable<T>
556
+ }
557
+ ```
558
+
559
+ ## Error Model
560
+
561
+ The core defines these error codes for RPC flows:
562
+
563
+ - `MICROSERVICE_OFFLINE`
564
+ - `MICROSERVICE_NOT_FOUND`
565
+ - `MICROSERVICE_RPC_TIMEOUT`
566
+
567
+ ## Environment Variables
568
+
569
+ - `SPIDERMESH_NAMESPACE`: namespace of the current node, default `default`
570
+ - `SPIDERMESH_NODE_HOSTNAME`: optional hostname attached to node metadata
571
+
572
+ ## Helpers
573
+
574
+ The package also exports:
575
+
576
+ - `LimitConcurrency(limit)` and `LimitConcurrentRunning(limit)` for throttling async method execution
577
+ - `randomUUID()` for Node.js, browser, and React Native compatible UUID generation using ESM-safe runtime detection
578
+ - `MicroserviceException` types for common RPC error codes
579
+
580
+ ## Build
581
+
582
+ ```bash
583
+ bun run build
584
+ ```
585
+
586
+ ## Notes
587
+
588
+ - Local services are registered when their class instances are constructed.
589
+ - Service identity is based on the class name.
590
+ - Event topic identity is based on the event class name.
591
+ - RPC target selection is round-robin unless you force `node_id` or `ip`.
592
+ - `SpiderMesh` owns RPC stream lifecycle, timeout, retry, and cancel behavior.
593
+ - Transporters focus on byte transport, pubsub topic IO, and discovery broadcasts.
594
+ - The root package entry intentionally focuses on runtime-agnostic APIs and shared contracts.
595
+ - If an AI agent is uncertain which import to use, prefer `@spider-mesh/core` first, then opt into a companion transport package such as `@spider-mesh/tcp` or `@spider-mesh/ws` only when a concrete transport is needed.
@@ -1,6 +1,6 @@
1
- import { RpcOptions, SpiderMeshNode } from "@spider-mesh/types";
2
1
  import { Observable } from "rxjs";
3
2
  import { ServiceChecker, SpiderMesh } from "./SpiderMesh.js";
3
+ import { RpcOptions, SpiderMeshNode } from "./types.js";
4
4
  export type IsUnknown<T, A, B> = unknown extends T ? ([T] extends [unknown] ? A : B) : B;
5
5
  export type RemoteServiceOptions = Partial<RpcOptions<any>> & {
6
6
  service: string;
@@ -1 +1 @@
1
- {"version":3,"file":"RemoteService.js","sourceRoot":"","sources":["../../src/RemoteService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"RemoteService.js","sourceRoot":"","sources":["../../src/RemoteService.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { Observable } from "rxjs";
2
- import { SpiderMeshNode, RpcTransporter, PubsubTransporter, DiscoveryTransporter, RpcOptions } from '@spider-mesh/types';
2
+ import { SpiderMeshNode, RpcTransporter, PubsubTransporter, DiscoveryTransporter, RpcOptions } from './types.js';
3
3
  export type HelloEvent = SpiderMeshNode & {
4
4
  back?: boolean;
5
5
  };
@@ -11,7 +11,7 @@ export type NodesMap = {
11
11
  export type SpiderMeshOptions = {
12
12
  transporters: Array<{
13
13
  new (): RpcTransporter | PubsubTransporter | DiscoveryTransporter;
14
- }>;
14
+ } | RpcTransporter | PubsubTransporter | DiscoveryTransporter>;
15
15
  };
16
16
  export declare class SpiderMesh {
17
17
  #private;