@greendrake/rpc 0.2.0 → 0.4.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @greendrake/rpc
2
2
 
3
- Client for the `@greendrake/rpc` wire format, defined below and served by [`@greendrake/rpc-server`](../rpc-server): 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; the Vue/Pinia binding (loading state, error UX, connectivity) is `@greendrake/vue-api`, built on this package.
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 and `@greendrake/rpc-server` are the two ends of one format; this section defines it. It is deliberately not JSON-RPC. One request envelope, one response envelope, JSON on both transports:
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. (`@greendrake/vue-api`'s `bindLive` carries both rules for app code.)
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; `@greendrake/vue-api`'s `ApiClient` composes one and derives its nonce rule from the same endpoint list.
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.2.0",
3
+ "version": "0.4.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.2.0"
37
+ "@greendrake/util": "0.4.0"
38
38
  },
39
39
  "devDependencies": {
40
- "@greendrake/dev-config": "0.2.0",
40
+ "@greendrake/dev-config": "0.4.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 — @greendrake/vue-api's ApiClient owns that rule, derived
25
- // from the single list of cacheable methods it is configured with.
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 (see ApiClient's offline park).
56
+ // for the caller.
57
57
  readonly inFlight: boolean
58
58
  readonly #event: CloseEvent
59
59
 
@@ -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 (see @greendrake/vue-api's bindLive, which carries that policy
25
- // for app code).
24
+ // then read.
26
25
  resync?: () => Promise<unknown> | void
27
26
  }
28
27