@es-joy/jsoe 0.28.2 → 0.30.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/.claude/scheduled_tasks.lock +1 -0
- package/CHANGES.md +25 -0
- package/README.md +4 -0
- package/dist/formatAndTypeChoices.d.ts +6 -6
- package/dist/formatAndTypeChoices.d.ts.map +1 -1
- package/dist/formats/schema.d.ts +5 -0
- package/dist/formats/schema.d.ts.map +1 -1
- package/dist/formats.d.ts +2 -2
- package/dist/formats.d.ts.map +1 -1
- package/dist/fundamentalTypes/dateType.d.ts +26 -2
- package/dist/fundamentalTypes/dateType.d.ts.map +1 -1
- package/dist/fundamentalTypes/domexceptionType.d.ts +7 -0
- package/dist/fundamentalTypes/domexceptionType.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/jtltExtensions.d.ts +112 -0
- package/dist/jtltExtensions.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/arraySearchType.d.ts +22 -0
- package/dist/search/fundamentalTypes/arraySearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/bigintSearchType.d.ts +10 -0
- package/dist/search/fundamentalTypes/bigintSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/blobSearchType.d.ts +19 -0
- package/dist/search/fundamentalTypes/blobSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/booleanSearchType.d.ts +11 -0
- package/dist/search/fundamentalTypes/booleanSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/catchSearchType.d.ts +18 -0
- package/dist/search/fundamentalTypes/catchSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/dateSearchType.d.ts +15 -0
- package/dist/search/fundamentalTypes/dateSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/domexceptionSearchType.d.ts +16 -0
- package/dist/search/fundamentalTypes/domexceptionSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/enumSearchType.d.ts +26 -0
- package/dist/search/fundamentalTypes/enumSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/errorSearchType.d.ts +9 -0
- package/dist/search/fundamentalTypes/errorSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/fileSearchType.d.ts +28 -0
- package/dist/search/fundamentalTypes/fileSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/filelistSearchType.d.ts +24 -0
- package/dist/search/fundamentalTypes/filelistSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/functionSearchType.d.ts +18 -0
- package/dist/search/fundamentalTypes/functionSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/mapSearchType.d.ts +22 -0
- package/dist/search/fundamentalTypes/mapSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/nanSearchType.d.ts +7 -0
- package/dist/search/fundamentalTypes/nanSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/nullSearchType.d.ts +7 -0
- package/dist/search/fundamentalTypes/nullSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/numberSearchType.d.ts +11 -0
- package/dist/search/fundamentalTypes/numberSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/objectSearchType.d.ts +21 -0
- package/dist/search/fundamentalTypes/objectSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/promiseSearchType.d.ts +20 -0
- package/dist/search/fundamentalTypes/promiseSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/regexpSearchType.d.ts +20 -0
- package/dist/search/fundamentalTypes/regexpSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/setSearchType.d.ts +15 -0
- package/dist/search/fundamentalTypes/setSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/stringSearchType.d.ts +21 -0
- package/dist/search/fundamentalTypes/stringSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/symbolSearchType.d.ts +16 -0
- package/dist/search/fundamentalTypes/symbolSearchType.d.ts.map +1 -0
- package/dist/search/fundamentalTypes/undefinedSearchType.d.ts +7 -0
- package/dist/search/fundamentalTypes/undefinedSearchType.d.ts.map +1 -0
- package/dist/search/index.d.ts +70 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/queryTree.d.ts +12 -1
- package/dist/search/queryTree.d.ts.map +1 -1
- package/dist/search/queryTreeBuilders.d.ts +18 -0
- package/dist/search/queryTreeBuilders.d.ts.map +1 -1
- package/dist/search/searchDispatch.d.ts +44 -0
- package/dist/search/searchDispatch.d.ts.map +1 -1
- package/dist/search/searchElementUtils.d.ts +106 -0
- package/dist/search/searchElementUtils.d.ts.map +1 -0
- package/dist/search/searchUtils.d.ts +550 -0
- package/dist/search/searchUtils.d.ts.map +1 -0
- package/dist/search/subTypes/blobHTMLSearchType.d.ts +36 -0
- package/dist/search/subTypes/blobHTMLSearchType.d.ts.map +1 -0
- package/dist/search/subTypes/recordSearchType.d.ts +18 -0
- package/dist/search/subTypes/recordSearchType.d.ts.map +1 -0
- package/dist/search/subTypes/tupleSearchType.d.ts +21 -0
- package/dist/search/subTypes/tupleSearchType.d.ts.map +1 -0
- package/dist/search/superTypes/SpecialRealNumberSearchType.d.ts +14 -0
- package/dist/search/superTypes/SpecialRealNumberSearchType.d.ts.map +1 -0
- package/dist/search/superTypes/buffersourceSearchType.d.ts +17 -0
- package/dist/search/superTypes/buffersourceSearchType.d.ts.map +1 -0
- package/dist/search/superTypes/dommatrixSearchType.d.ts +11 -0
- package/dist/search/superTypes/dommatrixSearchType.d.ts.map +1 -0
- package/dist/search/superTypes/dompointSearchType.d.ts +9 -0
- package/dist/search/superTypes/dompointSearchType.d.ts.map +1 -0
- package/dist/search/superTypes/domrectSearchType.d.ts +9 -0
- package/dist/search/superTypes/domrectSearchType.d.ts.map +1 -0
- package/dist/search/superTypes/errorsSpecialSearchType.d.ts +11 -0
- package/dist/search/superTypes/errorsSpecialSearchType.d.ts.map +1 -0
- package/dist/search/unions/discriminatedUnionSearchType.d.ts +12 -0
- package/dist/search/unions/discriminatedUnionSearchType.d.ts.map +1 -0
- package/dist/search/unions/unionFamilySearchType.d.ts +36 -0
- package/dist/search/unions/unionFamilySearchType.d.ts.map +1 -0
- package/dist/search/unions/unionSearchType.d.ts +8 -0
- package/dist/search/unions/unionSearchType.d.ts.map +1 -0
- package/dist/search/unions/xorSearchType.d.ts +12 -0
- package/dist/search/unions/xorSearchType.d.ts.map +1 -0
- package/dist/superTypes/buffersourceType.d.ts.map +1 -1
- package/dist/typeChoices.d.ts +3 -3
- package/dist/typeChoices.d.ts.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -4
- package/pnpm-workspace.yaml +1 -1
- package/rollup.config.js +12 -0
- package/src/formatAndTypeChoices.js +4 -4
- package/src/formats/schema.js +1 -1
- package/src/formats.js +1 -1
- package/src/fundamentalTypes/dateType.js +40 -14
- package/src/fundamentalTypes/domexceptionType.js +41 -33
- package/src/fundamentalTypes/regexpType.js +1 -1
- package/src/index.js +6 -0
- package/src/jsoe.css +204 -0
- package/src/jtltExtensions.js +103 -0
- package/src/search/fundamentalTypes/arraySearchType.js +101 -0
- package/src/search/fundamentalTypes/bigintSearchType.js +68 -0
- package/src/search/fundamentalTypes/blobSearchType.js +42 -0
- package/src/search/fundamentalTypes/booleanSearchType.js +40 -0
- package/src/search/fundamentalTypes/catchSearchType.js +59 -0
- package/src/search/fundamentalTypes/dateSearchType.js +166 -0
- package/src/search/fundamentalTypes/domexceptionSearchType.js +84 -0
- package/src/search/fundamentalTypes/enumSearchType.js +62 -0
- package/src/search/fundamentalTypes/errorSearchType.js +11 -0
- package/src/search/fundamentalTypes/fileSearchType.js +94 -0
- package/src/search/fundamentalTypes/filelistSearchType.js +103 -0
- package/src/search/fundamentalTypes/functionSearchType.js +102 -0
- package/src/search/fundamentalTypes/mapSearchType.js +117 -0
- package/src/search/fundamentalTypes/nanSearchType.js +11 -0
- package/src/search/fundamentalTypes/nullSearchType.js +11 -0
- package/src/search/fundamentalTypes/numberSearchType.js +59 -0
- package/src/search/fundamentalTypes/objectSearchType.js +367 -0
- package/src/search/fundamentalTypes/promiseSearchType.js +61 -0
- package/src/search/fundamentalTypes/regexpSearchType.js +72 -0
- package/src/search/fundamentalTypes/setSearchType.js +91 -0
- package/src/search/fundamentalTypes/stringSearchType.js +44 -0
- package/src/search/fundamentalTypes/symbolSearchType.js +39 -0
- package/src/search/fundamentalTypes/undefinedSearchType.js +11 -0
- package/src/search/index.js +96 -0
- package/src/search/queryTree.js +244 -0
- package/src/search/queryTreeBuilders.js +233 -0
- package/src/search/searchDispatch.js +291 -0
- package/src/search/searchElementUtils.js +373 -0
- package/src/search/searchUtils.js +847 -0
- package/src/search/subTypes/blobHTMLSearchType.js +122 -0
- package/src/search/subTypes/recordSearchType.js +105 -0
- package/src/search/subTypes/tupleSearchType.js +152 -0
- package/src/search/superTypes/SpecialRealNumberSearchType.js +42 -0
- package/src/search/superTypes/buffersourceSearchType.js +53 -0
- package/src/search/superTypes/dommatrixSearchType.js +24 -0
- package/src/search/superTypes/dompointSearchType.js +15 -0
- package/src/search/superTypes/domrectSearchType.js +15 -0
- package/src/search/superTypes/errorsSpecialSearchType.js +15 -0
- package/src/search/unions/discriminatedUnionSearchType.js +16 -0
- package/src/search/unions/unionFamilySearchType.js +168 -0
- package/src/search/unions/unionSearchType.js +12 -0
- package/src/search/unions/xorSearchType.js +16 -0
- package/src/superTypes/buffersourceType.js +13 -15
- package/src/typeChoices.js +2 -2
- package/src/types.js +2 -2
- package/tsconfig-prod.json +12 -0
- package/tsconfig.json +5 -10
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The only runtime pieces for building `queryTree.js` nodes - every search
|
|
3
|
+
* module builds nodes through these factories rather than hand-rolling leaf
|
|
4
|
+
* objects, so tests can import the same constructors to build expected-value
|
|
5
|
+
* fixtures.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {import('./queryTree.js').QueryNode[]} nodes
|
|
10
|
+
* @returns {import('./queryTree.js').QueryAnd}
|
|
11
|
+
*/
|
|
12
|
+
export function makeAndNode (nodes) {
|
|
13
|
+
return {$and: nodes};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Combines the leaves a single widget contributes (e.g. a number leaf's
|
|
18
|
+
* range plus its separate "Is/Is Not Integer" check) into one `QueryNode`:
|
|
19
|
+
* drops any `undefined` (no constraint entered there), returns `undefined`
|
|
20
|
+
* if nothing is left, the bare node if only one is left, else an `$and` of
|
|
21
|
+
* the rest - so a widget with several independent controls still honors
|
|
22
|
+
* `getQuery`'s "`undefined` means no constraint" convention without every
|
|
23
|
+
* such widget re-implementing this collapsing logic itself.
|
|
24
|
+
* @param {(import('./queryTree.js').QueryNode|undefined)[]} nodes
|
|
25
|
+
* @returns {import('./queryTree.js').QueryNode|undefined}
|
|
26
|
+
*/
|
|
27
|
+
export function combineAnd (nodes) {
|
|
28
|
+
const filtered = /** @type {import('./queryTree.js').QueryNode[]} */ (
|
|
29
|
+
nodes.filter((node) => node !== undefined)
|
|
30
|
+
);
|
|
31
|
+
if (filtered.length === 0) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
if (filtered.length === 1) {
|
|
35
|
+
return filtered[0];
|
|
36
|
+
}
|
|
37
|
+
return makeAndNode(filtered);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {import('./queryTree.js').QueryNode[]} nodes
|
|
42
|
+
* @returns {import('./queryTree.js').QueryOr}
|
|
43
|
+
*/
|
|
44
|
+
export function makeOrNode (nodes) {
|
|
45
|
+
return {$or: nodes};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @param {string} path
|
|
50
|
+
* @param {boolean} $exists
|
|
51
|
+
* @returns {import('./queryTree.js').QueryHasPropertyLeaf}
|
|
52
|
+
*/
|
|
53
|
+
export function makeHasPropertyLeaf (path, $exists) {
|
|
54
|
+
return {kind: 'hasProperty', path, $exists};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {string} path
|
|
59
|
+
* @param {{
|
|
60
|
+
* $size?: number,
|
|
61
|
+
* $gt?: number, $gte?: number, $lt?: number, $lte?: number,
|
|
62
|
+
* sparseCheck?: boolean
|
|
63
|
+
* }} cfg
|
|
64
|
+
* @returns {import('./queryTree.js').QueryLengthSizeLeaf}
|
|
65
|
+
*/
|
|
66
|
+
export function makeLengthSizeLeaf (path, cfg = {}) {
|
|
67
|
+
return {kind: 'lengthSize', path, ...cfg};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @param {string} path
|
|
72
|
+
* @param {import('./queryTree.js').QueryRangeLeaf['valueType']} valueType
|
|
73
|
+
* @param {{
|
|
74
|
+
* $gt?: number|bigint|string, $gte?: number|bigint|string,
|
|
75
|
+
* $lt?: number|bigint|string, $lte?: number|bigint|string
|
|
76
|
+
* }} cfg
|
|
77
|
+
* @returns {import('./queryTree.js').QueryRangeLeaf}
|
|
78
|
+
*/
|
|
79
|
+
export function makeRangeLeaf (path, valueType, cfg = {}) {
|
|
80
|
+
return {kind: 'range', path, valueType, ...cfg};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @param {import('./queryTree.js').QueryNode} query
|
|
85
|
+
* @returns {import('./queryTree.js').QueryNotLeaf}
|
|
86
|
+
*/
|
|
87
|
+
export function makeNotLeaf (query) {
|
|
88
|
+
return {kind: 'not', query};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @param {string} path
|
|
93
|
+
* @param {boolean} isInteger
|
|
94
|
+
* @returns {import('./queryTree.js').QueryIntegerCheckLeaf}
|
|
95
|
+
*/
|
|
96
|
+
export function makeIntegerCheckLeaf (path, isInteger) {
|
|
97
|
+
return {kind: 'integerCheck', path, isInteger};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @param {string} path
|
|
102
|
+
* @param {boolean} isValid
|
|
103
|
+
* @returns {import('./queryTree.js').QueryValidDateCheckLeaf}
|
|
104
|
+
*/
|
|
105
|
+
export function makeValidDateCheckLeaf (path, isValid) {
|
|
106
|
+
return {kind: 'validDateCheck', path, isValid};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @param {string} path
|
|
111
|
+
* @param {{$in?: unknown[], $nin?: unknown[]}} cfg
|
|
112
|
+
* @returns {import('./queryTree.js').QueryLiteralSetLeaf}
|
|
113
|
+
*/
|
|
114
|
+
export function makeLiteralSetLeaf (path, cfg = {}) {
|
|
115
|
+
return {kind: 'literalSet', path, ...cfg};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @param {string} path
|
|
120
|
+
* @param {string} $regex
|
|
121
|
+
* @param {string} [$options]
|
|
122
|
+
* @returns {import('./queryTree.js').QueryRegexLeaf}
|
|
123
|
+
*/
|
|
124
|
+
export function makeRegexLeaf (path, $regex, $options) {
|
|
125
|
+
return {kind: 'regex', path, $regex, ...($options ? {$options} : {})};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @param {string} path
|
|
130
|
+
* @param {string} value
|
|
131
|
+
* @returns {import('./queryTree.js').QueryNotContainsLeaf}
|
|
132
|
+
*/
|
|
133
|
+
export function makeNotContainsLeaf (path, value) {
|
|
134
|
+
return {kind: 'notContains', path, value};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @param {string} path
|
|
139
|
+
* @param {{$in?: unknown[], $nin?: unknown[]}} cfg
|
|
140
|
+
* @returns {import('./queryTree.js').QueryMultiSelectLeaf}
|
|
141
|
+
*/
|
|
142
|
+
export function makeMultiSelectLeaf (path, cfg = {}) {
|
|
143
|
+
return {kind: 'multiSelect', path, ...cfg};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @param {string} path
|
|
148
|
+
* @param {boolean} matchKeys
|
|
149
|
+
* @param {unknown[]} values
|
|
150
|
+
* @returns {import('./queryTree.js').QueryKeyValueEnumLeaf}
|
|
151
|
+
*/
|
|
152
|
+
export function makeKeyValueEnumLeaf (path, matchKeys, values) {
|
|
153
|
+
return {kind: 'keyValueEnum', path, matchKeys, values};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* @param {string} path
|
|
158
|
+
* @param {string} searchType
|
|
159
|
+
* @param {unknown} [discriminatorValue]
|
|
160
|
+
* @returns {import('./queryTree.js').QueryTypeOfLeaf}
|
|
161
|
+
*/
|
|
162
|
+
export function makeTypeOfLeaf (path, searchType, discriminatorValue) {
|
|
163
|
+
return {
|
|
164
|
+
kind: 'typeOf',
|
|
165
|
+
path,
|
|
166
|
+
searchType,
|
|
167
|
+
...(discriminatorValue === undefined ? {} : {discriminatorValue})
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* @param {string} path
|
|
173
|
+
* @param {import('./queryTree.js').QueryBlobHTMLLeaf['mode']} mode
|
|
174
|
+
* @param {string} value
|
|
175
|
+
* @returns {import('./queryTree.js').QueryBlobHTMLLeaf}
|
|
176
|
+
*/
|
|
177
|
+
export function makeBlobHTMLLeaf (path, mode, value) {
|
|
178
|
+
return {kind: 'blobHTML', path, mode, value};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* @param {string} path
|
|
183
|
+
* @param {{[dimension: string]: import('./queryTree.js').QueryRangeLeaf}} dimensions
|
|
184
|
+
* @param {{readonlyCheck?: boolean, dimensionCheck?: 2|3}} [cfg]
|
|
185
|
+
* @returns {import('./queryTree.js').QueryDomShapeLeaf}
|
|
186
|
+
*/
|
|
187
|
+
export function makeDomShapeLeaf (path, dimensions, cfg = {}) {
|
|
188
|
+
return {kind: 'domShape', path, dimensions, ...cfg};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* @param {string} path
|
|
193
|
+
* @param {boolean} joint
|
|
194
|
+
* @param {import('./queryTree.js').QueryNode} [keyQuery]
|
|
195
|
+
* @param {import('./queryTree.js').QueryNode} [valueQuery]
|
|
196
|
+
* @returns {import('./queryTree.js').QueryMapRecordJointLeaf}
|
|
197
|
+
*/
|
|
198
|
+
export function makeMapRecordJointLeaf (path, joint, keyQuery, valueQuery) {
|
|
199
|
+
return {
|
|
200
|
+
kind: 'mapRecordJoint',
|
|
201
|
+
path,
|
|
202
|
+
joint,
|
|
203
|
+
...(keyQuery ? {keyQuery} : {}),
|
|
204
|
+
...(valueQuery ? {valueQuery} : {})
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* @param {string} path
|
|
210
|
+
* @param {import('./queryTree.js').QueryNode} [query]
|
|
211
|
+
* @returns {import('./queryTree.js').QueryPassThroughLeaf}
|
|
212
|
+
*/
|
|
213
|
+
export function makePassThroughLeaf (path, query) {
|
|
214
|
+
return {kind: 'passThrough', path, ...(query ? {query} : {})};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* @param {string} path
|
|
219
|
+
* @param {boolean} $exists
|
|
220
|
+
* @returns {import('./queryTree.js').QueryPresenceLeaf}
|
|
221
|
+
*/
|
|
222
|
+
export function makePresenceLeaf (path, $exists) {
|
|
223
|
+
return {kind: 'presence', path, $exists};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* @param {string} path
|
|
228
|
+
* @param {boolean} value
|
|
229
|
+
* @returns {import('./queryTree.js').QueryBooleanEqualsLeaf}
|
|
230
|
+
*/
|
|
231
|
+
export function makeBooleanEqualsLeaf (path, value) {
|
|
232
|
+
return {kind: 'booleanEquals', path, value};
|
|
233
|
+
}
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import {getSchemaType, getTypesForSchema} from '../formats/schema.js';
|
|
2
|
+
|
|
3
|
+
import dateSearchType from './fundamentalTypes/dateSearchType.js';
|
|
4
|
+
import numberSearchType from './fundamentalTypes/numberSearchType.js';
|
|
5
|
+
import bigintSearchType from './fundamentalTypes/bigintSearchType.js';
|
|
6
|
+
import stringSearchType from './fundamentalTypes/stringSearchType.js';
|
|
7
|
+
import regexpSearchType from './fundamentalTypes/regexpSearchType.js';
|
|
8
|
+
import booleanSearchType from './fundamentalTypes/booleanSearchType.js';
|
|
9
|
+
import symbolSearchType from './fundamentalTypes/symbolSearchType.js';
|
|
10
|
+
import undefinedSearchType from './fundamentalTypes/undefinedSearchType.js';
|
|
11
|
+
import nullSearchType from './fundamentalTypes/nullSearchType.js';
|
|
12
|
+
import nanSearchType from './fundamentalTypes/nanSearchType.js';
|
|
13
|
+
import enumSearchType from './fundamentalTypes/enumSearchType.js';
|
|
14
|
+
import arraySearchType from './fundamentalTypes/arraySearchType.js';
|
|
15
|
+
import setSearchType from './fundamentalTypes/setSearchType.js';
|
|
16
|
+
import objectSearchType from './fundamentalTypes/objectSearchType.js';
|
|
17
|
+
import filelistSearchType from './fundamentalTypes/filelistSearchType.js';
|
|
18
|
+
import tupleSearchType from './subTypes/tupleSearchType.js';
|
|
19
|
+
import recordSearchType from './subTypes/recordSearchType.js';
|
|
20
|
+
import mapSearchType from './fundamentalTypes/mapSearchType.js';
|
|
21
|
+
import promiseSearchType from './fundamentalTypes/promiseSearchType.js';
|
|
22
|
+
import catchSearchType from './fundamentalTypes/catchSearchType.js';
|
|
23
|
+
import functionSearchType from './fundamentalTypes/functionSearchType.js';
|
|
24
|
+
import fileSearchType from './fundamentalTypes/fileSearchType.js';
|
|
25
|
+
import blobSearchType from './fundamentalTypes/blobSearchType.js';
|
|
26
|
+
import unionSearchType from './unions/unionSearchType.js';
|
|
27
|
+
import xorSearchType from './unions/xorSearchType.js';
|
|
28
|
+
import discriminatedUnionSearchType from './unions/discriminatedUnionSearchType.js';
|
|
29
|
+
import errorSearchType from './fundamentalTypes/errorSearchType.js';
|
|
30
|
+
import errorsSpecialSearchType from './superTypes/errorsSpecialSearchType.js';
|
|
31
|
+
import domexceptionSearchType from './fundamentalTypes/domexceptionSearchType.js';
|
|
32
|
+
import domrectSearchType from './superTypes/domrectSearchType.js';
|
|
33
|
+
import dompointSearchType from './superTypes/dompointSearchType.js';
|
|
34
|
+
import dommatrixSearchType from './superTypes/dommatrixSearchType.js';
|
|
35
|
+
import SpecialRealNumberSearchType from './superTypes/SpecialRealNumberSearchType.js';
|
|
36
|
+
import buffersourceSearchType from './superTypes/buffersourceSearchType.js';
|
|
37
|
+
import blobHTMLSearchType from './subTypes/blobHTMLSearchType.js';
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @typedef {import('./queryTree.js').QueryNode} QueryNode
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The search-side analogue of `TypeObject` (`src/types.js:308-408`): two
|
|
45
|
+
* methods, `buildUI` (a `jml` array) and `getQuery` (reads the built DOM
|
|
46
|
+
* back into a `QueryNode`, or `undefined` when no constraint was entered).
|
|
47
|
+
* @typedef {{
|
|
48
|
+
* buildUI: (cfg: {
|
|
49
|
+
* schemaObject: import('../formats/schema.js').ZodexSchema,
|
|
50
|
+
* path: string,
|
|
51
|
+
* typeNamespace?: string,
|
|
52
|
+
* topRoot?: import('../types.js').RootElement,
|
|
53
|
+
* types?: import('../types.js').default,
|
|
54
|
+
* originalJSON?: import('../formats/schema.js').ZodexSchema
|
|
55
|
+
* }) => import('../types.js').JamilihArray,
|
|
56
|
+
* getQuery: (cfg: {
|
|
57
|
+
* root: HTMLElement,
|
|
58
|
+
* path: string
|
|
59
|
+
* }) => QueryNode|undefined
|
|
60
|
+
* }} SearchTypeObject
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Temporary placeholder used while a given search type's real module is
|
|
65
|
+
* still to-do (build order, `docs/proposals/search-plan.md` §6). Renders a
|
|
66
|
+
* plainly-labelled marker rather than throwing, so the full dispatch table
|
|
67
|
+
* is exercisable end-to-end before every leaf/composite is implemented.
|
|
68
|
+
* @param {string} searchSchemaType
|
|
69
|
+
* @returns {SearchTypeObject}
|
|
70
|
+
*/
|
|
71
|
+
function stubSearchType (searchSchemaType) {
|
|
72
|
+
return {
|
|
73
|
+
buildUI: () => ['span', [`TODO: ${searchSchemaType}`]],
|
|
74
|
+
getQuery: () => undefined
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Escape hatch for `instanceof`-outside-`FileList` and any schema shape not
|
|
80
|
+
* (yet) recognized: no widget is rendered for it, only this stand-in.
|
|
81
|
+
* @type {SearchTypeObject}
|
|
82
|
+
*/
|
|
83
|
+
const noneditableSearchType = stubSearchType('noneditable');
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* `Record<string, SearchTypeObject>` registry, analogous to
|
|
87
|
+
* `Types.prototype.availableTypes` (`src/types.js:473-581`). Every entry is
|
|
88
|
+
* a stub for now (build order step 1); later steps replace individual
|
|
89
|
+
* entries with their real `*SearchType.js` module, one at a time, without
|
|
90
|
+
* touching this shape.
|
|
91
|
+
*
|
|
92
|
+
* A few keys deliberately share one module reference rather than getting
|
|
93
|
+
* their own: `BooleanObject`/`NumberObject`/`StringObject`/`bigintObject`
|
|
94
|
+
* point at their primitive counterpart's module because a search leaf only
|
|
95
|
+
* cares about the query semantics (e.g. "true or false"), never about how
|
|
96
|
+
* the value-editing side constructs the boxed wrapper at runtime. Likewise
|
|
97
|
+
* `arrayNonindexKeys` mirrors `array`, `looseRecord` mirrors `record`, and
|
|
98
|
+
* `templateLiteral` mirrors `string` (README: a template literal is still
|
|
99
|
+
* fundamentally a string-shape constraint for this pass; see §3 of the
|
|
100
|
+
* search plan).
|
|
101
|
+
* @type {{[key: string]: SearchTypeObject}}
|
|
102
|
+
*/
|
|
103
|
+
const availableSearchTypes = {
|
|
104
|
+
// fundamentalTypes
|
|
105
|
+
date: dateSearchType,
|
|
106
|
+
number: numberSearchType,
|
|
107
|
+
NumberObject: numberSearchType,
|
|
108
|
+
bigint: bigintSearchType,
|
|
109
|
+
bigintObject: bigintSearchType,
|
|
110
|
+
string: stringSearchType,
|
|
111
|
+
StringObject: stringSearchType,
|
|
112
|
+
regexp: regexpSearchType,
|
|
113
|
+
boolean: booleanSearchType,
|
|
114
|
+
BooleanObject: booleanSearchType,
|
|
115
|
+
symbol: symbolSearchType,
|
|
116
|
+
undef: undefinedSearchType,
|
|
117
|
+
null: nullSearchType,
|
|
118
|
+
nan: nanSearchType,
|
|
119
|
+
array: arraySearchType,
|
|
120
|
+
arrayNonindexKeys: arraySearchType,
|
|
121
|
+
object: objectSearchType,
|
|
122
|
+
map: mapSearchType,
|
|
123
|
+
set: setSearchType,
|
|
124
|
+
filelist: filelistSearchType,
|
|
125
|
+
file: fileSearchType,
|
|
126
|
+
blob: blobSearchType,
|
|
127
|
+
error: errorSearchType,
|
|
128
|
+
domexception: domexceptionSearchType,
|
|
129
|
+
promise: promiseSearchType,
|
|
130
|
+
function: functionSearchType,
|
|
131
|
+
enum: enumSearchType,
|
|
132
|
+
|
|
133
|
+
// subTypes
|
|
134
|
+
tuple: tupleSearchType,
|
|
135
|
+
record: recordSearchType,
|
|
136
|
+
looseRecord: recordSearchType,
|
|
137
|
+
blobHTML: blobHTMLSearchType,
|
|
138
|
+
|
|
139
|
+
// superTypes
|
|
140
|
+
domrect: domrectSearchType,
|
|
141
|
+
dompoint: dompointSearchType,
|
|
142
|
+
dommatrix: dommatrixSearchType,
|
|
143
|
+
errors: errorsSpecialSearchType,
|
|
144
|
+
SpecialNumber: stubSearchType('SpecialNumber'),
|
|
145
|
+
SpecialRealNumber: SpecialRealNumberSearchType,
|
|
146
|
+
buffersource: buffersourceSearchType,
|
|
147
|
+
|
|
148
|
+
// unions
|
|
149
|
+
union: unionSearchType,
|
|
150
|
+
xor: xorSearchType,
|
|
151
|
+
discriminatedUnion: discriminatedUnionSearchType,
|
|
152
|
+
|
|
153
|
+
// string-shape alias (§3)
|
|
154
|
+
templateLiteral: stringSearchType,
|
|
155
|
+
|
|
156
|
+
// `getSchemaType` has no case for `catch` at all (unlike `promise`/
|
|
157
|
+
// `function`, already in `zodexToStructuredCloningTypeMap`), so it's
|
|
158
|
+
// added as its own extra case in `getSearchSchemaType` below
|
|
159
|
+
catch: catchSearchType,
|
|
160
|
+
|
|
161
|
+
// escape hatch, also the fallback for any unrecognized/not-yet-supported
|
|
162
|
+
// schema shape (see `getSearchTypeObject`)
|
|
163
|
+
resurrectable: noneditableSearchType
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Schema-only analogue of `getSchemaType` (`src/formats/schema.js:145-166`).
|
|
168
|
+
* Must not reimplement that function's special-casing (stringbool pipe,
|
|
169
|
+
* `codec`/filelist, `instanceof`, `literal`, `enum`, `templateLiteral`,
|
|
170
|
+
* `getCheckedType` fallback) - it calls straight through to it, and only
|
|
171
|
+
* adds the extra shape distinctions `getSchemaType`'s own
|
|
172
|
+
* `AvailableArbitraryType` output collapses (tuple, record/looseRecord,
|
|
173
|
+
* union/xor/discriminatedUnion all currently reduce to `'array'`/`'object'`/
|
|
174
|
+
* nothing, per `zodexToStructuredCloningTypeMap`,
|
|
175
|
+
* `src/formats/schema.js:30-56`).
|
|
176
|
+
*
|
|
177
|
+
* Intersection schemas are deliberately not a case here - they're resolved
|
|
178
|
+
* before dispatch, by the search-widget walker calling `getTypesForSchema`
|
|
179
|
+
* (search plan §3), reusing jsoe's existing intersection-merging machinery
|
|
180
|
+
* rather than this function reinventing it.
|
|
181
|
+
* @param {import('../formats/schema.js').ZodexSchema} schemaObject
|
|
182
|
+
* @returns {string}
|
|
183
|
+
*/
|
|
184
|
+
export function getSearchSchemaType (schemaObject) {
|
|
185
|
+
if (schemaObject.type === 'tuple') {
|
|
186
|
+
return 'tuple';
|
|
187
|
+
}
|
|
188
|
+
if (schemaObject.type === 'record' || schemaObject.type === 'looseRecord') {
|
|
189
|
+
return schemaObject.type;
|
|
190
|
+
}
|
|
191
|
+
if (['union', 'xor', 'discriminatedUnion'].includes(schemaObject.type)) {
|
|
192
|
+
return schemaObject.type;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// An `enum` control can show a multiple-select list and template literal
|
|
196
|
+
// parts might justify their own search controls, so need to detect
|
|
197
|
+
// these schema types.
|
|
198
|
+
if (['templateLiteral', 'enum'].includes(schemaObject.type)) {
|
|
199
|
+
return schemaObject.type;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// `getSchemaType` (`src/formats/schema.js`) has no `catch` case at all -
|
|
203
|
+
// its `zodexToStructuredCloningTypeMap` never mapped it, unlike
|
|
204
|
+
// `promise`/`function` - so it's added here rather than there, matching
|
|
205
|
+
// how tuple/record/union already extend the search-only shape space.
|
|
206
|
+
if (schemaObject.type === 'catch') {
|
|
207
|
+
return 'catch';
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return /** @type {string} */ (
|
|
211
|
+
getSchemaType(schemaObject)
|
|
212
|
+
); // inherits stringbool/codec/instanceof/checks handling verbatim
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* The one exported call site every recursive search widget uses (analogous
|
|
217
|
+
* to `types.getTypeObject(type)`, `src/types.js:1106-1108`, but schema-in
|
|
218
|
+
* rather than type-string-in, since there's no value to key off). Falls
|
|
219
|
+
* back to `noneditableSearchType` for any schema shape `getSearchSchemaType`
|
|
220
|
+
* reports that isn't (yet) registered, rather than throwing - the same
|
|
221
|
+
* escape hatch a bare top-level `instanceof` schema falls through to.
|
|
222
|
+
* @param {import('../formats/schema.js').ZodexSchema} schemaObject
|
|
223
|
+
* @returns {SearchTypeObject}
|
|
224
|
+
*/
|
|
225
|
+
export function getSearchTypeObject (schemaObject) {
|
|
226
|
+
const searchSchemaType = getSearchSchemaType(schemaObject);
|
|
227
|
+
return availableSearchTypes[searchSchemaType] ?? noneditableSearchType;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Intersection schemas are never registered in `availableSearchTypes` -
|
|
232
|
+
* resolved here instead of in `getSearchSchemaType`, reusing jsoe's
|
|
233
|
+
* existing intersection-merging machinery (`getTypesForSchema`,
|
|
234
|
+
* `src/formats/schema.js`) rather than reinventing it (search plan §3/§5).
|
|
235
|
+
* A single merged result replaces the intersection outright; more than one
|
|
236
|
+
* (e.g. one side of the intersection is itself a union) is handed to
|
|
237
|
+
* `unionSearchType.js` unchanged via a synthesized `union` wrapper, the
|
|
238
|
+
* same way `unionSearchType.js` already treats distinguishable branches.
|
|
239
|
+
* @param {import('../formats/schema.js').ZodexSchema} schemaObject
|
|
240
|
+
* @param {import('../formats/schema.js').ZodexSchema} originalJSON
|
|
241
|
+
* @returns {import('../formats/schema.js').ZodexSchema}
|
|
242
|
+
*/
|
|
243
|
+
function resolveIntersection (schemaObject, originalJSON) {
|
|
244
|
+
if (schemaObject.type !== 'intersection') {
|
|
245
|
+
return schemaObject;
|
|
246
|
+
}
|
|
247
|
+
const merged = [...getTypesForSchema(schemaObject, originalJSON)];
|
|
248
|
+
return merged.length === 1
|
|
249
|
+
? merged[0]
|
|
250
|
+
: /** @type {import('../formats/schema.js').ZodexSchema} */ (
|
|
251
|
+
/** @type {unknown} */ ({type: 'union', options: merged})
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* The call site every *recursive* search widget uses in place of calling
|
|
257
|
+
* `getSearchTypeObject(...).buildUI(...)` directly - it's the same thing,
|
|
258
|
+
* plus `resolveIntersection` run first, so an intersection schema at any
|
|
259
|
+
* depth (not just the one `buildSearchChoices` is called with) still
|
|
260
|
+
* resolves instead of falling through to the `noneditableSearchType`
|
|
261
|
+
* escape hatch. `originalJSON` (needed for the `getTypesForSchema` call's
|
|
262
|
+
* own `$ref` resolution) defaults to `schemaObject` itself only as a last
|
|
263
|
+
* resort for a call site that has none to pass down - every recursive
|
|
264
|
+
* caller should be threading the true document root through via its own
|
|
265
|
+
* `originalJSON` parameter instead.
|
|
266
|
+
* @param {{
|
|
267
|
+
* schemaObject: import('../formats/schema.js').ZodexSchema,
|
|
268
|
+
* path: string,
|
|
269
|
+
* typeNamespace?: string,
|
|
270
|
+
* topRoot?: import('../types.js').RootElement,
|
|
271
|
+
* types?: import('../types.js').default,
|
|
272
|
+
* originalJSON?: import('../formats/schema.js').ZodexSchema
|
|
273
|
+
* }} cfg
|
|
274
|
+
* @returns {import('../types.js').JamilihArray}
|
|
275
|
+
*/
|
|
276
|
+
export function buildSearchWidget ({
|
|
277
|
+
schemaObject, path, typeNamespace, topRoot, types, originalJSON
|
|
278
|
+
}) {
|
|
279
|
+
const resolvedOriginalJSON = originalJSON ?? schemaObject;
|
|
280
|
+
const resolvedSchema = resolveIntersection(schemaObject, resolvedOriginalJSON);
|
|
281
|
+
return getSearchTypeObject(resolvedSchema).buildUI({
|
|
282
|
+
schemaObject: resolvedSchema,
|
|
283
|
+
path,
|
|
284
|
+
typeNamespace,
|
|
285
|
+
topRoot,
|
|
286
|
+
types,
|
|
287
|
+
originalJSON: resolvedOriginalJSON
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export {availableSearchTypes, noneditableSearchType, resolveIntersection};
|