@shivaedev/contract 0.17.0 → 0.19.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 +34 -0
- package/README.md +68 -32
- package/dist/automaticLive.d.ts +2 -2
- package/dist/automaticLive.d.ts.map +1 -1
- package/dist/automaticLive.js +4 -3
- package/dist/automaticLive.js.map +1 -1
- package/dist/bind.d.ts +11 -2
- package/dist/bind.d.ts.map +1 -1
- package/dist/bind.js +9 -0
- package/dist/bind.js.map +1 -1
- package/dist/clientOptions.d.ts +23 -0
- package/dist/clientOptions.d.ts.map +1 -0
- package/dist/clientOptions.js +2 -0
- package/dist/clientOptions.js.map +1 -0
- package/dist/contract.d.ts +4 -2
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +6 -5
- package/dist/contract.js.map +1 -1
- package/dist/internal/bindingOwner.d.ts +1 -1
- package/dist/internal/bindingOwner.d.ts.map +1 -1
- package/dist/internal/clientOperations.d.ts.map +1 -1
- package/dist/internal/clientOperations.js +26 -7
- package/dist/internal/clientOperations.js.map +1 -1
- package/dist/internal/httpClient.d.ts +21 -0
- package/dist/internal/httpClient.d.ts.map +1 -0
- package/dist/internal/httpClient.js +13 -0
- package/dist/internal/httpClient.js.map +1 -0
- package/dist/internal/operationDeclaration.d.ts +19 -0
- package/dist/internal/operationDeclaration.d.ts.map +1 -0
- package/dist/internal/operationDeclaration.js +20 -0
- package/dist/internal/operationDeclaration.js.map +1 -0
- package/dist/internal/queryHints.d.ts +8 -0
- package/dist/internal/queryHints.d.ts.map +1 -0
- package/dist/internal/queryHints.js +34 -0
- package/dist/internal/queryHints.js.map +1 -0
- package/dist/live.d.ts +7 -1
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +2 -2
- package/dist/live.js.map +1 -1
- package/dist/makeLiveServer.d.ts +27 -1
- package/dist/makeLiveServer.d.ts.map +1 -1
- package/dist/makeLiveServer.js +15 -8
- package/dist/makeLiveServer.js.map +1 -1
- package/dist/operation.d.ts +13 -9
- package/dist/operation.d.ts.map +1 -1
- package/dist/operation.js +5 -19
- package/dist/operation.js.map +1 -1
- package/dist/publicConfig.d.ts +9 -3
- package/dist/publicConfig.d.ts.map +1 -1
- package/dist/publicConfig.js +2 -1
- package/dist/publicConfig.js.map +1 -1
- package/dist/querySubscription.d.ts +15 -0
- package/dist/querySubscription.d.ts.map +1 -0
- package/dist/querySubscription.js +10 -0
- package/dist/querySubscription.js.map +1 -0
- package/dist/readPolicy.d.ts +11 -6
- package/dist/readPolicy.d.ts.map +1 -1
- package/dist/readPolicy.js +16 -19
- package/dist/readPolicy.js.map +1 -1
- package/dist/readPolicyErrors.d.ts +13 -0
- package/dist/readPolicyErrors.d.ts.map +1 -0
- package/dist/readPolicyErrors.js +6 -0
- package/dist/readPolicyErrors.js.map +1 -0
- package/dist/serverMetadata.d.ts +29 -11
- package/dist/serverMetadata.d.ts.map +1 -1
- package/dist/serverMetadata.js +19 -12
- package/dist/serverMetadata.js.map +1 -1
- package/dist/testing.d.ts +51 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +17 -0
- package/dist/testing.js.map +1 -0
- package/package.json +6 -5
- package/src/automaticLive.ts +8 -3
- package/src/bind.ts +45 -3
- package/src/clientOptions.ts +35 -0
- package/src/contract.ts +11 -6
- package/src/internal/bindingOwner.ts +1 -1
- package/src/internal/clientOperations.ts +30 -11
- package/src/internal/httpClient.ts +21 -0
- package/src/internal/operationDeclaration.ts +28 -0
- package/src/internal/queryHints.ts +38 -0
- package/src/live.ts +2 -2
- package/src/makeLiveServer.ts +18 -12
- package/src/operation.ts +27 -37
- package/src/publicConfig.ts +2 -2
- package/src/querySubscription.ts +21 -0
- package/src/readPolicy.ts +23 -23
- package/src/readPolicyErrors.ts +4 -0
- package/src/serverMetadata.ts +35 -19
- package/src/testing.ts +41 -0
- package/dist/internal/makeHintPolicy.d.ts +0 -4
- package/dist/internal/makeHintPolicy.d.ts.map +0 -1
- package/dist/internal/makeHintPolicy.js +0 -25
- package/dist/internal/makeHintPolicy.js.map +0 -1
- package/dist/keys.d.ts +0 -34
- package/dist/keys.d.ts.map +0 -1
- package/dist/keys.js +0 -25
- package/dist/keys.js.map +0 -1
- package/src/internal/makeHintPolicy.ts +0 -40
- package/src/keys.ts +0 -62
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.19.0 - 2026-10-28
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `@shivaedev/contract/bind.ts` builds a bound HTTP RPC client and atom runtime from a contract and URL, with an inferred request transform for cookies or bearer tokens.
|
|
8
|
+
- `@shivaedev/react/client/useNow.ts` exports `useNow(interval, runtime?)` to render the runtime's Effect clock and refresh on the requested interval, including with TestClock.
|
|
9
|
+
- Declare collection policies beside module contracts with `ModuleReadPolicies` and combine them with `mergeReadPolicies`. Unclaimed collections are denied. Each policy receives the request's optional viewer.
|
|
10
|
+
- The application host accepts a merged `readPolicy` and checks queries and live hints inside native session middleware, using its resolved identity without another session lookup. Policies can use application services and return `Forbidden` or `AuthUnavailable`.
|
|
11
|
+
- Query authorization and live-hint filtering check keys concurrently so native `Effect.request` resolvers can batch membership checks. Plain Effect policies remain supported.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- Live queries accept inputs JSON cannot encode, such as bigint ids.
|
|
16
|
+
- Enforce declared query read policies at the hosted RPC handler boundary, including contracts without identity middleware, whose viewer is anonymous. Query RPC error schemas include `QueryReadDenied` so native clients receive typed refusals before handlers run.
|
|
17
|
+
- Keep collection methods and untyped schema internals from making data parameters appear to carry callable services. Direct service implementations, nested dependency fields and service arrays remain subject to `effect/service-parameters`.
|
|
18
|
+
|
|
19
|
+
### Breaking
|
|
20
|
+
|
|
21
|
+
- Move key imports from `@shivaedev/contract/keys.ts` to `@shivaedev/changes/keys.ts`. Declare bucket fields with `collection(name, idSchema, fields)` and publish affected buckets alongside record keys.
|
|
22
|
+
- Replace collection policy maps, `mergeReadPolicies`, `ReadPolicy` and `ReadPolicyMemoWindow` with each query's `readPolicy(payload, viewer)`. Declare the same query's live scope with `reads(payload, viewer)`. Bound query atoms and subscriptions refuse missing policies with a declaration error; one-off query `run` calls remain available. Denied queries refuse the entire subscription. Server adapters replace `QueryReads` and `ChangesReads` with `QueryDefinition` and `ChangesQueries`. Custom middleware calls `authorizeReads(effect, request, viewer)` and declares `MissingReadPolicy` and `QueryReadDenied` errors.
|
|
23
|
+
- Custom subscription adapters yield `ChangesQueries.resolve(references)`, call `querySubscription(requests, viewer)` and pass the authorized result to `makeLiveServer.subscribe(subscription, context)`. Metadata values expose `QueryDefinition.definition` and `CommandInvalidation.invalidates` instead of bare definitions and callbacks. Yield the Effect returned by `queryKeys(queries, references)` when projecting keys for a custom stream. `resolveChanges` supplies the authorized subscription in hosted applications. Changed hints can carry query positions so bindings can rerun session-scoped reads without deriving session scopes in the browser.
|
|
24
|
+
- Remove `appHost`'s `readPolicy` option and module policy registration. Session and permission middleware apply query policies using the current session viewer. Handle the new typed policy errors in native clients, including `QueryReadDenied` on query RPCs without identity middleware; widen explicit query error annotations accordingly.
|
|
25
|
+
- Replace `sessionCommandChanges` with `commandChanges` for custom session middleware. Command invalidation callbacks can receive the session viewer as their third argument. Announce viewer buckets there; background writers must explicitly publish those bucket keys after commit.
|
|
26
|
+
- Built-in admin queries declare their permission policies alongside their schemas and read scopes. Consumers keep supplying the existing session and permission middleware layers.
|
|
27
|
+
- Local Work Board and Fleet queries declare their existing loopback read access explicitly so their generated live subscriptions remain available.
|
|
28
|
+
- `authorizeReads` now takes `(effect, request, policy, viewer, denied)`, and policies take `(key, viewer)`. Pass `Option.some(resolvedIdentity)` or `Option.none()` before the denial effect. Existing unary policy functions may ignore the new viewer argument. Apps using `appHost` can replace custom read middleware with its `readPolicy` option and merge their modules' policy maps.
|
|
29
|
+
|
|
30
|
+
## 0.18.0 - 2026-10-27
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- SQL stories can declare domain read keys that cover written tables with `withChangeCoverage(body, { covers })` and assert committed change keys with `expectPublished(keys)`.
|
|
35
|
+
- Contract stories can observe a viewer's live stream with `watchHints` and use `heard(viewer, keys)` to await allowed hints or report denied keys as unheard on the story clock.
|
|
36
|
+
|
|
3
37
|
## 0.17.0 - 2026-10-27
|
|
4
38
|
|
|
5
39
|
### Added
|
package/README.md
CHANGED
|
@@ -7,13 +7,13 @@ Declare a feature's queries, commands, streams, expected failures and refresh de
|
|
|
7
7
|
A feature often repeats its inputs, results and errors on both sides of an RPC boundary, then separately wires which views a write should refresh. Those copies are easy to make disagree. Put the boundary and its dependencies together:
|
|
8
8
|
|
|
9
9
|
```ts
|
|
10
|
-
import { Schema } from "effect";
|
|
10
|
+
import { Effect, Schema } from "effect";
|
|
11
11
|
import { contract } from "@shivaedev/contract/contract.ts";
|
|
12
|
-
import { collection } from "@shivaedev/
|
|
12
|
+
import { collection } from "@shivaedev/changes/keys.ts";
|
|
13
13
|
import { command, query } from "@shivaedev/contract/operation.ts";
|
|
14
14
|
|
|
15
15
|
const notes = collection("notes", Schema.Number);
|
|
16
|
-
const List = query("list", { reads: () => [notes.list], success: Schema.Array(Schema.String) });
|
|
16
|
+
const List = query("list", { readPolicy: () => Effect.succeed(true), reads: () => [notes.list], success: Schema.Array(Schema.String) });
|
|
17
17
|
const Rename = command("rename", {
|
|
18
18
|
payload: { id: Schema.Number, title: Schema.String },
|
|
19
19
|
invalidates: ({ id }) => [notes.item(id)],
|
|
@@ -35,14 +35,36 @@ A **collection key** names a dependency. Its item key identifies one item; its l
|
|
|
35
35
|
|
|
36
36
|
Optional live hints use those same keys. A hint asks for another read; it does not supply a replacement value, a journal entry or proof that a query is fresh.
|
|
37
37
|
|
|
38
|
+
### Build an HTTP client
|
|
39
|
+
|
|
40
|
+
Use `makeClient` once per session to bind a contract to an HTTP endpoint:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { HttpClient, HttpClientRequest } from "effect/http";
|
|
44
|
+
import { makeClient } from "@shivaedev/contract/bind.ts";
|
|
45
|
+
import { Notes } from "./notes.ts";
|
|
46
|
+
|
|
47
|
+
const { api, runtime } = makeClient(Notes, {
|
|
48
|
+
url: "/rpc",
|
|
49
|
+
transformClient: (client) => HttpClient.mapRequest(
|
|
50
|
+
client,
|
|
51
|
+
HttpClientRequest.setHeader("authorization", "Bearer session-token"),
|
|
52
|
+
),
|
|
53
|
+
});
|
|
54
|
+
const note = api.get.query({ id: 1 });
|
|
55
|
+
const rename = runtime.fn(api.rename.run);
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The request transform is optional and its native HTTP client type is inferred. Tests can set cookie and Origin headers through the same option. The default transport uses Fetch and NDJSON; `httpClient` and `serialization` accept native Layers for another HTTP client or codec. `group` can supply a larger native RPC group containing the contract, such as an admin registry. The result is a native client Layer that a host can pass to `ManagedRuntime.make`. It also exposes the native `Client` service and a scoped `client` Effect for callers outside React. Session-scoped contracts require `registry` in the options, just as `bind` does.
|
|
59
|
+
|
|
38
60
|
### 1. Once per feature: schemas and operations
|
|
39
61
|
|
|
40
62
|
Keep the shared declaration in a module that both server and client can import:
|
|
41
63
|
|
|
42
64
|
```ts
|
|
43
|
-
import { Schema } from "effect";
|
|
65
|
+
import { Effect, Schema } from "effect";
|
|
44
66
|
import { contract } from "@shivaedev/contract/contract.ts";
|
|
45
|
-
import { collection } from "@shivaedev/
|
|
67
|
+
import { collection } from "@shivaedev/changes/keys.ts";
|
|
46
68
|
import { command, query } from "@shivaedev/contract/operation.ts";
|
|
47
69
|
import { fieldRejection } from "@shivaedev/contract/rejection.ts";
|
|
48
70
|
|
|
@@ -56,12 +78,14 @@ export class NoteMissing extends Schema.TaggedError<NoteMissing>()("NoteMissing"
|
|
|
56
78
|
export const notes = collection("notes", Note.fields.id);
|
|
57
79
|
|
|
58
80
|
export const Get = query("get", {
|
|
81
|
+
readPolicy: () => Effect.succeed(true),
|
|
59
82
|
payload: { id: Schema.Number },
|
|
60
83
|
success: Note,
|
|
61
84
|
rejections: { NoteMissing },
|
|
62
85
|
reads: ({ id }) => [notes.item(id)],
|
|
63
86
|
});
|
|
64
87
|
export const List = query("list", {
|
|
88
|
+
readPolicy: () => Effect.succeed(true),
|
|
65
89
|
success: Schema.Array(Note),
|
|
66
90
|
reads: () => [notes.list],
|
|
67
91
|
});
|
|
@@ -80,7 +104,7 @@ export const Create = command("create", {
|
|
|
80
104
|
export const Notes = contract("notes", { queries: [Get, List], commands: [Rename, Create] });
|
|
81
105
|
```
|
|
82
106
|
|
|
83
|
-
Save this module as `notes.ts`. The payload can be struct fields, as in `Get`, or a schema, as in `Create`. An omitted payload or success is `Schema.Void`; no declared rejections gives `Schema.Never`. The `reads`
|
|
107
|
+
Save this module as `notes.ts`. The payload can be struct fields, as in `Get`, or a schema, as in `Create`. An omitted payload or success is `Schema.Void`; no declared rejections gives `Schema.Never`. The server resolves `reads` with the decoded payload and session viewer. For local command dependencies, the browser also evaluates it with `Option.none()`; return no viewer keys for that case. Authorized subscription scopes always come from the server. `invalidates` receives the decoded payload, successful result and optional session viewer, so a create call can invalidate the ID the server assigned.
|
|
84
108
|
|
|
85
109
|
The collection's ID schema gives `item` its ID type. Here, `notes.item` takes a number. Query and command callbacks retain their payload and result types, including when the operations are declared inline inside `contract`.
|
|
86
110
|
|
|
@@ -91,7 +115,7 @@ Operation names must differ within a contract, including across queries, command
|
|
|
91
115
|
Import the shared expected failures from `@shivaedev/errors/taxonomy.ts`: `NotFound`, `Unauthorized`, `Forbidden`, `BadRequest`, `Conflict`, `PreconditionFailed`, `TooManyRequests`, `AuthUnavailable`, `InternalServerError` and `ServiceUnavailable`. Each class is a tagged error schema with a string `message`; `BadRequest` and `Conflict` also accept an optional string `field`. Declare only the failures an operation can return:
|
|
92
116
|
|
|
93
117
|
```ts
|
|
94
|
-
import { Schema } from "effect";
|
|
118
|
+
import { Effect, Schema } from "effect";
|
|
95
119
|
import { Rpc } from "effect/rpc";
|
|
96
120
|
import { BadRequest, Conflict } from "@shivaedev/errors/taxonomy.ts";
|
|
97
121
|
|
|
@@ -293,7 +317,7 @@ const self = api.self.query(undefined);
|
|
|
293
317
|
const save = api.save.run({ title: "My preferences" });
|
|
294
318
|
```
|
|
295
319
|
|
|
296
|
-
The examples use `Schema` and `Effect` from `effect`, `contract`, `query`, `command
|
|
320
|
+
The examples use `Schema` and `Effect` from `effect`, `contract`, `query`, `command` and `bind` from contract's defining modules, `collection` from `@shivaedev/changes/keys.ts`, and `Authenticated` from `@shivaedev/identity/middleware.ts`. `Client` is the application's native AtomRpc service. In React, obtain `registry` from the second argument to `SessionBoundary.connect`:
|
|
297
321
|
|
|
298
322
|
```tsx
|
|
299
323
|
import { SessionBoundary } from "@shivaedev/react/client/sessionBoundary.ts";
|
|
@@ -360,7 +384,7 @@ const changes = Stream.unwrap(NotesClient.use((client) =>
|
|
|
360
384
|
));
|
|
361
385
|
```
|
|
362
386
|
|
|
363
|
-
The contract includes the reserved stream's payload, `LiveHint` elements and middleware failures in its native RPC type. The subscription uses the contract's middleware and needs no separate RPC group or cast. The caller owns stream consumption and interruption. References name declared queries and reuse their payload schemas; payloadless queries use `{ query: "list", payload: undefined }`.
|
|
387
|
+
The contract includes the reserved stream's payload, `LiveHint` elements and middleware failures in its native RPC type. The subscription uses the contract's middleware and needs no separate RPC group or cast. The caller owns stream consumption and interruption. References name declared queries and reuse their payload schemas; payloadless queries use `{ query: "list", payload: undefined }`. Custom subscription handlers yield the Effect from the `ChangesQueries` annotation's `resolve(references)` method, call `querySubscription(requests, viewer)` and pass its authorized result to `makeLiveServer.subscribe(subscription, context)`. Hosted applications use `resolveChanges` from identity to supply that subscription. Session-scoped bindings track mounted queries per registry and drop their references on unmount or disposal. Ordinary bindings track query references when atoms are created.
|
|
364
388
|
|
|
365
389
|
For a custom transport or explicit pause/status controls, the native live APIs remain available:
|
|
366
390
|
|
|
@@ -448,52 +472,64 @@ Call the release functions and dispose the registry when the application's root
|
|
|
448
472
|
|
|
449
473
|
Import `makeLiveServer` from `@shivaedev/contract/makeLiveServer.ts` and create it once with the server's `Reactivity` service. After application authorization, return `hints.stream([orders.item(id)])` from the native streaming RPC handler. Each subscription starts with `Resync`; invalidating its read keys produces `Changed` with those declared keys. `hints.resync` sends `Resync` to every live stream owned by that helper, including streams for otherwise unrelated keys. Independent helpers keep their resync scopes separate even when they share Reactivity. The native stream owns registration and interruption. Keep this server helper separate from the browser's `live` coordinator.
|
|
450
474
|
|
|
451
|
-
|
|
475
|
+
### Query policies, record keys and buckets
|
|
452
476
|
|
|
453
|
-
|
|
454
|
-
import { authorizeReads } from "@shivaedev/contract/readPolicy.ts";
|
|
477
|
+
A query declares its decoded input, result, `readPolicy` and `reads` together. `readPolicy(payload, viewer)` returns an Effect boolean. `viewer` is the session's `Option<{ id: string }>`; the browser does not send the identity. Policies may use browser-safe Effect service tags whose implementations the server supplies.
|
|
455
478
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
479
|
+
```ts
|
|
480
|
+
import { Effect, Option, Schema } from "effect";
|
|
481
|
+
import { collection } from "@shivaedev/changes/keys.ts";
|
|
482
|
+
import { query } from "@shivaedev/contract/operation.ts";
|
|
483
|
+
|
|
484
|
+
const notes = collection("notes", Schema.Number, { userId: Schema.String });
|
|
485
|
+
const Mine = query("mine", {
|
|
486
|
+
payload: { title: Schema.String },
|
|
487
|
+
success: Schema.Array(Schema.String),
|
|
488
|
+
readPolicy: (_input, viewer) => Effect.succeed(Option.isSome(viewer)),
|
|
489
|
+
reads: (_input, viewer) => Option.isSome(viewer)
|
|
490
|
+
? [notes.bucket.userId(viewer.value.id)]
|
|
491
|
+
: [],
|
|
492
|
+
});
|
|
463
493
|
```
|
|
464
494
|
|
|
465
|
-
|
|
495
|
+
A record key, `notes.item(id)`, names one record. A bucket, `notes.bucket.userId(id)`, names every row with that field value. Declare bucket fields on the collection model with their schemas. A list may add title, state or other filters to its input and handler, but those filters never narrow its bucket. It reruns whenever any row in that bucket changes, including a row excluded by the filter. Writers explicitly announce the record and affected buckets with the same constructors from `@shivaedev/changes/keys.ts`.
|
|
466
496
|
|
|
467
|
-
|
|
497
|
+
The same query policy guards running the query and subscribing to it. A subscription names query references, never arbitrary record or bucket keys. The entire subscription is refused with `QueryReadDenied` if any referenced query is denied. Without `readPolicy`, a query has no authorized live subscription: `MissingReadPolicy` tells its author to declare one. Bound query atoms also refuse a missing policy before their first read. Ordinary one-off `run` calls remain available. Reads outside a declared query acquire no automatic subscription.
|
|
468
498
|
|
|
469
|
-
|
|
499
|
+
The session middleware supplies the viewer and runs `authorizeReads(effect, request, viewer)`. Custom middleware calls that function after resolving its session and declares `MissingReadPolicy` and `QueryReadDenied` in its error schema. Before delivering changed keys, the stream rechecks the owning query's policy without memoization. A client refresh runs the same authorized query that produced its first value; hints carry no row values.
|
|
470
500
|
|
|
471
|
-
|
|
501
|
+
### Live hints in stories
|
|
472
502
|
|
|
473
|
-
|
|
474
|
-
import { ReadPolicyMemoWindow } from "@shivaedev/contract/readPolicy.ts";
|
|
503
|
+
Use `watchHints` and `heard` from `@shivaedev/contract/testing.ts` in an application's story kit. Pass each viewer's authenticated live stream to `watchHints`; it starts a scoped subscription and waits for its first hint before returning the viewer handle. The contract's viewer story kit exposes these as `listen(viewer, queries)` and `heard(viewer, keys)`.
|
|
475
504
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
);
|
|
505
|
+
```ts
|
|
506
|
+
const alice = yield* watchHints(aliceChanges);
|
|
507
|
+
const bob = yield* watchHints(bobChanges);
|
|
508
|
+
yield* renameNote;
|
|
509
|
+
expect(yield* heard(alice, [notes.item(1)])).toBe(true);
|
|
510
|
+
expect(yield* heard(bob, [notes.item(1)], { within: "50 millis" })).toBe(false);
|
|
479
511
|
```
|
|
480
512
|
|
|
513
|
+
`heard` returns `true` once a delivered `Changed` hint contains all the requested keys, including hints received before the call. Extra keys are allowed; `Resync` does not count. It returns `false` when no matching hint arrives within `within` (one second by default). Waiting uses the story's Effect clock, so a test clock controls expiry. Stream failures stay in the typed error channel. Keep expectations in the spec; the support verbs need no retry loops or hidden assertions.
|
|
514
|
+
|
|
481
515
|
### API by module
|
|
482
516
|
|
|
483
517
|
Import the module that defines the name; the package has no root entry.
|
|
484
518
|
|
|
485
519
|
| Module | Functions and schemas |
|
|
486
520
|
| --- | --- |
|
|
487
|
-
| `operation.ts` | `query(name, { payload?, success?, rejections?, reads })`; `command(name, { payload?, success?, rejections?, invalidates })`; `stream(name, { payload?, success, rejections?, reads })`. |
|
|
521
|
+
| `operation.ts` | `query(name, { payload?, success?, rejections?, readPolicy?, reads })`; `command(name, { payload?, success?, rejections?, invalidates })`; `stream(name, { payload?, success, rejections?, reads })`. |
|
|
488
522
|
| `contract.ts` | `contract(name, { queries?, commands?, streams?, keyScope? })`, returning a native RPC group with `declaration: { name, queries, commands, streams, keyScope }`. |
|
|
489
523
|
| `rejection.ts` | `fieldRejection(struct, fields?)`; lower-level `rejectionSet(specs)`, which constructs the rejection classes, union schema and failure helpers used by operations. |
|
|
490
|
-
| `keys.ts` | `collection(name, idSchema)`; `Key` schema; `readKeys(keys, context?)` and `invalidationKeys(keys, context?)`. |
|
|
491
524
|
| `bind.ts` | `bind(contract, atomRpcService, { registry }?)`, requiring the registry for session-scoped contracts and exposing `{ query, run }` for queries, `{ run }` Effects for commands and `{ run }` native Streams for streams. |
|
|
492
525
|
| `live.ts` | `LiveHint` schema; `live(runtime, { stream, resyncKeys, coalesceWindow?, keyContext?, resume?, retryDelay? })`, exposing `connection`, `coalesceWindow`, `paused` and `status`. |
|
|
526
|
+
| `querySubscription.ts` | `querySubscription(requests, viewer)` checks each referenced query and captures its scopes and ongoing authorization. |
|
|
493
527
|
| `makeLiveServer.ts` | `makeLiveServer`, an Effect requiring `Reactivity` that creates scoped server hint streams and a `resync` Effect. |
|
|
494
|
-
| `readPolicy.ts` | `authorizeReads(effect, request,
|
|
495
|
-
| `
|
|
528
|
+
| `readPolicy.ts` | `QueryReadPolicy`, `Viewer`, `authorizeReads(effect, request, viewer)`, `CurrentViewer`. |
|
|
529
|
+
| `readPolicyErrors.ts` | `MissingReadPolicy` and `QueryReadDenied`. |
|
|
530
|
+
| `serverMetadata.ts` | `KeyScope`, `QueryDefinition.definition`, `CommandInvalidation.invalidates`, `ChangesQueries.resolve(references)`, the Effect `queryKeys(queries, references)` and `changesRpc(name, queries)` for server adapters. |
|
|
496
531
|
| `resume.ts` | `resumeSignal({ window?, native? })`, returning a native numeric signal atom. |
|
|
532
|
+
| `testing.ts` | `watchHints(stream)` starts a scoped viewer subscription; `heard(viewer, keys, { within? }?)` waits for matching changed keys. |
|
|
497
533
|
|
|
498
534
|
A query atom takes native query options as its optional second argument, for example `api.get.query({ id: 1 }, { timeToLive: "1 minute" })`. A native resume source receives a callback and returns a cleanup function.
|
|
499
535
|
|
package/dist/automaticLive.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { type Duration } from "effect";
|
|
|
2
2
|
import * as Atom from "effect/reactivity/Atom";
|
|
3
3
|
import * as AtomRegistry from "effect/reactivity/AtomRegistry";
|
|
4
4
|
import type * as AtomRpc from "effect/reactivity/AtomRpc";
|
|
5
|
+
import { type Key } from "@shivaedev/changes/keys.ts";
|
|
5
6
|
import type { BindingOwner } from "#internal/bindingOwner.ts";
|
|
6
|
-
import { type Key } from "#keys.ts";
|
|
7
7
|
import { type LiveStatus } from "#live.ts";
|
|
8
8
|
import { type ResumeSource } from "#resume.ts";
|
|
9
9
|
import type { changesRpc, QueryReference } from "#serverMetadata.ts";
|
|
@@ -20,7 +20,7 @@ export declare function automaticLive(service: ChangesClient, name: string, owne
|
|
|
20
20
|
subscription: {
|
|
21
21
|
coalesceWindow: Atom.Writable<Duration.Input, Duration.Input>;
|
|
22
22
|
paused: Atom.Writable<boolean, boolean>;
|
|
23
|
-
status: Atom.Writable<LiveStatus<import("effect/rpc/RpcClientError").RpcClientError>, LiveStatus<import("effect/rpc/RpcClientError").RpcClientError>>;
|
|
23
|
+
status: Atom.Writable<LiveStatus<import("./readPolicyErrors.ts").MissingReadPolicy | import("./readPolicyErrors.ts").QueryReadDenied | import("effect/rpc/RpcClientError").RpcClientError>, LiveStatus<import("./readPolicyErrors.ts").MissingReadPolicy | import("./readPolicyErrors.ts").QueryReadDenied | import("effect/rpc/RpcClientError").RpcClientError>>;
|
|
24
24
|
connection: Atom.Atom<import("effect/reactivity/AsyncResult").AsyncResult<void, never>>;
|
|
25
25
|
};
|
|
26
26
|
track: (registry: AtomRegistry.AtomRegistry | undefined, reference: QueryReference, keys: readonly Key[]) => () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"automaticLive.d.ts","sourceRoot":"","sources":["../src/automaticLive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAmC,MAAM,QAAQ,CAAC;AACxE,OAAO,KAAK,IAAI,MAAM,wBAAwB,CAAC;AAC/C,OAAO,KAAK,YAAY,MAAM,gCAAgC,CAAC;AAC/D,OAAO,KAAK,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAC1D,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"automaticLive.d.ts","sourceRoot":"","sources":["../src/automaticLive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAmC,MAAM,QAAQ,CAAC;AACxE,OAAO,KAAK,IAAI,MAAM,wBAAwB,CAAC;AAC/C,OAAO,KAAK,YAAY,MAAM,gCAAgC,CAAC;AAC/D,OAAO,KAAK,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,KAAK,GAAG,EAAY,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,UAAU,CAAC;AACjD,OAAO,EAAE,KAAK,YAAY,EAAmC,MAAM,YAAY,CAAC;AAChF,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAIrE,eAAO,MAAM,cAAc,eAAmD,CAAC;AAC/E,MAAM,WAAW,SAAS;IACzB,QAAQ,CAAC,CAAC,cAAc,CAAC,EAAE;QAC1B,QAAQ,CAAC,cAAc,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACvD,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;KAChD,CAAC;CACF;AAED,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC;AAOlG,wBAAgB,aAAa,CAAC,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,YAAY;;;;;;;sBAIrF,YAAY,CAAC,YAAY,GAAG,SAAS,aAAa,cAAc,QAAQ,SAAS,GAAG,EAAE;EAgE/G"}
|
package/dist/automaticLive.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Effect, Stream, SubscriptionRef } from "effect";
|
|
2
2
|
import * as Atom from "effect/reactivity/Atom";
|
|
3
3
|
import * as AtomRegistry from "effect/reactivity/AtomRegistry";
|
|
4
|
-
import { readKeys } from "
|
|
4
|
+
import { readKeys } from "@shivaedev/changes/keys.ts";
|
|
5
|
+
import { localQueryKeys, queryHint } from "#internal/queryHints.ts";
|
|
5
6
|
import { live } from "#live.ts";
|
|
6
7
|
import { resumeSignal } from "#resume.ts";
|
|
7
8
|
export const LiveConnection = Symbol.for("@shivaedev/contract/LiveConnection");
|
|
@@ -43,13 +44,13 @@ export function automaticLive(service, name, owner, resume) {
|
|
|
43
44
|
return Stream.never;
|
|
44
45
|
}
|
|
45
46
|
const queries = [...current.values()].map(({ reference }) => reference);
|
|
46
|
-
return Stream.unwrap(service.use((client) => Effect.succeed(client(`${name}.$changes`, { queries }))));
|
|
47
|
+
return Stream.unwrap(service.use((client) => Effect.succeed(client(`${name}.$changes`, { queries }).pipe(Stream.map((hint) => queryHint(hint, [...current.values()]))))));
|
|
47
48
|
}
|
|
48
49
|
const signal = resumeSignal({ ...(typeof window === "undefined" ? {} : { window }), ...(resume === undefined ? {} : { native: resume }) });
|
|
49
50
|
const subscription = live(service.runtime, {
|
|
50
51
|
keyContext: owner?.context,
|
|
51
52
|
resume: signal,
|
|
52
|
-
resyncKeys: (registry) => [...Effect.runSync(SubscriptionRef.get(registry.get(tracked))).values()].flatMap(({ keys }) => keys),
|
|
53
|
+
resyncKeys: (registry) => [...Effect.runSync(SubscriptionRef.get(registry.get(tracked))).values()].flatMap(({ keys }) => localQueryKeys(keys)),
|
|
53
54
|
stream: Stream.unwrap(Effect.map(AtomRegistry.AtomRegistry, (registry) => Stream.zipLatest(SubscriptionRef.changes(registry.get(tracked)), AtomRegistry.toStream(registry, signal)).pipe(Stream.switchMap(([current]) => subscribe(current))))),
|
|
54
55
|
});
|
|
55
56
|
const connection = Atom.make((get) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"automaticLive.js","sourceRoot":"","sources":["../src/automaticLive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AACxE,OAAO,KAAK,IAAI,MAAM,wBAAwB,CAAC;AAC/C,OAAO,KAAK,YAAY,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"automaticLive.js","sourceRoot":"","sources":["../src/automaticLive.ts"],"names":[],"mappings":"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"}
|
package/dist/bind.d.ts
CHANGED
|
@@ -5,11 +5,13 @@ import type * as Atom from "effect/reactivity/Atom";
|
|
|
5
5
|
import type * as AtomRegistry from "effect/reactivity/AtomRegistry";
|
|
6
6
|
import type * as AtomRpc from "effect/reactivity/AtomRpc";
|
|
7
7
|
import type * as Reactivity from "effect/reactivity/Reactivity";
|
|
8
|
-
import type { Rpc } from "effect/rpc";
|
|
8
|
+
import type { Rpc, RpcGroup } from "effect/rpc";
|
|
9
9
|
import type { RpcClientError } from "effect/rpc/RpcClientError";
|
|
10
10
|
import { type LiveBound } from "#automaticLive.ts";
|
|
11
|
+
import type { ClientOptions, MadeClient } from "#clientOptions.ts";
|
|
11
12
|
import type { Contract, Tag } from "#contract.ts";
|
|
12
13
|
import type { CommandShape, QueryShape, StreamShape } from "#operation.ts";
|
|
14
|
+
import type { MissingReadPolicy } from "#readPolicyErrors.ts";
|
|
13
15
|
import type { ResumeSource } from "#resume.ts";
|
|
14
16
|
export type Failure<R extends Rpc.Any> = R extends Rpc.Rpc<infer _Tag, infer _Payload, infer _Success, infer _Error, infer TMiddleware, infer _Requires> ? Rpc.ErrorExit<R> | TMiddleware["error"]["Type"] | RpcClientError : never;
|
|
15
17
|
export type RunFailure<R extends Rpc.Any> = R extends Rpc.Rpc<infer _Tag, infer _Payload, infer _Success, infer _Error, infer TMiddleware, infer _Requires> ? Failure<R> | TMiddleware["~ClientError"] : never;
|
|
@@ -19,7 +21,7 @@ export interface QueryOptions {
|
|
|
19
21
|
readonly timeToLive?: Duration.Input;
|
|
20
22
|
}
|
|
21
23
|
export interface BoundQuery<R extends Rpc.Any, TSelf> {
|
|
22
|
-
readonly query: (payload: Rpc.Payload<R>, options?: QueryOptions) => Atom.Atom<AsyncResult.AsyncResult<Rpc.Success<R>, Failure<R
|
|
24
|
+
readonly query: (payload: Rpc.Payload<R>, options?: QueryOptions) => Atom.Atom<AsyncResult.AsyncResult<Rpc.Success<R>, Failure<R> | MissingReadPolicy>>;
|
|
23
25
|
readonly run: (payload: Rpc.Payload<R>) => Effect.Effect<Rpc.Success<R>, RunFailure<R>, TSelf>;
|
|
24
26
|
}
|
|
25
27
|
export interface BoundCommand<R extends Rpc.Any, TSelf> {
|
|
@@ -47,5 +49,12 @@ interface BindOptions {
|
|
|
47
49
|
export declare function bind<TName extends string, TQueries extends readonly QueryShape[], TCommands extends readonly CommandShape[], TRpcs extends Rpc.Any, TSelf, TId extends string, TClientRpcs extends Rpc.Any, TStreams extends readonly StreamShape[], TScope extends "session" | undefined>(contract: Contract<TName, TQueries, TCommands, TRpcs, TStreams, TScope>, service: AtomRpc.AtomRpcClient<TSelf, TId, TClientRpcs> & MatchingClient<NoInfer<TRpcs>, TClientRpcs>, ...options: "session" extends TScope ? [options: BindOptions & {
|
|
48
50
|
readonly registry: AtomRegistry.AtomRegistry;
|
|
49
51
|
}] : [options?: BindOptions]): Bound<TName, TQueries, TCommands, TRpcs, TSelf, TStreams> & LiveBound;
|
|
52
|
+
export declare function makeClient<TName extends string, TQueries extends readonly QueryShape[], TCommands extends readonly CommandShape[], TRpcs extends Rpc.Any, TStreams extends readonly StreamShape[], TScope extends "session" | undefined, TExtra extends Rpc.Any = never>(contract: Contract<TName, TQueries, TCommands, TRpcs, TStreams, TScope>, options: ClientOptions & {
|
|
53
|
+
readonly group?: RpcGroup.RpcGroup<TRpcs | TExtra>;
|
|
54
|
+
} & ("session" extends TScope ? {
|
|
55
|
+
readonly registry: AtomRegistry.AtomRegistry;
|
|
56
|
+
} : {
|
|
57
|
+
readonly registry?: AtomRegistry.AtomRegistry;
|
|
58
|
+
})): MadeClient<TName, TQueries, TCommands, TRpcs, TStreams, TExtra>;
|
|
50
59
|
export {};
|
|
51
60
|
//# sourceMappingURL=bind.d.ts.map
|
package/dist/bind.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bind.d.ts","sourceRoot":"","sources":["../src/bind.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"bind.d.ts","sourceRoot":"","sources":["../src/bind.ts"],"names":[],"mappings":"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"}
|
package/dist/bind.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { automaticLive, LiveConnection } from "#automaticLive.ts";
|
|
2
2
|
import { bindingOwner } from "#internal/bindingOwner.ts";
|
|
3
3
|
import { boundCommand, boundQuery, boundStream } from "#internal/clientOperations.ts";
|
|
4
|
+
import { httpClient } from "#internal/httpClient.ts";
|
|
4
5
|
export function bind(contract, service, options) {
|
|
6
|
+
return bindApi(contract, service, options);
|
|
7
|
+
}
|
|
8
|
+
function bindApi(contract, service, options) {
|
|
5
9
|
const { name, queries, commands, streams, keyScope } = contract.declaration;
|
|
6
10
|
const owner = bindingOwner(keyScope, options?.registry);
|
|
7
11
|
const automatic = automaticLive(service, name, owner, options?.resume);
|
|
@@ -11,4 +15,9 @@ export function bind(contract, service, options) {
|
|
|
11
15
|
...streams.map((stream) => [stream.name, boundStream(service, `${name}.${stream.name}`)]),
|
|
12
16
|
]), { [LiveConnection]: automatic.subscription });
|
|
13
17
|
}
|
|
18
|
+
export function makeClient(contract, options) {
|
|
19
|
+
const connection = httpClient(contract.declaration.name, options.group ?? contract, options);
|
|
20
|
+
const api = bindApi(contract, connection.Client, options);
|
|
21
|
+
return Object.assign(connection, { api });
|
|
22
|
+
}
|
|
14
23
|
//# sourceMappingURL=bind.js.map
|
package/dist/bind.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bind.js","sourceRoot":"","sources":["../src/bind.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,aAAa,EAAkB,cAAc,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"bind.js","sourceRoot":"","sources":["../src/bind.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,aAAa,EAAkB,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGlF,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACtF,OAAO,EAAkB,UAAU,EAAE,MAAM,yBAAyB,CAAC;AA8ErE,MAAM,UAAU,IAAI,CACnB,QAAmJ,EACnJ,OAAwD,EACxD,OAAqB;IAErB,OAAO,OAAO,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,OAAO,CACf,QAAmJ,EACnJ,OAAwD,EACxD,OAAqB;IAErB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAAC,WAAW,CAAC;IAC5E,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IACxD,MAAM,SAAS,GAAG,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IACvE,OAAO,MAAM,CAAC,MAAM,CACnB,MAAM,CAAC,WAAW,CAAC;QAClB,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,CAAU,CAAC;QAC7H,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,YAAY,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,OAAO,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,CAAU,CAAC;QACvH,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,CAAU,CAAC;KAClG,CAAC,EACF,EAAE,CAAC,cAAc,CAAC,EAAE,SAAS,CAAC,YAAY,EAAE,CAC5C,CAAC;AACH,CAAC;AAgBD,MAAM,UAAU,UAAU,CACzB,QAEC,EACD,OAGC;IAED,MAAM,UAAU,GAAG,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,IAAI,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7F,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1D,OAAO,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Context, Effect, Layer, Scope } from "effect";
|
|
2
|
+
import type { HttpClient } from "effect/http/HttpClient";
|
|
3
|
+
import type * as Atom from "effect/reactivity/Atom";
|
|
4
|
+
import type * as AtomRpc from "effect/reactivity/AtomRpc";
|
|
5
|
+
import type { Rpc, RpcClient, RpcSerialization } from "effect/rpc";
|
|
6
|
+
import type { RpcClientError } from "effect/rpc/RpcClientError";
|
|
7
|
+
import type { LiveBound } from "#automaticLive.ts";
|
|
8
|
+
import type { Bound } from "#bind.ts";
|
|
9
|
+
import type { CommandShape, QueryShape, StreamShape } from "#operation.ts";
|
|
10
|
+
export interface ClientOptions {
|
|
11
|
+
readonly httpClient?: Layer.Layer<HttpClient>;
|
|
12
|
+
readonly serialization?: Layer.Layer<RpcSerialization.RpcSerialization>;
|
|
13
|
+
readonly transformClient?: NonNullable<Parameters<typeof RpcClient.layerProtocolHttp>[0]["transformClient"]>;
|
|
14
|
+
readonly url: string;
|
|
15
|
+
}
|
|
16
|
+
export type ClientService<TName extends string, TRpcs extends Rpc.Any> = Context.ServiceClass.Shape<`${TName}/Client`, RpcClient.RpcClient.Flat<TRpcs, RpcClientError>>;
|
|
17
|
+
export type MadeClient<TName extends string, TQueries extends readonly QueryShape[], TCommands extends readonly CommandShape[], TRpcs extends Rpc.Any, TStreams extends readonly StreamShape[], TExtra extends Rpc.Any> = Layer.Layer<ClientService<TName, TRpcs | TExtra>> & {
|
|
18
|
+
readonly api: Bound<TName, TQueries, TCommands, TRpcs, ClientService<TName, TRpcs | TExtra>, TStreams> & LiveBound;
|
|
19
|
+
readonly Client: AtomRpc.AtomRpcClient<ClientService<TName, TRpcs | TExtra>, `${TName}/Client`, TRpcs | TExtra>;
|
|
20
|
+
readonly client: Effect.Effect<RpcClient.RpcClient<TRpcs | TExtra, RpcClientError>, never, Scope.Scope | Rpc.MiddlewareClient<TRpcs | TExtra>>;
|
|
21
|
+
readonly runtime: Atom.AtomRuntime<ClientService<TName, TRpcs | TExtra>>;
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=clientOptions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clientOptions.d.ts","sourceRoot":"","sources":["../src/clientOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,KAAK,IAAI,MAAM,wBAAwB,CAAC;AACpD,OAAO,KAAK,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAC1D,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE3E,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC9C,QAAQ,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IACxE,QAAQ,CAAC,eAAe,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAC7G,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,aAAa,CAAC,KAAK,SAAS,MAAM,EAAE,KAAK,SAAS,GAAG,CAAC,GAAG,IAAI,OAAO,CAAC,YAAY,CAAC,KAAK,CAClG,GAAG,KAAK,SAAS,EACjB,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,cAAc,CAAC,CAC/C,CAAC;AAEF,MAAM,MAAM,UAAU,CACrB,KAAK,SAAS,MAAM,EACpB,QAAQ,SAAS,SAAS,UAAU,EAAE,EACtC,SAAS,SAAS,SAAS,YAAY,EAAE,EACzC,KAAK,SAAS,GAAG,CAAC,GAAG,EACrB,QAAQ,SAAS,SAAS,WAAW,EAAE,EACvC,MAAM,SAAS,GAAG,CAAC,GAAG,IACnB,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,CAAC,GAAG;IACvD,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,EAAE,QAAQ,CAAC,GAAG,SAAS,CAAC;IACnH,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,EAAE,GAAG,KAAK,SAAS,EAAE,KAAK,GAAG,MAAM,CAAC,CAAC;IAChH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,GAAG,MAAM,EAAE,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,gBAAgB,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC;IAC/I,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC;CACzE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clientOptions.js","sourceRoot":"","sources":["../src/clientOptions.ts"],"names":[],"mappings":""}
|
package/dist/contract.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Schema } from "effect";
|
|
2
2
|
import { Rpc, RpcGroup, type RpcMiddleware, type RpcSchema } from "effect/rpc";
|
|
3
3
|
import type { CommandShape, OperationShape, QueryShape, StreamShape } from "#operation.ts";
|
|
4
|
+
import { QueryReadDenied } from "#readPolicyErrors.ts";
|
|
4
5
|
import { changesRpc } from "#serverMetadata.ts";
|
|
5
6
|
export type Tag<TContract extends string, TName extends string> = `${TContract}.${TName}`;
|
|
6
|
-
|
|
7
|
+
type OperationError<TOperation extends OperationShape> = TOperation extends QueryShape ? Schema.Union<readonly [TOperation["error"], typeof QueryReadDenied]> : TOperation["error"];
|
|
8
|
+
export type OperationRpc<TContract extends string, TOperation> = TOperation extends OperationShape ? TOperation extends StreamShape ? Rpc.Rpc<Tag<TContract, TOperation["name"]>, TOperation["payload"], RpcSchema.Stream<TOperation["success"], TOperation["error"]>, Schema.Never> : Rpc.Rpc<Tag<TContract, TOperation["name"]>, TOperation["payload"], TOperation["success"], OperationError<TOperation>> : never;
|
|
7
9
|
export interface Declared<TName extends string, TQueries extends readonly QueryShape[], TCommands extends readonly CommandShape[], TStreams extends readonly StreamShape[] = readonly [], TScope extends "session" | undefined = undefined> {
|
|
8
10
|
readonly commands: TCommands;
|
|
9
11
|
readonly keyScope: TScope;
|
package/dist/contract.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,MAAM,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC3F,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAuB,UAAU,EAA6B,MAAM,oBAAoB,CAAC;AAEhG,MAAM,MAAM,GAAG,CAAC,SAAS,SAAS,MAAM,EAAE,KAAK,SAAS,MAAM,IAAI,GAAG,SAAS,IAAI,KAAK,EAAE,CAAC;AAE1F,KAAK,cAAc,CAAC,UAAU,SAAS,cAAc,IAAI,UAAU,SAAS,UAAU,GACnF,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,OAAO,eAAe,CAAC,CAAC,GACpE,UAAU,CAAC,OAAO,CAAC,CAAC;AAEvB,MAAM,MAAM,YAAY,CAAC,SAAS,SAAS,MAAM,EAAE,UAAU,IAAI,UAAU,SAAS,cAAc,GAC/F,UAAU,SAAS,WAAW,GAC7B,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,GAC9I,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC,GACtH,KAAK,CAAC;AAET,MAAM,WAAW,QAAQ,CACxB,KAAK,SAAS,MAAM,EACpB,QAAQ,SAAS,SAAS,UAAU,EAAE,EACtC,SAAS,SAAS,SAAS,YAAY,EAAE,EACzC,QAAQ,SAAS,SAAS,WAAW,EAAE,GAAG,SAAS,EAAE,EACrD,MAAM,SAAS,SAAS,GAAG,SAAS,GAAG,SAAS;IAEhD,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;CAC3B;AAED,MAAM,WAAW,QAAQ,CACxB,KAAK,SAAS,MAAM,EACpB,QAAQ,SAAS,SAAS,UAAU,EAAE,EACtC,SAAS,SAAS,SAAS,YAAY,EAAE,EACzC,KAAK,SAAS,GAAG,CAAC,GAAG,GAAG,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,EAClI,QAAQ,SAAS,SAAS,WAAW,EAAE,GAAG,SAAS,EAAE,EACrD,MAAM,SAAS,SAAS,GAAG,SAAS,GAAG,SAAS,CAC/C,SAAQ,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC;IACjC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,KAAK,WAAW,CAAA;KAAE,CAAC,CAAC,CAAC;IAChG,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC7E,UAAU,EAAE,CAAC,EAAE,SAAS,aAAa,CAAC,UAAU,EAC/C,UAAU,EAAE,EAAE,KACV,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,CAAC,aAAa,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;CAC1F;AAED,KAAK,UAAU,CAAC,WAAW,SAAS,SAAS,cAAc,EAAE,EAAE,KAAK,SAAS,MAAM,GAAG,KAAK,IAAI,WAAW,SAAS,SAAS;IAC3H,MAAM,KAAK,SAAS,cAAc;IAClC,GAAG,MAAM,KAAK,SAAS,SAAS,cAAc,EAAE;CAChD,GACE,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAChG,KAAK,CAAC;AAET,KAAK,MAAM,CAAC,WAAW,SAAS,SAAS,cAAc,EAAE,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GACnG,OAAO,GACP,+CAA+C,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;AAsC5E,wBAAgB,QAAQ,CACvB,KAAK,CAAC,KAAK,SAAS,MAAM,EAC1B,KAAK,CAAC,QAAQ,SAAS,SAAS,UAAU,EAAE,GAAG,SAAS,EAAE,EAC1D,KAAK,CAAC,SAAS,SAAS,SAAS,YAAY,EAAE,GAAG,SAAS,EAAE,EAC7D,KAAK,CAAC,QAAQ,SAAS,SAAS,WAAW,EAAE,GAAG,SAAS,EAAE,EAC3D,KAAK,CAAC,MAAM,SAAS,SAAS,GAAG,SAAS,GAAG,SAAS,EAEtD,IAAI,EAAE,KAAK,EACX,UAAU,EAAE;IACX,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC,CAAC,GAAG,QAAQ,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC;IACpE,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC,CAAC,GAAG,QAAQ,EAAE,GAAG,SAAS,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC;CAC/E,GACC,QAAQ,CACV,KAAK,EACL,QAAQ,EACR,SAAS,EACT,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,EAC7H,QAAQ,EACR,MAAM,CACN,CAAC"}
|
package/dist/contract.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { Context } from "effect";
|
|
1
|
+
import { Context, Schema } from "effect";
|
|
2
2
|
import { Rpc, RpcGroup } from "effect/rpc";
|
|
3
|
-
import {
|
|
3
|
+
import { QueryReadDenied } from "#readPolicyErrors.ts";
|
|
4
|
+
import { CommandInvalidation, changesRpc, KeyScope, QueryDefinition } from "#serverMetadata.ts";
|
|
4
5
|
function assertUnique(operations) {
|
|
5
6
|
const duplicated = operations.map(({ name }) => name).filter((name, index, names) => names.indexOf(name) !== index);
|
|
6
7
|
if (duplicated.length > 0) {
|
|
@@ -10,9 +11,9 @@ function assertUnique(operations) {
|
|
|
10
11
|
function annotations(operation, keyScope) {
|
|
11
12
|
const scope = keyScope === undefined ? Context.empty() : Context.make(KeyScope, keyScope);
|
|
12
13
|
if (operation.kind === "command") {
|
|
13
|
-
return Context.add(scope, CommandInvalidation, operation.invalidates);
|
|
14
|
+
return Context.add(scope, CommandInvalidation, { invalidates: operation.invalidates });
|
|
14
15
|
}
|
|
15
|
-
return operation.kind === "query" ? Context.add(scope,
|
|
16
|
+
return operation.kind === "query" ? Context.add(scope, QueryDefinition, { definition: operation }) : scope;
|
|
16
17
|
}
|
|
17
18
|
function withDeclaration(group, application, declaration) {
|
|
18
19
|
const nativeMiddleware = group.middleware.bind(group);
|
|
@@ -26,7 +27,7 @@ export function contract(name, operations) {
|
|
|
26
27
|
const { queries = [], commands = [], streams = [], keyScope } = operations;
|
|
27
28
|
assertUnique([...queries, ...commands, ...streams]);
|
|
28
29
|
const rpcs = [...queries, ...commands, ...streams].map((operation) => Rpc.make(`${name}.${operation.name}`, {
|
|
29
|
-
error: operation.error,
|
|
30
|
+
error: operation.kind === "query" ? Schema.Union([operation.error, QueryReadDenied]) : operation.error,
|
|
30
31
|
payload: operation.payload,
|
|
31
32
|
stream: operation.kind === "stream",
|
|
32
33
|
success: operation.success,
|
package/dist/contract.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type * as AtomRegistry from "effect/reactivity/AtomRegistry";
|
|
2
|
-
import type { KeyContext } from "
|
|
2
|
+
import type { KeyContext } from "@shivaedev/changes/keys.ts";
|
|
3
3
|
export interface BindingOwner {
|
|
4
4
|
readonly context: KeyContext;
|
|
5
5
|
readonly registry: AtomRegistry.AtomRegistry;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bindingOwner.d.ts","sourceRoot":"","sources":["../../src/internal/bindingOwner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,YAAY,MAAM,gCAAgC,CAAC;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"bindingOwner.d.ts","sourceRoot":"","sources":["../../src/internal/bindingOwner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,YAAY,MAAM,gCAAgC,CAAC;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAE7D,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC,YAAY,CAAC;CAC7C;AAID,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,EAAE,QAAQ,CAAC,EAAE,YAAY,CAAC,YAAY,GAAG,YAAY,GAAG,SAAS,CAazH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clientOperations.d.ts","sourceRoot":"","sources":["../../src/internal/clientOperations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"clientOperations.d.ts","sourceRoot":"","sources":["../../src/internal/clientOperations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,KAAK,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE7D,OAAO,KAAK,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAE1D,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGtD,KAAK,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AAKhH,KAAK,qBAAqB,GAAG,OAAO,CAAC,aAAa,CACjD,OAAO,EACP,MAAM,EACN,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CACnF,CAAC;AAMF,wBAAgB,UAAU,CACzB,OAAO,EAAE,YAAY,EACrB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,OAAO,CAAC,EAChD,KAAK,CAAC,EAAE,YAAY;IAInB,KAAK,YAAY,OAAO,YAAW,YAAY;IA4B/C,GAAG,YAAY,OAAO;EAOvB;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,YAAY;IAS1G,GAAG,YAAY,OAAO;EAGvB;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,qBAAqB,EAAE,GAAG,EAAE,MAAM;IAErE,GAAG,YAAY,OAAO;EAEvB"}
|