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

chore: support thunks in doc methods

Lubos 99be2403 1cbb8262

+81 -69
+2 -2
dev/openapi-ts.config.ts
··· 47 47 // 'full.yaml', 48 48 // 'sdk-method-class-conflict.yaml', 49 49 // 'object-property-names.yaml', 50 - 'openai.yaml', 51 - // 'opencode.yaml', 50 + // 'openai.yaml', 51 + 'opencode.yaml', 52 52 // 'pagination-ref.yaml', 53 53 // 'sdk-instance.yaml', 54 54 // 'sdk-nested-classes.yaml',
+9 -8
packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts
··· 47 47 export const registryName = '__registry'; 48 48 49 49 const createRegistryClass = ({ 50 + plugin, 50 51 sdkSymbol, 51 52 symbol, 52 53 }: { ··· 54 55 sdkSymbol: Symbol; 55 56 symbol: Symbol; 56 57 }): TsDsl => { 57 - const defaultKey = 'defaultKey'; 58 - const instances = 'instances'; 58 + const symbolDefaultKey = plugin.symbol('defaultKey'); 59 + const symbolInstances = plugin.symbol('instances'); 59 60 return $.class(symbol) 60 61 .generic('T') 61 - .field(defaultKey, (f) => 62 + .field(symbolDefaultKey, (f) => 62 63 f.private().readonly().assign($.literal('default')), 63 64 ) 64 65 .newline() 65 - .field(instances, (f) => 66 + .field(symbolInstances, (f) => 66 67 f 67 68 .private() 68 69 .readonly() ··· 77 78 .do( 78 79 $.const('instance').assign( 79 80 $('this') 80 - .attr('instances') 81 + .attr(symbolInstances) 81 82 .attr('get') 82 - .call($('key').coalesce($('this').attr(defaultKey))), 83 + .call($('key').coalesce($('this').attr(symbolDefaultKey))), 83 84 ), 84 85 $.if($.not('instance')).do( 85 86 $.throw('Error').message( ··· 99 100 .param('key', (p) => p.type('string').optional()) 100 101 .do( 101 102 $('this') 102 - .attr(instances) 103 + .attr(symbolInstances) 103 104 .attr('set') 104 - .call($('key').coalesce($('this').attr(defaultKey)), 'value'), 105 + .call($('key').coalesce($('this').attr(symbolDefaultKey)), 'value'), 105 106 ), 106 107 ); 107 108 };
+2 -1
packages/openapi-ts/src/ts-dsl/decl/class.ts
··· 10 10 import { AbstractMixin, DefaultMixin, ExportMixin } from '../mixins/modifiers'; 11 11 import { TypeParamsMixin } from '../mixins/type-params'; 12 12 import { safeRuntimeName } from '../utils/name'; 13 + import type { FieldName } from './field'; 13 14 import { FieldTsDsl } from './field'; 14 15 import { InitTsDsl } from './init'; 15 16 import { MethodTsDsl } from './method'; ··· 70 71 } 71 72 72 73 /** Adds a class field. */ 73 - field(name: string, fn?: (f: FieldTsDsl) => void): this { 74 + field(name: FieldName, fn?: (f: FieldTsDsl) => void): this { 74 75 const f = new FieldTsDsl(name, fn); 75 76 this.body.push(f); 76 77 return this;
+5 -4
packages/openapi-ts/src/ts-dsl/decl/field.ts
··· 1 - import type { AnalysisContext } from '@hey-api/codegen-core'; 1 + import type { AnalysisContext, Symbol } from '@hey-api/codegen-core'; 2 2 import ts from 'typescript'; 3 3 4 4 import { TsDsl, TypeTsDsl } from '../base'; ··· 15 15 import type { TypeExprName } from '../type/expr'; 16 16 import { TypeExprTsDsl } from '../type/expr'; 17 17 18 + export type FieldName = Symbol | string; 18 19 export type FieldType = TypeExprName | TypeTsDsl; 19 20 20 21 const Mixed = DecoratorMixin( ··· 32 33 export class FieldTsDsl extends Mixed { 33 34 readonly '~dsl' = 'FieldTsDsl'; 34 35 35 - protected name: string; 36 + protected name: FieldName; 36 37 protected _type?: TypeTsDsl; 37 38 38 - constructor(name: string, fn?: (f: FieldTsDsl) => void) { 39 + constructor(name: FieldName, fn?: (f: FieldTsDsl) => void) { 39 40 super(); 40 41 this.name = name; 41 42 fn?.(this); ··· 55 56 override toAst() { 56 57 const node = ts.factory.createPropertyDeclaration( 57 58 [...this.$decorators(), ...this.modifiers], 58 - this.name, 59 + this.$node(this.name) as ts.PropertyName, 59 60 undefined, 60 61 this.$type(this._type), 61 62 this.$value(),
+16 -12
packages/openapi-ts/src/ts-dsl/layout/doc.ts
··· 5 5 import { TsDsl } from '../base'; 6 6 import { IdTsDsl } from '../expr/id'; 7 7 8 + type DocMaybeLazy<T> = (() => T) | T; 9 + export type DocFn = (d: DocTsDsl) => void; 10 + export type DocLines = DocMaybeLazy<MaybeArray<string>>; 11 + 8 12 export class DocTsDsl extends TsDsl<ts.Node> { 9 13 readonly '~dsl' = 'DocTsDsl'; 10 14 11 - protected _lines: Array<string> = []; 15 + protected _lines: Array<DocLines> = []; 12 16 13 - constructor(lines?: MaybeArray<string>, fn?: (d: DocTsDsl) => void) { 17 + constructor(lines?: DocLines, fn?: DocFn) { 14 18 super(); 15 - if (lines) { 16 - if (typeof lines === 'string') { 17 - this.add(lines); 18 - } else { 19 - this.add(...lines); 20 - } 21 - } 19 + if (lines) this.add(lines); 22 20 fn?.(this); 23 21 } 24 22 ··· 26 24 super.analyze(ctx); 27 25 } 28 26 29 - add(...lines: ReadonlyArray<string>): this { 30 - this._lines.push(...lines); 27 + add(lines: DocLines): this { 28 + this._lines.push(lines); 31 29 return this; 32 30 } 33 31 34 32 apply<T extends ts.Node>(node: T): T { 35 - const lines = this._lines.filter((line) => Boolean(line) || line === ''); 33 + const lines = this._lines.reduce((lines: Array<string>, line: DocLines) => { 34 + if (typeof line === 'function') line = line(); 35 + for (const l of typeof line === 'string' ? [line] : line) { 36 + if (l || l === '') lines.push(l); 37 + } 38 + return lines; 39 + }, []); 36 40 if (!lines.length) return node; 37 41 38 42 const jsdocTexts = lines.map((line) =>
+19 -12
packages/openapi-ts/src/ts-dsl/layout/hint.ts
··· 5 5 import { TsDsl } from '../base'; 6 6 import { IdTsDsl } from '../expr/id'; 7 7 8 + type HintMaybeLazy<T> = (() => T) | T; 9 + export type HintFn = (d: HintTsDsl) => void; 10 + export type HintLines = HintMaybeLazy<MaybeArray<string>>; 11 + 8 12 export class HintTsDsl extends TsDsl<ts.Node> { 9 13 readonly '~dsl' = 'HintTsDsl'; 10 14 11 - protected _lines: Array<string> = []; 15 + protected _lines: Array<HintLines> = []; 12 16 13 - constructor(lines?: MaybeArray<string>, fn?: (d: HintTsDsl) => void) { 17 + constructor(lines?: HintLines, fn?: HintFn) { 14 18 super(); 15 - if (lines) { 16 - if (typeof lines === 'string') { 17 - this.add(lines); 18 - } else { 19 - this.add(...lines); 20 - } 21 - } 19 + if (lines) this.add(lines); 22 20 fn?.(this); 23 21 } 24 22 ··· 26 24 super.analyze(ctx); 27 25 } 28 26 29 - add(...lines: ReadonlyArray<string>): this { 30 - this._lines.push(...lines); 27 + add(lines: HintLines): this { 28 + this._lines.push(lines); 31 29 return this; 32 30 } 33 31 34 32 apply<T extends ts.Node>(node: T): T { 35 - const lines = this._lines.filter((line) => Boolean(line) || line === ''); 33 + const lines = this._lines.reduce( 34 + (lines: Array<string>, line: HintLines) => { 35 + if (typeof line === 'function') line = line(); 36 + for (const l of typeof line === 'string' ? [line] : line) { 37 + if (l || l === '') lines.push(l); 38 + } 39 + return lines; 40 + }, 41 + [], 42 + ); 36 43 if (!lines.length) return node; 37 44 38 45 for (const line of lines) {
+19 -12
packages/openapi-ts/src/ts-dsl/layout/note.ts
··· 5 5 import { TsDsl } from '../base'; 6 6 import { IdTsDsl } from '../expr/id'; 7 7 8 + type NoteMaybeLazy<T> = (() => T) | T; 9 + export type NoteFn = (d: NoteTsDsl) => void; 10 + export type NoteLines = NoteMaybeLazy<MaybeArray<string>>; 11 + 8 12 export class NoteTsDsl extends TsDsl<ts.Node> { 9 13 readonly '~dsl' = 'NoteTsDsl'; 10 14 11 - protected _lines: Array<string> = []; 15 + protected _lines: Array<NoteLines> = []; 12 16 13 - constructor(lines?: MaybeArray<string>, fn?: (d: NoteTsDsl) => void) { 17 + constructor(lines?: NoteLines, fn?: NoteFn) { 14 18 super(); 15 - if (lines) { 16 - if (typeof lines === 'string') { 17 - this.add(lines); 18 - } else { 19 - this.add(...lines); 20 - } 21 - } 19 + if (lines) this.add(lines); 22 20 fn?.(this); 23 21 } 24 22 ··· 26 24 super.analyze(ctx); 27 25 } 28 26 29 - add(...lines: ReadonlyArray<string>): this { 30 - this._lines.push(...lines); 27 + add(lines: NoteLines): this { 28 + this._lines.push(lines); 31 29 return this; 32 30 } 33 31 34 32 apply<T extends ts.Node>(node: T): T { 35 - const lines = this._lines.filter((line) => Boolean(line) || line === ''); 33 + const lines = this._lines.reduce( 34 + (lines: Array<string>, line: NoteLines) => { 35 + if (typeof line === 'function') line = line(); 36 + for (const l of typeof line === 'string' ? [line] : line) { 37 + if (l || l === '') lines.push(l); 38 + } 39 + return lines; 40 + }, 41 + [], 42 + ); 36 43 if (!lines.length) return node; 37 44 38 45 ts.addSyntheticLeadingComment(
+3 -6
packages/openapi-ts/src/ts-dsl/mixins/doc.ts
··· 1 1 import type { AnalysisContext, Node } from '@hey-api/codegen-core'; 2 2 import type ts from 'typescript'; 3 3 4 - import type { MaybeArray } from '../base'; 4 + import type { DocFn, DocLines } from '../layout/doc'; 5 5 import { DocTsDsl } from '../layout/doc'; 6 6 import type { BaseCtor, MixinCtor } from './types'; 7 7 8 8 export interface DocMethods extends Node { 9 9 $docs<T extends ts.Node>(node: T): T; 10 - doc(lines?: MaybeArray<string>, fn?: (d: DocTsDsl) => void): this; 10 + doc(lines?: DocLines, fn?: DocFn): this; 11 11 } 12 12 13 13 export function DocMixin<T extends ts.Node, TBase extends BaseCtor<T>>( ··· 20 20 super.analyze(ctx); 21 21 } 22 22 23 - protected doc( 24 - lines?: MaybeArray<string>, 25 - fn?: (d: DocTsDsl) => void, 26 - ): this { 23 + protected doc(lines?: DocLines, fn?: DocFn): this { 27 24 this._doc = new DocTsDsl(lines, fn); 28 25 return this; 29 26 }
+3 -6
packages/openapi-ts/src/ts-dsl/mixins/hint.ts
··· 1 1 import type { AnalysisContext, Node } from '@hey-api/codegen-core'; 2 2 import type ts from 'typescript'; 3 3 4 - import type { MaybeArray } from '../base'; 4 + import type { HintFn, HintLines } from '../layout/hint'; 5 5 import { HintTsDsl } from '../layout/hint'; 6 6 import type { BaseCtor, MixinCtor } from './types'; 7 7 8 8 export interface HintMethods extends Node { 9 9 $hint<T extends ts.Node>(node: T): T; 10 - hint(lines?: MaybeArray<string>, fn?: (h: HintTsDsl) => void): this; 10 + hint(lines?: HintLines, fn?: HintFn): this; 11 11 } 12 12 13 13 export function HintMixin<T extends ts.Node, TBase extends BaseCtor<T>>( ··· 20 20 super.analyze(ctx); 21 21 } 22 22 23 - protected hint( 24 - lines?: MaybeArray<string>, 25 - fn?: (h: HintTsDsl) => void, 26 - ): this { 23 + protected hint(lines?: HintLines, fn?: HintFn): this { 27 24 this._hint = new HintTsDsl(lines, fn); 28 25 return this; 29 26 }
+3 -6
packages/openapi-ts/src/ts-dsl/mixins/note.ts
··· 1 1 import type { AnalysisContext, Node } from '@hey-api/codegen-core'; 2 2 import type ts from 'typescript'; 3 3 4 - import type { MaybeArray } from '../base'; 4 + import type { NoteFn, NoteLines } from '../layout/note'; 5 5 import { NoteTsDsl } from '../layout/note'; 6 6 import type { BaseCtor, MixinCtor } from './types'; 7 7 8 8 export interface NoteMethods extends Node { 9 9 $note<T extends ts.Node>(node: T): T; 10 - note(lines?: MaybeArray<string>, fn?: (h: NoteTsDsl) => void): this; 10 + note(lines?: NoteLines, fn?: NoteFn): this; 11 11 } 12 12 13 13 export function NoteMixin<T extends ts.Node, TBase extends BaseCtor<T>>( ··· 20 20 super.analyze(ctx); 21 21 } 22 22 23 - protected note( 24 - lines?: MaybeArray<string>, 25 - fn?: (h: NoteTsDsl) => void, 26 - ): this { 23 + protected note(lines?: NoteLines, fn?: NoteFn): this { 27 24 this._note = new NoteTsDsl(lines, fn); 28 25 return this; 29 26 }