fork of hey-api/openapi-ts because I need some additional things

chore: symbol ref

Lubos 0b345867 944f14cd

+489 -412
+8 -8
dev/openapi-ts.config.ts
··· 41 41 // 'dutchie.json', 42 42 // 'enum-names-values.yaml', 43 43 // 'invalid', 44 - 'full.yaml', 44 + // 'full.yaml', 45 45 // 'object-property-names.yaml', 46 46 // 'openai.yaml', 47 47 // 'opencode.yaml', ··· 53 53 // 'validators.yaml', 54 54 // 'validators-circular-ref.json', 55 55 // 'validators-circular-ref-2.yaml', 56 - // 'zoom-video-sdk.json', 56 + 'zoom-video-sdk.json', 57 57 ), 58 58 // path: 'https://get.heyapi.dev/hey-api/backend?branch=main&version=1.0.0', 59 59 // path: 'http://localhost:4000/', ··· 83 83 // 'https://somefakedomain.com/openapi.yaml', 84 84 ], 85 85 logs: { 86 - level: 'silent', 86 + // level: 'silent', 87 87 path: './logs', 88 88 }, 89 89 // name: 'foo', ··· 263 263 // }, 264 264 // include... 265 265 // instance: true, 266 - name: '@hey-api/sdk', 266 + // name: '@hey-api/sdk', 267 267 // operationId: false, 268 268 // paramsStructure: 'flat', 269 269 // responseStyle: 'data', ··· 328 328 // name: '{{name}}MO', 329 329 name: 'options', 330 330 }, 331 - name: '@tanstack/react-query', 331 + // name: '@tanstack/react-query', 332 332 queryKeys: { 333 333 // name: '{{name}}QK', 334 334 name: 'options', ··· 374 374 // definitions: 'z{{name}}Definition', 375 375 exportFromIndex: true, 376 376 // metadata: true, 377 - name: 'valibot', 377 + // name: 'valibot', 378 378 // requests: { 379 379 // case: 'PascalCase', 380 380 // name: '{{name}}Data', ··· 451 451 }, 452 452 // exportFromIndex: true, 453 453 metadata: true, 454 - name: 'zod', 454 + // name: 'zod', 455 455 // requests: { 456 456 // // case: 'SCREAMING_SNAKE_CASE', 457 457 // // name: 'z{{name}}TestData', ··· 528 528 httpResources: { 529 529 asClass: true, 530 530 }, 531 - name: '@angular/common', 531 + // name: '@angular/common', 532 532 }, 533 533 { 534 534 exportFromIndex: true,
+3 -3
packages/codegen-core/src/debug.ts
··· 14 14 const value = process.env.DEBUG; 15 15 if (!value) return; 16 16 17 - const groups = value.split(",").map(x => x.trim().toLowerCase()); 17 + const groups = value.split(',').map((x) => x.trim().toLowerCase()); 18 18 19 19 if ( 20 20 !( 21 - groups.includes("*") || 22 - groups.includes("heyapi:*") || 21 + groups.includes('*') || 22 + groups.includes('heyapi:*') || 23 23 groups.includes(`heyapi:${group}`) || 24 24 groups.includes(group) 25 25 )
+4 -4
packages/codegen-core/src/symbols/symbol.ts
··· 84 84 */ 85 85 private _name: string; 86 86 /** 87 - * Root DSL node that defines this symbol. 87 + * Root node that defines this symbol. 88 88 * 89 89 * @private 90 90 */ ··· 311 311 } 312 312 313 313 /** 314 - * Binds the DSL node that defines this symbol. 314 + * Binds the node that defines this symbol. 315 315 * 316 316 * This may only be set once. 317 317 */ 318 318 setRootNode(node: ISyntaxNode): void { 319 319 this.assertCanonical(); 320 320 if (this._rootNode && this._rootNode !== node) { 321 - throw new Error('Symbol is already bound to a different root DSL node.'); 321 + throw new Error('Symbol is already bound to a different root node.'); 322 322 } 323 323 this._rootNode = node; 324 324 } ··· 344 344 private assertCanonical(): void { 345 345 if (this._canonical && this._canonical !== this) { 346 346 const message = `Illegal mutation of stub symbol ${this.toString()} → canonical: ${this._canonical.toString()}`; 347 - debug(message, "symbol"); 347 + debug(message, 'symbol'); 348 348 throw new Error(message); 349 349 } 350 350 }
+4 -4
packages/codegen-core/src/syntax-node.d.ts
··· 2 2 3 3 export interface ISyntaxNode { 4 4 /** 5 - * Return local names introduced by this node. 5 + * Collect symbols referenced directly by this node into the provided accumulator. 6 6 */ 7 - getLocalNames(): Iterable<string>; 7 + collectSymbols(out: Set<Symbol>): void; 8 8 /** 9 - * Return symbols referenced directly by this node. 9 + * Return local names introduced by this node. 10 10 */ 11 - getSymbols(): Iterable<Symbol>; 11 + getLocalNames(): Iterable<string>; 12 12 /** 13 13 * Rewrite local identifiers based on a rename map. 14 14 */
+6
packages/openapi-ts/src/ir/types.d.ts
··· 1 + import type { Symbol } from '@hey-api/codegen-core'; 2 + 1 3 import type { JsonSchemaDraft2020_12 } from '~/openApi/3.1.x/types/json-schema-draft-2020-12'; 2 4 import type { 3 5 SecuritySchemeObject, ··· 185 187 * follow a specific convention. 186 188 */ 187 189 propertyNames?: IRSchemaObject; 190 + /** 191 + * Reference to symbol instead of `$ref` string. 192 + */ 193 + symbolRef?: Symbol; 188 194 /** 189 195 * Each schema eventually resolves into `type`. 190 196 */
+2 -2
packages/openapi-ts/src/plugins/@hey-api/client-core/createClientConfig.ts
··· 49 49 p 50 50 .optional() 51 51 .type( 52 - $.type(symbolConfig.placeholder).generic( 52 + $.type(symbolConfig).generic( 53 53 $.type.and(symbolDefaultClientOptions.placeholder, 'T'), 54 54 ), 55 55 ), 56 56 ) 57 57 .returns( 58 - $.type(symbolConfig.placeholder).generic( 58 + $.type(symbolConfig).generic( 59 59 $.type.and( 60 60 $.type('Required').generic( 61 61 symbolDefaultClientOptions.placeholder,
+1 -1
packages/openapi-ts/src/plugins/@hey-api/sdk/shared/typeOptions.ts
··· 80 80 ) 81 81 .type( 82 82 $.type.and( 83 - $.type(symbolClientOptions.placeholder).$if( 83 + $.type(symbolClientOptions).$if( 84 84 isNuxtClient, 85 85 (t) => 86 86 t
+2 -10
packages/openapi-ts/src/plugins/@hey-api/typescript/shared/operation.ts
··· 210 210 const node = $.type 211 211 .alias(symbol) 212 212 .export() 213 - .type( 214 - $.type(symbolErrors.placeholder).idx( 215 - $.type(symbolErrors.placeholder).keyof(), 216 - ), 217 - ); 213 + .type($.type(symbolErrors).idx($.type(symbolErrors).keyof())); 218 214 plugin.setSymbolValue(symbol, node); 219 215 } 220 216 } ··· 269 265 const node = $.type 270 266 .alias(symbol) 271 267 .export() 272 - .type( 273 - $.type(symbolResponses.placeholder).idx( 274 - $.type(symbolResponses.placeholder).keyof(), 275 - ), 276 - ); 268 + .type($.type(symbolResponses).idx($.type(symbolResponses).keyof())); 277 269 plugin.setSymbolValue(symbol, node); 278 270 } 279 271 }
+8 -20
packages/openapi-ts/src/plugins/@hey-api/typescript/shared/webhook.ts
··· 1 + import type { Symbol } from '@hey-api/codegen-core'; 2 + 1 3 import type { IR } from '~/ir/types'; 2 4 import { buildName } from '~/openApi/shared/utils/name'; 3 5 import { createSchemaComment } from '~/plugins/shared/utils/schema'; ··· 12 14 state, 13 15 }: IrSchemaToAstOptions & { 14 16 operation: IR.OperationObject; 15 - }): string => { 17 + }): Symbol => { 16 18 const data: IR.SchemaObject = { 17 19 type: 'object', 18 20 }; ··· 54 56 ); 55 57 plugin.setSymbolValue(symbolWebhookPayload, node); 56 58 57 - plugin.registerSymbol({ 58 - exported: true, 59 - kind: 'type', 60 - meta: { 61 - category: 'type', 62 - path: state.path.value, 63 - resource: 'definition', 64 - resourceId: symbolWebhookPayload.placeholder, 65 - tags: state.tags?.value, 66 - tool: 'typescript', 67 - }, 68 - name: symbolWebhookPayload.name, 69 - placeholder: symbolWebhookPayload.placeholder, 70 - }); 71 - data.properties.body = { $ref: symbolWebhookPayload.placeholder }; 59 + data.properties.body = { symbolRef: symbolWebhookPayload }; 72 60 dataRequired.push('body'); 73 61 } else { 74 62 data.properties.body = { type: 'never' }; ··· 112 100 ); 113 101 plugin.setSymbolValue(symbolWebhookRequest, node); 114 102 115 - return symbolWebhookRequest.placeholder; 103 + return symbolWebhookRequest; 116 104 }; 117 105 118 106 export const webhookToType = ({ ··· 121 109 state, 122 110 }: IrSchemaToAstOptions & { 123 111 operation: IR.OperationObject; 124 - }): string => { 125 - const name = operationToDataType({ operation, plugin, state }); 126 - return name; 112 + }): Symbol => { 113 + const symbol = operationToDataType({ operation, plugin, state }); 114 + return symbol; 127 115 128 116 // don't handle webhook responses for now, users only need requestBody 129 117 };
-23
packages/openapi-ts/src/plugins/@hey-api/typescript/shared/webhooks.ts
··· 1 - import type { Symbol } from '@hey-api/codegen-core'; 2 - 3 - import { $ } from '~/ts-dsl'; 4 - 5 - import type { HeyApiTypeScriptPlugin } from '../types'; 6 - 7 - export const createWebhooks = ({ 8 - plugin, 9 - symbolWebhooks, 10 - webhookNames, 11 - }: { 12 - plugin: HeyApiTypeScriptPlugin['Instance']; 13 - symbolWebhooks: Symbol; 14 - webhookNames: ReadonlyArray<string>; 15 - }) => { 16 - if (!webhookNames.length) return; 17 - 18 - const node = $.type 19 - .alias(symbolWebhooks) 20 - .export() 21 - .type($.type.or(...webhookNames)); 22 - plugin.setSymbolValue(symbolWebhooks, node); 23 - };
+16 -4
packages/openapi-ts/src/plugins/@hey-api/typescript/v1/plugin.ts
··· 1 + import type { Symbol } from '@hey-api/codegen-core'; 2 + 1 3 import { deduplicateSchema } from '~/ir/schema'; 2 4 import type { IR } from '~/ir/types'; 3 5 import { buildName } from '~/openApi/shared/utils/name'; ··· 11 13 import { operationToType } from '../shared/operation'; 12 14 import type { IrSchemaToAstOptions, PluginState } from '../shared/types'; 13 15 import { webhookToType } from '../shared/webhook'; 14 - import { createWebhooks } from '../shared/webhooks'; 15 16 import type { HeyApiTypeScriptPlugin } from '../types'; 16 17 import { irSchemaWithTypeToAst } from './toAst'; 17 18 ··· 22 23 }: IrSchemaToAstOptions & { 23 24 schema: IR.SchemaObject; 24 25 }): MaybeTsDsl<TypeTsDsl> => { 26 + if (schema.symbolRef) { 27 + return $.type(schema.symbolRef); 28 + } 29 + 25 30 if (schema.$ref) { 26 31 const symbol = plugin.referenceSymbol({ 27 32 category: 'type', ··· 112 117 }); 113 118 114 119 const servers: Array<IR.ServerObject> = []; 115 - const webhookNames: Array<string> = []; 120 + const webhooks: Array<Symbol> = []; 116 121 117 122 plugin.forEach( 118 123 'operation', ··· 159 164 servers.push(event.server); 160 165 break; 161 166 case 'webhook': 162 - webhookNames.push( 167 + webhooks.push( 163 168 webhookToType({ 164 169 operation: event.operation, 165 170 plugin, ··· 175 180 ); 176 181 177 182 createClientOptions({ plugin, servers, symbolClientOptions }); 178 - createWebhooks({ plugin, symbolWebhooks, webhookNames }); 183 + 184 + if (webhooks.length > 0) { 185 + const node = $.type 186 + .alias(symbolWebhooks) 187 + .export() 188 + .type($.type.or(...webhooks)); 189 + plugin.setSymbolValue(symbolWebhooks, node); 190 + } 179 191 };
+2 -2
packages/openapi-ts/src/plugins/@hey-api/typescript/v1/toAst/string.ts
··· 74 74 const node = $.type 75 75 .alias(symbolTypeName) 76 76 .export() 77 - .type($.type(symbolTypeId.placeholder).generic($.type.literal(type))); 77 + .type($.type(symbolTypeId).generic($.type.literal(type))); 78 78 plugin.setSymbolValue(symbolTypeName, node); 79 79 } 80 80 const symbol = plugin.referenceSymbol(query); 81 - return $.type(symbol.placeholder); 81 + return $.type(symbol); 82 82 } 83 83 } 84 84
+2 -4
packages/openapi-ts/src/plugins/@pinia/colada/queryKey.ts
··· 41 41 resource: `${plugin.name}._JSONValue`, 42 42 }); 43 43 44 - const returnType = $.type(symbolQueryKeyType.placeholder) 45 - .generic(TOptionsType) 46 - .idx(0); 44 + const returnType = $.type(symbolQueryKeyType).generic(TOptionsType).idx(0); 47 45 48 46 const baseUrlKey = getClientBaseUrlKey(plugin.context.config); 49 47 ··· 173 171 const queryKeyType = $.type 174 172 .alias(symbolQueryKeyType) 175 173 .export() 176 - .generic(TOptionsType, (g) => g.extends($.type(symbolOptions.placeholder))) 174 + .generic(TOptionsType, (g) => g.extends($.type(symbolOptions))) 177 175 .type( 178 176 $.type.tuple( 179 177 $.type.and(
+1 -3
packages/openapi-ts/src/plugins/@tanstack/query-core/queryKey.ts
··· 49 49 tool: 'sdk', 50 50 }); 51 51 52 - const returnType = $.type(symbolQueryKeyType.placeholder) 53 - .generic(TOptionsType) 54 - .idx(0); 52 + const returnType = $.type(symbolQueryKeyType).generic(TOptionsType).idx(0); 55 53 56 54 const fn = $.const(symbolCreateQueryKey).assign( 57 55 $.func()
+1 -3
packages/openapi-ts/src/plugins/arktype/shared/export.ts
··· 48 48 const inferType = $.type 49 49 .alias(typeInferSymbol) 50 50 .export() 51 - .type( 52 - $.type(symbol.placeholder).attr(identifiers.type.infer).typeofType(), 53 - ); 51 + .type($.type(symbol).attr(identifiers.type.infer).typeofType()); 54 52 plugin.setSymbolValue(typeInferSymbol, inferType); 55 53 } 56 54 };
+9 -21
packages/openapi-ts/src/plugins/fastify/plugin.ts
··· 26 26 type.prop('Body', (p) => 27 27 p 28 28 .required(operation.body!.required) 29 - .type($.type(symbolDataType.placeholder).idx($.type.literal('body'))), 29 + .type($.type(symbolDataType).idx($.type.literal('body'))), 30 30 ); 31 31 } 32 32 ··· 37 37 .required( 38 38 hasParameterGroupObjectRequired(operation.parameters!.header), 39 39 ) 40 - .type( 41 - $.type(symbolDataType.placeholder).idx($.type.literal('headers')), 42 - ), 40 + .type($.type(symbolDataType).idx($.type.literal('headers'))), 43 41 ); 44 42 } 45 43 ··· 49 47 .required( 50 48 hasParameterGroupObjectRequired(operation.parameters!.path), 51 49 ) 52 - .type( 53 - $.type(symbolDataType.placeholder).idx($.type.literal('path')), 54 - ), 50 + .type($.type(symbolDataType).idx($.type.literal('path'))), 55 51 ); 56 52 } 57 53 ··· 61 57 .required( 62 58 hasParameterGroupObjectRequired(operation.parameters!.query), 63 59 ) 64 - .type( 65 - $.type(symbolDataType.placeholder).idx($.type.literal('query')), 66 - ), 60 + .type($.type(symbolDataType).idx($.type.literal('query'))), 67 61 ); 68 62 } 69 63 } ··· 83 77 if (keys.length) { 84 78 const hasDefaultResponse = keys.includes('default'); 85 79 if (!hasDefaultResponse) { 86 - errorsTypeReference = $.type(symbolErrorType.placeholder); 80 + errorsTypeReference = $.type(symbolErrorType); 87 81 } else if (keys.length > 1) { 88 82 errorsTypeReference = $.type('Omit', (t) => 89 - t.generics( 90 - $.type(symbolErrorType.placeholder), 91 - $.type.literal('default'), 92 - ), 83 + t.generics($.type(symbolErrorType), $.type.literal('default')), 93 84 ); 94 85 } 95 86 } ··· 107 98 if (keys.length) { 108 99 const hasDefaultResponse = keys.includes('default'); 109 100 if (!hasDefaultResponse) { 110 - responsesTypeReference = $.type(symbolResponseType.placeholder); 101 + responsesTypeReference = $.type(symbolResponseType); 111 102 } else if (keys.length > 1) { 112 103 responsesTypeReference = $.type('Omit', (t) => 113 - t.generics( 114 - $.type(symbolResponseType.placeholder), 115 - $.type.literal('default'), 116 - ), 104 + t.generics($.type(symbolResponseType), $.type.literal('default')), 117 105 ); 118 106 } 119 107 } ··· 137 125 }); 138 126 return { 139 127 name: operation.id, 140 - type: $.type(symbolRouteHandler.placeholder, (t) => t.generic(type)), 128 + type: $.type(symbolRouteHandler, (t) => t.generic(type)), 141 129 }; 142 130 }; 143 131
+1 -5
packages/openapi-ts/src/plugins/valibot/shared/export.ts
··· 30 30 c.doc(v), 31 31 ) 32 32 .$if(state.hasLazyExpression.value, (c) => 33 - c.type( 34 - $.type(v.placeholder).attr( 35 - ast.typeName || identifiers.types.GenericSchema, 36 - ), 37 - ), 33 + c.type($.type(v).attr(ast.typeName || identifiers.types.GenericSchema)), 38 34 ) 39 35 .assign(pipesToAst({ pipes: ast.pipes, plugin })); 40 36 plugin.setSymbolValue(symbol, statement);
+2 -2
packages/openapi-ts/src/plugins/zod/shared/export.ts
··· 31 31 .$if(plugin.config.comments && createSchemaComment(schema), (c, v) => 32 32 c.doc(v), 33 33 ) 34 - .$if(ast.typeName, (c, v) => c.type($.type(z.placeholder).attr(v))) 34 + .$if(ast.typeName, (c, v) => c.type($.type(z).attr(v))) 35 35 .assign(ast.expression); 36 36 plugin.setSymbolValue(symbol, statement); 37 37 ··· 40 40 .alias(typeInferSymbol) 41 41 .export() 42 42 .type( 43 - $.type(z.placeholder) 43 + $.type(z) 44 44 .attr(identifiers.infer) 45 45 .generic($(symbol.placeholder).typeofType()), 46 46 );
+30 -22
packages/openapi-ts/src/ts-dsl/base.ts
··· 6 6 export type MaybeArray<T> = T | ReadonlyArray<T>; 7 7 8 8 export interface ITsDsl<T extends ts.Node = ts.Node> extends SyntaxNode { 9 - /** Render this DSL node into a concrete TypeScript AST node. */ 9 + /** Render this node into a concrete TypeScript AST. */ 10 10 $render(): T; 11 11 } 12 12 ··· 14 14 export type Constructor<T = ITsDsl> = new (...args: ReadonlyArray<any>) => T; 15 15 16 16 export abstract class TsDsl<T extends ts.Node = ts.Node> implements ITsDsl<T> { 17 - /** Render this DSL node into a concrete TypeScript AST node. */ 17 + /** Render this node into a concrete TypeScript AST. */ 18 18 protected abstract _render(): T; 19 19 20 - /** Walk this node and its children with a visitor. */ 21 - abstract traverse(visitor: (node: SyntaxNode) => void): void; 22 - 23 - /** Parent DSL node in the constructed syntax tree. */ 20 + /** Parent node in the constructed syntax tree. */ 24 21 protected parent?: TsDsl<any>; 25 22 26 23 /** The codegen symbol associated with this node. */ ··· 101 98 return this; 102 99 } 103 100 104 - /** Render this DSL node into a concrete TypeScript AST node. */ 101 + /** Render this node into a concrete TypeScript AST. */ 105 102 $render(): T { 106 103 if (!this.parent) { 107 104 this._validate(); ··· 109 106 return this._render(); 110 107 } 111 108 109 + /** Returns all symbols referenced by this node (directly or through children). */ 110 + // eslint-disable-next-line @typescript-eslint/no-unused-vars 111 + collectSymbols(_out: Set<Symbol>): void { 112 + // noop 113 + } 114 + 112 115 /** Returns all locally declared names within this node. */ 113 116 getLocalNames(): Iterable<string> { 114 117 return []; 115 118 } 116 119 117 - /** Returns all symbols referenced by this node (directly or through children). */ 118 - getSymbols(): Iterable<Symbol> { 119 - return []; 120 - } 121 - 122 120 /** Rewrites internal identifier nodes after final name resolution. */ 123 121 // eslint-disable-next-line @typescript-eslint/no-unused-vars 124 122 rewriteIdentifiers(_map: Map<string, string>): void { 125 123 // noop 126 124 } 127 125 128 - /** Assigns the parent DSL node, enforcing a single-parent invariant. */ 126 + /** Assigns the parent node, enforcing a single-parent invariant. */ 129 127 setParent(parent: TsDsl<any>): this { 130 128 if (this.parent && this.parent !== parent) { 131 129 const message = `${this.constructor.name} already had a parent (${this.parent.constructor.name}), new parent attempted: ${parent.constructor.name}`; ··· 143 141 return this; 144 142 } 145 143 144 + /** Walk this node and its children with a visitor. */ 145 + traverse(visitor: (node: SyntaxNode) => void): void { 146 + visitor(this); 147 + } 148 + 146 149 protected $maybeId<T extends string | ts.Expression>( 147 150 expr: T, 148 151 ): T extends string ? ts.Identifier : T { ··· 201 204 return this.parent ? this.parent.getRootSymbol() : this.symbol!.canonical; 202 205 } 203 206 204 - /** Unwraps nested DSL nodes into raw TypeScript AST nodes. */ 207 + /** Unwraps nested nodes into raw TypeScript AST. */ 205 208 protected unwrap<I>(value: I): I extends TsDsl<infer N> ? N : I { 206 209 return ( 207 - value instanceof TsDsl ? value.$render() : value 210 + value instanceof TsDsl ? value._render() : value 208 211 ) as I extends TsDsl<infer N> ? N : I; 209 212 } 210 213 211 214 /** Validate DSL invariants. */ 212 215 protected _validate(): void { 213 216 if (!this.parent && !this.symbol) { 214 - const message = `${this.constructor.name}: top-level DSL node has no symbol`; 217 + const message = 218 + `${this.constructor.name}: node has neither a parent nor a symbol — ` + 219 + `this likely means the node was never attached to a parent or is incorrectly ` + 220 + `being treated as a root-level construct.`; 215 221 debug(message, 'dsl'); 216 - throw new Error(message); 222 + // TODO: enable later 223 + // throw new Error(message); 217 224 } 218 225 219 226 if (this.parent && this.symbol) { ··· 223 230 } 224 231 225 232 if (this.parent === undefined && this.symbol === undefined) { 226 - const message = `${this.constructor.name}: non-root DSL node is missing a parent`; 233 + const message = `${this.constructor.name}: non-root node is missing a parent`; 227 234 debug(message, 'dsl'); 228 - throw new Error(message); 235 + // TODO: enable later 236 + // throw new Error(message); 229 237 } 230 238 231 239 if (this.symbol && this.symbol.canonical !== this.symbol) { 232 - const message = `${this.constructor.name}: DSL node is holding a non-canonical (stub) symbol`; 240 + const message = `${this.constructor.name}: node is holding a non-canonical (stub) symbol`; 233 241 debug(message, 'dsl'); 234 242 throw new Error(message); 235 243 } 236 244 237 245 this.traverse((node) => { 238 246 const dsl = node as TsDsl<any>; 239 - if (dsl !== this && dsl.parent !== this) { 240 - const message = `${dsl.constructor.name}: child node has incorrect or missing parent`; 247 + if (dsl !== this && !dsl.parent) { 248 + const message = `${dsl.constructor.name}: child node has missing parent`; 241 249 debug(message, 'dsl'); 242 250 throw new Error(message); 243 251 }
+7 -3
packages/openapi-ts/src/ts-dsl/decl/class.ts
··· 37 37 this.symbol.setRootNode(this); 38 38 } 39 39 40 + override collectSymbols(out: Set<Symbol>): void { 41 + console.log(out); 42 + } 43 + 40 44 /** Adds one or more class members (fields, methods, etc.). */ 41 45 do(...items: ReadonlyArray<MaybeTsDsl<ts.ClassElement | ts.Node>>): this { 42 46 for (const item of items) { 43 - if (typeof item === 'object' && 'setParent' in item) { 47 + if (item instanceof TsDsl) { 44 48 item.setParent(this); 45 49 } 46 50 // @ts-expect-error --- IGNORE --- ··· 86 90 return this; 87 91 } 88 92 89 - traverse(visitor: (node: SyntaxNode) => void): void { 90 - console.log(visitor); 93 + override traverse(visitor: (node: SyntaxNode) => void): void { 94 + super.traverse(visitor); 91 95 } 92 96 93 97 protected override _render() {
+10 -5
packages/openapi-ts/src/ts-dsl/decl/decorator.ts
··· 1 - import type { Symbol, SyntaxNode } from '@hey-api/codegen-core'; 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 + import { Symbol } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 16 17 ) { 17 18 super(); 18 19 this.name = name; 19 - if (typeof name !== 'string' && 'id' in name) { 20 + if (name instanceof Symbol) { 20 21 this.getRootSymbol().addDependency(name); 21 22 } 22 23 this.args(...args); 23 24 } 24 25 25 - traverse(visitor: (node: SyntaxNode) => void): void { 26 - console.log(visitor); 26 + override collectSymbols(out: Set<Symbol>): void { 27 + console.log(out); 28 + } 29 + 30 + override traverse(visitor: (node: SyntaxNode) => void): void { 31 + super.traverse(visitor); 27 32 } 28 33 29 34 protected override _render() { 30 35 const target = 31 - typeof this.name !== 'string' && 'id' in this.name 36 + this.name instanceof Symbol 32 37 ? this.$maybeId(this.name.finalName) 33 38 : this.$node(this.name); 34 39
+2 -2
packages/openapi-ts/src/ts-dsl/decl/enum.ts
··· 42 42 return this; 43 43 } 44 44 45 - traverse(visitor: (node: SyntaxNode) => void): void { 46 - console.log(visitor); 45 + override traverse(visitor: (node: SyntaxNode) => void): void { 46 + super.traverse(visitor); 47 47 } 48 48 49 49 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/decl/field.ts
··· 42 42 return this; 43 43 } 44 44 45 - traverse(visitor: (node: SyntaxNode) => void): void { 46 - console.log(visitor); 45 + override traverse(visitor: (node: SyntaxNode) => void): void { 46 + super.traverse(visitor); 47 47 } 48 48 49 49 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/decl/func.ts
··· 97 97 return this; 98 98 } 99 99 100 - traverse(visitor: (node: SyntaxNode) => void): void { 101 - console.log(visitor); 100 + override traverse(visitor: (node: SyntaxNode) => void): void { 101 + super.traverse(visitor); 102 102 } 103 103 104 104 // @ts-expect-error --- need to fix types ---
+2 -2
packages/openapi-ts/src/ts-dsl/decl/getter.ts
··· 42 42 fn?.(this); 43 43 } 44 44 45 - traverse(visitor: (node: SyntaxNode) => void): void { 46 - console.log(visitor); 45 + override traverse(visitor: (node: SyntaxNode) => void): void { 46 + super.traverse(visitor); 47 47 } 48 48 49 49 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/decl/init.ts
··· 26 26 fn?.(this); 27 27 } 28 28 29 - traverse(visitor: (node: SyntaxNode) => void): void { 30 - console.log(visitor); 29 + override traverse(visitor: (node: SyntaxNode) => void): void { 30 + super.traverse(visitor); 31 31 } 32 32 33 33 protected override _render() {
+3 -3
packages/openapi-ts/src/ts-dsl/decl/member.ts
··· 25 25 } 26 26 } 27 27 28 - traverse(visitor: (node: SyntaxNode) => void): void { 29 - console.log(visitor); 28 + override traverse(visitor: (node: SyntaxNode) => void): void { 29 + super.traverse(visitor); 30 30 } 31 31 32 32 /** Sets the enum member value. */ ··· 37 37 38 38 protected override _render() { 39 39 return ts.factory.createEnumMember( 40 - safeMemberName(this._name), 40 + this.$node(safeMemberName(this._name)), 41 41 this.$node(this._value), 42 42 ); 43 43 }
+2 -2
packages/openapi-ts/src/ts-dsl/decl/method.ts
··· 57 57 return this; 58 58 } 59 59 60 - traverse(visitor: (node: SyntaxNode) => void): void { 61 - console.log(visitor); 60 + override traverse(visitor: (node: SyntaxNode) => void): void { 61 + super.traverse(visitor); 62 62 } 63 63 64 64 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/decl/param.ts
··· 30 30 } 31 31 } 32 32 33 - traverse(visitor: (node: SyntaxNode) => void): void { 34 - console.log(visitor); 33 + override traverse(visitor: (node: SyntaxNode) => void): void { 34 + super.traverse(visitor); 35 35 } 36 36 37 37 /** Sets the parameter type. */
+2 -2
packages/openapi-ts/src/ts-dsl/decl/pattern.ts
··· 47 47 return this; 48 48 } 49 49 50 - traverse(visitor: (node: SyntaxNode) => void): void { 51 - console.log(visitor); 50 + override traverse(visitor: (node: SyntaxNode) => void): void { 51 + super.traverse(visitor); 52 52 } 53 53 54 54 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/decl/setter.ts
··· 42 42 fn?.(this); 43 43 } 44 44 45 - traverse(visitor: (node: SyntaxNode) => void): void { 46 - console.log(visitor); 45 + override traverse(visitor: (node: SyntaxNode) => void): void { 46 + super.traverse(visitor); 47 47 } 48 48 49 49 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/expr/array.ts
··· 50 50 return this; 51 51 } 52 52 53 - traverse(visitor: (node: SyntaxNode) => void): void { 54 - console.log(visitor); 53 + override traverse(visitor: (node: SyntaxNode) => void): void { 54 + super.traverse(visitor); 55 55 } 56 56 57 57 protected override _render() {
+2 -3
packages/openapi-ts/src/ts-dsl/expr/as.ts
··· 21 21 this.type = type; 22 22 } 23 23 24 - /** Walk this node and its children with a visitor. */ 25 - traverse(visitor: (node: SyntaxNode) => void): void { 26 - console.log(visitor); 24 + override traverse(visitor: (node: SyntaxNode) => void): void { 25 + super.traverse(visitor); 27 26 } 28 27 29 28 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/expr/attr.ts
··· 35 35 this.right = right; 36 36 } 37 37 38 - traverse(visitor: (node: SyntaxNode) => void): void { 39 - console.log(visitor); 38 + override traverse(visitor: (node: SyntaxNode) => void): void { 39 + super.traverse(visitor); 40 40 } 41 41 42 42 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/expr/await.ts
··· 15 15 this._awaitExpr = expr; 16 16 } 17 17 18 - traverse(visitor: (node: SyntaxNode) => void): void { 19 - console.log(visitor); 18 + override traverse(visitor: (node: SyntaxNode) => void): void { 19 + super.traverse(visitor); 20 20 } 21 21 22 22 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/expr/binary.ts
··· 120 120 return this.opAndExpr('*', expr); 121 121 } 122 122 123 - traverse(visitor: (node: SyntaxNode) => void): void { 124 - console.log(visitor); 123 + override traverse(visitor: (node: SyntaxNode) => void): void { 124 + super.traverse(visitor); 125 125 } 126 126 127 127 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/expr/call.ts
··· 26 26 ); 27 27 } 28 28 29 - traverse(visitor: (node: SyntaxNode) => void): void { 30 - console.log(visitor); 29 + override traverse(visitor: (node: SyntaxNode) => void): void { 30 + super.traverse(visitor); 31 31 } 32 32 33 33 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/expr/expr.ts
··· 20 20 this._exprInput = id; 21 21 } 22 22 23 - traverse(visitor: (node: SyntaxNode) => void): void { 24 - console.log(visitor); 23 + override traverse(visitor: (node: SyntaxNode) => void): void { 24 + super.traverse(visitor); 25 25 } 26 26 27 27 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/expr/id.ts
··· 13 13 this.name = name; 14 14 } 15 15 16 - traverse(visitor: (node: SyntaxNode) => void): void { 17 - console.log(visitor); 16 + override traverse(visitor: (node: SyntaxNode) => void): void { 17 + super.traverse(visitor); 18 18 } 19 19 20 20 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/expr/literal.ts
··· 15 15 this.value = value; 16 16 } 17 17 18 - traverse(visitor: (node: SyntaxNode) => void): void { 19 - console.log(visitor); 18 + override traverse(visitor: (node: SyntaxNode) => void): void { 19 + super.traverse(visitor); 20 20 } 21 21 22 22 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/expr/new.ts
··· 21 21 this.args(...args); 22 22 } 23 23 24 - traverse(visitor: (node: SyntaxNode) => void): void { 25 - console.log(visitor); 24 + override traverse(visitor: (node: SyntaxNode) => void): void { 25 + super.traverse(visitor); 26 26 } 27 27 28 28 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/expr/object.ts
··· 74 74 return this; 75 75 } 76 76 77 - traverse(visitor: (node: SyntaxNode) => void): void { 78 - console.log(visitor); 77 + override traverse(visitor: (node: SyntaxNode) => void): void { 78 + super.traverse(visitor); 79 79 } 80 80 81 81 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/expr/prefix.ts
··· 43 43 return this; 44 44 } 45 45 46 - traverse(visitor: (node: SyntaxNode) => void): void { 47 - console.log(visitor); 46 + override traverse(visitor: (node: SyntaxNode) => void): void { 47 + super.traverse(visitor); 48 48 } 49 49 50 50 protected override _render() {
+9 -5
packages/openapi-ts/src/ts-dsl/expr/prop.ts
··· 36 36 return this.missingRequiredCalls().length === 0; 37 37 } 38 38 39 - traverse(visitor: (node: SyntaxNode) => void): void { 40 - console.log(visitor); 39 + override traverse(visitor: (node: SyntaxNode) => void): void { 40 + super.traverse(visitor); 41 41 } 42 42 43 43 value(value: Expr | Stmt | ((p: ObjectPropTsDsl) => void)) { ··· 61 61 return ts.factory.createSpreadAssignment(node); 62 62 } 63 63 if (this.meta.kind === 'getter') { 64 - const getter = new GetterTsDsl(safePropName(this.meta.name)).do(node); 64 + const getter = new GetterTsDsl( 65 + this.$node(safePropName(this.meta.name)), 66 + ).do(node); 65 67 return this.$node(getter); 66 68 } 67 69 if (this.meta.kind === 'setter') { 68 - const setter = new SetterTsDsl(safePropName(this.meta.name)).do(node); 70 + const setter = new SetterTsDsl( 71 + this.$node(safePropName(this.meta.name)), 72 + ).do(node); 69 73 return this.$node(setter); 70 74 } 71 75 if (ts.isIdentifier(node) && node.text === this.meta.name) { ··· 81 85 ? ts.factory.createComputedPropertyName( 82 86 this.$node(new IdTsDsl(this.meta.name)), 83 87 ) 84 - : safePropName(this.meta.name), 88 + : this.$node(safePropName(this.meta.name)), 85 89 node, 86 90 ); 87 91 }
+2 -2
packages/openapi-ts/src/ts-dsl/expr/regexp.ts
··· 23 23 this.flags = flags; 24 24 } 25 25 26 - traverse(visitor: (node: SyntaxNode) => void): void { 27 - console.log(visitor); 26 + override traverse(visitor: (node: SyntaxNode) => void): void { 27 + super.traverse(visitor); 28 28 } 29 29 30 30 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/expr/template.ts
··· 19 19 return this; 20 20 } 21 21 22 - traverse(visitor: (node: SyntaxNode) => void): void { 23 - console.log(visitor); 22 + override traverse(visitor: (node: SyntaxNode) => void): void { 23 + super.traverse(visitor); 24 24 } 25 25 26 26 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/expr/ternary.ts
··· 31 31 return this; 32 32 } 33 33 34 - traverse(visitor: (node: SyntaxNode) => void): void { 35 - console.log(visitor); 34 + override traverse(visitor: (node: SyntaxNode) => void): void { 35 + super.traverse(visitor); 36 36 } 37 37 38 38 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/expr/typeof.ts
··· 16 16 this._expr = expr; 17 17 } 18 18 19 - traverse(visitor: (node: SyntaxNode) => void): void { 20 - console.log(visitor); 19 + override traverse(visitor: (node: SyntaxNode) => void): void { 20 + super.traverse(visitor); 21 21 } 22 22 23 23 protected override _render() {
-6
packages/openapi-ts/src/ts-dsl/layout/doc.ts
··· 1 - import type { SyntaxNode } from '@hey-api/codegen-core'; 2 1 import ts from 'typescript'; 3 2 4 3 import type { MaybeArray } from '../base'; ··· 57 56 ); 58 57 59 58 return node; 60 - } 61 - 62 - // eslint-disable-next-line @typescript-eslint/no-unused-vars 63 - traverse(_visitor: (node: SyntaxNode) => void): void { 64 - // noop 65 59 } 66 60 67 61 protected override _render(): ts.Node {
-6
packages/openapi-ts/src/ts-dsl/layout/hint.ts
··· 1 - import type { SyntaxNode } from '@hey-api/codegen-core'; 2 1 import ts from 'typescript'; 3 2 4 3 import type { MaybeArray } from '../base'; ··· 39 38 } 40 39 41 40 return node; 42 - } 43 - 44 - // eslint-disable-next-line @typescript-eslint/no-unused-vars 45 - traverse(_visitor: (node: SyntaxNode) => void): void { 46 - // noop 47 41 } 48 42 49 43 protected override _render(): ts.Node {
-6
packages/openapi-ts/src/ts-dsl/layout/newline.ts
··· 1 - import type { SyntaxNode } from '@hey-api/codegen-core'; 2 1 import type ts from 'typescript'; 3 2 4 3 import { TsDsl } from '../base'; 5 4 import { IdTsDsl } from '../expr/id'; 6 5 7 6 export class NewlineTsDsl extends TsDsl<ts.Identifier> { 8 - // eslint-disable-next-line @typescript-eslint/no-unused-vars 9 - traverse(_visitor: (node: SyntaxNode) => void): void { 10 - // noop 11 - } 12 - 13 7 protected override _render(): ts.Identifier { 14 8 return this.$node(new IdTsDsl('\n')); 15 9 }
-6
packages/openapi-ts/src/ts-dsl/layout/note.ts
··· 1 - import type { SyntaxNode } from '@hey-api/codegen-core'; 2 1 import ts from 'typescript'; 3 2 4 3 import type { MaybeArray } from '../base'; ··· 37 36 ); 38 37 39 38 return node; 40 - } 41 - 42 - // eslint-disable-next-line @typescript-eslint/no-unused-vars 43 - traverse(_visitor: (node: SyntaxNode) => void): void { 44 - // noop 45 39 } 46 40 47 41 protected override _render(): ts.Node {
+2 -1
packages/openapi-ts/src/ts-dsl/mixins/args.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import type ts from 'typescript'; 2 3 3 4 import type { MaybeTsDsl } from '../base'; 4 5 import type { BaseCtor, MixinCtor } from './types'; 5 6 6 - export interface ArgsMethods { 7 + export interface ArgsMethods extends SyntaxNode { 7 8 /** Renders the arguments into an array of `Expression`s. */ 8 9 $args(): ReadonlyArray<ts.Expression>; 9 10 /** Adds a single expression argument. */
+6 -1
packages/openapi-ts/src/ts-dsl/mixins/as.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import type ts from 'typescript'; 2 3 3 4 import type { MaybeTsDsl, TypeTsDsl } from '../base'; ··· 14 15 asFactory = factory; 15 16 } 16 17 17 - export interface AsMethods { 18 + export interface AsMethods extends SyntaxNode { 18 19 /** Creates an `as` type assertion expression (e.g. `value as Type`). */ 19 20 as(type: string | TypeTsDsl): AsTsDsl; 20 21 } ··· 25 26 abstract class As extends Base { 26 27 protected as(type: string | TypeTsDsl): AsTsDsl { 27 28 return asFactory!(this, type); 29 + } 30 + 31 + override traverse(visitor: (node: SyntaxNode) => void): void { 32 + super.traverse(visitor); 28 33 } 29 34 } 30 35
+3 -5
packages/openapi-ts/src/ts-dsl/mixins/decorator.ts
··· 1 - import type { Symbol } from '@hey-api/codegen-core'; 1 + import type { Symbol, SyntaxNode } from '@hey-api/codegen-core'; 2 2 import type ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; 5 5 import { DecoratorTsDsl } from '../decl/decorator'; 6 6 import type { BaseCtor, MixinCtor } from './types'; 7 7 8 - export interface DecoratorMethods { 8 + export interface DecoratorMethods extends SyntaxNode { 9 9 /** Renders the decorators into an array of `ts.Decorator`s. */ 10 10 $decorators(): ReadonlyArray<ts.Decorator>; 11 11 /** Adds a decorator (e.g. `@sealed({ in: 'root' })`). */ ··· 25 25 name: Symbol | string | MaybeTsDsl<ts.Expression>, 26 26 ...args: ReadonlyArray<string | MaybeTsDsl<ts.Expression>> 27 27 ): this { 28 - this.decorators.push( 29 - new DecoratorTsDsl(name, ...args).setParent(this as any), 30 - ); 28 + this.decorators.push(new DecoratorTsDsl(name, ...args).setParent(this)); 31 29 return this; 32 30 } 33 31
+2 -1
packages/openapi-ts/src/ts-dsl/mixins/do.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import type ts from 'typescript'; 2 3 3 4 import type { MaybeTsDsl } from '../base'; 4 5 import { StmtTsDsl } from '../stmt/stmt'; 5 6 import type { BaseCtor, MixinCtor } from './types'; 6 7 7 - export interface DoMethods { 8 + export interface DoMethods extends SyntaxNode { 8 9 /** Renders the collected `.do()` calls into an array of `Statement` nodes. */ 9 10 $do(): ReadonlyArray<ts.Statement>; 10 11 /** Adds one or more expressions/statements to the body. */
+2 -1
packages/openapi-ts/src/ts-dsl/mixins/doc.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import type ts from 'typescript'; 2 3 3 4 import type { MaybeArray } from '../base'; 4 5 import { DocTsDsl } from '../layout/doc'; 5 6 import type { BaseCtor, MixinCtor } from './types'; 6 7 7 - export interface DocMethods { 8 + export interface DocMethods extends SyntaxNode { 8 9 doc(lines?: MaybeArray<string>, fn?: (d: DocTsDsl) => void): this; 9 10 } 10 11
+2 -1
packages/openapi-ts/src/ts-dsl/mixins/expr.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import type ts from 'typescript'; 2 3 3 4 import type { MaybeTsDsl } from '../base'; ··· 41 42 returnFactory = factory; 42 43 } 43 44 44 - export interface ExprMethods { 45 + export interface ExprMethods extends SyntaxNode { 45 46 /** Accesses a property on the current expression (e.g. `this.foo`). */ 46 47 attr(name: string | ts.MemberName | number): AttrTsDsl; 47 48 /** Awaits the current expression (e.g. `await expr`). */
+2 -1
packages/openapi-ts/src/ts-dsl/mixins/hint.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import type ts from 'typescript'; 2 3 3 4 import type { MaybeArray } from '../base'; 4 5 import { HintTsDsl } from '../layout/hint'; 5 6 import type { BaseCtor, MixinCtor } from './types'; 6 7 7 - export interface HintMethods { 8 + export interface HintMethods extends SyntaxNode { 8 9 hint(lines?: MaybeArray<string>, fn?: (h: HintTsDsl) => void): this; 9 10 } 10 11
+2 -1
packages/openapi-ts/src/ts-dsl/mixins/layout.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import type ts from 'typescript'; 2 3 3 4 import type { BaseCtor, MixinCtor } from './types'; 4 5 5 - export interface LayoutMethods { 6 + export interface LayoutMethods extends SyntaxNode { 6 7 /** Computes whether output should be multiline based on layout setting and element count. */ 7 8 $multiline(count: number): boolean; 8 9 /** Sets automatic line output with optional threshold (default: 3). */
+1 -1
packages/openapi-ts/src/ts-dsl/mixins/modifiers.ts
··· 12 12 * 13 13 * @param kind - The syntax kind of the modifier to add. 14 14 * @param condition - Whether to add the modifier. 15 - * @returns The parent DSL node for chaining. 15 + * @returns The parent node for chaining. 16 16 */ 17 17 _m(kind: ts.ModifierSyntaxKind, condition: boolean): this; 18 18 }
+2 -1
packages/openapi-ts/src/ts-dsl/mixins/note.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import type ts from 'typescript'; 2 3 3 4 import type { MaybeArray } from '../base'; 4 5 import { NoteTsDsl } from '../layout/note'; 5 6 import type { BaseCtor, MixinCtor } from './types'; 6 7 7 - export interface NoteMethods { 8 + export interface NoteMethods extends SyntaxNode { 8 9 note(lines?: MaybeArray<string>, fn?: (h: NoteTsDsl) => void): this; 9 10 } 10 11
+2 -1
packages/openapi-ts/src/ts-dsl/mixins/operator.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import type ts from 'typescript'; 2 3 3 4 import type { MaybeTsDsl } from '../base'; ··· 6 7 7 8 type Expr = string | MaybeTsDsl<ts.Expression>; 8 9 9 - export interface OperatorMethods { 10 + export interface OperatorMethods extends SyntaxNode { 10 11 /** Logical AND — `this && expr` */ 11 12 and(expr: Expr): BinaryTsDsl; 12 13 /** Creates an assignment expression (e.g. `this = expr`). */
+2 -1
packages/openapi-ts/src/ts-dsl/mixins/optional.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import type ts from 'typescript'; 2 3 3 4 import type { BaseCtor, MixinCtor } from './types'; 4 5 5 - export interface OptionalMethods { 6 + export interface OptionalMethods extends SyntaxNode { 6 7 _optional?: boolean; 7 8 /** Marks the node as optional when the condition is true. */ 8 9 optional(condition?: boolean): this;
+2 -1
packages/openapi-ts/src/ts-dsl/mixins/param.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import type ts from 'typescript'; 2 3 3 4 import type { MaybeTsDsl } from '../base'; 4 5 import { ParamTsDsl } from '../decl/param'; 5 6 import type { BaseCtor, MixinCtor } from './types'; 6 7 7 - export interface ParamMethods { 8 + export interface ParamMethods extends SyntaxNode { 8 9 /** Renders the parameters into an array of `ParameterDeclaration`s. */ 9 10 $params(): ReadonlyArray<ts.ParameterDeclaration>; 10 11 /** Adds a parameter. */
+7 -5
packages/openapi-ts/src/ts-dsl/mixins/pattern.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import type ts from 'typescript'; 2 3 3 4 import type { MaybeArray } from '../base'; 4 5 import { PatternTsDsl } from '../decl/pattern'; 5 6 import type { BaseCtor, MixinCtor } from './types'; 6 7 7 - export interface PatternMethods { 8 + export interface PatternMethods extends SyntaxNode { 8 9 /** Renders the pattern into a `BindingName`. */ 9 10 $pattern(): ts.BindingName | undefined; 10 11 /** Defines an array binding pattern. */ ··· 24 25 Base: TBase, 25 26 ) { 26 27 abstract class Pattern extends Base { 27 - protected pattern: PatternTsDsl = new PatternTsDsl(); 28 + protected pattern?: PatternTsDsl; 28 29 29 30 protected array( 30 31 ...props: ReadonlyArray<string> | [ReadonlyArray<string>] 31 32 ): this { 32 - this.pattern.array(...props); 33 + (this.pattern ??= new PatternTsDsl()).array(...props); 33 34 return this; 34 35 } 35 36 36 37 protected object( 37 38 ...props: ReadonlyArray<MaybeArray<string> | Record<string, string>> 38 39 ): this { 39 - this.pattern.object(...props); 40 + (this.pattern ??= new PatternTsDsl()).object(...props); 40 41 return this; 41 42 } 42 43 43 44 /** Adds a spread element (e.g. `...args`, `...options`) to the pattern. */ 44 45 protected spread(name: string): this { 45 - this.pattern.spread(name); 46 + (this.pattern ??= new PatternTsDsl()).spread(name); 46 47 return this; 47 48 } 48 49 49 50 /** Renders the pattern into a `BindingName`. */ 50 51 protected $pattern(): ts.BindingName | undefined { 52 + if (!this.pattern) return; 51 53 return this.$node(this.pattern); 52 54 } 53 55 }
+24 -4
packages/openapi-ts/src/ts-dsl/mixins/type-args.ts
··· 1 + import type { Symbol, SyntaxNode } from '@hey-api/codegen-core'; 1 2 import type ts from 'typescript'; 2 3 3 4 import type { MaybeTsDsl, TypeTsDsl } from '../base'; 5 + import { TsDsl } from '../base'; 4 6 import type { BaseCtor, MixinCtor } from './types'; 5 7 6 - export interface TypeArgsMethods { 8 + export interface TypeArgsMethods extends SyntaxNode { 7 9 /** Returns the type arguments as an array of ts.TypeNode nodes. */ 8 10 $generics(): ReadonlyArray<ts.TypeNode> | undefined; 9 11 /** Adds a single type argument (e.g. `string` in `Foo<string>`). */ ··· 16 18 Base: TBase, 17 19 ) { 18 20 abstract class TypeArgs extends Base { 19 - protected _generics?: Array<string | MaybeTsDsl<TypeTsDsl>>; 21 + protected _generics: Array<string | MaybeTsDsl<TypeTsDsl>> = []; 20 22 21 23 protected generic(arg: string | MaybeTsDsl<TypeTsDsl>): this { 22 - (this._generics ??= []).push(arg); 24 + if (arg instanceof TsDsl) arg.setParent(this); 25 + this._generics.push(arg); 23 26 return this; 24 27 } 25 28 26 29 protected generics( 27 30 ...args: ReadonlyArray<string | MaybeTsDsl<TypeTsDsl>> 28 31 ): this { 29 - (this._generics ??= []).push(...args); 32 + for (const arg of args) { 33 + if (arg instanceof TsDsl) arg.setParent(this); 34 + this._generics.push(arg); 35 + } 30 36 return this; 31 37 } 32 38 33 39 protected $generics(): ReadonlyArray<ts.TypeNode> | undefined { 34 40 return this.$type(this._generics); 41 + } 42 + 43 + override collectSymbols(out: Set<Symbol>): void { 44 + super.collectSymbols(out); 45 + for (const g of this._generics) { 46 + if (g instanceof TsDsl) g.collectSymbols(out); 47 + } 48 + } 49 + 50 + override traverse(visitor: (node: SyntaxNode) => void): void { 51 + super.traverse(visitor); 52 + for (const g of this._generics) { 53 + if (g instanceof TsDsl) g.traverse(visitor); 54 + } 35 55 } 36 56 } 37 57
+32 -19
packages/openapi-ts/src/ts-dsl/mixins/type-expr.ts
··· 1 + import type { Symbol, SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import type { MaybeTsDsl, TypeTsDsl } from '../base'; ··· 64 65 typeQueryFactory = factory; 65 66 } 66 67 67 - export interface TypeExprMethods { 68 + export interface TypeExprMethods extends SyntaxNode { 68 69 /** Creates an indexed-access type (e.g. `Foo<T>[K]`). */ 69 70 idx( 70 71 this: MaybeTsDsl<TypeTsDsl>, ··· 74 75 keyof(this: MaybeTsDsl<TypeTsDsl>): TypeOperatorTsDsl; 75 76 /** Shorthand: builds `readonly T`. */ 76 77 readonly(this: MaybeTsDsl<TypeTsDsl>): TypeOperatorTsDsl; 77 - /** Create a TypeExpr DSL node representing ReturnType<this>. */ 78 + /** Create a TypeExpr node representing ReturnType<this>. */ 78 79 returnType(this: MaybeTsDsl<ts.Expression>): TypeExprTsDsl; 79 80 /** 80 81 * Create a `typeof` operator that narrows its return type based on the receiver. ··· 91 92 : T extends MaybeTsDsl<TypeTsDsl> 92 93 ? TypeQueryTsDsl 93 94 : TypeQueryTsDsl | TypeOfExprTsDsl; 94 - /** Create a TypeOfExpr DSL node representing typeof this. */ 95 + /** Create a TypeOfExpr node representing typeof this. */ 95 96 typeofExpr(this: MaybeTsDsl<ts.Expression>): TypeOfExprTsDsl; 96 - /** Create a TypeQuery DSL node representing typeof this. */ 97 + /** Create a TypeQuery node representing typeof this. */ 97 98 typeofType(this: MaybeTsDsl<TypeTsDsl | ts.Expression>): TypeQueryTsDsl; 98 99 /** Shorthand: builds `unique T`. */ 99 100 unique(this: MaybeTsDsl<TypeTsDsl>): TypeOperatorTsDsl; ··· 104 105 ) { 105 106 abstract class TypeExpr extends Base { 106 107 protected idx( 107 - this: MaybeTsDsl<TypeTsDsl>, 108 + this: TypeTsDsl, 108 109 index: string | number | MaybeTsDsl<ts.TypeNode>, 109 110 ): TypeIdxTsDsl { 110 111 return typeIdxFactory!(this, index); 111 112 } 112 113 113 - protected keyof(this: MaybeTsDsl<TypeTsDsl>): TypeOperatorTsDsl { 114 + protected keyof(this: TypeTsDsl): TypeOperatorTsDsl { 114 115 return typeOperatorFactory!().keyof(this); 115 116 } 116 117 117 - protected readonly(this: MaybeTsDsl<TypeTsDsl>): TypeOperatorTsDsl { 118 + protected readonly(this: TypeTsDsl): TypeOperatorTsDsl { 118 119 return typeOperatorFactory!().readonly(this); 119 120 } 120 121 121 - protected returnType(this: MaybeTsDsl<ts.Expression>): TypeExprTsDsl { 122 - return typeExprFactory!('ReturnType').generic(typeQueryFactory!(this)); 122 + protected returnType(this: TsDsl<ts.Expression>): TypeExprTsDsl { 123 + const node = typeExprFactory!('ReturnType'); 124 + node.setParent(this); 125 + return node.generic(typeQueryFactory!(this)); 123 126 } 124 127 125 - protected typeofExpr(this: MaybeTsDsl<ts.Expression>): TypeOfExprTsDsl { 128 + protected typeofExpr(this: TsDsl<ts.Expression>): TypeOfExprTsDsl { 126 129 return typeOfExprFactory!(this); 127 130 } 128 131 129 132 protected typeofType( 130 - this: MaybeTsDsl<TypeTsDsl | ts.Expression>, 133 + this: TypeTsDsl | TsDsl<ts.Expression>, 131 134 ): TypeQueryTsDsl { 132 135 return typeQueryFactory!(this); 133 136 } 134 137 135 - protected typeof<T extends MaybeTsDsl<TypeTsDsl | ts.Expression>>( 138 + protected typeof<T extends TypeTsDsl | TsDsl<ts.Expression>>( 136 139 this: T, 137 - ): T extends MaybeTsDsl<ts.Expression> 140 + ): T extends TsDsl<ts.Expression> 138 141 ? TypeOfExprTsDsl 139 - : T extends MaybeTsDsl<TypeTsDsl> 142 + : T extends TypeTsDsl 140 143 ? TypeQueryTsDsl 141 144 : TypeQueryTsDsl | TypeOfExprTsDsl { 142 145 if (this instanceof TsDsl) { 143 - const node = this.$render(); 144 - return ts.isExpression(node) 145 - ? (typeOfExprFactory!(this) as any) 146 - : (typeQueryFactory!(this) as any); 146 + // @ts-expect-error 147 + return ( 148 + ts.isExpression(this._render()) 149 + ? typeOfExprFactory!(this as any) 150 + : typeQueryFactory!(this) 151 + ) as any; 147 152 } 148 153 149 154 if (ts.isExpression(this as any)) { ··· 153 158 return typeQueryFactory!(this) as any; 154 159 } 155 160 156 - protected unique(this: MaybeTsDsl<TypeTsDsl>): TypeOperatorTsDsl { 161 + protected unique(this: TypeTsDsl): TypeOperatorTsDsl { 157 162 return typeOperatorFactory!().unique(this); 163 + } 164 + 165 + override collectSymbols(out: Set<Symbol>): void { 166 + super.collectSymbols(out); 167 + } 168 + 169 + override traverse(visitor: (node: SyntaxNode) => void): void { 170 + super.traverse(visitor); 158 171 } 159 172 } 160 173
+9 -7
packages/openapi-ts/src/ts-dsl/mixins/type-params.ts
··· 1 - import type { Symbol } from '@hey-api/codegen-core'; 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 + import { Symbol } from '@hey-api/codegen-core'; 2 3 import type ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; 6 + import { TsDsl } from '../base'; 5 7 import { TypeParamTsDsl } from '../type/param'; 6 8 import type { BaseCtor, MixinCtor } from './types'; 7 9 8 - export interface TypeParamsMethods { 10 + export interface TypeParamsMethods extends SyntaxNode { 9 11 /** Returns the type parameters as an array of ts.TypeParameterDeclaration nodes. */ 10 12 $generics(): ReadonlyArray<ts.TypeParameterDeclaration> | undefined; 11 13 /** Adds a single type parameter (e.g. `T` in `Array<T>`). */ ··· 20 22 Base: TBase, 21 23 ) { 22 24 abstract class TypeParams extends Base { 23 - protected _generics?: Array<MaybeTsDsl<TypeParamTsDsl>>; 25 + protected _generics: Array<MaybeTsDsl<TypeParamTsDsl>> = []; 24 26 25 27 protected generic( 26 28 ...args: ConstructorParameters<typeof TypeParamTsDsl> 27 29 ): this { 28 30 const g = new TypeParamTsDsl(...args).setParent(this); 29 - (this._generics ??= []).push(g); 31 + this._generics.push(g); 30 32 return this; 31 33 } 32 34 ··· 34 36 ...args: ReadonlyArray<Symbol | string | MaybeTsDsl<TypeParamTsDsl>> 35 37 ): this { 36 38 for (let arg of args) { 37 - if (typeof arg !== 'object' || 'id' in arg) { 39 + if (typeof arg === 'string' || arg instanceof Symbol) { 38 40 arg = new TypeParamTsDsl(arg); 39 41 } 40 - if (typeof arg === 'object' && 'setParent' in arg) { 42 + if (arg instanceof TsDsl) { 41 43 arg.setParent(this); 42 44 } 43 - (this._generics ??= []).push(arg); 45 + this._generics.push(arg); 44 46 } 45 47 return this; 46 48 }
+2 -1
packages/openapi-ts/src/ts-dsl/mixins/value.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import type ts from 'typescript'; 2 3 3 4 import type { MaybeTsDsl } from '../base'; 4 5 import type { BaseCtor, MixinCtor } from './types'; 5 6 6 - export interface ValueMethods { 7 + export interface ValueMethods extends SyntaxNode { 7 8 $value(): ts.Expression | undefined; 8 9 /** Sets the initializer expression (e.g. `= expr`). */ 9 10 assign(expr: string | MaybeTsDsl<ts.Expression>): this;
+2 -2
packages/openapi-ts/src/ts-dsl/stmt/if.ts
··· 26 26 return this; 27 27 } 28 28 29 - traverse(visitor: (node: SyntaxNode) => void): void { 30 - console.log(visitor); 29 + override traverse(visitor: (node: SyntaxNode) => void): void { 30 + super.traverse(visitor); 31 31 } 32 32 33 33 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/stmt/return.ts
··· 15 15 this._returnExpr = expr; 16 16 } 17 17 18 - traverse(visitor: (node: SyntaxNode) => void): void { 19 - console.log(visitor); 18 + override traverse(visitor: (node: SyntaxNode) => void): void { 19 + super.traverse(visitor); 20 20 } 21 21 22 22 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/stmt/stmt.ts
··· 13 13 this._inner = inner; 14 14 } 15 15 16 - traverse(visitor: (node: SyntaxNode) => void): void { 17 - console.log(visitor); 16 + override traverse(visitor: (node: SyntaxNode) => void): void { 17 + super.traverse(visitor); 18 18 } 19 19 20 20 protected override _render() {
+3 -3
packages/openapi-ts/src/ts-dsl/stmt/throw.ts
··· 23 23 return this; 24 24 } 25 25 26 - traverse(visitor: (node: SyntaxNode) => void): void { 27 - console.log(visitor); 26 + override traverse(visitor: (node: SyntaxNode) => void): void { 27 + super.traverse(visitor); 28 28 } 29 29 30 30 protected override _render() { 31 31 const errorNode = this.$node(this.error); 32 32 const messageNode = this.$node(this.msg ? [this.msg] : []).map((expr) => 33 - typeof expr === 'string' ? new LiteralTsDsl(expr).$render() : expr, 33 + typeof expr === 'string' ? this.$node(new LiteralTsDsl(expr)) : expr, 34 34 ); 35 35 if (this.useNew) { 36 36 return ts.factory.createThrowStatement(
+2 -2
packages/openapi-ts/src/ts-dsl/stmt/var.ts
··· 46 46 return this; 47 47 } 48 48 49 - traverse(visitor: (node: SyntaxNode) => void): void { 50 - console.log(visitor); 49 + override traverse(visitor: (node: SyntaxNode) => void): void { 50 + super.traverse(visitor); 51 51 } 52 52 53 53 /** Sets the variable type. */
-6
packages/openapi-ts/src/ts-dsl/token.ts
··· 1 - import type { SyntaxNode } from '@hey-api/codegen-core'; 2 1 import ts from 'typescript'; 3 2 4 3 import { TsDsl } from './base'; ··· 54 53 return (this as TokenTsDsl<ts.SyntaxKind.DotDotDotToken>).kind( 55 54 ts.SyntaxKind.DotDotDotToken, 56 55 ); 57 - } 58 - 59 - // eslint-disable-next-line @typescript-eslint/no-unused-vars 60 - traverse(_visitor: (node: SyntaxNode) => void): void { 61 - // noop 62 56 } 63 57 64 58 protected override _render(): ts.Token<K> {
+28 -9
packages/openapi-ts/src/ts-dsl/type/alias.ts
··· 1 - import type { Symbol, SyntaxNode } from '@hey-api/codegen-core'; 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 + import { Symbol } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 7 8 import { ExportMixin } from '../mixins/modifiers'; 8 9 import { TypeParamsMixin } from '../mixins/type-params'; 9 10 11 + type Name = Symbol | string; 12 + type Value = MaybeTsDsl<ts.TypeNode>; 13 + 10 14 const Mixed = DocMixin( 11 15 ExportMixin(TypeParamsMixin(TsDsl<ts.TypeAliasDeclaration>)), 12 16 ); 13 17 14 18 export class TypeAliasTsDsl extends Mixed { 15 - protected name: string; 16 - protected value?: MaybeTsDsl<ts.TypeNode>; 19 + protected name: Name; 20 + protected value?: Value; 17 21 18 - constructor(name: Symbol | string, fn?: (t: TypeAliasTsDsl) => void) { 22 + constructor(name: Name, fn?: (t: TypeAliasTsDsl) => void) { 19 23 super(); 20 24 if (typeof name === 'string') { 21 25 this.name = name; 22 26 } else { 23 - this.name = name.finalName; 27 + this.name = name; 24 28 this.symbol = name; 25 29 this.symbol.setKind('type'); 26 30 this.symbol.setRootNode(this); ··· 28 32 fn?.(this); 29 33 } 30 34 31 - traverse(visitor: (node: SyntaxNode) => void): void { 32 - console.log(visitor); 35 + override collectSymbols(out: Set<Symbol>): void { 36 + super.collectSymbols(out); 37 + if (this.name instanceof Symbol) { 38 + out.add(this.name); 39 + } 40 + if (this.value instanceof TsDsl) { 41 + this.value.collectSymbols(out); 42 + } 43 + } 44 + 45 + override traverse(visitor: (node: SyntaxNode) => void): void { 46 + super.traverse(visitor); 47 + if (this.value instanceof TsDsl) { 48 + this.value.traverse(visitor); 49 + } 33 50 } 34 51 35 52 /** Sets the type expression on the right-hand side of `= ...`. */ 36 - type(node: MaybeTsDsl<ts.TypeNode>): this { 53 + type(node: Value): this { 37 54 this.value = node; 55 + if (this.value instanceof TsDsl) this.value.setParent(this); 38 56 return this; 39 57 } 40 58 41 59 protected override _render() { 42 60 if (!this.value) 43 61 throw new Error(`Type alias '${this.name}' is missing a type definition`); 62 + const name = this.name instanceof Symbol ? this.name.finalName : this.name; 44 63 return ts.factory.createTypeAliasDeclaration( 45 64 this.modifiers, 46 - this.name, 65 + name, 47 66 this.$generics(), 48 67 this.$type(this.value), 49 68 );
+2 -2
packages/openapi-ts/src/ts-dsl/type/and.ts
··· 13 13 this.types(...nodes); 14 14 } 15 15 16 - traverse(visitor: (node: SyntaxNode) => void): void { 17 - console.log(visitor); 16 + override traverse(visitor: (node: SyntaxNode) => void): void { 17 + super.traverse(visitor); 18 18 } 19 19 20 20 types(...nodes: Array<string | ts.TypeNode | TypeTsDsl>): this {
+46 -25
packages/openapi-ts/src/ts-dsl/type/attr.ts
··· 1 - import type { Symbol, SyntaxNode } from '@hey-api/codegen-core'; 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 + import { Symbol } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; 5 - import { TypeTsDsl } from '../base'; 6 + import { TsDsl, TypeTsDsl } from '../base'; 6 7 import { TypeExprMixin } from '../mixins/type-expr'; 7 8 9 + type Base = Symbol | string | MaybeTsDsl<ts.EntityName>; 10 + type Right = Symbol | string | ts.Identifier; 11 + 8 12 const Mixed = TypeExprMixin(TypeTsDsl<ts.QualifiedName>); 9 13 10 14 export class TypeAttrTsDsl extends Mixed { 11 - protected _base?: Symbol | string | MaybeTsDsl<ts.EntityName>; 12 - protected right: Symbol | string | ts.Identifier; 15 + protected _base?: Base; 16 + protected _right!: Right; 13 17 14 - constructor( 15 - base: Symbol | string | MaybeTsDsl<ts.EntityName>, 16 - right: string | ts.Identifier, 17 - ); 18 - constructor(right: Symbol | string | ts.Identifier); 19 - constructor( 20 - baseOrRight: Symbol | string | MaybeTsDsl<ts.EntityName>, 21 - maybeRight?: Symbol | string | ts.Identifier, 22 - ) { 18 + constructor(base: Base, right: string | ts.Identifier); 19 + constructor(right: Right); 20 + constructor(base: Base, right?: Right) { 23 21 super(); 24 - if (maybeRight) { 25 - this.base(baseOrRight); 26 - this.right = maybeRight; 22 + if (right) { 23 + this.base(base); 24 + this.right(right); 27 25 } else { 28 - this.base(undefined); 29 - this.right = baseOrRight as string | ts.Identifier; 26 + this.base(); 27 + this.right(base as Right); 30 28 } 31 29 } 32 30 33 - base(base?: Symbol | string | MaybeTsDsl<ts.EntityName>): this { 31 + base(base?: Base): this { 34 32 this._base = base; 33 + if (this._base instanceof TsDsl) this._base.setParent(this); 35 34 return this; 36 35 } 37 36 38 - traverse(visitor: (node: SyntaxNode) => void): void { 39 - console.log(visitor); 37 + right(right: Right): this { 38 + this._right = right; 39 + return this; 40 + } 41 + 42 + override collectSymbols(out: Set<Symbol>): void { 43 + super.collectSymbols(out); 44 + if (this._base) { 45 + if (this._base instanceof Symbol) { 46 + out.add(this._base); 47 + } else if (this._base instanceof TsDsl) { 48 + this._base.collectSymbols(out); 49 + } 50 + } 51 + if (this._right instanceof Symbol) { 52 + out.add(this._right); 53 + } 54 + } 55 + 56 + override traverse(visitor: (node: SyntaxNode) => void): void { 57 + super.traverse(visitor); 58 + if (this._base instanceof TsDsl) { 59 + this._base.traverse(visitor); 60 + } 40 61 } 41 62 42 63 protected override _render() { ··· 44 65 throw new Error('TypeAttrTsDsl: missing base for qualified name'); 45 66 } 46 67 const left = 47 - typeof this._base !== 'string' && this._base && 'id' in this._base 68 + this._base instanceof Symbol 48 69 ? this.$node(this._base.finalName) 49 70 : this.$node(this._base); 50 71 if (!ts.isEntityName(left)) { 51 72 throw new Error('TypeAttrTsDsl: base must be an EntityName'); 52 73 } 53 74 const right = 54 - typeof this.right !== 'string' && this.right && 'id' in this.right 55 - ? this.$maybeId(this.right.finalName) 56 - : this.$maybeId(this.right); 75 + this._right instanceof Symbol 76 + ? this.$maybeId(this._right.finalName) 77 + : this.$maybeId(this._right); 57 78 return ts.factory.createQualifiedName(left, right); 58 79 } 59 80 }
+25 -15
packages/openapi-ts/src/ts-dsl/type/expr.ts
··· 1 - import type { Symbol, SyntaxNode } from '@hey-api/codegen-core'; 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 + import { Symbol } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 - import { TypeTsDsl } from '../base'; 5 + import { TsDsl, TypeTsDsl } from '../base'; 5 6 import { TypeArgsMixin } from '../mixins/type-args'; 6 7 import { 7 8 registerLazyAccessTypeExprFactory, ··· 23 24 fn?: (t: TypeExprTsDsl) => void, 24 25 ) { 25 26 super(); 26 - if (name) { 27 - if (typeof name === 'function') { 28 - name(this); 29 - } else { 30 - this._exprInput = name; 31 - if (typeof name !== 'string') { 32 - this.getRootSymbol().addDependency(name); 33 - } 34 - fn?.(this); 35 - } 27 + if (typeof name === 'function') { 28 + name(this); 29 + } else { 30 + this._exprInput = name; 31 + fn?.(this); 36 32 } 37 33 } 38 34 ··· 42 38 right instanceof TypeAttrTsDsl 43 39 ? right.base(this._exprInput) 44 40 : new TypeAttrTsDsl(this._exprInput!, right); 45 - this._exprInput = this._exprInput.setParent(this); 41 + this._exprInput.setParent(this); 46 42 return this; 47 43 } 48 44 49 - traverse(visitor: (node: SyntaxNode) => void): void { 50 - console.log(visitor); 45 + override collectSymbols(out: Set<Symbol>): void { 46 + super.collectSymbols(out); 47 + if (this._exprInput && typeof this._exprInput !== 'string') { 48 + if (this._exprInput instanceof Symbol) { 49 + out.add(this._exprInput); 50 + } else { 51 + this._exprInput.collectSymbols(out); 52 + } 53 + } 54 + } 55 + 56 + override traverse(visitor: (node: SyntaxNode) => void): void { 57 + super.traverse(visitor); 58 + if (this._exprInput instanceof TsDsl) { 59 + this._exprInput.traverse(visitor); 60 + } 51 61 } 52 62 53 63 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/type/func.ts
··· 20 20 return this; 21 21 } 22 22 23 - traverse(visitor: (node: SyntaxNode) => void): void { 24 - console.log(visitor); 23 + override traverse(visitor: (node: SyntaxNode) => void): void { 24 + super.traverse(visitor); 25 25 } 26 26 27 27 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/type/idx-sig.ts
··· 32 32 return this; 33 33 } 34 34 35 - traverse(visitor: (node: SyntaxNode) => void): void { 36 - console.log(visitor); 35 + override traverse(visitor: (node: SyntaxNode) => void): void { 36 + super.traverse(visitor); 37 37 } 38 38 39 39 /** Sets the property type. */
+21 -13
packages/openapi-ts/src/ts-dsl/type/idx.ts
··· 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; 5 - import { TypeTsDsl } from '../base'; 5 + import { TsDsl, TypeTsDsl } from '../base'; 6 6 import { 7 7 registerLazyAccessTypeIdxFactory, 8 8 TypeExprMixin, 9 9 } from '../mixins/type-expr'; 10 + 11 + type Base = string | MaybeTsDsl<ts.TypeNode>; 12 + type Index = string | number | MaybeTsDsl<ts.TypeNode>; 10 13 11 14 const Mixed = TypeExprMixin(TypeTsDsl<ts.IndexedAccessTypeNode>); 12 15 13 16 export class TypeIdxTsDsl extends Mixed { 14 - protected _base: string | MaybeTsDsl<ts.TypeNode>; 15 - protected _index: string | MaybeTsDsl<ts.TypeNode> | number; 17 + protected _base!: Base; 18 + protected _index!: Index; 16 19 17 - constructor( 18 - base: string | MaybeTsDsl<ts.TypeNode>, 19 - index: string | MaybeTsDsl<ts.TypeNode> | number, 20 - ) { 20 + constructor(base: Base, index: Index) { 21 21 super(); 22 - this._base = base; 23 - this._index = index; 22 + this.base(base); 23 + this.index(index); 24 24 } 25 25 26 - base(base: string | MaybeTsDsl<ts.TypeNode>): this { 26 + base(base: Base): this { 27 27 this._base = base; 28 + if (this._base instanceof TsDsl) this._base.setParent(this); 28 29 return this; 29 30 } 30 31 31 - index(index: string | MaybeTsDsl<ts.TypeNode> | number): this { 32 + index(index: Index): this { 32 33 this._index = index; 34 + if (this._index instanceof TsDsl) this._index.setParent(this); 33 35 return this; 34 36 } 35 37 36 - traverse(visitor: (node: SyntaxNode) => void): void { 37 - console.log(visitor); 38 + override traverse(visitor: (node: SyntaxNode) => void): void { 39 + super.traverse(visitor); 40 + if (this._base instanceof TsDsl) { 41 + this._base.traverse(visitor); 42 + } 43 + if (this._index instanceof TsDsl) { 44 + this._index.traverse(visitor); 45 + } 38 46 } 39 47 40 48 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/type/literal.ts
··· 14 14 this.value = value; 15 15 } 16 16 17 - traverse(visitor: (node: SyntaxNode) => void): void { 18 - console.log(visitor); 17 + override traverse(visitor: (node: SyntaxNode) => void): void { 18 + super.traverse(visitor); 19 19 } 20 20 21 21 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/type/mapped.ts
··· 68 68 return this; 69 69 } 70 70 71 - traverse(visitor: (node: SyntaxNode) => void): void { 72 - console.log(visitor); 71 + override traverse(visitor: (node: SyntaxNode) => void): void { 72 + super.traverse(visitor); 73 73 } 74 74 75 75 /** Sets the mapped value type: `[K in X]: ValueType` */
+2 -2
packages/openapi-ts/src/ts-dsl/type/object.ts
··· 34 34 return this; 35 35 } 36 36 37 - traverse(visitor: (node: SyntaxNode) => void): void { 38 - console.log(visitor); 37 + override traverse(visitor: (node: SyntaxNode) => void): void { 38 + super.traverse(visitor); 39 39 } 40 40 41 41 protected override _render() {
+12 -4
packages/openapi-ts/src/ts-dsl/type/operator.ts
··· 1 - import type { SyntaxNode } from '@hey-api/codegen-core'; 1 + import type { Symbol, SyntaxNode } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; 5 - import { TypeTsDsl } from '../base'; 5 + import { TsDsl, TypeTsDsl } from '../base'; 6 6 import { registerLazyAccessTypeOperatorFactory } from '../mixins/type-expr'; 7 7 8 8 type Op = ··· 28 28 export class TypeOperatorTsDsl extends Mixed { 29 29 protected _op?: Op; 30 30 protected _type?: Type; 31 + 32 + override collectSymbols(out: Set<Symbol>): void { 33 + super.collectSymbols(out); 34 + } 31 35 32 36 /** Shorthand: builds `keyof T`. */ 33 37 keyof(type: Type): this { ··· 49 53 return this; 50 54 } 51 55 52 - traverse(visitor: (node: SyntaxNode) => void): void { 53 - console.log(visitor); 56 + override traverse(visitor: (node: SyntaxNode) => void): void { 57 + super.traverse(visitor); 58 + if (this._type instanceof TsDsl) { 59 + this._type.traverse(visitor); 60 + } 54 61 } 55 62 56 63 /** Sets the target type of the operator. */ 57 64 type(type: Type): this { 58 65 this._type = type; 66 + if (this._type instanceof TsDsl) this._type.setParent(this); 59 67 return this; 60 68 } 61 69
+24 -12
packages/openapi-ts/src/ts-dsl/type/or.ts
··· 1 1 import type { SyntaxNode } from '@hey-api/codegen-core'; 2 + import { Symbol } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 - import { TypeTsDsl } from '../base'; 5 + import { TsDsl, TypeTsDsl } from '../base'; 6 + 7 + type Type = Symbol | string | ts.TypeNode | TypeTsDsl; 5 8 6 9 const Mixed = TypeTsDsl<ts.UnionTypeNode>; 7 10 8 11 export class TypeOrTsDsl extends Mixed { 9 - protected _types: Array<string | ts.TypeNode | TypeTsDsl> = []; 12 + protected _types: Array<Type> = []; 10 13 11 - constructor(...nodes: Array<string | ts.TypeNode | TypeTsDsl>) { 14 + constructor(...nodes: Array<Type>) { 12 15 super(); 13 16 this.types(...nodes); 14 17 } 15 18 16 - traverse(visitor: (node: SyntaxNode) => void): void { 17 - console.log(visitor); 19 + override traverse(visitor: (node: SyntaxNode) => void): void { 20 + super.traverse(visitor); 21 + for (const node of this._types) { 22 + if (node instanceof TsDsl) { 23 + node.traverse(visitor); 24 + } 25 + } 18 26 } 19 27 20 - types(...nodes: Array<string | ts.TypeNode | TypeTsDsl>): this { 21 - this._types.push(...nodes); 28 + types(...nodes: Array<Type>): this { 29 + for (const node of nodes) { 30 + if (node instanceof TsDsl) node.setParent(this); 31 + this._types.push(node); 32 + } 22 33 return this; 23 34 } 24 35 25 36 protected override _render() { 26 37 const flat: Array<ts.TypeNode> = []; 27 38 28 - for (const n of this._types) { 29 - const t = this.$type(n); 30 - if (ts.isUnionTypeNode(t)) { 31 - flat.push(...t.types); 39 + for (const node of this._types) { 40 + const value = node instanceof Symbol ? node.finalName : node; 41 + const type = this.$type(value); 42 + if (ts.isUnionTypeNode(type)) { 43 + flat.push(...type.types); 32 44 } else { 33 - flat.push(t); 45 + flat.push(type); 34 46 } 35 47 } 36 48
+6 -2
packages/openapi-ts/src/ts-dsl/type/param.ts
··· 20 20 fn?.(this); 21 21 } 22 22 23 + override collectSymbols(out: Set<Symbol>): void { 24 + console.log(out); 25 + } 26 + 23 27 default(value: string | MaybeTsDsl<TypeTsDsl> | boolean): this { 24 28 this.defaultValue = value; 25 29 return this; ··· 30 34 return this; 31 35 } 32 36 33 - traverse(visitor: (node: SyntaxNode) => void): void { 34 - console.log(visitor); 37 + override traverse(visitor: (node: SyntaxNode) => void): void { 38 + super.traverse(visitor); 35 39 } 36 40 37 41 protected override _render() {
+3 -3
packages/openapi-ts/src/ts-dsl/type/prop.ts
··· 21 21 fn(this); 22 22 } 23 23 24 - traverse(visitor: (node: SyntaxNode) => void): void { 25 - console.log(visitor); 24 + override traverse(visitor: (node: SyntaxNode) => void): void { 25 + super.traverse(visitor); 26 26 } 27 27 28 28 /** Sets the property type. */ ··· 37 37 } 38 38 return ts.factory.createPropertySignature( 39 39 this.modifiers, 40 - safePropName(this.name), 40 + this.$node(safePropName(this.name)), 41 41 this._optional ? this.$node(new TokenTsDsl().optional()) : undefined, 42 42 this.$type(this._type), 43 43 );
+2 -2
packages/openapi-ts/src/ts-dsl/type/query.ts
··· 18 18 this._expr = expr; 19 19 } 20 20 21 - traverse(visitor: (node: SyntaxNode) => void): void { 22 - console.log(visitor); 21 + override traverse(visitor: (node: SyntaxNode) => void): void { 22 + super.traverse(visitor); 23 23 } 24 24 25 25 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/type/template.ts
··· 20 20 return this; 21 21 } 22 22 23 - traverse(visitor: (node: SyntaxNode) => void): void { 24 - console.log(visitor); 23 + override traverse(visitor: (node: SyntaxNode) => void): void { 24 + super.traverse(visitor); 25 25 } 26 26 27 27 protected override _render() {
+2 -2
packages/openapi-ts/src/ts-dsl/type/tuple.ts
··· 18 18 return this; 19 19 } 20 20 21 - traverse(visitor: (node: SyntaxNode) => void): void { 22 - console.log(visitor); 21 + override traverse(visitor: (node: SyntaxNode) => void): void { 22 + super.traverse(visitor); 23 23 } 24 24 25 25 protected override _render() {
+10 -9
packages/openapi-ts/src/ts-dsl/utils/prop.ts
··· 1 - import ts from 'typescript'; 1 + import type ts from 'typescript'; 2 2 3 3 import { numberRegExp, validTypescriptIdentifierRegExp } from '~/utils/regexp'; 4 4 5 + import type { TsDsl } from '../base'; 5 6 import { IdTsDsl } from '../expr/id'; 6 7 import { LiteralTsDsl } from '../expr/literal'; 7 8 8 - export const safeMemberName = (name: string): ts.PropertyName => { 9 + export const safeMemberName = (name: string): TsDsl<ts.PropertyName> => { 9 10 validTypescriptIdentifierRegExp.lastIndex = 0; 10 11 if (validTypescriptIdentifierRegExp.test(name)) { 11 - return new IdTsDsl(name).$render(); 12 + return new IdTsDsl(name); 12 13 } 13 - return new LiteralTsDsl(name).$render() as ts.StringLiteral; 14 + return new LiteralTsDsl(name) as TsDsl<ts.PropertyName>; 14 15 }; 15 16 16 - export const safePropName = (name: string): ts.PropertyName => { 17 + export const safePropName = (name: string): TsDsl<ts.PropertyName> => { 17 18 numberRegExp.lastIndex = 0; 18 19 if (numberRegExp.test(name)) { 19 20 return name.startsWith('-') 20 - ? (new LiteralTsDsl(name).$render() as ts.StringLiteral) 21 - : ts.factory.createNumericLiteral(name); 21 + ? (new LiteralTsDsl(name) as TsDsl<ts.PropertyName>) 22 + : (new LiteralTsDsl(Number(name)) as TsDsl<ts.PropertyName>); 22 23 } 23 24 24 25 validTypescriptIdentifierRegExp.lastIndex = 0; 25 26 if (validTypescriptIdentifierRegExp.test(name)) { 26 - return new IdTsDsl(name).$render(); 27 + return new IdTsDsl(name); 27 28 } 28 29 29 - return new LiteralTsDsl(name).$render() as ts.StringLiteral; 30 + return new LiteralTsDsl(name) as TsDsl<ts.PropertyName>; 30 31 };