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

chore: pass ast context

Lubos ba5be94a 8d5d901c

+582 -366
+1
packages/codegen-core/src/__tests__/exports.test.ts
··· 27 27 // Type-level test: will fail to compile if any type export is missing or renamed 28 28 export type _TypeExports = [ 29 29 index.AnalysisContext, 30 + index.AstContext, 30 31 index.BindingKind, 31 32 index.ExportMember, 32 33 index.ExportModule,
+1
packages/codegen-core/src/__tests__/project.test.ts
··· 48 48 const renderer = file.renderer!; 49 49 50 50 expect(renderer.render).toHaveBeenCalledWith({ 51 + astContext: expect.any(Object), 51 52 file, 52 53 meta: { hello: true }, 53 54 project: p,
+1
packages/codegen-core/src/index.ts
··· 20 20 Language, 21 21 NameConflictResolvers, 22 22 } from './languages/types'; 23 + export type { AstContext } from './nodes/context'; 23 24 export type { INode as Node } from './nodes/node'; 24 25 export type { IOutput as Output } from './output'; 25 26 export {
+11
packages/codegen-core/src/nodes/context.d.ts
··· 1 + import type { INode } from './node'; 2 + 3 + /** 4 + * Context passed to `.toAst()` methods. 5 + */ 6 + export type AstContext = { 7 + /** 8 + * Returns the canonical node for accessing the provided node. 9 + */ 10 + getAccess<T extends INode>(node: T): T; 11 + };
+2 -1
packages/codegen-core/src/nodes/node.d.ts
··· 2 2 import type { Language } from '../languages/types'; 3 3 import type { IAnalysisContext } from '../planner/types'; 4 4 import type { Symbol } from '../symbols/symbol'; 5 + import type { AstContext } from './context'; 5 6 6 7 export interface INode<T = unknown> { 7 8 /** Perform semantic analysis. */ ··· 19 20 /** The symbol associated with this node. */ 20 21 symbol?: Symbol; 21 22 /** Convert this node into AST representation. */ 22 - toAst(): T; 23 + toAst(ctx: AstContext): T; 23 24 /** Brand used for renderer dispatch. */ 24 25 readonly '~brand': string; 25 26 }
+5 -1
packages/codegen-core/src/planner/planner.ts
··· 109 109 if (finalPath) { 110 110 file.setFinalPath(path.resolve(this.project.root, finalPath)); 111 111 } 112 - const ctx: RenderContext = { file, meta, project: this.project }; 112 + const ctx: Omit<RenderContext, 'astContext'> = { 113 + file, 114 + meta, 115 + project: this.project, 116 + }; 113 117 const renderer = this.project.renderers.find((r) => r.supports(ctx)); 114 118 if (renderer) file.setRenderer(renderer); 115 119 }
+12 -1
packages/codegen-core/src/project/project.ts
··· 5 5 import { defaultExtensions } from '../languages/extensions'; 6 6 import { defaultNameConflictResolvers } from '../languages/resolvers'; 7 7 import type { Extensions, NameConflictResolvers } from '../languages/types'; 8 + import type { AstContext } from '../nodes/context'; 8 9 import { NodeRegistry } from '../nodes/registry'; 9 10 import type { IOutput } from '../output'; 10 11 import { Planner } from '../planner/planner'; ··· 60 61 render(meta?: IProjectRenderMeta): ReadonlyArray<IOutput> { 61 62 new Planner(this).plan(meta); 62 63 const files: Array<IOutput> = []; 64 + const astContext: AstContext = { 65 + getAccess(node) { 66 + return node; 67 + }, 68 + }; 63 69 for (const file of this.files.registered()) { 64 70 if (file.finalPath && file.renderer) { 65 - const content = file.renderer.render({ file, meta, project: this }); 71 + const content = file.renderer.render({ 72 + astContext, 73 + file, 74 + meta, 75 + project: this, 76 + }); 66 77 files.push({ content, path: file.finalPath }); 67 78 } 68 79 }
+6 -1
packages/codegen-core/src/renderer.d.ts
··· 1 1 import type { IProjectRenderMeta } from './extensions'; 2 2 import type { File } from './files/file'; 3 + import type { AstContext } from './nodes/context'; 3 4 import type { IProject } from './project/types'; 4 5 5 6 export interface RenderContext { 7 + /** 8 + * The context passed to `.toAst()` methods. 9 + */ 10 + astContext: AstContext; 6 11 /** 7 12 * The current file. 8 13 */ ··· 21 26 /** Renders the given file. */ 22 27 render(ctx: RenderContext): string; 23 28 /** Returns whether this renderer can render the given file. */ 24 - supports(ctx: RenderContext): boolean; 29 + supports(ctx: Omit<RenderContext, 'astContext'>): boolean; 25 30 }
+16 -8
packages/openapi-ts/src/ts-dsl/base.ts
··· 1 1 // TODO: symbol should be protected, but needs to be public to satisfy types 2 2 import type { 3 3 AnalysisContext, 4 + AstContext, 4 5 File, 5 6 FromRef, 6 7 Language, ··· 27 28 parent?: Node; 28 29 root?: Node; 29 30 symbol?: Symbol; 30 - toAst(): T { 31 + // eslint-disable-next-line @typescript-eslint/no-unused-vars 32 + toAst(_: AstContext): T { 31 33 return undefined as unknown as T; 32 34 } 33 35 readonly '~brand' = nodeBrand; ··· 118 120 ) as T extends string ? ts.Identifier : T; 119 121 } 120 122 121 - protected $node<I>(value: I): NodeOfMaybe<I> { 123 + protected $node<I>(ctx: AstContext, value: I): NodeOfMaybe<I> { 122 124 if (value === undefined) { 123 125 return undefined as NodeOfMaybe<I>; 124 126 } ··· 133 135 if (value instanceof Array) { 134 136 return value.map((item) => { 135 137 if (isRef(item)) item = fromRef(item); 136 - return this.unwrap(item); 138 + return this.unwrap(item, ctx); 137 139 }) as NodeOfMaybe<I>; 138 140 } 139 - return this.unwrap(value as any) as NodeOfMaybe<I>; 141 + return this.unwrap(value as any, ctx) as NodeOfMaybe<I>; 140 142 } 141 143 142 144 protected $type<I>( 145 + ctx: AstContext, 143 146 value: I, 144 147 args?: ReadonlyArray<ts.TypeNode>, 145 148 ): TypeOfMaybe<I> { ··· 169 172 ) as TypeOfMaybe<I>; 170 173 } 171 174 if (value instanceof Array) { 172 - return value.map((item) => this.$type(item, args)) as TypeOfMaybe<I>; 175 + return value.map((item) => this.$type(ctx, item, args)) as TypeOfMaybe<I>; 173 176 } 174 - return this.unwrap(value as any) as TypeOfMaybe<I>; 177 + return this.unwrap(value as any, ctx) as TypeOfMaybe<I>; 175 178 } 176 179 177 180 /** Unwraps nested nodes into raw TypeScript AST. */ 178 - private unwrap<I>(value: I): I extends TsDsl<infer N> ? N : I { 179 - return (isNode(value) ? value.toAst() : value) as I extends TsDsl<infer N> 181 + private unwrap<I>( 182 + value: I, 183 + ctx: AstContext, 184 + ): I extends TsDsl<infer N> ? N : I { 185 + return (isNode(value) ? value.toAst(ctx) : value) as I extends TsDsl< 186 + infer N 187 + > 180 188 ? N 181 189 : I; 182 190 }
+15 -11
packages/openapi-ts/src/ts-dsl/decl/class.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { isSymbol, ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 97 102 return this; 98 103 } 99 104 100 - override toAst() { 101 - const body = this.$node(this.body) as ReadonlyArray<ts.ClassElement>; 105 + override toAst(ctx: AstContext) { 106 + const body = this.$node(ctx, this.body) as ReadonlyArray<ts.ClassElement>; 102 107 const node = ts.factory.createClassDeclaration( 103 - [...this.$decorators(), ...this.modifiers], 104 - // @ts-expect-error need to improve types 105 - this.$node(this.name), 106 - this.$generics(), 107 - this._heritage(), 108 + [...this.$decorators(ctx), ...this.modifiers], 109 + this.$node(ctx, this.name) as ts.Identifier, 110 + this.$generics(ctx), 111 + this._heritage(ctx), 108 112 body, 109 113 ); 110 - return this.$docs(node); 114 + return this.$docs(ctx, node); 111 115 } 112 116 113 117 /** Builds heritage clauses (extends). */ 114 - private _heritage(): ReadonlyArray<ts.HeritageClause> { 115 - const node = this.$node(this.baseClass); 118 + private _heritage(ctx: AstContext): ReadonlyArray<ts.HeritageClause> { 119 + const node = this.$node(ctx, this.baseClass); 116 120 if (!node) return []; 117 121 return [ 118 122 ts.factory.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [
+9 -4
packages/openapi-ts/src/ts-dsl/decl/decorator.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { isSymbol, ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 33 38 ctx.analyze(this.name); 34 39 } 35 40 36 - override toAst() { 37 - const target = this.$node(this.name); 38 - const args = this.$args(); 41 + override toAst(ctx: AstContext) { 42 + const target = this.$node(ctx, this.name); 43 + const args = this.$args(ctx); 39 44 return ts.factory.createDecorator( 40 45 args.length 41 46 ? ts.factory.createCallExpression(target, undefined, args)
+10 -6
packages/openapi-ts/src/ts-dsl/decl/enum.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { isSymbol, ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 58 63 return this; 59 64 } 60 65 61 - override toAst() { 66 + override toAst(ctx: AstContext) { 62 67 const node = ts.factory.createEnumDeclaration( 63 68 this.modifiers, 64 - // @ts-expect-error need to improve types 65 - this.$node(this._name), 66 - this.$node(this._members), 69 + this.$node(ctx, this._name) as ts.Identifier, 70 + this.$node(ctx, this._members) as ReadonlyArray<ts.EnumMember>, 67 71 ); 68 - return this.$docs(node); 72 + return this.$docs(ctx, node); 69 73 } 70 74 }
+11 -7
packages/openapi-ts/src/ts-dsl/decl/field.ts
··· 1 - import type { AnalysisContext, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Symbol, 5 + } from '@hey-api/codegen-core'; 2 6 import ts from 'typescript'; 3 7 4 8 import { TsDsl, TypeTsDsl } from '../base'; ··· 53 57 return this; 54 58 } 55 59 56 - override toAst() { 60 + override toAst(ctx: AstContext) { 57 61 const node = ts.factory.createPropertyDeclaration( 58 - [...this.$decorators(), ...this.modifiers], 59 - this.$node(this.name) as ts.PropertyName, 62 + [...this.$decorators(ctx), ...this.modifiers], 63 + this.$node(ctx, this.name) as ts.PropertyName, 60 64 undefined, 61 - this.$type(this._type), 62 - this.$value(), 65 + this.$type(ctx, this._type), 66 + this.$value(ctx), 63 67 ); 64 - return this.$docs(node); 68 + return this.$docs(ctx, node); 65 69 } 66 70 }
+25 -20
packages/openapi-ts/src/ts-dsl/decl/func.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { isSymbol, ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 113 118 } 114 119 115 120 // @ts-expect-error --- need to fix types --- 116 - override toAst(): M extends 'decl' 121 + override toAst( 122 + ctx: AstContext, 123 + ): M extends 'decl' 117 124 ? ts.FunctionDeclaration 118 125 : M extends 'expr' 119 126 ? ts.FunctionExpression 120 127 : ts.ArrowFunction { 121 - const body = this.$node(new BlockTsDsl(...this._do).pretty()); 128 + const body = this.$node(ctx, new BlockTsDsl(...this._do).pretty()); 122 129 123 130 if (this.mode === 'decl') { 124 131 if (!this.name) throw new Error('Function declaration requires a name'); 125 132 const node = ts.factory.createFunctionDeclaration( 126 - [...this.$decorators(), ...this.modifiers], 133 + [...this.$decorators(ctx), ...this.modifiers], 127 134 undefined, 128 - // @ts-expect-error need to improve types 129 - this.$node(this.name), 130 - this.$generics(), 131 - this.$params(), 132 - this.$type(this._returns), 135 + this.$node(ctx, this.name) as ts.Identifier, 136 + this.$generics(ctx), 137 + this.$params(ctx), 138 + this.$type(ctx, this._returns), 133 139 body, 134 140 ) as any; 135 - return this.$docs(node); 141 + return this.$docs(ctx, node); 136 142 } 137 143 138 144 if (this.mode === 'expr') { 139 145 const node = ts.factory.createFunctionExpression( 140 146 this.modifiers, 141 147 undefined, 142 - // @ts-expect-error need to improve types 143 - this.$node(this.name), 144 - this.$generics(), 145 - this.$params(), 146 - this.$type(this._returns), 148 + this.$node(ctx, this.name) as ts.Identifier, 149 + this.$generics(ctx), 150 + this.$params(ctx), 151 + this.$type(ctx, this._returns), 147 152 body, 148 153 ) as any; 149 - return this.$docs(node); 154 + return this.$docs(ctx, node); 150 155 } 151 156 152 157 const node = ts.factory.createArrowFunction( 153 158 this.modifiers, 154 - this.$generics(), 155 - this.$params(), 156 - this.$type(this._returns), 159 + this.$generics(ctx), 160 + this.$params(ctx), 161 + this.$type(ctx, this._returns), 157 162 undefined, 158 163 body.statements.length === 1 && 159 164 ts.isReturnStatement(body.statements[0]!) && ··· 161 166 ? body.statements[0].expression 162 167 : body, 163 168 ) as any; 164 - return this.$docs(node); 169 + return this.$docs(ctx, node); 165 170 } 166 171 } 167 172
+6 -6
packages/openapi-ts/src/ts-dsl/decl/getter.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import { TsDsl } from '../base'; ··· 56 56 } 57 57 } 58 58 59 - override toAst() { 59 + override toAst(ctx: AstContext) { 60 60 const node = ts.factory.createGetAccessorDeclaration( 61 - [...this.$decorators(), ...this.modifiers], 61 + [...this.$decorators(ctx), ...this.modifiers], 62 62 this.name, 63 - this.$params(), 63 + this.$params(ctx), 64 64 undefined, 65 - this.$node(new BlockTsDsl(...this._do).pretty()), 65 + this.$node(ctx, new BlockTsDsl(...this._do).pretty()), 66 66 ); 67 - return this.$docs(node); 67 + return this.$docs(ctx, node); 68 68 } 69 69 }
+6 -6
packages/openapi-ts/src/ts-dsl/decl/init.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import { TsDsl } from '../base'; ··· 38 38 } 39 39 } 40 40 41 - override toAst() { 41 + override toAst(ctx: AstContext) { 42 42 const node = ts.factory.createConstructorDeclaration( 43 - [...this.$decorators(), ...this.modifiers], 44 - this.$params(), 45 - this.$node(new BlockTsDsl(...this._do).pretty()), 43 + [...this.$decorators(ctx), ...this.modifiers], 44 + this.$params(ctx), 45 + this.$node(ctx, new BlockTsDsl(...this._do).pretty()), 46 46 ); 47 - return this.$docs(node); 47 + return this.$docs(ctx, node); 48 48 } 49 49 }
+5 -5
packages/openapi-ts/src/ts-dsl/decl/member.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; ··· 38 38 return this; 39 39 } 40 40 41 - override toAst() { 41 + override toAst(ctx: AstContext) { 42 42 const node = ts.factory.createEnumMember( 43 - this.$node(safeMemberName(this._name)), 44 - this.$node(this._value), 43 + this.$node(ctx, safeMemberName(this._name)), 44 + this.$node(ctx, this._value), 45 45 ); 46 - return this.$docs(node); 46 + return this.$docs(ctx, node); 47 47 } 48 48 }
+9 -9
packages/openapi-ts/src/ts-dsl/decl/method.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import { TsDsl, TypeTsDsl } from '../base'; ··· 70 70 return this; 71 71 } 72 72 73 - override toAst() { 73 + override toAst(ctx: AstContext) { 74 74 const node = ts.factory.createMethodDeclaration( 75 - [...this.$decorators(), ...this.modifiers], 75 + [...this.$decorators(ctx), ...this.modifiers], 76 76 undefined, 77 77 this.name, 78 - this._optional ? this.$node(new TokenTsDsl().optional()) : undefined, 79 - this.$generics(), 80 - this.$params(), 81 - this.$type(this._returns), 82 - this.$node(new BlockTsDsl(...this._do).pretty()), 78 + this._optional ? this.$node(ctx, new TokenTsDsl().optional()) : undefined, 79 + this.$generics(ctx), 80 + this.$params(ctx), 81 + this.$type(ctx, this._returns), 82 + this.$node(ctx, new BlockTsDsl(...this._do).pretty()), 83 83 ); 84 - return this.$docs(node); 84 + return this.$docs(ctx, node); 85 85 } 86 86 }
+12 -7
packages/openapi-ts/src/ts-dsl/decl/param.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { fromRef, isSymbolRef, ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 51 56 return this; 52 57 } 53 58 54 - override toAst() { 55 - let name: string | ReturnType<typeof this.$pattern> = this.$pattern(); 59 + override toAst(ctx: AstContext) { 60 + let name: string | ReturnType<typeof this.$pattern> = this.$pattern(ctx); 56 61 if (!name && this.name) { 57 62 name = isSymbolRef(this.name) 58 63 ? fromRef(this.name).finalName ··· 63 68 'Param must have either a name or a destructuring pattern', 64 69 ); 65 70 return ts.factory.createParameterDeclaration( 66 - this.$decorators(), 71 + this.$decorators(ctx), 67 72 undefined, 68 73 name, 69 - this._optional ? this.$node(new TokenTsDsl().optional()) : undefined, 70 - this.$type(this._type), 71 - this.$value(), 74 + this._optional ? this.$node(ctx, new TokenTsDsl().optional()) : undefined, 75 + this.$type(ctx, this._type), 76 + this.$value(ctx), 72 77 ); 73 78 } 74 79 }
+7 -7
packages/openapi-ts/src/ts-dsl/decl/pattern.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeArray } from '../base'; ··· 53 53 return this; 54 54 } 55 55 56 - override toAst() { 56 + override toAst(ctx: AstContext) { 57 57 if (!this.pattern) { 58 58 throw new Error('PatternTsDsl requires object() or array() pattern'); 59 59 } ··· 70 70 ) 71 71 : ts.factory.createBindingElement(undefined, key, alias, undefined), 72 72 ); 73 - const spread = this.createSpread(); 73 + const spread = this.createSpread(ctx); 74 74 if (spread) elements.push(spread); 75 75 return ts.factory.createObjectBindingPattern(elements); 76 76 } ··· 79 79 const elements = this.pattern.values.map((p) => 80 80 ts.factory.createBindingElement(undefined, undefined, p, undefined), 81 81 ); 82 - const spread = this.createSpread(); 82 + const spread = this.createSpread(ctx); 83 83 if (spread) elements.push(spread); 84 84 return ts.factory.createArrayBindingPattern(elements); 85 85 } ··· 87 87 throw new Error('PatternTsDsl requires object() or array() pattern'); 88 88 } 89 89 90 - private createSpread(): ts.BindingElement | undefined { 90 + private createSpread(ctx: AstContext): ts.BindingElement | undefined { 91 91 return this._spread 92 92 ? ts.factory.createBindingElement( 93 - this.$node(new TokenTsDsl().spread()), 93 + this.$node(ctx, new TokenTsDsl().spread()), 94 94 undefined, 95 - this.$node(new IdTsDsl(this._spread)), 95 + this.$node(ctx, new IdTsDsl(this._spread)), 96 96 ) 97 97 : undefined; 98 98 }
+6 -6
packages/openapi-ts/src/ts-dsl/decl/setter.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import { TsDsl } from '../base'; ··· 56 56 } 57 57 } 58 58 59 - override toAst() { 59 + override toAst(ctx: AstContext) { 60 60 const node = ts.factory.createSetAccessorDeclaration( 61 - [...this.$decorators(), ...this.modifiers], 61 + [...this.$decorators(ctx), ...this.modifiers], 62 62 this.name, 63 - this.$params(), 64 - this.$node(new BlockTsDsl(...this._do).pretty()), 63 + this.$params(ctx), 64 + this.$node(ctx, new BlockTsDsl(...this._do).pretty()), 65 65 ); 66 - return this.$docs(node); 66 + return this.$docs(ctx, node); 67 67 } 68 68 }
+3 -3
packages/openapi-ts/src/ts-dsl/expr/array.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; ··· 59 59 return this; 60 60 } 61 61 62 - override toAst() { 62 + override toAst(ctx: AstContext) { 63 63 const elements = this._elements.map((item) => { 64 - const node = this.$node(item.expr); 64 + const node = this.$node(ctx, item.expr); 65 65 return item.kind === 'spread' 66 66 ? ts.factory.createSpreadElement(node) 67 67 : node;
+9 -4
packages/openapi-ts/src/ts-dsl/expr/as.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 31 36 ctx.analyze(this.type); 32 37 } 33 38 34 - override toAst() { 39 + override toAst(ctx: AstContext) { 35 40 return ts.factory.createAsExpression( 36 - this.$node(this.expr), 37 - this.$type(this.type), 41 + this.$node(ctx, this.expr), 42 + this.$type(ctx, this.type), 38 43 ); 39 44 } 40 45 }
+14 -11
packages/openapi-ts/src/ts-dsl/expr/attr.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { fromRef, ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 44 49 ctx.analyze(this.right); 45 50 } 46 51 47 - override toAst() { 48 - const leftNode = this.$node(this.left); 52 + override toAst(ctx: AstContext) { 53 + const leftNode = this.$node(ctx, this.left); 49 54 regexp.typeScriptIdentifier.lastIndex = 0; 50 55 if ( 51 56 typeof fromRef(this.right) === 'number' || ··· 55 60 if (this._optional) { 56 61 return ts.factory.createElementAccessChain( 57 62 leftNode, 58 - this.$node(new TokenTsDsl().questionDot()), 59 - this.$node(new LiteralTsDsl(fromRef(this.right) as string)), 63 + this.$node(ctx, new TokenTsDsl().questionDot()), 64 + this.$node(ctx, new LiteralTsDsl(fromRef(this.right) as string)), 60 65 ); 61 66 } 62 67 return ts.factory.createElementAccessExpression( 63 68 leftNode, 64 - this.$node(new LiteralTsDsl(fromRef(this.right) as string)), 69 + this.$node(ctx, new LiteralTsDsl(fromRef(this.right) as string)), 65 70 ); 66 71 } 67 72 if (this._optional) { 68 73 return ts.factory.createPropertyAccessChain( 69 74 leftNode, 70 - this.$node(new TokenTsDsl().questionDot()), 71 - // @ts-expect-error ts.MemberName is not properly recognized here 72 - this.$node(this.right), 75 + this.$node(ctx, new TokenTsDsl().questionDot()), 76 + this.$node(ctx, this.right) as ts.MemberName, 73 77 ); 74 78 } 75 79 return ts.factory.createPropertyAccessExpression( 76 80 leftNode, 77 - // @ts-expect-error ts.MemberName is not properly recognized here 78 - this.$node(this.right), 81 + this.$node(ctx, this.right) as ts.MemberName, 79 82 ); 80 83 } 81 84 }
+8 -3
packages/openapi-ts/src/ts-dsl/expr/await.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 26 31 ctx.analyze(this._awaitExpr); 27 32 } 28 33 29 - override toAst() { 30 - return ts.factory.createAwaitExpression(this.$node(this._awaitExpr)); 34 + override toAst(ctx: AstContext) { 35 + return ts.factory.createAwaitExpression(this.$node(ctx, this._awaitExpr)); 31 36 } 32 37 } 33 38
+9 -4
packages/openapi-ts/src/ts-dsl/expr/binary.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 129 134 return this.opAndExpr('*', expr); 130 135 } 131 136 132 - override toAst() { 137 + override toAst(ctx: AstContext) { 133 138 if (!this._op) { 134 139 throw new Error('BinaryTsDsl: missing operator'); 135 140 } 136 - const expr = this.$node(this._expr); 141 + const expr = this.$node(ctx, this._expr); 137 142 if (!expr) { 138 143 throw new Error('BinaryTsDsl: missing right-hand expression'); 139 144 } 140 - const base = this.$node(this._base); 145 + const base = this.$node(ctx, this._base); 141 146 const operator = 142 147 typeof this._op === 'string' ? this.opToToken(this._op) : this._op; 143 148 return ts.factory.createBinaryExpression(base, operator, expr);
+9 -5
packages/openapi-ts/src/ts-dsl/expr/call.ts
··· 1 - import type { AnalysisContext, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Symbol, 5 + } from '@hey-api/codegen-core'; 2 6 import ts from 'typescript'; 3 7 4 8 import type { MaybeTsDsl } from '../base'; ··· 33 37 ctx.analyze(this._callee); 34 38 } 35 39 36 - override toAst() { 40 + override toAst(ctx: AstContext) { 37 41 return ts.factory.createCallExpression( 38 - this.$node(this._callee), 39 - this.$generics(), 40 - this.$args(), 42 + this.$node(ctx, this._callee), 43 + this.$generics(ctx), 44 + this.$args(ctx), 41 45 ); 42 46 } 43 47 }
+8 -3
packages/openapi-ts/src/ts-dsl/expr/expr.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { ref } from '@hey-api/codegen-core'; 3 8 import type ts from 'typescript'; 4 9 ··· 30 35 ctx.analyze(this._exprInput); 31 36 } 32 37 33 - override toAst() { 34 - return this.$node(this._exprInput); 38 + override toAst(ctx: AstContext) { 39 + return this.$node(ctx, this._exprInput); 35 40 } 36 41 }
+5 -3
packages/openapi-ts/src/ts-dsl/expr/literal.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import { TsDsl } from '../base'; ··· 21 21 super.analyze(ctx); 22 22 } 23 23 24 - override toAst() { 24 + override toAst(ctx: AstContext) { 25 25 if (typeof this.value === 'boolean') { 26 26 return this.value ? ts.factory.createTrue() : ts.factory.createFalse(); 27 27 } 28 28 if (typeof this.value === 'number') { 29 29 const expr = ts.factory.createNumericLiteral(Math.abs(this.value)); 30 - return this.value < 0 ? this.$node(new PrefixTsDsl(expr).neg()) : expr; 30 + return this.value < 0 31 + ? this.$node(ctx, new PrefixTsDsl(expr).neg()) 32 + : expr; 31 33 } 32 34 if (typeof this.value === 'string') { 33 35 return ts.factory.createStringLiteral(this.value, true);
+10 -5
packages/openapi-ts/src/ts-dsl/expr/new.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 28 33 ctx.analyze(this.classExpr); 29 34 } 30 35 31 - override toAst() { 36 + override toAst(ctx: AstContext) { 32 37 return ts.factory.createNewExpression( 33 - this.$node(this.classExpr), 34 - this.$generics(), 35 - this.$args(), 38 + this.$node(ctx, this.classExpr), 39 + this.$generics(ctx), 40 + this.$args(ctx), 36 41 ); 37 42 } 38 43 }
+8 -4
packages/openapi-ts/src/ts-dsl/expr/object.ts
··· 1 - import type { AnalysisContext, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Symbol, 5 + } from '@hey-api/codegen-core'; 2 6 import ts from 'typescript'; 3 7 4 8 import type { MaybeTsDsl } from '../base'; ··· 83 87 return this; 84 88 } 85 89 86 - override toAst() { 90 + override toAst(ctx: AstContext) { 87 91 const node = ts.factory.createObjectLiteralExpression( 88 - this.$node(this._props), 92 + this.$node(ctx, this._props), 89 93 this.$multiline(this._props.length), 90 94 ); 91 - return this.$hint(node); 95 + return this.$hint(ctx, node); 92 96 } 93 97 }
+3 -3
packages/openapi-ts/src/ts-dsl/expr/prefix.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; ··· 50 50 return this; 51 51 } 52 52 53 - override toAst() { 53 + override toAst(ctx: AstContext) { 54 54 if (!this._expr) { 55 55 throw new Error('Missing expression for prefix unary expression'); 56 56 } ··· 59 59 } 60 60 return ts.factory.createPrefixUnaryExpression( 61 61 this._op, 62 - this.$node(this._expr), 62 + this.$node(ctx, this._expr), 63 63 ); 64 64 } 65 65 }
+19 -14
packages/openapi-ts/src/ts-dsl/expr/prop.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 53 58 return this; 54 59 } 55 60 56 - override toAst() { 61 + override toAst(ctx: AstContext) { 57 62 this.$validate(); 58 - const node = this.$node(this._value); 63 + const node = this.$node(ctx, this._value); 59 64 if (this.meta.kind === 'spread') { 60 65 if (ts.isStatement(node)) { 61 66 throw new Error( ··· 63 68 ); 64 69 } 65 70 const result = ts.factory.createSpreadAssignment(node); 66 - return this.$docs(result); 71 + return this.$docs(ctx, result); 67 72 } 68 73 if (this.meta.kind === 'getter') { 69 74 const getter = new GetterTsDsl( 70 - this.$node(safePropName(this.meta.name)), 75 + this.$node(ctx, safePropName(this.meta.name)), 71 76 ).do(node); 72 - const result = this.$node(getter); 73 - return this.$docs(result); 77 + const result = this.$node(ctx, getter); 78 + return this.$docs(ctx, result); 74 79 } 75 80 if (this.meta.kind === 'setter') { 76 81 const setter = new SetterTsDsl( 77 - this.$node(safePropName(this.meta.name)), 82 + this.$node(ctx, safePropName(this.meta.name)), 78 83 ).do(node); 79 - const result = this.$node(setter); 80 - return this.$docs(result); 84 + const result = this.$node(ctx, setter); 85 + return this.$docs(ctx, result); 81 86 } 82 87 if (ts.isIdentifier(node) && node.text === this.meta.name) { 83 88 const result = ts.factory.createShorthandPropertyAssignment( 84 89 this.meta.name, 85 90 ); 86 - return this.$docs(result); 91 + return this.$docs(ctx, result); 87 92 } 88 93 if (ts.isStatement(node)) { 89 94 throw new Error( ··· 93 98 const result = ts.factory.createPropertyAssignment( 94 99 this.meta.kind === 'computed' 95 100 ? ts.factory.createComputedPropertyName( 96 - this.$node(new IdTsDsl(this.meta.name)), 101 + this.$node(ctx, new IdTsDsl(this.meta.name)), 97 102 ) 98 - : this.$node(safePropName(this.meta.name)), 103 + : this.$node(ctx, safePropName(this.meta.name)), 99 104 node, 100 105 ); 101 - return this.$docs(result); 106 + return this.$docs(ctx, result); 102 107 } 103 108 104 109 $validate(): asserts this is this & {
+8 -2
packages/openapi-ts/src/ts-dsl/expr/template.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { fromRef, isSymbol, ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 31 36 return this; 32 37 } 33 38 34 - override toAst() { 39 + override toAst(ctx: AstContext) { 35 40 const parts = this.$node( 41 + ctx, 36 42 this.parts.map((p) => { 37 43 const part = fromRef(p); 38 44 return isSymbol(part) ? part.finalName : part;
+5 -5
packages/openapi-ts/src/ts-dsl/expr/ternary.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; ··· 40 40 return this; 41 41 } 42 42 43 - override toAst() { 43 + override toAst(ctx: AstContext) { 44 44 if (!this._condition) throw new Error('Missing condition in ternary'); 45 45 if (!this._then) throw new Error('Missing then expression in ternary'); 46 46 if (!this._else) throw new Error('Missing else expression in ternary'); 47 47 48 48 return ts.factory.createConditionalExpression( 49 - this.$node(this._condition), 49 + this.$node(ctx, this._condition), 50 50 undefined, 51 - this.$node(this._then), 51 + this.$node(ctx, this._then), 52 52 undefined, 53 - this.$node(this._else), 53 + this.$node(ctx, this._else), 54 54 ); 55 55 } 56 56 }
+3 -3
packages/openapi-ts/src/ts-dsl/expr/typeof.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; ··· 23 23 ctx.analyze(this._expr); 24 24 } 25 25 26 - override toAst() { 27 - return ts.factory.createTypeOfExpression(this.$node(this._expr)); 26 + override toAst(ctx: AstContext) { 27 + return ts.factory.createTypeOfExpression(this.$node(ctx, this._expr)); 28 28 } 29 29 } 30 30
+6 -6
packages/openapi-ts/src/ts-dsl/layout/doc.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeArray } from '../base'; 5 5 import { TsDsl } from '../base'; 6 6 import { IdTsDsl } from '../expr/id'; 7 7 8 - type DocMaybeLazy<T> = (() => T) | T; 8 + type DocMaybeLazy<T> = ((ctx: AstContext) => T) | T; 9 9 export type DocFn = (d: DocTsDsl) => void; 10 10 export type DocLines = DocMaybeLazy<MaybeArray<string>>; 11 11 ··· 29 29 return this; 30 30 } 31 31 32 - apply<T extends ts.Node>(node: T): T { 32 + apply<T extends ts.Node>(ctx: AstContext, node: T): T { 33 33 const lines = this._lines.reduce((lines: Array<string>, line: DocLines) => { 34 - if (typeof line === 'function') line = line(); 34 + if (typeof line === 'function') line = line(ctx); 35 35 for (const l of typeof line === 'string' ? [line] : line) { 36 36 if (l || l === '') lines.push(l); 37 37 } ··· 69 69 return node; 70 70 } 71 71 72 - override toAst(): ts.Node { 72 + override toAst(ctx: AstContext): ts.Node { 73 73 // this class does not build a standalone node; 74 74 // it modifies other nodes via `apply()`. 75 75 // Return a dummy comment node for compliance. 76 - return this.$node(new IdTsDsl('')); 76 + return this.$node(ctx, new IdTsDsl('')); 77 77 } 78 78 }
+6 -6
packages/openapi-ts/src/ts-dsl/layout/hint.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeArray } from '../base'; 5 5 import { TsDsl } from '../base'; 6 6 import { IdTsDsl } from '../expr/id'; 7 7 8 - type HintMaybeLazy<T> = (() => T) | T; 8 + type HintMaybeLazy<T> = ((ctx: AstContext) => T) | T; 9 9 export type HintFn = (d: HintTsDsl) => void; 10 10 export type HintLines = HintMaybeLazy<MaybeArray<string>>; 11 11 ··· 29 29 return this; 30 30 } 31 31 32 - apply<T extends ts.Node>(node: T): T { 32 + apply<T extends ts.Node>(ctx: AstContext, node: T): T { 33 33 const lines = this._lines.reduce( 34 34 (lines: Array<string>, line: HintLines) => { 35 - if (typeof line === 'function') line = line(); 35 + if (typeof line === 'function') line = line(ctx); 36 36 for (const l of typeof line === 'string' ? [line] : line) { 37 37 if (l || l === '') lines.push(l); 38 38 } ··· 54 54 return node; 55 55 } 56 56 57 - override toAst(): ts.Node { 57 + override toAst(ctx: AstContext): ts.Node { 58 58 // this class does not build a standalone node; 59 59 // it modifies other nodes via `apply()`. 60 60 // Return a dummy comment node for compliance. 61 - return this.$node(new IdTsDsl('')); 61 + return this.$node(ctx, new IdTsDsl('')); 62 62 } 63 63 }
+3 -3
packages/openapi-ts/src/ts-dsl/layout/newline.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import type ts from 'typescript'; 3 3 4 4 import { TsDsl } from '../base'; ··· 11 11 super.analyze(ctx); 12 12 } 13 13 14 - override toAst(): ts.Identifier { 15 - return this.$node(new IdTsDsl('\n')); 14 + override toAst(ctx: AstContext): ts.Identifier { 15 + return this.$node(ctx, new IdTsDsl('\n')); 16 16 } 17 17 }
+6 -6
packages/openapi-ts/src/ts-dsl/layout/note.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeArray } from '../base'; 5 5 import { TsDsl } from '../base'; 6 6 import { IdTsDsl } from '../expr/id'; 7 7 8 - type NoteMaybeLazy<T> = (() => T) | T; 8 + type NoteMaybeLazy<T> = ((ctx: AstContext) => T) | T; 9 9 export type NoteFn = (d: NoteTsDsl) => void; 10 10 export type NoteLines = NoteMaybeLazy<MaybeArray<string>>; 11 11 ··· 29 29 return this; 30 30 } 31 31 32 - apply<T extends ts.Node>(node: T): T { 32 + apply<T extends ts.Node>(ctx: AstContext, node: T): T { 33 33 const lines = this._lines.reduce( 34 34 (lines: Array<string>, line: NoteLines) => { 35 - if (typeof line === 'function') line = line(); 35 + if (typeof line === 'function') line = line(ctx); 36 36 for (const l of typeof line === 'string' ? [line] : line) { 37 37 if (l || l === '') lines.push(l); 38 38 } ··· 52 52 return node; 53 53 } 54 54 55 - override toAst(): ts.Node { 55 + override toAst(ctx: AstContext): ts.Node { 56 56 // this class does not build a standalone node; 57 57 // it modifies other nodes via `apply()`. 58 58 // Return a dummy comment node for compliance. 59 - return this.$node(new IdTsDsl('')); 59 + return this.$node(ctx, new IdTsDsl('')); 60 60 } 61 61 }
+10 -4
packages/openapi-ts/src/ts-dsl/mixins/args.ts
··· 1 - import type { AnalysisContext, Node, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Node, 5 + Ref, 6 + Symbol, 7 + } from '@hey-api/codegen-core'; 2 8 import { ref } from '@hey-api/codegen-core'; 3 9 import type ts from 'typescript'; 4 10 ··· 9 15 10 16 export interface ArgsMethods extends Node { 11 17 /** Renders the arguments into an array of `Expression`s. */ 12 - $args(): ReadonlyArray<ts.Expression>; 18 + $args(ctx: AstContext): ReadonlyArray<ts.Expression>; 13 19 /** Adds a single expression argument. */ 14 20 arg(arg: Arg | undefined): this; 15 21 /** Adds one or more expression arguments. */ ··· 46 52 return this; 47 53 } 48 54 49 - protected $args(): ReadonlyArray<ts.Expression> { 50 - return this.$node(this._args).map((arg) => this.$node(arg)); 55 + protected $args(ctx: AstContext): ReadonlyArray<ts.Expression> { 56 + return this.$node(ctx, this._args).map((arg) => this.$node(ctx, arg)); 51 57 } 52 58 } 53 59
+9 -4
packages/openapi-ts/src/ts-dsl/mixins/decorator.ts
··· 1 - import type { AnalysisContext, Node, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Node, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import type ts from 'typescript'; 3 8 4 9 import type { MaybeTsDsl } from '../base'; ··· 7 12 8 13 export interface DecoratorMethods extends Node { 9 14 /** Renders the decorators into an array of `ts.Decorator`s. */ 10 - $decorators(): ReadonlyArray<ts.Decorator>; 15 + $decorators(ctx: AstContext): ReadonlyArray<ts.Decorator>; 11 16 /** Adds a decorator (e.g. `@sealed({ in: 'root' })`). */ 12 17 decorator( 13 18 name: Symbol | string | MaybeTsDsl<ts.Expression>, ··· 36 41 return this; 37 42 } 38 43 39 - protected $decorators(): ReadonlyArray<ts.Decorator> { 40 - return this.$node(this.decorators); 44 + protected $decorators(ctx: AstContext): ReadonlyArray<ts.Decorator> { 45 + return this.$node(ctx, this.decorators); 41 46 } 42 47 } 43 48
+7 -4
packages/openapi-ts/src/ts-dsl/mixins/do.ts
··· 1 - import type { AnalysisContext, Node } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext, Node } from '@hey-api/codegen-core'; 2 2 import type ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; ··· 9 9 10 10 export interface DoMethods extends Node { 11 11 /** Renders the collected `.do()` calls into an array of `Statement` nodes. */ 12 - $do(): ReadonlyArray<ts.Statement>; 12 + $do(ctx: AstContext): ReadonlyArray<ts.Statement>; 13 13 _do: Array<DoExpr>; 14 14 /** Adds one or more expressions/statements to the body. */ 15 15 do(...items: ReadonlyArray<DoExpr>): this; ··· 41 41 return this; 42 42 } 43 43 44 - protected $do(): ReadonlyArray<ts.Statement> { 45 - return this.$node(this._do.map((item) => new StmtTsDsl(item))); 44 + protected $do(ctx: AstContext): ReadonlyArray<ts.Statement> { 45 + return this.$node( 46 + ctx, 47 + this._do.map((item) => new StmtTsDsl(item)), 48 + ); 46 49 } 47 50 } 48 51
+4 -4
packages/openapi-ts/src/ts-dsl/mixins/doc.ts
··· 1 - import type { AnalysisContext, Node } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext, Node } from '@hey-api/codegen-core'; 2 2 import type ts from 'typescript'; 3 3 4 4 import type { DocFn, DocLines } from '../layout/doc'; ··· 6 6 import type { BaseCtor, MixinCtor } from './types'; 7 7 8 8 export interface DocMethods extends Node { 9 - $docs<T extends ts.Node>(node: T): T; 9 + $docs<T extends ts.Node>(ctx: AstContext, node: T): T; 10 10 doc(lines?: DocLines, fn?: DocFn): this; 11 11 } 12 12 ··· 25 25 return this; 26 26 } 27 27 28 - protected $docs<T extends ts.Node>(node: T): T { 29 - return this._doc ? this._doc.apply(node) : node; 28 + protected $docs<T extends ts.Node>(ctx: AstContext, node: T): T { 29 + return this._doc ? this._doc.apply(ctx, node) : node; 30 30 } 31 31 } 32 32
+4 -4
packages/openapi-ts/src/ts-dsl/mixins/hint.ts
··· 1 - import type { AnalysisContext, Node } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext, Node } from '@hey-api/codegen-core'; 2 2 import type ts from 'typescript'; 3 3 4 4 import type { HintFn, HintLines } from '../layout/hint'; ··· 6 6 import type { BaseCtor, MixinCtor } from './types'; 7 7 8 8 export interface HintMethods extends Node { 9 - $hint<T extends ts.Node>(node: T): T; 9 + $hint<T extends ts.Node>(ctx: AstContext, node: T): T; 10 10 hint(lines?: HintLines, fn?: HintFn): this; 11 11 } 12 12 ··· 25 25 return this; 26 26 } 27 27 28 - protected $hint<T extends ts.Node>(node: T): T { 29 - return this._hint ? this._hint.apply(node) : node; 28 + protected $hint<T extends ts.Node>(ctx: AstContext, node: T): T { 29 + return this._hint ? this._hint.apply(ctx, node) : node; 30 30 } 31 31 } 32 32
+4 -4
packages/openapi-ts/src/ts-dsl/mixins/note.ts
··· 1 - import type { AnalysisContext, Node } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext, Node } from '@hey-api/codegen-core'; 2 2 import type ts from 'typescript'; 3 3 4 4 import type { NoteFn, NoteLines } from '../layout/note'; ··· 6 6 import type { BaseCtor, MixinCtor } from './types'; 7 7 8 8 export interface NoteMethods extends Node { 9 - $note<T extends ts.Node>(node: T): T; 9 + $note<T extends ts.Node>(ctx: AstContext, node: T): T; 10 10 note(lines?: NoteLines, fn?: NoteFn): this; 11 11 } 12 12 ··· 25 25 return this; 26 26 } 27 27 28 - protected $note<T extends ts.Node>(node: T): T { 29 - return this._note ? this._note.apply(node) : node; 28 + protected $note<T extends ts.Node>(ctx: AstContext, node: T): T { 29 + return this._note ? this._note.apply(ctx, node) : node; 30 30 } 31 31 } 32 32
+4 -4
packages/openapi-ts/src/ts-dsl/mixins/param.ts
··· 1 - import type { AnalysisContext, Node } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext, Node } from '@hey-api/codegen-core'; 2 2 import type ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; ··· 8 8 9 9 export interface ParamMethods extends Node { 10 10 /** Renders the parameters into an array of `ParameterDeclaration`s. */ 11 - $params(): ReadonlyArray<ts.ParameterDeclaration>; 11 + $params(ast: AstContext): ReadonlyArray<ts.ParameterDeclaration>; 12 12 /** Adds a parameter. */ 13 13 param(...args: Parameters<ParamCtor>): this; 14 14 /** Adds multiple parameters. */ ··· 44 44 return this; 45 45 } 46 46 47 - protected $params(): ReadonlyArray<ts.ParameterDeclaration> { 48 - return this.$node(this._params); 47 + protected $params(ctx: AstContext): ReadonlyArray<ts.ParameterDeclaration> { 48 + return this.$node(ctx, this._params); 49 49 } 50 50 } 51 51
+4 -4
packages/openapi-ts/src/ts-dsl/mixins/pattern.ts
··· 1 - import type { AnalysisContext, Node } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext, Node } from '@hey-api/codegen-core'; 2 2 import type ts from 'typescript'; 3 3 4 4 import type { MaybeArray } from '../base'; ··· 7 7 8 8 export interface PatternMethods extends Node { 9 9 /** Renders the pattern into a `BindingName`. */ 10 - $pattern(): ts.BindingName | undefined; 10 + $pattern(ctx: AstContext): ts.BindingName | undefined; 11 11 /** Defines an array binding pattern. */ 12 12 array(...props: ReadonlyArray<string> | [ReadonlyArray<string>]): this; 13 13 /** Defines an object binding pattern. */ ··· 53 53 } 54 54 55 55 /** Renders the pattern into a `BindingName`. */ 56 - protected $pattern(): ts.BindingName | undefined { 56 + protected $pattern(ctx: AstContext): ts.BindingName | undefined { 57 57 if (!this.pattern) return; 58 - return this.$node(this.pattern); 58 + return this.$node(ctx, this.pattern); 59 59 } 60 60 } 61 61
+12 -4
packages/openapi-ts/src/ts-dsl/mixins/type-args.ts
··· 1 - import type { AnalysisContext, Node, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Node, 5 + Ref, 6 + Symbol, 7 + } from '@hey-api/codegen-core'; 2 8 import { ref } from '@hey-api/codegen-core'; 3 9 import type ts from 'typescript'; 4 10 ··· 9 15 10 16 export interface TypeArgsMethods extends Node { 11 17 /** Returns the type arguments as an array of ts.TypeNode nodes. */ 12 - $generics(): ReadonlyArray<ts.TypeNode> | undefined; 18 + $generics(ctx: AstContext): ReadonlyArray<ts.TypeNode> | undefined; 13 19 /** Adds a single type argument (e.g. `string` in `Foo<string>`). */ 14 20 generic(arg: Arg): this; 15 21 /** Adds type arguments (e.g. `Map<string, number>`). */ ··· 39 45 return this; 40 46 } 41 47 42 - protected $generics(): ReadonlyArray<ts.TypeNode> | undefined { 43 - return this.$type(this._generics); 48 + protected $generics( 49 + ctx: AstContext, 50 + ): ReadonlyArray<ts.TypeNode> | undefined { 51 + return this.$type(ctx, this._generics); 44 52 } 45 53 } 46 54
+13 -6
packages/openapi-ts/src/ts-dsl/mixins/type-params.ts
··· 1 - import type { AnalysisContext, Node, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Node, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { isSymbol } from '@hey-api/codegen-core'; 3 8 import type ts from 'typescript'; 4 9 ··· 8 13 9 14 export interface TypeParamsMethods extends Node { 10 15 /** Returns the type parameters as an array of ts.TypeParameterDeclaration nodes. */ 11 - $generics(): ReadonlyArray<ts.TypeParameterDeclaration> | undefined; 16 + $generics( 17 + ast: AstContext, 18 + ): ReadonlyArray<ts.TypeParameterDeclaration> | undefined; 12 19 /** Adds a single type parameter (e.g. `T` in `Array<T>`). */ 13 20 generic(...args: ConstructorParameters<typeof TypeParamTsDsl>): this; 14 21 /** Adds type parameters (e.g. `Map<string, T>`). */ ··· 50 57 return this; 51 58 } 52 59 53 - protected $generics(): 54 - | ReadonlyArray<ts.TypeParameterDeclaration> 55 - | undefined { 56 - return this.$node(this._generics); 60 + protected $generics( 61 + ctx: AstContext, 62 + ): ReadonlyArray<ts.TypeParameterDeclaration> | undefined { 63 + return this.$node(ctx, this._generics); 57 64 } 58 65 } 59 66
+4 -4
packages/openapi-ts/src/ts-dsl/mixins/value.ts
··· 1 - import type { AnalysisContext, Node } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext, Node } from '@hey-api/codegen-core'; 2 2 import type ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; ··· 7 7 export type ValueExpr = string | MaybeTsDsl<ts.Expression>; 8 8 9 9 export interface ValueMethods extends Node { 10 - $value(): ts.Expression | undefined; 10 + $value(ctx: AstContext): ts.Expression | undefined; 11 11 /** Sets the initializer expression (e.g. `= expr`). */ 12 12 assign(expr: ValueExpr): this; 13 13 } ··· 28 28 return this; 29 29 } 30 30 31 - protected $value(): ts.Expression | undefined { 32 - return this.$node(this.value); 31 + protected $value(ctx: AstContext): ts.Expression | undefined { 32 + return this.$node(ctx, this.value); 33 33 } 34 34 } 35 35
+9 -2
packages/openapi-ts/src/ts-dsl/render/__tests__/typescript.test.ts
··· 21 21 fileOverrides = {}, 22 22 projectOverrides = {}, 23 23 ): RenderContext => ({ 24 + astContext: { 25 + getAccess(node) { 26 + return node; 27 + }, 28 + }, 24 29 file: mockFile(fileOverrides), 25 30 project: new Project({ 26 31 root: '/root', ··· 42 47 }); 43 48 44 49 it('renderImport() generates named and namespace imports correctly', () => { 50 + const ctx = mockCtx(); 45 51 const group: ModuleImport = { 46 52 imports: [ 47 53 { ··· 55 61 modulePath: 'foo', 56 62 namespaceImport: undefined, 57 63 }; 58 - const node = renderer['renderImport'](group); 64 + const node = renderer['renderImport'](ctx, group); 59 65 expect(ts.isImportDeclaration(node)).toBe(true); 60 66 }); 61 67 62 68 it('renderExport() generates named and namespace exports correctly', () => { 69 + const ctx = mockCtx(); 63 70 const group: ModuleExport = { 64 71 canExportAll: false, 65 72 exports: [ ··· 74 81 modulePath: 'bar', 75 82 namespaceExport: undefined, 76 83 }; 77 - const node = renderer['renderExport'](group); 84 + const node = renderer['renderExport'](ctx, group); 78 85 expect(ts.isExportDeclaration(node)).toBe(true); 79 86 }); 80 87 });
+13 -7
packages/openapi-ts/src/ts-dsl/render/typescript.ts
··· 53 53 for (const group of this.getImports(ctx)) { 54 54 if (imports) imports += '\n'; 55 55 for (const imp of group) { 56 - imports += `${nodeToString(this.renderImport(imp))}\n`; 56 + imports += `${nodeToString(this.renderImport(ctx, imp))}\n`; 57 57 } 58 58 } 59 59 text = `${text}${text && imports ? '\n' : ''}${imports}`; ··· 62 62 for (const node of ctx.file.nodes) { 63 63 if (nodes) nodes += '\n'; 64 64 // @ts-expect-error 65 - nodes += `${nodeToString(node.toAst())}\n`; 65 + nodes += `${nodeToString(node.toAst(ctx.astContext))}\n`; 66 66 } 67 67 text = `${text}${text && nodes ? '\n' : ''}${nodes}`; 68 68 ··· 70 70 for (const group of this.getExports(ctx)) { 71 71 if ((!exports && nodes) || exports) exports += '\n'; 72 72 for (const exp of group) { 73 - exports += `${nodeToString(this.renderExport(exp))}\n`; 73 + exports += `${nodeToString(this.renderExport(ctx, exp))}\n`; 74 74 } 75 75 } 76 76 text = `${text}${text && exports ? '\n' : ''}${exports}`; ··· 234 234 return imports; 235 235 } 236 236 237 - private renderExport(group: ModuleExport): ts.ExportDeclaration { 237 + private renderExport( 238 + ctx: RenderContext, 239 + group: ModuleExport, 240 + ): ts.ExportDeclaration { 238 241 const specifiers = group.exports.map((exp) => { 239 242 const specifier = ts.factory.createExportSpecifier( 240 243 exp.isTypeOnly, ··· 254 257 undefined, 255 258 group.isTypeOnly, 256 259 exportClause, 257 - $.literal(group.modulePath).toAst(), 260 + $.literal(group.modulePath).toAst(ctx.astContext), 258 261 ); 259 262 } 260 263 261 - private renderImport(group: ModuleImport): ts.ImportDeclaration { 264 + private renderImport( 265 + ctx: RenderContext, 266 + group: ModuleImport, 267 + ): ts.ImportDeclaration { 262 268 const specifiers = group.imports.map((imp) => { 263 269 const specifier = ts.factory.createImportSpecifier( 264 270 imp.isTypeOnly, ··· 279 285 return ts.factory.createImportDeclaration( 280 286 undefined, 281 287 importClause, 282 - $.literal(group.modulePath).toAst(), 288 + $.literal(group.modulePath).toAst(ctx.astContext), 283 289 ); 284 290 } 285 291 }
+3 -3
packages/openapi-ts/src/ts-dsl/stmt/block.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import { TsDsl } from '../base'; ··· 20 20 super.analyze(ctx); 21 21 } 22 22 23 - override toAst() { 24 - const statements = this.$do(); 23 + override toAst(ctx: AstContext) { 24 + const statements = this.$do(ctx); 25 25 return ts.factory.createBlock( 26 26 statements, 27 27 this.$multiline(statements.length),
+5 -5
packages/openapi-ts/src/ts-dsl/stmt/if.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; ··· 47 47 return this; 48 48 } 49 49 50 - override toAst() { 50 + override toAst(ctx: AstContext) { 51 51 if (!this._condition) throw new Error('Missing condition in if'); 52 52 if (!this._do) throw new Error('Missing then block in if'); 53 53 54 54 return ts.factory.createIfStatement( 55 - this.$node(this._condition), 56 - this.$node(new BlockTsDsl(...this._do).pretty()), 55 + this.$node(ctx, this._condition), 56 + this.$node(ctx, new BlockTsDsl(...this._do).pretty()), 57 57 this._else 58 - ? this.$node(new BlockTsDsl(...this._else).pretty()) 58 + ? this.$node(ctx, new BlockTsDsl(...this._else).pretty()) 59 59 : undefined, 60 60 ); 61 61 }
+8 -3
packages/openapi-ts/src/ts-dsl/stmt/return.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 26 31 ctx.analyze(this._returnExpr); 27 32 } 28 33 29 - override toAst() { 30 - return ts.factory.createReturnStatement(this.$node(this._returnExpr)); 34 + override toAst(ctx: AstContext) { 35 + return ts.factory.createReturnStatement(this.$node(ctx, this._returnExpr)); 31 36 } 32 37 } 33 38
+3 -3
packages/openapi-ts/src/ts-dsl/stmt/stmt.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import { TsDsl } from '../base'; ··· 20 20 ctx.analyze(this._inner); 21 21 } 22 22 23 - override toAst() { 24 - const node = this.$node(this._inner); 23 + override toAst(ctx: AstContext) { 24 + const node = this.$node(ctx, this._inner); 25 25 return ts.isStatement(node) 26 26 ? node 27 27 : ts.factory.createExpressionStatement(node);
+8 -5
packages/openapi-ts/src/ts-dsl/stmt/throw.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; ··· 31 31 return this; 32 32 } 33 33 34 - override toAst() { 35 - const errorNode = this.$node(this.error); 36 - const messageNode = this.$node(this.msg ? [this.msg] : []).map((expr) => 37 - typeof expr === 'string' ? this.$node(new LiteralTsDsl(expr)) : expr, 34 + override toAst(ctx: AstContext) { 35 + const errorNode = this.$node(ctx, this.error); 36 + const messageNode = this.$node(ctx, this.msg ? [this.msg] : []).map( 37 + (expr) => 38 + typeof expr === 'string' 39 + ? this.$node(ctx, new LiteralTsDsl(expr)) 40 + : expr, 38 41 ); 39 42 if (this.useNew) { 40 43 return ts.factory.createThrowStatement(
+10 -6
packages/openapi-ts/src/ts-dsl/stmt/try.ts
··· 1 - import type { AnalysisContext, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Symbol, 5 + } from '@hey-api/codegen-core'; 2 6 import ts from 'typescript'; 3 7 4 8 import { TsDsl } from '../base'; ··· 76 80 return this; 77 81 } 78 82 79 - override toAst() { 83 + override toAst(ctx: AstContext) { 80 84 if (!this._try?.length) throw new Error('Missing try block'); 81 85 82 86 const catchParam = this._catchArg 83 - ? (this.$node(this._catchArg) as ts.BindingName) 87 + ? (this.$node(ctx, this._catchArg) as ts.BindingName) 84 88 : undefined; 85 89 86 90 return ts.factory.createTryStatement( 87 - this.$node(new BlockTsDsl(...this._try).pretty()), 91 + this.$node(ctx, new BlockTsDsl(...this._try).pretty()), 88 92 ts.factory.createCatchClause( 89 93 catchParam 90 94 ? ts.factory.createVariableDeclaration(catchParam) 91 95 : undefined, 92 - this.$node(new BlockTsDsl(...(this._catch ?? [])).pretty()), 96 + this.$node(ctx, new BlockTsDsl(...(this._catch ?? [])).pretty()), 93 97 ), 94 98 this._finally 95 - ? this.$node(new BlockTsDsl(...this._finally).pretty()) 99 + ? this.$node(ctx, new BlockTsDsl(...this._finally).pretty()) 96 100 : undefined, 97 101 ); 98 102 }
+12 -8
packages/openapi-ts/src/ts-dsl/stmt/var.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { isSymbol, ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 65 70 return this; 66 71 } 67 72 68 - override toAst() { 69 - const name = this.$pattern() ?? this.$node(this.name); 73 + override toAst(ctx: AstContext) { 74 + const name = this.$pattern(ctx) ?? this.$node(ctx, this.name); 70 75 if (!name) 71 76 throw new Error('Var must have either a name or a destructuring pattern'); 72 77 const node = ts.factory.createVariableStatement( ··· 74 79 ts.factory.createVariableDeclarationList( 75 80 [ 76 81 ts.factory.createVariableDeclaration( 77 - // @ts-expect-error need to improve types 78 - name, 82 + name as ts.BindingName, 79 83 undefined, 80 - this.$type(this._type), 81 - this.$value(), 84 + this.$type(ctx, this._type), 85 + this.$value(ctx), 82 86 ), 83 87 ], 84 88 this.kind, 85 89 ), 86 90 ); 87 - return this.$docs(this.$hint(node)); 91 + return this.$docs(ctx, this.$hint(ctx, node)); 88 92 } 89 93 }
+11 -7
packages/openapi-ts/src/ts-dsl/type/alias.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { fromRef, isSymbol, ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 45 50 return this; 46 51 } 47 52 48 - override toAst() { 53 + override toAst(ctx: AstContext) { 49 54 if (!this.value) 50 55 throw new Error( 51 56 `Type alias '${fromRef(this.name)}' is missing a type definition`, 52 57 ); 53 58 const node = ts.factory.createTypeAliasDeclaration( 54 59 this.modifiers, 55 - // @ts-expect-error need to improve types 56 - this.$node(this.name), 57 - this.$generics(), 58 - this.$type(this.value), 60 + this.$node(ctx, this.name) as ts.Identifier, 61 + this.$generics(ctx), 62 + this.$type(ctx, this.value), 59 63 ); 60 - return this.$docs(node); 64 + return this.$docs(ctx, node); 61 65 } 62 66 }
+8 -3
packages/openapi-ts/src/ts-dsl/type/and.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 30 35 return this; 31 36 } 32 37 33 - override toAst() { 38 + override toAst(ctx: AstContext) { 34 39 const flat: Array<ts.TypeNode> = []; 35 40 36 41 for (const node of this._types) { 37 - const type = this.$type(node); 42 + const type = this.$type(ctx, node); 38 43 if (ts.isIntersectionTypeNode(type)) { 39 44 flat.push(...type.types); 40 45 } else {
+9 -5
packages/openapi-ts/src/ts-dsl/type/attr.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { isRef, ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 50 55 return this; 51 56 } 52 57 53 - override toAst() { 58 + override toAst(ctx: AstContext) { 54 59 if (!this._base) { 55 60 throw new Error('TypeAttrTsDsl: missing base for qualified name'); 56 61 } 57 - const left = this.$node(this._base); 62 + const left = this.$node(ctx, this._base); 58 63 if (!ts.isEntityName(left)) { 59 64 throw new Error('TypeAttrTsDsl: base must be an EntityName'); 60 65 } 61 66 return ts.factory.createQualifiedName( 62 67 left, 63 - // @ts-expect-error need to improve types 64 - this.$node(this._right), 68 + this.$node(ctx, this._right) as ts.Identifier, 65 69 ); 66 70 } 67 71 }
+9 -5
packages/openapi-ts/src/ts-dsl/type/expr.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { isNode, ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 47 52 return this; 48 53 } 49 54 50 - override toAst() { 55 + override toAst(ctx: AstContext) { 51 56 if (!this._exprInput) throw new Error('TypeExpr must have an expression'); 52 57 return ts.factory.createTypeReferenceNode( 53 - // @ts-expect-error need to improve types 54 - this.$type(this._exprInput), 55 - this.$generics(), 58 + this.$type(ctx, this._exprInput) as ts.EntityName, 59 + this.$generics(ctx), 56 60 ); 57 61 } 58 62 }
+6 -6
packages/openapi-ts/src/ts-dsl/type/func.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import { TypeTsDsl } from '../base'; ··· 27 27 return this; 28 28 } 29 29 30 - override toAst() { 30 + override toAst(ctx: AstContext) { 31 31 if (this._returns === undefined) { 32 32 throw new Error('Missing return type in function type DSL'); 33 33 } 34 34 const node = ts.factory.createFunctionTypeNode( 35 - this.$generics(), 36 - this.$params(), 37 - this.$type(this._returns), 35 + this.$generics(ctx), 36 + this.$params(ctx), 37 + this.$type(ctx, this._returns), 38 38 ); 39 - return this.$docs(node); 39 + return this.$docs(ctx, node); 40 40 } 41 41 }
+5 -5
packages/openapi-ts/src/ts-dsl/type/idx-sig.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; ··· 47 47 return this; 48 48 } 49 49 50 - override toAst() { 50 + override toAst(ctx: AstContext) { 51 51 this.$validate(); 52 52 const node = ts.factory.createIndexSignature( 53 53 this.modifiers, ··· 57 57 undefined, 58 58 this._name, 59 59 undefined, 60 - this.$type(this._key), 60 + this.$type(ctx, this._key), 61 61 ), 62 62 ], 63 - this.$type(this._type), 63 + this.$type(ctx, this._type), 64 64 ); 65 - return this.$docs(node); 65 + return this.$docs(ctx, node); 66 66 } 67 67 68 68 $validate(): asserts this is this & {
+4 -4
packages/openapi-ts/src/ts-dsl/type/idx.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; ··· 38 38 return this; 39 39 } 40 40 41 - override toAst() { 41 + override toAst(ctx: AstContext) { 42 42 return ts.factory.createIndexedAccessTypeNode( 43 - this.$type(this._base), 44 - this.$type(this._index), 43 + this.$type(ctx, this._base), 44 + this.$type(ctx, this._index), 45 45 ); 46 46 } 47 47 }
+3 -3
packages/openapi-ts/src/ts-dsl/type/literal.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import { TypeTsDsl } from '../base'; ··· 20 20 super.analyze(ctx); 21 21 } 22 22 23 - override toAst() { 23 + override toAst(ctx: AstContext) { 24 24 return ts.factory.createLiteralTypeNode( 25 - this.$node(new LiteralTsDsl(this.value)), 25 + this.$node(ctx, new LiteralTsDsl(this.value)), 26 26 ); 27 27 } 28 28 }
+6 -6
packages/openapi-ts/src/ts-dsl/type/mapped.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; ··· 84 84 return this; 85 85 } 86 86 87 - override toAst() { 87 + override toAst(ctx: AstContext) { 88 88 this.$validate(); 89 89 return ts.factory.createMappedTypeNode( 90 - this.$node(this.readonlyToken), 90 + this.$node(ctx, this.readonlyToken), 91 91 ts.factory.createTypeParameterDeclaration( 92 92 undefined, 93 93 this._name, 94 - this.$type(this._key), 94 + this.$type(ctx, this._key), 95 95 undefined, 96 96 ), 97 97 undefined, 98 - this.$node(this.questionToken), 99 - this.$type(this._type), 98 + this.$node(ctx, this.questionToken), 99 + this.$type(ctx, this._type), 100 100 undefined, 101 101 ); 102 102 }
+3 -3
packages/openapi-ts/src/ts-dsl/type/object.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import { TypeTsDsl } from '../base'; ··· 43 43 return this; 44 44 } 45 45 46 - override toAst() { 47 - return ts.factory.createTypeLiteralNode(this.$node(this.props)); 46 + override toAst(ctx: AstContext) { 47 + return ts.factory.createTypeLiteralNode(this.$node(ctx, this.props)); 48 48 } 49 49 }
+6 -3
packages/openapi-ts/src/ts-dsl/type/operator.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; ··· 69 69 return this; 70 70 } 71 71 72 - override toAst() { 72 + override toAst(ctx: AstContext) { 73 73 this.$validate(); 74 - return ts.factory.createTypeOperatorNode(this._op, this.$type(this._type)); 74 + return ts.factory.createTypeOperatorNode( 75 + this._op, 76 + this.$type(ctx, this._type), 77 + ); 75 78 } 76 79 77 80 /** Throws if required fields are not set. */
+8 -3
packages/openapi-ts/src/ts-dsl/type/or.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 30 35 return this; 31 36 } 32 37 33 - override toAst() { 38 + override toAst(ctx: AstContext) { 34 39 const flat: Array<ts.TypeNode> = []; 35 40 36 41 for (const node of this._types) { 37 - const type = this.$type(node); 42 + const type = this.$type(ctx, node); 38 43 if (ts.isUnionTypeNode(type)) { 39 44 flat.push(...type.types); 40 45 } else {
+10 -6
packages/openapi-ts/src/ts-dsl/type/param.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 40 45 return this; 41 46 } 42 47 43 - override toAst() { 48 + override toAst(ctx: AstContext) { 44 49 if (!this.name) throw new Error('Missing type name'); 45 50 return ts.factory.createTypeParameterDeclaration( 46 51 undefined, 47 - // @ts-expect-error need to improve types 48 - this.$node(this.name), 49 - this.$type(this.constraint), 50 - this.$type(this.defaultValue), 52 + this.$node(ctx, this.name) as ts.Identifier, 53 + this.$type(ctx, this.constraint), 54 + this.$type(ctx, this.defaultValue), 51 55 ); 52 56 } 53 57 }
+11 -6
packages/openapi-ts/src/ts-dsl/type/prop.ts
··· 1 - import type { AnalysisContext, Ref, Symbol } from '@hey-api/codegen-core'; 1 + import type { 2 + AnalysisContext, 3 + AstContext, 4 + Ref, 5 + Symbol, 6 + } from '@hey-api/codegen-core'; 2 7 import { ref } from '@hey-api/codegen-core'; 3 8 import ts from 'typescript'; 4 9 ··· 38 43 return this; 39 44 } 40 45 41 - override toAst() { 46 + override toAst(ctx: AstContext) { 42 47 if (!this._type) { 43 48 throw new Error(`Type not specified for property '${this.name}'`); 44 49 } 45 50 const node = ts.factory.createPropertySignature( 46 51 this.modifiers, 47 - this.$node(safePropName(this.name)), 48 - this._optional ? this.$node(new TokenTsDsl().optional()) : undefined, 49 - this.$type(this._type), 52 + this.$node(ctx, safePropName(this.name)), 53 + this._optional ? this.$node(ctx, new TokenTsDsl().optional()) : undefined, 54 + this.$type(ctx, this._type), 50 55 ); 51 - return this.$docs(node); 56 + return this.$docs(ctx, node); 52 57 } 53 58 }
+3 -3
packages/openapi-ts/src/ts-dsl/type/query.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; ··· 22 22 ctx.analyze(this._expr); 23 23 } 24 24 25 - override toAst() { 26 - const expr = this.$node(this._expr); 25 + override toAst(ctx: AstContext) { 26 + const expr = this.$node(ctx, this._expr); 27 27 return ts.factory.createTypeQueryNode(expr as unknown as ts.EntityName); 28 28 } 29 29 }
+3 -3
packages/openapi-ts/src/ts-dsl/type/template.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; ··· 29 29 return this; 30 30 } 31 31 32 - override toAst() { 33 - const parts = this.$node(this.parts); 32 + override toAst(ctx: AstContext) { 33 + const parts = this.$node(ctx, this.parts); 34 34 35 35 const normalized: Array<string | ts.TypeNode> = []; 36 36 // merge consecutive string parts
+3 -3
packages/openapi-ts/src/ts-dsl/type/tuple.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import { TypeTsDsl } from '../base'; ··· 27 27 return this; 28 28 } 29 29 30 - override toAst() { 30 + override toAst(ctx: AstContext) { 31 31 return ts.factory.createTupleTypeNode( 32 - this._elements.map((t) => this.$type(t)), 32 + this._elements.map((t) => this.$type(ctx, t)), 33 33 ); 34 34 } 35 35 }
+10 -5
packages/openapi-ts/src/ts-dsl/utils/lazy.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, AstContext } from '@hey-api/codegen-core'; 2 2 import type ts from 'typescript'; 3 3 4 4 import { TsDsl } from '../base'; 5 5 6 - export type LazyThunk<T extends ts.Node> = () => TsDsl<T>; 6 + export type LazyThunk<T extends ts.Node> = (ctx: AstContext) => TsDsl<T>; 7 7 8 8 export class LazyTsDsl<T extends ts.Node = ts.Node> extends TsDsl<T> { 9 9 readonly '~dsl' = 'LazyTsDsl'; ··· 17 17 18 18 override analyze(ctx: AnalysisContext): void { 19 19 super.analyze(ctx); 20 - ctx.analyze(this._thunk()); 20 + const astContext: AstContext = { 21 + getAccess(node) { 22 + return node; 23 + }, 24 + }; 25 + ctx.analyze(this._thunk(astContext)); 21 26 } 22 27 23 - override toAst() { 24 - return this._thunk().toAst(); 28 + override toAst(ctx: AstContext) { 29 + return this._thunk(ctx).toAst(ctx); 25 30 } 26 31 }