@kubb/ast 5.0.0-beta.63 → 5.0.0-beta.64
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/{defineMacro-Shz8f6SG.js → defineMacro-B76LsJwO.js} +4 -4
- package/dist/{defineMacro-Shz8f6SG.js.map → defineMacro-B76LsJwO.js.map} +1 -1
- package/dist/{defineMacro-BATi7xoC.d.ts → defineMacro-B7qm3zTd.d.ts} +3 -3
- package/dist/factory-wJLzHeXT.d.ts +27 -0
- package/dist/factory.d.ts +3 -27
- package/dist/factory.js +2 -2
- package/dist/{index-B9cc8MBS.d.ts → index-BKD4drsX.d.ts} +2 -2
- package/dist/index.cjs +54 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +24 -21
- package/dist/index.js +54 -8
- package/dist/index.js.map +1 -1
- package/dist/macros.d.ts +2 -2
- package/dist/macros.js +4 -4
- package/dist/{operationParams-k5CKwSWZ.d.ts → operationParams-ByVfpYr7.d.ts} +3 -3
- package/dist/{refs-BjNDuCBD.js → refs-Dx6U5LoE.js} +3 -3
- package/dist/{refs-BjNDuCBD.js.map → refs-Dx6U5LoE.js.map} +1 -1
- package/dist/{schema-Cbnxmz4b.js → schema-YNbOtTCM.js} +2 -2
- package/dist/{schema-Cbnxmz4b.js.map → schema-YNbOtTCM.js.map} +1 -1
- package/dist/{types-BB_xgRJ3.d.ts → types-BP9BZoq-.d.ts} +8 -8
- package/dist/types.d.ts +5 -5
- package/dist/{utils-DaXkewb1.js → utils-BJi0y-xg.js} +4 -4
- package/dist/{utils-DaXkewb1.js.map → utils-BJi0y-xg.js.map} +1 -1
- package/dist/utils.d.ts +3 -3
- package/dist/utils.js +3 -3
- package/package.json +1 -2
- package/src/constants.ts +0 -150
- package/src/defineMacro.ts +0 -139
- package/src/defineNode.ts +0 -102
- package/src/definePrinter.ts +0 -258
- package/src/dialect.ts +0 -86
- package/src/factory.ts +0 -44
- package/src/guards.ts +0 -28
- package/src/index.ts +0 -13
- package/src/infer.ts +0 -132
- package/src/macros/index.ts +0 -3
- package/src/macros/macroDiscriminatorEnum.ts +0 -50
- package/src/macros/macroEnumName.ts +0 -33
- package/src/macros/macroSimplifyUnion.ts +0 -60
- package/src/nodes/base.ts +0 -49
- package/src/nodes/code.ts +0 -355
- package/src/nodes/content.ts +0 -51
- package/src/nodes/file.ts +0 -380
- package/src/nodes/function.ts +0 -283
- package/src/nodes/index.ts +0 -93
- package/src/nodes/input.ts +0 -144
- package/src/nodes/operation.ts +0 -168
- package/src/nodes/output.ts +0 -49
- package/src/nodes/parameter.ts +0 -71
- package/src/nodes/property.ts +0 -67
- package/src/nodes/requestBody.ts +0 -54
- package/src/nodes/response.ts +0 -173
- package/src/nodes/schema.ts +0 -732
- package/src/optionality.ts +0 -15
- package/src/registry.ts +0 -75
- package/src/signature.ts +0 -207
- package/src/types.ts +0 -8
- package/src/utils/codegen.ts +0 -103
- package/src/utils/extractStringsFromNodes.ts +0 -35
- package/src/utils/fileMerge.ts +0 -183
- package/src/utils/index.ts +0 -11
- package/src/utils/operationParams.ts +0 -353
- package/src/utils/refs.ts +0 -134
- package/src/utils/schemaGraph.ts +0 -177
- package/src/utils/schemaMerge.ts +0 -34
- package/src/utils/schemaTraversal.ts +0 -86
- package/src/utils/strings.ts +0 -139
- package/src/visitor.ts +0 -519
- /package/dist/{chunk-CNktS9qV.js → rolldown-runtime-CNktS9qV.js} +0 -0
package/src/nodes/file.ts
DELETED
|
@@ -1,380 +0,0 @@
|
|
|
1
|
-
import { hash } from 'node:crypto'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
import { trimExtName } from '@internals/utils'
|
|
4
|
-
import { defineNode } from '../defineNode.ts'
|
|
5
|
-
import { extractStringsFromNodes } from '../utils/extractStringsFromNodes.ts'
|
|
6
|
-
import { combineExports, combineImports, combineSources } from '../utils/fileMerge.ts'
|
|
7
|
-
import type { BaseNode } from './base.ts'
|
|
8
|
-
import type { CodeNode } from './code.ts'
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Supported file extensions.
|
|
12
|
-
*/
|
|
13
|
-
type Extname = '.ts' | '.js' | '.tsx' | '.json' | `.${string}`
|
|
14
|
-
|
|
15
|
-
type ImportName = string | Array<string | { propertyName: string; name?: string }>
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Represents a language-agnostic import/dependency declaration.
|
|
19
|
-
*
|
|
20
|
-
* @example Named import (TypeScript: `import { useState } from 'react'`)
|
|
21
|
-
* ```ts
|
|
22
|
-
* createImport({ name: ['useState'], path: 'react' })
|
|
23
|
-
* ```
|
|
24
|
-
*
|
|
25
|
-
* @example Default import (TypeScript: `import React from 'react'`)
|
|
26
|
-
* ```ts
|
|
27
|
-
* createImport({ name: 'React', path: 'react' })
|
|
28
|
-
* ```
|
|
29
|
-
*
|
|
30
|
-
* @example Type-only import (TypeScript: `import type { FC } from 'react'`)
|
|
31
|
-
* ```ts
|
|
32
|
-
* createImport({ name: ['FC'], path: 'react', isTypeOnly: true })
|
|
33
|
-
* ```
|
|
34
|
-
*
|
|
35
|
-
* @example Namespace import (TypeScript: `import * as React from 'react'`)
|
|
36
|
-
* ```ts
|
|
37
|
-
* createImport({ name: 'React', path: 'react', isNameSpace: true })
|
|
38
|
-
* ```
|
|
39
|
-
*/
|
|
40
|
-
export type ImportNode = BaseNode & {
|
|
41
|
-
kind: 'Import'
|
|
42
|
-
/**
|
|
43
|
-
* Import name(s) to be used.
|
|
44
|
-
*
|
|
45
|
-
* @example Named imports
|
|
46
|
-
* `['useState']`
|
|
47
|
-
*
|
|
48
|
-
* @example Default import
|
|
49
|
-
* `'React'`
|
|
50
|
-
*/
|
|
51
|
-
name: ImportName
|
|
52
|
-
/**
|
|
53
|
-
* Path for the import.
|
|
54
|
-
*
|
|
55
|
-
* @example
|
|
56
|
-
* `'@kubb/core'`
|
|
57
|
-
*/
|
|
58
|
-
path: string
|
|
59
|
-
/**
|
|
60
|
-
* Add a type-only import prefix.
|
|
61
|
-
* - `true` generates `import type { Type } from './path'`
|
|
62
|
-
* - `false` generates `import { Type } from './path'`
|
|
63
|
-
*/
|
|
64
|
-
isTypeOnly?: boolean | null
|
|
65
|
-
/**
|
|
66
|
-
* Import the entire module as a namespace.
|
|
67
|
-
* - `true` generates `import * as Name from './path'`
|
|
68
|
-
* - `false` generates a standard import
|
|
69
|
-
*/
|
|
70
|
-
isNameSpace?: boolean | null
|
|
71
|
-
/**
|
|
72
|
-
* When set, the import path is resolved relative to this root.
|
|
73
|
-
*/
|
|
74
|
-
root?: string | null
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Represents a language-agnostic export/public API declaration.
|
|
79
|
-
*
|
|
80
|
-
* @example Named export (TypeScript: `export { Pets } from './Pets'`)
|
|
81
|
-
* ```ts
|
|
82
|
-
* createExport({ name: ['Pets'], path: './Pets' })
|
|
83
|
-
* ```
|
|
84
|
-
*
|
|
85
|
-
* @example Type-only export (TypeScript: `export type { Pet } from './Pet'`)
|
|
86
|
-
* ```ts
|
|
87
|
-
* createExport({ name: ['Pet'], path: './Pet', isTypeOnly: true })
|
|
88
|
-
* ```
|
|
89
|
-
*
|
|
90
|
-
* @example Wildcard export (TypeScript: `export * from './utils'`)
|
|
91
|
-
* ```ts
|
|
92
|
-
* createExport({ path: './utils' })
|
|
93
|
-
* ```
|
|
94
|
-
*
|
|
95
|
-
* @example Namespace alias (TypeScript: `export * as utils from './utils'`)
|
|
96
|
-
* ```ts
|
|
97
|
-
* createExport({ name: 'utils', path: './utils', asAlias: true })
|
|
98
|
-
* ```
|
|
99
|
-
*/
|
|
100
|
-
export type ExportNode = BaseNode & {
|
|
101
|
-
kind: 'Export'
|
|
102
|
-
/**
|
|
103
|
-
* Export name(s) to be used. When omitted, generates a wildcard export.
|
|
104
|
-
*
|
|
105
|
-
* @example Named exports
|
|
106
|
-
* `['useState']`
|
|
107
|
-
*
|
|
108
|
-
* @example Single export
|
|
109
|
-
* `'React'`
|
|
110
|
-
*/
|
|
111
|
-
name?: string | Array<string> | null
|
|
112
|
-
/**
|
|
113
|
-
* Path for the export.
|
|
114
|
-
*
|
|
115
|
-
* @example
|
|
116
|
-
* `'@kubb/core'`
|
|
117
|
-
*/
|
|
118
|
-
path: string
|
|
119
|
-
/**
|
|
120
|
-
* Add a type-only export prefix.
|
|
121
|
-
* - `true` generates `export type { Type } from './path'`
|
|
122
|
-
* - `false` generates `export { Type } from './path'`
|
|
123
|
-
*/
|
|
124
|
-
isTypeOnly?: boolean | null
|
|
125
|
-
/**
|
|
126
|
-
* Export as an aliased namespace.
|
|
127
|
-
* - `true` generates `export * as aliasName from './path'`
|
|
128
|
-
* - `false` generates a standard export
|
|
129
|
-
*/
|
|
130
|
-
asAlias?: boolean | null
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Represents a fragment of source code within a file.
|
|
135
|
-
*
|
|
136
|
-
* @example Named exportable source
|
|
137
|
-
* ```ts
|
|
138
|
-
* createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')], isExportable: true, isIndexable: true })
|
|
139
|
-
* ```
|
|
140
|
-
*
|
|
141
|
-
* @example Inline unnamed code block
|
|
142
|
-
* ```ts
|
|
143
|
-
* createSource({ nodes: [createText('const x = 1')] })
|
|
144
|
-
* ```
|
|
145
|
-
*/
|
|
146
|
-
export type SourceNode = BaseNode & {
|
|
147
|
-
kind: 'Source'
|
|
148
|
-
/**
|
|
149
|
-
* Optional name identifying this source (used for deduplication and barrel generation).
|
|
150
|
-
*/
|
|
151
|
-
name?: string | null
|
|
152
|
-
/**
|
|
153
|
-
* Mark this source as a type-only export.
|
|
154
|
-
*/
|
|
155
|
-
isTypeOnly?: boolean | null
|
|
156
|
-
/**
|
|
157
|
-
* Include the `export` keyword in the generated source.
|
|
158
|
-
*/
|
|
159
|
-
isExportable?: boolean | null
|
|
160
|
-
/**
|
|
161
|
-
* Include this source in barrel/index file generation.
|
|
162
|
-
*/
|
|
163
|
-
isIndexable?: boolean | null
|
|
164
|
-
/**
|
|
165
|
-
* Child nodes that make up this source fragment, in DOM order.
|
|
166
|
-
* Use a {@link TextNode} for raw string content.
|
|
167
|
-
*/
|
|
168
|
-
nodes?: Array<CodeNode>
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Represents a fully resolved file in the AST.
|
|
173
|
-
*
|
|
174
|
-
* Created via `createFile()`, which computes the `id`, `name`, and `extname` from the input
|
|
175
|
-
* and deduplicates `imports`, `exports`, and `sources`.
|
|
176
|
-
*
|
|
177
|
-
* @example
|
|
178
|
-
* ```ts
|
|
179
|
-
* const file = createFile({
|
|
180
|
-
* baseName: 'petStore.ts',
|
|
181
|
-
* path: 'src/models/petStore.ts',
|
|
182
|
-
* sources: [createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')], isExportable: true })],
|
|
183
|
-
* imports: [createImport({ name: ['z'], path: 'zod' })],
|
|
184
|
-
* exports: [createExport({ name: ['Pet'], path: './petStore' })],
|
|
185
|
-
* })
|
|
186
|
-
* // file.id = SHA256 hash of the path
|
|
187
|
-
* // file.name = 'petStore'
|
|
188
|
-
* // file.extname = '.ts'
|
|
189
|
-
* ```
|
|
190
|
-
*/
|
|
191
|
-
export type FileNode<TMeta extends object = object> = BaseNode & {
|
|
192
|
-
kind: 'File'
|
|
193
|
-
/**
|
|
194
|
-
* Unique identifier derived from a SHA256 hash of the file path. `createFile`
|
|
195
|
-
* computes it, so callers do not need to provide it.
|
|
196
|
-
*/
|
|
197
|
-
id: string
|
|
198
|
-
/**
|
|
199
|
-
* File name without extension, derived from `baseName`.
|
|
200
|
-
*
|
|
201
|
-
* @see https://nodejs.org/api/path.html#pathformatpathobject
|
|
202
|
-
*/
|
|
203
|
-
name: string
|
|
204
|
-
/**
|
|
205
|
-
* File base name, including extension, shaped like `${name}${extname}`.
|
|
206
|
-
*
|
|
207
|
-
* @see https://nodejs.org/api/path.html#pathbasenamepath-suffix
|
|
208
|
-
*/
|
|
209
|
-
baseName: `${string}.${string}`
|
|
210
|
-
/**
|
|
211
|
-
* Full qualified path to the file.
|
|
212
|
-
*/
|
|
213
|
-
path: string
|
|
214
|
-
/**
|
|
215
|
-
* File extension extracted from `baseName`.
|
|
216
|
-
*/
|
|
217
|
-
extname: Extname
|
|
218
|
-
/**
|
|
219
|
-
* Deduplicated list of source code fragments.
|
|
220
|
-
*/
|
|
221
|
-
sources: Array<SourceNode>
|
|
222
|
-
/**
|
|
223
|
-
* Deduplicated list of import declarations.
|
|
224
|
-
*/
|
|
225
|
-
imports: Array<ImportNode>
|
|
226
|
-
/**
|
|
227
|
-
* Deduplicated list of export declarations.
|
|
228
|
-
*/
|
|
229
|
-
exports: Array<ExportNode>
|
|
230
|
-
/**
|
|
231
|
-
* Optional metadata attached to this file, read by plugins during barrel generation.
|
|
232
|
-
*/
|
|
233
|
-
meta?: TMeta
|
|
234
|
-
/**
|
|
235
|
-
* Optional banner prepended to the generated file content.
|
|
236
|
-
* Accepts `null` so `resolver.resolveBanner()` results can be passed directly.
|
|
237
|
-
*/
|
|
238
|
-
banner?: string | null
|
|
239
|
-
/**
|
|
240
|
-
* Optional footer appended to the generated file content.
|
|
241
|
-
* Accepts `null` so `resolver.resolveFooter()` results can be passed directly.
|
|
242
|
-
*/
|
|
243
|
-
footer?: string | null
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Definition for the {@link ImportNode}.
|
|
248
|
-
*/
|
|
249
|
-
export const importDef = defineNode<ImportNode>({ kind: 'Import' })
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Definition for the {@link ExportNode}.
|
|
253
|
-
*/
|
|
254
|
-
export const exportDef = defineNode<ExportNode>({ kind: 'Export' })
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* Definition for the {@link SourceNode}.
|
|
258
|
-
*/
|
|
259
|
-
export const sourceDef = defineNode<SourceNode>({ kind: 'Source' })
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Definition for the {@link FileNode}. The fully resolved builder lives in
|
|
263
|
-
* `createFile`, so this definition only supplies the guard.
|
|
264
|
-
*/
|
|
265
|
-
export const fileDef = defineNode<FileNode>({ kind: 'File' })
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* Creates an `ImportNode` representing a language-agnostic import/dependency declaration.
|
|
269
|
-
*
|
|
270
|
-
* @example Named import
|
|
271
|
-
* ```ts
|
|
272
|
-
* createImport({ name: ['useState'], path: 'react' })
|
|
273
|
-
* // import { useState } from 'react'
|
|
274
|
-
* ```
|
|
275
|
-
*/
|
|
276
|
-
export const createImport = importDef.create
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* Creates an `ExportNode` representing a language-agnostic export/public API declaration.
|
|
280
|
-
*
|
|
281
|
-
* @example Named export
|
|
282
|
-
* ```ts
|
|
283
|
-
* createExport({ name: ['Pet'], path: './Pet' })
|
|
284
|
-
* // export { Pet } from './Pet'
|
|
285
|
-
* ```
|
|
286
|
-
*/
|
|
287
|
-
export const createExport = exportDef.create
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* Creates a `SourceNode` representing a fragment of source code within a file.
|
|
291
|
-
*
|
|
292
|
-
* @example
|
|
293
|
-
* ```ts
|
|
294
|
-
* createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')], isExportable: true })
|
|
295
|
-
* ```
|
|
296
|
-
*/
|
|
297
|
-
export const createSource = sourceDef.create
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Input descriptor for {@link createFile}, before `id`, `name`, and `extname` are computed
|
|
301
|
-
* and `imports`/`exports`/`sources` are deduplicated.
|
|
302
|
-
*/
|
|
303
|
-
export type UserFileNode<TMeta extends object = object> = Omit<FileNode<TMeta>, 'kind' | 'id' | 'name' | 'extname' | 'imports' | 'exports' | 'sources'> &
|
|
304
|
-
Pick<Partial<FileNode<TMeta>>, 'imports' | 'exports' | 'sources'>
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* Creates a fully resolved `FileNode` from a file input descriptor.
|
|
308
|
-
*
|
|
309
|
-
* Computes:
|
|
310
|
-
* - `id` SHA256 hash of the file path
|
|
311
|
-
* - `name` `baseName` without extension
|
|
312
|
-
* - `extname` extension extracted from `baseName`
|
|
313
|
-
*
|
|
314
|
-
* Deduplicates:
|
|
315
|
-
* - `sources` via `combineSources`
|
|
316
|
-
* - `exports` via `combineExports`
|
|
317
|
-
* - `imports` via `combineImports` (also filters unused imports)
|
|
318
|
-
*
|
|
319
|
-
* @throws {Error} when `baseName` has no extension.
|
|
320
|
-
*
|
|
321
|
-
* @example
|
|
322
|
-
* ```ts
|
|
323
|
-
* const file = createFile({
|
|
324
|
-
* baseName: 'petStore.ts',
|
|
325
|
-
* path: 'src/models/petStore.ts',
|
|
326
|
-
* sources: [createSource({ name: 'Pet', nodes: [createText('export type Pet = { id: number }')] })],
|
|
327
|
-
* imports: [createImport({ name: ['z'], path: 'zod' })],
|
|
328
|
-
* exports: [createExport({ name: ['Pet'], path: './petStore' })],
|
|
329
|
-
* })
|
|
330
|
-
* // file.id = SHA256 hash of 'src/models/petStore.ts'
|
|
331
|
-
* // file.name = 'petStore'
|
|
332
|
-
* // file.extname = '.ts'
|
|
333
|
-
* ```
|
|
334
|
-
*/
|
|
335
|
-
export function createFile<TMeta extends object = object>(input: UserFileNode<TMeta>): FileNode<TMeta> {
|
|
336
|
-
const rawExtname = path.extname(input.baseName)
|
|
337
|
-
// Handle dotfile basename like '.ts' where path.extname returns ''
|
|
338
|
-
const extname = (rawExtname || (input.baseName.startsWith('.') ? input.baseName : '')) as `.${string}`
|
|
339
|
-
if (!extname) {
|
|
340
|
-
throw new Error(`No extname found for ${input.baseName}`)
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
const source = (input.sources ?? [])
|
|
344
|
-
.flatMap((item) => item.nodes ?? [])
|
|
345
|
-
.map((node) => extractStringsFromNodes([node]))
|
|
346
|
-
.filter(Boolean)
|
|
347
|
-
.join('\n\n')
|
|
348
|
-
const resolvedExports = input.exports?.length ? combineExports(input.exports) : []
|
|
349
|
-
const combinedImports = input.imports?.length ? combineImports(input.imports, resolvedExports, source || undefined) : []
|
|
350
|
-
const localNames = new Set((input.sources ?? []).map((item) => item.name).filter((name): name is string => Boolean(name)))
|
|
351
|
-
const nameOf = (item: string | { propertyName: string; name?: string }): string => (typeof item === 'string' ? item : (item.name ?? item.propertyName))
|
|
352
|
-
// Drop self-imports. Consolidating output (`mode: 'file'`) can place a symbol's
|
|
353
|
-
// definition and a cross-file import of it in the same file. The first pass catches imports that
|
|
354
|
-
// resolve to this file's own path. The second drops imports of names the file already defines,
|
|
355
|
-
// the case consolidation produces when the import path no longer matches `input.path`. Sources
|
|
356
|
-
// stay intact, so the local definition remains. Bare specifiers like `'zod'` never match a path.
|
|
357
|
-
const resolvedImports = combinedImports
|
|
358
|
-
.filter((imp) => imp.path !== input.path)
|
|
359
|
-
.flatMap((imp) => {
|
|
360
|
-
if (!Array.isArray(imp.name)) {
|
|
361
|
-
return typeof imp.name === 'string' && localNames.has(imp.name) ? [] : [imp]
|
|
362
|
-
}
|
|
363
|
-
const kept = imp.name.filter((item) => !localNames.has(nameOf(item)))
|
|
364
|
-
if (!kept.length) return []
|
|
365
|
-
return [kept.length === imp.name.length ? imp : { ...imp, name: kept }]
|
|
366
|
-
})
|
|
367
|
-
const resolvedSources = input.sources?.length ? combineSources(input.sources) : []
|
|
368
|
-
|
|
369
|
-
return {
|
|
370
|
-
kind: 'File',
|
|
371
|
-
...input,
|
|
372
|
-
id: hash('sha256', input.path, 'hex'),
|
|
373
|
-
name: trimExtName(input.baseName),
|
|
374
|
-
extname,
|
|
375
|
-
imports: resolvedImports,
|
|
376
|
-
exports: resolvedExports,
|
|
377
|
-
sources: resolvedSources,
|
|
378
|
-
meta: input.meta ?? ({} as TMeta),
|
|
379
|
-
}
|
|
380
|
-
}
|
package/src/nodes/function.ts
DELETED
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
import { defineNode } from '../defineNode.ts'
|
|
2
|
-
import type { BaseNode } from './base.ts'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* A language-agnostic type expression used as a function parameter type annotation.
|
|
6
|
-
*
|
|
7
|
-
* - a plain `string` is a type reference rendered as-is, e.g. `'string'`, `'QueryParams'`, `'Partial<Config>'`
|
|
8
|
-
* - a {@link TypeLiteralNode} is an inline anonymous type, e.g. `{ petId: string; name?: string }`
|
|
9
|
-
* - an {@link IndexedAccessTypeNode} is a single field accessed from a named type, e.g. `PathParams['petId']`
|
|
10
|
-
*/
|
|
11
|
-
export type TypeExpression = string | TypeLiteralNode | IndexedAccessTypeNode
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* AST node for an inline anonymous object type grouping named fields.
|
|
15
|
-
* TypeScript renders as `{ key: Type; other?: OtherType }`.
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* ```ts
|
|
19
|
-
* createTypeLiteral({ members: [{ name: 'petId', type: 'string', optional: false }] })
|
|
20
|
-
* // { petId: string }
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
export type TypeLiteralNode = BaseNode & {
|
|
24
|
-
kind: 'TypeLiteral'
|
|
25
|
-
/**
|
|
26
|
-
* Members of the object type, rendered in order.
|
|
27
|
-
*/
|
|
28
|
-
members: Array<{
|
|
29
|
-
/**
|
|
30
|
-
* Member key.
|
|
31
|
-
*/
|
|
32
|
-
name: string
|
|
33
|
-
/**
|
|
34
|
-
* Member type expression.
|
|
35
|
-
*/
|
|
36
|
-
type: TypeExpression
|
|
37
|
-
/**
|
|
38
|
-
* Whether the member is optional, rendered with `?`.
|
|
39
|
-
*/
|
|
40
|
-
optional?: boolean
|
|
41
|
-
}>
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* AST node for a single field accessed from a named group type.
|
|
46
|
-
* TypeScript renders as `target['key']`.
|
|
47
|
-
*
|
|
48
|
-
* @example
|
|
49
|
-
* ```ts
|
|
50
|
-
* createIndexedAccessType({ target: 'GetPetPathParams', key: 'petId' })
|
|
51
|
-
* // GetPetPathParams['petId']
|
|
52
|
-
* ```
|
|
53
|
-
*/
|
|
54
|
-
export type IndexedAccessTypeNode = BaseNode & {
|
|
55
|
-
kind: 'IndexedAccessType'
|
|
56
|
-
/**
|
|
57
|
-
* Name of the type being indexed, e.g. `'GetPetPathParams'`.
|
|
58
|
-
*/
|
|
59
|
-
target: string
|
|
60
|
-
/**
|
|
61
|
-
* Field key to access, e.g. `'petId'`.
|
|
62
|
-
*/
|
|
63
|
-
key: string
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* AST node for an object destructuring binding, used as the name of a grouped function parameter.
|
|
68
|
-
* TypeScript renders as `{ id, name }` or `{ id: renamed }` when `propertyName` differs.
|
|
69
|
-
*
|
|
70
|
-
* @example
|
|
71
|
-
* ```ts
|
|
72
|
-
* createObjectBindingPattern({ elements: [{ name: 'id' }, { name: 'name' }] })
|
|
73
|
-
* // { id, name }
|
|
74
|
-
* ```
|
|
75
|
-
*/
|
|
76
|
-
export type ObjectBindingPatternNode = BaseNode & {
|
|
77
|
-
kind: 'ObjectBindingPattern'
|
|
78
|
-
/**
|
|
79
|
-
* Bound elements, rendered in order.
|
|
80
|
-
*/
|
|
81
|
-
elements: Array<{
|
|
82
|
-
/**
|
|
83
|
-
* Local binding name.
|
|
84
|
-
*/
|
|
85
|
-
name: string
|
|
86
|
-
/**
|
|
87
|
-
* Source key when it differs from the binding name, rendered as `propertyName: name`.
|
|
88
|
-
*/
|
|
89
|
-
propertyName?: string
|
|
90
|
-
}>
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* AST node for one function parameter.
|
|
95
|
-
*
|
|
96
|
-
* A simple parameter has a `string` name. A destructured group has an
|
|
97
|
-
* {@link ObjectBindingPatternNode} name paired with a {@link TypeLiteralNode} type.
|
|
98
|
-
*
|
|
99
|
-
* @example Required parameter
|
|
100
|
-
* `name: Type`
|
|
101
|
-
*
|
|
102
|
-
* @example Optional parameter
|
|
103
|
-
* `name?: Type`
|
|
104
|
-
*
|
|
105
|
-
* @example Parameter with default value
|
|
106
|
-
* `name: Type = defaultValue`
|
|
107
|
-
*
|
|
108
|
-
* @example Rest parameter
|
|
109
|
-
* `...name: Type[]`
|
|
110
|
-
*
|
|
111
|
-
* @example Destructured group
|
|
112
|
-
* `{ id, name? }: { id: string; name?: string } = {}`
|
|
113
|
-
*/
|
|
114
|
-
export type FunctionParameterNode = BaseNode & {
|
|
115
|
-
kind: 'FunctionParameter'
|
|
116
|
-
/**
|
|
117
|
-
* Parameter name, or an {@link ObjectBindingPatternNode} for a destructured group.
|
|
118
|
-
*/
|
|
119
|
-
name: string | ObjectBindingPatternNode
|
|
120
|
-
/**
|
|
121
|
-
* Type annotation as a {@link TypeExpression}. Omit for untyped output.
|
|
122
|
-
*/
|
|
123
|
-
type?: TypeExpression
|
|
124
|
-
/**
|
|
125
|
-
* Whether the parameter is optional, rendered with `?`.
|
|
126
|
-
*/
|
|
127
|
-
optional?: boolean
|
|
128
|
-
/**
|
|
129
|
-
* Default value, written verbatim after `=`. Commonly `'{}'` for a destructured group.
|
|
130
|
-
*/
|
|
131
|
-
default?: string
|
|
132
|
-
/**
|
|
133
|
-
* When `true` the parameter is emitted as a rest parameter, e.g. `...name: Type[]`.
|
|
134
|
-
*/
|
|
135
|
-
rest?: boolean
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* AST node for a complete function parameter list.
|
|
140
|
-
*
|
|
141
|
-
* Printers are responsible for sorting (`required` → `optional` → `defaulted`).
|
|
142
|
-
* Nodes are plain immutable data.
|
|
143
|
-
*
|
|
144
|
-
* Renders differently depending on the output mode:
|
|
145
|
-
* - `declaration` → `(id: string, config: Config = {})` function declaration parameters
|
|
146
|
-
* - `call` → `(id, { method, url })` function call arguments
|
|
147
|
-
*/
|
|
148
|
-
export type FunctionParametersNode = BaseNode & {
|
|
149
|
-
kind: 'FunctionParameters'
|
|
150
|
-
/**
|
|
151
|
-
* Ordered parameter nodes.
|
|
152
|
-
*/
|
|
153
|
-
params: ReadonlyArray<FunctionParameterNode>
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Union of all function-parameter AST node variants used by the function-parameter printer.
|
|
158
|
-
*/
|
|
159
|
-
export type FunctionParamNode = FunctionParameterNode | FunctionParametersNode | TypeLiteralNode | IndexedAccessTypeNode | ObjectBindingPatternNode
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Handler-map keys for the function-parameter printer, one per {@link FunctionParamNode} kind.
|
|
163
|
-
*/
|
|
164
|
-
export type FunctionParamKind = FunctionParamNode['kind']
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Definition for the {@link TypeLiteralNode}.
|
|
168
|
-
*/
|
|
169
|
-
export const typeLiteralDef = defineNode<TypeLiteralNode, Pick<TypeLiteralNode, 'members'>>({ kind: 'TypeLiteral' })
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Definition for the {@link IndexedAccessTypeNode}.
|
|
173
|
-
*/
|
|
174
|
-
export const indexedAccessTypeDef = defineNode<IndexedAccessTypeNode, Omit<IndexedAccessTypeNode, 'kind'>>({ kind: 'IndexedAccessType' })
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Definition for the {@link ObjectBindingPatternNode}.
|
|
178
|
-
*/
|
|
179
|
-
export const objectBindingPatternDef = defineNode<ObjectBindingPatternNode, Pick<ObjectBindingPatternNode, 'elements'>>({ kind: 'ObjectBindingPattern' })
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Plain property descriptor for a destructured group built by {@link createFunctionParameter}.
|
|
183
|
-
*/
|
|
184
|
-
type FunctionParameterProperty = {
|
|
185
|
-
name: string
|
|
186
|
-
type: TypeExpression
|
|
187
|
-
optional?: boolean
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
type FunctionParameterInput =
|
|
191
|
-
| { name: string; type?: TypeExpression; optional?: boolean; default?: string; rest?: boolean }
|
|
192
|
-
| { properties: Array<FunctionParameterProperty>; optional?: boolean; default?: string }
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Definition for the {@link FunctionParameterNode}. `optional` defaults to `false`.
|
|
196
|
-
* Passing `properties` builds a destructured group: an {@link ObjectBindingPatternNode} name
|
|
197
|
-
* paired with a {@link TypeLiteralNode} type.
|
|
198
|
-
*/
|
|
199
|
-
export const functionParameterDef = defineNode<FunctionParameterNode, FunctionParameterInput>({
|
|
200
|
-
kind: 'FunctionParameter',
|
|
201
|
-
build: (input) => {
|
|
202
|
-
if ('properties' in input) {
|
|
203
|
-
return {
|
|
204
|
-
name: createObjectBindingPattern({ elements: input.properties.map((p) => ({ name: p.name })) }),
|
|
205
|
-
type: createTypeLiteral({ members: input.properties.map((p) => ({ name: p.name, type: p.type, optional: p.optional ?? false })) }),
|
|
206
|
-
optional: input.optional ?? false,
|
|
207
|
-
...(input.default !== undefined ? { default: input.default } : {}),
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
return { optional: false, ...input }
|
|
211
|
-
},
|
|
212
|
-
})
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Definition for the {@link FunctionParametersNode}.
|
|
216
|
-
*/
|
|
217
|
-
export const functionParametersDef = defineNode<FunctionParametersNode, Partial<Omit<FunctionParametersNode, 'kind'>>>({
|
|
218
|
-
kind: 'FunctionParameters',
|
|
219
|
-
defaults: { params: [] },
|
|
220
|
-
})
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Creates a {@link TypeLiteralNode} representing an inline anonymous object type.
|
|
224
|
-
*
|
|
225
|
-
* @example
|
|
226
|
-
* ```ts
|
|
227
|
-
* createTypeLiteral({ members: [{ name: 'petId', type: 'string', optional: false }] })
|
|
228
|
-
* // { petId: string }
|
|
229
|
-
* ```
|
|
230
|
-
*/
|
|
231
|
-
export const createTypeLiteral = typeLiteralDef.create
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Creates an {@link IndexedAccessTypeNode} representing a single field accessed from a named type.
|
|
235
|
-
*
|
|
236
|
-
* @example
|
|
237
|
-
* ```ts
|
|
238
|
-
* createIndexedAccessType({ target: 'DeletePetPathParams', key: 'petId' })
|
|
239
|
-
* // DeletePetPathParams['petId']
|
|
240
|
-
* ```
|
|
241
|
-
*/
|
|
242
|
-
export const createIndexedAccessType = indexedAccessTypeDef.create
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* Creates an {@link ObjectBindingPatternNode} for a destructured parameter binding.
|
|
246
|
-
*
|
|
247
|
-
* @example
|
|
248
|
-
* ```ts
|
|
249
|
-
* createObjectBindingPattern({ elements: [{ name: 'id' }, { name: 'name' }] })
|
|
250
|
-
* // { id, name }
|
|
251
|
-
* ```
|
|
252
|
-
*/
|
|
253
|
-
export const createObjectBindingPattern = objectBindingPatternDef.create
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Creates a `FunctionParameterNode`. `optional` defaults to `false`.
|
|
257
|
-
*
|
|
258
|
-
* @example Optional param
|
|
259
|
-
* ```ts
|
|
260
|
-
* createFunctionParameter({ name: 'params', type: 'QueryParams', optional: true })
|
|
261
|
-
* // → params?: QueryParams
|
|
262
|
-
* ```
|
|
263
|
-
*
|
|
264
|
-
* @example Destructured group
|
|
265
|
-
* ```ts
|
|
266
|
-
* createFunctionParameter({ properties: [{ name: 'id', type: 'string' }, { name: 'name', type: 'string', optional: true }], default: '{}' })
|
|
267
|
-
* // → { id, name }: { id: string; name?: string } = {}
|
|
268
|
-
* ```
|
|
269
|
-
*/
|
|
270
|
-
export const createFunctionParameter = functionParameterDef.create
|
|
271
|
-
|
|
272
|
-
/**
|
|
273
|
-
* Creates a `FunctionParametersNode` from an ordered list of parameters.
|
|
274
|
-
*
|
|
275
|
-
* @example
|
|
276
|
-
* ```ts
|
|
277
|
-
* const empty = createFunctionParameters()
|
|
278
|
-
* // { kind: 'FunctionParameters', params: [] }
|
|
279
|
-
* ```
|
|
280
|
-
*/
|
|
281
|
-
export function createFunctionParameters(props: Partial<Omit<FunctionParametersNode, 'kind'>> = {}): FunctionParametersNode {
|
|
282
|
-
return functionParametersDef.create(props)
|
|
283
|
-
}
|