@es-joy/jsoe 0.28.2 → 0.29.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.
Files changed (163) hide show
  1. package/CHANGES.md +19 -0
  2. package/README.md +2 -0
  3. package/dist/formatAndTypeChoices.d.ts +6 -6
  4. package/dist/formatAndTypeChoices.d.ts.map +1 -1
  5. package/dist/formats/schema.d.ts +5 -0
  6. package/dist/formats/schema.d.ts.map +1 -1
  7. package/dist/formats.d.ts +2 -2
  8. package/dist/formats.d.ts.map +1 -1
  9. package/dist/fundamentalTypes/dateType.d.ts +21 -2
  10. package/dist/fundamentalTypes/dateType.d.ts.map +1 -1
  11. package/dist/fundamentalTypes/domexceptionType.d.ts +7 -0
  12. package/dist/fundamentalTypes/domexceptionType.d.ts.map +1 -1
  13. package/dist/index.d.ts +2 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +2 -2
  16. package/dist/index.js.map +1 -1
  17. package/dist/jtltExtensions.d.ts +112 -0
  18. package/dist/jtltExtensions.d.ts.map +1 -0
  19. package/dist/search/fundamentalTypes/arraySearchType.d.ts +15 -0
  20. package/dist/search/fundamentalTypes/arraySearchType.d.ts.map +1 -0
  21. package/dist/search/fundamentalTypes/bigintSearchType.d.ts +10 -0
  22. package/dist/search/fundamentalTypes/bigintSearchType.d.ts.map +1 -0
  23. package/dist/search/fundamentalTypes/blobSearchType.d.ts +19 -0
  24. package/dist/search/fundamentalTypes/blobSearchType.d.ts.map +1 -0
  25. package/dist/search/fundamentalTypes/booleanSearchType.d.ts +11 -0
  26. package/dist/search/fundamentalTypes/booleanSearchType.d.ts.map +1 -0
  27. package/dist/search/fundamentalTypes/catchSearchType.d.ts +18 -0
  28. package/dist/search/fundamentalTypes/catchSearchType.d.ts.map +1 -0
  29. package/dist/search/fundamentalTypes/dateSearchType.d.ts +10 -0
  30. package/dist/search/fundamentalTypes/dateSearchType.d.ts.map +1 -0
  31. package/dist/search/fundamentalTypes/domexceptionSearchType.d.ts +16 -0
  32. package/dist/search/fundamentalTypes/domexceptionSearchType.d.ts.map +1 -0
  33. package/dist/search/fundamentalTypes/enumSearchType.d.ts +22 -0
  34. package/dist/search/fundamentalTypes/enumSearchType.d.ts.map +1 -0
  35. package/dist/search/fundamentalTypes/errorSearchType.d.ts +9 -0
  36. package/dist/search/fundamentalTypes/errorSearchType.d.ts.map +1 -0
  37. package/dist/search/fundamentalTypes/fileSearchType.d.ts +19 -0
  38. package/dist/search/fundamentalTypes/fileSearchType.d.ts.map +1 -0
  39. package/dist/search/fundamentalTypes/filelistSearchType.d.ts +32 -0
  40. package/dist/search/fundamentalTypes/filelistSearchType.d.ts.map +1 -0
  41. package/dist/search/fundamentalTypes/functionSearchType.d.ts +18 -0
  42. package/dist/search/fundamentalTypes/functionSearchType.d.ts.map +1 -0
  43. package/dist/search/fundamentalTypes/mapSearchType.d.ts +18 -0
  44. package/dist/search/fundamentalTypes/mapSearchType.d.ts.map +1 -0
  45. package/dist/search/fundamentalTypes/nanSearchType.d.ts +7 -0
  46. package/dist/search/fundamentalTypes/nanSearchType.d.ts.map +1 -0
  47. package/dist/search/fundamentalTypes/nullSearchType.d.ts +7 -0
  48. package/dist/search/fundamentalTypes/nullSearchType.d.ts.map +1 -0
  49. package/dist/search/fundamentalTypes/numberSearchType.d.ts +11 -0
  50. package/dist/search/fundamentalTypes/numberSearchType.d.ts.map +1 -0
  51. package/dist/search/fundamentalTypes/objectSearchType.d.ts +15 -0
  52. package/dist/search/fundamentalTypes/objectSearchType.d.ts.map +1 -0
  53. package/dist/search/fundamentalTypes/promiseSearchType.d.ts +20 -0
  54. package/dist/search/fundamentalTypes/promiseSearchType.d.ts.map +1 -0
  55. package/dist/search/fundamentalTypes/regexpSearchType.d.ts +14 -0
  56. package/dist/search/fundamentalTypes/regexpSearchType.d.ts.map +1 -0
  57. package/dist/search/fundamentalTypes/setSearchType.d.ts +14 -0
  58. package/dist/search/fundamentalTypes/setSearchType.d.ts.map +1 -0
  59. package/dist/search/fundamentalTypes/stringSearchType.d.ts +13 -0
  60. package/dist/search/fundamentalTypes/stringSearchType.d.ts.map +1 -0
  61. package/dist/search/fundamentalTypes/symbolSearchType.d.ts +16 -0
  62. package/dist/search/fundamentalTypes/symbolSearchType.d.ts.map +1 -0
  63. package/dist/search/fundamentalTypes/undefinedSearchType.d.ts +7 -0
  64. package/dist/search/fundamentalTypes/undefinedSearchType.d.ts.map +1 -0
  65. package/dist/search/index.d.ts +60 -0
  66. package/dist/search/index.d.ts.map +1 -0
  67. package/dist/search/queryTree.d.ts.map +1 -1
  68. package/dist/search/queryTreeBuilders.d.ts +12 -0
  69. package/dist/search/queryTreeBuilders.d.ts.map +1 -1
  70. package/dist/search/searchDispatch.d.ts +44 -0
  71. package/dist/search/searchDispatch.d.ts.map +1 -1
  72. package/dist/search/searchElementUtils.d.ts +97 -0
  73. package/dist/search/searchElementUtils.d.ts.map +1 -0
  74. package/dist/search/searchUtils.d.ts +225 -0
  75. package/dist/search/searchUtils.d.ts.map +1 -0
  76. package/dist/search/subTypes/blobHTMLSearchType.d.ts +16 -0
  77. package/dist/search/subTypes/blobHTMLSearchType.d.ts.map +1 -0
  78. package/dist/search/subTypes/recordSearchType.d.ts +18 -0
  79. package/dist/search/subTypes/recordSearchType.d.ts.map +1 -0
  80. package/dist/search/subTypes/tupleSearchType.d.ts +21 -0
  81. package/dist/search/subTypes/tupleSearchType.d.ts.map +1 -0
  82. package/dist/search/superTypes/SpecialRealNumberSearchType.d.ts +14 -0
  83. package/dist/search/superTypes/SpecialRealNumberSearchType.d.ts.map +1 -0
  84. package/dist/search/superTypes/buffersourceSearchType.d.ts +17 -0
  85. package/dist/search/superTypes/buffersourceSearchType.d.ts.map +1 -0
  86. package/dist/search/superTypes/dommatrixSearchType.d.ts +11 -0
  87. package/dist/search/superTypes/dommatrixSearchType.d.ts.map +1 -0
  88. package/dist/search/superTypes/dompointSearchType.d.ts +9 -0
  89. package/dist/search/superTypes/dompointSearchType.d.ts.map +1 -0
  90. package/dist/search/superTypes/domrectSearchType.d.ts +9 -0
  91. package/dist/search/superTypes/domrectSearchType.d.ts.map +1 -0
  92. package/dist/search/superTypes/errorsSpecialSearchType.d.ts +11 -0
  93. package/dist/search/superTypes/errorsSpecialSearchType.d.ts.map +1 -0
  94. package/dist/search/unions/discriminatedUnionSearchType.d.ts +12 -0
  95. package/dist/search/unions/discriminatedUnionSearchType.d.ts.map +1 -0
  96. package/dist/search/unions/unionFamilySearchType.d.ts +36 -0
  97. package/dist/search/unions/unionFamilySearchType.d.ts.map +1 -0
  98. package/dist/search/unions/unionSearchType.d.ts +8 -0
  99. package/dist/search/unions/unionSearchType.d.ts.map +1 -0
  100. package/dist/search/unions/xorSearchType.d.ts +12 -0
  101. package/dist/search/unions/xorSearchType.d.ts.map +1 -0
  102. package/dist/superTypes/buffersourceType.d.ts.map +1 -1
  103. package/dist/typeChoices.d.ts +3 -3
  104. package/dist/typeChoices.d.ts.map +1 -1
  105. package/dist/types.d.ts +3 -3
  106. package/dist/types.d.ts.map +1 -1
  107. package/package.json +5 -4
  108. package/pnpm-workspace.yaml +1 -1
  109. package/rollup.config.js +12 -0
  110. package/src/formatAndTypeChoices.js +4 -4
  111. package/src/formats/schema.js +1 -1
  112. package/src/formats.js +1 -1
  113. package/src/fundamentalTypes/dateType.js +35 -14
  114. package/src/fundamentalTypes/domexceptionType.js +41 -33
  115. package/src/index.js +6 -0
  116. package/src/jtltExtensions.js +103 -0
  117. package/src/search/fundamentalTypes/arraySearchType.js +66 -0
  118. package/src/search/fundamentalTypes/bigintSearchType.js +62 -0
  119. package/src/search/fundamentalTypes/blobSearchType.js +41 -0
  120. package/src/search/fundamentalTypes/booleanSearchType.js +40 -0
  121. package/src/search/fundamentalTypes/catchSearchType.js +59 -0
  122. package/src/search/fundamentalTypes/dateSearchType.js +73 -0
  123. package/src/search/fundamentalTypes/domexceptionSearchType.js +55 -0
  124. package/src/search/fundamentalTypes/enumSearchType.js +58 -0
  125. package/src/search/fundamentalTypes/errorSearchType.js +11 -0
  126. package/src/search/fundamentalTypes/fileSearchType.js +41 -0
  127. package/src/search/fundamentalTypes/filelistSearchType.js +78 -0
  128. package/src/search/fundamentalTypes/functionSearchType.js +78 -0
  129. package/src/search/fundamentalTypes/mapSearchType.js +87 -0
  130. package/src/search/fundamentalTypes/nanSearchType.js +11 -0
  131. package/src/search/fundamentalTypes/nullSearchType.js +11 -0
  132. package/src/search/fundamentalTypes/numberSearchType.js +52 -0
  133. package/src/search/fundamentalTypes/objectSearchType.js +148 -0
  134. package/src/search/fundamentalTypes/promiseSearchType.js +61 -0
  135. package/src/search/fundamentalTypes/regexpSearchType.js +48 -0
  136. package/src/search/fundamentalTypes/setSearchType.js +65 -0
  137. package/src/search/fundamentalTypes/stringSearchType.js +35 -0
  138. package/src/search/fundamentalTypes/symbolSearchType.js +38 -0
  139. package/src/search/fundamentalTypes/undefinedSearchType.js +11 -0
  140. package/src/search/index.js +79 -0
  141. package/src/search/queryTree.js +235 -0
  142. package/src/search/queryTreeBuilders.js +224 -0
  143. package/src/search/searchDispatch.js +291 -0
  144. package/src/search/searchElementUtils.js +289 -0
  145. package/src/search/searchUtils.js +355 -0
  146. package/src/search/subTypes/blobHTMLSearchType.js +65 -0
  147. package/src/search/subTypes/recordSearchType.js +84 -0
  148. package/src/search/subTypes/tupleSearchType.js +111 -0
  149. package/src/search/superTypes/SpecialRealNumberSearchType.js +42 -0
  150. package/src/search/superTypes/buffersourceSearchType.js +47 -0
  151. package/src/search/superTypes/dommatrixSearchType.js +24 -0
  152. package/src/search/superTypes/dompointSearchType.js +15 -0
  153. package/src/search/superTypes/domrectSearchType.js +15 -0
  154. package/src/search/superTypes/errorsSpecialSearchType.js +15 -0
  155. package/src/search/unions/discriminatedUnionSearchType.js +16 -0
  156. package/src/search/unions/unionFamilySearchType.js +160 -0
  157. package/src/search/unions/unionSearchType.js +12 -0
  158. package/src/search/unions/xorSearchType.js +16 -0
  159. package/src/superTypes/buffersourceType.js +13 -15
  160. package/src/typeChoices.js +2 -2
  161. package/src/types.js +2 -2
  162. package/tsconfig-prod.json +12 -0
  163. package/tsconfig.json +5 -10
