@kubb/ast 5.0.0-alpha.12 → 5.0.0-alpha.14
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/index.cjs +126 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +125 -51
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/{visitor-C73H2CCg.d.ts → visitor-UlWOe-In.d.ts} +82 -37
- package/package.json +1 -1
- package/src/factory.ts +23 -2
- package/src/index.ts +2 -1
- package/src/nodes/operation.ts +4 -0
- package/src/types.ts +1 -1
- package/src/visitor.ts +157 -80
package/src/visitor.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { VisitorDepth } from './constants.ts'
|
|
2
2
|
import { visitorDepths, WALK_CONCURRENCY } from './constants.ts'
|
|
3
|
+
import { createParameter, createProperty } from './factory.ts'
|
|
3
4
|
import type { Node, OperationNode, ParameterNode, PropertyNode, ResponseNode, RootNode, SchemaNode } from './nodes/index.ts'
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -35,27 +36,47 @@ function createLimit(concurrency: number) {
|
|
|
35
36
|
type LimitFn = ReturnType<typeof createLimit>
|
|
36
37
|
|
|
37
38
|
/**
|
|
38
|
-
*
|
|
39
|
+
* Single source of truth: ordered list of `[NodeType, ParentType]` pairs
|
|
40
|
+
* describing which node types can be the parent of a given node in the AST.
|
|
41
|
+
*
|
|
42
|
+
* `ParentOf` walks this tuple and returns the parent type of the first matching entry.
|
|
39
43
|
*/
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
type ParentNodeMap = [
|
|
45
|
+
[RootNode, undefined],
|
|
46
|
+
[OperationNode, RootNode],
|
|
47
|
+
[SchemaNode, RootNode | OperationNode | SchemaNode | PropertyNode | ParameterNode | ResponseNode],
|
|
48
|
+
[PropertyNode, SchemaNode],
|
|
49
|
+
[ParameterNode, OperationNode],
|
|
50
|
+
[ResponseNode, OperationNode],
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
export type ParentOf<T extends Node, TEntries extends ReadonlyArray<[Node, unknown]> = ParentNodeMap> = TEntries extends [
|
|
54
|
+
infer TEntry extends [Node, unknown],
|
|
55
|
+
...infer TRest extends ReadonlyArray<[Node, unknown]>,
|
|
56
|
+
]
|
|
57
|
+
? T extends TEntry[0]
|
|
58
|
+
? TEntry[1]
|
|
59
|
+
: ParentOf<T, TRest>
|
|
60
|
+
: Node
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Traversal context passed as the second argument to every visitor callback.
|
|
64
|
+
* The `parent` field is narrowed based on the node type being visited.
|
|
65
|
+
*/
|
|
66
|
+
export type VisitorContext<T extends Node = Node> = {
|
|
67
|
+
parent?: ParentOf<T>
|
|
47
68
|
}
|
|
48
69
|
|
|
49
70
|
/**
|
|
50
71
|
* Synchronous visitor for `transform` and `walk`.
|
|
51
72
|
*/
|
|
52
73
|
export type Visitor = {
|
|
53
|
-
root?(node: RootNode): void | RootNode
|
|
54
|
-
operation?(node: OperationNode): void | OperationNode
|
|
55
|
-
schema?(node: SchemaNode): void | SchemaNode
|
|
56
|
-
property?(node: PropertyNode): void | PropertyNode
|
|
57
|
-
parameter?(node: ParameterNode): void | ParameterNode
|
|
58
|
-
response?(node: ResponseNode): void | ResponseNode
|
|
74
|
+
root?(node: RootNode, context: VisitorContext<RootNode>): void | RootNode
|
|
75
|
+
operation?(node: OperationNode, context: VisitorContext<OperationNode>): void | OperationNode
|
|
76
|
+
schema?(node: SchemaNode, context: VisitorContext<SchemaNode>): void | SchemaNode
|
|
77
|
+
property?(node: PropertyNode, context: VisitorContext<PropertyNode>): void | PropertyNode
|
|
78
|
+
parameter?(node: ParameterNode, context: VisitorContext<ParameterNode>): void | ParameterNode
|
|
79
|
+
response?(node: ResponseNode, context: VisitorContext<ResponseNode>): void | ResponseNode
|
|
59
80
|
}
|
|
60
81
|
|
|
61
82
|
type MaybePromise<T> = T | Promise<T>
|
|
@@ -64,24 +85,52 @@ type MaybePromise<T> = T | Promise<T>
|
|
|
64
85
|
* Async visitor for `walk`. Synchronous `Visitor` objects are compatible.
|
|
65
86
|
*/
|
|
66
87
|
export type AsyncVisitor = {
|
|
67
|
-
root?(node: RootNode): MaybePromise<void | RootNode>
|
|
68
|
-
operation?(node: OperationNode): MaybePromise<void | OperationNode>
|
|
69
|
-
schema?(node: SchemaNode): MaybePromise<void | SchemaNode>
|
|
70
|
-
property?(node: PropertyNode): MaybePromise<void | PropertyNode>
|
|
71
|
-
parameter?(node: ParameterNode): MaybePromise<void | ParameterNode>
|
|
72
|
-
response?(node: ResponseNode): MaybePromise<void | ResponseNode>
|
|
88
|
+
root?(node: RootNode, context: VisitorContext<RootNode>): MaybePromise<void | RootNode>
|
|
89
|
+
operation?(node: OperationNode, context: VisitorContext<OperationNode>): MaybePromise<void | OperationNode>
|
|
90
|
+
schema?(node: SchemaNode, context: VisitorContext<SchemaNode>): MaybePromise<void | SchemaNode>
|
|
91
|
+
property?(node: PropertyNode, context: VisitorContext<PropertyNode>): MaybePromise<void | PropertyNode>
|
|
92
|
+
parameter?(node: ParameterNode, context: VisitorContext<ParameterNode>): MaybePromise<void | ParameterNode>
|
|
93
|
+
response?(node: ResponseNode, context: VisitorContext<ResponseNode>): MaybePromise<void | ResponseNode>
|
|
73
94
|
}
|
|
74
95
|
|
|
75
96
|
/**
|
|
76
97
|
* Visitor for `collect`.
|
|
77
98
|
*/
|
|
78
99
|
export type CollectVisitor<T> = {
|
|
79
|
-
root?(node: RootNode): T | undefined
|
|
80
|
-
operation?(node: OperationNode): T | undefined
|
|
81
|
-
schema?(node: SchemaNode): T | undefined
|
|
82
|
-
property?(node: PropertyNode): T | undefined
|
|
83
|
-
parameter?(node: ParameterNode): T | undefined
|
|
84
|
-
response?(node: ResponseNode): T | undefined
|
|
100
|
+
root?(node: RootNode, context: VisitorContext<RootNode>): T | undefined
|
|
101
|
+
operation?(node: OperationNode, context: VisitorContext<OperationNode>): T | undefined
|
|
102
|
+
schema?(node: SchemaNode, context: VisitorContext<SchemaNode>): T | undefined
|
|
103
|
+
property?(node: PropertyNode, context: VisitorContext<PropertyNode>): T | undefined
|
|
104
|
+
parameter?(node: ParameterNode, context: VisitorContext<ParameterNode>): T | undefined
|
|
105
|
+
response?(node: ResponseNode, context: VisitorContext<ResponseNode>): T | undefined
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Options for `transform` and `collect`. Extends `Visitor` with traversal settings.
|
|
110
|
+
*/
|
|
111
|
+
export type TransformOptions = Visitor & {
|
|
112
|
+
depth?: VisitorDepth
|
|
113
|
+
parent?: Node
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Options for `walk`. Extends `AsyncVisitor` with traversal settings.
|
|
118
|
+
*/
|
|
119
|
+
export type WalkOptions = AsyncVisitor & {
|
|
120
|
+
depth?: VisitorDepth
|
|
121
|
+
/**
|
|
122
|
+
* Maximum number of sibling nodes visited concurrently.
|
|
123
|
+
* @default 30
|
|
124
|
+
*/
|
|
125
|
+
concurrency?: number
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Options for `collect`. Extends `CollectVisitor` with traversal settings.
|
|
130
|
+
*/
|
|
131
|
+
export type CollectOptions<T> = CollectVisitor<T> & {
|
|
132
|
+
depth?: VisitorDepth
|
|
133
|
+
parent?: Node
|
|
85
134
|
}
|
|
86
135
|
|
|
87
136
|
/**
|
|
@@ -125,34 +174,31 @@ function getChildren(node: Node, recurse: boolean): Array<Node> {
|
|
|
125
174
|
* Depth-first traversal for side effects. Visitor return values are ignored.
|
|
126
175
|
* Sibling nodes at each level are visited concurrently up to `options.concurrency` (default: 30).
|
|
127
176
|
*/
|
|
128
|
-
export async function walk(node: Node,
|
|
177
|
+
export async function walk(node: Node, options: WalkOptions): Promise<void> {
|
|
129
178
|
const recurse = (options.depth ?? visitorDepths.deep) === visitorDepths.deep
|
|
130
179
|
const limit = createLimit(options.concurrency ?? WALK_CONCURRENCY)
|
|
131
|
-
return _walk(node,
|
|
180
|
+
return _walk(node, options, recurse, limit, undefined)
|
|
132
181
|
}
|
|
133
182
|
|
|
134
|
-
|
|
135
|
-
* Internal recursive walk implementation — calls visitor then recurses into children.
|
|
136
|
-
*/
|
|
137
|
-
async function _walk(node: Node, visitor: AsyncVisitor, recurse: boolean, limit: LimitFn): Promise<void> {
|
|
183
|
+
async function _walk(node: Node, visitor: AsyncVisitor, recurse: boolean, limit: LimitFn, parent: Node | undefined): Promise<void> {
|
|
138
184
|
switch (node.kind) {
|
|
139
185
|
case 'Root':
|
|
140
|
-
await limit(() => visitor.root?.(node))
|
|
186
|
+
await limit(() => visitor.root?.(node, { parent: parent as ParentOf<RootNode> }))
|
|
141
187
|
break
|
|
142
188
|
case 'Operation':
|
|
143
|
-
await limit(() => visitor.operation?.(node))
|
|
189
|
+
await limit(() => visitor.operation?.(node, { parent: parent as ParentOf<OperationNode> }))
|
|
144
190
|
break
|
|
145
191
|
case 'Schema':
|
|
146
|
-
await limit(() => visitor.schema?.(node))
|
|
192
|
+
await limit(() => visitor.schema?.(node, { parent: parent as ParentOf<SchemaNode> }))
|
|
147
193
|
break
|
|
148
194
|
case 'Property':
|
|
149
|
-
await limit(() => visitor.property?.(node))
|
|
195
|
+
await limit(() => visitor.property?.(node, { parent: parent as ParentOf<PropertyNode> }))
|
|
150
196
|
break
|
|
151
197
|
case 'Parameter':
|
|
152
|
-
await limit(() => visitor.parameter?.(node))
|
|
198
|
+
await limit(() => visitor.parameter?.(node, { parent: parent as ParentOf<ParameterNode> }))
|
|
153
199
|
break
|
|
154
200
|
case 'Response':
|
|
155
|
-
await limit(() => visitor.response?.(node))
|
|
201
|
+
await limit(() => visitor.response?.(node, { parent: parent as ParentOf<ResponseNode> }))
|
|
156
202
|
break
|
|
157
203
|
case 'FunctionParameter':
|
|
158
204
|
case 'ObjectBindingParameter':
|
|
@@ -161,91 +207,94 @@ async function _walk(node: Node, visitor: AsyncVisitor, recurse: boolean, limit:
|
|
|
161
207
|
}
|
|
162
208
|
|
|
163
209
|
const children = getChildren(node, recurse)
|
|
164
|
-
await Promise.all(children.map((child) => _walk(child, visitor, recurse, limit)))
|
|
210
|
+
await Promise.all(children.map((child) => _walk(child, visitor, recurse, limit, node)))
|
|
165
211
|
}
|
|
166
212
|
|
|
167
213
|
/**
|
|
168
214
|
* Depth-first immutable transformation. Visitor return values replace nodes; `undefined` keeps the original.
|
|
169
215
|
*/
|
|
170
|
-
export function transform(node: RootNode,
|
|
171
|
-
export function transform(node: OperationNode,
|
|
172
|
-
export function transform(node: SchemaNode,
|
|
173
|
-
export function transform(node: PropertyNode,
|
|
174
|
-
export function transform(node: ParameterNode,
|
|
175
|
-
export function transform(node: ResponseNode,
|
|
176
|
-
export function transform(node: Node,
|
|
177
|
-
export function transform(node: Node,
|
|
178
|
-
const
|
|
216
|
+
export function transform(node: RootNode, options: TransformOptions): RootNode
|
|
217
|
+
export function transform(node: OperationNode, options: TransformOptions): OperationNode
|
|
218
|
+
export function transform(node: SchemaNode, options: TransformOptions): SchemaNode
|
|
219
|
+
export function transform(node: PropertyNode, options: TransformOptions): PropertyNode
|
|
220
|
+
export function transform(node: ParameterNode, options: TransformOptions): ParameterNode
|
|
221
|
+
export function transform(node: ResponseNode, options: TransformOptions): ResponseNode
|
|
222
|
+
export function transform(node: Node, options: TransformOptions): Node
|
|
223
|
+
export function transform(node: Node, options: TransformOptions): Node {
|
|
224
|
+
const { depth, parent, ...visitor } = options
|
|
225
|
+
const recurse = (depth ?? visitorDepths.deep) === visitorDepths.deep
|
|
179
226
|
|
|
180
227
|
switch (node.kind) {
|
|
181
228
|
case 'Root': {
|
|
182
229
|
let root = node
|
|
183
|
-
const replaced = visitor.root?.(root)
|
|
230
|
+
const replaced = visitor.root?.(root, { parent: parent as ParentOf<RootNode> })
|
|
184
231
|
if (replaced) root = replaced
|
|
185
232
|
|
|
186
233
|
return {
|
|
187
234
|
...root,
|
|
188
|
-
schemas: root.schemas.map((s) => transform(s,
|
|
189
|
-
operations: root.operations.map((op) => transform(op,
|
|
235
|
+
schemas: root.schemas.map((s) => transform(s, { ...options, parent: root })),
|
|
236
|
+
operations: root.operations.map((op) => transform(op, { ...options, parent: root })),
|
|
190
237
|
}
|
|
191
238
|
}
|
|
192
239
|
case 'Operation': {
|
|
193
240
|
let op = node
|
|
194
|
-
const replaced = visitor.operation?.(op)
|
|
241
|
+
const replaced = visitor.operation?.(op, { parent: parent as ParentOf<OperationNode> })
|
|
195
242
|
if (replaced) op = replaced
|
|
196
243
|
|
|
197
244
|
return {
|
|
198
245
|
...op,
|
|
199
|
-
parameters: op.parameters.map((p) => transform(p,
|
|
246
|
+
parameters: op.parameters.map((p) => transform(p, { ...options, parent: op })),
|
|
200
247
|
requestBody: op.requestBody
|
|
201
|
-
? { ...op.requestBody, schema: op.requestBody.schema ? transform(op.requestBody.schema,
|
|
248
|
+
? { ...op.requestBody, schema: op.requestBody.schema ? transform(op.requestBody.schema, { ...options, parent: op }) : undefined }
|
|
202
249
|
: undefined,
|
|
203
|
-
responses: op.responses.map((r) => transform(r,
|
|
250
|
+
responses: op.responses.map((r) => transform(r, { ...options, parent: op })),
|
|
204
251
|
}
|
|
205
252
|
}
|
|
206
253
|
case 'Schema': {
|
|
207
254
|
let schema = node
|
|
208
|
-
const replaced = visitor.schema?.(schema)
|
|
255
|
+
const replaced = visitor.schema?.(schema, { parent: parent as ParentOf<SchemaNode> })
|
|
209
256
|
if (replaced) schema = replaced
|
|
210
257
|
|
|
258
|
+
const childOptions = { ...options, parent: schema }
|
|
259
|
+
|
|
211
260
|
return {
|
|
212
261
|
...schema,
|
|
213
|
-
...('properties' in schema && recurse ? { properties: schema.properties.map((p) => transform(p,
|
|
214
|
-
...('items' in schema && recurse ? { items: schema.items?.map((i) => transform(i,
|
|
215
|
-
...('members' in schema && recurse ? { members: schema.members?.map((m) => transform(m,
|
|
262
|
+
...('properties' in schema && recurse ? { properties: schema.properties.map((p) => transform(p, childOptions)) } : {}),
|
|
263
|
+
...('items' in schema && recurse ? { items: schema.items?.map((i) => transform(i, childOptions)) } : {}),
|
|
264
|
+
...('members' in schema && recurse ? { members: schema.members?.map((m) => transform(m, childOptions)) } : {}),
|
|
216
265
|
...('additionalProperties' in schema && recurse && schema.additionalProperties && schema.additionalProperties !== true
|
|
217
|
-
? { additionalProperties: transform(schema.additionalProperties,
|
|
266
|
+
? { additionalProperties: transform(schema.additionalProperties, childOptions) }
|
|
218
267
|
: {}),
|
|
219
|
-
}
|
|
268
|
+
} as SchemaNode
|
|
220
269
|
}
|
|
221
270
|
case 'Property': {
|
|
222
271
|
let prop = node
|
|
223
|
-
const replaced = visitor.property?.(prop)
|
|
272
|
+
const replaced = visitor.property?.(prop, { parent: parent as ParentOf<PropertyNode> })
|
|
224
273
|
if (replaced) prop = replaced
|
|
225
274
|
|
|
226
|
-
return {
|
|
275
|
+
return createProperty({
|
|
227
276
|
...prop,
|
|
228
|
-
schema: transform(prop.schema,
|
|
229
|
-
}
|
|
277
|
+
schema: transform(prop.schema, { ...options, parent: prop }),
|
|
278
|
+
})
|
|
230
279
|
}
|
|
231
280
|
case 'Parameter': {
|
|
232
281
|
let param = node
|
|
233
|
-
const replaced = visitor.parameter?.(param)
|
|
282
|
+
const replaced = visitor.parameter?.(param, { parent: parent as ParentOf<ParameterNode> })
|
|
234
283
|
if (replaced) param = replaced
|
|
235
284
|
|
|
236
|
-
return {
|
|
285
|
+
return createParameter({
|
|
237
286
|
...param,
|
|
238
|
-
schema: transform(param.schema,
|
|
239
|
-
}
|
|
287
|
+
schema: transform(param.schema, { ...options, parent: param }),
|
|
288
|
+
})
|
|
240
289
|
}
|
|
241
290
|
case 'Response': {
|
|
242
291
|
let response = node
|
|
243
|
-
const replaced = visitor.response?.(response)
|
|
292
|
+
const replaced = visitor.response?.(response, { parent: parent as ParentOf<ResponseNode> })
|
|
244
293
|
if (replaced) response = replaced
|
|
245
294
|
|
|
246
295
|
return {
|
|
247
296
|
...response,
|
|
248
|
-
schema: transform(response.schema,
|
|
297
|
+
schema: transform(response.schema, { ...options, parent: response }),
|
|
249
298
|
}
|
|
250
299
|
}
|
|
251
300
|
case 'FunctionParameter':
|
|
@@ -255,32 +304,60 @@ export function transform(node: Node, visitor: Visitor, options: VisitorOptions
|
|
|
255
304
|
}
|
|
256
305
|
}
|
|
257
306
|
|
|
307
|
+
/**
|
|
308
|
+
* Combines multiple visitors into a single visitor that applies them sequentially (left to right).
|
|
309
|
+
* For each node kind, the output of one visitor becomes the input of the next.
|
|
310
|
+
*/
|
|
311
|
+
export function composeTransformers(...visitors: Array<Visitor>): Visitor {
|
|
312
|
+
return {
|
|
313
|
+
root(node, context) {
|
|
314
|
+
return visitors.reduce<RootNode>((acc, v) => v.root?.(acc, context) ?? acc, node)
|
|
315
|
+
},
|
|
316
|
+
operation(node, context) {
|
|
317
|
+
return visitors.reduce<OperationNode>((acc, v) => v.operation?.(acc, context) ?? acc, node)
|
|
318
|
+
},
|
|
319
|
+
schema(node, context) {
|
|
320
|
+
return visitors.reduce<SchemaNode>((acc, v) => v.schema?.(acc, context) ?? acc, node)
|
|
321
|
+
},
|
|
322
|
+
property(node, context) {
|
|
323
|
+
return visitors.reduce<PropertyNode>((acc, v) => v.property?.(acc, context) ?? acc, node)
|
|
324
|
+
},
|
|
325
|
+
parameter(node, context) {
|
|
326
|
+
return visitors.reduce<ParameterNode>((acc, v) => v.parameter?.(acc, context) ?? acc, node)
|
|
327
|
+
},
|
|
328
|
+
response(node, context) {
|
|
329
|
+
return visitors.reduce<ResponseNode>((acc, v) => v.response?.(acc, context) ?? acc, node)
|
|
330
|
+
},
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
258
334
|
/**
|
|
259
335
|
* Depth-first synchronous reduction. Collects non-`undefined` visitor return values into an array.
|
|
260
336
|
*/
|
|
261
|
-
export function collect<T>(node: Node,
|
|
262
|
-
const
|
|
337
|
+
export function collect<T>(node: Node, options: CollectOptions<T>): Array<T> {
|
|
338
|
+
const { depth, parent, ...visitor } = options
|
|
339
|
+
const recurse = (depth ?? visitorDepths.deep) === visitorDepths.deep
|
|
263
340
|
const results: Array<T> = []
|
|
264
341
|
|
|
265
342
|
let v: T | undefined
|
|
266
343
|
switch (node.kind) {
|
|
267
344
|
case 'Root':
|
|
268
|
-
v = visitor.root?.(node)
|
|
345
|
+
v = visitor.root?.(node, { parent: parent as ParentOf<RootNode> })
|
|
269
346
|
break
|
|
270
347
|
case 'Operation':
|
|
271
|
-
v = visitor.operation?.(node)
|
|
348
|
+
v = visitor.operation?.(node, { parent: parent as ParentOf<OperationNode> })
|
|
272
349
|
break
|
|
273
350
|
case 'Schema':
|
|
274
|
-
v = visitor.schema?.(node)
|
|
351
|
+
v = visitor.schema?.(node, { parent: parent as ParentOf<SchemaNode> })
|
|
275
352
|
break
|
|
276
353
|
case 'Property':
|
|
277
|
-
v = visitor.property?.(node)
|
|
354
|
+
v = visitor.property?.(node, { parent: parent as ParentOf<PropertyNode> })
|
|
278
355
|
break
|
|
279
356
|
case 'Parameter':
|
|
280
|
-
v = visitor.parameter?.(node)
|
|
357
|
+
v = visitor.parameter?.(node, { parent: parent as ParentOf<ParameterNode> })
|
|
281
358
|
break
|
|
282
359
|
case 'Response':
|
|
283
|
-
v = visitor.response?.(node)
|
|
360
|
+
v = visitor.response?.(node, { parent: parent as ParentOf<ResponseNode> })
|
|
284
361
|
break
|
|
285
362
|
case 'FunctionParameter':
|
|
286
363
|
case 'ObjectBindingParameter':
|
|
@@ -290,7 +367,7 @@ export function collect<T>(node: Node, visitor: CollectVisitor<T>, options: Visi
|
|
|
290
367
|
if (v !== undefined) results.push(v)
|
|
291
368
|
|
|
292
369
|
for (const child of getChildren(node, recurse)) {
|
|
293
|
-
for (const item of collect(child,
|
|
370
|
+
for (const item of collect(child, { ...options, parent: node })) {
|
|
294
371
|
results.push(item)
|
|
295
372
|
}
|
|
296
373
|
}
|