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

refactor: move factories into a separate module

Lubos dbac0ef3 4d790ac2

+214 -167
+16 -3
dev/openapi-ts.config.ts
··· 43 43 // 'circular.yaml', 44 44 // 'dutchie.json', 45 45 // 'enum-names-values.yaml', 46 - // 'invalid', 47 46 // 'full.yaml', 48 - // 'sdk-method-class-conflict.yaml', 47 + // 'integer-formats.yaml', 48 + // 'invalid', 49 49 // 'object-property-names.yaml', 50 50 // 'openai.yaml', 51 51 'opencode.yaml', 52 52 // 'pagination-ref.yaml', 53 + // 'schema-const.yaml', 53 54 // 'sdk-instance.yaml', 55 + // 'sdk-method-class-conflict.yaml', 54 56 // 'sdk-nested-classes.yaml', 55 57 // 'string-with-format.yaml', 56 58 // 'transformers.json', ··· 477 479 }, 478 480 exportFromIndex: true, 479 481 metadata: true, 480 - // name: 'zod', 482 + name: 'zod', 481 483 // requests: { 482 484 // // case: 'SCREAMING_SNAKE_CASE', 483 485 // // name: 'z{{name}}TestData', ··· 526 528 formats: { 527 529 // date: ({ $ }) => $('z').attr('date').call(), 528 530 // 'date-time': ({ $ }) => $('z').attr('date').call(), 531 + // int64: ({ $ }) => $('z').attr('string').call().attr('refine').call( 532 + // $.func().param('val').do( 533 + // $.try( 534 + // $('z').attr('int64').call().attr('parse').call($('BigInt').call('val')), 535 + // $.return($.literal(true)) 536 + // ).catch( 537 + // $.return($.literal(false)) 538 + // ), 539 + // ), 540 + // $.object().prop('message', $.literal('Must be a valid int64 string')) 541 + // ), 529 542 }, 530 543 }, 531 544 // validator({ $, schema }) {
+3 -2
packages/openapi-ts/src/ts-dsl/expr/as.ts
··· 9 9 10 10 import type { MaybeTsDsl, TypeTsDsl } from '../base'; 11 11 import { TsDsl } from '../base'; 12 - import { AsMixin, setAsFactory } from '../mixins/as'; 12 + import { AsMixin } from '../mixins/as'; 13 13 import { ExprMixin } from '../mixins/expr'; 14 + import { f } from '../utils/factories'; 14 15 15 16 export type AsExpr = Symbol | string | MaybeTsDsl<ts.Expression>; 16 17 export type AsType = Symbol | string | TypeTsDsl; ··· 44 45 } 45 46 } 46 47 47 - setAsFactory((...args) => new AsTsDsl(...args)); 48 + f.as.set((...args) => new AsTsDsl(...args));
+3 -2
packages/openapi-ts/src/ts-dsl/expr/attr.ts
··· 10 10 import type { MaybeTsDsl } from '../base'; 11 11 import { TsDsl } from '../base'; 12 12 import { AsMixin } from '../mixins/as'; 13 - import { ExprMixin, setAttrFactory } from '../mixins/expr'; 13 + import { ExprMixin } from '../mixins/expr'; 14 14 import { OperatorMixin } from '../mixins/operator'; 15 15 import { OptionalMixin } from '../mixins/optional'; 16 16 import { TokenTsDsl } from '../token'; 17 + import { f } from '../utils/factories'; 17 18 import { regexp } from '../utils/regexp'; 18 19 import { LiteralTsDsl } from './literal'; 19 20 ··· 83 84 } 84 85 } 85 86 86 - setAttrFactory((...args) => new AttrTsDsl(...args)); 87 + f.attr.set((...args) => new AttrTsDsl(...args));
+3 -2
packages/openapi-ts/src/ts-dsl/expr/await.ts
··· 9 9 10 10 import type { MaybeTsDsl } from '../base'; 11 11 import { TsDsl } from '../base'; 12 - import { ExprMixin, setAwaitFactory } from '../mixins/expr'; 12 + import { ExprMixin } from '../mixins/expr'; 13 + import { f } from '../utils/factories'; 13 14 14 15 export type AwaitExpr = Symbol | string | MaybeTsDsl<ts.Expression>; 15 16 export type AwaitCtor = (expr: AwaitExpr) => AwaitTsDsl; ··· 36 37 } 37 38 } 38 39 39 - setAwaitFactory((...args) => new AwaitTsDsl(...args)); 40 + f.await.set((...args) => new AwaitTsDsl(...args));
+3 -2
packages/openapi-ts/src/ts-dsl/expr/call.ts
··· 9 9 import { TsDsl } from '../base'; 10 10 import { ArgsMixin } from '../mixins/args'; 11 11 import { AsMixin } from '../mixins/as'; 12 - import { ExprMixin, setCallFactory } from '../mixins/expr'; 12 + import { ExprMixin } from '../mixins/expr'; 13 13 import { TypeArgsMixin } from '../mixins/type-args'; 14 + import { f } from '../utils/factories'; 14 15 15 16 export type CallCallee = string | MaybeTsDsl<ts.Expression>; 16 17 export type CallArg = Symbol | string | MaybeTsDsl<ts.Expression>; ··· 46 47 } 47 48 } 48 49 49 - setCallFactory((...args) => new CallTsDsl(...args)); 50 + f.call.set((...args) => new CallTsDsl(...args));
+7 -4
packages/openapi-ts/src/ts-dsl/expr/typeof.ts
··· 4 4 import type { MaybeTsDsl } from '../base'; 5 5 import { TsDsl } from '../base'; 6 6 import { OperatorMixin } from '../mixins/operator'; 7 - import { setTypeOfExprFactory } from '../mixins/type-expr'; 7 + import { f } from '../utils/factories'; 8 + 9 + export type TypeOfExpr = string | MaybeTsDsl<ts.Expression>; 10 + export type TypeOfExprCtor = (expr: TypeOfExpr) => TypeOfExprTsDsl; 8 11 9 12 const Mixed = OperatorMixin(TsDsl<ts.TypeOfExpression>); 10 13 11 14 export class TypeOfExprTsDsl extends Mixed { 12 15 readonly '~dsl' = 'TypeOfExprTsDsl'; 13 16 14 - protected _expr: string | MaybeTsDsl<ts.Expression>; 17 + protected _expr: TypeOfExpr; 15 18 16 - constructor(expr: string | MaybeTsDsl<ts.Expression>) { 19 + constructor(expr: TypeOfExpr) { 17 20 super(); 18 21 this._expr = expr; 19 22 } ··· 28 31 } 29 32 } 30 33 31 - setTypeOfExprFactory((...args) => new TypeOfExprTsDsl(...args)); 34 + f.typeofExpr.set((...args) => new TypeOfExprTsDsl(...args));
+2 -2
packages/openapi-ts/src/ts-dsl/index.ts
··· 321 321 }, 322 322 ), 323 323 324 - /** Creates a runtime `typeof` expression (e.g. typeof x). */ 324 + /** Creates a `typeof` expression (e.g. `typeof value`). */ 325 325 typeofExpr: (...args: ConstructorParameters<typeof TypeOfExprTsDsl>) => 326 326 new TypeOfExprTsDsl(...args), 327 327 328 - /** Creates a variable declaration (var). */ 328 + /** Creates a variable declaration (`var`). */ 329 329 var: (...args: ConstructorParameters<typeof VarTsDsl>) => 330 330 new VarTsDsl(...args), 331 331 };
+7 -11
packages/openapi-ts/src/ts-dsl/mixins/as.ts
··· 1 1 import type { AnalysisContext, Node } from '@hey-api/codegen-core'; 2 2 import type ts from 'typescript'; 3 3 4 - import type { AsCtor, AsTsDsl, AsType } from '../expr/as'; 5 - import type { BaseCtor, MixinCtor } from './types'; 6 - 7 - let asFactory: AsCtor | undefined; 8 - /** Lazy register the factory to avoid circular imports. */ 9 - export function setAsFactory(factory: AsCtor): void { 10 - asFactory = factory; 11 - } 4 + import { f } from '../utils/factories'; 5 + import type { BaseCtor, DropFirst, MixinCtor } from './types'; 12 6 13 7 export interface AsMethods extends Node { 14 8 /** Creates an `as` type assertion expression (e.g. `value as Type`). */ 15 - as(type: AsType): AsTsDsl; 9 + as(...args: DropFirst<Parameters<typeof f.as>>): ReturnType<typeof f.as>; 16 10 } 17 11 18 12 export function AsMixin<T extends ts.Expression, TBase extends BaseCtor<T>>( ··· 23 17 super.analyze(ctx); 24 18 } 25 19 26 - protected as(type: AsType): AsTsDsl { 27 - return asFactory!(this, type); 20 + protected as( 21 + ...args: DropFirst<Parameters<typeof f.as>> 22 + ): ReturnType<typeof f.as> { 23 + return f.as(this, ...args); 28 24 } 29 25 } 30 26
+22 -41
packages/openapi-ts/src/ts-dsl/mixins/expr.ts
··· 1 1 import type { AnalysisContext, Node } from '@hey-api/codegen-core'; 2 2 import type ts from 'typescript'; 3 3 4 - import type { AttrCtor, AttrRight, AttrTsDsl } from '../expr/attr'; 5 - import type { AwaitCtor, AwaitTsDsl } from '../expr/await'; 6 - import type { CallArgs, CallCtor, CallTsDsl } from '../expr/call'; 7 - import type { ReturnCtor, ReturnTsDsl } from '../stmt/return'; 8 - import type { BaseCtor, MixinCtor } from './types'; 9 - 10 - let attrFactory: AttrCtor | undefined; 11 - /** Lazy register the factory to avoid circular imports. */ 12 - export function setAttrFactory(fn: AttrCtor): void { 13 - attrFactory = fn; 14 - } 15 - 16 - let awaitFactory: AwaitCtor | undefined; 17 - /** Lazy register the factory to avoid circular imports. */ 18 - export function setAwaitFactory(fn: AwaitCtor): void { 19 - awaitFactory = fn; 20 - } 21 - 22 - let callFactory: CallCtor | undefined; 23 - /** Lazy register the factory to avoid circular imports. */ 24 - export function setCallFactory(fn: CallCtor): void { 25 - callFactory = fn; 26 - } 27 - 28 - let returnFactory: ReturnCtor | undefined; 29 - /** Lazy register the factory to avoid circular imports. */ 30 - export function setReturnFactory(fn: ReturnCtor): void { 31 - returnFactory = fn; 32 - } 4 + import { f } from '../utils/factories'; 5 + import type { BaseCtor, DropFirst, MixinCtor } from './types'; 33 6 34 7 export interface ExprMethods extends Node { 35 8 /** Accesses a property on the current expression (e.g. `this.foo`). */ 36 - attr(name: AttrRight): AttrTsDsl; 9 + attr( 10 + ...args: DropFirst<Parameters<typeof f.attr>> 11 + ): ReturnType<typeof f.attr>; 37 12 /** Awaits the current expression (e.g. `await expr`). */ 38 - await(): AwaitTsDsl; 13 + await(): ReturnType<typeof f.await>; 39 14 /** Calls the current expression (e.g. `fn(arg1, arg2)`). */ 40 - call(...args: CallArgs): CallTsDsl; 15 + call( 16 + ...args: DropFirst<Parameters<typeof f.call>> 17 + ): ReturnType<typeof f.call>; 41 18 /** Produces a `return` statement returning the current expression. */ 42 - return(): ReturnTsDsl; 19 + return(): ReturnType<typeof f.return>; 43 20 } 44 21 45 22 export function ExprMixin<T extends ts.Expression, TBase extends BaseCtor<T>>( ··· 50 27 super.analyze(ctx); 51 28 } 52 29 53 - protected attr(name: AttrRight): AttrTsDsl { 54 - return attrFactory!(this, name); 30 + protected attr( 31 + ...args: DropFirst<Parameters<typeof f.attr>> 32 + ): ReturnType<typeof f.attr> { 33 + return f.attr(this, ...args); 55 34 } 56 35 57 - protected await(): AwaitTsDsl { 58 - return awaitFactory!(this); 36 + protected await(): ReturnType<typeof f.await> { 37 + return f.await(this); 59 38 } 60 39 61 - protected call(...args: CallArgs): CallTsDsl { 62 - return callFactory!(this, ...args); 40 + protected call( 41 + ...args: DropFirst<Parameters<typeof f.call>> 42 + ): ReturnType<typeof f.call> { 43 + return f.call(this, ...args); 63 44 } 64 45 65 - protected return(): ReturnTsDsl { 66 - return returnFactory!(this); 46 + protected return(): ReturnType<typeof f.return> { 47 + return f.return(this); 67 48 } 68 49 } 69 50
+45 -78
packages/openapi-ts/src/ts-dsl/mixins/type-expr.ts
··· 1 1 import type { AnalysisContext, Node } from '@hey-api/codegen-core'; 2 2 import type ts from 'typescript'; 3 3 4 - import type { MaybeTsDsl, TsDsl, TypeTsDsl } from '../base'; 5 - import type { TypeOfExprTsDsl } from '../expr/typeof'; 6 - import type { TypeExprTsDsl } from '../type/expr'; 7 - import type { TypeIdxTsDsl } from '../type/idx'; 8 - import type { TypeOperatorTsDsl } from '../type/operator'; 9 - import type { TypeQueryTsDsl } from '../type/query'; 10 - import type { BaseCtor, MixinCtor } from './types'; 11 - 12 - type TypeExprFactory = ( 13 - nameOrFn?: string | ((t: TypeExprTsDsl) => void), 14 - fn?: (t: TypeExprTsDsl) => void, 15 - ) => TypeExprTsDsl; 16 - let typeExprFactory: TypeExprFactory | undefined; 17 - /** Lazy register the factory to avoid circular imports. */ 18 - export function setTypeExprFactory(factory: TypeExprFactory): void { 19 - typeExprFactory = factory; 20 - } 21 - 22 - type TypeIdxFactory = ( 23 - expr: MaybeTsDsl<TypeTsDsl>, 24 - index: string | number | MaybeTsDsl<ts.TypeNode>, 25 - ) => TypeIdxTsDsl; 26 - let typeIdxFactory: TypeIdxFactory | undefined; 27 - /** Lazy register the factory to avoid circular imports. */ 28 - export function setTypeIdxFactory(factory: TypeIdxFactory): void { 29 - typeIdxFactory = factory; 30 - } 31 - 32 - type TypeOfExprFactory = ( 33 - expr: string | MaybeTsDsl<ts.Expression>, 34 - ) => TypeOfExprTsDsl; 35 - let typeOfExprFactory: TypeOfExprFactory | undefined; 36 - /** Lazy register the factory to avoid circular imports. */ 37 - export function setTypeOfExprFactory(factory: TypeOfExprFactory): void { 38 - typeOfExprFactory = factory; 39 - } 40 - 41 - type TypeOperatorFactory = () => TypeOperatorTsDsl; 42 - let typeOperatorFactory: TypeOperatorFactory | undefined; 43 - /** Lazy register the factory to avoid circular imports. */ 44 - export function setTypeOperatorFactory(factory: TypeOperatorFactory): void { 45 - typeOperatorFactory = factory; 46 - } 47 - 48 - type TypeQueryFactory = ( 49 - expr: string | MaybeTsDsl<TypeTsDsl | ts.Expression>, 50 - ) => TypeQueryTsDsl; 51 - let typeQueryFactory: TypeQueryFactory | undefined; 52 - /** Lazy register the factory to avoid circular imports. */ 53 - export function setTypeQueryFactory(factory: TypeQueryFactory): void { 54 - typeQueryFactory = factory; 55 - } 4 + import type { MaybeTsDsl, TypeTsDsl } from '../base'; 5 + import { f } from '../utils/factories'; 6 + import type { BaseCtor, DropFirst, MixinCtor } from './types'; 56 7 57 8 export interface TypeExprMethods extends Node { 58 9 /** Creates an indexed-access type (e.g. `Foo<T>[K]`). */ 59 10 idx( 60 - this: MaybeTsDsl<TypeTsDsl>, 61 - index: string | number | MaybeTsDsl<ts.TypeNode>, 62 - ): TypeIdxTsDsl; 11 + this: Parameters<typeof f.type.idx>[0], 12 + ...args: DropFirst<Parameters<typeof f.type.idx>> 13 + ): ReturnType<typeof f.type.idx>; 63 14 /** Shorthand: builds `keyof T`. */ 64 - keyof(this: MaybeTsDsl<TypeTsDsl>): TypeOperatorTsDsl; 15 + keyof(this: MaybeTsDsl<TypeTsDsl>): ReturnType<typeof f.type.operator>; 65 16 /** Shorthand: builds `readonly T`. */ 66 - readonly(this: MaybeTsDsl<TypeTsDsl>): TypeOperatorTsDsl; 17 + readonly(this: MaybeTsDsl<TypeTsDsl>): ReturnType<typeof f.type.operator>; 67 18 /** Create a TypeExpr node representing ReturnType<this>. */ 68 - returnType(this: MaybeTsDsl<ts.Expression>): TypeExprTsDsl; 19 + returnType( 20 + this: Parameters<typeof f.type.query>[0], 21 + ...args: DropFirst<Parameters<typeof f.type.query>> 22 + ): ReturnType<typeof f.type.expr>; 69 23 /** Create a TypeOfExpr node representing typeof this. */ 70 - typeofExpr(this: MaybeTsDsl<ts.Expression>): TypeOfExprTsDsl; 24 + typeofExpr( 25 + this: Parameters<typeof f.typeofExpr>[0], 26 + ...args: DropFirst<Parameters<typeof f.typeofExpr>> 27 + ): ReturnType<typeof f.typeofExpr>; 71 28 /** Create a TypeQuery node representing typeof this. */ 72 - typeofType(this: MaybeTsDsl<TypeTsDsl | ts.Expression>): TypeQueryTsDsl; 29 + typeofType( 30 + this: Parameters<typeof f.type.query>[0], 31 + ...args: DropFirst<Parameters<typeof f.type.query>> 32 + ): ReturnType<typeof f.type.query>; 73 33 /** Shorthand: builds `unique T`. */ 74 - unique(this: MaybeTsDsl<TypeTsDsl>): TypeOperatorTsDsl; 34 + unique(this: MaybeTsDsl<TypeTsDsl>): ReturnType<typeof f.type.operator>; 75 35 } 76 36 77 37 export function TypeExprMixin<T extends ts.Node, TBase extends BaseCtor<T>>( ··· 83 43 } 84 44 85 45 protected idx( 86 - this: TypeTsDsl, 87 - index: string | number | MaybeTsDsl<ts.TypeNode>, 88 - ): TypeIdxTsDsl { 89 - return typeIdxFactory!(this, index); 46 + this: Parameters<typeof f.type.idx>[0], 47 + ...args: DropFirst<Parameters<typeof f.type.idx>> 48 + ): ReturnType<typeof f.type.idx> { 49 + return f.type.idx(this, ...args); 90 50 } 91 51 92 - protected keyof(this: TypeTsDsl): TypeOperatorTsDsl { 93 - return typeOperatorFactory!().keyof(this); 52 + protected keyof(this: TypeTsDsl): ReturnType<typeof f.type.operator> { 53 + return f.type.operator().keyof(this); 94 54 } 95 55 96 - protected readonly(this: TypeTsDsl): TypeOperatorTsDsl { 97 - return typeOperatorFactory!().readonly(this); 56 + protected readonly(this: TypeTsDsl): ReturnType<typeof f.type.operator> { 57 + return f.type.operator().readonly(this); 98 58 } 99 59 100 - protected returnType(this: TsDsl<ts.Expression>): TypeExprTsDsl { 101 - return typeExprFactory!('ReturnType').generic(typeQueryFactory!(this)); 60 + protected returnType( 61 + this: Parameters<typeof f.type.query>[0], 62 + ...args: DropFirst<Parameters<typeof f.type.query>> 63 + ): ReturnType<typeof f.type.expr> { 64 + return f.type.expr('ReturnType').generic(f.type.query(this, ...args)); 102 65 } 103 66 104 - protected typeofExpr(this: TsDsl<ts.Expression>): TypeOfExprTsDsl { 105 - return typeOfExprFactory!(this); 67 + protected typeofExpr( 68 + this: Parameters<typeof f.typeofExpr>[0], 69 + ...args: DropFirst<Parameters<typeof f.typeofExpr>> 70 + ): ReturnType<typeof f.typeofExpr> { 71 + return f.typeofExpr(this, ...args); 106 72 } 107 73 108 74 protected typeofType( 109 - this: TypeTsDsl | TsDsl<ts.Expression>, 110 - ): TypeQueryTsDsl { 111 - return typeQueryFactory!(this); 75 + this: Parameters<typeof f.type.query>[0], 76 + ...args: DropFirst<Parameters<typeof f.type.query>> 77 + ): ReturnType<typeof f.type.query> { 78 + return f.type.query(this, ...args); 112 79 } 113 80 114 - protected unique(this: TypeTsDsl): TypeOperatorTsDsl { 115 - return typeOperatorFactory!().unique(this); 81 + protected unique(this: TypeTsDsl): ReturnType<typeof f.type.operator> { 82 + return f.type.operator().unique(this); 116 83 } 117 84 } 118 85
+7 -2
packages/openapi-ts/src/ts-dsl/mixins/types.d.ts
··· 1 1 import type { TsDsl } from '../base'; 2 2 3 - export type BaseCtor<T> = abstract new (...args: any[]) => TsDsl<T>; 3 + export type BaseCtor<T> = abstract new (...args: Array<any>) => TsDsl<T>; 4 + 5 + export type DropFirst<T extends Array<any>> = T extends [any, ...infer Rest] 6 + ? Rest 7 + : never; 8 + 4 9 export type MixinCtor<T extends BaseCtor<any>, K> = abstract new ( 5 - ...args: any[] 10 + ...args: Array<any> 6 11 ) => InstanceType<T> & K;
+2 -2
packages/openapi-ts/src/ts-dsl/stmt/return.ts
··· 9 9 10 10 import type { MaybeTsDsl } from '../base'; 11 11 import { TsDsl } from '../base'; 12 - import { setReturnFactory } from '../mixins/expr'; 12 + import { f } from '../utils/factories'; 13 13 14 14 export type ReturnExpr = Symbol | string | MaybeTsDsl<ts.Expression>; 15 15 export type ReturnCtor = (expr?: ReturnExpr) => ReturnTsDsl; ··· 36 36 } 37 37 } 38 38 39 - setReturnFactory((...args) => new ReturnTsDsl(...args)); 39 + f.return.set((...args) => new ReturnTsDsl(...args));
+11 -8
packages/openapi-ts/src/ts-dsl/type/expr.ts
··· 9 9 10 10 import { TypeTsDsl } from '../base'; 11 11 import { TypeArgsMixin } from '../mixins/type-args'; 12 - import { setTypeExprFactory, TypeExprMixin } from '../mixins/type-expr'; 12 + import { TypeExprMixin } from '../mixins/type-expr'; 13 + import { f } from '../utils/factories'; 13 14 import { TypeAttrTsDsl } from './attr'; 14 15 15 16 export type TypeExprName = Symbol | string; 16 17 export type TypeExprExpr = TypeExprName | TypeAttrTsDsl; 18 + export type TypeExprFn = (t: TypeExprTsDsl) => void; 19 + export type TypeExprCtor = ( 20 + nameOrFn?: TypeExprName | TypeExprFn, 21 + fn?: TypeExprFn, 22 + ) => TypeExprTsDsl; 17 23 18 24 const Mixed = TypeArgsMixin(TypeExprMixin(TypeTsDsl<ts.TypeReferenceNode>)); 19 25 ··· 23 29 protected _exprInput?: Ref<TypeExprExpr>; 24 30 25 31 constructor(); 26 - constructor(fn: (t: TypeExprTsDsl) => void); 32 + constructor(fn: TypeExprFn); 27 33 constructor(name: TypeExprName); 28 - constructor(name: TypeExprName, fn?: (t: TypeExprTsDsl) => void); 29 - constructor( 30 - name?: TypeExprName | ((t: TypeExprTsDsl) => void), 31 - fn?: (t: TypeExprTsDsl) => void, 32 - ) { 34 + constructor(name: TypeExprName, fn?: TypeExprFn); 35 + constructor(name?: TypeExprName | TypeExprFn, fn?: TypeExprFn) { 33 36 super(); 34 37 if (typeof name === 'function') { 35 38 name(this); ··· 61 64 } 62 65 } 63 66 64 - setTypeExprFactory( 67 + f.type.expr.set( 65 68 (...args) => 66 69 new TypeExprTsDsl(...(args as ConstructorParameters<typeof TypeExprTsDsl>)), 67 70 );
+4 -2
packages/openapi-ts/src/ts-dsl/type/idx.ts
··· 3 3 4 4 import type { MaybeTsDsl } from '../base'; 5 5 import { TypeTsDsl } from '../base'; 6 - import { setTypeIdxFactory, TypeExprMixin } from '../mixins/type-expr'; 6 + import { TypeExprMixin } from '../mixins/type-expr'; 7 + import { f } from '../utils/factories'; 7 8 8 9 type Base = string | MaybeTsDsl<ts.TypeNode>; 9 10 type Index = string | number | MaybeTsDsl<ts.TypeNode>; 11 + export type TypeIdxCtor = (base: Base, index: Index) => TypeIdxTsDsl; 10 12 11 13 const Mixed = TypeExprMixin(TypeTsDsl<ts.IndexedAccessTypeNode>); 12 14 ··· 46 48 } 47 49 } 48 50 49 - setTypeIdxFactory((...args) => new TypeIdxTsDsl(...args)); 51 + f.type.idx.set((...args) => new TypeIdxTsDsl(...args));
+3 -2
packages/openapi-ts/src/ts-dsl/type/operator.ts
··· 3 3 4 4 import type { MaybeTsDsl } from '../base'; 5 5 import { TypeTsDsl } from '../base'; 6 - import { setTypeOperatorFactory } from '../mixins/type-expr'; 6 + import { f } from '../utils/factories'; 7 7 8 8 type Op = 9 9 | ts.SyntaxKind.KeyOfKeyword 10 10 | ts.SyntaxKind.ReadonlyKeyword 11 11 | ts.SyntaxKind.UniqueKeyword; 12 12 type Type = string | MaybeTsDsl<ts.TypeNode>; 13 + export type TypeOperatorCtor = () => TypeOperatorTsDsl; 13 14 14 15 const Mixed = TypeTsDsl<ts.TypeOperatorNode>; 15 16 ··· 95 96 } 96 97 } 97 98 98 - setTypeOperatorFactory((...args) => new TypeOperatorTsDsl(...args)); 99 + f.type.operator.set((...args) => new TypeOperatorTsDsl(...args));
+8 -4
packages/openapi-ts/src/ts-dsl/type/query.ts
··· 3 3 4 4 import type { MaybeTsDsl } from '../base'; 5 5 import { TypeTsDsl } from '../base'; 6 - import { setTypeQueryFactory, TypeExprMixin } from '../mixins/type-expr'; 6 + import { TypeExprMixin } from '../mixins/type-expr'; 7 + import { f } from '../utils/factories'; 8 + 9 + export type TypeQueryExpr = string | MaybeTsDsl<TypeTsDsl | ts.Expression>; 10 + export type TypeQueryCtor = (expr: TypeQueryExpr) => TypeQueryTsDsl; 7 11 8 12 const Mixed = TypeExprMixin(TypeTsDsl<ts.TypeQueryNode>); 9 13 10 14 export class TypeQueryTsDsl extends Mixed { 11 15 readonly '~dsl' = 'TypeQueryTsDsl'; 12 16 13 - protected _expr: string | MaybeTsDsl<TypeTsDsl | ts.Expression>; 17 + protected _expr: TypeQueryExpr; 14 18 15 - constructor(expr: string | MaybeTsDsl<TypeTsDsl | ts.Expression>) { 19 + constructor(expr: TypeQueryExpr) { 16 20 super(); 17 21 this._expr = expr; 18 22 } ··· 28 32 } 29 33 } 30 34 31 - setTypeQueryFactory((...args) => new TypeQueryTsDsl(...args)); 35 + f.type.query.set((...args) => new TypeQueryTsDsl(...args));
+68
packages/openapi-ts/src/ts-dsl/utils/factories.ts
··· 1 + import type { AsCtor } from '../expr/as'; 2 + import type { AttrCtor } from '../expr/attr'; 3 + import type { AwaitCtor } from '../expr/await'; 4 + import type { CallCtor } from '../expr/call'; 5 + import type { TypeOfExprCtor } from '../expr/typeof'; 6 + import type { ReturnCtor } from '../stmt/return'; 7 + import type { TypeExprCtor } from '../type/expr'; 8 + import type { TypeIdxCtor } from '../type/idx'; 9 + import type { TypeOperatorCtor } from '../type/operator'; 10 + import type { TypeQueryCtor } from '../type/query'; 11 + 12 + type Ctor = (...args: Array<any>) => any; 13 + 14 + type Factory<T extends Ctor> = { 15 + (...args: Parameters<T>): ReturnType<T>; 16 + /** Sets the implementation of this factory. */ 17 + set(fn: T): void; 18 + }; 19 + 20 + function createFactory<T extends Ctor>(name: string): Factory<T> { 21 + let impl: T | undefined; 22 + 23 + const slot = ((...args: Parameters<T>) => { 24 + if (!impl) throw new Error(`${name} factory not registered`); 25 + return impl(...args); 26 + }) as Factory<T>; 27 + 28 + slot.set = (fn: T) => { 29 + impl = fn; 30 + }; 31 + 32 + return slot; 33 + } 34 + 35 + export const f = { 36 + /** Factory for creating `as` type assertion expressions (e.g. `value as Type`). */ 37 + as: createFactory<AsCtor>('as'), 38 + 39 + /** Factory for creating property access expressions (e.g. `obj.foo`). */ 40 + attr: createFactory<AttrCtor>('attr'), 41 + 42 + /** Factory for creating await expressions (e.g. `await promise`). */ 43 + await: createFactory<AwaitCtor>('await'), 44 + 45 + /** Factory for creating function or method call expressions (e.g. `fn(arg)`). */ 46 + call: createFactory<CallCtor>('call'), 47 + 48 + /** Factory for creating return statements. */ 49 + return: createFactory<ReturnCtor>('return'), 50 + 51 + /** Factories for creating type nodes. */ 52 + type: { 53 + /** Factory for creating basic type references or type expressions (e.g. Foo or Foo<T>). */ 54 + expr: createFactory<TypeExprCtor>('type.expr'), 55 + 56 + /** Factory for creating indexed-access types (e.g. `Foo<T>[K]`). */ 57 + idx: createFactory<TypeIdxCtor>('type.idx'), 58 + 59 + /** Factory for creating type operator nodes (e.g. `readonly T`, `keyof T`, `unique T`). */ 60 + operator: createFactory<TypeOperatorCtor>('type.operator'), 61 + 62 + /** Factory for creating type query nodes (e.g. `typeof Foo`). */ 63 + query: createFactory<TypeQueryCtor>('type.query'), 64 + }, 65 + 66 + /** Factory for creating `typeof` expressions (e.g. `typeof value`). */ 67 + typeofExpr: createFactory<TypeOfExprCtor>('typeofExpr'), 68 + };