@greendrake/rpc 0.3.0 → 0.5.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 +4 -4
- package/package.json +3 -3
- package/src/RpcClient.ts +2 -2
- package/src/errors.ts +1 -1
- package/src/liveBinding.ts +1 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @greendrake/rpc
|
|
2
2
|
|
|
3
|
-
Client for the `@greendrake/rpc` wire format, defined below
|
|
3
|
+
Client for the `@greendrake/rpc` wire format, defined below: a typed method-map facade (`RpcClient`), an HTTP transport and a reconnecting WebSocket transport with server push, the error classes both transports map response codes to, a TTL response cache, and a pluggable payload codec. Framework-free: loading state, error UX and connectivity belong to whatever UI binding is built on it.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -12,7 +12,7 @@ TypeScript source ships as-is (`src/main.ts` is the entry; no build step, no `.d
|
|
|
12
12
|
|
|
13
13
|
## The wire
|
|
14
14
|
|
|
15
|
-
This package
|
|
15
|
+
This package is the client end of one format, and this section defines it for both ends. It is deliberately not JSON-RPC. One request envelope, one response envelope, JSON on both transports:
|
|
16
16
|
|
|
17
17
|
```ts
|
|
18
18
|
interface RpcRequest {
|
|
@@ -178,7 +178,7 @@ The contract:
|
|
|
178
178
|
- **Apply or resync.** `apply` folds the push in and nothing else happens. Without it the push runs `resync` — so `{}` means "every such push re-reads". A handler with neither `apply` nor a `resync` to fall back on throws at binding time.
|
|
179
179
|
- **Reconnect.** `resync` also runs when the socket returns from a drop the binding witnessed: a connection has no memory, so what it missed is only recoverable by asking. The first connect after the binding is created is not a return from a drop. A binding without `resync` subscribes to nothing connection-related.
|
|
180
180
|
- **Coalescing.** One `resync` at a time; pushes arriving during a run collapse into a single follow-up after it, however many there are — they ask the same question.
|
|
181
|
-
- **No error policy.** The binding awaits `resync` only to know when the slot is free, and interprets neither outcome: `resync` owns its errors. It must also not be served by a response cache the missed pushes would have invalidated — invalidate the entries its read would hit, then read.
|
|
181
|
+
- **No error policy.** The binding awaits `resync` only to know when the slot is free, and interprets neither outcome: `resync` owns its errors. It must also not be served by a response cache the missed pushes would have invalidated — invalidate the entries its read would hit, then read.
|
|
182
182
|
- **Release.** The returned function detaches every subscription and drops any pending follow-up; calling it twice is harmless.
|
|
183
183
|
|
|
184
184
|
## Errors
|
|
@@ -215,7 +215,7 @@ cache.prime('taxonomy.tree', [{ taxonomy: 'category' }], pushed) // seed from a
|
|
|
215
215
|
cache.clear() // everything, e.g. when the session identity changes
|
|
216
216
|
```
|
|
217
217
|
|
|
218
|
-
`ttlFor(method)` returns the seconds for a listed method, `false` otherwise. `CacheConfig` and `CacheLookup` are the config and `get` result types. `RpcClient` holds no cache;
|
|
218
|
+
`ttlFor(method)` returns the seconds for a listed method, `false` otherwise. `CacheConfig` and `CacheLookup` are the config and `get` result types. `RpcClient` holds no cache; a client that composes one derives its nonce rule from the same endpoint list.
|
|
219
219
|
|
|
220
220
|
## Codec
|
|
221
221
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@greendrake/rpc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "RPC client over JSON: typed method-map API, HTTP and reconnecting WebSocket transports, pluggable codec and headers, TTL response cache",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Eugene Greendrake <eugene@greendrake.nz>",
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
},
|
|
35
35
|
"prettier": "@greendrake/dev-config/prettier",
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@greendrake/util": "0.
|
|
37
|
+
"@greendrake/util": "0.5.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@greendrake/dev-config": "0.
|
|
40
|
+
"@greendrake/dev-config": "0.5.0",
|
|
41
41
|
"typescript": "6.0.3"
|
|
42
42
|
}
|
|
43
43
|
}
|
package/src/RpcClient.ts
CHANGED
|
@@ -21,8 +21,8 @@ export class RpcClient<M extends MethodMapConstraint<M> = MethodMap> {
|
|
|
21
21
|
// The one way to invoke a method; every request carries a nonce for
|
|
22
22
|
// server-side dedup. Omitting the nonce is only worth doing where a
|
|
23
23
|
// response cache needs byte-identical requests to key on, and this client
|
|
24
|
-
// holds no cache —
|
|
25
|
-
//
|
|
24
|
+
// holds no cache — a client composing one owns that rule, derived from the
|
|
25
|
+
// single list of cacheable methods it is configured with.
|
|
26
26
|
call<K extends keyof M & string>(method: K, ...args: Parameters<M[K]>): Promise<Awaited<ReturnType<M[K]>>> {
|
|
27
27
|
return this.#invoke(true, method, args)
|
|
28
28
|
}
|
package/src/errors.ts
CHANGED
|
@@ -53,7 +53,7 @@ export class WebSocketClosedError extends NetworkError {
|
|
|
53
53
|
// socket went. A request that never left cannot have had an effect and is
|
|
54
54
|
// always safe to re-issue; one that was in flight may have executed
|
|
55
55
|
// server-side with only its response lost, so re-issuing it is a decision
|
|
56
|
-
// for the caller
|
|
56
|
+
// for the caller.
|
|
57
57
|
readonly inFlight: boolean
|
|
58
58
|
readonly #event: CloseEvent
|
|
59
59
|
|
package/src/liveBinding.ts
CHANGED
|
@@ -21,8 +21,7 @@ export interface LiveOptions<PEvents, PData> {
|
|
|
21
21
|
// It owns its own errors: the binding awaits it only to know when the slot
|
|
22
22
|
// is free, and interprets neither outcome. It must also not be served by a
|
|
23
23
|
// response cache the missed pushes would have invalidated — invalidate,
|
|
24
|
-
// then read
|
|
25
|
-
// for app code).
|
|
24
|
+
// then read.
|
|
26
25
|
resync?: () => Promise<unknown> | void
|
|
27
26
|
}
|
|
28
27
|
|