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

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #3666 from hey-api/chore/ts-dsl-bump

chore: update ts-dsl

authored by

Lubos and committed by
GitHub
0d2b8eca 19075fb0

+250 -82
+8 -5
packages/openapi-ts/src/ts-dsl/decl/func.ts
··· 10 10 import { 11 11 AbstractMixin, 12 12 AsyncMixin, 13 + ExportMixin, 13 14 PrivateMixin, 14 15 ProtectedMixin, 15 16 PublicMixin, ··· 29 30 DecoratorMixin( 30 31 DoMixin( 31 32 DocMixin( 32 - ParamMixin( 33 - PrivateMixin( 34 - ProtectedMixin( 35 - PublicMixin( 36 - StaticMixin(TypeParamsMixin(TypeReturnsMixin(TsDsl<ts.ArrowFunction>))), 33 + ExportMixin( 34 + ParamMixin( 35 + PrivateMixin( 36 + ProtectedMixin( 37 + PublicMixin( 38 + StaticMixin(TypeParamsMixin(TypeReturnsMixin(TsDsl<ts.ArrowFunction>))), 39 + ), 37 40 ), 38 41 ), 39 42 ),
+5
packages/openapi-ts/src/ts-dsl/decl/method.ts
··· 19 19 import { TypeReturnsMixin } from '../mixins/type-returns'; 20 20 import { BlockTsDsl } from '../stmt/block'; 21 21 import { TokenTsDsl } from '../token'; 22 + import { f } from '../utils/factories'; 22 23 import { safeAccessorName } from '../utils/name'; 24 + 25 + export type MethodCtor = (name: NodeName, fn?: (m: MethodTsDsl) => void) => MethodTsDsl; 23 26 24 27 const Mixed = AbstractMixin( 25 28 AsyncMixin( ··· 78 81 return this.$docs(node); 79 82 } 80 83 } 84 + 85 + f.method.set((...args) => new MethodTsDsl(...args));
+2 -2
packages/openapi-ts/src/ts-dsl/decl/param.ts
··· 45 45 } 46 46 47 47 /** Sets the parameter type. */ 48 - type(type: string | TypeTsDsl): this { 49 - this._type = type instanceof TypeTsDsl ? type : new TypeExprTsDsl(type); 48 + type(node: NodeName | TypeTsDsl): this { 49 + this._type = node instanceof TypeTsDsl ? node : new TypeExprTsDsl(node); 50 50 return this; 51 51 } 52 52
+11 -22
packages/openapi-ts/src/ts-dsl/expr/array.ts
··· 6 6 import { AsMixin } from '../mixins/as'; 7 7 import { ExprMixin } from '../mixins/expr'; 8 8 import { LayoutMixin } from '../mixins/layout'; 9 + import { SpreadMixin } from '../mixins/spread'; 9 10 import { LiteralTsDsl } from './literal'; 10 11 11 - const Mixed = AsMixin(ExprMixin(LayoutMixin(TsDsl<ts.ArrayLiteralExpression>))); 12 + export type ArrayExpr = string | number | boolean | MaybeTsDsl<ts.Expression>; 13 + 14 + const Mixed = AsMixin(ExprMixin(LayoutMixin(SpreadMixin(TsDsl<ts.ArrayLiteralExpression>)))); 12 15 13 16 export class ArrayTsDsl extends Mixed { 14 17 readonly '~dsl' = 'ArrayTsDsl'; 15 18 16 - protected _elements: Array< 17 - | { expr: MaybeTsDsl<ts.Expression>; kind: 'element' } 18 - | { expr: MaybeTsDsl<ts.Expression>; kind: 'spread' } 19 - > = []; 19 + protected _elements: Array<MaybeTsDsl<ts.Expression>> = []; 20 20 21 - constructor(...exprs: Array<string | number | boolean | MaybeTsDsl<ts.Expression>>) { 21 + constructor(...exprs: Array<ArrayExpr>) { 22 22 super(); 23 23 this.elements(...exprs); 24 24 } ··· 26 26 override analyze(ctx: AnalysisContext): void { 27 27 super.analyze(ctx); 28 28 for (const item of this._elements) { 29 - ctx.analyze(item.expr); 29 + ctx.analyze(item); 30 30 } 31 31 } 32 32 33 33 /** Adds a single array element. */ 34 - element(expr: string | number | boolean | MaybeTsDsl<ts.Expression>): this { 34 + element(expr: ArrayExpr): this { 35 35 const node = 36 36 typeof expr === 'string' || typeof expr === 'number' || typeof expr === 'boolean' 37 37 ? new LiteralTsDsl(expr) 38 38 : expr; 39 - this._elements.push({ expr: node, kind: 'element' }); 39 + this._elements.push(node); 40 40 return this; 41 41 } 42 42 43 43 /** Adds multiple array elements. */ 44 - elements(...exprs: ReadonlyArray<string | number | boolean | MaybeTsDsl<ts.Expression>>): this { 44 + elements(...exprs: ReadonlyArray<ArrayExpr>): this { 45 45 for (const expr of exprs) this.element(expr); 46 46 return this; 47 47 } 48 48 49 - /** Adds a spread element (`...expr`). */ 50 - spread(expr: MaybeTsDsl<ts.Expression>): this { 51 - this._elements.push({ expr, kind: 'spread' }); 52 - return this; 53 - } 54 - 55 49 override toAst() { 56 - const elements = this._elements.map((item) => { 57 - const node = this.$node(item.expr); 58 - return item.kind === 'spread' ? ts.factory.createSpreadElement(node) : node; 59 - }); 60 - 61 50 return ts.factory.createArrayLiteralExpression( 62 - elements, 51 + this._elements.map((item) => this.$node(item)), 63 52 this.$multiline(this._elements.length), 64 53 ); 65 54 }
+4 -1
packages/openapi-ts/src/ts-dsl/expr/attr.ts
··· 8 8 import { ExprMixin } from '../mixins/expr'; 9 9 import { OperatorMixin } from '../mixins/operator'; 10 10 import { OptionalMixin } from '../mixins/optional'; 11 + import { SpreadMixin } from '../mixins/spread'; 11 12 import { TokenTsDsl } from '../token'; 12 13 import { f } from '../utils/factories'; 13 14 import { regexp } from '../utils/regexp'; ··· 18 19 19 20 const Mixed = AsMixin( 20 21 ExprMixin( 21 - OperatorMixin(OptionalMixin(TsDsl<ts.PropertyAccessExpression | ts.ElementAccessExpression>)), 22 + OperatorMixin( 23 + OptionalMixin(SpreadMixin(TsDsl<ts.PropertyAccessExpression | ts.ElementAccessExpression>)), 24 + ), 22 25 ), 23 26 ); 24 27
+2 -1
packages/openapi-ts/src/ts-dsl/expr/call.ts
··· 7 7 import { ArgsMixin } from '../mixins/args'; 8 8 import { AsMixin } from '../mixins/as'; 9 9 import { ExprMixin } from '../mixins/expr'; 10 + import { SpreadMixin } from '../mixins/spread'; 10 11 import { TypeArgsMixin } from '../mixins/type-args'; 11 12 import { f } from '../utils/factories'; 12 13 ··· 14 15 export type CallCallee = NodeName | MaybeTsDsl<ts.Expression>; 15 16 export type CallCtor = (callee: CallCallee, ...args: CallArgs) => CallTsDsl; 16 17 17 - const Mixed = ArgsMixin(AsMixin(ExprMixin(TypeArgsMixin(TsDsl<ts.CallExpression>)))); 18 + const Mixed = ArgsMixin(AsMixin(ExprMixin(SpreadMixin(TypeArgsMixin(TsDsl<ts.CallExpression>))))); 18 19 19 20 export class CallTsDsl extends Mixed { 20 21 readonly '~dsl' = 'CallTsDsl';
+2 -1
packages/openapi-ts/src/ts-dsl/expr/expr.ts
··· 7 7 import { AsMixin } from '../mixins/as'; 8 8 import { ExprMixin } from '../mixins/expr'; 9 9 import { OperatorMixin } from '../mixins/operator'; 10 + import { SpreadMixin } from '../mixins/spread'; 10 11 import { TypeExprMixin } from '../mixins/type-expr'; 11 12 12 13 type Id = NodeName | MaybeTsDsl<ts.Expression>; 13 14 14 - const Mixed = AsMixin(ExprMixin(OperatorMixin(TypeExprMixin(TsDsl<ts.Expression>)))); 15 + const Mixed = AsMixin(ExprMixin(OperatorMixin(SpreadMixin(TypeExprMixin(TsDsl<ts.Expression>))))); 15 16 16 17 export class ExprTsDsl extends Mixed { 17 18 readonly '~dsl' = 'ExprTsDsl';
+2 -1
packages/openapi-ts/src/ts-dsl/expr/new.ts
··· 7 7 import { ArgsMixin } from '../mixins/args'; 8 8 import { AsMixin } from '../mixins/as'; 9 9 import { ExprMixin } from '../mixins/expr'; 10 + import { SpreadMixin } from '../mixins/spread'; 10 11 import { TypeArgsMixin } from '../mixins/type-args'; 11 12 import { f } from '../utils/factories'; 12 13 ··· 14 15 export type NewExpr = NodeName | MaybeTsDsl<ts.Expression>; 15 16 export type NewCtor = (expr: NewExpr, ...args: NewArgs) => NewTsDsl; 16 17 17 - const Mixed = ArgsMixin(AsMixin(ExprMixin(TypeArgsMixin(TsDsl<ts.NewExpression>)))); 18 + const Mixed = ArgsMixin(AsMixin(ExprMixin(SpreadMixin(TypeArgsMixin(TsDsl<ts.NewExpression>))))); 18 19 19 20 export class NewTsDsl extends Mixed { 20 21 readonly '~dsl' = 'NewTsDsl';
+26 -9
packages/openapi-ts/src/ts-dsl/expr/object.ts
··· 3 3 4 4 import type { MaybeTsDsl } from '../base'; 5 5 import { TsDsl } from '../base'; 6 + import type { MethodTsDsl } from '../decl/method'; 6 7 import { AsMixin } from '../mixins/as'; 7 8 import { ExprMixin } from '../mixins/expr'; 8 9 import { HintMixin } from '../mixins/hint'; 9 10 import { LayoutMixin } from '../mixins/layout'; 11 + import { f } from '../utils/factories'; 10 12 import { ObjectPropTsDsl } from './prop'; 11 13 12 14 type Expr = NodeName | MaybeTsDsl<ts.Expression>; 13 15 type Stmt = NodeName | MaybeTsDsl<ts.Statement>; 14 - type ExprFn = Expr | ((p: ObjectPropTsDsl) => void); 15 - type StmtFn = Stmt | ((p: ObjectPropTsDsl) => void); 16 16 17 17 const Mixed = AsMixin(ExprMixin(HintMixin(LayoutMixin(TsDsl<ts.ObjectLiteralExpression>)))); 18 18 ··· 22 22 protected _props = new Map<string, ObjectPropTsDsl>(); 23 23 protected _spreadCounter = 0; 24 24 25 - constructor(...props: Array<ObjectPropTsDsl>) { 25 + constructor(...props: Array<ObjectPropTsDsl> | [(o: ObjectTsDsl) => void]) { 26 26 super(); 27 - this.props(...props); 27 + if (props.length === 1 && typeof props[0] === 'function') { 28 + props[0](this); 29 + } else { 30 + this.props(...(props as Array<ObjectPropTsDsl>)); 31 + } 28 32 } 29 33 30 34 override analyze(ctx: AnalysisContext): void { ··· 43 47 } 44 48 45 49 /** Adds a computed property (e.g., `{ [expr]: value }`), or removes if null. */ 46 - computed(name: string, expr: ExprFn | null): this { 50 + computed(name: string, expr: Expr | null): this { 47 51 if (expr === null) { 48 52 this._props.delete(`computed:${name}`); 49 53 } else { ··· 56 60 } 57 61 58 62 /** Adds a getter property (e.g., `{ get foo() { ... } }`), or removes if null. */ 59 - getter(name: string, stmt: StmtFn | null): this { 63 + getter(name: string, stmt: Stmt | null): this { 60 64 if (stmt === null) { 61 65 this._props.delete(`getter:${name}`); 62 66 } else { ··· 75 79 return this._props.size === 0; 76 80 } 77 81 82 + /** Adds a method property (e.g., `{ foo() { ... } }`), or removes if null. */ 83 + method(name: string, fn: ((m: MethodTsDsl) => void) | null): this { 84 + if (fn === null) { 85 + this._props.delete(`method:${name}`); 86 + } else { 87 + this._props.set( 88 + `method:${name}`, 89 + new ObjectPropTsDsl({ kind: 'method', name }).value(f.method(name, fn)), 90 + ); 91 + } 92 + return this; 93 + } 94 + 78 95 /** Adds a property assignment, or removes if null. */ 79 - prop(name: string, expr: ExprFn | null): this { 96 + prop(name: string, expr: Expr | null): this { 80 97 if (expr === null) { 81 98 this._props.delete(`prop:${name}`); 82 99 } else { ··· 94 111 } 95 112 96 113 /** Adds a setter property (e.g., `{ set foo(v) { ... } }`), or removes if null. */ 97 - setter(name: string, stmt: StmtFn | null): this { 114 + setter(name: string, stmt: Stmt | null): this { 98 115 if (stmt === null) { 99 116 this._props.delete(`setter:${name}`); 100 117 } else { ··· 104 121 } 105 122 106 123 /** Adds a spread property (e.g., `{ ...options }`). */ 107 - spread(expr: ExprFn): this { 124 + spread(expr: Expr): this { 108 125 const key = `spread:${this._spreadCounter++}`; 109 126 this._props.set(key, new ObjectPropTsDsl({ kind: 'spread' }).value(expr)); 110 127 return this;
+26 -24
packages/openapi-ts/src/ts-dsl/expr/prop.ts
··· 7 7 import { GetterTsDsl } from '../decl/getter'; 8 8 import { SetterTsDsl } from '../decl/setter'; 9 9 import { DocMixin } from '../mixins/doc'; 10 + import type { f } from '../utils/factories'; 10 11 import { safePropName } from '../utils/name'; 11 12 import { IdTsDsl } from './id'; 12 13 13 - type Expr = NodeName | MaybeTsDsl<ts.Expression>; 14 - type Stmt = NodeName | MaybeTsDsl<ts.Statement>; 15 - 16 - export type ObjectPropKind = 'computed' | 'getter' | 'prop' | 'setter' | 'spread'; 14 + export type ObjectPropKind = 'computed' | 'getter' | 'method' | 'prop' | 'setter' | 'spread'; 15 + export type ObjectPropValue = 16 + | NodeName 17 + | MaybeTsDsl<ts.Expression | ts.Statement> 18 + | ReturnType<typeof f.method>; 17 19 18 20 type Meta = 19 21 | { kind: 'computed'; name: string } 20 22 | { kind: 'getter'; name: string } 23 + | { kind: 'method'; name: string } 21 24 | { kind: 'prop'; name: string } 22 25 | { kind: 'setter'; name: string } 23 26 | { kind: 'spread'; name?: undefined }; ··· 27 30 export class ObjectPropTsDsl extends Mixed { 28 31 readonly '~dsl' = 'ObjectPropTsDsl'; 29 32 30 - protected _value?: Ref<Expr | Stmt>; 33 + protected _value?: Ref<ObjectPropValue>; 31 34 protected _meta: Meta; 32 35 33 36 constructor(meta: Meta) { ··· 35 38 this._meta = meta; 36 39 } 37 40 38 - get kind(): ObjectPropKind { 39 - return this._meta.kind; 40 - } 41 - 42 - get propName(): string | undefined { 43 - return this._meta.name; 44 - } 45 - 46 41 override analyze(ctx: AnalysisContext): void { 47 42 super.analyze(ctx); 48 43 ctx.analyze(this._value); ··· 52 47 return !this.missingRequiredCalls().length; 53 48 } 54 49 55 - value(value: Expr | Stmt | ((p: ObjectPropTsDsl) => void)) { 56 - if (typeof value === 'function') { 57 - value(this); 58 - } else { 59 - this._value = ref(value); 60 - } 50 + get kind(): ObjectPropKind { 51 + return this._meta.kind; 52 + } 53 + 54 + get propName(): string | undefined { 55 + return this._meta.name; 56 + } 57 + 58 + value(value: ObjectPropValue): this { 59 + this._value = ref(value); 61 60 return this; 62 61 } 63 62 ··· 68 67 if (ts.isStatement(node)) { 69 68 throw new Error('Invalid spread: object spread must be an expression, not a statement.'); 70 69 } 71 - const result = ts.factory.createSpreadAssignment(node); 70 + const result = ts.factory.createSpreadAssignment(node as ts.Expression); 72 71 return this.$docs(result); 73 72 } 74 73 if (this._meta.kind === 'getter') { 75 - const getter = new GetterTsDsl(this._meta.name).do(node); 74 + const getter = new GetterTsDsl(this._meta.name).do(node as ts.Statement); 76 75 const result = this.$node(getter); 77 76 return this.$docs(result); 78 77 } 79 78 if (this._meta.kind === 'setter') { 80 - const setter = new SetterTsDsl(this._meta.name).do(node); 79 + const setter = new SetterTsDsl(this._meta.name).do(node as ts.Statement); 81 80 const result = this.$node(setter); 82 81 return this.$docs(result); 83 82 } 83 + if (this._meta.kind === 'method') { 84 + return this.$docs(node as ts.MethodDeclaration); 85 + } 84 86 if (ts.isIdentifier(node) && node.text === this._meta.name) { 85 87 const result = ts.factory.createShorthandPropertyAssignment(this._meta.name); 86 88 return this.$docs(result); ··· 94 96 this._meta.kind === 'computed' 95 97 ? ts.factory.createComputedPropertyName(this.$node(new IdTsDsl(this._meta.name))) 96 98 : this.$node(safePropName(this._meta.name)), 97 - node, 99 + node as ts.Expression, 98 100 ); 99 101 return this.$docs(result); 100 102 } 101 103 102 104 $validate(): asserts this is this & { 103 - _value: Expr | Stmt; 105 + _value: ObjectPropValue; 104 106 kind: ObjectPropKind; 105 107 } { 106 108 const missing = this.missingRequiredCalls();
+34
packages/openapi-ts/src/ts-dsl/expr/spread.ts
··· 1 + import type { AnalysisContext, NodeName, Ref } from '@hey-api/codegen-core'; 2 + import { ref } from '@hey-api/codegen-core'; 3 + import ts from 'typescript'; 4 + 5 + import type { MaybeTsDsl } from '../base'; 6 + import { TsDsl } from '../base'; 7 + import { f } from '../utils/factories'; 8 + 9 + export type SpreadExpr = NodeName | MaybeTsDsl<ts.Expression>; 10 + export type SpreadCtor = (expr: SpreadExpr) => SpreadTsDsl; 11 + 12 + const Mixed = TsDsl<ts.SpreadElement>; 13 + 14 + export class SpreadTsDsl extends Mixed { 15 + readonly '~dsl' = 'SpreadTsDsl'; 16 + 17 + protected _expr: Ref<SpreadExpr>; 18 + 19 + constructor(expr: SpreadExpr) { 20 + super(); 21 + this._expr = ref(expr); 22 + } 23 + 24 + override analyze(ctx: AnalysisContext): void { 25 + super.analyze(ctx); 26 + ctx.analyze(this._expr); 27 + } 28 + 29 + override toAst() { 30 + return ts.factory.createSpreadElement(this.$node(this._expr)); 31 + } 32 + } 33 + 34 + f.spread.set((...args) => new SpreadTsDsl(...args));
+2 -2
packages/openapi-ts/src/ts-dsl/expr/typeof.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, NodeName } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; ··· 6 6 import { OperatorMixin } from '../mixins/operator'; 7 7 import { f } from '../utils/factories'; 8 8 9 - export type TypeOfExpr = string | MaybeTsDsl<ts.Expression>; 9 + export type TypeOfExpr = NodeName | MaybeTsDsl<ts.Expression>; 10 10 export type TypeOfExprCtor = (expr: TypeOfExpr) => TypeOfExprTsDsl; 11 11 12 12 const Mixed = OperatorMixin(TsDsl<ts.TypeOfExpression>);
+13 -3
packages/openapi-ts/src/ts-dsl/index.ts
··· 1 + import type { NodeName } from '@hey-api/codegen-core'; 1 2 import type ts from 'typescript'; 2 3 3 4 import { ClassTsDsl } from './decl/class'; ··· 28 29 import { PrefixTsDsl } from './expr/prefix'; 29 30 import { ObjectPropTsDsl } from './expr/prop'; 30 31 import { RegExpTsDsl } from './expr/regexp'; 32 + import { SpreadTsDsl } from './expr/spread'; 31 33 import { TemplateTsDsl } from './expr/template'; 32 34 import { TernaryTsDsl } from './expr/ternary'; 33 35 import { TypeOfExprTsDsl } from './expr/typeof'; ··· 61 63 import { TypeQueryTsDsl } from './type/query'; 62 64 import { TypeTemplateTsDsl } from './type/template'; 63 65 import { TypeTupleTsDsl } from './type/tuple'; 66 + import { TypeTupleMemberTsDsl } from './type/tuple-member'; 64 67 import { LazyTsDsl } from './utils/lazy'; 65 68 66 69 const tsDsl = { ··· 135 138 }) as { 136 139 (): FuncTsDsl<'arrow'>; 137 140 (fn: (f: FuncTsDsl<'arrow'>) => void): FuncTsDsl<'arrow'>; 138 - (name: string): FuncTsDsl<'decl'>; 139 - (name: string, fn: (f: FuncTsDsl<'decl'>) => void): FuncTsDsl<'decl'>; 140 - (name?: string, fn?: (f: FuncTsDsl<'decl'>) => void): FuncTsDsl<'arrow'> | FuncTsDsl<'decl'>; 141 + (name: NodeName): FuncTsDsl<'decl'>; 142 + (name: NodeName, fn: (f: FuncTsDsl<'decl'>) => void): FuncTsDsl<'decl'>; 143 + (name?: NodeName, fn?: (f: FuncTsDsl<'decl'>) => void): FuncTsDsl<'arrow'> | FuncTsDsl<'decl'>; 141 144 }, 142 145 143 146 /** Creates a getter method declaration. */ ··· 212 215 213 216 /** Creates a setter method declaration. */ 214 217 setter: (...args: ConstructorParameters<typeof SetterTsDsl>) => new SetterTsDsl(...args), 218 + 219 + /** Creates a spread element from an expression (e.g., `...expr`). */ 220 + spread: (...args: ConstructorParameters<typeof SpreadTsDsl>) => new SpreadTsDsl(...args), 215 221 216 222 /** Wraps an expression or statement-like value into a `StmtTsDsl`. */ 217 223 stmt: (...args: ConstructorParameters<typeof StmtTsDsl>) => new StmtTsDsl(...args), ··· 287 293 288 294 /** Creates a tuple type (e.g., [A, B, C]). */ 289 295 tuple: (...args: ConstructorParameters<typeof TypeTupleTsDsl>) => new TypeTupleTsDsl(...args), 296 + 297 + /** Creates a named tuple element (e.g., `[resolver?: R]`). */ 298 + tupleMember: (...args: ConstructorParameters<typeof TypeTupleMemberTsDsl>) => 299 + new TypeTupleMemberTsDsl(...args), 290 300 }, 291 301 ), 292 302
+4 -4
packages/openapi-ts/src/ts-dsl/mixins/args.ts
··· 5 5 import type { MaybeTsDsl } from '../base'; 6 6 import type { BaseCtor, MixinCtor } from './types'; 7 7 8 - type Arg = NodeName | MaybeTsDsl<ts.Expression>; 8 + type Arg = NodeName | MaybeTsDsl<ts.Expression | ts.SpreadElement>; 9 9 10 10 export interface ArgsMethods extends Node { 11 - /** Renders the arguments into an array of `Expression`s. */ 12 - $args(): ReadonlyArray<ts.Expression>; 11 + /** Renders the arguments into an array of `Expression`s or `SpreadElement`s. */ 12 + $args(): ReadonlyArray<ts.Expression | ts.SpreadElement>; 13 13 /** Adds a single expression argument. */ 14 14 arg(arg: Arg | undefined): this; 15 15 /** Adds one or more expression arguments. */ ··· 42 42 return this; 43 43 } 44 44 45 - protected $args(): ReadonlyArray<ts.Expression> { 45 + protected $args(): ReadonlyArray<ts.Expression | ts.SpreadElement> { 46 46 return this.$node(this._args).map((arg) => this.$node(arg)); 47 47 } 48 48 }
+24
packages/openapi-ts/src/ts-dsl/mixins/spread.ts
··· 1 + import type { AnalysisContext, Node } from '@hey-api/codegen-core'; 2 + import type ts from 'typescript'; 3 + 4 + import { f } from '../utils/factories'; 5 + import type { BaseCtor, MixinCtor } from './types'; 6 + 7 + export interface SpreadMethods extends Node { 8 + /** Produces a spread element from the current expression (e.g., `...expr`). */ 9 + spread(): ReturnType<typeof f.spread>; 10 + } 11 + 12 + export function SpreadMixin<T extends ts.Expression, TBase extends BaseCtor<T>>(Base: TBase) { 13 + abstract class Spread extends Base { 14 + override analyze(ctx: AnalysisContext): void { 15 + super.analyze(ctx); 16 + } 17 + 18 + protected spread(): ReturnType<typeof f.spread> { 19 + return f.spread(this); 20 + } 21 + } 22 + 23 + return Spread as unknown as MixinCtor<TBase, SpreadMethods>; 24 + }
+2 -2
packages/openapi-ts/src/ts-dsl/stmt/if.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, NodeName } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import type { MaybeTsDsl } from '../base'; ··· 7 7 import { DoMixin } from '../mixins/do'; 8 8 import { BlockTsDsl } from './block'; 9 9 10 - export type IfCondition = string | MaybeTsDsl<ts.Expression>; 10 + export type IfCondition = NodeName | MaybeTsDsl<ts.Expression>; 11 11 12 12 const Mixed = DoMixin(TsDsl<ts.IfStatement>); 13 13
+2 -2
packages/openapi-ts/src/ts-dsl/stmt/var.ts
··· 52 52 } 53 53 54 54 /** Sets the variable type. */ 55 - type(type: string | TypeTsDsl): this { 56 - this._type = type instanceof TypeTsDsl ? type : new TypeExprTsDsl(type); 55 + type(node: NodeName | TypeTsDsl): this { 56 + this._type = node instanceof TypeTsDsl ? node : new TypeExprTsDsl(node); 57 57 return this; 58 58 } 59 59
+64
packages/openapi-ts/src/ts-dsl/type/tuple-member.ts
··· 1 + import type { AnalysisContext, NodeName, NodeScope, Ref } from '@hey-api/codegen-core'; 2 + import { ref } from '@hey-api/codegen-core'; 3 + import ts from 'typescript'; 4 + 5 + import type { TypeTsDsl as TypeTsDslType } from '../base'; 6 + import { TsDsl } from '../base'; 7 + import { OptionalMixin } from '../mixins/optional'; 8 + import { f } from '../utils/factories'; 9 + 10 + export type TypeTupleMemberCtor = (name: NodeName) => TypeTupleMemberTsDsl; 11 + 12 + const Mixed = OptionalMixin(TsDsl<ts.NamedTupleMember>); 13 + 14 + export class TypeTupleMemberTsDsl extends Mixed { 15 + readonly '~dsl' = 'TypeTupleMemberTsDsl'; 16 + override scope: NodeScope = 'type'; 17 + 18 + protected _type?: Ref<NodeName | TypeTsDslType>; 19 + 20 + constructor(name: NodeName) { 21 + super(); 22 + this.name.set(name); 23 + } 24 + 25 + override analyze(ctx: AnalysisContext): void { 26 + super.analyze(ctx); 27 + ctx.analyze(this.name); 28 + ctx.analyze(this._type); 29 + } 30 + 31 + /** Returns true when all required builder calls are present. */ 32 + get isValid(): boolean { 33 + return !this.missingRequiredCalls().length; 34 + } 35 + 36 + type(node: NodeName | TypeTsDslType): this { 37 + this._type = ref(node); 38 + return this; 39 + } 40 + 41 + override toAst() { 42 + this.$validate(); 43 + return ts.factory.createNamedTupleMember( 44 + undefined, 45 + this.$node(this.name) as ts.Identifier, 46 + this._optional ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined, 47 + this.$type(this._type!), 48 + ); 49 + } 50 + 51 + $validate(): asserts this { 52 + const missing = this.missingRequiredCalls(); 53 + if (!missing.length) return; 54 + throw new Error(`Tuple member missing ${missing.join(' and ')}`); 55 + } 56 + 57 + private missingRequiredCalls(): Array<string> { 58 + const missing: Array<string> = []; 59 + if (!this._type) missing.push('.\u200Btype()'); 60 + return missing; 61 + } 62 + } 63 + 64 + f.type.tupleMember.set((name) => new TypeTupleMemberTsDsl(name));
+5 -3
packages/openapi-ts/src/ts-dsl/type/tuple.ts
··· 4 4 import type { TypeTsDsl } from '../base'; 5 5 import { TsDsl } from '../base'; 6 6 7 + export type TupleElement = string | ts.TypeNode | TypeTsDsl; 8 + 7 9 const Mixed = TsDsl<ts.TupleTypeNode>; 8 10 9 11 export class TypeTupleTsDsl extends Mixed { 10 12 readonly '~dsl' = 'TypeTupleTsDsl'; 11 13 override scope: NodeScope = 'type'; 12 14 13 - protected _elements: Array<string | ts.TypeNode | TypeTsDsl> = []; 15 + protected _elements: Array<TupleElement> = []; 14 16 15 - constructor(...nodes: Array<string | ts.TypeNode | TypeTsDsl>) { 17 + constructor(...nodes: Array<TupleElement>) { 16 18 super(); 17 19 this.elements(...nodes); 18 20 } ··· 24 26 } 25 27 } 26 28 27 - elements(...types: Array<string | ts.TypeNode | TypeTsDsl>): this { 29 + elements(...types: Array<TupleElement>): this { 28 30 this._elements.push(...types); 29 31 return this; 30 32 }
+12
packages/openapi-ts/src/ts-dsl/utils/factories.ts
··· 1 + import type { MethodCtor } from '../decl/method'; 1 2 import type { AsCtor } from '../expr/as'; 2 3 import type { AttrCtor } from '../expr/attr'; 3 4 import type { AwaitCtor } from '../expr/await'; 4 5 import type { CallCtor } from '../expr/call'; 5 6 import type { NewCtor } from '../expr/new'; 7 + import type { SpreadCtor } from '../expr/spread'; 6 8 import type { TypeOfExprCtor } from '../expr/typeof'; 7 9 import type { ReturnCtor } from '../stmt/return'; 8 10 import type { TypeExprCtor } from '../type/expr'; 9 11 import type { TypeIdxCtor } from '../type/idx'; 10 12 import type { TypeOperatorCtor } from '../type/operator'; 11 13 import type { TypeQueryCtor } from '../type/query'; 14 + import type { TypeTupleMemberCtor } from '../type/tuple-member'; 12 15 13 16 type Ctor = (...args: Array<any>) => any; 14 17 ··· 45 48 46 49 /** Factory for creating function or method call expressions (e.g., `fn(arg)`). */ 47 50 call: createFactory<CallCtor>('call'), 51 + 52 + /** Factory for creating method declarations (e.g., `{ foo() { ... } }`). */ 53 + method: createFactory<MethodCtor>('method'), 48 54 49 55 /** Factory for creating new expressions (e.g., `new ClassName()`). */ 50 56 new: createFactory<NewCtor>('new'), ··· 52 58 /** Factory for creating return statements. */ 53 59 return: createFactory<ReturnCtor>('return'), 54 60 61 + /** Factory for creating spread expressions (e.g., `...expr`). */ 62 + spread: createFactory<SpreadCtor>('spread'), 63 + 55 64 /** Factories for creating type nodes. */ 56 65 type: { 57 66 /** Factory for creating basic type references or type expressions (e.g., Foo or Foo<T>). */ ··· 65 74 66 75 /** Factory for creating type query nodes (e.g., `typeof Foo`). */ 67 76 query: createFactory<TypeQueryCtor>('type.query'), 77 + 78 + /** Factory for creating named tuple elements (e.g., `[resolver?: R]`). */ 79 + tupleMember: createFactory<TypeTupleMemberCtor>('type.tupleMember'), 68 80 }, 69 81 70 82 /** Factory for creating `typeof` expressions (e.g., `typeof value`). */