@logixjs/form 0.0.2 → 1.0.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/dist/Form.cjs +110 -140
- package/dist/Form.cjs.map +1 -1
- package/dist/Form.d.cts +20 -17
- package/dist/Form.d.ts +20 -17
- package/dist/Form.js +2 -2
- package/dist/Rule.cjs +0 -1
- package/dist/Rule.cjs.map +1 -1
- package/dist/Rule.js +1 -1
- package/dist/{chunk-YVHXLY63.js → chunk-3U6VHYYQ.js} +2 -3
- package/dist/chunk-3U6VHYYQ.js.map +1 -0
- package/dist/{chunk-YHDEJ47V.js → chunk-WGBRLVRO.js} +80 -109
- package/dist/chunk-WGBRLVRO.js.map +1 -0
- package/dist/{impl-Ccdm5eDF.d.cts → impl-DWIHAuQq.d.cts} +29 -29
- package/dist/{impl-BfSlyM58.d.ts → impl-DXbfEc3o.d.ts} +29 -29
- package/dist/index.cjs +110 -140
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/react/index.d.cts +1 -1
- package/dist/react/index.d.ts +1 -1
- package/package.json +12 -7
- package/dist/chunk-YHDEJ47V.js.map +0 -1
- package/dist/chunk-YVHXLY63.js.map +0 -1
package/dist/Form.d.cts
CHANGED
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { f as FormAction, j as FormController, F as FormErrors, i as FormExtendDef, k as FormHandleExt, h as FormMakeConfig, d as FormMeta, l as FormModule, g as FormShape, e as FormState, c as FormUiState, n as RuleDescriptor, o as RuleScope,
|
|
1
|
+
import { R as RulesDsl } from './impl-DWIHAuQq.cjs';
|
|
2
|
+
export { f as FormAction, j as FormController, F as FormErrors, i as FormExtendDef, k as FormHandleExt, h as FormMakeConfig, d as FormMeta, l as FormModule, g as FormShape, e as FormState, c as FormUiState, n as RuleDescriptor, o as RuleScope, p as RulesManifest, a as RulesNode, b as RulesSpec, m as make, r as rules } from './impl-DWIHAuQq.cjs';
|
|
3
3
|
import { Schema } from 'effect';
|
|
4
|
-
import { D as DerivedSpec } from './Trait-Bu794ROY.cjs';
|
|
5
4
|
import * as Logix from '@logixjs/core';
|
|
5
|
+
import { D as DerivedSpec } from './Trait-Bu794ROY.cjs';
|
|
6
6
|
import { j as RuleEntry } from './Rule-BOAiSVz9.cjs';
|
|
7
7
|
export { d as CanonicalListItem, c as CanonicalListPath, C as CanonicalPath, b as CanonicalValue, F as FieldPath, a as FieldValue } from './Rule-BOAiSVz9.cjs';
|
|
8
8
|
|
|
9
|
-
/**
|
|
10
|
-
* Form.derived:
|
|
11
|
-
* - Provides "type narrowing based on the values schema" for derived specs, so you can compose derived fragments
|
|
12
|
-
* without losing type information.
|
|
13
|
-
* - Does no extra runtime normalization; final validation is still governed by Form.make guardrails.
|
|
14
|
-
*/
|
|
15
|
-
declare const derived: <TValues extends object, I>(_valuesSchema: Schema.Schema<TValues, I>) => (spec: DerivedSpec<TValues>) => DerivedSpec<TValues>;
|
|
16
|
-
|
|
17
9
|
type NonNull<T> = Exclude<T, null | undefined>;
|
|
18
10
|
type ListItem<T> = NonNull<T> extends readonly (infer Item)[] ? Item : never;
|
|
19
11
|
type NodeSpec$1<Input = unknown, Ctx = unknown> = Omit<Logix.StateTrait.StateTraitNode<Input, Ctx>, '_tag' | 'check'> & {
|
|
@@ -38,17 +30,28 @@ type TraitsSpec<TValues extends object> = {
|
|
|
38
30
|
* - Form defaults `check.deps=[]`; only declare deps when you need "cross-field linked validation triggers".
|
|
39
31
|
* - Returns a StateTraitSpec fragment that can be spread directly (assembled by Form.make).
|
|
40
32
|
*/
|
|
41
|
-
declare const traits: <TValues extends object
|
|
33
|
+
declare const traits: <TValues extends object>(_valuesSchema: Schema.Schema<TValues>) => {
|
|
42
34
|
(spec: TraitsSpec<TValues>): Logix.StateTrait.StateTraitSpec<TValues>;
|
|
43
35
|
(spec: Logix.StateTrait.StateTraitSpec<TValues>): Logix.StateTrait.StateTraitSpec<TValues>;
|
|
44
36
|
};
|
|
45
37
|
|
|
46
38
|
type FormFrom<TValues extends object> = Readonly<{
|
|
47
|
-
readonly derived:
|
|
48
|
-
readonly rules:
|
|
49
|
-
readonly traits:
|
|
39
|
+
readonly derived: (spec: DerivedSpec<TValues>) => DerivedSpec<TValues>;
|
|
40
|
+
readonly rules: RulesDsl<TValues>;
|
|
41
|
+
readonly traits: {
|
|
42
|
+
(spec: TraitsSpec<TValues>): Logix.StateTrait.StateTraitSpec<TValues>;
|
|
43
|
+
(spec: Logix.StateTrait.StateTraitSpec<TValues>): Logix.StateTrait.StateTraitSpec<TValues>;
|
|
44
|
+
};
|
|
50
45
|
}>;
|
|
51
|
-
declare const fromValues: <TValues extends object
|
|
46
|
+
declare const fromValues: <TValues extends object>(valuesSchema: Schema.Schema<TValues>) => FormFrom<TValues>;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Form.derived:
|
|
50
|
+
* - Provides "type narrowing based on the values schema" for derived specs, so you can compose derived fragments
|
|
51
|
+
* without losing type information.
|
|
52
|
+
* - Does no extra runtime normalization; final validation is still governed by Form.make guardrails.
|
|
53
|
+
*/
|
|
54
|
+
declare const derived: <TValues extends object>(_valuesSchema: Schema.Schema<TValues>) => (spec: DerivedSpec<TValues>) => DerivedSpec<TValues>;
|
|
52
55
|
|
|
53
56
|
type NodeSpec<Input = unknown, Ctx = unknown> = Omit<Logix.StateTrait.StateTraitNode<Input, Ctx>, '_tag' | 'check'> & {
|
|
54
57
|
readonly check?: Readonly<Record<string, RuleEntry<Input, Ctx>>>;
|
|
@@ -61,4 +64,4 @@ type ListSpec<Item = unknown> = Omit<Logix.StateTrait.StateTraitList<Item>, '_ta
|
|
|
61
64
|
};
|
|
62
65
|
declare const list: <Item = unknown>(spec: ListSpec<Item>) => Logix.StateTrait.StateTraitList<Item>;
|
|
63
66
|
|
|
64
|
-
export { type FormFrom, type ListSpec$1 as ListSpec, type NodeSpec$1 as NodeSpec, type TraitsSpec, derived, fromValues, list, node,
|
|
67
|
+
export { type FormFrom, type ListSpec$1 as ListSpec, type NodeSpec$1 as NodeSpec, RulesDsl, type TraitsSpec, derived, fromValues, list, node, traits };
|
package/dist/Form.d.ts
CHANGED
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { f as FormAction, j as FormController, F as FormErrors, i as FormExtendDef, k as FormHandleExt, h as FormMakeConfig, d as FormMeta, l as FormModule, g as FormShape, e as FormState, c as FormUiState, n as RuleDescriptor, o as RuleScope,
|
|
1
|
+
import { R as RulesDsl } from './impl-DXbfEc3o.js';
|
|
2
|
+
export { f as FormAction, j as FormController, F as FormErrors, i as FormExtendDef, k as FormHandleExt, h as FormMakeConfig, d as FormMeta, l as FormModule, g as FormShape, e as FormState, c as FormUiState, n as RuleDescriptor, o as RuleScope, p as RulesManifest, a as RulesNode, b as RulesSpec, m as make, r as rules } from './impl-DXbfEc3o.js';
|
|
3
3
|
import { Schema } from 'effect';
|
|
4
|
-
import { D as DerivedSpec } from './Trait-Bu794ROY.js';
|
|
5
4
|
import * as Logix from '@logixjs/core';
|
|
5
|
+
import { D as DerivedSpec } from './Trait-Bu794ROY.js';
|
|
6
6
|
import { j as RuleEntry } from './Rule-BOAiSVz9.js';
|
|
7
7
|
export { d as CanonicalListItem, c as CanonicalListPath, C as CanonicalPath, b as CanonicalValue, F as FieldPath, a as FieldValue } from './Rule-BOAiSVz9.js';
|
|
8
8
|
|
|
9
|
-
/**
|
|
10
|
-
* Form.derived:
|
|
11
|
-
* - Provides "type narrowing based on the values schema" for derived specs, so you can compose derived fragments
|
|
12
|
-
* without losing type information.
|
|
13
|
-
* - Does no extra runtime normalization; final validation is still governed by Form.make guardrails.
|
|
14
|
-
*/
|
|
15
|
-
declare const derived: <TValues extends object, I>(_valuesSchema: Schema.Schema<TValues, I>) => (spec: DerivedSpec<TValues>) => DerivedSpec<TValues>;
|
|
16
|
-
|
|
17
9
|
type NonNull<T> = Exclude<T, null | undefined>;
|
|
18
10
|
type ListItem<T> = NonNull<T> extends readonly (infer Item)[] ? Item : never;
|
|
19
11
|
type NodeSpec$1<Input = unknown, Ctx = unknown> = Omit<Logix.StateTrait.StateTraitNode<Input, Ctx>, '_tag' | 'check'> & {
|
|
@@ -38,17 +30,28 @@ type TraitsSpec<TValues extends object> = {
|
|
|
38
30
|
* - Form defaults `check.deps=[]`; only declare deps when you need "cross-field linked validation triggers".
|
|
39
31
|
* - Returns a StateTraitSpec fragment that can be spread directly (assembled by Form.make).
|
|
40
32
|
*/
|
|
41
|
-
declare const traits: <TValues extends object
|
|
33
|
+
declare const traits: <TValues extends object>(_valuesSchema: Schema.Schema<TValues>) => {
|
|
42
34
|
(spec: TraitsSpec<TValues>): Logix.StateTrait.StateTraitSpec<TValues>;
|
|
43
35
|
(spec: Logix.StateTrait.StateTraitSpec<TValues>): Logix.StateTrait.StateTraitSpec<TValues>;
|
|
44
36
|
};
|
|
45
37
|
|
|
46
38
|
type FormFrom<TValues extends object> = Readonly<{
|
|
47
|
-
readonly derived:
|
|
48
|
-
readonly rules:
|
|
49
|
-
readonly traits:
|
|
39
|
+
readonly derived: (spec: DerivedSpec<TValues>) => DerivedSpec<TValues>;
|
|
40
|
+
readonly rules: RulesDsl<TValues>;
|
|
41
|
+
readonly traits: {
|
|
42
|
+
(spec: TraitsSpec<TValues>): Logix.StateTrait.StateTraitSpec<TValues>;
|
|
43
|
+
(spec: Logix.StateTrait.StateTraitSpec<TValues>): Logix.StateTrait.StateTraitSpec<TValues>;
|
|
44
|
+
};
|
|
50
45
|
}>;
|
|
51
|
-
declare const fromValues: <TValues extends object
|
|
46
|
+
declare const fromValues: <TValues extends object>(valuesSchema: Schema.Schema<TValues>) => FormFrom<TValues>;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Form.derived:
|
|
50
|
+
* - Provides "type narrowing based on the values schema" for derived specs, so you can compose derived fragments
|
|
51
|
+
* without losing type information.
|
|
52
|
+
* - Does no extra runtime normalization; final validation is still governed by Form.make guardrails.
|
|
53
|
+
*/
|
|
54
|
+
declare const derived: <TValues extends object>(_valuesSchema: Schema.Schema<TValues>) => (spec: DerivedSpec<TValues>) => DerivedSpec<TValues>;
|
|
52
55
|
|
|
53
56
|
type NodeSpec<Input = unknown, Ctx = unknown> = Omit<Logix.StateTrait.StateTraitNode<Input, Ctx>, '_tag' | 'check'> & {
|
|
54
57
|
readonly check?: Readonly<Record<string, RuleEntry<Input, Ctx>>>;
|
|
@@ -61,4 +64,4 @@ type ListSpec<Item = unknown> = Omit<Logix.StateTrait.StateTraitList<Item>, '_ta
|
|
|
61
64
|
};
|
|
62
65
|
declare const list: <Item = unknown>(spec: ListSpec<Item>) => Logix.StateTrait.StateTraitList<Item>;
|
|
63
66
|
|
|
64
|
-
export { type FormFrom, type ListSpec$1 as ListSpec, type NodeSpec$1 as NodeSpec, type TraitsSpec, derived, fromValues, list, node,
|
|
67
|
+
export { type FormFrom, type ListSpec$1 as ListSpec, type NodeSpec$1 as NodeSpec, RulesDsl, type TraitsSpec, derived, fromValues, list, node, traits };
|
package/dist/Form.js
CHANGED
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
node,
|
|
7
7
|
rules,
|
|
8
8
|
traits
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-WGBRLVRO.js";
|
|
10
|
+
import "./chunk-3U6VHYYQ.js";
|
|
11
11
|
import "./chunk-JZ5FZKPJ.js";
|
|
12
12
|
import "./chunk-5DRI5UGD.js";
|
|
13
13
|
import "./chunk-OJVEZKU7.js";
|
package/dist/Rule.cjs
CHANGED
|
@@ -38,7 +38,6 @@ __export(Rule_exports, {
|
|
|
38
38
|
module.exports = __toCommonJS(Rule_exports);
|
|
39
39
|
|
|
40
40
|
// src/internal/validators/index.ts
|
|
41
|
-
var import_effect = require("effect");
|
|
42
41
|
var ERROR_VALUE_MAX_BYTES = 256;
|
|
43
42
|
var textEncoder = new TextEncoder();
|
|
44
43
|
var jsonByteSize = (value) => {
|
package/dist/Rule.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/Rule.ts","../src/internal/validators/index.ts"],"sourcesContent":["import type * as Logix from '@logixjs/core'\nimport * as Validators from './internal/validators/index.js'\nimport type { CanonicalPath } from './internal/form/types.js'\n\nexport type AutoValidateOn = 'onChange' | 'onBlur'\n\nexport type RuleValidateOn = ReadonlyArray<AutoValidateOn>\n\nexport type RuleFn<Input, Ctx = unknown> = (input: Input, ctx: Ctx) => unknown | undefined\n\ntype RuleDeps<Input> = Input extends object\n ? CanonicalPath<Input> extends never\n ? string\n : CanonicalPath<Input>\n : string\n\nexport type Rule<Input, Ctx = unknown> = Logix.StateTrait.CheckRule<Input, Ctx> & {\n /**\n * validateOn:\n * - Only affects the auto-validation phase (onChange/onBlur); submit/manual always runs.\n * - If an empty array, auto-validation is disabled (only submit/manual runs).\n */\n readonly validateOn?: RuleValidateOn\n}\n\nexport type RuleSet<Input, Ctx = unknown> = Readonly<Record<string, Rule<Input, Ctx>>>\n\nexport type RuleEntry<Input, Ctx = unknown> =\n | RuleFn<Input, Ctx>\n | (Omit<Rule<Input, Ctx>, 'deps'> & {\n readonly deps?: ReadonlyArray<RuleDeps<Input>>\n })\n\nexport type RuleGroup<Input, Ctx = unknown> = Readonly<{\n readonly deps?: ReadonlyArray<RuleDeps<Input>>\n readonly validateOn?: RuleValidateOn\n readonly validate: Readonly<Record<string, RuleEntry<Input, Ctx>>>\n}>\n\nexport type RuleConfig<Input, Ctx = unknown> = Readonly<{\n readonly deps?: ReadonlyArray<RuleDeps<Input>>\n readonly validateOn?: RuleValidateOn\n\n // RHF-like builtins (expanded at build time into equivalent pure functions)\n readonly required?: Validators.RequiredDecl\n readonly minLength?: Validators.MinLengthDecl\n readonly maxLength?: Validators.MaxLengthDecl\n readonly min?: Validators.MinDecl\n readonly max?: Validators.MaxDecl\n readonly pattern?: Validators.PatternDecl\n\n // RHF-like validate: a function or a named map of functions (RuleEntry form is also allowed to override deps/validateOn)\n readonly validate?: RuleFn<Input, Ctx> | Readonly<Record<string, RuleEntry<Input, Ctx>>>\n}>\n\nexport type RuleInput<Input, Ctx = unknown> = RuleFn<Input, Ctx> | RuleGroup<Input, Ctx> | RuleConfig<Input, Ctx>\n\nconst uniq = <T>(items: ReadonlyArray<T>): ReadonlyArray<T> => Array.from(new Set(items))\n\nconst normalizeValidateOn = (input: unknown): RuleValidateOn | undefined => {\n if (!Array.isArray(input)) return undefined\n const out: Array<AutoValidateOn> = []\n for (const x of input) {\n if (x === 'onChange' || x === 'onBlur') out.push(x)\n }\n return uniq(out)\n}\n\nconst normalizeDeps = (input: unknown): ReadonlyArray<string> | undefined => {\n if (!Array.isArray(input)) return undefined\n const out: Array<string> = []\n for (const x of input) {\n if (typeof x !== 'string') continue\n const v = x.trim()\n if (!v) continue\n out.push(v)\n }\n return uniq(out)\n}\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n Boolean(value) && typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/**\n * make:\n * - The result must be directly attachable to `StateTrait.node({ check })`.\n * - Does not introduce an extra wrapper (e.g. `{ rules: ... }`).\n */\nexport const make = <Input, Ctx = unknown>(input: RuleInput<Input, Ctx>): RuleSet<Input, Ctx> => {\n if (typeof input === 'function') {\n return {\n default: {\n deps: [],\n validate: input,\n },\n }\n }\n\n if (!isPlainObject(input)) {\n return {}\n }\n\n const baseDeps = normalizeDeps((input as any).deps) ?? []\n const baseValidateOn = normalizeValidateOn((input as any).validateOn)\n\n const byName = new Map<string, Rule<Input, Ctx>>()\n\n const addRule = (name: string, raw: unknown): void => {\n const ruleName = typeof name === 'string' ? name.trim() : ''\n if (!ruleName) return\n if (byName.has(ruleName)) {\n throw new Error(`[Form.Rule.make] Duplicate rule name \"${ruleName}\"`)\n }\n\n if (typeof raw === 'function') {\n byName.set(ruleName, {\n deps: baseDeps,\n validate: raw as any,\n ...(baseValidateOn !== undefined ? { validateOn: baseValidateOn } : {}),\n })\n return\n }\n\n if (!raw || typeof raw !== 'object') return\n const entry = raw as any\n const deps = normalizeDeps(entry.deps) ?? baseDeps\n const validateOn = normalizeValidateOn(entry.validateOn) ?? baseValidateOn\n const validate = entry.validate\n if (typeof validate !== 'function') return\n\n byName.set(ruleName, {\n ...entry,\n deps,\n validate,\n ...(validateOn !== undefined ? { validateOn } : {}),\n })\n }\n\n // RHF-like builtins (if declared, it will be expanded into an equivalent pure function)\n const requiredDecl = (input as any).required as Validators.RequiredDecl | undefined\n if (requiredDecl !== undefined && requiredDecl !== false) {\n const validate = Validators.required(requiredDecl)\n addRule('required', (value: Input) => validate(value))\n }\n\n const minLengthDecl = (input as any).minLength as Validators.MinLengthDecl | undefined\n if (minLengthDecl !== undefined) {\n const validate = Validators.minLength(minLengthDecl)\n addRule('minLength', (value: Input) => validate(value))\n }\n\n const maxLengthDecl = (input as any).maxLength as Validators.MaxLengthDecl | undefined\n if (maxLengthDecl !== undefined) {\n const validate = Validators.maxLength(maxLengthDecl)\n addRule('maxLength', (value: Input) => validate(value))\n }\n\n const minDecl = (input as any).min as Validators.MinDecl | undefined\n if (minDecl !== undefined) {\n const validate = Validators.min(minDecl)\n addRule('min', (value: Input) => validate(value))\n }\n\n const maxDecl = (input as any).max as Validators.MaxDecl | undefined\n if (maxDecl !== undefined) {\n const validate = Validators.max(maxDecl)\n addRule('max', (value: Input) => validate(value))\n }\n\n const patternDecl = (input as any).pattern as Validators.PatternDecl | undefined\n if (patternDecl !== undefined) {\n const validate = Validators.pattern(patternDecl)\n addRule('pattern', (value: Input) => validate(value))\n }\n\n // validate: supports both legacy RuleGroup `{ validate: Record<string, RuleEntry> }`\n // and RHF-style `validate: fn | Record<string, fn>`.\n const validateBlock = (input as any).validate as unknown\n if (typeof validateBlock === 'function') {\n addRule('validate', validateBlock)\n } else if (isPlainObject(validateBlock)) {\n const names = Object.keys(validateBlock).sort((a, b) => a.localeCompare(b))\n for (const name of names) {\n addRule(name, (validateBlock as any)[name])\n }\n }\n\n const out: Record<string, Rule<Input, Ctx>> = {}\n const names = Array.from(byName.keys()).sort((a, b) => a.localeCompare(b))\n for (const name of names) {\n out[name] = byName.get(name)!\n }\n return out\n}\n\nexport const merge = <Input, Ctx = unknown>(...rules: ReadonlyArray<RuleSet<Input, Ctx>>): RuleSet<Input, Ctx> => {\n const byName = new Map<string, Rule<Input, Ctx>>()\n const duplicates = new Set<string>()\n\n for (const ruleSet of rules) {\n for (const name of Object.keys(ruleSet)) {\n if (byName.has(name)) duplicates.add(name)\n else byName.set(name, ruleSet[name]!)\n }\n }\n\n if (duplicates.size > 0) {\n const list = Array.from(duplicates)\n .sort((a, b) => a.localeCompare(b))\n .join(', ')\n throw new Error(`[Form.Rule.merge] Duplicate rule name(s): ${list}`)\n }\n\n const merged: Record<string, Rule<Input, Ctx>> = {}\n const names = Array.from(byName.keys()).sort((a, b) => a.localeCompare(b))\n for (const name of names) {\n merged[name] = byName.get(name)!\n }\n\n return merged\n}\n\nexport type ErrorTarget = '$value' | '$self'\n\nexport type ListIdentityPolicy =\n | Readonly<{ readonly mode: 'trackBy'; readonly trackBy: string }>\n | Readonly<{ readonly mode: 'store' }>\n | Readonly<{ readonly mode: 'index' }>\n\nexport type FieldDecl<Input, Ctx = unknown> = Readonly<{\n readonly kind: 'field'\n readonly valuePath: string\n readonly rule: RuleInput<Input, Ctx>\n readonly errorTarget?: ErrorTarget\n}>\n\nexport type RootDecl<Input, Ctx = unknown> = Readonly<{\n readonly kind: 'root'\n readonly rule: RuleInput<Input, Ctx>\n}>\n\nexport type ListDecl<Item, Ctx = unknown> = Readonly<{\n readonly kind: 'list'\n readonly listPath: string\n readonly identity: ListIdentityPolicy\n readonly item?: RuleInput<Item, Ctx>\n readonly list?: RuleInput<ReadonlyArray<Item>, Ctx>\n}>\n\nexport type RulesDecl<TValues extends object = any> = FieldDecl<any> | RootDecl<TValues> | ListDecl<any>\n\nexport const field = <Input, Ctx = unknown>(\n valuePath: string,\n rule: RuleInput<Input, Ctx>,\n options?: { readonly errorTarget?: ErrorTarget },\n): FieldDecl<Input, Ctx> => ({\n kind: 'field',\n valuePath,\n rule,\n ...(options?.errorTarget !== undefined ? { errorTarget: options.errorTarget } : {}),\n})\n\nexport const root = <Input, Ctx = unknown>(rule: RuleInput<Input, Ctx>): RootDecl<Input, Ctx> => ({\n kind: 'root',\n rule,\n})\n\nexport const list = <Item, Ctx = unknown>(\n listPath: string,\n spec: {\n readonly identity: ListIdentityPolicy\n readonly item?: RuleInput<Item, Ctx>\n readonly list?: RuleInput<ReadonlyArray<Item>, Ctx>\n },\n): ListDecl<Item, Ctx> => ({\n kind: 'list',\n listPath,\n identity: spec.identity,\n ...(spec.item !== undefined ? { item: spec.item } : {}),\n ...(spec.list !== undefined ? { list: spec.list } : {}),\n})\n\nexport const fields = <Input, Ctx = unknown>(\n ...decls: ReadonlyArray<FieldDecl<Input, Ctx> | ReadonlyArray<FieldDecl<Input, Ctx>>>\n): Readonly<Record<string, RuleInput<Input, Ctx>>> => {\n const out: Record<string, RuleInput<Input, Ctx>> = {}\n const list: Array<FieldDecl<Input, Ctx>> = []\n\n const isDeclArray = (value: unknown): value is ReadonlyArray<FieldDecl<Input, Ctx>> => Array.isArray(value)\n\n for (const item of decls) {\n if (isDeclArray(item)) {\n list.push(...item)\n continue\n }\n list.push(item)\n }\n\n for (const decl of list) {\n const path = typeof decl?.valuePath === 'string' ? decl.valuePath.trim() : ''\n if (!path) continue\n if (path in out) {\n throw new Error(`[Form.Rule.fields] Duplicate valuePath \"${path}\"`)\n }\n out[path] = decl.rule\n }\n\n return out\n}\n\nexport {\n ERROR_VALUE_MAX_BYTES,\n assertErrorValueBudget,\n required,\n minLength,\n maxLength,\n min,\n max,\n pattern,\n} from './internal/validators/index.js'\n","import { ParseResult } from 'effect'\n\nexport const ERROR_VALUE_MAX_BYTES = 256\n\nconst textEncoder = new TextEncoder()\n\nconst jsonByteSize = (value: unknown): number => {\n const json = JSON.stringify(value)\n return textEncoder.encode(json).length\n}\n\nconst truncateToJsonByteBudget = (value: string, maxBytes: number): string => {\n if (jsonByteSize(value) <= maxBytes) return value\n\n let lo = 0\n let hi = value.length\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2)\n const slice = value.slice(0, mid)\n if (jsonByteSize(slice) <= maxBytes) lo = mid\n else hi = mid - 1\n }\n return value.slice(0, lo)\n}\n\nexport const assertErrorValueBudget = (value: unknown, label: string): unknown => {\n const bytes = jsonByteSize(value)\n if (bytes <= ERROR_VALUE_MAX_BYTES) return value\n throw new Error(`[Form.validators] ErrorValue for \"${label}\" must be JSON ≤${ERROR_VALUE_MAX_BYTES}B (got ${bytes}B)`)\n}\n\nconst errorValue = (label: string, value: unknown): unknown => assertErrorValueBudget(value, label)\n\nexport type RequiredDecl =\n | boolean\n | string\n | Readonly<{\n readonly message?: string\n readonly trim?: boolean\n }>\n\nexport const required = (decl: RequiredDecl): ((value: unknown) => unknown | undefined) => {\n const trim = typeof decl === 'object' && decl !== null ? Boolean((decl as any).trim) : true\n const message =\n typeof decl === 'string'\n ? decl\n : typeof decl === 'object' && decl !== null && typeof (decl as any).message === 'string'\n ? (decl as any).message\n : 'required'\n\n const err = errorValue('required', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return err\n if (typeof value === 'string') {\n const v = trim ? value.trim() : value\n return v.length > 0 ? undefined : err\n }\n if (Array.isArray(value)) return value.length > 0 ? undefined : err\n if (typeof value === 'boolean') return value ? undefined : err\n return undefined\n }\n}\n\nexport type MinLengthDecl =\n | number\n | Readonly<{\n readonly min: number\n readonly message?: string\n }>\n\nexport const minLength = (decl: MinLengthDecl): ((value: unknown) => unknown | undefined) => {\n const min = typeof decl === 'number' ? decl : decl.min\n const message =\n typeof decl === 'object' && decl !== null && typeof decl.message === 'string' ? decl.message : 'minLength'\n const err = errorValue('minLength', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value === 'string') return value.length >= min ? undefined : err\n if (Array.isArray(value)) return value.length >= min ? undefined : err\n return undefined\n }\n}\n\nexport type MaxLengthDecl =\n | number\n | Readonly<{\n readonly max: number\n readonly message?: string\n }>\n\nexport const maxLength = (decl: MaxLengthDecl): ((value: unknown) => unknown | undefined) => {\n const max = typeof decl === 'number' ? decl : decl.max\n const message =\n typeof decl === 'object' && decl !== null && typeof decl.message === 'string' ? decl.message : 'maxLength'\n const err = errorValue('maxLength', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value === 'string') return value.length <= max ? undefined : err\n if (Array.isArray(value)) return value.length <= max ? undefined : err\n return undefined\n }\n}\n\nexport type MinDecl =\n | number\n | Readonly<{\n readonly min: number\n readonly message?: string\n }>\n\nexport const min = (decl: MinDecl): ((value: unknown) => unknown | undefined) => {\n const minValue = typeof decl === 'number' ? decl : decl.min\n const message = typeof decl === 'object' && decl !== null && typeof decl.message === 'string' ? decl.message : 'min'\n const err = errorValue('min', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value === 'number' && Number.isFinite(value)) return value >= minValue ? undefined : err\n return undefined\n }\n}\n\nexport type MaxDecl =\n | number\n | Readonly<{\n readonly max: number\n readonly message?: string\n }>\n\nexport const max = (decl: MaxDecl): ((value: unknown) => unknown | undefined) => {\n const maxValue = typeof decl === 'number' ? decl : decl.max\n const message = typeof decl === 'object' && decl !== null && typeof decl.message === 'string' ? decl.message : 'max'\n const err = errorValue('max', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value === 'number' && Number.isFinite(value)) return value <= maxValue ? undefined : err\n return undefined\n }\n}\n\nexport type PatternDecl =\n | RegExp\n | Readonly<{\n readonly re: RegExp\n readonly message?: string\n }>\n\nexport const pattern = (decl: PatternDecl): ((value: unknown) => unknown | undefined) => {\n const re = decl instanceof RegExp ? decl : decl.re\n const message =\n typeof decl === 'object' && decl !== null && typeof (decl as any).message === 'string'\n ? (decl as any).message\n : 'pattern'\n const err = errorValue('pattern', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value !== 'string') return undefined\n return re.test(value) ? undefined : err\n }\n}\n\nexport const schemaErrorMessage = (schemaError: unknown): string => {\n let message: string\n try {\n message = ParseResult.TreeFormatter.formatErrorSync(schemaError as any)\n } catch {\n message = 'schema invalid'\n }\n\n const truncated = truncateToJsonByteBudget(message, ERROR_VALUE_MAX_BYTES)\n return truncated.length > 0 ? truncated : 'schema invalid'\n}\n"],"mappings":"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","names":["min","max","names","list"]}
|
|
1
|
+
{"version":3,"sources":["../src/Rule.ts","../src/internal/validators/index.ts"],"sourcesContent":["import type * as Logix from '@logixjs/core'\nimport * as Validators from './internal/validators/index.js'\nimport type { CanonicalPath } from './internal/form/types.js'\n\nexport type AutoValidateOn = 'onChange' | 'onBlur'\n\nexport type RuleValidateOn = ReadonlyArray<AutoValidateOn>\n\nexport type RuleFn<Input, Ctx = unknown> = (input: Input, ctx: Ctx) => unknown | undefined\n\ntype RuleDeps<Input> = Input extends object\n ? CanonicalPath<Input> extends never\n ? string\n : CanonicalPath<Input>\n : string\n\nexport type Rule<Input, Ctx = unknown> = Logix.StateTrait.CheckRule<Input, Ctx> & {\n /**\n * validateOn:\n * - Only affects the auto-validation phase (onChange/onBlur); submit/manual always runs.\n * - If an empty array, auto-validation is disabled (only submit/manual runs).\n */\n readonly validateOn?: RuleValidateOn\n}\n\nexport type RuleSet<Input, Ctx = unknown> = Readonly<Record<string, Rule<Input, Ctx>>>\n\nexport type RuleEntry<Input, Ctx = unknown> =\n | RuleFn<Input, Ctx>\n | (Omit<Rule<Input, Ctx>, 'deps'> & {\n readonly deps?: ReadonlyArray<RuleDeps<Input>>\n })\n\nexport type RuleGroup<Input, Ctx = unknown> = Readonly<{\n readonly deps?: ReadonlyArray<RuleDeps<Input>>\n readonly validateOn?: RuleValidateOn\n readonly validate: Readonly<Record<string, RuleEntry<Input, Ctx>>>\n}>\n\nexport type RuleConfig<Input, Ctx = unknown> = Readonly<{\n readonly deps?: ReadonlyArray<RuleDeps<Input>>\n readonly validateOn?: RuleValidateOn\n\n // RHF-like builtins (expanded at build time into equivalent pure functions)\n readonly required?: Validators.RequiredDecl\n readonly minLength?: Validators.MinLengthDecl\n readonly maxLength?: Validators.MaxLengthDecl\n readonly min?: Validators.MinDecl\n readonly max?: Validators.MaxDecl\n readonly pattern?: Validators.PatternDecl\n\n // RHF-like validate: a function or a named map of functions (RuleEntry form is also allowed to override deps/validateOn)\n readonly validate?: RuleFn<Input, Ctx> | Readonly<Record<string, RuleEntry<Input, Ctx>>>\n}>\n\nexport type RuleInput<Input, Ctx = unknown> = RuleFn<Input, Ctx> | RuleGroup<Input, Ctx> | RuleConfig<Input, Ctx>\n\nconst uniq = <T>(items: ReadonlyArray<T>): ReadonlyArray<T> => Array.from(new Set(items))\n\nconst normalizeValidateOn = (input: unknown): RuleValidateOn | undefined => {\n if (!Array.isArray(input)) return undefined\n const out: Array<AutoValidateOn> = []\n for (const x of input) {\n if (x === 'onChange' || x === 'onBlur') out.push(x)\n }\n return uniq(out)\n}\n\nconst normalizeDeps = (input: unknown): ReadonlyArray<string> | undefined => {\n if (!Array.isArray(input)) return undefined\n const out: Array<string> = []\n for (const x of input) {\n if (typeof x !== 'string') continue\n const v = x.trim()\n if (!v) continue\n out.push(v)\n }\n return uniq(out)\n}\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n Boolean(value) && typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/**\n * make:\n * - The result must be directly attachable to `StateTrait.node({ check })`.\n * - Does not introduce an extra wrapper (e.g. `{ rules: ... }`).\n */\nexport const make = <Input, Ctx = unknown>(input: RuleInput<Input, Ctx>): RuleSet<Input, Ctx> => {\n if (typeof input === 'function') {\n return {\n default: {\n deps: [],\n validate: input,\n },\n }\n }\n\n if (!isPlainObject(input)) {\n return {}\n }\n\n const baseDeps = normalizeDeps((input as any).deps) ?? []\n const baseValidateOn = normalizeValidateOn((input as any).validateOn)\n\n const byName = new Map<string, Rule<Input, Ctx>>()\n\n const addRule = (name: string, raw: unknown): void => {\n const ruleName = typeof name === 'string' ? name.trim() : ''\n if (!ruleName) return\n if (byName.has(ruleName)) {\n throw new Error(`[Form.Rule.make] Duplicate rule name \"${ruleName}\"`)\n }\n\n if (typeof raw === 'function') {\n byName.set(ruleName, {\n deps: baseDeps,\n validate: raw as any,\n ...(baseValidateOn !== undefined ? { validateOn: baseValidateOn } : {}),\n })\n return\n }\n\n if (!raw || typeof raw !== 'object') return\n const entry = raw as any\n const deps = normalizeDeps(entry.deps) ?? baseDeps\n const validateOn = normalizeValidateOn(entry.validateOn) ?? baseValidateOn\n const validate = entry.validate\n if (typeof validate !== 'function') return\n\n byName.set(ruleName, {\n ...entry,\n deps,\n validate,\n ...(validateOn !== undefined ? { validateOn } : {}),\n })\n }\n\n // RHF-like builtins (if declared, it will be expanded into an equivalent pure function)\n const requiredDecl = (input as any).required as Validators.RequiredDecl | undefined\n if (requiredDecl !== undefined && requiredDecl !== false) {\n const validate = Validators.required(requiredDecl)\n addRule('required', (value: Input) => validate(value))\n }\n\n const minLengthDecl = (input as any).minLength as Validators.MinLengthDecl | undefined\n if (minLengthDecl !== undefined) {\n const validate = Validators.minLength(minLengthDecl)\n addRule('minLength', (value: Input) => validate(value))\n }\n\n const maxLengthDecl = (input as any).maxLength as Validators.MaxLengthDecl | undefined\n if (maxLengthDecl !== undefined) {\n const validate = Validators.maxLength(maxLengthDecl)\n addRule('maxLength', (value: Input) => validate(value))\n }\n\n const minDecl = (input as any).min as Validators.MinDecl | undefined\n if (minDecl !== undefined) {\n const validate = Validators.min(minDecl)\n addRule('min', (value: Input) => validate(value))\n }\n\n const maxDecl = (input as any).max as Validators.MaxDecl | undefined\n if (maxDecl !== undefined) {\n const validate = Validators.max(maxDecl)\n addRule('max', (value: Input) => validate(value))\n }\n\n const patternDecl = (input as any).pattern as Validators.PatternDecl | undefined\n if (patternDecl !== undefined) {\n const validate = Validators.pattern(patternDecl)\n addRule('pattern', (value: Input) => validate(value))\n }\n\n // validate: supports both legacy RuleGroup `{ validate: Record<string, RuleEntry> }`\n // and RHF-style `validate: fn | Record<string, fn>`.\n const validateBlock = (input as any).validate as unknown\n if (typeof validateBlock === 'function') {\n addRule('validate', validateBlock)\n } else if (isPlainObject(validateBlock)) {\n const names = Object.keys(validateBlock).sort((a, b) => a.localeCompare(b))\n for (const name of names) {\n addRule(name, (validateBlock as any)[name])\n }\n }\n\n const out: Record<string, Rule<Input, Ctx>> = {}\n const names = Array.from(byName.keys()).sort((a, b) => a.localeCompare(b))\n for (const name of names) {\n out[name] = byName.get(name)!\n }\n return out\n}\n\nexport const merge = <Input, Ctx = unknown>(...rules: ReadonlyArray<RuleSet<Input, Ctx>>): RuleSet<Input, Ctx> => {\n const byName = new Map<string, Rule<Input, Ctx>>()\n const duplicates = new Set<string>()\n\n for (const ruleSet of rules) {\n for (const name of Object.keys(ruleSet)) {\n if (byName.has(name)) duplicates.add(name)\n else byName.set(name, ruleSet[name]!)\n }\n }\n\n if (duplicates.size > 0) {\n const list = Array.from(duplicates)\n .sort((a, b) => a.localeCompare(b))\n .join(', ')\n throw new Error(`[Form.Rule.merge] Duplicate rule name(s): ${list}`)\n }\n\n const merged: Record<string, Rule<Input, Ctx>> = {}\n const names = Array.from(byName.keys()).sort((a, b) => a.localeCompare(b))\n for (const name of names) {\n merged[name] = byName.get(name)!\n }\n\n return merged\n}\n\nexport type ErrorTarget = '$value' | '$self'\n\nexport type ListIdentityPolicy =\n | Readonly<{ readonly mode: 'trackBy'; readonly trackBy: string }>\n | Readonly<{ readonly mode: 'store' }>\n | Readonly<{ readonly mode: 'index' }>\n\nexport type FieldDecl<Input, Ctx = unknown> = Readonly<{\n readonly kind: 'field'\n readonly valuePath: string\n readonly rule: RuleInput<Input, Ctx>\n readonly errorTarget?: ErrorTarget\n}>\n\nexport type RootDecl<Input, Ctx = unknown> = Readonly<{\n readonly kind: 'root'\n readonly rule: RuleInput<Input, Ctx>\n}>\n\nexport type ListDecl<Item, Ctx = unknown> = Readonly<{\n readonly kind: 'list'\n readonly listPath: string\n readonly identity: ListIdentityPolicy\n readonly item?: RuleInput<Item, Ctx>\n readonly list?: RuleInput<ReadonlyArray<Item>, Ctx>\n}>\n\nexport type RulesDecl<TValues extends object = any> = FieldDecl<any> | RootDecl<TValues> | ListDecl<any>\n\nexport const field = <Input, Ctx = unknown>(\n valuePath: string,\n rule: RuleInput<Input, Ctx>,\n options?: { readonly errorTarget?: ErrorTarget },\n): FieldDecl<Input, Ctx> => ({\n kind: 'field',\n valuePath,\n rule,\n ...(options?.errorTarget !== undefined ? { errorTarget: options.errorTarget } : {}),\n})\n\nexport const root = <Input, Ctx = unknown>(rule: RuleInput<Input, Ctx>): RootDecl<Input, Ctx> => ({\n kind: 'root',\n rule,\n})\n\nexport const list = <Item, Ctx = unknown>(\n listPath: string,\n spec: {\n readonly identity: ListIdentityPolicy\n readonly item?: RuleInput<Item, Ctx>\n readonly list?: RuleInput<ReadonlyArray<Item>, Ctx>\n },\n): ListDecl<Item, Ctx> => ({\n kind: 'list',\n listPath,\n identity: spec.identity,\n ...(spec.item !== undefined ? { item: spec.item } : {}),\n ...(spec.list !== undefined ? { list: spec.list } : {}),\n})\n\nexport const fields = <Input, Ctx = unknown>(\n ...decls: ReadonlyArray<FieldDecl<Input, Ctx> | ReadonlyArray<FieldDecl<Input, Ctx>>>\n): Readonly<Record<string, RuleInput<Input, Ctx>>> => {\n const out: Record<string, RuleInput<Input, Ctx>> = {}\n const list: Array<FieldDecl<Input, Ctx>> = []\n\n const isDeclArray = (value: unknown): value is ReadonlyArray<FieldDecl<Input, Ctx>> => Array.isArray(value)\n\n for (const item of decls) {\n if (isDeclArray(item)) {\n list.push(...item)\n continue\n }\n list.push(item)\n }\n\n for (const decl of list) {\n const path = typeof decl?.valuePath === 'string' ? decl.valuePath.trim() : ''\n if (!path) continue\n if (path in out) {\n throw new Error(`[Form.Rule.fields] Duplicate valuePath \"${path}\"`)\n }\n out[path] = decl.rule\n }\n\n return out\n}\n\nexport {\n ERROR_VALUE_MAX_BYTES,\n assertErrorValueBudget,\n required,\n minLength,\n maxLength,\n min,\n max,\n pattern,\n} from './internal/validators/index.js'\n","export const ERROR_VALUE_MAX_BYTES = 256\n\nconst textEncoder = new TextEncoder()\n\nconst jsonByteSize = (value: unknown): number => {\n const json = JSON.stringify(value)\n return textEncoder.encode(json).length\n}\n\nconst truncateToJsonByteBudget = (value: string, maxBytes: number): string => {\n if (jsonByteSize(value) <= maxBytes) return value\n\n let lo = 0\n let hi = value.length\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2)\n const slice = value.slice(0, mid)\n if (jsonByteSize(slice) <= maxBytes) lo = mid\n else hi = mid - 1\n }\n return value.slice(0, lo)\n}\n\nexport const assertErrorValueBudget = (value: unknown, label: string): unknown => {\n const bytes = jsonByteSize(value)\n if (bytes <= ERROR_VALUE_MAX_BYTES) return value\n throw new Error(`[Form.validators] ErrorValue for \"${label}\" must be JSON ≤${ERROR_VALUE_MAX_BYTES}B (got ${bytes}B)`)\n}\n\nconst errorValue = (label: string, value: unknown): unknown => assertErrorValueBudget(value, label)\n\nexport type RequiredDecl =\n | boolean\n | string\n | Readonly<{\n readonly message?: string\n readonly trim?: boolean\n }>\n\nexport const required = (decl: RequiredDecl): ((value: unknown) => unknown | undefined) => {\n const trim = typeof decl === 'object' && decl !== null ? Boolean((decl as any).trim) : true\n const message =\n typeof decl === 'string'\n ? decl\n : typeof decl === 'object' && decl !== null && typeof (decl as any).message === 'string'\n ? (decl as any).message\n : 'required'\n\n const err = errorValue('required', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return err\n if (typeof value === 'string') {\n const v = trim ? value.trim() : value\n return v.length > 0 ? undefined : err\n }\n if (Array.isArray(value)) return value.length > 0 ? undefined : err\n if (typeof value === 'boolean') return value ? undefined : err\n return undefined\n }\n}\n\nexport type MinLengthDecl =\n | number\n | Readonly<{\n readonly min: number\n readonly message?: string\n }>\n\nexport const minLength = (decl: MinLengthDecl): ((value: unknown) => unknown | undefined) => {\n const min = typeof decl === 'number' ? decl : decl.min\n const message =\n typeof decl === 'object' && decl !== null && typeof decl.message === 'string' ? decl.message : 'minLength'\n const err = errorValue('minLength', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value === 'string') return value.length >= min ? undefined : err\n if (Array.isArray(value)) return value.length >= min ? undefined : err\n return undefined\n }\n}\n\nexport type MaxLengthDecl =\n | number\n | Readonly<{\n readonly max: number\n readonly message?: string\n }>\n\nexport const maxLength = (decl: MaxLengthDecl): ((value: unknown) => unknown | undefined) => {\n const max = typeof decl === 'number' ? decl : decl.max\n const message =\n typeof decl === 'object' && decl !== null && typeof decl.message === 'string' ? decl.message : 'maxLength'\n const err = errorValue('maxLength', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value === 'string') return value.length <= max ? undefined : err\n if (Array.isArray(value)) return value.length <= max ? undefined : err\n return undefined\n }\n}\n\nexport type MinDecl =\n | number\n | Readonly<{\n readonly min: number\n readonly message?: string\n }>\n\nexport const min = (decl: MinDecl): ((value: unknown) => unknown | undefined) => {\n const minValue = typeof decl === 'number' ? decl : decl.min\n const message = typeof decl === 'object' && decl !== null && typeof decl.message === 'string' ? decl.message : 'min'\n const err = errorValue('min', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value === 'number' && Number.isFinite(value)) return value >= minValue ? undefined : err\n return undefined\n }\n}\n\nexport type MaxDecl =\n | number\n | Readonly<{\n readonly max: number\n readonly message?: string\n }>\n\nexport const max = (decl: MaxDecl): ((value: unknown) => unknown | undefined) => {\n const maxValue = typeof decl === 'number' ? decl : decl.max\n const message = typeof decl === 'object' && decl !== null && typeof decl.message === 'string' ? decl.message : 'max'\n const err = errorValue('max', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value === 'number' && Number.isFinite(value)) return value <= maxValue ? undefined : err\n return undefined\n }\n}\n\nexport type PatternDecl =\n | RegExp\n | Readonly<{\n readonly re: RegExp\n readonly message?: string\n }>\n\nexport const pattern = (decl: PatternDecl): ((value: unknown) => unknown | undefined) => {\n const re = decl instanceof RegExp ? decl : decl.re\n const message =\n typeof decl === 'object' && decl !== null && typeof (decl as any).message === 'string'\n ? (decl as any).message\n : 'pattern'\n const err = errorValue('pattern', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value !== 'string') return undefined\n return re.test(value) ? undefined : err\n }\n}\n\nexport const schemaErrorMessage = (schemaError: unknown): string => {\n let message: string\n try {\n message = schemaError instanceof Error ? (schemaError.message || 'schema invalid') : String(schemaError)\n } catch {\n message = 'schema invalid'\n }\n\n const truncated = truncateToJsonByteBudget(message, ERROR_VALUE_MAX_BYTES)\n return truncated.length > 0 ? truncated : 'schema invalid'\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,wBAAwB;AAErC,IAAM,cAAc,IAAI,YAAY;AAEpC,IAAM,eAAe,CAAC,UAA2B;AAC/C,QAAM,OAAO,KAAK,UAAU,KAAK;AACjC,SAAO,YAAY,OAAO,IAAI,EAAE;AAClC;AAgBO,IAAM,yBAAyB,CAAC,OAAgB,UAA2B;AAChF,QAAM,QAAQ,aAAa,KAAK;AAChC,MAAI,SAAS,sBAAuB,QAAO;AAC3C,QAAM,IAAI,MAAM,qCAAqC,KAAK,wBAAmB,qBAAqB,UAAU,KAAK,IAAI;AACvH;AAEA,IAAM,aAAa,CAAC,OAAe,UAA4B,uBAAuB,OAAO,KAAK;AAU3F,IAAM,WAAW,CAAC,SAAkE;AACzF,QAAM,OAAO,OAAO,SAAS,YAAY,SAAS,OAAO,QAAS,KAAa,IAAI,IAAI;AACvF,QAAM,UACJ,OAAO,SAAS,WACZ,OACA,OAAO,SAAS,YAAY,SAAS,QAAQ,OAAQ,KAAa,YAAY,WAC3E,KAAa,UACd;AAER,QAAM,MAAM,WAAW,YAAY,OAAO;AAE1C,SAAO,CAAC,UAAmB;AACzB,QAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,QAAI,OAAO,UAAU,UAAU;AAC7B,YAAM,IAAI,OAAO,MAAM,KAAK,IAAI;AAChC,aAAO,EAAE,SAAS,IAAI,SAAY;AAAA,IACpC;AACA,QAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,SAAS,IAAI,SAAY;AAChE,QAAI,OAAO,UAAU,UAAW,QAAO,QAAQ,SAAY;AAC3D,WAAO;AAAA,EACT;AACF;AASO,IAAM,YAAY,CAAC,SAAmE;AAC3F,QAAMA,OAAM,OAAO,SAAS,WAAW,OAAO,KAAK;AACnD,QAAM,UACJ,OAAO,SAAS,YAAY,SAAS,QAAQ,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AACjG,QAAM,MAAM,WAAW,aAAa,OAAO;AAE3C,SAAO,CAAC,UAAmB;AACzB,QAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,QAAI,OAAO,UAAU,SAAU,QAAO,MAAM,UAAUA,OAAM,SAAY;AACxE,QAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,UAAUA,OAAM,SAAY;AACnE,WAAO;AAAA,EACT;AACF;AASO,IAAM,YAAY,CAAC,SAAmE;AAC3F,QAAMC,OAAM,OAAO,SAAS,WAAW,OAAO,KAAK;AACnD,QAAM,UACJ,OAAO,SAAS,YAAY,SAAS,QAAQ,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AACjG,QAAM,MAAM,WAAW,aAAa,OAAO;AAE3C,SAAO,CAAC,UAAmB;AACzB,QAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,QAAI,OAAO,UAAU,SAAU,QAAO,MAAM,UAAUA,OAAM,SAAY;AACxE,QAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,UAAUA,OAAM,SAAY;AACnE,WAAO;AAAA,EACT;AACF;AASO,IAAM,MAAM,CAAC,SAA6D;AAC/E,QAAM,WAAW,OAAO,SAAS,WAAW,OAAO,KAAK;AACxD,QAAM,UAAU,OAAO,SAAS,YAAY,SAAS,QAAQ,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AAC/G,QAAM,MAAM,WAAW,OAAO,OAAO;AAErC,SAAO,CAAC,UAAmB;AACzB,QAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,QAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,EAAG,QAAO,SAAS,WAAW,SAAY;AAChG,WAAO;AAAA,EACT;AACF;AASO,IAAM,MAAM,CAAC,SAA6D;AAC/E,QAAM,WAAW,OAAO,SAAS,WAAW,OAAO,KAAK;AACxD,QAAM,UAAU,OAAO,SAAS,YAAY,SAAS,QAAQ,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AAC/G,QAAM,MAAM,WAAW,OAAO,OAAO;AAErC,SAAO,CAAC,UAAmB;AACzB,QAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,QAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,EAAG,QAAO,SAAS,WAAW,SAAY;AAChG,WAAO;AAAA,EACT;AACF;AASO,IAAM,UAAU,CAAC,SAAiE;AACvF,QAAM,KAAK,gBAAgB,SAAS,OAAO,KAAK;AAChD,QAAM,UACJ,OAAO,SAAS,YAAY,SAAS,QAAQ,OAAQ,KAAa,YAAY,WACzE,KAAa,UACd;AACN,QAAM,MAAM,WAAW,WAAW,OAAO;AAEzC,SAAO,CAAC,UAAmB;AACzB,QAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,QAAI,OAAO,UAAU,SAAU,QAAO;AACtC,WAAO,GAAG,KAAK,KAAK,IAAI,SAAY;AAAA,EACtC;AACF;;;ADzGA,IAAM,OAAO,CAAI,UAA8C,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC;AAExF,IAAM,sBAAsB,CAAC,UAA+C;AAC1E,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO;AAClC,QAAM,MAA6B,CAAC;AACpC,aAAW,KAAK,OAAO;AACrB,QAAI,MAAM,cAAc,MAAM,SAAU,KAAI,KAAK,CAAC;AAAA,EACpD;AACA,SAAO,KAAK,GAAG;AACjB;AAEA,IAAM,gBAAgB,CAAC,UAAsD;AAC3E,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO;AAClC,QAAM,MAAqB,CAAC;AAC5B,aAAW,KAAK,OAAO;AACrB,QAAI,OAAO,MAAM,SAAU;AAC3B,UAAM,IAAI,EAAE,KAAK;AACjB,QAAI,CAAC,EAAG;AACR,QAAI,KAAK,CAAC;AAAA,EACZ;AACA,SAAO,KAAK,GAAG;AACjB;AAEA,IAAM,gBAAgB,CAAC,UACrB,QAAQ,KAAK,KAAK,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAOhF,IAAM,OAAO,CAAuB,UAAsD;AAC/F,MAAI,OAAO,UAAU,YAAY;AAC/B,WAAO;AAAA,MACL,SAAS;AAAA,QACP,MAAM,CAAC;AAAA,QACP,UAAU;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,cAAc,KAAK,GAAG;AACzB,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,WAAW,cAAe,MAAc,IAAI,KAAK,CAAC;AACxD,QAAM,iBAAiB,oBAAqB,MAAc,UAAU;AAEpE,QAAM,SAAS,oBAAI,IAA8B;AAEjD,QAAM,UAAU,CAAC,MAAc,QAAuB;AACpD,UAAM,WAAW,OAAO,SAAS,WAAW,KAAK,KAAK,IAAI;AAC1D,QAAI,CAAC,SAAU;AACf,QAAI,OAAO,IAAI,QAAQ,GAAG;AACxB,YAAM,IAAI,MAAM,yCAAyC,QAAQ,GAAG;AAAA,IACtE;AAEA,QAAI,OAAO,QAAQ,YAAY;AAC7B,aAAO,IAAI,UAAU;AAAA,QACnB,MAAM;AAAA,QACN,UAAU;AAAA,QACV,GAAI,mBAAmB,SAAY,EAAE,YAAY,eAAe,IAAI,CAAC;AAAA,MACvE,CAAC;AACD;AAAA,IACF;AAEA,QAAI,CAAC,OAAO,OAAO,QAAQ,SAAU;AACrC,UAAM,QAAQ;AACd,UAAM,OAAO,cAAc,MAAM,IAAI,KAAK;AAC1C,UAAM,aAAa,oBAAoB,MAAM,UAAU,KAAK;AAC5D,UAAM,WAAW,MAAM;AACvB,QAAI,OAAO,aAAa,WAAY;AAEpC,WAAO,IAAI,UAAU;AAAA,MACnB,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA,GAAI,eAAe,SAAY,EAAE,WAAW,IAAI,CAAC;AAAA,IACnD,CAAC;AAAA,EACH;AAGA,QAAM,eAAgB,MAAc;AACpC,MAAI,iBAAiB,UAAa,iBAAiB,OAAO;AACxD,UAAM,WAAsB,SAAS,YAAY;AACjD,YAAQ,YAAY,CAAC,UAAiB,SAAS,KAAK,CAAC;AAAA,EACvD;AAEA,QAAM,gBAAiB,MAAc;AACrC,MAAI,kBAAkB,QAAW;AAC/B,UAAM,WAAsB,UAAU,aAAa;AACnD,YAAQ,aAAa,CAAC,UAAiB,SAAS,KAAK,CAAC;AAAA,EACxD;AAEA,QAAM,gBAAiB,MAAc;AACrC,MAAI,kBAAkB,QAAW;AAC/B,UAAM,WAAsB,UAAU,aAAa;AACnD,YAAQ,aAAa,CAAC,UAAiB,SAAS,KAAK,CAAC;AAAA,EACxD;AAEA,QAAM,UAAW,MAAc;AAC/B,MAAI,YAAY,QAAW;AACzB,UAAM,WAAsB,IAAI,OAAO;AACvC,YAAQ,OAAO,CAAC,UAAiB,SAAS,KAAK,CAAC;AAAA,EAClD;AAEA,QAAM,UAAW,MAAc;AAC/B,MAAI,YAAY,QAAW;AACzB,UAAM,WAAsB,IAAI,OAAO;AACvC,YAAQ,OAAO,CAAC,UAAiB,SAAS,KAAK,CAAC;AAAA,EAClD;AAEA,QAAM,cAAe,MAAc;AACnC,MAAI,gBAAgB,QAAW;AAC7B,UAAM,WAAsB,QAAQ,WAAW;AAC/C,YAAQ,WAAW,CAAC,UAAiB,SAAS,KAAK,CAAC;AAAA,EACtD;AAIA,QAAM,gBAAiB,MAAc;AACrC,MAAI,OAAO,kBAAkB,YAAY;AACvC,YAAQ,YAAY,aAAa;AAAA,EACnC,WAAW,cAAc,aAAa,GAAG;AACvC,UAAMC,SAAQ,OAAO,KAAK,aAAa,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AAC1E,eAAW,QAAQA,QAAO;AACxB,cAAQ,MAAO,cAAsB,IAAI,CAAC;AAAA,IAC5C;AAAA,EACF;AAEA,QAAM,MAAwC,CAAC;AAC/C,QAAM,QAAQ,MAAM,KAAK,OAAO,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AACzE,aAAW,QAAQ,OAAO;AACxB,QAAI,IAAI,IAAI,OAAO,IAAI,IAAI;AAAA,EAC7B;AACA,SAAO;AACT;AAEO,IAAM,QAAQ,IAA0B,UAAmE;AAChH,QAAM,SAAS,oBAAI,IAA8B;AACjD,QAAM,aAAa,oBAAI,IAAY;AAEnC,aAAW,WAAW,OAAO;AAC3B,eAAW,QAAQ,OAAO,KAAK,OAAO,GAAG;AACvC,UAAI,OAAO,IAAI,IAAI,EAAG,YAAW,IAAI,IAAI;AAAA,UACpC,QAAO,IAAI,MAAM,QAAQ,IAAI,CAAE;AAAA,IACtC;AAAA,EACF;AAEA,MAAI,WAAW,OAAO,GAAG;AACvB,UAAMC,QAAO,MAAM,KAAK,UAAU,EAC/B,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC,EACjC,KAAK,IAAI;AACZ,UAAM,IAAI,MAAM,6CAA6CA,KAAI,EAAE;AAAA,EACrE;AAEA,QAAM,SAA2C,CAAC;AAClD,QAAM,QAAQ,MAAM,KAAK,OAAO,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AACzE,aAAW,QAAQ,OAAO;AACxB,WAAO,IAAI,IAAI,OAAO,IAAI,IAAI;AAAA,EAChC;AAEA,SAAO;AACT;AA+BO,IAAM,QAAQ,CACnB,WACA,MACA,aAC2B;AAAA,EAC3B,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA,GAAI,SAAS,gBAAgB,SAAY,EAAE,aAAa,QAAQ,YAAY,IAAI,CAAC;AACnF;AAEO,IAAM,OAAO,CAAuB,UAAuD;AAAA,EAChG,MAAM;AAAA,EACN;AACF;AAEO,IAAM,OAAO,CAClB,UACA,UAKyB;AAAA,EACzB,MAAM;AAAA,EACN;AAAA,EACA,UAAU,KAAK;AAAA,EACf,GAAI,KAAK,SAAS,SAAY,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;AAAA,EACrD,GAAI,KAAK,SAAS,SAAY,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;AACvD;AAEO,IAAM,SAAS,IACjB,UACiD;AACpD,QAAM,MAA6C,CAAC;AACpD,QAAMA,QAAqC,CAAC;AAE5C,QAAM,cAAc,CAAC,UAAkE,MAAM,QAAQ,KAAK;AAE1G,aAAW,QAAQ,OAAO;AACxB,QAAI,YAAY,IAAI,GAAG;AACrB,MAAAA,MAAK,KAAK,GAAG,IAAI;AACjB;AAAA,IACF;AACA,IAAAA,MAAK,KAAK,IAAI;AAAA,EAChB;AAEA,aAAW,QAAQA,OAAM;AACvB,UAAM,OAAO,OAAO,MAAM,cAAc,WAAW,KAAK,UAAU,KAAK,IAAI;AAC3E,QAAI,CAAC,KAAM;AACX,QAAI,QAAQ,KAAK;AACf,YAAM,IAAI,MAAM,2CAA2C,IAAI,GAAG;AAAA,IACpE;AACA,QAAI,IAAI,IAAI,KAAK;AAAA,EACnB;AAEA,SAAO;AACT;","names":["min","max","names","list"]}
|
package/dist/Rule.js
CHANGED
|
@@ -22,7 +22,6 @@ __export(Rule_exports, {
|
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
// src/internal/validators/index.ts
|
|
25
|
-
import { ParseResult } from "effect";
|
|
26
25
|
var ERROR_VALUE_MAX_BYTES = 256;
|
|
27
26
|
var textEncoder = new TextEncoder();
|
|
28
27
|
var jsonByteSize = (value) => {
|
|
@@ -117,7 +116,7 @@ var pattern = (decl) => {
|
|
|
117
116
|
var schemaErrorMessage = (schemaError) => {
|
|
118
117
|
let message;
|
|
119
118
|
try {
|
|
120
|
-
message =
|
|
119
|
+
message = schemaError instanceof Error ? schemaError.message || "schema invalid" : String(schemaError);
|
|
121
120
|
} catch {
|
|
122
121
|
message = "schema invalid";
|
|
123
122
|
}
|
|
@@ -312,4 +311,4 @@ export {
|
|
|
312
311
|
fields,
|
|
313
312
|
Rule_exports
|
|
314
313
|
};
|
|
315
|
-
//# sourceMappingURL=chunk-
|
|
314
|
+
//# sourceMappingURL=chunk-3U6VHYYQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/Rule.ts","../src/internal/validators/index.ts"],"sourcesContent":["import type * as Logix from '@logixjs/core'\nimport * as Validators from './internal/validators/index.js'\nimport type { CanonicalPath } from './internal/form/types.js'\n\nexport type AutoValidateOn = 'onChange' | 'onBlur'\n\nexport type RuleValidateOn = ReadonlyArray<AutoValidateOn>\n\nexport type RuleFn<Input, Ctx = unknown> = (input: Input, ctx: Ctx) => unknown | undefined\n\ntype RuleDeps<Input> = Input extends object\n ? CanonicalPath<Input> extends never\n ? string\n : CanonicalPath<Input>\n : string\n\nexport type Rule<Input, Ctx = unknown> = Logix.StateTrait.CheckRule<Input, Ctx> & {\n /**\n * validateOn:\n * - Only affects the auto-validation phase (onChange/onBlur); submit/manual always runs.\n * - If an empty array, auto-validation is disabled (only submit/manual runs).\n */\n readonly validateOn?: RuleValidateOn\n}\n\nexport type RuleSet<Input, Ctx = unknown> = Readonly<Record<string, Rule<Input, Ctx>>>\n\nexport type RuleEntry<Input, Ctx = unknown> =\n | RuleFn<Input, Ctx>\n | (Omit<Rule<Input, Ctx>, 'deps'> & {\n readonly deps?: ReadonlyArray<RuleDeps<Input>>\n })\n\nexport type RuleGroup<Input, Ctx = unknown> = Readonly<{\n readonly deps?: ReadonlyArray<RuleDeps<Input>>\n readonly validateOn?: RuleValidateOn\n readonly validate: Readonly<Record<string, RuleEntry<Input, Ctx>>>\n}>\n\nexport type RuleConfig<Input, Ctx = unknown> = Readonly<{\n readonly deps?: ReadonlyArray<RuleDeps<Input>>\n readonly validateOn?: RuleValidateOn\n\n // RHF-like builtins (expanded at build time into equivalent pure functions)\n readonly required?: Validators.RequiredDecl\n readonly minLength?: Validators.MinLengthDecl\n readonly maxLength?: Validators.MaxLengthDecl\n readonly min?: Validators.MinDecl\n readonly max?: Validators.MaxDecl\n readonly pattern?: Validators.PatternDecl\n\n // RHF-like validate: a function or a named map of functions (RuleEntry form is also allowed to override deps/validateOn)\n readonly validate?: RuleFn<Input, Ctx> | Readonly<Record<string, RuleEntry<Input, Ctx>>>\n}>\n\nexport type RuleInput<Input, Ctx = unknown> = RuleFn<Input, Ctx> | RuleGroup<Input, Ctx> | RuleConfig<Input, Ctx>\n\nconst uniq = <T>(items: ReadonlyArray<T>): ReadonlyArray<T> => Array.from(new Set(items))\n\nconst normalizeValidateOn = (input: unknown): RuleValidateOn | undefined => {\n if (!Array.isArray(input)) return undefined\n const out: Array<AutoValidateOn> = []\n for (const x of input) {\n if (x === 'onChange' || x === 'onBlur') out.push(x)\n }\n return uniq(out)\n}\n\nconst normalizeDeps = (input: unknown): ReadonlyArray<string> | undefined => {\n if (!Array.isArray(input)) return undefined\n const out: Array<string> = []\n for (const x of input) {\n if (typeof x !== 'string') continue\n const v = x.trim()\n if (!v) continue\n out.push(v)\n }\n return uniq(out)\n}\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n Boolean(value) && typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/**\n * make:\n * - The result must be directly attachable to `StateTrait.node({ check })`.\n * - Does not introduce an extra wrapper (e.g. `{ rules: ... }`).\n */\nexport const make = <Input, Ctx = unknown>(input: RuleInput<Input, Ctx>): RuleSet<Input, Ctx> => {\n if (typeof input === 'function') {\n return {\n default: {\n deps: [],\n validate: input,\n },\n }\n }\n\n if (!isPlainObject(input)) {\n return {}\n }\n\n const baseDeps = normalizeDeps((input as any).deps) ?? []\n const baseValidateOn = normalizeValidateOn((input as any).validateOn)\n\n const byName = new Map<string, Rule<Input, Ctx>>()\n\n const addRule = (name: string, raw: unknown): void => {\n const ruleName = typeof name === 'string' ? name.trim() : ''\n if (!ruleName) return\n if (byName.has(ruleName)) {\n throw new Error(`[Form.Rule.make] Duplicate rule name \"${ruleName}\"`)\n }\n\n if (typeof raw === 'function') {\n byName.set(ruleName, {\n deps: baseDeps,\n validate: raw as any,\n ...(baseValidateOn !== undefined ? { validateOn: baseValidateOn } : {}),\n })\n return\n }\n\n if (!raw || typeof raw !== 'object') return\n const entry = raw as any\n const deps = normalizeDeps(entry.deps) ?? baseDeps\n const validateOn = normalizeValidateOn(entry.validateOn) ?? baseValidateOn\n const validate = entry.validate\n if (typeof validate !== 'function') return\n\n byName.set(ruleName, {\n ...entry,\n deps,\n validate,\n ...(validateOn !== undefined ? { validateOn } : {}),\n })\n }\n\n // RHF-like builtins (if declared, it will be expanded into an equivalent pure function)\n const requiredDecl = (input as any).required as Validators.RequiredDecl | undefined\n if (requiredDecl !== undefined && requiredDecl !== false) {\n const validate = Validators.required(requiredDecl)\n addRule('required', (value: Input) => validate(value))\n }\n\n const minLengthDecl = (input as any).minLength as Validators.MinLengthDecl | undefined\n if (minLengthDecl !== undefined) {\n const validate = Validators.minLength(minLengthDecl)\n addRule('minLength', (value: Input) => validate(value))\n }\n\n const maxLengthDecl = (input as any).maxLength as Validators.MaxLengthDecl | undefined\n if (maxLengthDecl !== undefined) {\n const validate = Validators.maxLength(maxLengthDecl)\n addRule('maxLength', (value: Input) => validate(value))\n }\n\n const minDecl = (input as any).min as Validators.MinDecl | undefined\n if (minDecl !== undefined) {\n const validate = Validators.min(minDecl)\n addRule('min', (value: Input) => validate(value))\n }\n\n const maxDecl = (input as any).max as Validators.MaxDecl | undefined\n if (maxDecl !== undefined) {\n const validate = Validators.max(maxDecl)\n addRule('max', (value: Input) => validate(value))\n }\n\n const patternDecl = (input as any).pattern as Validators.PatternDecl | undefined\n if (patternDecl !== undefined) {\n const validate = Validators.pattern(patternDecl)\n addRule('pattern', (value: Input) => validate(value))\n }\n\n // validate: supports both legacy RuleGroup `{ validate: Record<string, RuleEntry> }`\n // and RHF-style `validate: fn | Record<string, fn>`.\n const validateBlock = (input as any).validate as unknown\n if (typeof validateBlock === 'function') {\n addRule('validate', validateBlock)\n } else if (isPlainObject(validateBlock)) {\n const names = Object.keys(validateBlock).sort((a, b) => a.localeCompare(b))\n for (const name of names) {\n addRule(name, (validateBlock as any)[name])\n }\n }\n\n const out: Record<string, Rule<Input, Ctx>> = {}\n const names = Array.from(byName.keys()).sort((a, b) => a.localeCompare(b))\n for (const name of names) {\n out[name] = byName.get(name)!\n }\n return out\n}\n\nexport const merge = <Input, Ctx = unknown>(...rules: ReadonlyArray<RuleSet<Input, Ctx>>): RuleSet<Input, Ctx> => {\n const byName = new Map<string, Rule<Input, Ctx>>()\n const duplicates = new Set<string>()\n\n for (const ruleSet of rules) {\n for (const name of Object.keys(ruleSet)) {\n if (byName.has(name)) duplicates.add(name)\n else byName.set(name, ruleSet[name]!)\n }\n }\n\n if (duplicates.size > 0) {\n const list = Array.from(duplicates)\n .sort((a, b) => a.localeCompare(b))\n .join(', ')\n throw new Error(`[Form.Rule.merge] Duplicate rule name(s): ${list}`)\n }\n\n const merged: Record<string, Rule<Input, Ctx>> = {}\n const names = Array.from(byName.keys()).sort((a, b) => a.localeCompare(b))\n for (const name of names) {\n merged[name] = byName.get(name)!\n }\n\n return merged\n}\n\nexport type ErrorTarget = '$value' | '$self'\n\nexport type ListIdentityPolicy =\n | Readonly<{ readonly mode: 'trackBy'; readonly trackBy: string }>\n | Readonly<{ readonly mode: 'store' }>\n | Readonly<{ readonly mode: 'index' }>\n\nexport type FieldDecl<Input, Ctx = unknown> = Readonly<{\n readonly kind: 'field'\n readonly valuePath: string\n readonly rule: RuleInput<Input, Ctx>\n readonly errorTarget?: ErrorTarget\n}>\n\nexport type RootDecl<Input, Ctx = unknown> = Readonly<{\n readonly kind: 'root'\n readonly rule: RuleInput<Input, Ctx>\n}>\n\nexport type ListDecl<Item, Ctx = unknown> = Readonly<{\n readonly kind: 'list'\n readonly listPath: string\n readonly identity: ListIdentityPolicy\n readonly item?: RuleInput<Item, Ctx>\n readonly list?: RuleInput<ReadonlyArray<Item>, Ctx>\n}>\n\nexport type RulesDecl<TValues extends object = any> = FieldDecl<any> | RootDecl<TValues> | ListDecl<any>\n\nexport const field = <Input, Ctx = unknown>(\n valuePath: string,\n rule: RuleInput<Input, Ctx>,\n options?: { readonly errorTarget?: ErrorTarget },\n): FieldDecl<Input, Ctx> => ({\n kind: 'field',\n valuePath,\n rule,\n ...(options?.errorTarget !== undefined ? { errorTarget: options.errorTarget } : {}),\n})\n\nexport const root = <Input, Ctx = unknown>(rule: RuleInput<Input, Ctx>): RootDecl<Input, Ctx> => ({\n kind: 'root',\n rule,\n})\n\nexport const list = <Item, Ctx = unknown>(\n listPath: string,\n spec: {\n readonly identity: ListIdentityPolicy\n readonly item?: RuleInput<Item, Ctx>\n readonly list?: RuleInput<ReadonlyArray<Item>, Ctx>\n },\n): ListDecl<Item, Ctx> => ({\n kind: 'list',\n listPath,\n identity: spec.identity,\n ...(spec.item !== undefined ? { item: spec.item } : {}),\n ...(spec.list !== undefined ? { list: spec.list } : {}),\n})\n\nexport const fields = <Input, Ctx = unknown>(\n ...decls: ReadonlyArray<FieldDecl<Input, Ctx> | ReadonlyArray<FieldDecl<Input, Ctx>>>\n): Readonly<Record<string, RuleInput<Input, Ctx>>> => {\n const out: Record<string, RuleInput<Input, Ctx>> = {}\n const list: Array<FieldDecl<Input, Ctx>> = []\n\n const isDeclArray = (value: unknown): value is ReadonlyArray<FieldDecl<Input, Ctx>> => Array.isArray(value)\n\n for (const item of decls) {\n if (isDeclArray(item)) {\n list.push(...item)\n continue\n }\n list.push(item)\n }\n\n for (const decl of list) {\n const path = typeof decl?.valuePath === 'string' ? decl.valuePath.trim() : ''\n if (!path) continue\n if (path in out) {\n throw new Error(`[Form.Rule.fields] Duplicate valuePath \"${path}\"`)\n }\n out[path] = decl.rule\n }\n\n return out\n}\n\nexport {\n ERROR_VALUE_MAX_BYTES,\n assertErrorValueBudget,\n required,\n minLength,\n maxLength,\n min,\n max,\n pattern,\n} from './internal/validators/index.js'\n","export const ERROR_VALUE_MAX_BYTES = 256\n\nconst textEncoder = new TextEncoder()\n\nconst jsonByteSize = (value: unknown): number => {\n const json = JSON.stringify(value)\n return textEncoder.encode(json).length\n}\n\nconst truncateToJsonByteBudget = (value: string, maxBytes: number): string => {\n if (jsonByteSize(value) <= maxBytes) return value\n\n let lo = 0\n let hi = value.length\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2)\n const slice = value.slice(0, mid)\n if (jsonByteSize(slice) <= maxBytes) lo = mid\n else hi = mid - 1\n }\n return value.slice(0, lo)\n}\n\nexport const assertErrorValueBudget = (value: unknown, label: string): unknown => {\n const bytes = jsonByteSize(value)\n if (bytes <= ERROR_VALUE_MAX_BYTES) return value\n throw new Error(`[Form.validators] ErrorValue for \"${label}\" must be JSON ≤${ERROR_VALUE_MAX_BYTES}B (got ${bytes}B)`)\n}\n\nconst errorValue = (label: string, value: unknown): unknown => assertErrorValueBudget(value, label)\n\nexport type RequiredDecl =\n | boolean\n | string\n | Readonly<{\n readonly message?: string\n readonly trim?: boolean\n }>\n\nexport const required = (decl: RequiredDecl): ((value: unknown) => unknown | undefined) => {\n const trim = typeof decl === 'object' && decl !== null ? Boolean((decl as any).trim) : true\n const message =\n typeof decl === 'string'\n ? decl\n : typeof decl === 'object' && decl !== null && typeof (decl as any).message === 'string'\n ? (decl as any).message\n : 'required'\n\n const err = errorValue('required', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return err\n if (typeof value === 'string') {\n const v = trim ? value.trim() : value\n return v.length > 0 ? undefined : err\n }\n if (Array.isArray(value)) return value.length > 0 ? undefined : err\n if (typeof value === 'boolean') return value ? undefined : err\n return undefined\n }\n}\n\nexport type MinLengthDecl =\n | number\n | Readonly<{\n readonly min: number\n readonly message?: string\n }>\n\nexport const minLength = (decl: MinLengthDecl): ((value: unknown) => unknown | undefined) => {\n const min = typeof decl === 'number' ? decl : decl.min\n const message =\n typeof decl === 'object' && decl !== null && typeof decl.message === 'string' ? decl.message : 'minLength'\n const err = errorValue('minLength', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value === 'string') return value.length >= min ? undefined : err\n if (Array.isArray(value)) return value.length >= min ? undefined : err\n return undefined\n }\n}\n\nexport type MaxLengthDecl =\n | number\n | Readonly<{\n readonly max: number\n readonly message?: string\n }>\n\nexport const maxLength = (decl: MaxLengthDecl): ((value: unknown) => unknown | undefined) => {\n const max = typeof decl === 'number' ? decl : decl.max\n const message =\n typeof decl === 'object' && decl !== null && typeof decl.message === 'string' ? decl.message : 'maxLength'\n const err = errorValue('maxLength', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value === 'string') return value.length <= max ? undefined : err\n if (Array.isArray(value)) return value.length <= max ? undefined : err\n return undefined\n }\n}\n\nexport type MinDecl =\n | number\n | Readonly<{\n readonly min: number\n readonly message?: string\n }>\n\nexport const min = (decl: MinDecl): ((value: unknown) => unknown | undefined) => {\n const minValue = typeof decl === 'number' ? decl : decl.min\n const message = typeof decl === 'object' && decl !== null && typeof decl.message === 'string' ? decl.message : 'min'\n const err = errorValue('min', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value === 'number' && Number.isFinite(value)) return value >= minValue ? undefined : err\n return undefined\n }\n}\n\nexport type MaxDecl =\n | number\n | Readonly<{\n readonly max: number\n readonly message?: string\n }>\n\nexport const max = (decl: MaxDecl): ((value: unknown) => unknown | undefined) => {\n const maxValue = typeof decl === 'number' ? decl : decl.max\n const message = typeof decl === 'object' && decl !== null && typeof decl.message === 'string' ? decl.message : 'max'\n const err = errorValue('max', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value === 'number' && Number.isFinite(value)) return value <= maxValue ? undefined : err\n return undefined\n }\n}\n\nexport type PatternDecl =\n | RegExp\n | Readonly<{\n readonly re: RegExp\n readonly message?: string\n }>\n\nexport const pattern = (decl: PatternDecl): ((value: unknown) => unknown | undefined) => {\n const re = decl instanceof RegExp ? decl : decl.re\n const message =\n typeof decl === 'object' && decl !== null && typeof (decl as any).message === 'string'\n ? (decl as any).message\n : 'pattern'\n const err = errorValue('pattern', message)\n\n return (value: unknown) => {\n if (value === null || value === undefined) return undefined\n if (typeof value !== 'string') return undefined\n return re.test(value) ? undefined : err\n }\n}\n\nexport const schemaErrorMessage = (schemaError: unknown): string => {\n let message: string\n try {\n message = schemaError instanceof Error ? (schemaError.message || 'schema invalid') : String(schemaError)\n } catch {\n message = 'schema invalid'\n }\n\n const truncated = truncateToJsonByteBudget(message, ERROR_VALUE_MAX_BYTES)\n return truncated.length > 0 ? truncated : 'schema invalid'\n}\n"],"mappings":"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","names":["min","max","names","list"]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
make,
|
|
5
5
|
root,
|
|
6
6
|
schemaErrorMessage
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-3U6VHYYQ.js";
|
|
8
8
|
import {
|
|
9
9
|
toSchemaErrorTree
|
|
10
10
|
} from "./chunk-JZ5FZKPJ.js";
|
|
@@ -668,8 +668,14 @@ var makeFormController = (params) => {
|
|
|
668
668
|
});
|
|
669
669
|
const state = yield* runtime.getState;
|
|
670
670
|
const { errors: _errors, ui: _ui, $form: _meta, ...values } = state;
|
|
671
|
-
const
|
|
672
|
-
|
|
671
|
+
const schemaTree = (() => {
|
|
672
|
+
try {
|
|
673
|
+
Schema.decodeUnknownSync(params.valuesSchema)(values);
|
|
674
|
+
return {};
|
|
675
|
+
} catch (error) {
|
|
676
|
+
return toSchemaErrorTree(error);
|
|
677
|
+
}
|
|
678
|
+
})();
|
|
673
679
|
yield* runtime.dispatch({
|
|
674
680
|
_tag: "setValue",
|
|
675
681
|
payload: { path: "errors.$schema", value: schemaTree }
|
|
@@ -711,8 +717,14 @@ var makeFormController = (params) => {
|
|
|
711
717
|
$form: _metaAfterRules,
|
|
712
718
|
...valuesAfterRules
|
|
713
719
|
} = stateAfterRules;
|
|
714
|
-
const
|
|
715
|
-
|
|
720
|
+
const schemaTree = (() => {
|
|
721
|
+
try {
|
|
722
|
+
Schema.decodeUnknownSync(params.valuesSchema)(valuesAfterRules);
|
|
723
|
+
return {};
|
|
724
|
+
} catch (error) {
|
|
725
|
+
return toSchemaErrorTree(error);
|
|
726
|
+
}
|
|
727
|
+
})();
|
|
716
728
|
yield* runtime.dispatch({
|
|
717
729
|
_tag: "setValue",
|
|
718
730
|
payload: { path: "errors.$schema", value: schemaTree }
|
|
@@ -828,7 +840,7 @@ var install = (module, config) => module.logic(($) => {
|
|
|
828
840
|
const prev = pending.get(path);
|
|
829
841
|
if (!prev) return;
|
|
830
842
|
pending.delete(path);
|
|
831
|
-
yield* Fiber.
|
|
843
|
+
yield* Fiber.interrupt(prev);
|
|
832
844
|
});
|
|
833
845
|
const scheduleDebouncedValidate = (path) => Effect2.gen(function* () {
|
|
834
846
|
const ms = debounceMs ?? 0;
|
|
@@ -839,9 +851,9 @@ var install = (module, config) => module.logic(($) => {
|
|
|
839
851
|
yield* cancelPending(path);
|
|
840
852
|
const fiber = yield* Effect2.forkScoped(
|
|
841
853
|
Effect2.sleep(Duration.millis(ms)).pipe(
|
|
842
|
-
Effect2.
|
|
854
|
+
Effect2.flatMap(() => validate("valueChange", path)),
|
|
843
855
|
Effect2.ensuring(Effect2.sync(() => pending.delete(path))),
|
|
844
|
-
Effect2.
|
|
856
|
+
Effect2.catchCause(() => Effect2.void)
|
|
845
857
|
)
|
|
846
858
|
);
|
|
847
859
|
pending.set(path, fiber);
|
|
@@ -1018,14 +1030,12 @@ var make2 = (id, config, extend) => {
|
|
|
1018
1030
|
isDirty: Schema2.Boolean,
|
|
1019
1031
|
errorCount: Schema2.Number
|
|
1020
1032
|
});
|
|
1021
|
-
const StateSchema = Schema2.
|
|
1022
|
-
config.values,
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
})
|
|
1028
|
-
);
|
|
1033
|
+
const StateSchema = Schema2.Struct({
|
|
1034
|
+
...config.values.fields ?? {},
|
|
1035
|
+
errors: ErrorsSchema,
|
|
1036
|
+
ui: UiSchema,
|
|
1037
|
+
$form: MetaSchema
|
|
1038
|
+
});
|
|
1029
1039
|
const Actions = FormActions;
|
|
1030
1040
|
const reducers = makeFormReducers({
|
|
1031
1041
|
initialValues: config.initialValues
|
|
@@ -1067,67 +1077,60 @@ var make2 = (id, config, extend) => {
|
|
|
1067
1077
|
if (mode === "store" || mode === "index") return;
|
|
1068
1078
|
throw new Error(`[Form.make] Invalid identity.mode for "${listPath}" (got "${String(mode)}")`);
|
|
1069
1079
|
};
|
|
1080
|
+
const isRelativeRuleDep = (dep, options) => {
|
|
1081
|
+
const allowNumericRelativeDep = options?.allowNumericRelativeDep ?? true;
|
|
1082
|
+
if (dep === "$root") return false;
|
|
1083
|
+
if (dep.includes("[") || dep.includes("]") || dep.includes(".")) return false;
|
|
1084
|
+
if (!allowNumericRelativeDep && /^[0-9]+$/.test(dep)) return false;
|
|
1085
|
+
return true;
|
|
1086
|
+
};
|
|
1087
|
+
const prefixRuleDeps = (deps, prefix, options) => {
|
|
1088
|
+
if (!Array.isArray(deps)) return void 0;
|
|
1089
|
+
const out = [];
|
|
1090
|
+
for (const raw of deps) {
|
|
1091
|
+
if (typeof raw !== "string") continue;
|
|
1092
|
+
const dep = raw.trim();
|
|
1093
|
+
if (!dep) continue;
|
|
1094
|
+
out.push(isRelativeRuleDep(dep, options) && prefix ? `${prefix}.${dep}` : dep);
|
|
1095
|
+
}
|
|
1096
|
+
return out;
|
|
1097
|
+
};
|
|
1098
|
+
const prefixRuleInputDeps = (input, prefix, options) => {
|
|
1099
|
+
if (!input || typeof input !== "object") return input;
|
|
1100
|
+
if (Array.isArray(input)) return input;
|
|
1101
|
+
const anyInput = input;
|
|
1102
|
+
const deps = prefixRuleDeps(anyInput.deps, prefix, options);
|
|
1103
|
+
const validate = anyInput.validate;
|
|
1104
|
+
if (typeof validate === "function") {
|
|
1105
|
+
return deps !== void 0 ? { ...anyInput, deps } : input;
|
|
1106
|
+
}
|
|
1107
|
+
if (validate && typeof validate === "object" && !Array.isArray(validate)) {
|
|
1108
|
+
const nextValidate = { ...validate };
|
|
1109
|
+
for (const [name, raw] of Object.entries(validate)) {
|
|
1110
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
|
|
1111
|
+
const entryDeps = prefixRuleDeps(raw.deps, prefix, options);
|
|
1112
|
+
if (entryDeps !== void 0) {
|
|
1113
|
+
nextValidate[name] = { ...raw, deps: entryDeps };
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
return {
|
|
1117
|
+
...anyInput,
|
|
1118
|
+
...deps !== void 0 ? { deps } : {},
|
|
1119
|
+
validate: nextValidate
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1122
|
+
return deps !== void 0 ? { ...anyInput, deps } : input;
|
|
1123
|
+
};
|
|
1070
1124
|
const compileRulesToTraitSpec = (rulesSpec2) => {
|
|
1071
1125
|
if (!rulesSpec2 || rulesSpec2._tag !== "FormRulesSpec") {
|
|
1072
1126
|
throw new Error(`[Form.make] "rules" must be a FormRulesSpec (from Form.rules(...)/rules.schema(...))`);
|
|
1073
1127
|
}
|
|
1074
|
-
const joinPath2 = (prefix, suffix) => {
|
|
1075
|
-
if (!prefix) return suffix;
|
|
1076
|
-
if (!suffix) return prefix;
|
|
1077
|
-
return `${prefix}.${suffix}`;
|
|
1078
|
-
};
|
|
1079
1128
|
const dirnamePath = (path) => {
|
|
1080
1129
|
const p = String(path ?? "").trim();
|
|
1081
1130
|
if (!p) return "";
|
|
1082
1131
|
const idx = p.lastIndexOf(".");
|
|
1083
1132
|
return idx >= 0 ? p.slice(0, idx) : "";
|
|
1084
1133
|
};
|
|
1085
|
-
const isRelativeDep = (dep) => {
|
|
1086
|
-
if (typeof dep !== "string") return false;
|
|
1087
|
-
const d = dep.trim();
|
|
1088
|
-
if (!d) return false;
|
|
1089
|
-
if (d === "$root") return false;
|
|
1090
|
-
if (d.includes("[") || d.includes("]")) return false;
|
|
1091
|
-
if (d.includes(".")) return false;
|
|
1092
|
-
return true;
|
|
1093
|
-
};
|
|
1094
|
-
const prefixDeps = (deps, prefix) => {
|
|
1095
|
-
if (!Array.isArray(deps)) return void 0;
|
|
1096
|
-
const out = [];
|
|
1097
|
-
for (const raw of deps) {
|
|
1098
|
-
if (typeof raw !== "string") continue;
|
|
1099
|
-
const d = raw.trim();
|
|
1100
|
-
if (!d) continue;
|
|
1101
|
-
out.push(isRelativeDep(d) ? joinPath2(prefix, d) : d);
|
|
1102
|
-
}
|
|
1103
|
-
return out;
|
|
1104
|
-
};
|
|
1105
|
-
const prefixRuleInputDeps = (input, prefix) => {
|
|
1106
|
-
if (!input || typeof input !== "object") return input;
|
|
1107
|
-
if (Array.isArray(input)) return input;
|
|
1108
|
-
const anyInput = input;
|
|
1109
|
-
const deps = prefixDeps(anyInput.deps, prefix);
|
|
1110
|
-
const validate = anyInput.validate;
|
|
1111
|
-
if (typeof validate === "function") {
|
|
1112
|
-
return deps !== void 0 ? { ...anyInput, deps } : input;
|
|
1113
|
-
}
|
|
1114
|
-
if (validate && typeof validate === "object" && !Array.isArray(validate)) {
|
|
1115
|
-
const nextValidate = { ...validate };
|
|
1116
|
-
for (const [name, raw] of Object.entries(validate)) {
|
|
1117
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
|
|
1118
|
-
const entryDeps = prefixDeps(raw.deps, prefix);
|
|
1119
|
-
if (entryDeps !== void 0) {
|
|
1120
|
-
nextValidate[name] = { ...raw, deps: entryDeps };
|
|
1121
|
-
}
|
|
1122
|
-
}
|
|
1123
|
-
return {
|
|
1124
|
-
...anyInput,
|
|
1125
|
-
...deps !== void 0 ? { deps } : {},
|
|
1126
|
-
validate: nextValidate
|
|
1127
|
-
};
|
|
1128
|
-
}
|
|
1129
|
-
return deps !== void 0 ? { ...anyInput, deps } : input;
|
|
1130
|
-
};
|
|
1131
1134
|
const decls = Array.isArray(rulesSpec2.decls) ? rulesSpec2.decls : [];
|
|
1132
1135
|
const spec = {};
|
|
1133
1136
|
const declared = /* @__PURE__ */ new Set();
|
|
@@ -1302,45 +1305,9 @@ var make2 = (id, config, extend) => {
|
|
|
1302
1305
|
const idx = valuePath.lastIndexOf(".");
|
|
1303
1306
|
return idx >= 0 ? valuePath.slice(0, idx) : "";
|
|
1304
1307
|
})();
|
|
1305
|
-
const
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
for (const raw of deps) {
|
|
1309
|
-
if (typeof raw !== "string") continue;
|
|
1310
|
-
const d = raw.trim();
|
|
1311
|
-
if (!d) continue;
|
|
1312
|
-
const isRelative = d !== "$root" && !d.includes("[") && !d.includes("]") && !d.includes(".") && !/^[0-9]+$/.test(d);
|
|
1313
|
-
out.push(isRelative && prefix ? `${prefix}.${d}` : d);
|
|
1314
|
-
}
|
|
1315
|
-
return out;
|
|
1316
|
-
};
|
|
1317
|
-
const prefixRuleInputDeps = (input, prefix) => {
|
|
1318
|
-
if (!input || typeof input !== "object") return input;
|
|
1319
|
-
if (Array.isArray(input)) return input;
|
|
1320
|
-
const anyInput = input;
|
|
1321
|
-
const deps = prefixDeps(anyInput.deps, prefix);
|
|
1322
|
-
const validate = anyInput.validate;
|
|
1323
|
-
if (typeof validate === "function") {
|
|
1324
|
-
return deps !== void 0 ? { ...anyInput, deps } : input;
|
|
1325
|
-
}
|
|
1326
|
-
if (validate && typeof validate === "object" && !Array.isArray(validate)) {
|
|
1327
|
-
const nextValidate = { ...validate };
|
|
1328
|
-
for (const [ruleName, raw] of Object.entries(validate)) {
|
|
1329
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
|
|
1330
|
-
const entryDeps = prefixDeps(raw.deps, prefix);
|
|
1331
|
-
if (entryDeps !== void 0) {
|
|
1332
|
-
nextValidate[ruleName] = { ...raw, deps: entryDeps };
|
|
1333
|
-
}
|
|
1334
|
-
}
|
|
1335
|
-
return {
|
|
1336
|
-
...anyInput,
|
|
1337
|
-
...deps !== void 0 ? { deps } : {},
|
|
1338
|
-
validate: nextValidate
|
|
1339
|
-
};
|
|
1340
|
-
}
|
|
1341
|
-
return deps !== void 0 ? { ...anyInput, deps } : input;
|
|
1342
|
-
};
|
|
1343
|
-
const ruleInput = prefixRuleInputDeps(decl.rule, depsPrefix);
|
|
1308
|
+
const ruleInput = prefixRuleInputDeps(decl.rule, depsPrefix, {
|
|
1309
|
+
allowNumericRelativeDep: false
|
|
1310
|
+
});
|
|
1344
1311
|
const rules3 = make(ruleInput);
|
|
1345
1312
|
emitRuleSet({
|
|
1346
1313
|
source: "rules",
|
|
@@ -1620,8 +1587,12 @@ var makeFieldNode = (rule) => ({
|
|
|
1620
1587
|
var fieldFromSchema = (schema) => ({
|
|
1621
1588
|
validate: {
|
|
1622
1589
|
schema: (value) => {
|
|
1623
|
-
|
|
1624
|
-
|
|
1590
|
+
try {
|
|
1591
|
+
Schema3.decodeUnknownSync(schema)(value);
|
|
1592
|
+
return void 0;
|
|
1593
|
+
} catch (error) {
|
|
1594
|
+
return schemaErrorMessage(error);
|
|
1595
|
+
}
|
|
1625
1596
|
}
|
|
1626
1597
|
}
|
|
1627
1598
|
});
|
|
@@ -1882,4 +1853,4 @@ export {
|
|
|
1882
1853
|
node,
|
|
1883
1854
|
list2 as list
|
|
1884
1855
|
};
|
|
1885
|
-
//# sourceMappingURL=chunk-
|
|
1856
|
+
//# sourceMappingURL=chunk-WGBRLVRO.js.map
|