@@ -0,0 +1,235 @@
1
+ /**
2
+ * JSDoc-only typedefs for the schema-driven search query tree. No runtime
3
+ * exports live here; construct nodes through `queryTreeBuilders.js` instead
4
+ * so every search module (and every test fixture) goes through one place.
5
+ *
6
+ * Leaf `path` values reuse the existing JSON-Pointer convention from
7
+ * `src/utils/jsonPointer.js` (`makeJSONPointer`/`getJSONPointerParts`)
8
+ * rather than Mongo's dot-notation, so the search tree shares a path format
9
+ * with the rest of jsoe (e.g. `arrayType.js`'s `currentPath`).
10
+ *
11
+ * The leaf vocabulary borrows MongoDB's own operator names (`$and`/`$or`,
12
+ * `$gt`/`$gte`/`$lt`/`$lte`, `$in`/`$nin`, `$regex`/`$options`, `$exists`)
13
+ * wherever a leaf kind has a clean Mongo equivalent, so a host can adapt the
14
+ * common cases to `sift()` (or real MongoDB) almost for free - this is not a
15
+ * claim of full drop-in Mongo query-document compatibility: several
16
+ * jsoe-specific leaf kinds have no Mongo equivalent and stay custom, and
17
+ * every leaf keeps jsoe's own `kind`-discriminated, path-carrying shape
18
+ * rather than Mongo's field-keyed document shape.
19
+ *
20
+ * A path segment of `*` (e.g. `#/tags/*`) means "any element of the array
21
+ * at this point" - `arraySearchType.js`/`setSearchType.js`/`filelistSearchType.js`
22
+ * (element/value length/count constraint aside) and `tupleSearchType.js`'s
23
+ * `rest` portion use it when recursing into their element/value schema's
24
+ * own search widget, so a single nested leaf expresses "the collection
25
+ * contains at least one element matching this" (Mongo's `$elemMatch` is the
26
+ * natural translation target for a host walking a path that contains this
27
+ * segment) without needing a dedicated wrapper leaf kind - the collection's
28
+ * own `lengthSize` leaf and the recursed element leaf simply combine via
29
+ * `$and`. `recordSearchType.js`/`mapSearchType.js` similarly recurse into
30
+ * their `key`/`value` schemas at `*key`/`*value` segments, feeding the
31
+ * results into a single `mapRecordJoint` leaf (below) rather than combining
32
+ * via `$and`, since a host needs to know whether the two must match the
33
+ * same entry. `functionSearchType.js` recurses into its `input`/`output`
34
+ * schemas at `*args`/`*output` segments (the former itself a tuple, so its
35
+ * own per-position segments nest under `*args`), combined via `$and`.
36
+ * `promiseSearchType.js`/`catchSearchType.js` recurse into their wrapped
37
+ * value/`innerType` at the same path (there being exactly one value, no
38
+ * segment to add) and wrap the result in a `passThrough` leaf (below)
39
+ * rather than returning it bare, so the tree keeps visible that the leaf
40
+ * was reached through one of these transparent wrappers.
41
+ */
42
+
43
+ /**
44
+ * @typedef {{$and: QueryNode[]}} QueryAnd
45
+ */
46
+
47
+ /**
48
+ * @typedef {{$or: QueryNode[]}} QueryOr
49
+ */
50
+
51
+ /**
52
+ * `object` (via `$exists: true/false`).
53
+ * @typedef {{kind: 'hasProperty', path: string, $exists: boolean}} QueryHasPropertyLeaf
54
+ */
55
+
56
+ /**
57
+ * `array`/`set`/tuple-with-rest/`filelist` (via `$size`, or a range of
58
+ * operators when the schema doesn't pin an exact length), +`sparseCheck`
59
+ * for array sparse/not-sparse.
60
+ * @typedef {{
61
+ * kind: 'lengthSize',
62
+ * path: string,
63
+ * $size?: number,
64
+ * $gt?: number, $gte?: number, $lt?: number, $lte?: number,
65
+ * sparseCheck?: boolean
66
+ * }} QueryLengthSizeLeaf
67
+ */
68
+
69
+ /**
70
+ * `number`/`NumberObject`/`bigint`/`date`/`buffersource`, with `valueType`
71
+ * distinguishing them. Bounds are Mongo-style `$gt`/`$gte`/`$lt`/`$lte`
72
+ * rather than a `min`/`max` pair plus an inclusive boolean - inclusivity is
73
+ * simply which operator is present. The README's "Is Not Range" variant
74
+ * wraps the same leaf in `$not` rather than being a separate kind.
75
+ * @typedef {{
76
+ * kind: 'range',
77
+ * path: string,
78
+ * valueType: 'number'|'NumberObject'|'bigint'|'date'|'buffersource',
79
+ * $gt?: number|bigint|string,
80
+ * $gte?: number|bigint|string,
81
+ * $lt?: number|bigint|string,
82
+ * $lte?: number|bigint|string
83
+ * }} QueryRangeLeaf
84
+ */
85
+
86
+ /**
87
+ * @typedef {{kind: 'not', query: QueryNode}} QueryNotLeaf
88
+ */
89
+
90
+ /**
91
+ * `number`/`NumberObject`: is/is-not an integer.
92
+ * @typedef {{kind: 'integerCheck', path: string, isInteger: boolean}} QueryIntegerCheckLeaf
93
+ */
94
+
95
+ /**
96
+ * `string`/`StringObject`/`Blob`/`File`/regexp-source/symbol-description
97
+ * (via `$in`/`$nin`).
98
+ * @typedef {{
99
+ * kind: 'literalSet',
100
+ * path: string,
101
+ * $in?: unknown[],
102
+ * $nin?: unknown[]
103
+ * }} QueryLiteralSetLeaf
104
+ */
105
+
106
+ /**
107
+ * `string`/`StringObject`/`Blob`/`File`/regexp-source/symbol-description
108
+ * (via `$regex`/`$options`, matching Mongo's own field names).
109
+ * @typedef {{
110
+ * kind: 'regex',
111
+ * path: string,
112
+ * $regex: string,
113
+ * $options?: string
114
+ * }} QueryRegexLeaf
115
+ */
116
+
117
+ /**
118
+ * `string`/`StringObject`/`Blob`/`File`/regexp-source/symbol-description:
119
+ * a substring the value must not contain.
120
+ * @typedef {{
121
+ * kind: 'notContains',
122
+ * path: string,
123
+ * value: string
124
+ * }} QueryNotContainsLeaf
125
+ */
126
+
127
+ /**
128
+ * `enum`, SpecialNumber's `Infinity`/`-Infinity`/`NaN`/`-0` (via
129
+ * `$in`/`$nin`).
130
+ * @typedef {{
131
+ * kind: 'multiSelect',
132
+ * path: string,
133
+ * $in?: unknown[],
134
+ * $nin?: unknown[]
135
+ * }} QueryMultiSelectLeaf
136
+ */
137
+
138
+ /**
139
+ * Native enum key-vs-value; no Mongo equivalent, stays custom.
140
+ * @typedef {{
141
+ * kind: 'keyValueEnum',
142
+ * path: string,
143
+ * matchKeys: boolean,
144
+ * values: unknown[]
145
+ * }} QueryKeyValueEnumLeaf
146
+ */
147
+
148
+ /**
149
+ * Union/xor/discriminatedUnion "has type", carrying `discriminatorValue`
150
+ * when applicable, including when nested under a Map/Record key or value;
151
+ * no Mongo equivalent, stays custom.
152
+ * @typedef {{
153
+ * kind: 'typeOf',
154
+ * path: string,
155
+ * searchType: string,
156
+ * discriminatorValue?: unknown
157
+ * }} QueryTypeOfLeaf
158
+ */
159
+
160
+ /**
161
+ * XPath/CSS-selector/full-text/raw-HTML-regex; no Mongo equivalent.
162
+ * @typedef {{
163
+ * kind: 'blobHTML',
164
+ * path: string,
165
+ * mode: 'xpath'|'cssSelector'|'fullText'|'rawHTMLRegex',
166
+ * value: string
167
+ * }} QueryBlobHTMLLeaf
168
+ */
169
+
170
+ /**
171
+ * Per-dimension ranges for DOMRect/Point/Matrix, each dimension itself a
172
+ * `range` leaf, + `readonlyCheck`/`dimensionCheck` (is/is-not readonly,
173
+ * is/is-not 3d); no Mongo equivalent.
174
+ * @typedef {{
175
+ * kind: 'domShape',
176
+ * path: string,
177
+ * dimensions: {[dimension: string]: QueryRangeLeaf},
178
+ * readonlyCheck?: boolean,
179
+ * dimensionCheck?: 2|3
180
+ * }} QueryDomShapeLeaf
181
+ */
182
+
183
+ /**
184
+ * Paired key+value leaves with a joint-match flag; no Mongo equivalent.
185
+ * @typedef {{
186
+ * kind: 'mapRecordJoint',
187
+ * path: string,
188
+ * keyQuery?: QueryNode,
189
+ * valueQuery?: QueryNode,
190
+ * joint: boolean
191
+ * }} QueryMapRecordJointLeaf
192
+ */
193
+
194
+ /**
195
+ * Promise/literal/catch/function: forwards to a nested `QueryNode` for the
196
+ * child schema so the tree stays uniform even where a type adds no
197
+ * constraint of its own; purely structural, no Mongo equivalent.
198
+ * @typedef {{
199
+ * kind: 'passThrough',
200
+ * path: string,
201
+ * query?: QueryNode
202
+ * }} QueryPassThroughLeaf
203
+ */
204
+
205
+ /**
206
+ * Undefined/void/null (via `$exists`).
207
+ * @typedef {{kind: 'presence', path: string, $exists: boolean}} QueryPresenceLeaf
208
+ */
209
+
210
+ /**
211
+ * Boolean/BooleanObject - Mongo would normally express this as a bare
212
+ * `{field: true}` shorthand, which doesn't fit our path-carrying leaf
213
+ * shape, so this stays a custom kind.
214
+ * @typedef {{
215
+ * kind: 'booleanEquals',
216
+ * path: string,
217
+ * value: boolean
218
+ * }} QueryBooleanEqualsLeaf
219
+ */
220
+
221
+ /**
222
+ * @typedef {QueryHasPropertyLeaf|QueryLengthSizeLeaf|QueryRangeLeaf|
223
+ * QueryNotLeaf|QueryIntegerCheckLeaf|QueryLiteralSetLeaf|QueryRegexLeaf|
224
+ * QueryNotContainsLeaf|QueryMultiSelectLeaf|QueryKeyValueEnumLeaf|
225
+ * QueryTypeOfLeaf|QueryBlobHTMLLeaf|QueryDomShapeLeaf|
226
+ * QueryMapRecordJointLeaf|QueryPassThroughLeaf|QueryPresenceLeaf|
227
+ * QueryBooleanEqualsLeaf
228
+ * } QueryLeaf
229
+ */
230
+
231
+ /**
232
+ * @typedef {QueryAnd|QueryOr|QueryLeaf} QueryNode
233
+ */
234
+
235
+ export {};
@@ -0,0 +1,224 @@
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 {{$in?: unknown[], $nin?: unknown[]}} cfg
103
+ * @returns {import('./queryTree.js').QueryLiteralSetLeaf}
104
+ */
105
+ export function makeLiteralSetLeaf (path, cfg = {}) {
106
+ return {kind: 'literalSet', path, ...cfg};
107
+ }
108
+
109
+ /**
110
+ * @param {string} path
111
+ * @param {string} $regex
112
+ * @param {string} [$options]
113
+ * @returns {import('./queryTree.js').QueryRegexLeaf}
114
+ */
115
+ export function makeRegexLeaf (path, $regex, $options) {
116
+ return {kind: 'regex', path, $regex, ...($options ? {$options} : {})};
117
+ }
118
+
119
+ /**
120
+ * @param {string} path
121
+ * @param {string} value
122
+ * @returns {import('./queryTree.js').QueryNotContainsLeaf}
123
+ */
124
+ export function makeNotContainsLeaf (path, value) {
125
+ return {kind: 'notContains', path, value};
126
+ }
127
+
128
+ /**
129
+ * @param {string} path
130
+ * @param {{$in?: unknown[], $nin?: unknown[]}} cfg
131
+ * @returns {import('./queryTree.js').QueryMultiSelectLeaf}
132
+ */
133
+ export function makeMultiSelectLeaf (path, cfg = {}) {
134
+ return {kind: 'multiSelect', path, ...cfg};
135
+ }
136
+
137
+ /**
138
+ * @param {string} path
139
+ * @param {boolean} matchKeys
140
+ * @param {unknown[]} values
141
+ * @returns {import('./queryTree.js').QueryKeyValueEnumLeaf}
142
+ */
143
+ export function makeKeyValueEnumLeaf (path, matchKeys, values) {
144
+ return {kind: 'keyValueEnum', path, matchKeys, values};
145
+ }
146
+
147
+ /**
148
+ * @param {string} path
149
+ * @param {string} searchType
150
+ * @param {unknown} [discriminatorValue]
151
+ * @returns {import('./queryTree.js').QueryTypeOfLeaf}
152
+ */
153
+ export function makeTypeOfLeaf (path, searchType, discriminatorValue) {
154
+ return {
155
+ kind: 'typeOf',
156
+ path,
157
+ searchType,
158
+ ...(discriminatorValue === undefined ? {} : {discriminatorValue})
159
+ };
160
+ }
161
+
162
+ /**
163
+ * @param {string} path
164
+ * @param {import('./queryTree.js').QueryBlobHTMLLeaf['mode']} mode
165
+ * @param {string} value
166
+ * @returns {import('./queryTree.js').QueryBlobHTMLLeaf}
167
+ */
168
+ export function makeBlobHTMLLeaf (path, mode, value) {
169
+ return {kind: 'blobHTML', path, mode, value};
170
+ }
171
+
172
+ /**
173
+ * @param {string} path
174
+ * @param {{[dimension: string]: import('./queryTree.js').QueryRangeLeaf}} dimensions
175
+ * @param {{readonlyCheck?: boolean, dimensionCheck?: 2|3}} [cfg]
176
+ * @returns {import('./queryTree.js').QueryDomShapeLeaf}
177
+ */
178
+ export function makeDomShapeLeaf (path, dimensions, cfg = {}) {
179
+ return {kind: 'domShape', path, dimensions, ...cfg};
180
+ }
181
+
182
+ /**
183
+ * @param {string} path
184
+ * @param {boolean} joint
185
+ * @param {import('./queryTree.js').QueryNode} [keyQuery]
186
+ * @param {import('./queryTree.js').QueryNode} [valueQuery]
187
+ * @returns {import('./queryTree.js').QueryMapRecordJointLeaf}
188
+ */
189
+ export function makeMapRecordJointLeaf (path, joint, keyQuery, valueQuery) {
190
+ return {
191
+ kind: 'mapRecordJoint',
192
+ path,
193
+ joint,
194
+ ...(keyQuery ? {keyQuery} : {}),
195
+ ...(valueQuery ? {valueQuery} : {})
196
+ };
197
+ }
198
+
199
+ /**
200
+ * @param {string} path
201
+ * @param {import('./queryTree.js').QueryNode} [query]
202
+ * @returns {import('./queryTree.js').QueryPassThroughLeaf}
203
+ */
204
+ export function makePassThroughLeaf (path, query) {
205
+ return {kind: 'passThrough', path, ...(query ? {query} : {})};
206
+ }
207
+
208
+ /**
209
+ * @param {string} path
210
+ * @param {boolean} $exists
211
+ * @returns {import('./queryTree.js').QueryPresenceLeaf}
212
+ */
213
+ export function makePresenceLeaf (path, $exists) {
214
+ return {kind: 'presence', path, $exists};
215
+ }
216
+
217
+ /**
218
+ * @param {string} path
219
+ * @param {boolean} value
220
+ * @returns {import('./queryTree.js').QueryBooleanEqualsLeaf}
221
+ */
222
+ export function makeBooleanEqualsLeaf (path, value) {
223
+ return {kind: 'booleanEquals', path, value};
224
+ }