foldkit 0.165.0 → 0.166.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/devTools/serialize.d.ts +8 -4
- package/dist/devTools/serialize.d.ts.map +1 -1
- package/dist/devTools/serialize.js +12 -8
- package/dist/experimental/index.d.ts +1 -0
- package/dist/experimental/index.d.ts.map +1 -1
- package/dist/experimental/index.js +1 -0
- package/dist/experimental/query/define.d.ts +15 -0
- package/dist/experimental/query/define.d.ts.map +1 -0
- package/dist/experimental/query/define.js +10 -0
- package/dist/experimental/query/index.d.ts +4 -0
- package/dist/experimental/query/index.d.ts.map +1 -0
- package/dist/experimental/query/index.js +1 -0
- package/dist/experimental/query/internal.d.ts +57 -0
- package/dist/experimental/query/internal.d.ts.map +1 -0
- package/dist/experimental/query/internal.js +25 -0
- package/dist/experimental/query/keyedQuery.d.ts +89 -0
- package/dist/experimental/query/keyedQuery.d.ts.map +1 -0
- package/dist/experimental/query/keyedQuery.js +144 -0
- package/dist/experimental/query/public.d.ts +4 -0
- package/dist/experimental/query/public.d.ts.map +1 -0
- package/dist/experimental/query/public.js +1 -0
- package/dist/experimental/query/query.d.ts +78 -0
- package/dist/experimental/query/query.d.ts.map +1 -0
- package/dist/experimental/query/query.js +102 -0
- package/dist/managedResource/managedResource.d.ts +7 -7
- package/dist/managedResource/managedResource.d.ts.map +1 -1
- package/dist/managedResource/managedResource.js +7 -7
- package/dist/runtime/devToolsConfig.d.ts +2 -0
- package/dist/runtime/devToolsConfig.d.ts.map +1 -1
- package/dist/subscription/subscription.d.ts +33 -72
- package/dist/subscription/subscription.d.ts.map +1 -1
- package/dist/subscription/subscription.js +31 -61
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<a href="https://www.npmjs.com/package/foldkit"><img src="https://img.shields.io/npm/v/foldkit" alt="npm version"></a>
|
|
11
11
|
</p>
|
|
12
12
|
|
|
13
|
-
<h3 align="center">
|
|
13
|
+
<h3 align="center">Build faster. Understand what ships.</h3>
|
|
14
14
|
|
|
15
15
|
<p align="center">
|
|
16
16
|
<a href="https://foldkit.dev"><strong>Documentation</strong></a> · <a href="https://foldkit.dev/introduction/why-foldkit"><strong>Why Foldkit</strong></a> · <a href="https://foldkit.dev/example-apps"><strong>Examples</strong></a> · <a href="https://foldkit.dev/get-started"><strong>Get Started</strong></a> · <a href="https://discord.gg/kav8VNxqGm"><strong>Discord</strong></a>
|
|
@@ -153,6 +153,7 @@ Some of what you can build with Foldkit. [See all example apps on foldkit.dev](h
|
|
|
153
153
|
- **[Job Application](https://foldkit.dev/example-apps/job-application)**: Multi-step form with cross-field validation, file uploads, and per-step error indicators
|
|
154
154
|
- **[Weather](https://foldkit.dev/example-apps/weather)**: HTTP requests with async state handling
|
|
155
155
|
- **[API Cache](https://foldkit.dev/example-apps/api-cache)**: Query caching with stale-while-revalidate, request deduplication, and interval refetching
|
|
156
|
+
- **[API Cache Query](https://foldkit.dev/example-apps/api-cache-query)**: The same app with experimental `Query.define` owning fetch and keyed slots
|
|
156
157
|
- **[Routing](https://foldkit.dev/example-apps/routing)**: URL routing with parser combinators
|
|
157
158
|
- **[Route Transitions](https://foldkit.dev/example-apps/route-transitions)**: Live transition log with entry, exit, and stayed navigation policies
|
|
158
159
|
- **[Query Sync](https://foldkit.dev/example-apps/query-sync)**: URL query parameter sync with filtering and sorting
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { SerializedCommand, SerializedEntry, SerializedMount } from './protocol.js';
|
|
2
2
|
import type { CommandRecord, HistoryEntry, MountRecord } from './store.js';
|
|
3
3
|
/**
|
|
4
|
-
* Convert
|
|
4
|
+
* Convert Effect `Redacted` values to their labeled placeholder strings and
|
|
5
|
+
* DOM-class instances (File, Blob, Date, URL) to plain-object
|
|
5
6
|
* representations so the tree renderer's key-enumeration walk can see their
|
|
6
7
|
* meaningful data, which otherwise lives on the prototype as getters and
|
|
7
8
|
* is invisible to `Object.keys`. Recurses through arrays and records so
|
|
@@ -22,20 +23,23 @@ export declare const toInspectableValue: (value: unknown) => unknown;
|
|
|
22
23
|
/**
|
|
23
24
|
* Convert a runtime `CommandRecord` to its wire shape. Args are wrapped in an
|
|
24
25
|
* `Option` so `None` cleanly distinguishes argless Commands from Commands that
|
|
25
|
-
* happen to have an empty args record.
|
|
26
|
+
* happen to have an empty args record. Nested Effect `Redacted` values become
|
|
27
|
+
* their placeholder strings before transmission.
|
|
26
28
|
*/
|
|
27
29
|
export declare const toSerializedCommand: (command: CommandRecord) => SerializedCommand;
|
|
28
30
|
/**
|
|
29
31
|
* Convert a runtime `MountRecord` to its wire shape. Args are wrapped in an
|
|
30
32
|
* `Option` so `None` cleanly distinguishes argless Mounts from Mounts that
|
|
31
|
-
* happen to have an empty args record.
|
|
33
|
+
* happen to have an empty args record. Nested Effect `Redacted` values become
|
|
34
|
+
* their placeholder strings before transmission.
|
|
32
35
|
*/
|
|
33
36
|
export declare const toSerializedMount: (mount: MountRecord) => SerializedMount;
|
|
34
37
|
/**
|
|
35
38
|
* Convert a `HistoryEntry` plus its absolute index into the wire-friendly
|
|
36
39
|
* `SerializedEntry` shape. Flattens the diff's `HashSet` path collections to
|
|
37
40
|
* plain string arrays for JSON transmission and runs the message body through
|
|
38
|
-
* `toInspectableValue` so
|
|
41
|
+
* `toInspectableValue` so Effect `Redacted` values become placeholders and
|
|
42
|
+
* DOM-class instances become inspectable objects.
|
|
39
43
|
*/
|
|
40
44
|
export declare const toSerializedEntry: (entry: HistoryEntry, index: number) => SerializedEntry;
|
|
41
45
|
//# sourceMappingURL=serialize.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../../src/devTools/serialize.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../../src/devTools/serialize.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EACf,eAAe,EAChB,MAAM,eAAe,CAAA;AACtB,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAyB1E;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,kBAAkB,UAAW,OAAO,KAAG,OAUnD,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,YACrB,aAAa,KACrB,iBAOD,CAAA;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,UAAW,WAAW,KAAG,eAMrD,CAAA;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,UACrB,YAAY,SACZ,MAAM,KACZ,eAoBF,CAAA"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Array, Function, Match, Option, Predicate, Record } from 'effect';
|
|
1
|
+
import { Array, Function, Match, Option, Predicate, Record, Redacted, } from 'effect';
|
|
2
2
|
import { extractSubmodelInfo } from './submodelPath.js';
|
|
3
3
|
const inspectableCache = new WeakMap();
|
|
4
|
-
const computeInspectableValue = (value) => Match.value(value).pipe(Match.when(Match.instanceOf(File), file => ({
|
|
4
|
+
const computeInspectableValue = (value) => Match.value(value).pipe(Match.when(Redacted.isRedacted, globalThis.String), Match.when(Match.instanceOf(File), file => ({
|
|
5
5
|
name: file.name,
|
|
6
6
|
size: file.size,
|
|
7
7
|
type: file.type,
|
|
@@ -11,7 +11,8 @@ const computeInspectableValue = (value) => Match.value(value).pipe(Match.when(Ma
|
|
|
11
11
|
type: blob.type,
|
|
12
12
|
})), Match.when(Match.instanceOf(Date), date => date.toISOString()), Match.when(Match.instanceOf(URL), ({ href }) => href), Match.when(globalThis.Array.isArray, Array.map(toInspectableValue)), Match.when(Predicate.isObject, Record.map(toInspectableValue)), Match.orElse(Function.identity));
|
|
13
13
|
/**
|
|
14
|
-
* Convert
|
|
14
|
+
* Convert Effect `Redacted` values to their labeled placeholder strings and
|
|
15
|
+
* DOM-class instances (File, Blob, Date, URL) to plain-object
|
|
15
16
|
* representations so the tree renderer's key-enumeration walk can see their
|
|
16
17
|
* meaningful data, which otherwise lives on the prototype as getters and
|
|
17
18
|
* is invisible to `Object.keys`. Recurses through arrays and records so
|
|
@@ -42,27 +43,30 @@ export const toInspectableValue = (value) => {
|
|
|
42
43
|
/**
|
|
43
44
|
* Convert a runtime `CommandRecord` to its wire shape. Args are wrapped in an
|
|
44
45
|
* `Option` so `None` cleanly distinguishes argless Commands from Commands that
|
|
45
|
-
* happen to have an empty args record.
|
|
46
|
+
* happen to have an empty args record. Nested Effect `Redacted` values become
|
|
47
|
+
* their placeholder strings before transmission.
|
|
46
48
|
*/
|
|
47
49
|
export const toSerializedCommand = (command) => ({
|
|
48
50
|
name: command.name,
|
|
49
|
-
args: Option.fromNullishOr(command.args),
|
|
51
|
+
args: Option.map(Option.fromNullishOr(command.args), Record.map(toInspectableValue)),
|
|
50
52
|
maybeSubmodelPath: command.maybeSubmodelPath,
|
|
51
53
|
});
|
|
52
54
|
/**
|
|
53
55
|
* Convert a runtime `MountRecord` to its wire shape. Args are wrapped in an
|
|
54
56
|
* `Option` so `None` cleanly distinguishes argless Mounts from Mounts that
|
|
55
|
-
* happen to have an empty args record.
|
|
57
|
+
* happen to have an empty args record. Nested Effect `Redacted` values become
|
|
58
|
+
* their placeholder strings before transmission.
|
|
56
59
|
*/
|
|
57
60
|
export const toSerializedMount = (mount) => ({
|
|
58
61
|
name: mount.name,
|
|
59
|
-
args: Option.fromNullishOr(mount.args),
|
|
62
|
+
args: Option.map(Option.fromNullishOr(mount.args), Record.map(toInspectableValue)),
|
|
60
63
|
});
|
|
61
64
|
/**
|
|
62
65
|
* Convert a `HistoryEntry` plus its absolute index into the wire-friendly
|
|
63
66
|
* `SerializedEntry` shape. Flattens the diff's `HashSet` path collections to
|
|
64
67
|
* plain string arrays for JSON transmission and runs the message body through
|
|
65
|
-
* `toInspectableValue` so
|
|
68
|
+
* `toInspectableValue` so Effect `Redacted` values become placeholders and
|
|
69
|
+
* DOM-class instances become inspectable objects.
|
|
66
70
|
*/
|
|
67
71
|
export const toSerializedEntry = (entry, index) => {
|
|
68
72
|
const { submodelPath, maybeLeafTag } = extractSubmodelInfo(entry.tag, entry.message);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/experimental/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAA;AAC7C,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/experimental/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAA;AAC7C,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type KeyedQuery, type KeyedQueryConfig, type SyncFields } from './keyedQuery.js';
|
|
2
|
+
import { type Query, type QueryConfig } from './query.js';
|
|
3
|
+
/**
|
|
4
|
+
* Defines a Submodel that fetches data and retains it in the application
|
|
5
|
+
* Model. Add `args` to define a {@link KeyedQuery}; omit them to define a
|
|
6
|
+
* {@link Query}.
|
|
7
|
+
*
|
|
8
|
+
* @experimental Ships from `foldkit/experimental/query`; expect breaking changes while the API settles.
|
|
9
|
+
*/
|
|
10
|
+
export declare function define<Name extends string, A, AI, E, EI, Fields extends SyncFields, R = never>(config: KeyedQueryConfig<Name, A, AI, E, EI, Fields, R>): KeyedQuery<Name, A, AI, E, EI, Fields, R>;
|
|
11
|
+
export declare function define<Name extends string, A, AI, E, EI, R = never>(config: QueryConfig<Name, A, AI, E, EI, R> & {
|
|
12
|
+
readonly args?: never;
|
|
13
|
+
readonly toKey?: never;
|
|
14
|
+
}): Query<Name, A, AI, E, EI, R>;
|
|
15
|
+
//# sourceMappingURL=define.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../../src/experimental/query/define.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,UAAU,EAEhB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,WAAW,EAAe,MAAM,YAAY,CAAA;AA6BtE;;;;;;GAMG;AACH,wBAAgB,MAAM,CACpB,IAAI,SAAS,MAAM,EACnB,CAAC,EACD,EAAE,EACF,CAAC,EACD,EAAE,EACF,MAAM,SAAS,UAAU,EACzB,CAAC,GAAG,KAAK,EAET,MAAM,EAAE,gBAAgB,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,GACtD,UAAU,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;AAC5C,wBAAgB,MAAM,CAAC,IAAI,SAAS,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,KAAK,EACjE,MAAM,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG;IAC3C,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CACvB,GACA,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Predicate } from 'effect';
|
|
2
|
+
import { defineKeyedQuery, } from './keyedQuery.js';
|
|
3
|
+
import { defineQuery } from './query.js';
|
|
4
|
+
const isKeyedQueryConfig = (config) => Predicate.hasProperty(config, 'args');
|
|
5
|
+
export function define(config) {
|
|
6
|
+
if (isKeyedQueryConfig(config)) {
|
|
7
|
+
return defineKeyedQuery(config);
|
|
8
|
+
}
|
|
9
|
+
return defineQuery(config);
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/experimental/query/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AACjD,YAAY,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { define } from './define.js';
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Effect, Option, Schema } from 'effect';
|
|
2
|
+
import * as AsyncData from '../../asyncData/index.js';
|
|
3
|
+
import * as Command from '../../command/index.js';
|
|
4
|
+
import * as Update from '../../update/index.js';
|
|
5
|
+
export type FoldLens<ParentModel, ParentMessage, ChildModel, ChildMessage> = Pick<Update.ChildFold<ParentModel, ParentMessage, ChildModel, never, ChildMessage>, 'read' | 'write' | 'toParentMessage'>;
|
|
6
|
+
export type ParentFieldOf<ParentModel, ChildModel> = Extract<{
|
|
7
|
+
[K in keyof ParentModel]-?: ParentModel[K] extends ChildModel ? K : never;
|
|
8
|
+
}[keyof ParentModel], string>;
|
|
9
|
+
export type ParentFieldConfig<ParentModel, ParentMessage, ChildModel, ChildMessage> = Readonly<{
|
|
10
|
+
parentField: ParentFieldOf<ParentModel, ChildModel>;
|
|
11
|
+
toParentMessage: (message: ChildMessage) => ParentMessage;
|
|
12
|
+
}>;
|
|
13
|
+
export type LiftConfig<ParentModel, ParentMessage, ChildModel, ChildMessage> = ParentFieldConfig<ParentModel, ParentMessage, ChildModel, ChildMessage> | FoldLens<ParentModel, ParentMessage, ChildModel, ChildMessage>;
|
|
14
|
+
export type LiftQuery<ChildModel, ChildMessage, R> = {
|
|
15
|
+
<ParentModel, ParentMessage>(config: ParentFieldConfig<ParentModel, ParentMessage, ChildModel, ChildMessage>): LiftedQuery<ParentModel, ParentMessage, ChildMessage, R>;
|
|
16
|
+
<ParentModel, ParentMessage>(config: FoldLens<ParentModel, ParentMessage, ChildModel, ChildMessage>): LiftedQuery<ParentModel, ParentMessage, ChildMessage, R>;
|
|
17
|
+
};
|
|
18
|
+
export type LiftKeyedQuery<ChildModel, ChildMessage, Args, R> = {
|
|
19
|
+
<ParentModel, ParentMessage>(config: ParentFieldConfig<ParentModel, ParentMessage, ChildModel, ChildMessage>): LiftedKeyedQuery<ParentModel, ParentMessage, ChildMessage, Args, R>;
|
|
20
|
+
<ParentModel, ParentMessage>(config: FoldLens<ParentModel, ParentMessage, ChildModel, ChildMessage>): LiftedKeyedQuery<ParentModel, ParentMessage, ChildMessage, Args, R>;
|
|
21
|
+
};
|
|
22
|
+
export declare const isParentFieldConfig: <ParentModel, ParentMessage, ChildModel, ChildMessage>(config: LiftConfig<ParentModel, ParentMessage, ChildModel, ChildMessage>) => config is Extract<LiftConfig<ParentModel, ParentMessage, ChildModel, ChildMessage>, {
|
|
23
|
+
readonly parentField: string;
|
|
24
|
+
}>;
|
|
25
|
+
export declare const parentFieldToLens: <ParentModel extends Record<ParentFieldOf<ParentModel, ChildModel>, ChildModel>, ParentMessage, ChildModel, ChildMessage>(config: ParentFieldConfig<ParentModel, ParentMessage, ChildModel, ChildMessage>) => FoldLens<ParentModel, ParentMessage, ChildModel, ChildMessage>;
|
|
26
|
+
export declare const liftChildFold: <ParentModel, ParentMessage, ChildModel, ChildMessage, Input, R>(childFold: Update.Fold<ChildModel, ChildMessage, Input, R>, lens: FoldLens<ParentModel, ParentMessage, ChildModel, ChildMessage>) => Update.Fold<ParentModel, ParentMessage, Input, R>;
|
|
27
|
+
export type AsyncDataTransition = <A, E>(data: AsyncData.AsyncData<A, E>) => Option.Option<AsyncData.AsyncData<A, E>>;
|
|
28
|
+
export type QueryStore<Model, Args, A, E, Message, R> = Readonly<{
|
|
29
|
+
read: (model: Model, args: Args) => AsyncData.AsyncData<A, E>;
|
|
30
|
+
start: (model: Model, args: Args, data: AsyncData.AsyncData<A, E>) => Readonly<{
|
|
31
|
+
model: Model;
|
|
32
|
+
generation: number;
|
|
33
|
+
}>;
|
|
34
|
+
fetch: (args: Args, generation: number) => Command.Command<Message, never, R>;
|
|
35
|
+
}>;
|
|
36
|
+
export declare const applyTransition: <Model, Args, A, E, Message, R>(store: QueryStore<Model, Args, A, E, Message, R>, model: Model, args: Args, transition: AsyncDataTransition) => Update.Return<Model, Message, R>;
|
|
37
|
+
export declare const runExecute: <A, E, R>(execute: Effect.Effect<A, E, R>) => Effect.Effect<AsyncData.AsyncData<A, E>, never, R>;
|
|
38
|
+
export type CompletedFetchOf<Message extends Schema.Top> = Extract<Message['Type'], {
|
|
39
|
+
readonly _tag: 'CompletedFetch';
|
|
40
|
+
}>;
|
|
41
|
+
export type KeyedArgs<Fields extends Schema.Struct.Fields> = Schema.Schema.Type<Schema.Struct<Fields>>;
|
|
42
|
+
type LiftedQuery<ParentModel, ParentMessage, ChildMessage, R> = Readonly<{
|
|
43
|
+
fold: Update.Fold<ParentModel, ParentMessage, ChildMessage>;
|
|
44
|
+
reset: Update.Step<ParentModel, ParentMessage>;
|
|
45
|
+
revalidate: Update.Step<ParentModel, ParentMessage, R>;
|
|
46
|
+
revalidateOrLoad: Update.Step<ParentModel, ParentMessage, R>;
|
|
47
|
+
loadIfMissing: Update.Step<ParentModel, ParentMessage, R>;
|
|
48
|
+
}>;
|
|
49
|
+
type LiftedKeyedQuery<ParentModel, ParentMessage, ChildMessage, Args, R> = Readonly<{
|
|
50
|
+
fold: Update.Fold<ParentModel, ParentMessage, ChildMessage>;
|
|
51
|
+
reset: Update.Step<ParentModel, ParentMessage>;
|
|
52
|
+
revalidate: Update.Fold<ParentModel, ParentMessage, Args, R>;
|
|
53
|
+
revalidateOrLoad: Update.Fold<ParentModel, ParentMessage, Args, R>;
|
|
54
|
+
loadIfMissing: Update.Fold<ParentModel, ParentMessage, Args, R>;
|
|
55
|
+
}>;
|
|
56
|
+
export {};
|
|
57
|
+
//# sourceMappingURL=internal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../../src/experimental/query/internal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Effect, Option, Predicate, pipe } from 'effect';
|
|
2
|
+
import * as AsyncData from '../../asyncData/index.js';
|
|
3
|
+
import * as Update from '../../update/index.js';
|
|
4
|
+
export const isParentFieldConfig = (config) => Predicate.hasProperty(config, 'parentField');
|
|
5
|
+
const setField = (model, field, value) => ({ ...model, [field]: value });
|
|
6
|
+
export const parentFieldToLens = (config) => ({
|
|
7
|
+
read: (model) => Option.some(model[config.parentField]),
|
|
8
|
+
write: (model, nextChild) => setField(model, config.parentField, nextChild),
|
|
9
|
+
toParentMessage: config.toParentMessage,
|
|
10
|
+
});
|
|
11
|
+
export const liftChildFold = (childFold, lens) => Update.foldChild({
|
|
12
|
+
update: (childModel, input) => childFold(childModel, input),
|
|
13
|
+
...lens,
|
|
14
|
+
});
|
|
15
|
+
export const applyTransition = (store, model, args, transition) => Option.match(transition(store.read(model, args)), {
|
|
16
|
+
onNone: () => ({ model }),
|
|
17
|
+
onSome: nextData => {
|
|
18
|
+
const queryStart = store.start(model, args, nextData);
|
|
19
|
+
return {
|
|
20
|
+
model: queryStart.model,
|
|
21
|
+
commands: [store.fetch(args, queryStart.generation)],
|
|
22
|
+
};
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
export const runExecute = (execute) => pipe(execute, Effect.result, Effect.map(result => AsyncData.settle(AsyncData.Loading(), result)));
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Effect, Schema } from 'effect';
|
|
2
|
+
import * as AsyncData from '../../asyncData/index.js';
|
|
3
|
+
import * as Command from '../../command/index.js';
|
|
4
|
+
import * as Update from '../../update/index.js';
|
|
5
|
+
import { type CompletedFetchOf, type KeyedArgs, type LiftKeyedQuery } from './internal.js';
|
|
6
|
+
export type SyncFields = {
|
|
7
|
+
readonly [x: PropertyKey]: Schema.Codec<unknown, unknown, never, never>;
|
|
8
|
+
};
|
|
9
|
+
export type KeyedQueryConfig<Name extends string, A, AI, E, EI, Fields extends SyncFields, R> = Readonly<{
|
|
10
|
+
name: Name;
|
|
11
|
+
data: Schema.Codec<A, AI, never, never>;
|
|
12
|
+
error: Schema.Codec<E, EI, never, never>;
|
|
13
|
+
args: Fields;
|
|
14
|
+
toKey?: (args: Schema.Schema.Type<Schema.Struct<Fields>>) => string;
|
|
15
|
+
execute: (args: Schema.Schema.Type<Schema.Struct<Fields>>) => Effect.Effect<A, E, R>;
|
|
16
|
+
}>;
|
|
17
|
+
declare const makeKeyedQueryMessage: <A, AI, E, EI, Fields extends SyncFields>(data: Schema.Codec<A, AI>, error: Schema.Codec<E, EI>, Args: Schema.Struct<Fields>) => import("../../schema/index.js").MessageUnion<{
|
|
18
|
+
readonly CompletedFetch: {
|
|
19
|
+
args: Schema.Struct<Fields>;
|
|
20
|
+
generation: Schema.Number;
|
|
21
|
+
result: Schema.Result<Schema.Codec<A, AI, never, never>, Schema.Codec<E, EI, never, never>>;
|
|
22
|
+
};
|
|
23
|
+
}>;
|
|
24
|
+
/**
|
|
25
|
+
* Schema-backed Message union dispatched when a KeyedQuery fetch completes.
|
|
26
|
+
*
|
|
27
|
+
* @experimental Ships from `foldkit/experimental/query`; expect breaking changes while the API settles.
|
|
28
|
+
*/
|
|
29
|
+
export type KeyedQueryMessage<A, AI, E, EI, Fields extends SyncFields> = ReturnType<typeof makeKeyedQueryMessage<A, AI, E, EI, Fields>>;
|
|
30
|
+
/** Builds the Model Schema for a KeyedQuery. */
|
|
31
|
+
export declare const makeKeyedQueryModel: <A, AI, E, EI, Fields extends SyncFields>(data: Schema.Codec<A, AI>, error: Schema.Codec<E, EI>, Args: Schema.Struct<Fields>) => Schema.Struct<{
|
|
32
|
+
readonly generation: Schema.Number;
|
|
33
|
+
readonly entries: Schema.HashMap<Schema.String, Schema.Struct<{
|
|
34
|
+
readonly args: Schema.Struct<Fields>;
|
|
35
|
+
readonly data: Schema.Codec<AsyncData.AsyncData<A, E>, AsyncData.AsyncDataEncoded<AI, EI>, never, never>;
|
|
36
|
+
readonly generation: Schema.Number;
|
|
37
|
+
}>>;
|
|
38
|
+
}>;
|
|
39
|
+
/**
|
|
40
|
+
* Model Schema for a KeyedQuery containing retained `AsyncData` entries.
|
|
41
|
+
*
|
|
42
|
+
* @experimental Ships from `foldkit/experimental/query`; expect breaking changes while the API settles.
|
|
43
|
+
*/
|
|
44
|
+
export type KeyedQueryModel<A, AI, E, EI, Fields extends SyncFields> = ReturnType<typeof makeKeyedQueryModel<A, AI, E, EI, Fields>>;
|
|
45
|
+
/**
|
|
46
|
+
* Submodel for fetching and retaining `AsyncData` values by argument key.
|
|
47
|
+
*
|
|
48
|
+
* @experimental Ships from `foldkit/experimental/query`; expect breaking changes while the API settles.
|
|
49
|
+
*/
|
|
50
|
+
export interface KeyedQuery<Name extends string, A, AI, E, EI, Fields extends SyncFields, R = never> {
|
|
51
|
+
/** Schema for this KeyedQuery's Model. */
|
|
52
|
+
readonly Model: KeyedQueryModel<A, AI, E, EI, Fields>;
|
|
53
|
+
/** Schema-backed union of Messages handled by this KeyedQuery. */
|
|
54
|
+
readonly Message: KeyedQueryMessage<A, AI, E, EI, Fields>;
|
|
55
|
+
/**
|
|
56
|
+
* Command definition for matching this KeyedQuery's pending fetch in Story
|
|
57
|
+
* and Scene tests. Start fetches through a loading operation so the Model
|
|
58
|
+
* and request generation advance together; do not call this directly.
|
|
59
|
+
*/
|
|
60
|
+
readonly Fetch: Command.CommandDefinitionWithArgs<`Fetch${Name}`, {
|
|
61
|
+
readonly args: Schema.Struct<Fields>;
|
|
62
|
+
readonly generation: typeof Schema.Number;
|
|
63
|
+
}, Effect.Effect<CompletedFetchOf<KeyedQueryMessage<A, AI, E, EI, Fields>>, never, R>>;
|
|
64
|
+
/**
|
|
65
|
+
* Creates a KeyedQuery Model for initial parent Model construction. Never
|
|
66
|
+
* replace a live KeyedQuery with `init()`: it can reuse an in-flight request
|
|
67
|
+
* generation. Use `reset` instead.
|
|
68
|
+
*/
|
|
69
|
+
readonly init: () => KeyedQueryModel<A, AI, E, EI, Fields>['Type'];
|
|
70
|
+
/** Clears every entry while preserving request identity. */
|
|
71
|
+
readonly reset: (model: KeyedQueryModel<A, AI, E, EI, Fields>['Type']) => Update.Return<KeyedQueryModel<A, AI, E, EI, Fields>['Type'], KeyedQueryMessage<A, AI, E, EI, Fields>['Type']>;
|
|
72
|
+
/** Reads one entry, returning `Idle` when that entry does not exist. */
|
|
73
|
+
readonly read: (model: KeyedQueryModel<A, AI, E, EI, Fields>['Type'], args: KeyedArgs<Fields>) => AsyncData.AsyncData<A, E>;
|
|
74
|
+
/** Folds a keyed Fetch completion into the matching entry. */
|
|
75
|
+
readonly update: (model: KeyedQueryModel<A, AI, E, EI, Fields>['Type'], message: KeyedQueryMessage<A, AI, E, EI, Fields>['Type']) => Update.Return<KeyedQueryModel<A, AI, E, EI, Fields>['Type'], KeyedQueryMessage<A, AI, E, EI, Fields>['Type']>;
|
|
76
|
+
/** Refreshes a loaded entry and does nothing when it has no data. */
|
|
77
|
+
readonly revalidate: Update.Fold<KeyedQueryModel<A, AI, E, EI, Fields>['Type'], KeyedQueryMessage<A, AI, E, EI, Fields>['Type'], KeyedArgs<Fields>, R>;
|
|
78
|
+
/** Loads a missing entry or refreshes a loaded entry. */
|
|
79
|
+
readonly revalidateOrLoad: Update.Fold<KeyedQueryModel<A, AI, E, EI, Fields>['Type'], KeyedQueryMessage<A, AI, E, EI, Fields>['Type'], KeyedArgs<Fields>, R>;
|
|
80
|
+
/** Loads an entry only when it has no usable value. */
|
|
81
|
+
readonly loadIfMissing: Update.Fold<KeyedQueryModel<A, AI, E, EI, Fields>['Type'], KeyedQueryMessage<A, AI, E, EI, Fields>['Type'], KeyedArgs<Fields>, R>;
|
|
82
|
+
/** Lifts this KeyedQuery's update and loading operations into a parent Model. */
|
|
83
|
+
readonly lift: LiftKeyedQuery<KeyedQueryModel<A, AI, E, EI, Fields>['Type'], KeyedQueryMessage<A, AI, E, EI, Fields>['Type'], KeyedArgs<Fields>, R>;
|
|
84
|
+
/** Executes one keyed fetch directly and returns settled `AsyncData`. */
|
|
85
|
+
readonly run: (args: KeyedArgs<Fields>) => Effect.Effect<AsyncData.AsyncData<A, E>, never, R>;
|
|
86
|
+
}
|
|
87
|
+
export declare function defineKeyedQuery<Name extends string, A, AI, E, EI, Fields extends SyncFields, R>(config: KeyedQueryConfig<Name, A, AI, E, EI, Fields, R>): KeyedQuery<Name, A, AI, E, EI, Fields, R>;
|
|
88
|
+
export {};
|
|
89
|
+
//# sourceMappingURL=keyedQuery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyedQuery.d.ts","sourceRoot":"","sources":["../../../src/experimental/query/keyedQuery.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,MAAM,EAQN,MAAM,EAEP,MAAM,QAAQ,CAAA;AAEf,OAAO,KAAK,SAAS,MAAM,0BAA0B,CAAA;AACrD,OAAO,KAAK,OAAO,MAAM,wBAAwB,CAAA;AAGjD,OAAO,KAAK,MAAM,MAAM,uBAAuB,CAAA;AAC/C,OAAO,EAEL,KAAK,gBAAgB,EAErB,KAAK,SAAS,EAEd,KAAK,cAAc,EAQpB,MAAM,eAAe,CAAA;AAEtB,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;CACxE,CAAA;AA4CD,MAAM,MAAM,gBAAgB,CAC1B,IAAI,SAAS,MAAM,EACnB,CAAC,EACD,EAAE,EACF,CAAC,EACD,EAAE,EACF,MAAM,SAAS,UAAU,EACzB,CAAC,IACC,QAAQ,CAAC;IACX,IAAI,EAAE,IAAI,CAAA;IACV,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;IACvC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;IACxC,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,MAAM,CAAA;IACnE,OAAO,EAAE,CACP,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAC5C,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;CAC5B,CAAC,CAAA;AAEF,QAAA,MAAM,qBAAqB,GAAI,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,SAAS,UAAU,QAC9D,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,SAClB,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,QACpB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;;QAIvB,IAAI;QACJ,UAAU;QACV,MAAM;;EAER,CAAA;AAEJ;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,CAC3B,CAAC,EACD,EAAE,EACF,CAAC,EACD,EAAE,EACF,MAAM,SAAS,UAAU,IACvB,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,CAAA;AAElE,gDAAgD;AAChD,eAAO,MAAM,mBAAmB,GAAI,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,SAAS,UAAU,QACnE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,SAClB,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,QACpB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;;;;;;;EAe5B,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,eAAe,CACzB,CAAC,EACD,EAAE,EACF,CAAC,EACD,EAAE,EACF,MAAM,SAAS,UAAU,IACvB,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,CAAA;AAEhE;;;;GAIG;AACH,MAAM,WAAW,UAAU,CACzB,IAAI,SAAS,MAAM,EACnB,CAAC,EACD,EAAE,EACF,CAAC,EACD,EAAE,EACF,MAAM,SAAS,UAAU,EACzB,CAAC,GAAG,KAAK;IAET,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAA;IACrD,kEAAkE;IAClE,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAA;IACzD;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,yBAAyB,CAC/C,QAAQ,IAAI,EAAE,EACd;QACE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QACpC,QAAQ,CAAC,UAAU,EAAE,OAAO,MAAM,CAAC,MAAM,CAAA;KAC1C,EACD,MAAM,CAAC,MAAM,CACX,gBAAgB,CAAC,iBAAiB,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,EACzD,KAAK,EACL,CAAC,CACF,CACF,CAAA;IACD;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,eAAe,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;IAClE,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,EAAE,CACd,KAAK,EAAE,eAAe,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KACjD,MAAM,CAAC,MAAM,CAChB,eAAe,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,EAC7C,iBAAiB,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,CAChD,CAAA;IACD,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,CACb,KAAK,EAAE,eAAe,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,EACpD,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,KACpB,SAAS,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC9B,8DAA8D;IAC9D,QAAQ,CAAC,MAAM,EAAE,CACf,KAAK,EAAE,eAAe,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,EACpD,OAAO,EAAE,iBAAiB,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KACrD,MAAM,CAAC,MAAM,CAChB,eAAe,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,EAC7C,iBAAiB,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,CAChD,CAAA;IACD,qEAAqE;IACrE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,CAC9B,eAAe,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,EAC7C,iBAAiB,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,EAC/C,SAAS,CAAC,MAAM,CAAC,EACjB,CAAC,CACF,CAAA;IACD,yDAAyD;IACzD,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC,IAAI,CACpC,eAAe,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,EAC7C,iBAAiB,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,EAC/C,SAAS,CAAC,MAAM,CAAC,EACjB,CAAC,CACF,CAAA;IACD,uDAAuD;IACvD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,CACjC,eAAe,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,EAC7C,iBAAiB,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,EAC/C,SAAS,CAAC,MAAM,CAAC,EACjB,CAAC,CACF,CAAA;IACD,iFAAiF;IACjF,QAAQ,CAAC,IAAI,EAAE,cAAc,CAC3B,eAAe,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,EAC7C,iBAAiB,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,EAC/C,SAAS,CAAC,MAAM,CAAC,EACjB,CAAC,CACF,CAAA;IACD,yEAAyE;IACzE,QAAQ,CAAC,GAAG,EAAE,CACZ,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,KACpB,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;CACxD;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,SAAS,MAAM,EACnB,CAAC,EACD,EAAE,EACF,CAAC,EACD,EAAE,EACF,MAAM,SAAS,UAAU,EACzB,CAAC,EAED,MAAM,EAAE,gBAAgB,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,GACtD,UAAU,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAkK3C"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { Array, Effect, Function, HashMap, Number, Option, Order, Predicate, Record, Schema, pipe, } from 'effect';
|
|
2
|
+
import * as AsyncData from '../../asyncData/index.js';
|
|
3
|
+
import * as Command from '../../command/index.js';
|
|
4
|
+
import { defineMessageUnion } from '../../message/index.js';
|
|
5
|
+
import { modifyFields } from '../../struct/index.js';
|
|
6
|
+
import * as Update from '../../update/index.js';
|
|
7
|
+
import { applyTransition, isParentFieldConfig, liftChildFold, parentFieldToLens, runExecute, } from './internal.js';
|
|
8
|
+
const canonicalizeJsonEntry = ([key, value]) => [key, canonicalizeJson(value)];
|
|
9
|
+
const jsonEntryOrder = Order.mapInput(Order.String, ([key]) => key);
|
|
10
|
+
const isJsonObject = (value) => Predicate.isObject(value) && !globalThis.Array.isArray(value);
|
|
11
|
+
const canonicalizeJson = (value) => {
|
|
12
|
+
if (globalThis.Array.isArray(value)) {
|
|
13
|
+
return Array.map(value, canonicalizeJson);
|
|
14
|
+
}
|
|
15
|
+
if (isJsonObject(value)) {
|
|
16
|
+
return pipe(value, Record.toEntries, Array.sort(jsonEntryOrder), Array.map(canonicalizeJsonEntry), Record.fromEntries);
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
};
|
|
20
|
+
const encodeJsonString = Schema.encodeUnknownSync(Schema.fromJsonString(Schema.Json));
|
|
21
|
+
const encodeKey = (schema) => {
|
|
22
|
+
const encodeJson = Schema.encodeUnknownSync(Schema.toCodecJson(schema));
|
|
23
|
+
return (value) => encodeJsonString(canonicalizeJson(encodeJson(value)));
|
|
24
|
+
};
|
|
25
|
+
const makeKeyedQueryMessage = (data, error, Args) => defineMessageUnion({
|
|
26
|
+
CompletedFetch: {
|
|
27
|
+
args: Args,
|
|
28
|
+
generation: Schema.Number,
|
|
29
|
+
result: Schema.Result(data, error),
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
/** Builds the Model Schema for a KeyedQuery. */
|
|
33
|
+
export const makeKeyedQueryModel = (data, error, Args) => {
|
|
34
|
+
const asyncData = AsyncData.Schema(data, error);
|
|
35
|
+
return Schema.Struct({
|
|
36
|
+
generation: Schema.Number,
|
|
37
|
+
entries: Schema.HashMap(Schema.String, Schema.Struct({
|
|
38
|
+
args: Args,
|
|
39
|
+
data: asyncData.schema,
|
|
40
|
+
generation: Schema.Number,
|
|
41
|
+
})),
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
export function defineKeyedQuery(config) {
|
|
45
|
+
const asyncData = AsyncData.Schema(config.data, config.error);
|
|
46
|
+
const Args = Schema.Struct(config.args);
|
|
47
|
+
if (Array.isArrayEmpty(Record.keys(config.args))) {
|
|
48
|
+
throw new Error(`Query.define("${config.name}"): keyed args must include at least one field`);
|
|
49
|
+
}
|
|
50
|
+
const argsToKey = config.toKey ?? encodeKey(Args);
|
|
51
|
+
const Message = makeKeyedQueryMessage(config.data, config.error, Args);
|
|
52
|
+
const Fetch = Command.define(`Fetch${config.name}`, {
|
|
53
|
+
args: { args: Args, generation: Schema.Number },
|
|
54
|
+
messages: [Message.CompletedFetch],
|
|
55
|
+
execute: ({ args, generation }) => pipe(config.execute(args), Effect.result, Effect.map((result) =>
|
|
56
|
+
// NOTE: CompletedFetch's constructor input view rejects args that are already the decoded Type.
|
|
57
|
+
({
|
|
58
|
+
_tag: 'CompletedFetch',
|
|
59
|
+
args,
|
|
60
|
+
generation,
|
|
61
|
+
result,
|
|
62
|
+
}))),
|
|
63
|
+
});
|
|
64
|
+
const Model = makeKeyedQueryModel(config.data, config.error, Args);
|
|
65
|
+
const store = {
|
|
66
|
+
read: (model, args) => AsyncData.fromOptionOrIdle(Option.map(HashMap.get(model.entries, argsToKey(args)), entry => entry.data)),
|
|
67
|
+
start: (model, args, data) => {
|
|
68
|
+
const nextGeneration = Number.increment(model.generation);
|
|
69
|
+
return {
|
|
70
|
+
model: modifyFields(model, {
|
|
71
|
+
entries: HashMap.set(argsToKey(args), {
|
|
72
|
+
args,
|
|
73
|
+
data,
|
|
74
|
+
generation: nextGeneration,
|
|
75
|
+
}),
|
|
76
|
+
generation: () => nextGeneration,
|
|
77
|
+
}),
|
|
78
|
+
generation: nextGeneration,
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
fetch: (args, generation) => Fetch({ args, generation }),
|
|
82
|
+
};
|
|
83
|
+
const init = () => Model.make({ entries: HashMap.empty(), generation: 0 });
|
|
84
|
+
const reset = (model) => ({
|
|
85
|
+
model: modifyFields(model, { entries: () => HashMap.empty() }),
|
|
86
|
+
});
|
|
87
|
+
const read = (model, args) => store.read(model, args);
|
|
88
|
+
const liftTransition = (transition) => Function.dual(2, (model, args) => applyTransition(store, model, args, transition));
|
|
89
|
+
const revalidate = liftTransition(AsyncData.revalidate);
|
|
90
|
+
const revalidateOrLoad = liftTransition(AsyncData.revalidateOrLoad);
|
|
91
|
+
const loadIfMissing = liftTransition(AsyncData.loadIfMissing);
|
|
92
|
+
const update = (model, message) => Message.match(message, {
|
|
93
|
+
CompletedFetch({ args, generation, result }) {
|
|
94
|
+
const key = argsToKey(args);
|
|
95
|
+
const maybeEntry = HashMap.get(model.entries, key);
|
|
96
|
+
if (Option.isNone(maybeEntry)) {
|
|
97
|
+
return { model };
|
|
98
|
+
}
|
|
99
|
+
const entry = maybeEntry.value;
|
|
100
|
+
if (!AsyncData.isPending(entry.data) ||
|
|
101
|
+
generation !== entry.generation) {
|
|
102
|
+
return { model };
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
model: modifyFields(model, {
|
|
106
|
+
entries: HashMap.set(key, modifyFields(entry, {
|
|
107
|
+
data: () => AsyncData.settle(entry.data, result),
|
|
108
|
+
})),
|
|
109
|
+
}),
|
|
110
|
+
};
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
const liftFromLens = (lens) => ({
|
|
114
|
+
fold: Update.foldChild({ update, ...lens }),
|
|
115
|
+
reset: Update.foldChildStep({
|
|
116
|
+
update: reset,
|
|
117
|
+
...lens,
|
|
118
|
+
}),
|
|
119
|
+
revalidate: liftChildFold(revalidate, lens),
|
|
120
|
+
revalidateOrLoad: liftChildFold(revalidateOrLoad, lens),
|
|
121
|
+
loadIfMissing: liftChildFold(loadIfMissing, lens),
|
|
122
|
+
});
|
|
123
|
+
function lift(config) {
|
|
124
|
+
if (isParentFieldConfig(config)) {
|
|
125
|
+
return liftFromLens(parentFieldToLens(config));
|
|
126
|
+
}
|
|
127
|
+
return liftFromLens(config);
|
|
128
|
+
}
|
|
129
|
+
const run = (args) => runExecute(config.execute(args));
|
|
130
|
+
return {
|
|
131
|
+
Model,
|
|
132
|
+
Message,
|
|
133
|
+
Fetch,
|
|
134
|
+
init,
|
|
135
|
+
reset,
|
|
136
|
+
read,
|
|
137
|
+
update,
|
|
138
|
+
revalidate,
|
|
139
|
+
revalidateOrLoad,
|
|
140
|
+
loadIfMissing,
|
|
141
|
+
lift,
|
|
142
|
+
run,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/experimental/query/public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACnC,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AACjD,YAAY,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { define } from './index.js';
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Effect, Schema } from 'effect';
|
|
2
|
+
import * as AsyncData from '../../asyncData/index.js';
|
|
3
|
+
import * as Command from '../../command/index.js';
|
|
4
|
+
import * as Update from '../../update/index.js';
|
|
5
|
+
import { type CompletedFetchOf, type LiftQuery } from './internal.js';
|
|
6
|
+
export type QueryConfig<Name extends string, A, AI, E, EI, R> = Readonly<{
|
|
7
|
+
name: Name;
|
|
8
|
+
data: Schema.Codec<A, AI, never, never>;
|
|
9
|
+
error: Schema.Codec<E, EI, never, never>;
|
|
10
|
+
execute: Effect.Effect<A, E, R>;
|
|
11
|
+
}>;
|
|
12
|
+
declare const makeQueryMessage: <A, AI, E, EI>(data: Schema.Codec<A, AI>, error: Schema.Codec<E, EI>) => import("../../schema/index.js").MessageUnion<{
|
|
13
|
+
readonly CompletedFetch: {
|
|
14
|
+
generation: Schema.Number;
|
|
15
|
+
result: Schema.Result<Schema.Codec<A, AI, never, never>, Schema.Codec<E, EI, never, never>>;
|
|
16
|
+
};
|
|
17
|
+
}>;
|
|
18
|
+
/**
|
|
19
|
+
* Schema-backed Message union dispatched when a Query Fetch completes.
|
|
20
|
+
*
|
|
21
|
+
* @experimental Ships from `foldkit/experimental/query`; expect breaking changes while the API settles.
|
|
22
|
+
*/
|
|
23
|
+
export type QueryMessage<A, AI, E, EI> = ReturnType<typeof makeQueryMessage<A, AI, E, EI>>;
|
|
24
|
+
/** Builds the Model Schema for a Query. */
|
|
25
|
+
export declare const makeQueryModel: <A, AI, E, EI>(data: Schema.Codec<A, AI>, error: Schema.Codec<E, EI>) => Schema.Struct<{
|
|
26
|
+
readonly data: Schema.Codec<AsyncData.AsyncData<A, E>, AsyncData.AsyncDataEncoded<AI, EI>, never, never>;
|
|
27
|
+
readonly generation: Schema.Number;
|
|
28
|
+
}>;
|
|
29
|
+
/**
|
|
30
|
+
* Model Schema for a Query containing one `AsyncData` value.
|
|
31
|
+
*
|
|
32
|
+
* @experimental Ships from `foldkit/experimental/query`; expect breaking changes while the API settles.
|
|
33
|
+
*/
|
|
34
|
+
export type QueryModel<A, AI, E, EI> = ReturnType<typeof makeQueryModel<A, AI, E, EI>>;
|
|
35
|
+
/**
|
|
36
|
+
* Submodel for fetching and retaining one `AsyncData` value.
|
|
37
|
+
*
|
|
38
|
+
* @experimental Ships from `foldkit/experimental/query`; expect breaking changes while the API settles.
|
|
39
|
+
*/
|
|
40
|
+
export interface Query<Name extends string, A, AI, E, EI, R = never> {
|
|
41
|
+
/** Schema for this Query's Model. */
|
|
42
|
+
readonly Model: QueryModel<A, AI, E, EI>;
|
|
43
|
+
/** Schema-backed union of Messages handled by this Query. */
|
|
44
|
+
readonly Message: QueryMessage<A, AI, E, EI>;
|
|
45
|
+
/**
|
|
46
|
+
* Command definition for matching this Query's pending fetch in Story and
|
|
47
|
+
* Scene tests. Start fetches through a loading operation so the Model and
|
|
48
|
+
* request generation advance together; do not call this directly.
|
|
49
|
+
*/
|
|
50
|
+
readonly Fetch: Command.CommandDefinitionWithArgs<`Fetch${Name}`, {
|
|
51
|
+
readonly generation: typeof Schema.Number;
|
|
52
|
+
}, Effect.Effect<CompletedFetchOf<QueryMessage<A, AI, E, EI>>, never, R>>;
|
|
53
|
+
/**
|
|
54
|
+
* Creates a Query Model for initial parent Model construction. Never replace
|
|
55
|
+
* a live Query with `init()`: it can reuse an in-flight request generation.
|
|
56
|
+
* Use `reset` instead.
|
|
57
|
+
*/
|
|
58
|
+
readonly init: () => QueryModel<A, AI, E, EI>['Type'];
|
|
59
|
+
/** Clears the Query while preserving its request identity. */
|
|
60
|
+
readonly reset: (model: QueryModel<A, AI, E, EI>['Type']) => Update.Return<QueryModel<A, AI, E, EI>['Type'], QueryMessage<A, AI, E, EI>['Type']>;
|
|
61
|
+
/** Reads the `AsyncData` value from the Query Model. */
|
|
62
|
+
readonly read: (model: QueryModel<A, AI, E, EI>['Type']) => AsyncData.AsyncData<A, E>;
|
|
63
|
+
/** Folds a Fetch completion into the Query Model. */
|
|
64
|
+
readonly update: (model: QueryModel<A, AI, E, EI>['Type'], message: QueryMessage<A, AI, E, EI>['Type']) => Update.Return<QueryModel<A, AI, E, EI>['Type'], QueryMessage<A, AI, E, EI>['Type']>;
|
|
65
|
+
/** Refreshes loaded data and does nothing when no data is present. */
|
|
66
|
+
readonly revalidate: (model: QueryModel<A, AI, E, EI>['Type']) => Update.Return<QueryModel<A, AI, E, EI>['Type'], QueryMessage<A, AI, E, EI>['Type'], R>;
|
|
67
|
+
/** Loads missing data or refreshes loaded data. */
|
|
68
|
+
readonly revalidateOrLoad: (model: QueryModel<A, AI, E, EI>['Type']) => Update.Return<QueryModel<A, AI, E, EI>['Type'], QueryMessage<A, AI, E, EI>['Type'], R>;
|
|
69
|
+
/** Loads data only when the Query has no usable value. */
|
|
70
|
+
readonly loadIfMissing: (model: QueryModel<A, AI, E, EI>['Type']) => Update.Return<QueryModel<A, AI, E, EI>['Type'], QueryMessage<A, AI, E, EI>['Type'], R>;
|
|
71
|
+
/** Lifts this Query's update and loading operations into a parent Model. */
|
|
72
|
+
readonly lift: LiftQuery<QueryModel<A, AI, E, EI>['Type'], QueryMessage<A, AI, E, EI>['Type'], R>;
|
|
73
|
+
/** Executes the configured fetch directly and returns settled `AsyncData`. */
|
|
74
|
+
readonly run: Effect.Effect<AsyncData.AsyncData<A, E>, never, R>;
|
|
75
|
+
}
|
|
76
|
+
export declare function defineQuery<Name extends string, A, AI, E, EI, R>(config: QueryConfig<Name, A, AI, E, EI, R>): Query<Name, A, AI, E, EI, R>;
|
|
77
|
+
export {};
|
|
78
|
+
//# sourceMappingURL=query.d.ts.map
|