@shivaedev/form 0.13.1 → 0.14.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 +15 -0
- package/README.md +7 -1
- package/dist/adapters/browserDraftStorage.d.ts.map +1 -1
- package/dist/adapters/browserDraftStorage.js +27 -2
- package/dist/adapters/browserDraftStorage.js.map +1 -1
- package/dist/adapters/draftCodec.d.ts +7 -0
- package/dist/adapters/draftCodec.d.ts.map +1 -0
- package/dist/adapters/draftCodec.js +40 -0
- package/dist/adapters/draftCodec.js.map +1 -0
- package/dist/adapters/persistence.d.ts +1 -1
- package/dist/adapters/persistence.d.ts.map +1 -1
- package/dist/adapters/persistence.js +91 -61
- package/dist/adapters/persistence.js.map +1 -1
- package/dist/adapters/react.d.ts.map +1 -1
- package/dist/adapters/react.js +3 -1
- package/dist/adapters/react.js.map +1 -1
- package/dist/draft.d.ts +2 -2
- package/dist/draft.d.ts.map +1 -1
- package/dist/draft.js +67 -45
- package/dist/draft.js.map +1 -1
- package/dist/draftValues.d.ts +13 -0
- package/dist/draftValues.d.ts.map +1 -0
- package/dist/draftValues.js +47 -0
- package/dist/draftValues.js.map +1 -0
- package/dist/form.d.ts.map +1 -1
- package/dist/form.js +17 -9
- package/dist/form.js.map +1 -1
- package/dist/persistence.d.ts +15 -11
- package/dist/persistence.d.ts.map +1 -1
- package/dist/persistence.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/browserDraftStorage.ts +30 -2
- package/src/adapters/draftCodec.ts +43 -0
- package/src/adapters/persistence.ts +97 -63
- package/src/adapters/react.ts +3 -1
- package/src/draft.ts +70 -62
- package/src/draftValues.ts +65 -0
- package/src/form.ts +12 -6
- package/src/persistence.ts +17 -7
package/dist/draft.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"draft.js","sourceRoot":"","sources":["../src/draft.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"draft.js","sourceRoot":"","sources":["../src/draft.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type Entries = Readonly<Record<string, unknown>>;
|
|
2
|
+
export interface Draft<TValues> {
|
|
3
|
+
readonly baseline: TValues;
|
|
4
|
+
readonly current: TValues;
|
|
5
|
+
readonly settled: Entries;
|
|
6
|
+
}
|
|
7
|
+
export declare function untouched({ baseline, current, settled }: Draft<Entries>, name: string): boolean;
|
|
8
|
+
export declare function changed(held: Draft<Entries>): boolean;
|
|
9
|
+
export declare function merged<TValues>(held: Draft<TValues>, incoming: TValues): TValues;
|
|
10
|
+
export declare function mergeObserved<TValues>(current: TValues, incoming: TValues, local: ReadonlySet<string>): TValues;
|
|
11
|
+
export declare function changedFields(previous: Entries, current: Entries): readonly string[];
|
|
12
|
+
export declare function accepted<TValues extends Entries>(held: Draft<TValues>, baseline: TValues, submitted: TValues, incoming?: TValues): Draft<TValues>;
|
|
13
|
+
//# sourceMappingURL=draftValues.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draftValues.d.ts","sourceRoot":"","sources":["../src/draftValues.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAExD,MAAM,WAAW,KAAK,CAAC,OAAO;IAC7B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE/F;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,OAAO,CAErD;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC;AAoBlF,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC;AAYjH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,MAAM,EAAE,CAEpF;AAED,wBAAgB,QAAQ,CAAC,OAAO,SAAS,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,CAUjJ"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Equal } from "effect";
|
|
2
|
+
export function untouched({ baseline, current, settled }, name) {
|
|
3
|
+
return Equal.equals(current[name], baseline[name]) || (Object.hasOwn(settled, name) && Equal.equals(current[name], settled[name]));
|
|
4
|
+
}
|
|
5
|
+
export function changed(held) {
|
|
6
|
+
return Object.keys({ ...held.baseline, ...held.current }).some((name) => !untouched(held, name));
|
|
7
|
+
}
|
|
8
|
+
export function merged(held, incoming) {
|
|
9
|
+
const result = {};
|
|
10
|
+
for (const name of Object.keys({ ...held.current, ...incoming })) {
|
|
11
|
+
const source = untouched(held, name) ? incoming : held.current;
|
|
12
|
+
if (Object.hasOwn(source, name)) {
|
|
13
|
+
result[name] = source[name];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
function matching(current, submitted) {
|
|
19
|
+
return Object.fromEntries(Object.keys({ ...current, ...submitted })
|
|
20
|
+
.filter((name) => Equal.equals(current[name], submitted[name]))
|
|
21
|
+
.map((name) => [name, submitted[name]]));
|
|
22
|
+
}
|
|
23
|
+
export function mergeObserved(current, incoming, local) {
|
|
24
|
+
const result = {};
|
|
25
|
+
for (const name of Object.keys({ ...current, ...incoming })) {
|
|
26
|
+
const source = local.has(name) ? current : incoming;
|
|
27
|
+
if (Object.hasOwn(source, name)) {
|
|
28
|
+
result[name] = source[name];
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
export function changedFields(previous, current) {
|
|
34
|
+
return Object.keys({ ...previous, ...current }).filter((name) => !Equal.equals(previous[name], current[name]));
|
|
35
|
+
}
|
|
36
|
+
export function accepted(held, baseline, submitted, incoming) {
|
|
37
|
+
if (held.baseline !== baseline) {
|
|
38
|
+
return { ...held, settled: matching(held.current, submitted) };
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
...held,
|
|
42
|
+
baseline: incoming ?? submitted,
|
|
43
|
+
current: incoming === undefined ? held.current : merged({ ...held, baseline: submitted, settled: {} }, incoming),
|
|
44
|
+
settled: {},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=draftValues.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draftValues.js","sourceRoot":"","sources":["../src/draftValues.ts"],"names":[],"mappings":"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"}
|
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,EAAyB,MAAM,EAAkC,MAAM,QAAQ,CAAC;AAUvF,OAAO,EAAE,KAAK,MAAM,EAA4C,KAAK,MAAM,EAAE,KAAK,IAAI,EAA4C,MAAM,YAAY,CAAC;AAcrJ,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,
|
|
1
|
+
{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,MAAM,EAAkC,MAAM,QAAQ,CAAC;AAUvF,OAAO,EAAE,KAAK,MAAM,EAA4C,KAAK,MAAM,EAAE,KAAK,IAAI,EAA4C,MAAM,YAAY,CAAC;AAcrJ,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,CA2G9C"}
|
package/dist/form.js
CHANGED
|
@@ -35,7 +35,11 @@ export function form(schema, config) {
|
|
|
35
35
|
held[name] = made;
|
|
36
36
|
return made;
|
|
37
37
|
}
|
|
38
|
-
const
|
|
38
|
+
const fromValues = fromRef(values);
|
|
39
|
+
const valuesAtom = Atom.readable((get) => {
|
|
40
|
+
get(editing.mounted);
|
|
41
|
+
return get(fromValues);
|
|
42
|
+
});
|
|
39
43
|
const decoded = runtime.atom((get) => decode(get(valuesAtom)).pipe(Effect.match({
|
|
40
44
|
onFailure: (issue) => Result.fail(issue),
|
|
41
45
|
onSuccess: (value) => Result.succeed(value),
|
|
@@ -51,17 +55,21 @@ export function form(schema, config) {
|
|
|
51
55
|
const submitter = {
|
|
52
56
|
fail: (path, message) => Effect.fail(new FieldFailure(typeof path === "string" ? { message, path } : { message, path: path[0], segments: path })),
|
|
53
57
|
};
|
|
54
|
-
const validate = runtime.fn()(() => {
|
|
58
|
+
const validate = runtime.fn()((_, get) => {
|
|
59
|
+
get.mount(editing.mounted);
|
|
55
60
|
status.attempt();
|
|
56
61
|
return snapshot(values.value);
|
|
57
62
|
});
|
|
58
|
-
const submit = runtime.fn()(() =>
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
const submit = runtime.fn()((_, get) => {
|
|
64
|
+
get.mount(editing.mounted);
|
|
65
|
+
return Effect.gen(function* () {
|
|
66
|
+
status.attempt();
|
|
67
|
+
const submission = editing.submission();
|
|
68
|
+
const submitted = submission.values;
|
|
69
|
+
const { decoded: value } = yield* snapshot(submitted);
|
|
70
|
+
return yield* onSubmit(value, submitter, submitted).pipe(Effect.tapError(noted(submitted)), Effect.tap((saved) => Effect.sync(() => submission.accept(config.savedValues?.(saved)))));
|
|
71
|
+
});
|
|
72
|
+
});
|
|
65
73
|
return {
|
|
66
74
|
blur: status.touch,
|
|
67
75
|
change: (name, value) => {
|
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,EAAE,MAAM,EAAoB,YAAY,EAAE,MAAM,QAAQ,CAAC;AACvF,OAAO,KAAK,WAAW,MAAM,+BAA+B,CAAC;AAC7D,OAAO,KAAK,IAAI,MAAM,wBAAwB,CAAC;AAE/C,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAA2C,YAAY,EAAoE,MAAM,YAAY,CAAC;AACrJ,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAK/C,SAAS,iBAAiB,CAAC,MAA+D;IACzF,OAAO,MAAM,CAAC,OAAO,IAAI,YAAY,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,IAAI,CACnB,MAA8B,EAC9B,MAAiE;IAEjE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC;IAC3C,MAAM,OAAO,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,YAAY,CAAC;IACjD,MAAM,MAAM,GAAyH,IAAI,GAAG,CAC3I,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CACnC,CAAC;IACF,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAEzE,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACrH,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC3B,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAC;IAC1B,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAChE,MAAM,IAAI,GAA0E,EAAE,CAAC;IACvF,SAAS,MAAM,CAA6B,IAAU;QACrD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACjE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC;QACd,CAAC;QACD,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QAClB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"form.js","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"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"}
|
package/dist/persistence.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { Context } from "effect";
|
|
1
|
+
import { Context, type Effect } from "effect";
|
|
2
2
|
import type { DraftSession } from "./draftSession.ts";
|
|
3
|
+
export type DraftOperation<A> = A | Effect.Effect<A, unknown>;
|
|
3
4
|
export interface DraftStorage {
|
|
4
|
-
readonly getItem: (key: string) => string | null
|
|
5
|
-
readonly removeItem: (key: string) => void
|
|
6
|
-
readonly setItem: (key: string, value: string) => void
|
|
5
|
+
readonly getItem: (key: string) => DraftOperation<string | null>;
|
|
6
|
+
readonly removeItem: (key: string, expected: string) => DraftOperation<void>;
|
|
7
|
+
readonly setItem: (key: string, value: string, expected?: string) => DraftOperation<void>;
|
|
8
|
+
readonly subscribe?: (key: string, listener: (value: string | null) => void) => () => void;
|
|
7
9
|
}
|
|
8
10
|
declare const DraftStorageProvider_base: Context.ServiceClass<DraftStorageProvider, "@shivaedev/form/DraftStorageProvider", () => DraftStorage>;
|
|
9
11
|
export declare class DraftStorageProvider extends DraftStorageProvider_base {
|
|
@@ -16,14 +18,16 @@ export interface PersistedDraftConfig {
|
|
|
16
18
|
readonly session?: DraftSession | undefined;
|
|
17
19
|
readonly storage: () => DraftStorage;
|
|
18
20
|
}
|
|
21
|
+
export interface StoredValues<TValues> {
|
|
22
|
+
readonly baseline: TValues;
|
|
23
|
+
readonly edited: readonly string[];
|
|
24
|
+
readonly values: TValues;
|
|
25
|
+
}
|
|
19
26
|
export interface Persistence<TValues> {
|
|
20
|
-
readonly clear: () => void;
|
|
21
|
-
readonly
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
readonly values: TValues;
|
|
25
|
-
} | undefined;
|
|
26
|
-
readonly write: (baseline: TValues, values: TValues, edited: readonly string[]) => void;
|
|
27
|
+
readonly clear: (revision?: string) => void;
|
|
28
|
+
readonly observe: (receive: (values: StoredValues<TValues> | undefined) => boolean) => () => void;
|
|
29
|
+
readonly revision: () => () => string | undefined;
|
|
30
|
+
readonly write: (baseline: TValues, values: TValues, edited: readonly string[], sameInput?: boolean) => void;
|
|
27
31
|
}
|
|
28
32
|
export {};
|
|
29
33
|
//# sourceMappingURL=persistence.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAE9D,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,cAAc,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACjE,QAAQ,CAAC,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,cAAc,CAAC,IAAI,CAAC,CAAC;IAC7E,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,cAAc,CAAC,IAAI,CAAC,CAAC;IAC1F,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;CAC3F;kIAEqF,YAAY;AAAlG,qBAAa,oBAAqB,SAAQ,yBAAmG;CAAG;AAEhJ,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,YAAY,CAAC,OAAO;IACpC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,WAAW,CAAC,OAAO;IACnC,QAAQ,CAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,OAAO,CAAC,GAAG,SAAS,KAAK,OAAO,KAAK,MAAM,IAAI,CAAC;IAClG,QAAQ,CAAC,QAAQ,EAAE,MAAM,MAAM,MAAM,GAAG,SAAS,CAAC;IAClD,QAAQ,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,SAAS,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CAC7G"}
|
package/dist/persistence.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistence.js","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"persistence.js","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,QAAQ,CAAC;AAY9C,MAAM,OAAO,oBAAqB,SAAQ,OAAO,CAAC,OAAO,EAA4C,CAAC,sCAAsC,CAAC;CAAG"}
|
package/package.json
CHANGED
|
@@ -1,4 +1,32 @@
|
|
|
1
|
-
import { Layer } from "effect";
|
|
1
|
+
import { Effect, Layer } from "effect";
|
|
2
2
|
import { DraftStorageProvider } from "#persistence.ts";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
function mutate(key: string, run: () => void) {
|
|
5
|
+
const locks = globalThis.navigator?.locks;
|
|
6
|
+
return locks ? Effect.promise(() => locks.request(`@shivaedev/form/${key}`, run)) : run();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const browserDraftStorage = Layer.succeed(DraftStorageProvider, () => ({
|
|
10
|
+
getItem: (key) => globalThis.localStorage.getItem(key),
|
|
11
|
+
removeItem: (key, expected) =>
|
|
12
|
+
mutate(key, () => {
|
|
13
|
+
if (globalThis.localStorage.getItem(key) === expected) {
|
|
14
|
+
globalThis.localStorage.removeItem(key);
|
|
15
|
+
}
|
|
16
|
+
}),
|
|
17
|
+
setItem: (key, value, expected) =>
|
|
18
|
+
mutate(key, () => {
|
|
19
|
+
if (expected === undefined || globalThis.localStorage.getItem(key) === expected) {
|
|
20
|
+
globalThis.localStorage.setItem(key, value);
|
|
21
|
+
}
|
|
22
|
+
}),
|
|
23
|
+
subscribe: (key, listener) => {
|
|
24
|
+
function changed(event: StorageEvent) {
|
|
25
|
+
if (event.storageArea === globalThis.localStorage && (event.key === key || event.key === null)) {
|
|
26
|
+
listener(event.newValue);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
globalThis.addEventListener("storage", changed);
|
|
30
|
+
return () => globalThis.removeEventListener("storage", changed);
|
|
31
|
+
},
|
|
32
|
+
}));
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Schema, SchemaParser } from "effect";
|
|
2
|
+
import type { PersistedDraftConfig, StoredValues } from "#persistence.ts";
|
|
3
|
+
|
|
4
|
+
export function draftCodec<TSchema extends Schema.Constraint>(schema: TSchema, config: PersistedDraftConfig) {
|
|
5
|
+
const StoredDraft = Schema.Struct({
|
|
6
|
+
baseline: Schema.Unknown,
|
|
7
|
+
edited: Schema.Array(Schema.String),
|
|
8
|
+
session: Schema.String,
|
|
9
|
+
updatedAt: Schema.Number,
|
|
10
|
+
values: Schema.Unknown,
|
|
11
|
+
version: Schema.Literal(1),
|
|
12
|
+
});
|
|
13
|
+
const valid = Schema.is(StoredDraft);
|
|
14
|
+
const decode = SchemaParser.decodeUnknownSync(Schema.toEncoded(schema), { disableChecks: true });
|
|
15
|
+
const maxAgeMs = config.maxAgeMs ?? 7 * 24 * 60 * 60 * 1000;
|
|
16
|
+
const maxBytes = config.maxBytes ?? 256 * 1024;
|
|
17
|
+
const session = config.session?.id ?? "";
|
|
18
|
+
function read(raw: string): StoredValues<TSchema["Encoded"]> {
|
|
19
|
+
const value: unknown = new TextEncoder().encode(raw).byteLength <= maxBytes ? JSON.parse(raw) : undefined;
|
|
20
|
+
const now = config.now();
|
|
21
|
+
if (
|
|
22
|
+
!valid(value)
|
|
23
|
+
|| value.session !== session
|
|
24
|
+
|| !Number.isFinite(maxAgeMs)
|
|
25
|
+
|| !Number.isFinite(maxBytes)
|
|
26
|
+
|| maxAgeMs <= 0
|
|
27
|
+
|| maxBytes <= 0
|
|
28
|
+
|| now - value.updatedAt > maxAgeMs
|
|
29
|
+
|| value.updatedAt > now
|
|
30
|
+
) {
|
|
31
|
+
throw new Error("Invalid stored draft");
|
|
32
|
+
}
|
|
33
|
+
return { baseline: decode(value.baseline), edited: value.edited, values: decode(value.values) };
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
read,
|
|
37
|
+
write: (baseline: TSchema["Encoded"], values: TSchema["Encoded"], edited: readonly string[]) => {
|
|
38
|
+
const raw = JSON.stringify({ baseline, edited, revision: crypto.randomUUID(), session, updatedAt: config.now(), values, version: 1 });
|
|
39
|
+
read(raw);
|
|
40
|
+
return raw;
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -1,87 +1,121 @@
|
|
|
1
|
-
import { Schema,
|
|
2
|
-
import type { PersistedDraftConfig, Persistence } from "#persistence.ts";
|
|
1
|
+
import { Data, Effect, type Schema, Semaphore } from "effect";
|
|
2
|
+
import type { DraftOperation, PersistedDraftConfig, Persistence } from "#persistence.ts";
|
|
3
|
+
import { draftCodec } from "./draftCodec.ts";
|
|
4
|
+
|
|
5
|
+
class DraftStorageUnavailable extends Data.TaggedError("DraftStorageUnavailable")<{ readonly cause: unknown }> {}
|
|
6
|
+
|
|
7
|
+
function operation<A>(run: () => DraftOperation<A>): Effect.Effect<A, DraftStorageUnavailable> {
|
|
8
|
+
return Effect.suspend(() => {
|
|
9
|
+
const value = run();
|
|
10
|
+
return Effect.isEffect(value) ? value : Effect.succeed(value);
|
|
11
|
+
}).pipe(Effect.catchCause((cause) => Effect.fail(new DraftStorageUnavailable({ cause }))));
|
|
12
|
+
}
|
|
3
13
|
|
|
4
14
|
export function persistence<TSchema extends Schema.Constraint>(schema: TSchema, config: PersistedDraftConfig): Persistence<TSchema["Encoded"]> {
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
edited: Schema.Array(Schema.String),
|
|
9
|
-
session: Schema.String,
|
|
10
|
-
updatedAt: Schema.Number,
|
|
11
|
-
values: Schema.Unknown,
|
|
12
|
-
version: Schema.Literal(1),
|
|
13
|
-
});
|
|
14
|
-
const valid = Schema.is(StoredDraft);
|
|
15
|
-
const decode = SchemaParser.decodeUnknownSync(encoded, { disableChecks: true });
|
|
16
|
-
const maxAgeMs = config.maxAgeMs ?? 7 * 24 * 60 * 60 * 1000;
|
|
17
|
-
const maxBytes = config.maxBytes ?? 256 * 1024;
|
|
18
|
-
function bytes(value: string) {
|
|
19
|
-
return new TextEncoder().encode(value).byteLength;
|
|
20
|
-
}
|
|
21
|
-
const storage = config.storage;
|
|
22
|
-
const session = config.session?.id ?? "";
|
|
15
|
+
const codec = draftCodec(schema, config);
|
|
16
|
+
const serial = Semaphore.makeUnsafe(1);
|
|
17
|
+
let revision: { value: string | undefined } = { value: undefined };
|
|
23
18
|
function active() {
|
|
24
19
|
return config.session?.active !== false;
|
|
25
20
|
}
|
|
26
|
-
function
|
|
21
|
+
function run(effect: Effect.Effect<unknown, DraftStorageUnavailable>) {
|
|
22
|
+
return Effect.runCallback(serial.withPermit(effect).pipe(Effect.catchTag("DraftStorageUnavailable", () => Effect.void)));
|
|
23
|
+
}
|
|
24
|
+
function clear(expected = revision.value) {
|
|
25
|
+
if (expected !== undefined) {
|
|
26
|
+
run(operation(() => config.storage().removeItem(config.key, expected)));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function read(raw: string | null) {
|
|
27
30
|
try {
|
|
28
|
-
return
|
|
31
|
+
return { values: raw === null ? undefined : codec.read(raw) };
|
|
29
32
|
} catch {
|
|
30
|
-
|
|
33
|
+
if (raw !== null) {
|
|
34
|
+
clear(raw);
|
|
35
|
+
}
|
|
31
36
|
return undefined;
|
|
32
37
|
}
|
|
33
38
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
config.session?.track(config.key, () =>
|
|
40
|
+
run(
|
|
41
|
+
Effect.gen(function* () {
|
|
42
|
+
const storage = yield* operation(config.storage);
|
|
43
|
+
const raw = yield* operation(() => storage.getItem(config.key));
|
|
44
|
+
if (raw !== null) {
|
|
45
|
+
yield* operation(() => codec.read(raw));
|
|
46
|
+
yield* operation(() => storage.removeItem(config.key, raw));
|
|
47
|
+
}
|
|
48
|
+
}),
|
|
49
|
+
),
|
|
50
|
+
);
|
|
38
51
|
return {
|
|
39
|
-
clear: () => {
|
|
52
|
+
clear: (expected = revision.value) => {
|
|
40
53
|
if (active()) {
|
|
41
|
-
clear();
|
|
54
|
+
clear(expected);
|
|
42
55
|
}
|
|
43
56
|
},
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
57
|
+
observe: (receive) => {
|
|
58
|
+
let stopped = false;
|
|
59
|
+
let changes = 0;
|
|
60
|
+
function changed(raw: string | null, loaded = false) {
|
|
61
|
+
if (stopped || !active()) {
|
|
62
|
+
return;
|
|
48
63
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return undefined;
|
|
64
|
+
if (!loaded && revision.value === (raw ?? undefined)) {
|
|
65
|
+
return;
|
|
52
66
|
}
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
valid(value)
|
|
57
|
-
&& value.session === session
|
|
58
|
-
&& Number.isFinite(maxAgeMs)
|
|
59
|
-
&& Number.isFinite(maxBytes)
|
|
60
|
-
&& maxAgeMs > 0
|
|
61
|
-
&& maxBytes > 0
|
|
62
|
-
&& now - value.updatedAt <= maxAgeMs
|
|
63
|
-
&& value.updatedAt <= now
|
|
64
|
-
) {
|
|
65
|
-
return { baseline: decode(value.baseline), edited: value.edited, values: decode(value.values) };
|
|
67
|
+
const parsed = read(raw);
|
|
68
|
+
if (parsed && receive(parsed.values)) {
|
|
69
|
+
revision = { value: raw ?? undefined };
|
|
66
70
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
}
|
|
72
|
+
let unsubscribe: (() => void) | undefined;
|
|
73
|
+
const stop = Effect.runCallback(
|
|
74
|
+
Effect.gen(function* () {
|
|
75
|
+
if (!active()) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const storage = yield* operation(config.storage);
|
|
79
|
+
unsubscribe = yield* operation(() =>
|
|
80
|
+
storage.subscribe?.(config.key, (incoming) => {
|
|
81
|
+
changes += 1;
|
|
82
|
+
changed(incoming);
|
|
83
|
+
}),
|
|
84
|
+
);
|
|
85
|
+
const before = changes;
|
|
86
|
+
const captured = revision;
|
|
87
|
+
const raw = yield* operation(() => storage.getItem(config.key));
|
|
88
|
+
if (before === changes && captured === revision) {
|
|
89
|
+
changed(raw, true);
|
|
90
|
+
}
|
|
91
|
+
}).pipe(Effect.catchTag("DraftStorageUnavailable", () => Effect.void)),
|
|
92
|
+
);
|
|
93
|
+
return () => {
|
|
94
|
+
stopped = true;
|
|
95
|
+
unsubscribe?.();
|
|
96
|
+
stop();
|
|
97
|
+
};
|
|
98
|
+
},
|
|
99
|
+
revision: () => {
|
|
100
|
+
const captured = revision;
|
|
101
|
+
return () => captured.value;
|
|
102
|
+
},
|
|
103
|
+
write: (baseline, values, edited, sameInput) => {
|
|
71
104
|
if (!active()) {
|
|
72
105
|
return;
|
|
73
106
|
}
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
if (
|
|
78
|
-
|
|
79
|
-
|
|
107
|
+
try {
|
|
108
|
+
const expected = sameInput ? revision.value : undefined;
|
|
109
|
+
const raw = codec.write(baseline, values, edited);
|
|
110
|
+
if (sameInput) {
|
|
111
|
+
revision.value = raw;
|
|
112
|
+
} else {
|
|
113
|
+
revision = { value: raw };
|
|
80
114
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
115
|
+
run(operation(() => (active() ? config.storage().setItem(config.key, raw, expected) : undefined)));
|
|
116
|
+
} catch {
|
|
117
|
+
clear();
|
|
118
|
+
}
|
|
85
119
|
},
|
|
86
120
|
};
|
|
87
121
|
}
|
package/src/adapters/react.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useAtomRef, useAtomSet, useAtomValue } from "@effect/atom-react";
|
|
1
|
+
import { useAtomMount, useAtomRef, useAtomSet, useAtomValue } from "@effect/atom-react";
|
|
2
2
|
import type * as AsyncResult from "effect/reactivity/AsyncResult";
|
|
3
3
|
import { createContext, useCallback, useContext, useMemo } from "react";
|
|
4
4
|
import type { DraftSession } from "#draftSession.ts";
|
|
@@ -23,6 +23,7 @@ export function useField<TFields extends Fields, A, E, TRuntimeError, TKey exten
|
|
|
23
23
|
form: Form<TFields, A, E, TRuntimeError>,
|
|
24
24
|
name: TKey,
|
|
25
25
|
): Field<TFields, TKey> {
|
|
26
|
+
useAtomMount(form.dirty);
|
|
26
27
|
const value = useAtomRef(form.field(name));
|
|
27
28
|
const error = useAtomValue(form.error(name));
|
|
28
29
|
const onChange = useCallback((next: Encoded<TFields>[TKey]) => form.change(name, next), [form, name]);
|
|
@@ -38,6 +39,7 @@ export interface Submit<A, E> {
|
|
|
38
39
|
export function useSubmit<TFields extends Fields, A, E, TRuntimeError>(
|
|
39
40
|
form: Form<TFields, A, E, TRuntimeError>,
|
|
40
41
|
): Submit<A, E | TRuntimeError | FieldFailure | Invalid> {
|
|
42
|
+
useAtomMount(form.dirty);
|
|
41
43
|
const result = useAtomValue(form.submit);
|
|
42
44
|
const set = useAtomSet(form.submit);
|
|
43
45
|
const run = useCallback(() => set(), [set]);
|