@pipelex/mthds-form 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -2
- package/dist/chunk-6XD6UZSU.js +28 -0
- package/dist/chunk-6XD6UZSU.js.map +1 -0
- package/dist/chunk-7BMOPXDY.js +205 -0
- package/dist/chunk-7BMOPXDY.js.map +1 -0
- package/dist/chunk-GKV77RAS.js +46 -0
- package/dist/chunk-GKV77RAS.js.map +1 -0
- package/dist/chunk-HARYEWNG.js +31 -0
- package/dist/chunk-HARYEWNG.js.map +1 -0
- package/dist/chunk-KFZ5MZOM.js +44 -0
- package/dist/chunk-KFZ5MZOM.js.map +1 -0
- package/dist/chunk-NMT7BRLO.js +40 -0
- package/dist/chunk-NMT7BRLO.js.map +1 -0
- package/dist/chunk-O4O3QNVC.js +146 -0
- package/dist/chunk-O4O3QNVC.js.map +1 -0
- package/dist/chunk-PM55AHRO.js +52 -0
- package/dist/chunk-PM55AHRO.js.map +1 -0
- package/dist/chunk-RPA7DNSK.js +41 -0
- package/dist/chunk-RPA7DNSK.js.map +1 -0
- package/dist/chunk-V3OV2XQT.js +12 -0
- package/dist/chunk-V3OV2XQT.js.map +1 -0
- package/dist/chunk-VMLXO5JS.js +132 -0
- package/dist/chunk-VMLXO5JS.js.map +1 -0
- package/dist/chunk-VTPUDBSJ.js +61 -0
- package/dist/chunk-VTPUDBSJ.js.map +1 -0
- package/dist/chunk-WXBSM2CE.js +201 -0
- package/dist/chunk-WXBSM2CE.js.map +1 -0
- package/dist/chunk-XEPD5VJQ.js +99 -0
- package/dist/chunk-XEPD5VJQ.js.map +1 -0
- package/dist/core/contracts.d.ts +143 -0
- package/dist/core/contracts.js +4 -0
- package/dist/core/contracts.js.map +1 -0
- package/dist/core/date-format.d.ts +87 -0
- package/dist/core/date-format.js +3 -0
- package/dist/core/date-format.js.map +1 -0
- package/dist/core/derive.d.ts +20 -0
- package/dist/core/derive.js +7 -0
- package/dist/core/derive.js.map +1 -0
- package/dist/{descriptor-X6MwFIWu.d.ts → core/descriptor.d.ts} +42 -1
- package/dist/core/descriptor.js +3 -0
- package/dist/core/descriptor.js.map +1 -0
- package/dist/core/gate-validator.d.ts +27 -0
- package/dist/core/gate-validator.js +4 -0
- package/dist/core/gate-validator.js.map +1 -0
- package/dist/core/gate.d.ts +144 -0
- package/dist/core/gate.js +13 -0
- package/dist/core/gate.js.map +1 -0
- package/dist/core/index.d.ts +12 -615
- package/dist/core/index.js +14 -1
- package/dist/core/native-concepts.d.ts +78 -0
- package/dist/core/native-concepts.js +3 -0
- package/dist/core/native-concepts.js.map +1 -0
- package/dist/core/normalize-schema.d.ts +30 -0
- package/dist/core/normalize-schema.js +4 -0
- package/dist/core/normalize-schema.js.map +1 -0
- package/dist/core/own-property.d.ts +46 -0
- package/dist/core/own-property.js +3 -0
- package/dist/core/own-property.js.map +1 -0
- package/dist/core/readiness.d.ts +89 -0
- package/dist/core/readiness.js +4 -0
- package/dist/core/readiness.js.map +1 -0
- package/dist/core/schema-utils.d.ts +74 -0
- package/dist/core/schema-utils.js +3 -0
- package/dist/core/schema-utils.js.map +1 -0
- package/dist/core/validation-message.d.ts +39 -0
- package/dist/core/validation-message.js +4 -0
- package/dist/core/validation-message.js.map +1 -0
- package/dist/core/values.d.ts +91 -0
- package/dist/core/values.js +11 -0
- package/dist/core/values.js.map +1 -0
- package/dist/core/wire-format.d.ts +95 -0
- package/dist/core/wire-format.js +7 -0
- package/dist/core/wire-format.js.map +1 -0
- package/dist/react/index.d.ts +22 -1
- package/dist/react/index.js +128 -48
- package/dist/react/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +5 -1
- package/dist/chunk-YWMUM7BC.js +0 -966
- package/dist/chunk-YWMUM7BC.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"date-format.js"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { PipeInputContract } from './contracts.js';
|
|
2
|
+
import { RunField } from './descriptor.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The ONE derivation function: `PipeInputContract` map → `RunField[]`.
|
|
6
|
+
*
|
|
7
|
+
* Everything heuristic stays module-private behind `buildRunFields`: the
|
|
8
|
+
* native-concept taxonomy, `isDocumentObject`, the depth-based prose/label
|
|
9
|
+
* rule, the `accept` strings, list splitting. Nothing here is exported except
|
|
10
|
+
* the function itself - so the M1 milestone can swap the source of the
|
|
11
|
+
* descriptor (server-derived) without touching consumers.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Convert the API's per-input contracts into the runner's field descriptors.
|
|
16
|
+
* The map's insertion order is preserved (required-first is the caller's job).
|
|
17
|
+
*/
|
|
18
|
+
declare function buildRunFields(inputs: Record<string, PipeInputContract>): RunField[];
|
|
19
|
+
|
|
20
|
+
export { buildRunFields };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"derive.js"}
|
|
@@ -30,6 +30,20 @@ interface RunFieldCommon {
|
|
|
30
30
|
* they are gated through their parent's `fieldFilled`.
|
|
31
31
|
*/
|
|
32
32
|
gating?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* The single property this field's value sits inside on the wire, when its
|
|
35
|
+
* concept declares a scalar content model: `native.Text` is `TextContent
|
|
36
|
+
* {text}`, `native.Number` is `NumberContent {number}`, `native.YesNo` is
|
|
37
|
+
* `YesNoContent {yes_no}`. The control still holds the plain scalar; the
|
|
38
|
+
* value bridge wraps into this property on the way out and unwraps on the way
|
|
39
|
+
* back in.
|
|
40
|
+
*
|
|
41
|
+
* A property NAME, never a schema - the descriptor stays the only currency
|
|
42
|
+
* and `buildRunFields` stays the only reader of JSON Schema. Absent whenever
|
|
43
|
+
* the value is already the whole content (a structured concept, a file, a
|
|
44
|
+
* child property of a structure): wrapping those would double-nest them.
|
|
45
|
+
*/
|
|
46
|
+
contentKey?: string;
|
|
33
47
|
}
|
|
34
48
|
interface TextRunField extends RunFieldCommon {
|
|
35
49
|
kind: 'text';
|
|
@@ -75,6 +89,33 @@ interface ListRunField extends RunFieldCommon {
|
|
|
75
89
|
kind: 'list';
|
|
76
90
|
/** The element descriptor (its `name` is unused; the index labels items). */
|
|
77
91
|
item: RunField;
|
|
92
|
+
/**
|
|
93
|
+
* The FEWEST items the slot accepts, when the schema states a lower bound.
|
|
94
|
+
* Absent for a variable `Concept[]` list, which demands none.
|
|
95
|
+
*
|
|
96
|
+
* Read off the array schema's `minItems` rather than off the contract's
|
|
97
|
+
* `item_count`, which states the same number: this exists so `fieldFilled` can
|
|
98
|
+
* answer the question **ajv** answers, and `minItems` is the keyword ajv
|
|
99
|
+
* reads. pipelex emits `minItems`/`maxItems` = N for a `[N]` slot and neither
|
|
100
|
+
* for `[]`, so on a top-level slot the two sources agree by construction.
|
|
101
|
+
*
|
|
102
|
+
* A schema may still state a lower bound alone - `mapSchema` recurses, so a
|
|
103
|
+
* nested array inside a structured concept reaches here with whatever its
|
|
104
|
+
* model declared and no MTHDS multiplicity behind it. Gating on that bound is
|
|
105
|
+
* the same rule, and it is the direction that cannot leave readiness more
|
|
106
|
+
* permissive than the gate.
|
|
107
|
+
*/
|
|
108
|
+
itemCount?: number;
|
|
109
|
+
/**
|
|
110
|
+
* The MOST items the slot accepts, off the schema's `maxItems`.
|
|
111
|
+
*
|
|
112
|
+
* A separate field because it is a separate fact, and conflating them is a
|
|
113
|
+
* bug that hides: `itemCount` was read as a minimum by readiness and as a
|
|
114
|
+
* maximum by the control that stops offering `Add`, which agree only while
|
|
115
|
+
* a contract states both bounds equal. A list told "at least two" was then
|
|
116
|
+
* presented as a list of exactly two.
|
|
117
|
+
*/
|
|
118
|
+
maxItemCount?: number;
|
|
78
119
|
}
|
|
79
120
|
interface UnknownRunField extends RunFieldCommon {
|
|
80
121
|
kind: 'unknown';
|
|
@@ -84,4 +125,4 @@ type RunField = TextRunField | ProseRunField | DateRunField | NumberRunField | B
|
|
|
84
125
|
type ConceptCategory = 'text' | 'date' | 'document' | 'image' | 'number' | 'boolean' | 'choice' | 'structured' | 'list';
|
|
85
126
|
declare function conceptCategory(field: RunField): ConceptCategory;
|
|
86
127
|
|
|
87
|
-
export { type BooleanRunField
|
|
128
|
+
export { type BooleanRunField, type ConceptCategory, type DateRunField, type EnumRunField, type FileRunField, type ListRunField, type NumberRunField, type ObjectRunField, type ProseRunField, type RunField, type RunFieldCommon, type RunFieldKind, type TextRunField, type UnknownRunField, conceptCategory };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"descriptor.js"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One validation error, in the shape hosts read (`property`, `message`,
|
|
3
|
+
* `name`, `stack`, `params.format`). Structurally a superset-compatible twin of
|
|
4
|
+
* RJSF's `RJSFValidationError`, so a host surface still holding RJSF form errors
|
|
5
|
+
* (an RJSF-based inputs panel) can hand them to the same message renderer.
|
|
6
|
+
*/
|
|
7
|
+
interface RunInputError {
|
|
8
|
+
/** The ajv keyword that failed (`required`, `format`, `type`, …). */
|
|
9
|
+
name?: string;
|
|
10
|
+
/** Dotted path into the form data (`.quote_date.date`); for a `required`
|
|
11
|
+
* error the missing property name is appended (top-level: no leading dot). */
|
|
12
|
+
property?: string;
|
|
13
|
+
message?: string;
|
|
14
|
+
params?: Record<string, unknown>;
|
|
15
|
+
/** The human line: `property message`, or `'title' message` when the parent
|
|
16
|
+
* schema titles the field. */
|
|
17
|
+
stack: string;
|
|
18
|
+
schemaPath?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Validate `data` against `schema`, returning mapped errors (empty = valid).
|
|
22
|
+
* MUTATES `data` where ajv coerces (`"20"` → `20`) - deliberate and relied on:
|
|
23
|
+
* the string the user typed is stored as a number going forward.
|
|
24
|
+
*/
|
|
25
|
+
declare function validateRunInputsSchema(data: unknown, schema: object): RunInputError[];
|
|
26
|
+
|
|
27
|
+
export { type RunInputError, validateRunInputsSchema };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"gate-validator.js"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { RunInputError } from './gate-validator.js';
|
|
2
|
+
import { PipeInputContract, PipeIOContract } from './contracts.js';
|
|
3
|
+
|
|
4
|
+
type Dict = Record<string, unknown>;
|
|
5
|
+
/**
|
|
6
|
+
* Combine the per-input schemas into one object schema.
|
|
7
|
+
*
|
|
8
|
+
* Each input variable becomes a property, titled with the variable name and
|
|
9
|
+
* described with the concept code. Only the inputs the method actually demands
|
|
10
|
+
* land in `required` - an optional (`?`) or variable-plural (`[]`) input must
|
|
11
|
+
* not block the form (see `inputMustBeFilled`).
|
|
12
|
+
*
|
|
13
|
+
* The per-input schema travels verbatim, which is how a fixed-count (`[N]`)
|
|
14
|
+
* list's declared count reaches ajv: pipelex states it as `minItems`/`maxItems`
|
|
15
|
+
* on the array wrapper, so the count is enforced here without the kernel
|
|
16
|
+
* restating it.
|
|
17
|
+
*/
|
|
18
|
+
declare function buildRunInputsSchema(inputs: Record<string, PipeInputContract>): Dict;
|
|
19
|
+
/**
|
|
20
|
+
* Last-gate repair, in two passes against the exact schema ajv validates.
|
|
21
|
+
*
|
|
22
|
+
* 1. **HEAL** - persisted `inputData` may still carry the legacy double-wrapped
|
|
23
|
+
* `{ text: { text } }` shape (or a form's state may lag a store fix).
|
|
24
|
+
* 2. **PRUNE** - RJSF fills every unset string with `""` on mount, which an
|
|
25
|
+
* optional CONSTRAINED field rejects (`DateContent.time` is `format: "time"`)
|
|
26
|
+
* - blocking a run on a field the user never opened. An absent optional field
|
|
27
|
+
* is what pipelex means by `None` anyway, so dropping it is the semantically
|
|
28
|
+
* correct repair, not a validation dodge.
|
|
29
|
+
*/
|
|
30
|
+
declare function prepareRunInputs(data: Dict, schema: Dict): Dict;
|
|
31
|
+
interface RunInputsVerdict {
|
|
32
|
+
isValid: boolean;
|
|
33
|
+
/** Variable names the scan could pin a missing required field on. */
|
|
34
|
+
missingInputs: string[];
|
|
35
|
+
/** Raw ajv errors, for when the scan cannot name anything. */
|
|
36
|
+
errors: RunInputError[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Validate PREPARED data against the combined schema.
|
|
40
|
+
*
|
|
41
|
+
* `missingInputs` is reported by VARIABLE NAME - the name on the node the user
|
|
42
|
+
* clicks - never by `concept_ref`, which used to produce "Missing required
|
|
43
|
+
* fields in: native.Text" and named neither the input at fault nor, when several
|
|
44
|
+
* inputs share a concept, which of them. Inputs the method declared omittable
|
|
45
|
+
* are skipped: an empty `?` input is not a missing one.
|
|
46
|
+
*
|
|
47
|
+
* The scan can come up empty even on an invalid form (a wrong value shape, a
|
|
48
|
+
* nested mismatch); `errors` is what the caller falls back to then, so a failure
|
|
49
|
+
* is never undiagnosable.
|
|
50
|
+
*
|
|
51
|
+
* `preparedData` is `unknown` for the same reason `gateRunInputs`' `data` is: on
|
|
52
|
+
* a public endpoint the body is whatever was sent, and ajv must be shown that
|
|
53
|
+
* rather than a repair of it, or `must be object` is a verdict no caller can
|
|
54
|
+
* ever receive. The name-the-variable scan below needs something indexable, so
|
|
55
|
+
* a body that is not a record scans against nothing and names every input the
|
|
56
|
+
* method demands - which is the honest answer for a body that carried none.
|
|
57
|
+
*/
|
|
58
|
+
declare function validateRunInputs(preparedData: unknown, inputs: Record<string, PipeInputContract>, schema: Dict): RunInputsVerdict;
|
|
59
|
+
/**
|
|
60
|
+
* Build the `{ concept, content }` map a run expects, from PREPARED data.
|
|
61
|
+
*
|
|
62
|
+
* The two ways a method says "this may be nothing" land differently on the wire:
|
|
63
|
+
* - an **optional (`?`)** input left blank is OMITTED, so the runtime records a
|
|
64
|
+
* real absence the method can branch on - sending `{ text: "" }` would look
|
|
65
|
+
* like the caller supplied an empty string;
|
|
66
|
+
* - a **plural (`[]`)** input keeps its key, because a plural slot is never
|
|
67
|
+
* absent - its empty form IS the empty list, and the runtime requires the key.
|
|
68
|
+
* When that list is EMPTY it is sent BARE, without the envelope: the envelope
|
|
69
|
+
* is the runtime's "explicit form", which bypasses the top-down shaper and
|
|
70
|
+
* hands the value to the bottom-up factory, and that factory types a list from
|
|
71
|
+
* its first item - so an empty list there raises "Cannot create Stuff from
|
|
72
|
+
* empty list in content". The bare form keeps the shaper, which reads the
|
|
73
|
+
* DECLARED concept and builds the empty list correctly. (pipelex/#1096 makes
|
|
74
|
+
* the envelope agree; the bare form runs today and stays correct after.)
|
|
75
|
+
*
|
|
76
|
+
* A fixed-count (`[N]`) list takes that same empty-list path, and an empty one
|
|
77
|
+
* is not a payload the method can accept. It is unreachable through the gate,
|
|
78
|
+
* which demands the input and rejects a short list on `minItems`; building the
|
|
79
|
+
* payload straight from unvalidated data is what would reach it, and inventing
|
|
80
|
+
* a different absence here would only hide that.
|
|
81
|
+
*/
|
|
82
|
+
declare function apiInputsFromSchemaData(preparedData: Dict, inputs: Record<string, PipeInputContract>): Dict;
|
|
83
|
+
/** The gate's verdict: the payload to send, or why the run may not start. */
|
|
84
|
+
type RunInputsGateResult = {
|
|
85
|
+
ok: true;
|
|
86
|
+
inputs: Dict;
|
|
87
|
+
} | {
|
|
88
|
+
ok: false;
|
|
89
|
+
/** Variable names the caller left empty or short. */
|
|
90
|
+
missingInputs: string[];
|
|
91
|
+
/** Raw ajv errors, for when the scan cannot name anything. */
|
|
92
|
+
errors: RunInputError[];
|
|
93
|
+
/** The repaired data the verdict was reached on - what
|
|
94
|
+
* `describeValidationError` needs to quote the value it received. */
|
|
95
|
+
preparedData: Dict;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Gate a run: repair the caller's data, validate it against the contract,
|
|
99
|
+
* refuse anything the Run button would have refused, and build the payload.
|
|
100
|
+
*
|
|
101
|
+
* Returns a verdict rather than throwing. A server endpoint must not throw
|
|
102
|
+
* across the boundary to its client - frameworks routinely strip the message to
|
|
103
|
+
* an opaque digest in a production build - and a rejection here is an ordinary
|
|
104
|
+
* outcome, not an exceptional one.
|
|
105
|
+
*
|
|
106
|
+
* **`data` is `unknown` because that is what it is.** A run endpoint is public
|
|
107
|
+
* and no framework enforces a declared parameter type, so the argument is
|
|
108
|
+
* whatever the caller put in the body. The chain indexes the payload by
|
|
109
|
+
* variable name without first checking it is indexable, so a `null` body would
|
|
110
|
+
* throw *after* ajv had already reported `must be object` and before any
|
|
111
|
+
* verdict came back.
|
|
112
|
+
*
|
|
113
|
+
* So the two uses are separated rather than collapsed into one repair. **ajv
|
|
114
|
+
* judges the value the caller actually sent**, which is what makes `must be
|
|
115
|
+
* object` the verdict for a body that is not one; the indexing that follows
|
|
116
|
+
* uses a safe `{}` stand-in, which is what keeps the gate from throwing. Repair
|
|
117
|
+
* FIRST - coercing a non-object to `{}` before validating - is the shape that
|
|
118
|
+
* looks equivalent and is not: a contract whose inputs are all optional has an
|
|
119
|
+
* empty `required` list, so `{}` validates, and `gateRunInputs("garbage", …)`
|
|
120
|
+
* came back `ok: true` on a body the caller never meant as a run. Fail-closed
|
|
121
|
+
* costs a malformed caller an error it earned; the other direction bills a run.
|
|
122
|
+
*
|
|
123
|
+
* **The schema alone is not the rule.** ajv's `required` asserts only that a
|
|
124
|
+
* key is PRESENT, and a content model carries no `minLength` - so a required
|
|
125
|
+
* input that arrived empty (`{document: {url: ""}}`, `{text: {text: ""}}`)
|
|
126
|
+
* satisfies the schema. That is the natural payload, not a contrived one:
|
|
127
|
+
* `rjsfDataFromRunValues({}, fields)` emits exactly that when nothing is
|
|
128
|
+
* selected. So the gate re-applies the emptiness rule using
|
|
129
|
+
* `computeReadiness`'s OWN two functions over the same derived fields, which is
|
|
130
|
+
* the only way to be sure the two sides cannot disagree.
|
|
131
|
+
*
|
|
132
|
+
* Picking a pair that merely looks equivalent is not enough, and this is the
|
|
133
|
+
* whole reason the assembly lives here rather than in each host: the obvious
|
|
134
|
+
* choice, `inputMustBeFilled` + `isFilled`, agrees on every leaf kind and
|
|
135
|
+
* diverges on a structured concept in BOTH directions - `isFilled` on an object
|
|
136
|
+
* is `some(child filled)` where `fieldFilled` is `every(required child
|
|
137
|
+
* filled)`. That accepts a half-filled struct the browser refuses (a paid run
|
|
138
|
+
* past a disabled button) and rejects a filled all-optional struct the browser
|
|
139
|
+
* accepts. A host whose methods happen to use only native concepts has no test
|
|
140
|
+
* that can catch either.
|
|
141
|
+
*/
|
|
142
|
+
declare function gateRunInputs(contract: PipeIOContract, data: unknown): RunInputsGateResult;
|
|
143
|
+
|
|
144
|
+
export { type RunInputsGateResult, type RunInputsVerdict, apiInputsFromSchemaData, buildRunInputsSchema, gateRunInputs, prepareRunInputs, validateRunInputs };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { apiInputsFromSchemaData, buildRunInputsSchema, gateRunInputs, prepareRunInputs, validateRunInputs } from '../chunk-XEPD5VJQ.js';
|
|
2
|
+
import '../chunk-KFZ5MZOM.js';
|
|
3
|
+
import '../chunk-7BMOPXDY.js';
|
|
4
|
+
import '../chunk-PM55AHRO.js';
|
|
5
|
+
import '../chunk-VMLXO5JS.js';
|
|
6
|
+
import '../chunk-O4O3QNVC.js';
|
|
7
|
+
import '../chunk-HARYEWNG.js';
|
|
8
|
+
import '../chunk-V3OV2XQT.js';
|
|
9
|
+
import '../chunk-VTPUDBSJ.js';
|
|
10
|
+
import '../chunk-GKV77RAS.js';
|
|
11
|
+
import '../chunk-NMT7BRLO.js';
|
|
12
|
+
//# sourceMappingURL=gate.js.map
|
|
13
|
+
//# sourceMappingURL=gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"gate.js"}
|