@shivaedev/effect-contract 0.1.0 → 0.2.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 +19 -0
- package/README.md +24 -24
- package/dist/bind.d.ts +3 -3
- package/dist/bind.d.ts.map +1 -1
- package/dist/bind.js.map +1 -1
- package/dist/contract.d.ts +8 -8
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +4 -3
- package/dist/contract.js.map +1 -1
- package/dist/keys.d.ts +4 -4
- package/dist/keys.d.ts.map +1 -1
- package/dist/keys.js +2 -2
- package/dist/keys.js.map +1 -1
- package/dist/operation.d.ts +14 -13
- package/dist/operation.d.ts.map +1 -1
- package/dist/operation.js +3 -2
- package/dist/operation.js.map +1 -1
- package/dist/rejection.d.ts +9 -9
- package/dist/rejection.d.ts.map +1 -1
- package/dist/rejection.js +1 -1
- package/dist/rejection.js.map +1 -1
- package/package.json +28 -27
- package/src/bind.ts +7 -7
- package/src/contract.ts +19 -17
- package/src/keys.ts +6 -6
- package/src/operation.ts +21 -18
- package/src/rejection.ts +15 -13
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0 - 2026-10-04
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Consolidate duplicate test cases around observable package behavior.
|
|
8
|
+
- The function members of `Contract`, `Query` and `Command` are declared as properties, so TypeScript checks their parameters strictly. `QueryShape.reads` and `CommandShape.invalidates` stay bivariant, so a contract still takes operations with typed payloads; the package now depends on `@shivaedev/types` for `Bivariant`.
|
|
9
|
+
|
|
10
|
+
- Validate packed consumers and executable bins through the shared workspace gate.
|
|
11
|
+
|
|
12
|
+
- Build with the `@shivaedev/quality` tsconfig presets, which target ESNext and allow only erasable TypeScript syntax.
|
|
13
|
+
|
|
14
|
+
- Type-check with TypeScript 7 only. TypeScript 6 still builds the package.
|
|
15
|
+
|
|
16
|
+
- Lint and format with the `@shivaedev/quality` Biome preset through `quality lint` at the repository root, which replaces the package's `check` script.
|
|
17
|
+
|
|
18
|
+
- Run tests through the `@shivaedev/quality` Vitest projects, which take a test's environment from its file name. Type tests are named `*.typecheck.test.ts`.
|
|
19
|
+
|
|
20
|
+
- Keep `package.json` in sort-package-json key order, checked by `quality lint`.
|
|
21
|
+
|
|
3
22
|
## 0.1.0 - 2026-09-26
|
|
4
23
|
|
|
5
24
|
### Added
|
package/README.md
CHANGED
|
@@ -6,27 +6,27 @@ Declare queries and commands once. Each declaration becomes an ordinary native E
|
|
|
6
6
|
import { Schema } from "effect";
|
|
7
7
|
import { collection, command, contract, fieldRejection, query } from "@shivaedev/effect-contract";
|
|
8
8
|
|
|
9
|
-
class
|
|
10
|
-
class
|
|
11
|
-
const
|
|
9
|
+
class Order extends Schema.Class<Order>("Order")({ id: Schema.Number, name: Schema.String, quantity: Schema.Number }) {}
|
|
10
|
+
class OrderNotFound extends Schema.TaggedError<OrderNotFound>()("OrderNotFound", {}) {}
|
|
11
|
+
const OrderDraft = Schema.Struct({ name: Order.fields.name, quantity: Order.fields.quantity });
|
|
12
12
|
|
|
13
|
-
export const
|
|
13
|
+
export const orders = collection("orders", Order.fields.id);
|
|
14
14
|
|
|
15
|
-
export const
|
|
15
|
+
export const GetOrder = query("get", {
|
|
16
16
|
payload: { id: Schema.Number },
|
|
17
|
-
success:
|
|
18
|
-
rejections: {
|
|
19
|
-
reads: ({ id }) => [
|
|
17
|
+
success: Order,
|
|
18
|
+
rejections: { OrderNotFound },
|
|
19
|
+
reads: ({ id }) => [orders.item(id)],
|
|
20
20
|
});
|
|
21
|
-
export const
|
|
22
|
-
export const
|
|
23
|
-
payload: { id: Schema.Number, ...
|
|
24
|
-
success:
|
|
25
|
-
rejections: {
|
|
26
|
-
invalidates: ({ id }) => [
|
|
21
|
+
export const ListOrders = query("list", { success: Schema.Array(Order), reads: () => [orders.list] });
|
|
22
|
+
export const SaveOrder = command("save", {
|
|
23
|
+
payload: { id: Schema.Number, ...OrderDraft.fields },
|
|
24
|
+
success: Order,
|
|
25
|
+
rejections: { OrderNotFound, OrderValidation: fieldRejection(OrderDraft) },
|
|
26
|
+
invalidates: ({ id }) => [orders.item(id)],
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
-
export const
|
|
29
|
+
export const Orders = contract("orders", { queries: [GetOrder, ListOrders], commands: [SaveOrder] }).middleware(Authentication);
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
## API
|
|
@@ -47,33 +47,33 @@ Payload accepts struct fields or any schema, as in `Rpc.make`. Omitted payload a
|
|
|
47
47
|
|
|
48
48
|
- Each operation exposes `payload`, `success`, `error` (the rejection union, or `Schema.Never` without rejections), `Rejection.X` (the class) and `reject.X(...)`, an `Effect<never, X>`.
|
|
49
49
|
- `rejections: { Tag: fields }` generates a `Schema.TaggedError` class with that `_tag`. `rejections: { Tag: ExistingClass }` reuses a class; its `_tag` must equal the key. Reuse one class when several operations or a shared service raise the same rejection. Generated classes are distinct per operation.
|
|
50
|
-
- `fieldRejection(
|
|
50
|
+
- `fieldRejection(OrderDraft)` derives the `field` literal union from the struct's keys, so a form can attach the rejection to one of its own fields. Pass a key list to narrow it.
|
|
51
51
|
|
|
52
52
|
### Contract
|
|
53
53
|
|
|
54
|
-
- RPC tags are `` `${contract}.${operation}` ``. Implement handlers with native `
|
|
54
|
+
- RPC tags are `` `${contract}.${operation}` ``. Implement handlers with native `Orders.toLayer(Effect.gen(...))` and `Orders.of({ "orders.get": ... })`; `of` rejects wrong payloads, successes and undeclared failures.
|
|
55
55
|
- Middleware is the native `.middleware(M)`. On a contract it returns a contract, keeping `declaration` (`{ name, queries, commands }`). Other native group combinators (`add`, `merge`, `prefix`, `omit`) return plain groups.
|
|
56
56
|
- Operation names in one contract must all differ, across and within queries and commands. The compiler rejects duplicates in literal arrays; `contract` throws for duplicates it cannot see.
|
|
57
57
|
- Operations can be declared inline in `contract(...)` or beforehand; both keep the same types and defaults.
|
|
58
58
|
|
|
59
59
|
### Reactivity keys
|
|
60
60
|
|
|
61
|
-
`collection("
|
|
61
|
+
`collection("orders", Order.fields.id)` gives `orders.list` and `orders.item(id)`; ids must be strings or numbers. The binding applies the one rule that is easy to get wrong with native keys:
|
|
62
62
|
|
|
63
63
|
| Declared | Query registers | Command invalidates |
|
|
64
64
|
| --- | --- | --- |
|
|
65
|
-
| `
|
|
66
|
-
| `
|
|
65
|
+
| `orders.item(id)` | `` `orders:${id}` `` | `` `orders:${id}` `` and `"orders"` |
|
|
66
|
+
| `orders.list` | `"orders"` | `"orders"` |
|
|
67
67
|
|
|
68
|
-
An item change therefore refreshes that item and every list, but not other items. Invalidating `
|
|
68
|
+
An item change therefore refreshes that item and every list, but not other items. Invalidating `orders.list` does not refresh item queries. The strings match native Reactivity's hashing of `{ orders: [id] }`.
|
|
69
69
|
|
|
70
70
|
### Client binding
|
|
71
71
|
|
|
72
72
|
`bind` is browser-safe and uses no React:
|
|
73
73
|
|
|
74
74
|
```ts
|
|
75
|
-
class
|
|
76
|
-
const api = bind(
|
|
75
|
+
class OrdersClient extends AtomRpc.Service<OrdersClient>()("app/OrdersClient", { group: Orders, protocol }) {}
|
|
76
|
+
const api = bind(Orders, OrdersClient);
|
|
77
77
|
|
|
78
78
|
api.get.query({ id }, { timeToLive: "1 minute" }); // native Client.query atom with the declared read keys
|
|
79
79
|
api.get.run({ id }); // one call, no registration
|
|
@@ -81,7 +81,7 @@ api.save.run(input); // Effect: call, then invali
|
|
|
81
81
|
```
|
|
82
82
|
|
|
83
83
|
- `query` returns the native `AtomRpc` query atom; `headers`, `timeToLive` and `serializationKey` pass through.
|
|
84
|
-
- `run` returns `Effect<Success, Rejection | middleware error | RpcClientError,
|
|
84
|
+
- `run` returns `Effect<Success, Rejection | middleware error | RpcClientError, OrdersClient | Reactivity>` for that single invocation. Run it through the service's atom runtime (for example as a form's submit handler) so invalidation reaches the same registry. Keys, including result-dependent keys, are invalidated only after success.
|
|
85
85
|
- There is no shared mutation atom or second cache.
|
|
86
86
|
|
|
87
87
|
Authorization and transactions stay in handlers and services. For server-side invalidation after a SQL commit, see `transact` in `@shivaedev/effect-sql`.
|
package/dist/bind.d.ts
CHANGED
|
@@ -13,8 +13,8 @@ export type Failure<R extends Rpc.Any> = R extends Rpc.Rpc<infer _Tag, infer _Pa
|
|
|
13
13
|
export type RunFailure<R extends Rpc.Any> = R extends Rpc.Rpc<infer _Tag, infer _Payload, infer _Success, infer _Error, infer Middleware, infer _Requires> ? Failure<R> | Middleware["~ClientError"] : never;
|
|
14
14
|
export interface QueryOptions {
|
|
15
15
|
readonly headers?: Headers.Input;
|
|
16
|
-
readonly timeToLive?: Duration.Input;
|
|
17
16
|
readonly serializationKey?: string;
|
|
17
|
+
readonly timeToLive?: Duration.Input;
|
|
18
18
|
}
|
|
19
19
|
export interface BoundQuery<R extends Rpc.Any, Self> {
|
|
20
20
|
readonly query: (payload: Rpc.Payload<R>, options?: QueryOptions) => Atom.Atom<AsyncResult.AsyncResult<Rpc.Success<R>, Failure<R>>>;
|
|
@@ -23,10 +23,10 @@ export interface BoundQuery<R extends Rpc.Any, Self> {
|
|
|
23
23
|
export interface BoundCommand<R extends Rpc.Any, Self> {
|
|
24
24
|
readonly run: (payload: Rpc.Payload<R>) => Effect.Effect<Rpc.Success<R>, RunFailure<R>, Self | Reactivity.Reactivity>;
|
|
25
25
|
}
|
|
26
|
-
export type Bound<Name extends string, Queries extends
|
|
26
|
+
export type Bound<Name extends string, Queries extends readonly QueryShape[], Commands extends readonly CommandShape[], Rpcs extends Rpc.Any, Self> = {
|
|
27
27
|
readonly [Query in Queries[number] as Query["name"]]: BoundQuery<Rpc.ExtractTag<Rpcs, Tag<Name, Query["name"]>>, Self>;
|
|
28
28
|
} & {
|
|
29
29
|
readonly [Command in Commands[number] as Command["name"]]: BoundCommand<Rpc.ExtractTag<Rpcs, Tag<Name, Command["name"]>>, Self>;
|
|
30
30
|
};
|
|
31
|
-
export declare function bind<Name extends string, Queries extends
|
|
31
|
+
export declare function bind<Name extends string, Queries extends readonly QueryShape[], Commands extends readonly CommandShape[], Rpcs extends Rpc.Any, Self, Id extends string>(contract: Contract<Name, Queries, Commands, Rpcs>, service: AtomRpc.AtomRpcClient<Self, Id, Rpcs>): Bound<Name, Queries, Commands, Rpcs, Self>;
|
|
32
32
|
//# 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,EAAU,MAAM,QAAQ,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,KAAK,WAAW,MAAM,wCAAwC,CAAC;AAC3E,OAAO,KAAK,KAAK,IAAI,MAAM,iCAAiC,CAAC;AAC7D,OAAO,KAAK,KAAK,OAAO,MAAM,oCAAoC,CAAC;AACnE,OAAO,KAAK,UAAU,MAAM,uCAAuC,CAAC;AACpE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAY,GAAG,EAAE,MAAM,eAAe,CAAC;AAE7D,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE/D,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,GAAG,CAAC,GAAG,IACpC,CAAC,SAAS,GAAG,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,MAAM,QAAQ,EAAE,MAAM,QAAQ,EAAE,MAAM,KAAK,EAAE,MAAM,UAAU,EAAE,MAAM,SAAS,CAAC,GAC1G,KAAK,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,cAAc,GAC5D,KAAK,CAAC;AAEV,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,GAAG,CAAC,GAAG,IACvC,CAAC,SAAS,GAAG,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,MAAM,QAAQ,EAAE,MAAM,QAAQ,EAAE,MAAM,MAAM,EAAE,MAAM,UAAU,EAAE,MAAM,SAAS,CAAC,GAC3G,OAAO,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,cAAc,CAAC,GACvC,KAAK,CAAC;AAEV,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC;IACjC,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"bind.d.ts","sourceRoot":"","sources":["../src/bind.ts"],"names":[],"mappings":"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"}
|
package/dist/bind.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bind.js","sourceRoot":"","sources":["../src/bind.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAKhC,OAAO,KAAK,UAAU,MAAM,uCAAuC,CAAC;AAIpE,OAAO,EAAE,gBAAgB,EAAY,QAAQ,EAAE,MAAM,WAAW,CAAC;AA0CjE,MAAM,eAAe,GAAG,MAAM,CAAC,EAAE,CAAC,2BAA2B,CAAC,CAAC,QAAQ,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"bind.js","sourceRoot":"","sources":["../src/bind.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAKhC,OAAO,KAAK,UAAU,MAAM,uCAAuC,CAAC;AAIpE,OAAO,EAAE,gBAAgB,EAAY,QAAQ,EAAE,MAAM,WAAW,CAAC;AA0CjE,MAAM,eAAe,GAAG,MAAM,CAAC,EAAE,CAAC,2BAA2B,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAoB;IAC7F,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;AACtD,CAAC,CAAC,CAAC;AAEH,MAAM,UAAU,GAAG,CAAC,OAAqB,EAAE,GAAW,EAAE,KAAiB,EAAE,EAAE;IAC5E,MAAM,KAAK,GAAG,CAAC,OAAgB,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IACnE,OAAO;QACN,KAAK,EAAE,CAAC,OAAgB,EAAE,UAAwB,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,cAAc,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACpI,GAAG,EAAE,CAAC,OAAgB,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;KACxE,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,OAAqB,EAAE,GAAW,EAAE,OAAqB,EAAE,EAAE,CAAC,CAAC;IACpF,GAAG,EAAE,CAAC,OAAgB,EAAE,EAAE,CACzB,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;CAClI,CAAC,CAAC;AAUH,MAAM,UAAU,IAAI,CACnB,QAAoG,EACpG,OAAqB;IAErB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAAC,WAAW,CAAC;IACzD,OAAO,MAAM,CAAC,WAAW,CAAC;QACzB,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,CAAC,CAAU,CAAC;QACrG,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,CAAC,CAAU,CAAC;KAChH,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/contract.d.ts
CHANGED
|
@@ -2,21 +2,21 @@ import { Rpc, RpcGroup, type RpcMiddleware } from "effect/unstable/rpc";
|
|
|
2
2
|
import type { CommandShape, OperationShape, QueryShape } from "./operation.ts";
|
|
3
3
|
export type Tag<Contract extends string, Name extends string> = `${Contract}.${Name}`;
|
|
4
4
|
export type OperationRpc<Contract extends string, Operation> = Operation extends OperationShape ? Rpc.Rpc<Tag<Contract, Operation["name"]>, Operation["payload"], Operation["success"], Operation["error"]> : never;
|
|
5
|
-
export interface Declared<Name extends string, Queries extends
|
|
5
|
+
export interface Declared<Name extends string, Queries extends readonly QueryShape[], Commands extends readonly CommandShape[]> {
|
|
6
|
+
readonly commands: Commands;
|
|
6
7
|
readonly name: Name;
|
|
7
8
|
readonly queries: Queries;
|
|
8
|
-
readonly commands: Commands;
|
|
9
9
|
}
|
|
10
|
-
export interface Contract<Name extends string, Queries extends
|
|
10
|
+
export interface Contract<Name extends string, Queries extends readonly QueryShape[], Commands extends readonly CommandShape[], Rpcs extends Rpc.Any = OperationRpc<Name, Queries[number] | Commands[number]>> extends RpcGroup.RpcGroup<Rpcs> {
|
|
11
11
|
readonly declaration: Declared<Name, Queries, Commands>;
|
|
12
|
-
middleware<M extends RpcMiddleware.AnyService>(middleware: M)
|
|
12
|
+
middleware: <M extends RpcMiddleware.AnyService>(middleware: M) => Contract<Name, Queries, Commands, Rpc.AddMiddleware<Rpcs, M>>;
|
|
13
13
|
}
|
|
14
|
-
type Duplicated<Operations extends
|
|
14
|
+
type Duplicated<Operations extends readonly OperationShape[], Seen extends string = never> = Operations extends readonly [
|
|
15
15
|
infer Head extends OperationShape,
|
|
16
|
-
...infer Tail extends
|
|
16
|
+
...infer Tail extends readonly OperationShape[]
|
|
17
17
|
] ? (Head["name"] extends Seen ? Head["name"] : never) | Duplicated<Tail, Seen | Head["name"]> : never;
|
|
18
|
-
type Unique<Operations extends
|
|
19
|
-
export declare function contract<const Name extends string, const Queries extends
|
|
18
|
+
type Unique<Operations extends readonly OperationShape[]> = [Duplicated<Operations>] extends [never] ? unknown : `Operation names must be unique; duplicated: ${Duplicated<Operations>}`;
|
|
19
|
+
export declare function contract<const Name extends string, const Queries extends readonly QueryShape[] = readonly [], const Commands extends readonly CommandShape[] = readonly []>(name: Name, operations: {
|
|
20
20
|
readonly queries?: Queries & Unique<Queries>;
|
|
21
21
|
readonly commands?: Commands & Unique<[...Queries, ...Commands]>;
|
|
22
22
|
}): Contract<Name, Queries, Commands>;
|
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,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE/E,MAAM,MAAM,GAAG,CAAC,QAAQ,SAAS,MAAM,EAAE,IAAI,SAAS,MAAM,IAAI,GAAG,QAAQ,IAAI,IAAI,EAAE,CAAC;AAEtF,MAAM,MAAM,YAAY,CAAC,QAAQ,SAAS,MAAM,EAAE,SAAS,IAAI,SAAS,SAAS,cAAc,GAC5F,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,GACzG,KAAK,CAAC;AAET,MAAM,WAAW,QAAQ,CAAC,IAAI,SAAS,MAAM,EAAE,OAAO,SAAS,
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"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"}
|
package/dist/contract.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Rpc, RpcGroup } from "effect/unstable/rpc";
|
|
2
2
|
const assertUnique = (operations) => {
|
|
3
3
|
const duplicated = operations.map(({ name }) => name).filter((name, index, names) => names.indexOf(name) !== index);
|
|
4
|
-
if (duplicated.length > 0)
|
|
4
|
+
if (duplicated.length > 0) {
|
|
5
5
|
throw new Error(`Operation names must be unique; duplicated: ${[...new Set(duplicated)].join(", ")}`);
|
|
6
|
+
}
|
|
6
7
|
};
|
|
7
8
|
const withDeclaration = (group, declaration) => {
|
|
8
9
|
const nativeMiddleware = group.middleware.bind(group);
|
|
@@ -14,7 +15,7 @@ const withDeclaration = (group, declaration) => {
|
|
|
14
15
|
export function contract(name, operations) {
|
|
15
16
|
const { queries = [], commands = [] } = operations;
|
|
16
17
|
assertUnique([...queries, ...commands]);
|
|
17
|
-
const rpcs = [...queries, ...commands].map((operation) => Rpc.make(`${name}.${operation.name}`, {
|
|
18
|
-
return withDeclaration(RpcGroup.make(...rpcs), { name, queries
|
|
18
|
+
const rpcs = [...queries, ...commands].map((operation) => Rpc.make(`${name}.${operation.name}`, { error: operation.error, payload: operation.payload, success: operation.success }));
|
|
19
|
+
return withDeclaration(RpcGroup.make(...rpcs), { commands, name, queries });
|
|
19
20
|
}
|
|
20
21
|
//# sourceMappingURL=contract.js.map
|
package/dist/contract.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAsB,MAAM,qBAAqB,CAAC;AAoCxE,MAAM,YAAY,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAsB,MAAM,qBAAqB,CAAC;AAoCxE,MAAM,YAAY,GAAG,CAAC,UAAqC,EAAE,EAAE;IAC9D,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC;IACpH,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvG,CAAC;AACF,CAAC,CAAC;AAYF,MAAM,eAAe,GAAG,CAAC,KAAY,EAAE,WAAwB,EAAiB,EAAE;IACjF,MAAM,gBAAgB,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtD,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE;QAC3B,WAAW;QACX,UAAU,EAAE,CAAC,UAAoC,EAAE,EAAE,CAAC,eAAe,CAAC,gBAAgB,CAAC,UAAU,CAAC,EAAE,WAAW,CAAC;KAChH,CAAC,CAAC;AACJ,CAAC,CAAC;AAUF,MAAM,UAAU,QAAQ,CACvB,IAAY,EACZ,UAAqG;IAErG,MAAM,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,EAAE,EAAE,GAAG,UAAU,CAAC;IACnD,YAAY,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,CAAC,GAAG,OAAO,EAAE,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CACxD,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,SAAS,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,CACzH,CAAC;IACF,OAAO,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AAC7E,CAAC"}
|
package/dist/keys.d.ts
CHANGED
|
@@ -11,13 +11,13 @@ export interface ItemKey<Name extends string = string> {
|
|
|
11
11
|
}
|
|
12
12
|
export type Key = ListKey | ItemKey;
|
|
13
13
|
export interface Collection<Name extends string, Id extends Identity> {
|
|
14
|
-
readonly name: Name;
|
|
15
|
-
readonly list: ListKey<Name>;
|
|
16
14
|
readonly item: (id: Id) => ItemKey<Name>;
|
|
15
|
+
readonly list: ListKey<Name>;
|
|
16
|
+
readonly name: Name;
|
|
17
17
|
}
|
|
18
18
|
export declare const collection: <const Name extends string, Id extends Schema.Top & {
|
|
19
19
|
readonly Type: Identity;
|
|
20
20
|
}>(name: Name, _id: Id) => Collection<Name, Id["Type"]>;
|
|
21
|
-
export declare const readKeys: (keys:
|
|
22
|
-
export declare const invalidationKeys: (keys:
|
|
21
|
+
export declare const readKeys: (keys: readonly Key[]) => readonly string[];
|
|
22
|
+
export declare const invalidationKeys: (keys: readonly Key[]) => readonly string[];
|
|
23
23
|
//# sourceMappingURL=keys.d.ts.map
|
package/dist/keys.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAEvC,MAAM,WAAW,OAAO,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,OAAO,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC;CACtB;AAED,MAAM,MAAM,GAAG,GAAG,OAAO,GAAG,OAAO,CAAC;AAEpC,MAAM,WAAW,UAAU,CAAC,IAAI,SAAS,MAAM,EAAE,EAAE,SAAS,QAAQ;IACnE,QAAQ,CAAC,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAEvC,MAAM,WAAW,OAAO,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,OAAO,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC;CACtB;AAED,MAAM,MAAM,GAAG,GAAG,OAAO,GAAG,OAAO,CAAC;AAEpC,MAAM,WAAW,UAAU,CAAC,IAAI,SAAS,MAAM,EAAE,EAAE,SAAS,QAAQ;IACnE,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;CACpB;AAED,eAAO,MAAM,UAAU,GAAI,KAAK,CAAC,IAAI,SAAS,MAAM,EAAE,EAAE,SAAS,MAAM,CAAC,GAAG,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,EACxG,MAAM,IAAI,EACV,KAAK,EAAE,KACL,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,CAI5B,CAAC;AAIH,eAAO,MAAM,QAAQ,GAAI,MAAM,SAAS,GAAG,EAAE,KAAG,SAAS,MAAM,EAAiC,CAAC;AAEjG,eAAO,MAAM,gBAAgB,GAAI,MAAM,SAAS,GAAG,EAAE,KAAG,SAAS,MAAM,EAEtE,CAAC"}
|
package/dist/keys.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const collection = (name, _id) => ({
|
|
2
|
-
name,
|
|
3
|
-
list: { _tag: "List", collection: name },
|
|
4
2
|
item: (id) => ({ _tag: "Item", collection: name, id }),
|
|
3
|
+
list: { _tag: "List", collection: name },
|
|
4
|
+
name,
|
|
5
5
|
});
|
|
6
6
|
const own = (key) => (key._tag === "List" ? key.collection : `${key.collection}:${key.id}`);
|
|
7
7
|
export const readKeys = (keys) => [...new Set(keys.map(own))];
|
package/dist/keys.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAuBA,MAAM,CAAC,MAAM,UAAU,GAAG,CACzB,IAAU,EACV,GAAO,EACwB,EAAE,CAAC,CAAC;IACnC,IAAI
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAuBA,MAAM,CAAC,MAAM,UAAU,GAAG,CACzB,IAAU,EACV,GAAO,EACwB,EAAE,CAAC,CAAC;IACnC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IACtD,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE;IACxC,IAAI;CACJ,CAAC,CAAC;AAEH,MAAM,GAAG,GAAG,CAAC,GAAQ,EAAU,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;AAEzG,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAoB,EAAqB,EAAE,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAEjG,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,IAAoB,EAAqB,EAAE,CAAC;IAC5E,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;CACxG,CAAC"}
|
package/dist/operation.d.ts
CHANGED
|
@@ -1,53 +1,54 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
|
+
import type { Bivariant } from "@shivaedev/types";
|
|
2
3
|
import type { Key } from "./keys.ts";
|
|
3
4
|
import { type MatchingTags, type Reject, type RejectionSpecs, type Rejections, type RejectionUnion } from "./rejection.ts";
|
|
4
5
|
export type PayloadSchema<Payload extends Schema.Top | Schema.Struct.Fields> = Payload extends Schema.Struct.Fields ? Schema.Struct<Payload> : Payload;
|
|
5
6
|
type NoRejections = Record<never, never>;
|
|
6
7
|
export interface OperationShape {
|
|
8
|
+
readonly error: Schema.Top;
|
|
7
9
|
readonly kind: "query" | "command";
|
|
8
10
|
readonly name: string;
|
|
9
11
|
readonly payload: Schema.Top;
|
|
10
|
-
readonly success: Schema.Top;
|
|
11
|
-
readonly error: Schema.Top;
|
|
12
|
-
readonly rejections: RejectionSpecs;
|
|
13
12
|
readonly Rejection: object;
|
|
14
13
|
readonly reject: object;
|
|
14
|
+
readonly rejections: RejectionSpecs;
|
|
15
|
+
readonly success: Schema.Top;
|
|
15
16
|
}
|
|
16
17
|
export interface QueryShape extends OperationShape {
|
|
17
18
|
readonly kind: "query";
|
|
18
|
-
reads(payload: unknown)
|
|
19
|
+
reads: Bivariant<(payload: unknown) => readonly Key[]>;
|
|
19
20
|
}
|
|
20
21
|
export interface CommandShape extends OperationShape {
|
|
22
|
+
invalidates: Bivariant<(payload: unknown, result: unknown) => readonly Key[]>;
|
|
21
23
|
readonly kind: "command";
|
|
22
|
-
invalidates(payload: unknown, result: unknown): ReadonlyArray<Key>;
|
|
23
24
|
}
|
|
24
25
|
interface Operation<Name extends string, Payload extends Schema.Top, Success extends Schema.Top, Specs extends RejectionSpecs> extends OperationShape {
|
|
26
|
+
readonly error: RejectionUnion<Specs>;
|
|
25
27
|
readonly name: Name;
|
|
26
28
|
readonly payload: Payload;
|
|
27
|
-
readonly success: Success;
|
|
28
|
-
readonly error: RejectionUnion<Specs>;
|
|
29
|
-
readonly rejections: Specs;
|
|
30
29
|
readonly Rejection: Rejections<Specs>;
|
|
31
30
|
readonly reject: Reject<Specs>;
|
|
31
|
+
readonly rejections: Specs;
|
|
32
|
+
readonly success: Success;
|
|
32
33
|
}
|
|
33
34
|
export interface Query<Name extends string, Payload extends Schema.Top, Success extends Schema.Top, Specs extends RejectionSpecs> extends Operation<Name, Payload, Success, Specs> {
|
|
34
35
|
readonly kind: "query";
|
|
35
|
-
reads(payload: Payload["Type"])
|
|
36
|
+
reads: (payload: Payload["Type"]) => readonly Key[];
|
|
36
37
|
}
|
|
37
38
|
export interface Command<Name extends string, Payload extends Schema.Top, Success extends Schema.Top, Specs extends RejectionSpecs> extends Operation<Name, Payload, Success, Specs> {
|
|
39
|
+
invalidates: (payload: Payload["Type"], result: Success["Type"]) => readonly Key[];
|
|
38
40
|
readonly kind: "command";
|
|
39
|
-
invalidates(payload: Payload["Type"], result: Success["Type"]): ReadonlyArray<Key>;
|
|
40
41
|
}
|
|
41
42
|
interface Declaration<Payload extends Schema.Top | Schema.Struct.Fields, Success extends Schema.Top, Specs extends RejectionSpecs> {
|
|
42
43
|
readonly payload?: Payload;
|
|
43
|
-
readonly success?: Success;
|
|
44
44
|
readonly rejections?: Specs & MatchingTags<Specs>;
|
|
45
|
+
readonly success?: Success;
|
|
45
46
|
}
|
|
46
47
|
export declare function query<const Name extends string, Payload extends Schema.Top | Schema.Struct.Fields = Schema.Void, Success extends Schema.Top = Schema.Void, const Specs extends RejectionSpecs = NoRejections>(name: Name, declaration: Declaration<Payload, Success, Specs> & {
|
|
47
|
-
readonly reads: (payload: PayloadSchema<Payload>["Type"]) =>
|
|
48
|
+
readonly reads: (payload: PayloadSchema<Payload>["Type"]) => readonly Key[];
|
|
48
49
|
}): NoInfer<Query<Name, PayloadSchema<Payload>, Success, Specs>>;
|
|
49
50
|
export declare function command<const Name extends string, Payload extends Schema.Top | Schema.Struct.Fields = Schema.Void, Success extends Schema.Top = Schema.Void, const Specs extends RejectionSpecs = NoRejections>(name: Name, declaration: Declaration<Payload, Success, Specs> & {
|
|
50
|
-
readonly invalidates: (payload: PayloadSchema<Payload>["Type"], result: Success["Type"]) =>
|
|
51
|
+
readonly invalidates: (payload: PayloadSchema<Payload>["Type"], result: Success["Type"]) => readonly Key[];
|
|
51
52
|
}): NoInfer<Command<Name, PayloadSchema<Payload>, Success, Specs>>;
|
|
52
53
|
export {};
|
|
53
54
|
//# sourceMappingURL=operation.d.ts.map
|
package/dist/operation.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operation.d.ts","sourceRoot":"","sources":["../src/operation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,MAAM,EAAE,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,KAAK,cAAc,EAAgB,MAAM,gBAAgB,CAAC;AAEzI,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,OAAO,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,GAChH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,GACtB,OAAO,CAAC;AAEX,KAAK,YAAY,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAEzC,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC;IAC7B,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"operation.d.ts","sourceRoot":"","sources":["../src/operation.ts"],"names":[],"mappings":"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"}
|
package/dist/operation.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
2
|
import { rejectionSet } from "./rejection.js";
|
|
3
3
|
const payloadSchema = (payload) => {
|
|
4
|
-
if (payload === undefined)
|
|
4
|
+
if (payload === undefined) {
|
|
5
5
|
return Schema.Void;
|
|
6
|
+
}
|
|
6
7
|
return Schema.isSchema(payload) ? payload : Schema.Struct(payload);
|
|
7
8
|
};
|
|
8
9
|
const operation = (kind, name, declaration) => {
|
|
@@ -11,8 +12,8 @@ const operation = (kind, name, declaration) => {
|
|
|
11
12
|
kind,
|
|
12
13
|
name,
|
|
13
14
|
payload: payloadSchema(payload),
|
|
14
|
-
success: success ?? Schema.Void,
|
|
15
15
|
rejections,
|
|
16
|
+
success: success ?? Schema.Void,
|
|
16
17
|
...rejectionSet(rejections),
|
|
17
18
|
};
|
|
18
19
|
};
|
package/dist/operation.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operation.js","sourceRoot":"","sources":["../src/operation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"operation.js","sourceRoot":"","sources":["../src/operation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,OAAO,EAA6F,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAgEzI,MAAM,aAAa,GAAG,CAAC,OAAyB,EAAc,EAAE;IAC/D,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,MAAM,CAAC,IAAI,CAAC;IACpB,CAAC;IACD,OAAO,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACpE,CAAC,CAAC;AAEF,MAAM,SAAS,GAAG,CAAsC,IAAU,EAAE,IAAY,EAAE,WAAkB,EAAE,EAAE;IACvG,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,GAAG,EAAE,EAAE,GAAG,WAAW,CAAC;IAC1D,OAAO;QACN,IAAI;QACJ,IAAI;QACJ,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC;QAC/B,UAAU;QACV,OAAO,EAAE,OAAO,IAAI,MAAM,CAAC,IAAI;QAC/B,GAAG,YAAY,CAAC,UAAU,CAAC;KAC3B,CAAC;AACH,CAAC,CAAC;AAaF,MAAM,UAAU,KAAK,CAAC,IAAY,EAAE,WAA6E;IAChH,OAAO,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE,CAAC;AAC/E,CAAC;AAaD,MAAM,UAAU,OAAO,CACtB,IAAY,EACZ,WAAoG;IAEpG,OAAO,EAAE,GAAG,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE,WAAW,EAAE,WAAW,CAAC,WAAW,EAAE,CAAC;AAC7F,CAAC"}
|
package/dist/rejection.d.ts
CHANGED
|
@@ -4,9 +4,9 @@ export type RejectionClass<Tag extends string, Fields extends Schema.Struct.Fiel
|
|
|
4
4
|
export type TaggedRejection = Schema.Top & (new (...args: never) => {
|
|
5
5
|
readonly _tag: string;
|
|
6
6
|
});
|
|
7
|
-
export
|
|
7
|
+
export interface RejectionSpecs {
|
|
8
8
|
readonly [tag: string]: Schema.Struct.Fields | TaggedRejection;
|
|
9
|
-
}
|
|
9
|
+
}
|
|
10
10
|
export type Rejections<Specs extends RejectionSpecs> = {
|
|
11
11
|
readonly [Tag in keyof Specs & string]: Specs[Tag] extends TaggedRejection ? Specs[Tag] : Specs[Tag] extends Schema.Struct.Fields ? RejectionClass<Tag, Specs[Tag]> : never;
|
|
12
12
|
};
|
|
@@ -16,26 +16,26 @@ export type RejectedBy<Specs extends RejectionSpecs> = {
|
|
|
16
16
|
export type Reject<Specs extends RejectionSpecs> = {
|
|
17
17
|
readonly [Tag in keyof Specs & string]: Rejections<Specs>[Tag] extends new (...args: infer Arguments) => infer Value ? (...args: Arguments) => Effect.Effect<never, Value> : never;
|
|
18
18
|
};
|
|
19
|
-
export type RejectionUnion<Specs extends RejectionSpecs> = [keyof Specs & string] extends [never] ? Schema.Never : Schema.Union<
|
|
19
|
+
export type RejectionUnion<Specs extends RejectionSpecs> = [keyof Specs & string] extends [never] ? Schema.Never : Schema.Union<readonly Rejections<Specs>[keyof Specs & string][]>;
|
|
20
20
|
export type MatchingTags<Specs extends RejectionSpecs> = {
|
|
21
21
|
readonly [Tag in keyof Specs]: Specs[Tag] extends TaggedRejection ? Specs[Tag]["Type"] extends {
|
|
22
22
|
readonly _tag: Tag;
|
|
23
23
|
} ? Specs[Tag] : `The rejection class under "${Tag & string}" must have that _tag` : Specs[Tag];
|
|
24
24
|
};
|
|
25
25
|
export interface RejectionSet<Specs extends RejectionSpecs> {
|
|
26
|
+
readonly error: RejectionUnion<Specs>;
|
|
26
27
|
readonly Rejection: Rejections<Specs>;
|
|
27
28
|
readonly reject: Reject<Specs>;
|
|
28
|
-
readonly error: RejectionUnion<Specs>;
|
|
29
29
|
}
|
|
30
30
|
export declare function rejectionSet<const Specs extends RejectionSpecs>(specs: Specs): RejectionSet<Specs>;
|
|
31
|
-
export type FieldRejection<Field extends string> = {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
31
|
+
export type FieldRejection<Field extends string> = Readonly<{
|
|
32
|
+
field: Schema.Literals<readonly Field[]>;
|
|
33
|
+
message: Schema.String;
|
|
34
|
+
}>;
|
|
35
35
|
export declare function fieldRejection<const Fields extends Schema.Struct.Fields>(struct: {
|
|
36
36
|
readonly fields: Fields;
|
|
37
37
|
}): FieldRejection<keyof Fields & string>;
|
|
38
38
|
export declare function fieldRejection<const Fields extends Schema.Struct.Fields, const Field extends keyof Fields & string>(struct: {
|
|
39
39
|
readonly fields: Fields;
|
|
40
|
-
}, fields:
|
|
40
|
+
}, fields: readonly Field[]): FieldRejection<Field>;
|
|
41
41
|
//# sourceMappingURL=rejection.d.ts.map
|
package/dist/rejection.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rejection.d.ts","sourceRoot":"","sources":["../src/rejection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEpD,MAAM,MAAM,cAAc,CAAC,GAAG,SAAS,MAAM,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,cAAc,CAAC;AAEtJ,MAAM,MAAM,cAAc,CAAC,GAAG,SAAS,MAAM,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,CACjG,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,EAC3B,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,EAChC,KAAK,CAAC,cAAc,CACpB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,GAAG,IAAI,EAAE,KAAK,KAAK;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE/F,MAAM,
|
|
1
|
+
{"version":3,"file":"rejection.d.ts","sourceRoot":"","sources":["../src/rejection.ts"],"names":[],"mappings":"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"}
|
package/dist/rejection.js
CHANGED
|
@@ -5,9 +5,9 @@ export function rejectionSet(specs) {
|
|
|
5
5
|
Schema.isSchema(spec) ? spec : Schema.TaggedError()(tag, spec),
|
|
6
6
|
]);
|
|
7
7
|
return {
|
|
8
|
+
error: classes.length === 0 ? Schema.Never : Schema.Union(classes.map(([, schema]) => schema)),
|
|
8
9
|
Rejection: Object.fromEntries(classes),
|
|
9
10
|
reject: Object.fromEntries(classes.map(([tag, Rejection]) => [tag, (...args) => Effect.fail(Reflect.construct(Rejection, args))])),
|
|
10
|
-
error: classes.length === 0 ? Schema.Never : Schema.Union(classes.map(([, schema]) => schema)),
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
13
|
export function fieldRejection(struct, fields) {
|
package/dist/rejection.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rejection.js","sourceRoot":"","sources":["../src/rejection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"rejection.js","sourceRoot":"","sources":["../src/rejection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AA6DpD,MAAM,UAAU,YAAY,CAAC,KAAqB;IACjD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,EAAsC,EAAE,CAAC;QAC9F,GAAG;QACH,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,EAAwB,CAAC,GAAG,EAAE,IAAI,CAAC;KACpF,CAAC,CAAC;IACH,OAAO;QACN,KAAK,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;QAC9F,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC;QACtC,MAAM,EAAE,MAAM,CAAC,WAAW,CACzB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,IAAwB,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAC1H;KACD,CAAC;AACH,CAAC;AAYD,MAAM,UAAU,cAAc,CAAC,MAAiD,EAAE,MAA0B;IAC3G,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AACjG,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,28 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shivaedev/effect-contract",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Typed query and command contracts over native Effect RPC and reactivity",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"repository": {
|
|
8
|
-
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/ShivaeDev/platform.git",
|
|
10
|
-
"directory": "packages/effect-contract"
|
|
11
|
-
},
|
|
12
5
|
"homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/effect-contract#readme",
|
|
13
6
|
"bugs": {
|
|
14
7
|
"url": "https://github.com/ShivaeDev/platform/issues"
|
|
15
8
|
},
|
|
16
|
-
"
|
|
17
|
-
"
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/ShivaeDev/platform.git",
|
|
12
|
+
"directory": "packages/effect-contract"
|
|
18
13
|
},
|
|
14
|
+
"license": "MIT",
|
|
19
15
|
"sideEffects": false,
|
|
20
|
-
"
|
|
21
|
-
"dist",
|
|
22
|
-
"src",
|
|
23
|
-
"CHANGELOG.md",
|
|
24
|
-
"README.md"
|
|
25
|
-
],
|
|
16
|
+
"type": "module",
|
|
26
17
|
"exports": {
|
|
27
18
|
".": {
|
|
28
19
|
"types": "./dist/index.d.ts",
|
|
@@ -32,28 +23,38 @@
|
|
|
32
23
|
},
|
|
33
24
|
"./package.json": "./package.json"
|
|
34
25
|
},
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"src",
|
|
29
|
+
"CHANGELOG.md",
|
|
30
|
+
"README.md"
|
|
31
|
+
],
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@shivaedev/types": "0.1.0"
|
|
41
34
|
},
|
|
42
35
|
"devDependencies": {
|
|
43
36
|
"@effect/vitest": "4.0.0-rc.112",
|
|
37
|
+
"@shivaedev/quality": "0.7.0",
|
|
44
38
|
"@types/node": "24.10.1",
|
|
45
39
|
"@typescript/native": "npm:typescript@7.0.2",
|
|
46
40
|
"effect": "4.0.0-rc.112",
|
|
47
41
|
"typescript": "npm:@typescript/typescript6@6.0.2",
|
|
48
42
|
"vitest": "4.1.9"
|
|
49
43
|
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"effect": "4.0.0-rc.112"
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=24"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public",
|
|
52
|
+
"provenance": true
|
|
53
|
+
},
|
|
50
54
|
"scripts": {
|
|
51
55
|
"build": "node --eval \"import('node:fs').then(({ rmSync }) => rmSync('dist', { force: true, recursive: true }))\" && tsc6 --project tsconfig.build.json",
|
|
52
|
-
"
|
|
56
|
+
"ready": "pnpm typecheck && pnpm test && pnpm build",
|
|
53
57
|
"test": "vitest run",
|
|
54
|
-
"
|
|
55
|
-
"typecheck": "tsc --noEmit",
|
|
56
|
-
"typecheck:compat": "tsc6 --noEmit",
|
|
57
|
-
"ready": "pnpm check && pnpm typecheck && pnpm typecheck:compat && pnpm test && pnpm build && pnpm test:package"
|
|
58
|
+
"typecheck": "tsc --noEmit"
|
|
58
59
|
}
|
|
59
60
|
}
|
package/src/bind.ts
CHANGED
|
@@ -23,8 +23,8 @@ export type RunFailure<R extends Rpc.Any> =
|
|
|
23
23
|
|
|
24
24
|
export interface QueryOptions {
|
|
25
25
|
readonly headers?: Headers.Input;
|
|
26
|
-
readonly timeToLive?: Duration.Input;
|
|
27
26
|
readonly serializationKey?: string;
|
|
27
|
+
readonly timeToLive?: Duration.Input;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
export interface BoundQuery<R extends Rpc.Any, Self> {
|
|
@@ -38,8 +38,8 @@ export interface BoundCommand<R extends Rpc.Any, Self> {
|
|
|
38
38
|
|
|
39
39
|
export type Bound<
|
|
40
40
|
Name extends string,
|
|
41
|
-
Queries extends
|
|
42
|
-
Commands extends
|
|
41
|
+
Queries extends readonly QueryShape[],
|
|
42
|
+
Commands extends readonly CommandShape[],
|
|
43
43
|
Rpcs extends Rpc.Any,
|
|
44
44
|
Self,
|
|
45
45
|
> = {
|
|
@@ -50,7 +50,7 @@ export type Bound<
|
|
|
50
50
|
|
|
51
51
|
type ErasedClient = AtomRpc.AtomRpcClient<unknown, string, Rpc.Rpc<string, Schema.Top, Schema.Top, Schema.Top>>;
|
|
52
52
|
|
|
53
|
-
const invalidateAfter = Effect.fn("EffectContract.invalidate")(function* (keys:
|
|
53
|
+
const invalidateAfter = Effect.fn("EffectContract.invalidate")(function* (keys: readonly Key[]) {
|
|
54
54
|
yield* Reactivity.invalidate(invalidationKeys(keys));
|
|
55
55
|
});
|
|
56
56
|
|
|
@@ -69,14 +69,14 @@ const boundCommand = (service: ErasedClient, tag: string, command: CommandShape)
|
|
|
69
69
|
|
|
70
70
|
export function bind<
|
|
71
71
|
Name extends string,
|
|
72
|
-
Queries extends
|
|
73
|
-
Commands extends
|
|
72
|
+
Queries extends readonly QueryShape[],
|
|
73
|
+
Commands extends readonly CommandShape[],
|
|
74
74
|
Rpcs extends Rpc.Any,
|
|
75
75
|
Self,
|
|
76
76
|
Id extends string,
|
|
77
77
|
>(contract: Contract<Name, Queries, Commands, Rpcs>, service: AtomRpc.AtomRpcClient<Self, Id, Rpcs>): Bound<Name, Queries, Commands, Rpcs, Self>;
|
|
78
78
|
export function bind(
|
|
79
|
-
contract: { readonly declaration: Declared<string,
|
|
79
|
+
contract: { readonly declaration: Declared<string, readonly QueryShape[], readonly CommandShape[]> },
|
|
80
80
|
service: ErasedClient,
|
|
81
81
|
): unknown {
|
|
82
82
|
const { name, queries, commands } = contract.declaration;
|
package/src/contract.ts
CHANGED
|
@@ -7,42 +7,44 @@ export type OperationRpc<Contract extends string, Operation> = Operation extends
|
|
|
7
7
|
? Rpc.Rpc<Tag<Contract, Operation["name"]>, Operation["payload"], Operation["success"], Operation["error"]>
|
|
8
8
|
: never;
|
|
9
9
|
|
|
10
|
-
export interface Declared<Name extends string, Queries extends
|
|
10
|
+
export interface Declared<Name extends string, Queries extends readonly QueryShape[], Commands extends readonly CommandShape[]> {
|
|
11
|
+
readonly commands: Commands;
|
|
11
12
|
readonly name: Name;
|
|
12
13
|
readonly queries: Queries;
|
|
13
|
-
readonly commands: Commands;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export interface Contract<
|
|
17
17
|
Name extends string,
|
|
18
|
-
Queries extends
|
|
19
|
-
Commands extends
|
|
18
|
+
Queries extends readonly QueryShape[],
|
|
19
|
+
Commands extends readonly CommandShape[],
|
|
20
20
|
Rpcs extends Rpc.Any = OperationRpc<Name, Queries[number] | Commands[number]>,
|
|
21
21
|
> extends RpcGroup.RpcGroup<Rpcs> {
|
|
22
22
|
readonly declaration: Declared<Name, Queries, Commands>;
|
|
23
|
-
middleware<M extends RpcMiddleware.AnyService>(middleware: M)
|
|
23
|
+
middleware: <M extends RpcMiddleware.AnyService>(middleware: M) => Contract<Name, Queries, Commands, Rpc.AddMiddleware<Rpcs, M>>;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
type Duplicated<Operations extends
|
|
26
|
+
type Duplicated<Operations extends readonly OperationShape[], Seen extends string = never> = Operations extends readonly [
|
|
27
27
|
infer Head extends OperationShape,
|
|
28
|
-
...infer Tail extends
|
|
28
|
+
...infer Tail extends readonly OperationShape[],
|
|
29
29
|
]
|
|
30
30
|
? (Head["name"] extends Seen ? Head["name"] : never) | Duplicated<Tail, Seen | Head["name"]>
|
|
31
31
|
: never;
|
|
32
32
|
|
|
33
|
-
type Unique<Operations extends
|
|
33
|
+
type Unique<Operations extends readonly OperationShape[]> = [Duplicated<Operations>] extends [never]
|
|
34
34
|
? unknown
|
|
35
35
|
: `Operation names must be unique; duplicated: ${Duplicated<Operations>}`;
|
|
36
36
|
|
|
37
|
-
const assertUnique = (operations:
|
|
37
|
+
const assertUnique = (operations: readonly OperationShape[]) => {
|
|
38
38
|
const duplicated = operations.map(({ name }) => name).filter((name, index, names) => names.indexOf(name) !== index);
|
|
39
|
-
if (duplicated.length > 0)
|
|
39
|
+
if (duplicated.length > 0) {
|
|
40
|
+
throw new Error(`Operation names must be unique; duplicated: ${[...new Set(duplicated)].join(", ")}`);
|
|
41
|
+
}
|
|
40
42
|
};
|
|
41
43
|
|
|
42
|
-
type AnyDeclared = Declared<string,
|
|
44
|
+
type AnyDeclared = Declared<string, readonly QueryShape[], readonly CommandShape[]>;
|
|
43
45
|
|
|
44
46
|
interface Group {
|
|
45
|
-
middleware(middleware: RpcMiddleware.AnyService)
|
|
47
|
+
middleware: (middleware: RpcMiddleware.AnyService) => Group;
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
interface DeclaredGroup extends Group {
|
|
@@ -59,20 +61,20 @@ const withDeclaration = (group: Group, declaration: AnyDeclared): DeclaredGroup
|
|
|
59
61
|
|
|
60
62
|
export function contract<
|
|
61
63
|
const Name extends string,
|
|
62
|
-
const Queries extends
|
|
63
|
-
const Commands extends
|
|
64
|
+
const Queries extends readonly QueryShape[] = readonly [],
|
|
65
|
+
const Commands extends readonly CommandShape[] = readonly [],
|
|
64
66
|
>(
|
|
65
67
|
name: Name,
|
|
66
68
|
operations: { readonly queries?: Queries & Unique<Queries>; readonly commands?: Commands & Unique<[...Queries, ...Commands]> },
|
|
67
69
|
): Contract<Name, Queries, Commands>;
|
|
68
70
|
export function contract(
|
|
69
71
|
name: string,
|
|
70
|
-
operations: { readonly queries?:
|
|
72
|
+
operations: { readonly queries?: readonly QueryShape[]; readonly commands?: readonly CommandShape[] },
|
|
71
73
|
): DeclaredGroup {
|
|
72
74
|
const { queries = [], commands = [] } = operations;
|
|
73
75
|
assertUnique([...queries, ...commands]);
|
|
74
76
|
const rpcs = [...queries, ...commands].map((operation) =>
|
|
75
|
-
Rpc.make(`${name}.${operation.name}`, {
|
|
77
|
+
Rpc.make(`${name}.${operation.name}`, { error: operation.error, payload: operation.payload, success: operation.success }),
|
|
76
78
|
);
|
|
77
|
-
return withDeclaration(RpcGroup.make(...rpcs), { name, queries
|
|
79
|
+
return withDeclaration(RpcGroup.make(...rpcs), { commands, name, queries });
|
|
78
80
|
}
|
package/src/keys.ts
CHANGED
|
@@ -16,24 +16,24 @@ export interface ItemKey<Name extends string = string> {
|
|
|
16
16
|
export type Key = ListKey | ItemKey;
|
|
17
17
|
|
|
18
18
|
export interface Collection<Name extends string, Id extends Identity> {
|
|
19
|
-
readonly name: Name;
|
|
20
|
-
readonly list: ListKey<Name>;
|
|
21
19
|
readonly item: (id: Id) => ItemKey<Name>;
|
|
20
|
+
readonly list: ListKey<Name>;
|
|
21
|
+
readonly name: Name;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export const collection = <const Name extends string, Id extends Schema.Top & { readonly Type: Identity }>(
|
|
25
25
|
name: Name,
|
|
26
26
|
_id: Id,
|
|
27
27
|
): Collection<Name, Id["Type"]> => ({
|
|
28
|
-
name,
|
|
29
|
-
list: { _tag: "List", collection: name },
|
|
30
28
|
item: (id) => ({ _tag: "Item", collection: name, id }),
|
|
29
|
+
list: { _tag: "List", collection: name },
|
|
30
|
+
name,
|
|
31
31
|
});
|
|
32
32
|
|
|
33
33
|
const own = (key: Key): string => (key._tag === "List" ? key.collection : `${key.collection}:${key.id}`);
|
|
34
34
|
|
|
35
|
-
export const readKeys = (keys:
|
|
35
|
+
export const readKeys = (keys: readonly Key[]): readonly string[] => [...new Set(keys.map(own))];
|
|
36
36
|
|
|
37
|
-
export const invalidationKeys = (keys:
|
|
37
|
+
export const invalidationKeys = (keys: readonly Key[]): readonly string[] => [
|
|
38
38
|
...new Set(keys.flatMap((key) => (key._tag === "List" ? [key.collection] : [own(key), key.collection]))),
|
|
39
39
|
];
|
package/src/operation.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
|
+
import type { Bivariant } from "@shivaedev/types";
|
|
2
3
|
import type { Key } from "./keys.ts";
|
|
3
4
|
import { type MatchingTags, type Reject, type RejectionSpecs, type Rejections, type RejectionUnion, rejectionSet } from "./rejection.ts";
|
|
4
5
|
|
|
@@ -9,63 +10,65 @@ export type PayloadSchema<Payload extends Schema.Top | Schema.Struct.Fields> = P
|
|
|
9
10
|
type NoRejections = Record<never, never>;
|
|
10
11
|
|
|
11
12
|
export interface OperationShape {
|
|
13
|
+
readonly error: Schema.Top;
|
|
12
14
|
readonly kind: "query" | "command";
|
|
13
15
|
readonly name: string;
|
|
14
16
|
readonly payload: Schema.Top;
|
|
15
|
-
readonly success: Schema.Top;
|
|
16
|
-
readonly error: Schema.Top;
|
|
17
|
-
readonly rejections: RejectionSpecs;
|
|
18
17
|
readonly Rejection: object;
|
|
19
18
|
readonly reject: object;
|
|
19
|
+
readonly rejections: RejectionSpecs;
|
|
20
|
+
readonly success: Schema.Top;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
export interface QueryShape extends OperationShape {
|
|
23
24
|
readonly kind: "query";
|
|
24
|
-
reads(payload: unknown)
|
|
25
|
+
reads: Bivariant<(payload: unknown) => readonly Key[]>;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
export interface CommandShape extends OperationShape {
|
|
29
|
+
invalidates: Bivariant<(payload: unknown, result: unknown) => readonly Key[]>;
|
|
28
30
|
readonly kind: "command";
|
|
29
|
-
invalidates(payload: unknown, result: unknown): ReadonlyArray<Key>;
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
interface Operation<Name extends string, Payload extends Schema.Top, Success extends Schema.Top, Specs extends RejectionSpecs>
|
|
33
34
|
extends OperationShape {
|
|
35
|
+
readonly error: RejectionUnion<Specs>;
|
|
34
36
|
readonly name: Name;
|
|
35
37
|
readonly payload: Payload;
|
|
36
|
-
readonly success: Success;
|
|
37
|
-
readonly error: RejectionUnion<Specs>;
|
|
38
|
-
readonly rejections: Specs;
|
|
39
38
|
readonly Rejection: Rejections<Specs>;
|
|
40
39
|
readonly reject: Reject<Specs>;
|
|
40
|
+
readonly rejections: Specs;
|
|
41
|
+
readonly success: Success;
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
export interface Query<Name extends string, Payload extends Schema.Top, Success extends Schema.Top, Specs extends RejectionSpecs>
|
|
44
45
|
extends Operation<Name, Payload, Success, Specs> {
|
|
45
46
|
readonly kind: "query";
|
|
46
|
-
reads(payload: Payload["Type"])
|
|
47
|
+
reads: (payload: Payload["Type"]) => readonly Key[];
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
export interface Command<Name extends string, Payload extends Schema.Top, Success extends Schema.Top, Specs extends RejectionSpecs>
|
|
50
51
|
extends Operation<Name, Payload, Success, Specs> {
|
|
52
|
+
invalidates: (payload: Payload["Type"], result: Success["Type"]) => readonly Key[];
|
|
51
53
|
readonly kind: "command";
|
|
52
|
-
invalidates(payload: Payload["Type"], result: Success["Type"]): ReadonlyArray<Key>;
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
interface Declaration<Payload extends Schema.Top | Schema.Struct.Fields, Success extends Schema.Top, Specs extends RejectionSpecs> {
|
|
56
57
|
readonly payload?: Payload;
|
|
57
|
-
readonly success?: Success;
|
|
58
58
|
readonly rejections?: Specs & MatchingTags<Specs>;
|
|
59
|
+
readonly success?: Success;
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
interface Loose {
|
|
62
63
|
readonly payload?: Schema.Top | Schema.Struct.Fields;
|
|
63
|
-
readonly success?: Schema.Top;
|
|
64
64
|
readonly rejections?: RejectionSpecs;
|
|
65
|
+
readonly success?: Schema.Top;
|
|
65
66
|
}
|
|
66
67
|
|
|
67
68
|
const payloadSchema = (payload: Loose["payload"]): Schema.Top => {
|
|
68
|
-
if (payload === undefined)
|
|
69
|
+
if (payload === undefined) {
|
|
70
|
+
return Schema.Void;
|
|
71
|
+
}
|
|
69
72
|
return Schema.isSchema(payload) ? payload : Schema.Struct(payload);
|
|
70
73
|
};
|
|
71
74
|
|
|
@@ -75,8 +78,8 @@ const operation = <Kind extends OperationShape["kind"]>(kind: Kind, name: string
|
|
|
75
78
|
kind,
|
|
76
79
|
name,
|
|
77
80
|
payload: payloadSchema(payload),
|
|
78
|
-
success: success ?? Schema.Void,
|
|
79
81
|
rejections,
|
|
82
|
+
success: success ?? Schema.Void,
|
|
80
83
|
...rejectionSet(rejections),
|
|
81
84
|
};
|
|
82
85
|
};
|
|
@@ -89,10 +92,10 @@ export function query<
|
|
|
89
92
|
>(
|
|
90
93
|
name: Name,
|
|
91
94
|
declaration: Declaration<Payload, Success, Specs> & {
|
|
92
|
-
readonly reads: (payload: PayloadSchema<Payload>["Type"]) =>
|
|
95
|
+
readonly reads: (payload: PayloadSchema<Payload>["Type"]) => readonly Key[];
|
|
93
96
|
},
|
|
94
97
|
): NoInfer<Query<Name, PayloadSchema<Payload>, Success, Specs>>;
|
|
95
|
-
export function query(name: string, declaration: Loose & { readonly reads: (payload: unknown) =>
|
|
98
|
+
export function query(name: string, declaration: Loose & { readonly reads: (payload: unknown) => readonly Key[] }): QueryShape {
|
|
96
99
|
return { ...operation("query", name, declaration), reads: declaration.reads };
|
|
97
100
|
}
|
|
98
101
|
|
|
@@ -104,12 +107,12 @@ export function command<
|
|
|
104
107
|
>(
|
|
105
108
|
name: Name,
|
|
106
109
|
declaration: Declaration<Payload, Success, Specs> & {
|
|
107
|
-
readonly invalidates: (payload: PayloadSchema<Payload>["Type"], result: Success["Type"]) =>
|
|
110
|
+
readonly invalidates: (payload: PayloadSchema<Payload>["Type"], result: Success["Type"]) => readonly Key[];
|
|
108
111
|
},
|
|
109
112
|
): NoInfer<Command<Name, PayloadSchema<Payload>, Success, Specs>>;
|
|
110
113
|
export function command(
|
|
111
114
|
name: string,
|
|
112
|
-
declaration: Loose & { readonly invalidates: (payload: unknown, result: unknown) =>
|
|
115
|
+
declaration: Loose & { readonly invalidates: (payload: unknown, result: unknown) => readonly Key[] },
|
|
113
116
|
): CommandShape {
|
|
114
117
|
return { ...operation("command", name, declaration), invalidates: declaration.invalidates };
|
|
115
118
|
}
|
package/src/rejection.ts
CHANGED
|
@@ -10,7 +10,9 @@ export type RejectionClass<Tag extends string, Fields extends Schema.Struct.Fiel
|
|
|
10
10
|
|
|
11
11
|
export type TaggedRejection = Schema.Top & (new (...args: never) => { readonly _tag: string });
|
|
12
12
|
|
|
13
|
-
export
|
|
13
|
+
export interface RejectionSpecs {
|
|
14
|
+
readonly [tag: string]: Schema.Struct.Fields | TaggedRejection;
|
|
15
|
+
}
|
|
14
16
|
|
|
15
17
|
export type Rejections<Specs extends RejectionSpecs> = {
|
|
16
18
|
readonly [Tag in keyof Specs & string]: Specs[Tag] extends TaggedRejection
|
|
@@ -34,7 +36,7 @@ export type Reject<Specs extends RejectionSpecs> = {
|
|
|
34
36
|
|
|
35
37
|
export type RejectionUnion<Specs extends RejectionSpecs> = [keyof Specs & string] extends [never]
|
|
36
38
|
? Schema.Never
|
|
37
|
-
: Schema.Union<
|
|
39
|
+
: Schema.Union<readonly Rejections<Specs>[keyof Specs & string][]>;
|
|
38
40
|
|
|
39
41
|
export type MatchingTags<Specs extends RejectionSpecs> = {
|
|
40
42
|
readonly [Tag in keyof Specs]: Specs[Tag] extends TaggedRejection
|
|
@@ -45,15 +47,15 @@ export type MatchingTags<Specs extends RejectionSpecs> = {
|
|
|
45
47
|
};
|
|
46
48
|
|
|
47
49
|
export interface RejectionSet<Specs extends RejectionSpecs> {
|
|
50
|
+
readonly error: RejectionUnion<Specs>;
|
|
48
51
|
readonly Rejection: Rejections<Specs>;
|
|
49
52
|
readonly reject: Reject<Specs>;
|
|
50
|
-
readonly error: RejectionUnion<Specs>;
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
interface LooseRejectionSet {
|
|
54
|
-
readonly Rejection: { readonly [tag: string]: TaggedRejection };
|
|
55
|
-
readonly reject: { readonly [tag: string]: (...args: ReadonlyArray<unknown>) => Effect.Effect<never, unknown> };
|
|
56
56
|
readonly error: Schema.Top;
|
|
57
|
+
readonly Rejection: { readonly [tag: string]: TaggedRejection };
|
|
58
|
+
readonly reject: { readonly [tag: string]: (...args: readonly unknown[]) => Effect.Effect<never, unknown> };
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
export function rejectionSet<const Specs extends RejectionSpecs>(specs: Specs): RejectionSet<Specs>;
|
|
@@ -63,24 +65,24 @@ export function rejectionSet(specs: RejectionSpecs): LooseRejectionSet {
|
|
|
63
65
|
Schema.isSchema(spec) ? spec : Schema.TaggedError<Cause.YieldableError>()(tag, spec),
|
|
64
66
|
]);
|
|
65
67
|
return {
|
|
68
|
+
error: classes.length === 0 ? Schema.Never : Schema.Union(classes.map(([, schema]) => schema)),
|
|
66
69
|
Rejection: Object.fromEntries(classes),
|
|
67
70
|
reject: Object.fromEntries(
|
|
68
|
-
classes.map(([tag, Rejection]) => [tag, (...args:
|
|
71
|
+
classes.map(([tag, Rejection]) => [tag, (...args: readonly unknown[]) => Effect.fail(Reflect.construct(Rejection, args))]),
|
|
69
72
|
),
|
|
70
|
-
error: classes.length === 0 ? Schema.Never : Schema.Union(classes.map(([, schema]) => schema)),
|
|
71
73
|
};
|
|
72
74
|
}
|
|
73
75
|
|
|
74
|
-
export type FieldRejection<Field extends string> = {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
76
|
+
export type FieldRejection<Field extends string> = Readonly<{
|
|
77
|
+
field: Schema.Literals<readonly Field[]>;
|
|
78
|
+
message: Schema.String;
|
|
79
|
+
}>;
|
|
78
80
|
|
|
79
81
|
export function fieldRejection<const Fields extends Schema.Struct.Fields>(struct: { readonly fields: Fields }): FieldRejection<keyof Fields & string>;
|
|
80
82
|
export function fieldRejection<const Fields extends Schema.Struct.Fields, const Field extends keyof Fields & string>(
|
|
81
83
|
struct: { readonly fields: Fields },
|
|
82
|
-
fields:
|
|
84
|
+
fields: readonly Field[],
|
|
83
85
|
): FieldRejection<Field>;
|
|
84
|
-
export function fieldRejection(struct: { readonly fields: Schema.Struct.Fields }, fields?:
|
|
86
|
+
export function fieldRejection(struct: { readonly fields: Schema.Struct.Fields }, fields?: readonly string[]): FieldRejection<string> {
|
|
85
87
|
return { field: Schema.Literals(fields ?? Object.keys(struct.fields)), message: Schema.String };
|
|
86
88
|
}
|