@shivaedev/form 0.7.1 → 0.9.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 +21 -0
- package/README.md +12 -21
- package/dist/form.d.ts +2 -2
- package/dist/form.d.ts.map +1 -1
- package/dist/form.js +20 -18
- package/dist/form.js.map +1 -1
- package/dist/paths.d.ts +1 -3
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +0 -3
- package/dist/paths.js.map +1 -1
- package/dist/persistence.d.ts +1 -0
- package/dist/persistence.d.ts.map +1 -1
- package/dist/persistence.js +3 -3
- package/dist/persistence.js.map +1 -1
- package/dist/shape.d.ts +6 -7
- package/dist/shape.d.ts.map +1 -1
- package/dist/shape.js +0 -12
- package/dist/shape.js.map +1 -1
- package/dist/trackRejections.d.ts +2 -2
- package/dist/trackRejections.d.ts.map +1 -1
- package/dist/trackRejections.js +2 -2
- package/dist/trackRejections.js.map +1 -1
- package/package.json +4 -4
- package/src/form.ts +32 -27
- package/src/paths.ts +1 -6
- package/src/persistence.ts +4 -3
- package/src/shape.ts +5 -24
- package/src/trackRejections.ts +8 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.0 - 2026-10-30
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Forms without application service requirements can omit `runtime` and use an empty atom runtime. Handlers, advisory checks and schema decoding that require application services still need a matching runtime.
|
|
8
|
+
|
|
9
|
+
### Breaking
|
|
10
|
+
|
|
11
|
+
- `Config` is a conditional type so service requirements determine whether `runtime` is required. Extend generic configurations with an intersection type instead of an interface that extends `Config`.
|
|
12
|
+
|
|
13
|
+
## 0.8.0 - 2026-10-30
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Work Board reads draft timestamps and expiry through its form client’s runtime Clock.
|
|
18
|
+
|
|
19
|
+
### Breaking
|
|
20
|
+
|
|
21
|
+
- Persisted drafts require a `now: () => number` callback in core forms, `usePersistedDraft`, `useEditor` and `useCreate`. Capture `Clock.Clock` in the application’s Effect setup and pass `now: () => clock.currentTimeMillisUnsafe()` so timestamps and expiry follow that clock, including TestClock in stories.
|
|
22
|
+
- Form no longer exports the identity cast helpers `holder`, `fieldOf`, `choicesOf` or `checkOf` from `shape.ts`, or `keySelector` from `paths.ts`. Use declared reference, field, check and selector types directly; get field refs and choices through the form’s typed `field` and `choices` methods.
|
|
23
|
+
|
|
3
24
|
## 0.7.1 - 2026-10-30
|
|
4
25
|
|
|
5
26
|
### Changed
|
package/README.md
CHANGED
|
@@ -10,7 +10,6 @@ An input gives you a string; your service needs a number. Meanwhile, fresh serve
|
|
|
10
10
|
const order = form(Schema.Struct({ name: Schema.String, quantity: Schema.NumberFromString }), {
|
|
11
11
|
initialValues: { name: "Paper", quantity: "300" },
|
|
12
12
|
onSubmit: Effect.succeed,
|
|
13
|
-
runtime,
|
|
14
13
|
});
|
|
15
14
|
|
|
16
15
|
order.change("name", "Copy paper");
|
|
@@ -29,21 +28,19 @@ The **baseline** is the encoded value against which the form recognizes edits. I
|
|
|
29
28
|
|
|
30
29
|
Keep one form instance for one editing session. Use a new instance for a different entity or user session. Query acquisition, entity identity, normalized saved rows and create-reset orchestration can be composed with [`useEditor` and `useCreate`](https://github.com/ShivaeDev/platform/blob/main/packages/react/README.md) from `@shivaedev/react`.
|
|
31
30
|
|
|
32
|
-
### Once per application: supply
|
|
31
|
+
### Once per application: supply services and a registry
|
|
33
32
|
|
|
34
|
-
`form`
|
|
33
|
+
`form` uses an empty atom runtime when the handler, field checks and schema decoding need no application services. To use application services, pass `runtime: Atom.runtime(layer)` with a Layer that provides them. Missing service dependencies fail to compile. The native `Scope`, `AtomRegistry` and `Reactivity` services are available without a supplied runtime.
|
|
35
34
|
|
|
36
35
|
Use an `AtomRegistry` to mount and read atoms and write the submit atom. Own its lifetime at the application boundary. In React, provide that registry through `RegistryContext` from `@effect/atom-react`.
|
|
37
36
|
|
|
38
37
|
### Once per feature: define fields and submission
|
|
39
38
|
|
|
40
39
|
```ts
|
|
41
|
-
import { Effect,
|
|
42
|
-
import * as Atom from "effect/reactivity/Atom";
|
|
40
|
+
import { Effect, Schema } from "effect";
|
|
43
41
|
import * as AtomRegistry from "effect/reactivity/AtomRegistry";
|
|
44
42
|
import { form } from "@shivaedev/form/form.ts";
|
|
45
43
|
|
|
46
|
-
const runtime = Atom.runtime(Layer.empty);
|
|
47
44
|
const fields = Schema.Struct({
|
|
48
45
|
name: Schema.NonEmptyString,
|
|
49
46
|
quantity: Schema.NumberFromString,
|
|
@@ -52,7 +49,6 @@ const fields = Schema.Struct({
|
|
|
52
49
|
const order = form(fields, {
|
|
53
50
|
initialValues: { name: "Paper", quantity: "300" },
|
|
54
51
|
onSubmit: (values, submitter) => (values.name === "reserved" ? submitter.fail("name", "Choose another name") : Effect.succeed(values)),
|
|
55
|
-
runtime,
|
|
56
52
|
});
|
|
57
53
|
|
|
58
54
|
const registry = AtomRegistry.make();
|
|
@@ -77,15 +73,13 @@ The handler has three arguments: decoded values, the submitter, and the submitte
|
|
|
77
73
|
|
|
78
74
|
```tsx
|
|
79
75
|
import { RegistryContext } from "@effect/atom-react";
|
|
80
|
-
import { Effect,
|
|
81
|
-
import * as Atom from "effect/reactivity/Atom";
|
|
76
|
+
import { Effect, Schema } from "effect";
|
|
82
77
|
import * as AtomRegistry from "effect/reactivity/AtomRegistry";
|
|
83
78
|
import { useState } from "react";
|
|
84
79
|
import { createRoot } from "react-dom/client";
|
|
85
80
|
import { form } from "@shivaedev/form/form.ts";
|
|
86
81
|
import { useDirty, useField, useSubmit } from "@shivaedev/form/client/react.ts";
|
|
87
82
|
|
|
88
|
-
const runtime = Atom.runtime(Layer.empty);
|
|
89
83
|
const fields = Schema.Struct({ name: Schema.NonEmptyString, quantity: Schema.NumberFromString });
|
|
90
84
|
|
|
91
85
|
function OrderEditor() {
|
|
@@ -93,7 +87,6 @@ function OrderEditor() {
|
|
|
93
87
|
form(fields, {
|
|
94
88
|
initialValues: { name: "Paper", quantity: "300" },
|
|
95
89
|
onSubmit: Effect.succeed,
|
|
96
|
-
runtime,
|
|
97
90
|
}),
|
|
98
91
|
);
|
|
99
92
|
const name = useField(order, "name");
|
|
@@ -165,14 +158,15 @@ The form does not replace submitted encoded input with its decoded representatio
|
|
|
165
158
|
|
|
166
159
|
Opt in with `persistedDraft`. The application chooses a key for one logical editing session. Keep that key stable across server revisions so a refresh can find the same draft; choose a new key when the encoded field shape changes. Stored input includes its baseline and edited field names, so edited fields survive reload while untouched fields adopt the latest received values.
|
|
167
160
|
|
|
168
|
-
For a core form, supply the storage provider explicitly:
|
|
161
|
+
Supply `now`, a function that reads epoch milliseconds from the caller’s clock. Capture `Clock.Clock` in the application’s Effect setup and pass its `currentTimeMillisUnsafe` method through a closure. The same callback reads time on each write and expiry check, so a supplied TestClock controls draft age. For a core form, supply the storage provider explicitly:
|
|
169
162
|
|
|
170
163
|
```ts
|
|
164
|
+
const clock = yield* Clock.Clock;
|
|
165
|
+
const now = () => clock.currentTimeMillisUnsafe();
|
|
171
166
|
const order = form(fields, {
|
|
172
167
|
initialValues: { name: "Paper", quantity: "300" },
|
|
173
168
|
onSubmit: Effect.succeed,
|
|
174
|
-
persistedDraft: { key: "order:123", storage: () => window.localStorage },
|
|
175
|
-
runtime,
|
|
169
|
+
persistedDraft: { key: "order:123", now, storage: () => window.localStorage },
|
|
176
170
|
});
|
|
177
171
|
```
|
|
178
172
|
|
|
@@ -182,21 +176,20 @@ For a React form, call `usePersistedDraft` before creating the form. It defaults
|
|
|
182
176
|
import { useState } from "react";
|
|
183
177
|
import { usePersistedDraft } from "@shivaedev/form/client/react.ts";
|
|
184
178
|
|
|
185
|
-
function OrderEditor() {
|
|
186
|
-
const persistedDraft = usePersistedDraft({ key: "order:123" });
|
|
179
|
+
function OrderEditor({ now }: { readonly now: () => number }) {
|
|
180
|
+
const persistedDraft = usePersistedDraft({ key: "order:123", now });
|
|
187
181
|
const [order] = useState(() =>
|
|
188
182
|
form(fields, {
|
|
189
183
|
initialValues: { name: "Paper", quantity: "300" },
|
|
190
184
|
onSubmit: Effect.succeed,
|
|
191
185
|
persistedDraft,
|
|
192
|
-
runtime,
|
|
193
186
|
}),
|
|
194
187
|
);
|
|
195
188
|
return <OrderFields form={order} />;
|
|
196
189
|
}
|
|
197
190
|
```
|
|
198
191
|
|
|
199
|
-
`OrderFields` is the application's field UI. Keep this component mounted for one record; remount it when its identity changes. `useEditor` and `useCreate` from `react` accept `persistedDraft: { key }` directly and attach the same owner. A committed `SessionBoundary` session replacement or sign-out drops its tracked drafts, including screens already unmounted, and disables writes from its old forms. A suspended replacement that is canceled preserves the visible session's stored draft and future persistence. Ordinary unmounts and React effect replay preserve stored drafts. A stored draft with a different session generation is discarded when read.
|
|
192
|
+
`OrderFields` is the application's field UI. Keep this component mounted for one record; remount it when its identity changes. `useEditor` and `useCreate` from `react` accept `persistedDraft: { key, now }` directly and attach the same owner. A committed `SessionBoundary` session replacement or sign-out drops its tracked drafts, including screens already unmounted, and disables writes from its old forms. A suspended replacement that is canceled preserves the visible session's stored draft and future persistence. Ordinary unmounts and React effect replay preserve stored drafts. A stored draft with a different session generation is discarded when read.
|
|
200
193
|
|
|
201
194
|
Each stored record defaults to at most 256 KiB of UTF-8 JSON and seven days since its last write. Set `maxBytes` and `maxAgeMs` to finite positive limits to change those bounds. Oversized, expired, malformed or incompatible records are dropped when encountered. Persistence requires JSON-compatible encoded input; invalid input such as an empty required string or an unfinished numeric string still persists. Storage access, serialization and quota failures leave the form usable.
|
|
202
195
|
|
|
@@ -218,7 +211,6 @@ const profile = form(Schema.Struct({ name: Schema.String }), {
|
|
|
218
211
|
debounce: "300 millis",
|
|
219
212
|
initialValues: { name: "" },
|
|
220
213
|
onSubmit: Effect.succeed,
|
|
221
|
-
runtime,
|
|
222
214
|
});
|
|
223
215
|
```
|
|
224
216
|
|
|
@@ -239,7 +231,6 @@ const answers = form(
|
|
|
239
231
|
arrayKeys: { answers: (answer) => answer.id },
|
|
240
232
|
initialValues: { answers: [{ id: "question", text: "Yes" }] },
|
|
241
233
|
onSubmit: (_values, submitter) => submitter.fail(["answers", 0, "text"], "This answer is closed"),
|
|
242
|
-
runtime,
|
|
243
234
|
},
|
|
244
235
|
);
|
|
245
236
|
```
|
|
@@ -281,7 +272,7 @@ Import the module that defines a name; there is no root entry.
|
|
|
281
272
|
| Option | Type or role |
|
|
282
273
|
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
283
274
|
| `initialValues` | `Encoded<F>` |
|
|
284
|
-
| `runtime` |
|
|
275
|
+
| `runtime` | Optional when no application services are needed; otherwise an atom runtime for handler/check and schema decoding services |
|
|
285
276
|
| `onSubmit` | `(values, submitter, submitted) => Effect<A, E, R>`; the three arguments are decoded values, field failure helper and encoded snapshot |
|
|
286
277
|
| `checks` | Optional functions keyed by field, from encoded input to an Effect of `string \| undefined` |
|
|
287
278
|
| `arrayKeys` | Optional `ArrayKeys<F>` selectors keyed by top-level array field, from encoded element to stable `PropertyKey`; retains nested feedback across reordering |
|
package/dist/form.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Schema } from "effect";
|
|
2
2
|
import { type Config, type Fields, type Form } from "./shape.ts";
|
|
3
|
-
export declare function form<TFields extends Fields, TValue, TError, TServices, TRuntimeError>(schema: Schema.Struct<TFields>, config: Config<TFields, TValue, TError, TServices, TRuntimeError>): Form<TFields, TValue, TError, TRuntimeError>;
|
|
3
|
+
export declare function form<TFields extends Fields, TValue, TError, TServices = never, TRuntimeError = never>(schema: Schema.Struct<TFields>, config: Config<TFields, TValue, TError, TServices, TRuntimeError>): Form<TFields, TValue, TError, TRuntimeError>;
|
|
4
4
|
//# sourceMappingURL=form.d.ts.map
|
package/dist/form.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,MAAM,EAAkC,MAAM,QAAQ,CAAC;AAS9F,OAAO,EACN,KAAK,MAAM,EAIX,KAAK,MAAM,EACX,KAAK,IAAI,EAKT,MAAM,YAAY,CAAC;AAapB,wBAAgB,IAAI,CAAC,OAAO,SAAS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,KAAK,EAAE,aAAa,GAAG,KAAK,EACpG,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAC9B,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,CAAC,GAC/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,CA8G9C"}
|
package/dist/form.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Effect, Equal, Result, SchemaParser } from "effect";
|
|
1
|
+
import { Effect, Equal, Layer, Result, Schema, SchemaParser } from "effect";
|
|
2
2
|
import * as AsyncResult from "effect/reactivity/AsyncResult";
|
|
3
3
|
import * as Atom from "effect/reactivity/Atom";
|
|
4
4
|
import { draft } from "./draft.js";
|
|
@@ -6,35 +6,33 @@ import { literalChoices, messageAt, messagesByField, schemaFeedback } from "./me
|
|
|
6
6
|
import { pathMessageAt } from "./paths.js";
|
|
7
7
|
import { persistence } from "./persistence.js";
|
|
8
8
|
import { fromRef, propertyRef } from "./refs.js";
|
|
9
|
-
import {
|
|
9
|
+
import { FieldFailure, Invalid, } from "./shape.js";
|
|
10
10
|
import { statusOf } from "./statusOf.js";
|
|
11
11
|
import { trackRejections } from "./trackRejections.js";
|
|
12
|
+
const emptyRuntime = Atom.runtime(Layer.empty);
|
|
13
|
+
function configuredRuntime(config) {
|
|
14
|
+
return config.runtime ?? emptyRuntime;
|
|
15
|
+
}
|
|
12
16
|
export function form(schema, config) {
|
|
13
|
-
const { initialValues, onSubmit
|
|
17
|
+
const { initialValues, onSubmit } = config;
|
|
18
|
+
const runtime = configuredRuntime(config);
|
|
14
19
|
const debounce = config.debounce ?? "300 millis";
|
|
15
20
|
const checks = new Map(Object.entries(config.checks ?? {}));
|
|
16
21
|
const decode = SchemaParser.decodeUnknownEffect(schema, { errors: "all" });
|
|
17
22
|
const editing = draft(initialValues, config.persistedDraft ? persistence(schema, config.persistedDraft) : undefined);
|
|
18
23
|
const { values } = editing;
|
|
19
24
|
const status = statusOf();
|
|
20
|
-
const noted = trackRejections(
|
|
21
|
-
const held =
|
|
25
|
+
const noted = trackRejections(values, config.arrayKeys, status);
|
|
26
|
+
const held = {};
|
|
22
27
|
function refFor(name) {
|
|
23
|
-
const known =
|
|
28
|
+
const known = Object.hasOwn(held, name) ? held[name] : undefined;
|
|
24
29
|
if (known !== undefined) {
|
|
25
30
|
return known;
|
|
26
31
|
}
|
|
27
|
-
const made = propertyRef(
|
|
28
|
-
held
|
|
32
|
+
const made = propertyRef(values, name);
|
|
33
|
+
held[name] = made;
|
|
29
34
|
return made;
|
|
30
35
|
}
|
|
31
|
-
const offered = new Map();
|
|
32
|
-
for (const [name, member] of Object.entries(schema.fields)) {
|
|
33
|
-
const choices = literalChoices(member.ast);
|
|
34
|
-
if (choices !== undefined) {
|
|
35
|
-
offered.set(name, choices);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
36
|
const valuesAtom = fromRef(values);
|
|
39
37
|
const decoded = runtime.atom((get) => decode(get(valuesAtom)).pipe(Effect.match({
|
|
40
38
|
onFailure: (issue) => Result.fail(issue),
|
|
@@ -50,7 +48,7 @@ export function form(schema, config) {
|
|
|
50
48
|
const settled = Atom.debounce(current, debounce);
|
|
51
49
|
const answered = runtime.atom((get) => {
|
|
52
50
|
const input = get(settled);
|
|
53
|
-
return Effect.map(
|
|
51
|
+
return Effect.map(check(input), (message) => ({
|
|
54
52
|
input,
|
|
55
53
|
message,
|
|
56
54
|
}));
|
|
@@ -83,14 +81,18 @@ export function form(schema, config) {
|
|
|
83
81
|
refFor(name).set(value);
|
|
84
82
|
status.touch(name);
|
|
85
83
|
},
|
|
86
|
-
choices: (name) =>
|
|
84
|
+
choices: (name) => {
|
|
85
|
+
const member = schema.fields[name];
|
|
86
|
+
const decodeChoice = SchemaParser.decodeUnknownSync(Schema.toEncoded(schema), { disableChecks: true });
|
|
87
|
+
return (member ? literalChoices(member.ast) : undefined)?.map((value) => decodeChoice({ ...initialValues, [name]: value })[name]);
|
|
88
|
+
},
|
|
87
89
|
dirty: editing.dirty,
|
|
88
90
|
error,
|
|
89
91
|
errorAt: Atom.family((path) => {
|
|
90
92
|
const message = schemaErrors.at(path);
|
|
91
93
|
return Atom.readable((get) => get(status.touched)[path[0]] === true || get(status.submitted) ? (pathMessageAt(get(status.paths), path) ?? get(message)) : undefined);
|
|
92
94
|
}),
|
|
93
|
-
field:
|
|
95
|
+
field: refFor,
|
|
94
96
|
receive: editing.receive,
|
|
95
97
|
revert: editing.revert,
|
|
96
98
|
submit,
|
package/dist/form.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.js","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"form.js","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"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"}
|
package/dist/paths.d.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import type { Path } from "./shape.ts";
|
|
2
|
-
type Key = (element: unknown) => PropertyKey;
|
|
2
|
+
export type Key = (element: unknown) => PropertyKey;
|
|
3
3
|
export type KeySelectors = ReadonlyMap<string, Key>;
|
|
4
4
|
export interface PathMessage {
|
|
5
5
|
readonly message: string;
|
|
6
6
|
readonly path: Path;
|
|
7
7
|
}
|
|
8
|
-
export declare function keySelector(selector: unknown): Key;
|
|
9
8
|
export declare function asPath(path: string | Path): Path;
|
|
10
9
|
export declare function retainedPath(path: Path, previous: unknown, current: unknown, keys: KeySelectors): Path | undefined;
|
|
11
10
|
export declare function pathMessageAt(messages: readonly PathMessage[], path: readonly PropertyKey[]): string | undefined;
|
|
12
|
-
export {};
|
|
13
11
|
//# sourceMappingURL=paths.d.ts.map
|
package/dist/paths.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,WAAW,CAAC;AACpD,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;CACpB;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAEhD;AAqBD,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,CAmBlH;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,WAAW,EAAE,GAAG,MAAM,GAAG,SAAS,CAEhH"}
|
package/dist/paths.js
CHANGED
package/dist/paths.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"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"}
|
package/dist/persistence.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAgB,MAAM,QAAQ,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACjD,QAAQ,CAAC,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACvD;AAED,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,OAAO,EAAE,MAAM,YAAY,CAAC;CACrC;AAED,MAAM,WAAW,WAAW,CAAC,OAAO;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM;QAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;IAC9H,QAAQ,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,KAAK,IAAI,CAAC;CACxF;AAED,wBAAgB,WAAW,CAAC,OAAO,SAAS,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,oBAAoB,GAAG,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAmF7I"}
|
package/dist/persistence.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Schema, SchemaParser } from "effect";
|
|
2
2
|
export function persistence(schema, config) {
|
|
3
3
|
const encoded = Schema.toEncoded(schema);
|
|
4
4
|
const StoredDraft = Schema.Struct({
|
|
@@ -49,7 +49,7 @@ export function persistence(schema, config) {
|
|
|
49
49
|
return undefined;
|
|
50
50
|
}
|
|
51
51
|
const value = bytes(raw) <= maxBytes ? JSON.parse(raw) : undefined;
|
|
52
|
-
const now =
|
|
52
|
+
const now = config.now();
|
|
53
53
|
if (valid(value)
|
|
54
54
|
&& value.session === session
|
|
55
55
|
&& Number.isFinite(maxAgeMs)
|
|
@@ -68,7 +68,7 @@ export function persistence(schema, config) {
|
|
|
68
68
|
return;
|
|
69
69
|
}
|
|
70
70
|
attempt(() => {
|
|
71
|
-
const raw = JSON.stringify({ baseline, edited, session, updatedAt:
|
|
71
|
+
const raw = JSON.stringify({ baseline, edited, session, updatedAt: config.now(), values, version: 1 });
|
|
72
72
|
const parsed = JSON.parse(raw);
|
|
73
73
|
if (!(maxAgeMs > 0 && Number.isFinite(maxAgeMs) && Number.isFinite(maxBytes) && bytes(raw) <= maxBytes && valid(parsed))) {
|
|
74
74
|
clear();
|
package/dist/persistence.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistence.js","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"persistence.js","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"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"}
|
package/dist/shape.d.ts
CHANGED
|
@@ -36,15 +36,18 @@ export interface Submitter<TName extends string> {
|
|
|
36
36
|
export type Checks<TFields extends Fields, R> = {
|
|
37
37
|
readonly [TKey in Name<TFields>]?: (value: Encoded<TFields>[TKey]) => Effect.Effect<string | undefined, never, R>;
|
|
38
38
|
};
|
|
39
|
-
export
|
|
39
|
+
export type Config<TFields extends Fields, A, E, R, TRuntimeError> = {
|
|
40
40
|
readonly arrayKeys?: ArrayKeys<TFields>;
|
|
41
41
|
readonly checks?: Checks<TFields, R>;
|
|
42
42
|
readonly debounce?: Duration.Input;
|
|
43
43
|
readonly initialValues: Encoded<TFields>;
|
|
44
44
|
readonly onSubmit: (values: Decoded<TFields>, submitter: Submitter<Name<TFields>>, submitted: Encoded<TFields>) => Effect.Effect<A, E, R | Scope.Scope | AtomRegistry | Reactivity>;
|
|
45
45
|
readonly persistedDraft?: PersistedDraftConfig | undefined;
|
|
46
|
+
} & ([Exclude<Services<TFields, R>, Scope.Scope | AtomRegistry | Reactivity>] extends [never] ? {
|
|
47
|
+
readonly runtime?: Atom.AtomRuntime<Services<TFields, R>, TRuntimeError>;
|
|
48
|
+
} : {
|
|
46
49
|
readonly runtime: Atom.AtomRuntime<Services<TFields, R>, TRuntimeError>;
|
|
47
|
-
}
|
|
50
|
+
});
|
|
48
51
|
export interface Form<TFields extends Fields, A, E, TRuntimeError> {
|
|
49
52
|
readonly blur: (name: Name<TFields>) => void;
|
|
50
53
|
readonly change: <TKey extends Name<TFields>>(name: TKey, value: Encoded<TFields>[TKey]) => void;
|
|
@@ -59,10 +62,6 @@ export interface Form<TFields extends Fields, A, E, TRuntimeError> {
|
|
|
59
62
|
readonly submitting: Atom.Atom<boolean>;
|
|
60
63
|
readonly values: AtomRef.AtomRef<Encoded<TFields>>;
|
|
61
64
|
}
|
|
62
|
-
export type Holder = AtomRef.
|
|
63
|
-
export declare function holder(values: object): Holder;
|
|
64
|
-
export declare function fieldOf<TValue>(ref: AtomRef.AtomRef<unknown>): AtomRef.AtomRef<TValue>;
|
|
65
|
-
export declare function choicesOf<TValue>(choices: readonly unknown[] | undefined): readonly TValue[] | undefined;
|
|
66
|
-
export declare function checkOf<R>(check: unknown): (value: unknown) => Effect.Effect<string | undefined, never, R>;
|
|
65
|
+
export type Holder = AtomRef.ReadonlyRef<Readonly<Record<string, unknown>>>;
|
|
67
66
|
export {};
|
|
68
67
|
//# sourceMappingURL=shape.d.ts.map
|
package/dist/shape.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shape.d.ts","sourceRoot":"","sources":["../src/shape.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,QAAQ,EAAE,KAAK,MAAM,EAAE,KAAK,MAAM,EAAE,KAAK,KAAK,EAAE,MAAM,QAAQ,CAAC;AACnF,OAAO,KAAK,KAAK,IAAI,MAAM,wBAAwB,CAAC;AACpD,OAAO,KAAK,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;AAE1C,MAAM,MAAM,OAAO,CAAC,OAAO,SAAS,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AAE7E,MAAM,MAAM,OAAO,CAAC,OAAO,SAAS,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAE1E,MAAM,MAAM,IAAI,CAAC,OAAO,SAAS,MAAM,IAAI,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC;AAE3E,MAAM,MAAM,IAAI,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,IAAI,SAAS,CAAC,KAAK,EAAE,GAAG,WAAW,EAAE,CAAC,CAAC;AAErF,MAAM,MAAM,SAAS,CAAC,OAAO,SAAS,MAAM,IAAI;IAC/C,QAAQ,EAAE,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,SAAS,CAAC,MAAM,QAAQ,CAAC,EAAE,GACvG,CAAC,OAAO,EAAE,QAAQ,KAAK,WAAW,GAClC,KAAK;CACR,CAAC;AAEF,MAAM,MAAM,QAAQ,CAAC,OAAO,SAAS,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;;;;AAE9F,qBAAa,YAAa,SAAQ,kBAAiC;IAClE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC;CACzB,CAAC;CAAG;;;;AAEL,qBAAa,OAAQ,SAAQ,aAA4B;IACxD,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;CACjC,CAAC;CAAG;AAEL,MAAM,WAAW,SAAS,CAAC,KAAK,SAAS,MAAM;IAC9C,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;CAClG;AAED,MAAM,MAAM,MAAM,CAAC,OAAO,SAAS,MAAM,EAAE,CAAC,IAAI;IAC/C,QAAQ,EAAE,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;CACjH,CAAC;AAEF,MAAM,
|
|
1
|
+
{"version":3,"file":"shape.d.ts","sourceRoot":"","sources":["../src/shape.ts"],"names":[],"mappings":"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"}
|
package/dist/shape.js
CHANGED
|
@@ -3,16 +3,4 @@ export class FieldFailure extends Data.TaggedError("FieldFailure") {
|
|
|
3
3
|
}
|
|
4
4
|
export class Invalid extends Data.TaggedError("Invalid") {
|
|
5
5
|
}
|
|
6
|
-
export function holder(values) {
|
|
7
|
-
return values;
|
|
8
|
-
}
|
|
9
|
-
export function fieldOf(ref) {
|
|
10
|
-
return ref;
|
|
11
|
-
}
|
|
12
|
-
export function choicesOf(choices) {
|
|
13
|
-
return choices;
|
|
14
|
-
}
|
|
15
|
-
export function checkOf(check) {
|
|
16
|
-
return check;
|
|
17
|
-
}
|
|
18
6
|
//# sourceMappingURL=shape.js.map
|
package/dist/shape.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shape.js","sourceRoot":"","sources":["../src/shape.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAuD,MAAM,QAAQ,CAAC;AA0BnF,MAAM,OAAO,YAAa,SAAQ,IAAI,CAAC,WAAW,CAAC,cAAc,CAI/D;CAAG;AAEL,MAAM,OAAO,OAAQ,SAAQ,IAAI,CAAC,WAAW,CAAC,SAAS,CAErD;CAAG
|
|
1
|
+
{"version":3,"file":"shape.js","sourceRoot":"","sources":["../src/shape.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAuD,MAAM,QAAQ,CAAC;AA0BnF,MAAM,OAAO,YAAa,SAAQ,IAAI,CAAC,WAAW,CAAC,cAAc,CAI/D;CAAG;AAEL,MAAM,OAAO,OAAQ,SAAQ,IAAI,CAAC,WAAW,CAAC,SAAS,CAErD;CAAG"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
-
import { type Holder } from "./shape.ts";
|
|
2
|
+
import { type ArrayKeys, type Fields, type Holder } from "./shape.ts";
|
|
3
3
|
import type { statusOf } from "./statusOf.ts";
|
|
4
|
-
export declare function trackRejections(values: Holder, selectors:
|
|
4
|
+
export declare function trackRejections<TFields extends Fields>(values: Holder, selectors: ArrayKeys<TFields> | undefined, status: ReturnType<typeof statusOf>): (submitted: unknown) => (cause: unknown) => Effect.Effect<void>;
|
|
5
5
|
//# sourceMappingURL=trackRejections.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trackRejections.d.ts","sourceRoot":"","sources":["../src/trackRejections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"trackRejections.d.ts","sourceRoot":"","sources":["../src/trackRejections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,KAAK,SAAS,EAAgB,KAAK,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AACpF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,wBAAgB,eAAe,CAAC,OAAO,SAAS,MAAM,EACrD,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,CAAC,OAAO,CAAC,GAAG,SAAS,EACzC,MAAM,EAAE,UAAU,CAAC,OAAO,QAAQ,CAAC,eAQhB,OAAO,aACjB,OAAO,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAStC"}
|
package/dist/trackRejections.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
-
import { asPath,
|
|
2
|
+
import { asPath, retainedPath } from "./paths.js";
|
|
3
3
|
import { FieldFailure } from "./shape.js";
|
|
4
4
|
export function trackRejections(values, selectors, status) {
|
|
5
|
-
const keys = new Map(Object.entries(selectors ?? {})
|
|
5
|
+
const keys = new Map(Object.entries(selectors ?? {}));
|
|
6
6
|
let previous = values.value;
|
|
7
7
|
values.subscribe((next) => {
|
|
8
8
|
status.rebase(previous, next, keys);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trackRejections.js","sourceRoot":"","sources":["../src/trackRejections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"trackRejections.js","sourceRoot":"","sources":["../src/trackRejections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,MAAM,EAAY,YAAY,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAkB,YAAY,EAA4B,MAAM,YAAY,CAAC;AAGpF,MAAM,UAAU,eAAe,CAC9B,MAAc,EACd,SAAyC,EACzC,MAAmC;IAEnC,MAAM,IAAI,GAA6B,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC;IAChF,IAAI,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC;IAC5B,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE;QACzB,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACpC,QAAQ,GAAG,IAAI,CAAC;IACjB,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,SAAkB,EAAE,EAAE,CAC7B,CAAC,KAAc,EAAuB,EAAE,CACvC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;QAChB,IAAI,KAAK,YAAY,YAAY,EAAE,CAAC;YACnC,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAC/F,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACxB,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YAClC,CAAC;QACF,CAAC;IACF,CAAC,CAAC,CAAC;AACN,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shivaedev/form",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Schema-derived Effect atom forms with optional React hooks",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"effect"
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@effect/atom-react": "4.0.6",
|
|
47
47
|
"@effect/vitest": "4.0.6",
|
|
48
|
-
"@shivaedev/quality": "0.
|
|
49
|
-
"@shivaedev/test": "0.
|
|
50
|
-
"@shivaedev/test-story": "0.
|
|
48
|
+
"@shivaedev/quality": "0.48.0",
|
|
49
|
+
"@shivaedev/test": "0.12.0",
|
|
50
|
+
"@shivaedev/test-story": "0.26.2",
|
|
51
51
|
"@types/node": "24.19.2",
|
|
52
52
|
"@types/react": "19.3.0",
|
|
53
53
|
"effect": "4.0.6",
|
package/src/form.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Effect, Equal, Result,
|
|
1
|
+
import { Effect, Equal, Layer, Result, Schema, type SchemaIssue, SchemaParser } from "effect";
|
|
2
2
|
import * as AsyncResult from "effect/reactivity/AsyncResult";
|
|
3
3
|
import * as Atom from "effect/reactivity/Atom";
|
|
4
4
|
import type * as AtomRef from "effect/reactivity/AtomRef";
|
|
@@ -9,54 +9,55 @@ import { persistence } from "./persistence.ts";
|
|
|
9
9
|
import { fromRef, propertyRef } from "./refs.ts";
|
|
10
10
|
import {
|
|
11
11
|
type Config,
|
|
12
|
-
checkOf,
|
|
13
|
-
choicesOf,
|
|
14
12
|
type Decoded,
|
|
15
13
|
type Encoded,
|
|
16
14
|
FieldFailure,
|
|
17
15
|
type Fields,
|
|
18
16
|
type Form,
|
|
19
|
-
fieldOf,
|
|
20
|
-
holder,
|
|
21
17
|
Invalid,
|
|
22
18
|
type Name,
|
|
19
|
+
type Services,
|
|
23
20
|
type Submitter,
|
|
24
21
|
} from "./shape.ts";
|
|
25
22
|
import { statusOf } from "./statusOf.ts";
|
|
26
23
|
import { trackRejections } from "./trackRejections.ts";
|
|
27
24
|
|
|
28
|
-
|
|
25
|
+
const emptyRuntime = Atom.runtime(Layer.empty);
|
|
26
|
+
|
|
27
|
+
function configuredRuntime<TFields extends Fields, A, E, R, TRuntimeError>(
|
|
28
|
+
config: Config<TFields, A, E, R, TRuntimeError>,
|
|
29
|
+
): Atom.AtomRuntime<Services<TFields, R>, TRuntimeError>;
|
|
30
|
+
function configuredRuntime(config: { readonly runtime?: Atom.AtomRuntime<never, unknown> }): Atom.AtomRuntime<never, unknown> {
|
|
31
|
+
return config.runtime ?? emptyRuntime;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function form<TFields extends Fields, TValue, TError, TServices = never, TRuntimeError = never>(
|
|
29
35
|
schema: Schema.Struct<TFields>,
|
|
30
36
|
config: Config<TFields, TValue, TError, TServices, TRuntimeError>,
|
|
31
37
|
): Form<TFields, TValue, TError, TRuntimeError> {
|
|
32
|
-
const { initialValues, onSubmit
|
|
38
|
+
const { initialValues, onSubmit } = config;
|
|
39
|
+
const runtime = configuredRuntime(config);
|
|
33
40
|
const debounce = config.debounce ?? "300 millis";
|
|
34
|
-
const checks: ReadonlyMap<string,
|
|
41
|
+
const checks: ReadonlyMap<string, (value: Encoded<TFields>[Name<TFields>]) => Effect.Effect<string | undefined, never, TServices>> = new Map(
|
|
42
|
+
Object.entries(config.checks ?? {}),
|
|
43
|
+
);
|
|
35
44
|
const decode = SchemaParser.decodeUnknownEffect(schema, { errors: "all" });
|
|
36
45
|
|
|
37
46
|
const editing = draft(initialValues, config.persistedDraft ? persistence(schema, config.persistedDraft) : undefined);
|
|
38
47
|
const { values } = editing;
|
|
39
48
|
const status = statusOf();
|
|
40
|
-
const noted = trackRejections(
|
|
41
|
-
const held
|
|
42
|
-
function refFor(name:
|
|
43
|
-
const known =
|
|
49
|
+
const noted = trackRejections(values, config.arrayKeys, status);
|
|
50
|
+
const held: { [TKey in Name<TFields>]?: AtomRef.AtomRef<Encoded<TFields>[TKey]> } = {};
|
|
51
|
+
function refFor<TKey extends Name<TFields>>(name: TKey): AtomRef.AtomRef<Encoded<TFields>[TKey]> {
|
|
52
|
+
const known = Object.hasOwn(held, name) ? held[name] : undefined;
|
|
44
53
|
if (known !== undefined) {
|
|
45
54
|
return known;
|
|
46
55
|
}
|
|
47
|
-
const made = propertyRef(
|
|
48
|
-
held
|
|
56
|
+
const made = propertyRef(values, name);
|
|
57
|
+
held[name] = made;
|
|
49
58
|
return made;
|
|
50
59
|
}
|
|
51
60
|
|
|
52
|
-
const offered = new Map<string, readonly unknown[]>();
|
|
53
|
-
for (const [name, member] of Object.entries(schema.fields)) {
|
|
54
|
-
const choices = literalChoices(member.ast);
|
|
55
|
-
if (choices !== undefined) {
|
|
56
|
-
offered.set(name, choices);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
61
|
const valuesAtom = fromRef(values);
|
|
61
62
|
|
|
62
63
|
const decoded = runtime.atom((get) =>
|
|
@@ -70,7 +71,7 @@ export function form<TFields extends Fields, TValue, TError, TServices, TRuntime
|
|
|
70
71
|
|
|
71
72
|
const schemaErrors = schemaFeedback(decoded);
|
|
72
73
|
|
|
73
|
-
const checkError = Atom.family((name:
|
|
74
|
+
const checkError = Atom.family((name: Name<TFields>): Atom.Atom<string | undefined> => {
|
|
74
75
|
const check = checks.get(name);
|
|
75
76
|
if (check === undefined) {
|
|
76
77
|
return Atom.make((): string | undefined => undefined);
|
|
@@ -79,7 +80,7 @@ export function form<TFields extends Fields, TValue, TError, TServices, TRuntime
|
|
|
79
80
|
const settled = Atom.debounce(current, debounce);
|
|
80
81
|
const answered = runtime.atom((get) => {
|
|
81
82
|
const input = get(settled);
|
|
82
|
-
return Effect.map(
|
|
83
|
+
return Effect.map(check(input), (message) => ({
|
|
83
84
|
input,
|
|
84
85
|
message,
|
|
85
86
|
}));
|
|
@@ -91,7 +92,7 @@ export function form<TFields extends Fields, TValue, TError, TServices, TRuntime
|
|
|
91
92
|
});
|
|
92
93
|
});
|
|
93
94
|
|
|
94
|
-
const error = Atom.family((name:
|
|
95
|
+
const error = Atom.family((name: Name<TFields>) =>
|
|
95
96
|
Atom.readable((get): string | undefined => {
|
|
96
97
|
if (get(status.touched)[name] !== true && !get(status.submitted)) {
|
|
97
98
|
return undefined;
|
|
@@ -123,7 +124,11 @@ export function form<TFields extends Fields, TValue, TError, TServices, TRuntime
|
|
|
123
124
|
refFor(name).set(value);
|
|
124
125
|
status.touch(name);
|
|
125
126
|
},
|
|
126
|
-
choices: <TName extends Name<TFields>>(name: TName) =>
|
|
127
|
+
choices: <TName extends Name<TFields>>(name: TName) => {
|
|
128
|
+
const member = schema.fields[name];
|
|
129
|
+
const decodeChoice = SchemaParser.decodeUnknownSync(Schema.toEncoded(schema), { disableChecks: true });
|
|
130
|
+
return (member ? literalChoices(member.ast) : undefined)?.map((value) => decodeChoice({ ...initialValues, [name]: value })[name]);
|
|
131
|
+
},
|
|
127
132
|
dirty: editing.dirty,
|
|
128
133
|
error,
|
|
129
134
|
errorAt: Atom.family((path: readonly [Name<TFields>, ...PropertyKey[]]) => {
|
|
@@ -132,7 +137,7 @@ export function form<TFields extends Fields, TValue, TError, TServices, TRuntime
|
|
|
132
137
|
get(status.touched)[path[0]] === true || get(status.submitted) ? (pathMessageAt(get(status.paths), path) ?? get(message)) : undefined,
|
|
133
138
|
);
|
|
134
139
|
}),
|
|
135
|
-
field:
|
|
140
|
+
field: refFor,
|
|
136
141
|
receive: editing.receive,
|
|
137
142
|
revert: editing.revert,
|
|
138
143
|
submit,
|
package/src/paths.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Equal } from "effect";
|
|
2
2
|
import type { Path } from "./shape.ts";
|
|
3
3
|
|
|
4
|
-
type Key = (element: unknown) => PropertyKey;
|
|
4
|
+
export type Key = (element: unknown) => PropertyKey;
|
|
5
5
|
export type KeySelectors = ReadonlyMap<string, Key>;
|
|
6
6
|
|
|
7
7
|
export interface PathMessage {
|
|
@@ -9,11 +9,6 @@ export interface PathMessage {
|
|
|
9
9
|
readonly path: Path;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export function keySelector(selector: unknown): Key;
|
|
13
|
-
export function keySelector(selector: unknown): unknown {
|
|
14
|
-
return selector;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
12
|
export function asPath(path: string | Path): Path {
|
|
18
13
|
return typeof path === "string" ? [path] : path;
|
|
19
14
|
}
|
package/src/persistence.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Schema, SchemaParser } from "effect";
|
|
2
2
|
import type { DraftSession } from "./draftSession.ts";
|
|
3
3
|
|
|
4
4
|
export interface DraftStorage {
|
|
@@ -11,6 +11,7 @@ export interface PersistedDraftConfig {
|
|
|
11
11
|
readonly key: string;
|
|
12
12
|
readonly maxAgeMs?: number;
|
|
13
13
|
readonly maxBytes?: number;
|
|
14
|
+
readonly now: () => number;
|
|
14
15
|
readonly session?: DraftSession | undefined;
|
|
15
16
|
readonly storage: () => DraftStorage;
|
|
16
17
|
}
|
|
@@ -71,7 +72,7 @@ export function persistence<TSchema extends Schema.Constraint>(schema: TSchema,
|
|
|
71
72
|
return undefined;
|
|
72
73
|
}
|
|
73
74
|
const value: unknown = bytes(raw) <= maxBytes ? JSON.parse(raw) : undefined;
|
|
74
|
-
const now =
|
|
75
|
+
const now = config.now();
|
|
75
76
|
if (
|
|
76
77
|
valid(value)
|
|
77
78
|
&& value.session === session
|
|
@@ -92,7 +93,7 @@ export function persistence<TSchema extends Schema.Constraint>(schema: TSchema,
|
|
|
92
93
|
return;
|
|
93
94
|
}
|
|
94
95
|
attempt(() => {
|
|
95
|
-
const raw = JSON.stringify({ baseline, edited, session, updatedAt:
|
|
96
|
+
const raw = JSON.stringify({ baseline, edited, session, updatedAt: config.now(), values, version: 1 });
|
|
96
97
|
const parsed: unknown = JSON.parse(raw);
|
|
97
98
|
if (!(maxAgeMs > 0 && Number.isFinite(maxAgeMs) && Number.isFinite(maxBytes) && bytes(raw) <= maxBytes && valid(parsed))) {
|
|
98
99
|
clear();
|
package/src/shape.ts
CHANGED
|
@@ -42,7 +42,7 @@ export type Checks<TFields extends Fields, R> = {
|
|
|
42
42
|
readonly [TKey in Name<TFields>]?: (value: Encoded<TFields>[TKey]) => Effect.Effect<string | undefined, never, R>;
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
export
|
|
45
|
+
export type Config<TFields extends Fields, A, E, R, TRuntimeError> = {
|
|
46
46
|
readonly arrayKeys?: ArrayKeys<TFields>;
|
|
47
47
|
readonly checks?: Checks<TFields, R>;
|
|
48
48
|
readonly debounce?: Duration.Input;
|
|
@@ -53,8 +53,9 @@ export interface Config<TFields extends Fields, A, E, R, TRuntimeError> {
|
|
|
53
53
|
submitted: Encoded<TFields>,
|
|
54
54
|
) => Effect.Effect<A, E, R | Scope.Scope | AtomRegistry | Reactivity>;
|
|
55
55
|
readonly persistedDraft?: PersistedDraftConfig | undefined;
|
|
56
|
-
|
|
57
|
-
}
|
|
56
|
+
} & ([Exclude<Services<TFields, R>, Scope.Scope | AtomRegistry | Reactivity>] extends [never]
|
|
57
|
+
? { readonly runtime?: Atom.AtomRuntime<Services<TFields, R>, TRuntimeError> }
|
|
58
|
+
: { readonly runtime: Atom.AtomRuntime<Services<TFields, R>, TRuntimeError> });
|
|
58
59
|
|
|
59
60
|
export interface Form<TFields extends Fields, A, E, TRuntimeError> {
|
|
60
61
|
readonly blur: (name: Name<TFields>) => void;
|
|
@@ -71,24 +72,4 @@ export interface Form<TFields extends Fields, A, E, TRuntimeError> {
|
|
|
71
72
|
readonly values: AtomRef.AtomRef<Encoded<TFields>>;
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
export type Holder = AtomRef.
|
|
75
|
-
|
|
76
|
-
export function holder(values: object): Holder;
|
|
77
|
-
export function holder(values: object): unknown {
|
|
78
|
-
return values;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export function fieldOf<TValue>(ref: AtomRef.AtomRef<unknown>): AtomRef.AtomRef<TValue>;
|
|
82
|
-
export function fieldOf(ref: AtomRef.AtomRef<unknown>): unknown {
|
|
83
|
-
return ref;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export function choicesOf<TValue>(choices: readonly unknown[] | undefined): readonly TValue[] | undefined;
|
|
87
|
-
export function choicesOf(choices: readonly unknown[] | undefined): unknown {
|
|
88
|
-
return choices;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export function checkOf<R>(check: unknown): (value: unknown) => Effect.Effect<string | undefined, never, R>;
|
|
92
|
-
export function checkOf(check: unknown): unknown {
|
|
93
|
-
return check;
|
|
94
|
-
}
|
|
75
|
+
export type Holder = AtomRef.ReadonlyRef<Readonly<Record<string, unknown>>>;
|
package/src/trackRejections.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
-
import { asPath,
|
|
3
|
-
import { FieldFailure, type Holder } from "./shape.ts";
|
|
2
|
+
import { asPath, type Key, retainedPath } from "./paths.ts";
|
|
3
|
+
import { type ArrayKeys, FieldFailure, type Fields, type Holder } from "./shape.ts";
|
|
4
4
|
import type { statusOf } from "./statusOf.ts";
|
|
5
5
|
|
|
6
|
-
export function trackRejections
|
|
7
|
-
|
|
6
|
+
export function trackRejections<TFields extends Fields>(
|
|
7
|
+
values: Holder,
|
|
8
|
+
selectors: ArrayKeys<TFields> | undefined,
|
|
9
|
+
status: ReturnType<typeof statusOf>,
|
|
10
|
+
) {
|
|
11
|
+
const keys: ReadonlyMap<string, Key> = new Map(Object.entries(selectors ?? {}));
|
|
8
12
|
let previous = values.value;
|
|
9
13
|
values.subscribe((next) => {
|
|
10
14
|
status.rebase(previous, next, keys);
|