@shivaedev/effect-react 0.11.1 → 0.12.1
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 +13 -0
- package/dist/fieldRejection.d.ts +14 -12
- package/dist/fieldRejection.d.ts.map +1 -1
- package/dist/fieldRejection.js +14 -12
- package/dist/fieldRejection.js.map +1 -1
- package/dist/submission.js +3 -3
- package/dist/submission.js.map +1 -1
- package/package.json +13 -13
- package/src/fieldRejection.ts +23 -21
- package/src/submission.ts +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.12.1 - 2026-10-21
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Release with updated workspace dependencies.
|
|
8
|
+
|
|
9
|
+
## 0.12.0 - 2026-10-19
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Choose a live changed-hint coalescing window per bound query with React's `useQuery(atom, { coalesceWindow })`, keeping the session window as the default. Queries over one connection refetch on their own schedules; changing the option does not reconnect or refetch queries.
|
|
14
|
+
- Configure a bound query's window through its registry with `queryCoalesceWindow(query)` from `@shivaedev/effect-contract/queryCoalesceWindow.ts`.
|
|
15
|
+
|
|
3
16
|
## 0.11.1 - 2026-10-19
|
|
4
17
|
|
|
5
18
|
### Fixed
|
package/dist/fieldRejection.d.ts
CHANGED
|
@@ -2,22 +2,24 @@ import { Effect, type Schema, type Scope } from "effect";
|
|
|
2
2
|
import type { AtomRegistry } from "effect/reactivity/AtomRegistry";
|
|
3
3
|
import type { Reactivity } from "effect/reactivity/Reactivity";
|
|
4
4
|
import type { FieldFailure, Fields, Name, Submitter } from "@shivaedev/effect-form/shape.ts";
|
|
5
|
-
export interface FieldRejection<
|
|
6
|
-
readonly field:
|
|
5
|
+
export interface FieldRejection<TName extends string> {
|
|
6
|
+
readonly field: TName;
|
|
7
7
|
readonly message: string;
|
|
8
8
|
}
|
|
9
|
-
export type AtomServices<
|
|
10
|
-
export type RejectField<
|
|
11
|
-
type Unmatched<
|
|
9
|
+
export type AtomServices<TRequirements> = TRequirements | Scope.Scope | AtomRegistry | Reactivity;
|
|
10
|
+
export type RejectField<TFields extends Fields, TError> = (error: TError) => FieldRejection<Name<TFields>> | undefined;
|
|
11
|
+
type Unmatched<TFields extends Fields, TError> = TError extends {
|
|
12
12
|
readonly _tag: string;
|
|
13
13
|
readonly message: string;
|
|
14
|
-
} ? "field" extends keyof
|
|
15
|
-
export type FieldRejectionMapping<
|
|
16
|
-
readonly rejectField?: RejectField<
|
|
17
|
-
} & ([
|
|
18
|
-
|
|
14
|
+
} ? "field" extends keyof TError ? Exclude<TError["field"], Name<TFields> | undefined> : never : never;
|
|
15
|
+
export type FieldRejectionMapping<TFields extends Fields, TError> = {
|
|
16
|
+
readonly rejectField?: RejectField<TFields, TError>;
|
|
17
|
+
} & ([
|
|
18
|
+
Unmatched<TFields, TError>
|
|
19
|
+
] extends [never] ? unknown : {
|
|
20
|
+
readonly rejectField: RejectField<TFields, TError>;
|
|
19
21
|
});
|
|
20
|
-
export declare
|
|
21
|
-
export declare
|
|
22
|
+
export declare function fieldRejectionOf<TFields extends Fields>(schema: Schema.Struct<TFields>): (error: unknown) => FieldRejection<Name<TFields>> | undefined;
|
|
23
|
+
export declare function rejecting<TFields extends Fields, TValues, TResult, TError, TRequirements>(schema: Schema.Struct<TFields>, save: (values: TValues) => Effect.Effect<TResult, TError, TRequirements>, reject: RejectField<TFields, TError> | undefined): (values: TValues, submitter: Submitter<Name<TFields>>) => Effect.Effect<TResult, TError | FieldFailure, TRequirements>;
|
|
22
24
|
export {};
|
|
23
25
|
//# sourceMappingURL=fieldRejection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fieldRejection.d.ts","sourceRoot":"","sources":["../src/fieldRejection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAa,KAAK,MAAM,EAAE,KAAK,KAAK,EAAE,MAAM,QAAQ,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAE7F,MAAM,WAAW,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"fieldRejection.d.ts","sourceRoot":"","sources":["../src/fieldRejection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAa,KAAK,MAAM,EAAE,KAAK,KAAK,EAAE,MAAM,QAAQ,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAE7F,MAAM,WAAW,cAAc,CAAC,KAAK,SAAS,MAAM;IACnD,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,YAAY,CAAC,aAAa,IAAI,aAAa,GAAG,KAAK,CAAC,KAAK,GAAG,YAAY,GAAG,UAAU,CAAC;AAElG,MAAM,MAAM,WAAW,CAAC,OAAO,SAAS,MAAM,EAAE,MAAM,IAAI,CAAC,KAAK,EAAE,MAAM,KAAK,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;AAEvH,KAAK,SAAS,CAAC,OAAO,SAAS,MAAM,EAAE,MAAM,IAAI,MAAM,SAAS;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAChH,OAAO,SAAS,MAAM,MAAM,GAC3B,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC,GACnD,KAAK,GACN,KAAK,CAAC;AAET,MAAM,MAAM,qBAAqB,CAAC,OAAO,SAAS,MAAM,EAAE,MAAM,IAAI;IAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,CAAC;IAC9H,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,SAAS,CAAC,KAAK,CAAC,GACd,OAAO,GACP;IAAE,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC,CAAC;AAE3D,wBAAgB,gBAAgB,CAAC,OAAO,SAAS,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,WACvE,OAAO,KAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,SAAS,CAUlE;AAED,wBAAgB,SAAS,CAAC,OAAO,SAAS,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EACxF,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAC9B,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,EACxE,MAAM,EAAE,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,SAAS,YAGhC,OAAO,aAAa,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE,aAAa,CAAC,CAK3H"}
|
package/dist/fieldRejection.js
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { Effect, Predicate } from "effect";
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
};
|
|
12
|
-
|
|
2
|
+
export function fieldRejectionOf(schema) {
|
|
3
|
+
return (error) => {
|
|
4
|
+
function isName(name) {
|
|
5
|
+
return typeof name === "string" && Object.hasOwn(schema.fields, name);
|
|
6
|
+
}
|
|
7
|
+
if (!(Predicate.hasProperty(error, "_tag") && Predicate.hasProperty(error, "field") && Predicate.hasProperty(error, "message"))) {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
const { _tag, field, message } = error;
|
|
11
|
+
return typeof _tag === "string" && isName(field) && typeof message === "string" ? { field, message } : undefined;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export function rejecting(schema, save, reject) {
|
|
13
15
|
const rejection = reject ?? fieldRejectionOf(schema);
|
|
14
16
|
return (values, submitter) => Effect.catch(save(values), (error) => {
|
|
15
17
|
const found = rejection(error);
|
|
16
18
|
return found === undefined ? Effect.fail(error) : submitter.fail(found.field, found.message);
|
|
17
19
|
});
|
|
18
|
-
}
|
|
20
|
+
}
|
|
19
21
|
//# sourceMappingURL=fieldRejection.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fieldRejection.js","sourceRoot":"","sources":["../src/fieldRejection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,SAAS,EAA2B,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"fieldRejection.js","sourceRoot":"","sources":["../src/fieldRejection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,SAAS,EAA2B,MAAM,QAAQ,CAAC;AA0BpE,MAAM,UAAU,gBAAgB,CAAyB,MAA8B;IACtF,OAAO,CAAC,KAAc,EAA6C,EAAE;QACpE,SAAS,MAAM,CAAC,IAAa;YAC5B,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACvE,CAAC;QACD,IAAI,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;YACjI,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;QACvC,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAClH,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CACxB,MAA8B,EAC9B,IAAwE,EACxE,MAAgD;IAEhD,MAAM,SAAS,GAAG,MAAM,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACrD,OAAO,CAAC,MAAe,EAAE,SAAmC,EAAgE,EAAE,CAC7H,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAA+C,EAAE;QACjF,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;QAC/B,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9F,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/submission.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { form } from "@shivaedev/effect-form/form.ts";
|
|
2
2
|
import { actionTrace } from "#actionTrace.ts";
|
|
3
3
|
import { rejecting } from "./fieldRejection.js";
|
|
4
4
|
export function submission(config) {
|
|
5
5
|
const { fields, initialValues, runtime } = config;
|
|
6
6
|
const save = rejecting(fields, config.save, config.rejectField);
|
|
7
7
|
let submitted;
|
|
8
|
-
const
|
|
8
|
+
const currentForm = form(fields, {
|
|
9
9
|
initialValues,
|
|
10
10
|
onSubmit: (values, submitter, snapshot) => {
|
|
11
11
|
submitted = snapshot;
|
|
@@ -14,6 +14,6 @@ export function submission(config) {
|
|
|
14
14
|
persistedDraft: config.persistedDraft,
|
|
15
15
|
runtime,
|
|
16
16
|
});
|
|
17
|
-
return { form, submitted: () => submitted };
|
|
17
|
+
return { form: currentForm, submitted: () => submitted };
|
|
18
18
|
}
|
|
19
19
|
//# sourceMappingURL=submission.js.map
|
package/dist/submission.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"submission.js","sourceRoot":"","sources":["../src/submission.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AAGtD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAuC,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAgBrF,MAAM,UAAU,UAAU,CACzB,MAAyD;IAEzD,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IAClD,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;IAChE,IAAI,SAAuC,CAAC;IAC5C,MAAM,
|
|
1
|
+
{"version":3,"file":"submission.js","sourceRoot":"","sources":["../src/submission.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AAGtD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAuC,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAgBrF,MAAM,UAAU,UAAU,CACzB,MAAyD;IAEzD,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IAClD,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;IAChE,IAAI,SAAuC,CAAC;IAC5C,MAAM,WAAW,GAAsD,IAAI,CAAC,MAAM,EAAE;QACnF,aAAa;QACb,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE;YACzC,SAAS,GAAG,QAAQ,CAAC;YACrB,OAAO,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,WAAW,CAAC,CAAC;QAC1D,CAAC;QACD,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,OAAO;KACP,CAAC,CAAC;IACH,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,CAAC;AAC1D,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shivaedev/effect-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "React query, action, editor and session hooks for native Effect atoms",
|
|
5
5
|
"homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/effect-react#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -43,41 +43,41 @@
|
|
|
43
43
|
"README.md"
|
|
44
44
|
],
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@shivaedev/effect-contract": "0.
|
|
47
|
-
"@shivaedev/effect-form": "0.
|
|
46
|
+
"@shivaedev/effect-contract": "0.10.0",
|
|
47
|
+
"@shivaedev/effect-form": "0.6.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@effect/atom-react": "4.0.4",
|
|
51
51
|
"@effect/platform-node": "4.0.4",
|
|
52
52
|
"@effect/sql-pg": "4.0.4",
|
|
53
53
|
"@effect/sql-sqlite-node": "4.0.4",
|
|
54
|
-
"@shivaedev/effect-pg-boss": "0.
|
|
54
|
+
"@shivaedev/effect-pg-boss": "0.15.2",
|
|
55
55
|
"@shivaedev/effect-service": "0.4.0",
|
|
56
|
-
"@shivaedev/effect-sql": "0.
|
|
56
|
+
"@shivaedev/effect-sql": "0.13.0",
|
|
57
57
|
"@shivaedev/effect-test": "0.7.1",
|
|
58
|
-
"@shivaedev/effect-test-sql": "0.8.
|
|
58
|
+
"@shivaedev/effect-test-sql": "0.8.2",
|
|
59
59
|
"@shivaedev/local-postgres": "0.6.0",
|
|
60
|
-
"@shivaedev/platform": "0.
|
|
61
|
-
"@shivaedev/quality": "0.
|
|
60
|
+
"@shivaedev/platform": "0.23.1",
|
|
61
|
+
"@shivaedev/quality": "0.32.1",
|
|
62
62
|
"@shivaedev/test-story": "0.17.0",
|
|
63
|
-
"@tanstack/react-router": "1.170.
|
|
63
|
+
"@tanstack/react-router": "1.170.44",
|
|
64
64
|
"@types/node": "24.19.2",
|
|
65
65
|
"@types/react": "19.3.0",
|
|
66
66
|
"@types/react-dom": "19.3.0",
|
|
67
67
|
"effect": "4.0.4",
|
|
68
|
-
"happy-dom": "
|
|
68
|
+
"happy-dom": "21.0.1",
|
|
69
69
|
"react": "19.3.0",
|
|
70
70
|
"react-dom": "19.3.0",
|
|
71
71
|
"typescript": "7.0.2",
|
|
72
|
-
"vitest": "5.0.
|
|
72
|
+
"vitest": "5.0.4"
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
75
|
"@effect/atom-react": "4.0.4",
|
|
76
|
-
"@tanstack/react-router": "1.170.
|
|
76
|
+
"@tanstack/react-router": "1.170.44",
|
|
77
77
|
"effect": "4.0.4",
|
|
78
78
|
"react": "19.3.0",
|
|
79
79
|
"react-dom": "19.3.0",
|
|
80
|
-
"vitest": "5.0.
|
|
80
|
+
"vitest": "5.0.4"
|
|
81
81
|
},
|
|
82
82
|
"peerDependenciesMeta": {
|
|
83
83
|
"@tanstack/react-router": {
|
package/src/fieldRejection.ts
CHANGED
|
@@ -3,29 +3,30 @@ import type { AtomRegistry } from "effect/reactivity/AtomRegistry";
|
|
|
3
3
|
import type { Reactivity } from "effect/reactivity/Reactivity";
|
|
4
4
|
import type { FieldFailure, Fields, Name, Submitter } from "@shivaedev/effect-form/shape.ts";
|
|
5
5
|
|
|
6
|
-
export interface FieldRejection<
|
|
7
|
-
readonly field:
|
|
6
|
+
export interface FieldRejection<TName extends string> {
|
|
7
|
+
readonly field: TName;
|
|
8
8
|
readonly message: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export type AtomServices<
|
|
11
|
+
export type AtomServices<TRequirements> = TRequirements | Scope.Scope | AtomRegistry | Reactivity;
|
|
12
12
|
|
|
13
|
-
export type RejectField<
|
|
13
|
+
export type RejectField<TFields extends Fields, TError> = (error: TError) => FieldRejection<Name<TFields>> | undefined;
|
|
14
14
|
|
|
15
|
-
type Unmatched<
|
|
16
|
-
? "field" extends keyof
|
|
17
|
-
? Exclude<
|
|
15
|
+
type Unmatched<TFields extends Fields, TError> = TError extends { readonly _tag: string; readonly message: string }
|
|
16
|
+
? "field" extends keyof TError
|
|
17
|
+
? Exclude<TError["field"], Name<TFields> | undefined>
|
|
18
18
|
: never
|
|
19
19
|
: never;
|
|
20
20
|
|
|
21
|
-
export type FieldRejectionMapping<
|
|
21
|
+
export type FieldRejectionMapping<TFields extends Fields, TError> = { readonly rejectField?: RejectField<TFields, TError> } & ([
|
|
22
|
+
Unmatched<TFields, TError>,
|
|
23
|
+
] extends [never]
|
|
22
24
|
? unknown
|
|
23
|
-
: { readonly rejectField: RejectField<
|
|
25
|
+
: { readonly rejectField: RejectField<TFields, TError> });
|
|
24
26
|
|
|
25
|
-
export
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
function isName(name: unknown): name is Name<F> {
|
|
27
|
+
export function fieldRejectionOf<TFields extends Fields>(schema: Schema.Struct<TFields>) {
|
|
28
|
+
return (error: unknown): FieldRejection<Name<TFields>> | undefined => {
|
|
29
|
+
function isName(name: unknown): name is Name<TFields> {
|
|
29
30
|
return typeof name === "string" && Object.hasOwn(schema.fields, name);
|
|
30
31
|
}
|
|
31
32
|
if (!(Predicate.hasProperty(error, "_tag") && Predicate.hasProperty(error, "field") && Predicate.hasProperty(error, "message"))) {
|
|
@@ -34,16 +35,17 @@ export const fieldRejectionOf =
|
|
|
34
35
|
const { _tag, field, message } = error;
|
|
35
36
|
return typeof _tag === "string" && isName(field) && typeof message === "string" ? { field, message } : undefined;
|
|
36
37
|
};
|
|
38
|
+
}
|
|
37
39
|
|
|
38
|
-
export
|
|
39
|
-
schema: Schema.Struct<
|
|
40
|
-
save: (values:
|
|
41
|
-
reject: RejectField<
|
|
42
|
-
)
|
|
40
|
+
export function rejecting<TFields extends Fields, TValues, TResult, TError, TRequirements>(
|
|
41
|
+
schema: Schema.Struct<TFields>,
|
|
42
|
+
save: (values: TValues) => Effect.Effect<TResult, TError, TRequirements>,
|
|
43
|
+
reject: RejectField<TFields, TError> | undefined,
|
|
44
|
+
) {
|
|
43
45
|
const rejection = reject ?? fieldRejectionOf(schema);
|
|
44
|
-
return (values:
|
|
45
|
-
Effect.catch(save(values), (error): Effect.Effect<never,
|
|
46
|
+
return (values: TValues, submitter: Submitter<Name<TFields>>): Effect.Effect<TResult, TError | FieldFailure, TRequirements> =>
|
|
47
|
+
Effect.catch(save(values), (error): Effect.Effect<never, TError | FieldFailure> => {
|
|
46
48
|
const found = rejection(error);
|
|
47
49
|
return found === undefined ? Effect.fail(error) : submitter.fail(found.field, found.message);
|
|
48
50
|
});
|
|
49
|
-
}
|
|
51
|
+
}
|
package/src/submission.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Effect, Schema } from "effect";
|
|
2
2
|
import type * as Atom from "effect/reactivity/Atom";
|
|
3
|
-
import {
|
|
3
|
+
import { form } from "@shivaedev/effect-form/form.ts";
|
|
4
4
|
import type { PersistedDraftConfig } from "@shivaedev/effect-form/persistence.ts";
|
|
5
5
|
import type { Decoded, Encoded, FieldFailure, Fields, Form, Services } from "@shivaedev/effect-form/shape.ts";
|
|
6
6
|
import { actionTrace } from "#actionTrace.ts";
|
|
@@ -26,7 +26,7 @@ export function submission<TFields extends Fields, A, E, R, TRuntimeError>(
|
|
|
26
26
|
const { fields, initialValues, runtime } = config;
|
|
27
27
|
const save = rejecting(fields, config.save, config.rejectField);
|
|
28
28
|
let submitted: Encoded<TFields> | undefined;
|
|
29
|
-
const
|
|
29
|
+
const currentForm: Form<TFields, A, E | FieldFailure, TRuntimeError> = form(fields, {
|
|
30
30
|
initialValues,
|
|
31
31
|
onSubmit: (values, submitter, snapshot) => {
|
|
32
32
|
submitted = snapshot;
|
|
@@ -35,5 +35,5 @@ export function submission<TFields extends Fields, A, E, R, TRuntimeError>(
|
|
|
35
35
|
persistedDraft: config.persistedDraft,
|
|
36
36
|
runtime,
|
|
37
37
|
});
|
|
38
|
-
return { form, submitted: () => submitted };
|
|
38
|
+
return { form: currentForm, submitted: () => submitted };
|
|
39
39
|
}
|