···1414 const value = process.env.DEBUG;
1515 if (!value) return;
16161717- const groups = value.split(",").map(x => x.trim().toLowerCase());
1717+ const groups = value.split(',').map((x) => x.trim().toLowerCase());
18181919 if (
2020 !(
2121- groups.includes("*") ||
2222- groups.includes("heyapi:*") ||
2121+ groups.includes('*') ||
2222+ groups.includes('heyapi:*') ||
2323 groups.includes(`heyapi:${group}`) ||
2424 groups.includes(group)
2525 )
+4-4
packages/codegen-core/src/symbols/symbol.ts
···8484 */
8585 private _name: string;
8686 /**
8787- * Root DSL node that defines this symbol.
8787+ * Root node that defines this symbol.
8888 *
8989 * @private
9090 */
···311311 }
312312313313 /**
314314- * Binds the DSL node that defines this symbol.
314314+ * Binds the node that defines this symbol.
315315 *
316316 * This may only be set once.
317317 */
318318 setRootNode(node: ISyntaxNode): void {
319319 this.assertCanonical();
320320 if (this._rootNode && this._rootNode !== node) {
321321- throw new Error('Symbol is already bound to a different root DSL node.');
321321+ throw new Error('Symbol is already bound to a different root node.');
322322 }
323323 this._rootNode = node;
324324 }
···344344 private assertCanonical(): void {
345345 if (this._canonical && this._canonical !== this) {
346346 const message = `Illegal mutation of stub symbol ${this.toString()} → canonical: ${this._canonical.toString()}`;
347347- debug(message, "symbol");
347347+ debug(message, 'symbol');
348348 throw new Error(message);
349349 }
350350 }
+4-4
packages/codegen-core/src/syntax-node.d.ts
···2233export interface ISyntaxNode {
44 /**
55- * Return local names introduced by this node.
55+ * Collect symbols referenced directly by this node into the provided accumulator.
66 */
77- getLocalNames(): Iterable<string>;
77+ collectSymbols(out: Set<Symbol>): void;
88 /**
99- * Return symbols referenced directly by this node.
99+ * Return local names introduced by this node.
1010 */
1111- getSymbols(): Iterable<Symbol>;
1111+ getLocalNames(): Iterable<string>;
1212 /**
1313 * Rewrite local identifiers based on a rename map.
1414 */
+6
packages/openapi-ts/src/ir/types.d.ts
···11+import type { Symbol } from '@hey-api/codegen-core';
22+13import type { JsonSchemaDraft2020_12 } from '~/openApi/3.1.x/types/json-schema-draft-2020-12';
24import type {
35 SecuritySchemeObject,
···185187 * follow a specific convention.
186188 */
187189 propertyNames?: IRSchemaObject;
190190+ /**
191191+ * Reference to symbol instead of `$ref` string.
192192+ */
193193+ symbolRef?: Symbol;
188194 /**
189195 * Each schema eventually resolves into `type`.
190196 */
···11-import type { SyntaxNode } from '@hey-api/codegen-core';
21import ts from 'typescript';
3243import type { MaybeArray } from '../base';
···5756 );
58575958 return node;
6060- }
6161-6262- // eslint-disable-next-line @typescript-eslint/no-unused-vars
6363- traverse(_visitor: (node: SyntaxNode) => void): void {
6464- // noop
6559 }
66606761 protected override _render(): ts.Node {
-6
packages/openapi-ts/src/ts-dsl/layout/hint.ts
···11-import type { SyntaxNode } from '@hey-api/codegen-core';
21import ts from 'typescript';
3243import type { MaybeArray } from '../base';
···3938 }
40394140 return node;
4242- }
4343-4444- // eslint-disable-next-line @typescript-eslint/no-unused-vars
4545- traverse(_visitor: (node: SyntaxNode) => void): void {
4646- // noop
4741 }
48424943 protected override _render(): ts.Node {
-6
packages/openapi-ts/src/ts-dsl/layout/newline.ts
···11-import type { SyntaxNode } from '@hey-api/codegen-core';
21import type ts from 'typescript';
3243import { TsDsl } from '../base';
54import { IdTsDsl } from '../expr/id';
6576export class NewlineTsDsl extends TsDsl<ts.Identifier> {
88- // eslint-disable-next-line @typescript-eslint/no-unused-vars
99- traverse(_visitor: (node: SyntaxNode) => void): void {
1010- // noop
1111- }
1212-137 protected override _render(): ts.Identifier {
148 return this.$node(new IdTsDsl('\n'));
159 }
-6
packages/openapi-ts/src/ts-dsl/layout/note.ts
···11-import type { SyntaxNode } from '@hey-api/codegen-core';
21import ts from 'typescript';
3243import type { MaybeArray } from '../base';
···3736 );
38373938 return node;
4040- }
4141-4242- // eslint-disable-next-line @typescript-eslint/no-unused-vars
4343- traverse(_visitor: (node: SyntaxNode) => void): void {
4444- // noop
4539 }
46404741 protected override _render(): ts.Node {
+2-1
packages/openapi-ts/src/ts-dsl/mixins/args.ts
···11+import type { SyntaxNode } from '@hey-api/codegen-core';
12import type ts from 'typescript';
2334import type { MaybeTsDsl } from '../base';
45import type { BaseCtor, MixinCtor } from './types';
5666-export interface ArgsMethods {
77+export interface ArgsMethods extends SyntaxNode {
78 /** Renders the arguments into an array of `Expression`s. */
89 $args(): ReadonlyArray<ts.Expression>;
910 /** Adds a single expression argument. */
+6-1
packages/openapi-ts/src/ts-dsl/mixins/as.ts
···11+import type { SyntaxNode } from '@hey-api/codegen-core';
12import type ts from 'typescript';
2334import type { MaybeTsDsl, TypeTsDsl } from '../base';
···1415 asFactory = factory;
1516}
16171717-export interface AsMethods {
1818+export interface AsMethods extends SyntaxNode {
1819 /** Creates an `as` type assertion expression (e.g. `value as Type`). */
1920 as(type: string | TypeTsDsl): AsTsDsl;
2021}
···2526 abstract class As extends Base {
2627 protected as(type: string | TypeTsDsl): AsTsDsl {
2728 return asFactory!(this, type);
2929+ }
3030+3131+ override traverse(visitor: (node: SyntaxNode) => void): void {
3232+ super.traverse(visitor);
2833 }
2934 }
3035
···11-import type { Symbol } from '@hey-api/codegen-core';
11+import type { Symbol, SyntaxNode } from '@hey-api/codegen-core';
22import type ts from 'typescript';
3344import type { MaybeTsDsl } from '../base';
55import { DecoratorTsDsl } from '../decl/decorator';
66import type { BaseCtor, MixinCtor } from './types';
7788-export interface DecoratorMethods {
88+export interface DecoratorMethods extends SyntaxNode {
99 /** Renders the decorators into an array of `ts.Decorator`s. */
1010 $decorators(): ReadonlyArray<ts.Decorator>;
1111 /** Adds a decorator (e.g. `@sealed({ in: 'root' })`). */
···2525 name: Symbol | string | MaybeTsDsl<ts.Expression>,
2626 ...args: ReadonlyArray<string | MaybeTsDsl<ts.Expression>>
2727 ): this {
2828- this.decorators.push(
2929- new DecoratorTsDsl(name, ...args).setParent(this as any),
3030- );
2828+ this.decorators.push(new DecoratorTsDsl(name, ...args).setParent(this));
3129 return this;
3230 }
3331
+2-1
packages/openapi-ts/src/ts-dsl/mixins/do.ts
···11+import type { SyntaxNode } from '@hey-api/codegen-core';
12import type ts from 'typescript';
2334import type { MaybeTsDsl } from '../base';
45import { StmtTsDsl } from '../stmt/stmt';
56import type { BaseCtor, MixinCtor } from './types';
6777-export interface DoMethods {
88+export interface DoMethods extends SyntaxNode {
89 /** Renders the collected `.do()` calls into an array of `Statement` nodes. */
910 $do(): ReadonlyArray<ts.Statement>;
1011 /** Adds one or more expressions/statements to the body. */
+2-1
packages/openapi-ts/src/ts-dsl/mixins/doc.ts
···11+import type { SyntaxNode } from '@hey-api/codegen-core';
12import type ts from 'typescript';
2334import type { MaybeArray } from '../base';
45import { DocTsDsl } from '../layout/doc';
56import type { BaseCtor, MixinCtor } from './types';
6777-export interface DocMethods {
88+export interface DocMethods extends SyntaxNode {
89 doc(lines?: MaybeArray<string>, fn?: (d: DocTsDsl) => void): this;
910}
1011
+2-1
packages/openapi-ts/src/ts-dsl/mixins/expr.ts
···11+import type { SyntaxNode } from '@hey-api/codegen-core';
12import type ts from 'typescript';
2334import type { MaybeTsDsl } from '../base';
···4142 returnFactory = factory;
4243}
43444444-export interface ExprMethods {
4545+export interface ExprMethods extends SyntaxNode {
4546 /** Accesses a property on the current expression (e.g. `this.foo`). */
4647 attr(name: string | ts.MemberName | number): AttrTsDsl;
4748 /** Awaits the current expression (e.g. `await expr`). */
+2-1
packages/openapi-ts/src/ts-dsl/mixins/hint.ts
···11+import type { SyntaxNode } from '@hey-api/codegen-core';
12import type ts from 'typescript';
2334import type { MaybeArray } from '../base';
45import { HintTsDsl } from '../layout/hint';
56import type { BaseCtor, MixinCtor } from './types';
6777-export interface HintMethods {
88+export interface HintMethods extends SyntaxNode {
89 hint(lines?: MaybeArray<string>, fn?: (h: HintTsDsl) => void): this;
910}
1011
+2-1
packages/openapi-ts/src/ts-dsl/mixins/layout.ts
···11+import type { SyntaxNode } from '@hey-api/codegen-core';
12import type ts from 'typescript';
2334import type { BaseCtor, MixinCtor } from './types';
4555-export interface LayoutMethods {
66+export interface LayoutMethods extends SyntaxNode {
67 /** Computes whether output should be multiline based on layout setting and element count. */
78 $multiline(count: number): boolean;
89 /** Sets automatic line output with optional threshold (default: 3). */
···1212 *
1313 * @param kind - The syntax kind of the modifier to add.
1414 * @param condition - Whether to add the modifier.
1515- * @returns The parent DSL node for chaining.
1515+ * @returns The parent node for chaining.
1616 */
1717 _m(kind: ts.ModifierSyntaxKind, condition: boolean): this;
1818}
+2-1
packages/openapi-ts/src/ts-dsl/mixins/note.ts
···11+import type { SyntaxNode } from '@hey-api/codegen-core';
12import type ts from 'typescript';
2334import type { MaybeArray } from '../base';
45import { NoteTsDsl } from '../layout/note';
56import type { BaseCtor, MixinCtor } from './types';
6777-export interface NoteMethods {
88+export interface NoteMethods extends SyntaxNode {
89 note(lines?: MaybeArray<string>, fn?: (h: NoteTsDsl) => void): this;
910}
1011
+2-1
packages/openapi-ts/src/ts-dsl/mixins/operator.ts
···11+import type { SyntaxNode } from '@hey-api/codegen-core';
12import type ts from 'typescript';
2334import type { MaybeTsDsl } from '../base';
···6778type Expr = string | MaybeTsDsl<ts.Expression>;
8999-export interface OperatorMethods {
1010+export interface OperatorMethods extends SyntaxNode {
1011 /** Logical AND — `this && expr` */
1112 and(expr: Expr): BinaryTsDsl;
1213 /** Creates an assignment expression (e.g. `this = expr`). */
+2-1
packages/openapi-ts/src/ts-dsl/mixins/optional.ts
···11+import type { SyntaxNode } from '@hey-api/codegen-core';
12import type ts from 'typescript';
2334import type { BaseCtor, MixinCtor } from './types';
4555-export interface OptionalMethods {
66+export interface OptionalMethods extends SyntaxNode {
67 _optional?: boolean;
78 /** Marks the node as optional when the condition is true. */
89 optional(condition?: boolean): this;
+2-1
packages/openapi-ts/src/ts-dsl/mixins/param.ts
···11+import type { SyntaxNode } from '@hey-api/codegen-core';
12import type ts from 'typescript';
2334import type { MaybeTsDsl } from '../base';
45import { ParamTsDsl } from '../decl/param';
56import type { BaseCtor, MixinCtor } from './types';
6777-export interface ParamMethods {
88+export interface ParamMethods extends SyntaxNode {
89 /** Renders the parameters into an array of `ParameterDeclaration`s. */
910 $params(): ReadonlyArray<ts.ParameterDeclaration>;
1011 /** Adds a parameter. */
+7-5
packages/openapi-ts/src/ts-dsl/mixins/pattern.ts
···11+import type { SyntaxNode } from '@hey-api/codegen-core';
12import type ts from 'typescript';
2334import type { MaybeArray } from '../base';
45import { PatternTsDsl } from '../decl/pattern';
56import type { BaseCtor, MixinCtor } from './types';
6777-export interface PatternMethods {
88+export interface PatternMethods extends SyntaxNode {
89 /** Renders the pattern into a `BindingName`. */
910 $pattern(): ts.BindingName | undefined;
1011 /** Defines an array binding pattern. */
···2425 Base: TBase,
2526) {
2627 abstract class Pattern extends Base {
2727- protected pattern: PatternTsDsl = new PatternTsDsl();
2828+ protected pattern?: PatternTsDsl;
28292930 protected array(
3031 ...props: ReadonlyArray<string> | [ReadonlyArray<string>]
3132 ): this {
3232- this.pattern.array(...props);
3333+ (this.pattern ??= new PatternTsDsl()).array(...props);
3334 return this;
3435 }
35363637 protected object(
3738 ...props: ReadonlyArray<MaybeArray<string> | Record<string, string>>
3839 ): this {
3939- this.pattern.object(...props);
4040+ (this.pattern ??= new PatternTsDsl()).object(...props);
4041 return this;
4142 }
42434344 /** Adds a spread element (e.g. `...args`, `...options`) to the pattern. */
4445 protected spread(name: string): this {
4545- this.pattern.spread(name);
4646+ (this.pattern ??= new PatternTsDsl()).spread(name);
4647 return this;
4748 }
48494950 /** Renders the pattern into a `BindingName`. */
5051 protected $pattern(): ts.BindingName | undefined {
5252+ if (!this.pattern) return;
5153 return this.$node(this.pattern);
5254 }
5355 }