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

feat: canonical symbols

Lubos 2b253c05 4f982d5a

+1523 -745
+8 -7
dev/openapi-ts.config.ts
··· 39 39 '3.1.x', 40 40 // 'circular.yaml', 41 41 // 'dutchie.json', 42 + 'enum-names-values.yaml', 42 43 // 'invalid', 43 - 'full.yaml', 44 + // 'full.yaml', 44 45 // 'object-property-names.yaml', 45 46 // 'openai.yaml', 46 47 // 'opencode.yaml', ··· 217 218 { 218 219 // baseUrl: false, 219 220 // exportFromIndex: true, 220 - name: '@hey-api/client-angular', 221 + // name: '@hey-api/client-angular', 221 222 // runtimeConfigPath: path.resolve(__dirname, 'hey-api.ts'), 222 223 // runtimeConfigPath: './src/hey-api.ts', 223 224 // strictBaseUrl: true, ··· 265 266 name: '@hey-api/sdk', 266 267 // operationId: false, 267 268 // paramsStructure: 'flat', 268 - responseStyle: 'data', 269 + // responseStyle: 'data', 269 270 // signature: 'auto', 270 271 // signature: 'client', 271 272 // signature: 'object', ··· 293 294 { 294 295 // bigInt: true, 295 296 dates: true, 296 - name: '@hey-api/transformers', 297 + // name: '@hey-api/transformers', 297 298 }, 298 299 { 299 - name: 'fastify', 300 + // name: 'fastify', 300 301 }, 301 302 { 302 - name: 'swr', 303 + // name: 'swr', 303 304 }, 304 305 { 305 306 // case: 'SCREAMING_SNAKE_CASE', ··· 362 363 }, 363 364 }, 364 365 { 365 - name: 'arktype', 366 + // name: 'arktype', 366 367 types: { 367 368 infer: true, 368 369 },
+1 -1
docs/package.json
··· 1 1 { 2 2 "name": "@docs/openapi-ts", 3 3 "version": "0.10.4", 4 - "description": "Documentation for OpenaAPI TypeScript.", 4 + "description": "Documentation for OpenAPI TypeScript.", 5 5 "private": true, 6 6 "type": "module", 7 7 "scripts": {
+13
docs/scripts/optimize-images.js
··· 31 31 ], 32 32 source: 'bricks.png', 33 33 }, 34 + // { 35 + // sizes: [ 36 + // { 37 + // formats: ['png'], 38 + // width: 300, 39 + // }, 40 + // { 41 + // formats: ['png'], 42 + // width: 640, 43 + // }, 44 + // ], 45 + // source: 'hero.png', 46 + // }, 34 47 { 35 48 sizes: [ 36 49 {
+61 -61
examples/openapi-ts-openai/src/client/types.gen.ts
··· 259 259 GPT_3_5_TURBO_16K_0613: 'gpt-3.5-turbo-16k-0613', 260 260 } as const; 261 261 262 - export type AssistantSupportedModels = 263 - (typeof AssistantSupportedModels)[keyof typeof AssistantSupportedModels]; 262 + export type AssistantSupportedModels2 = 263 + (typeof AssistantSupportedModels2)[keyof typeof AssistantSupportedModels2]; 264 264 265 265 /** 266 266 * Code interpreter tool ··· 378 378 * The format of the output, in one of these options: `json`, `text`, `srt`, `verbose_json`, or `vtt`. For `gpt-4o-transcribe` and `gpt-4o-mini-transcribe`, the only supported format is `json`. 379 379 * 380 380 */ 381 - export type AudioResponseFormat = 382 - (typeof AudioResponseFormat)[keyof typeof AudioResponseFormat]; 381 + export type AudioResponseFormat2 = 382 + (typeof AudioResponseFormat2)[keyof typeof AudioResponseFormat2]; 383 383 384 384 /** 385 385 * A log of a user action or configuration change within this organization. ··· 389 389 * The ID of this log. 390 390 */ 391 391 id: string; 392 - type: AuditLogEventType; 392 + type: AuditLogEventType2; 393 393 /** 394 394 * The Unix timestamp (in seconds) of the event. 395 395 */ ··· 949 949 /** 950 950 * The event type. 951 951 */ 952 - export type AuditLogEventType = 953 - (typeof AuditLogEventType)[keyof typeof AuditLogEventType]; 952 + export type AuditLogEventType2 = 953 + (typeof AuditLogEventType2)[keyof typeof AuditLogEventType2]; 954 954 955 955 /** 956 956 * Auto Chunking Strategy ··· 1911 1911 /** 1912 1912 * The role of the author of a message 1913 1913 */ 1914 - export type ChatCompletionRole = 1915 - (typeof ChatCompletionRole)[keyof typeof ChatCompletionRole]; 1914 + export type ChatCompletionRole2 = 1915 + (typeof ChatCompletionRole2)[keyof typeof ChatCompletionRole2]; 1916 1916 1917 1917 /** 1918 1918 * Options for streaming response. Only set this when you set `stream: true`. ··· 2698 2698 * ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models) for descriptions of them. 2699 2699 * 2700 2700 */ 2701 - model: string | AssistantSupportedModels; 2701 + model: string | AssistantSupportedModels2; 2702 2702 /** 2703 2703 * The name of the assistant. The maximum length is 256 characters. 2704 2704 * ··· 2714 2714 * 2715 2715 */ 2716 2716 instructions?: string; 2717 - reasoning_effort?: ReasoningEffort; 2717 + reasoning_effort?: ReasoningEffort2; 2718 2718 /** 2719 2719 * A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `file_search`, or `function`. 2720 2720 * ··· 2815 2815 */ 2816 2816 model: ModelIdsShared; 2817 2817 modalities?: ResponseModalities; 2818 - verbosity?: Verbosity; 2819 - reasoning_effort?: ReasoningEffort; 2818 + verbosity?: Verbosity2; 2819 + reasoning_effort?: ReasoningEffort2; 2820 2820 /** 2821 2821 * An upper bound for the number of tokens that can be generated for a completion, including visible output tokens and [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). 2822 2822 * ··· 2856 2856 type: 'approximate'; 2857 2857 approximate: WebSearchLocation; 2858 2858 }; 2859 - search_context_size?: WebSearchContextSize; 2859 + search_context_size?: WebSearchContextSize2; 2860 2860 }; 2861 2861 /** 2862 2862 * An integer between 0 and 20 specifying the number of most likely tokens to ··· 3077 3077 * The model used for the chat completion. 3078 3078 */ 3079 3079 model: string; 3080 - service_tier?: ServiceTier; 3080 + service_tier?: ServiceTier2; 3081 3081 /** 3082 3082 * This fingerprint represents the backend configuration that the model runs with. 3083 3083 * ··· 3151 3151 * The model to generate the completion. 3152 3152 */ 3153 3153 model: string; 3154 - service_tier?: ServiceTier; 3154 + service_tier?: ServiceTier2; 3155 3155 /** 3156 3156 * This fingerprint represents the backend configuration that the model runs with. 3157 3157 * Can be used in conjunction with the `seed` request parameter to understand when backend changes have been made that might impact determinism. ··· 3859 3859 * 3860 3860 */ 3861 3861 file: Blob | File; 3862 - purpose: FilePurpose; 3862 + purpose: FilePurpose2; 3863 3863 expires_after?: FileExpirationAfter; 3864 3864 }; 3865 3865 ··· 4065 4065 * 4066 4066 */ 4067 4067 user?: string; 4068 - input_fidelity?: ImageInputFidelity; 4068 + input_fidelity?: ImageInputFidelity2; 4069 4069 /** 4070 4070 * Edit the image in streaming mode. Defaults to `false`. See the 4071 4071 * [Image generation guide](https://platform.openai.com/docs/guides/image-generation) for more information. ··· 4498 4498 * enrolled in the zero data retention program). 4499 4499 * 4500 4500 */ 4501 - include?: Array<Includable>; 4501 + include?: Array<Includable2>; 4502 4502 /** 4503 4503 * Whether to allow the model to run tool calls in parallel. 4504 4504 * ··· 4538 4538 /** 4539 4539 * The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used. 4540 4540 */ 4541 - model?: string | AssistantSupportedModels; 4542 - reasoning_effort?: ReasoningEffort; 4541 + model?: string | AssistantSupportedModels2; 4542 + reasoning_effort?: ReasoningEffort2; 4543 4543 /** 4544 4544 * Overrides the [instructions](https://platform.openai.com/docs/api-reference/assistants/createAssistant) of the assistant. This is useful for modifying the behavior on a per-run basis. 4545 4545 */ ··· 4836 4836 * 4837 4837 */ 4838 4838 prompt?: string; 4839 - response_format?: AudioResponseFormat; 4839 + response_format?: AudioResponseFormat2; 4840 4840 /** 4841 4841 * The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit. 4842 4842 * ··· 4866 4866 * the models `gpt-4o-transcribe` and `gpt-4o-mini-transcribe`. 4867 4867 * 4868 4868 */ 4869 - include?: Array<TranscriptionInclude>; 4869 + include?: Array<TranscriptionInclude2>; 4870 4870 }; 4871 4871 4872 4872 /** ··· 5746 5746 /** 5747 5747 * Optional reasoning effort parameter. This is a query parameter used to select responses. 5748 5748 */ 5749 - reasoning_effort?: ReasoningEffort; 5749 + reasoning_effort?: ReasoningEffort2; 5750 5750 /** 5751 5751 * Sampling temperature. This is a query parameter used to select responses. 5752 5752 */ ··· 6181 6181 /** 6182 6182 * The ranker to use for the file search. If not specified will use the `auto` ranker. 6183 6183 */ 6184 - export type FileSearchRanker = 6185 - (typeof FileSearchRanker)[keyof typeof FileSearchRanker]; 6184 + export type FileSearchRanker2 = 6185 + (typeof FileSearchRanker2)[keyof typeof FileSearchRanker2]; 6186 6186 6187 6187 /** 6188 6188 * File search tool call ranking options ··· 6193 6193 * 6194 6194 */ 6195 6195 export type FileSearchRankingOptions = { 6196 - ranker?: FileSearchRanker; 6196 + ranker?: FileSearchRanker2; 6197 6197 /** 6198 6198 * The score threshold for the file search. All values must be a floating point number between 0 and 1. 6199 6199 */ ··· 7313 7313 * 7314 7314 */ 7315 7315 background?: 'transparent' | 'opaque' | 'auto'; 7316 - input_fidelity?: ImageInputFidelity; 7316 + input_fidelity?: ImageInputFidelity2; 7317 7317 /** 7318 7318 * Optional mask for inpainting. Contains `image_url` 7319 7319 * (string, optional) and `file_id` (string, optional). ··· 7381 7381 * for `gpt-image-1`. Supports `high` and `low`. Defaults to `low`. 7382 7382 * 7383 7383 */ 7384 - export type ImageInputFidelity = 7385 - (typeof ImageInputFidelity)[keyof typeof ImageInputFidelity]; 7384 + export type ImageInputFidelity2 = 7385 + (typeof ImageInputFidelity2)[keyof typeof ImageInputFidelity2]; 7386 7386 7387 7387 /** 7388 7388 * Image generation response ··· 7494 7494 * enrolled in the zero data retention program). 7495 7495 * 7496 7496 */ 7497 - export type Includable = (typeof Includable)[keyof typeof Includable]; 7497 + export type Includable2 = (typeof Includable2)[keyof typeof Includable2]; 7498 7498 7499 7499 /** 7500 7500 * Audio input ··· 8846 8846 | 'computer-use-preview' 8847 8847 | 'computer-use-preview-2025-03-11'; 8848 8848 8849 - export type ModelIdsShared = string | ChatModel; 8849 + export type ModelIdsShared = string | ChatModel2; 8850 8850 8851 8851 export type ModelResponseProperties = { 8852 8852 metadata?: Metadata; ··· 8892 8892 * 8893 8893 */ 8894 8894 prompt_cache_key?: string; 8895 - service_tier?: ServiceTier; 8895 + service_tier?: ServiceTier2; 8896 8896 }; 8897 8897 8898 8898 export type ModifyAssistantRequest = { ··· 8900 8900 * ID of the model to use. You can use the [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](https://platform.openai.com/docs/models) for descriptions of them. 8901 8901 * 8902 8902 */ 8903 - model?: string | AssistantSupportedModels; 8904 - reasoning_effort?: ReasoningEffort; 8903 + model?: string | AssistantSupportedModels2; 8904 + reasoning_effort?: ReasoningEffort2; 8905 8905 /** 8906 8906 * The name of the assistant. The maximum length is 256 characters. 8907 8907 * ··· 12424 12424 * 12425 12425 */ 12426 12426 export type Reasoning = { 12427 - effort?: ReasoningEffort; 12427 + effort?: ReasoningEffort2; 12428 12428 /** 12429 12429 * A summary of the reasoning performed by the model. This can be 12430 12430 * useful for debugging and understanding the model's reasoning process. ··· 12468 12468 * on reasoning in a response. 12469 12469 * 12470 12470 */ 12471 - export type ReasoningEffort = 12472 - (typeof ReasoningEffort)[keyof typeof ReasoningEffort]; 12471 + export type ReasoningEffort2 = 12472 + (typeof ReasoningEffort2)[keyof typeof ReasoningEffort2]; 12473 12473 12474 12474 /** 12475 12475 * Reasoning ··· 12980 12980 * 12981 12981 */ 12982 12982 export type ResponseError = { 12983 - code: ResponseErrorCode; 12983 + code: ResponseErrorCode2; 12984 12984 /** 12985 12985 * A human-readable description of the error. 12986 12986 * ··· 13017 13017 * The error code for the response. 13018 13018 * 13019 13019 */ 13020 - export type ResponseErrorCode = 13021 - (typeof ResponseErrorCode)[keyof typeof ResponseErrorCode]; 13020 + export type ResponseErrorCode2 = 13021 + (typeof ResponseErrorCode2)[keyof typeof ResponseErrorCode2]; 13022 13022 13023 13023 /** 13024 13024 * Emitted when an error occurs. ··· 13896 13896 */ 13897 13897 text?: { 13898 13898 format?: TextResponseFormatConfiguration; 13899 - verbosity?: Verbosity; 13899 + verbosity?: Verbosity2; 13900 13900 }; 13901 13901 /** 13902 13902 * An array of tools the model may call while generating a response. You ··· 13923 13923 * 13924 13924 */ 13925 13925 tool_choice?: 13926 - | ToolChoiceOptions 13926 + | ToolChoiceOptions2 13927 13927 | ToolChoiceAllowed 13928 13928 | ToolChoiceTypes 13929 13929 | ToolChoiceFunction ··· 14765 14765 * The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) used for execution of this run. 14766 14766 */ 14767 14767 assistant_id: string; 14768 - status: RunStatus; 14768 + status: RunStatus2; 14769 14769 /** 14770 14770 * Details on the action required to continue the run. Will be `null` if no action is required. 14771 14771 */ ··· 15190 15190 * The ranking options for the file search. 15191 15191 */ 15192 15192 export type RunStepDetailsToolCallsFileSearchRankingOptionsObject = { 15193 - ranker: FileSearchRanker; 15193 + ranker: FileSearchRanker2; 15194 15194 /** 15195 15195 * The score threshold for the file search. All values must be a floating point number between 0 and 1. 15196 15196 */ ··· 15537 15537 * When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter. 15538 15538 * 15539 15539 */ 15540 - export type ServiceTier = (typeof ServiceTier)[keyof typeof ServiceTier]; 15540 + export type ServiceTier2 = (typeof ServiceTier2)[keyof typeof ServiceTier2]; 15541 15541 15542 15542 /** 15543 15543 * Emitted for each chunk of audio data generated during speech synthesis. ··· 15933 15933 * `required` means the model must call one or more tools. 15934 15934 * 15935 15935 */ 15936 - export type ToolChoiceOptions = 15937 - (typeof ToolChoiceOptions)[keyof typeof ToolChoiceOptions]; 15936 + export type ToolChoiceOptions2 = 15937 + (typeof ToolChoiceOptions2)[keyof typeof ToolChoiceOptions2]; 15938 15938 15939 15939 /** 15940 15940 * Hosted tool ··· 16100 16100 16101 16101 export const TranscriptionInclude = { LOGPROBS: 'logprobs' } as const; 16102 16102 16103 - export type TranscriptionInclude = 16104 - (typeof TranscriptionInclude)[keyof typeof TranscriptionInclude]; 16103 + export type TranscriptionInclude2 = 16104 + (typeof TranscriptionInclude2)[keyof typeof TranscriptionInclude2]; 16105 16105 16106 16106 export type TranscriptionSegment = { 16107 16107 /** ··· 17000 17000 * Currently supported values are `low`, `medium`, and `high`. 17001 17001 * 17002 17002 */ 17003 - export type Verbosity = (typeof Verbosity)[keyof typeof Verbosity]; 17003 + export type Verbosity2 = (typeof Verbosity2)[keyof typeof Verbosity2]; 17004 17004 17005 17005 export type VoiceIdsShared = 17006 17006 | string ··· 17106 17106 * search. One of `low`, `medium`, or `high`. `medium` is the default. 17107 17107 * 17108 17108 */ 17109 - export type WebSearchContextSize = 17110 - (typeof WebSearchContextSize)[keyof typeof WebSearchContextSize]; 17109 + export type WebSearchContextSize2 = 17110 + (typeof WebSearchContextSize2)[keyof typeof WebSearchContextSize2]; 17111 17111 17112 17112 /** 17113 17113 * Web search location ··· 18269 18269 * The intended purpose of the uploaded file. One of: - `assistants`: Used in the Assistants API - `batch`: Used in the Batch API - `fine-tune`: Used for fine-tuning - `vision`: Images used for vision fine-tuning - `user_data`: Flexible file type for any purpose - `evals`: Used for eval data sets 18270 18270 * 18271 18271 */ 18272 - export type FilePurpose = (typeof FilePurpose)[keyof typeof FilePurpose]; 18272 + export type FilePurpose2 = (typeof FilePurpose2)[keyof typeof FilePurpose2]; 18273 18273 18274 18274 export type BatchError = { 18275 18275 /** ··· 18451 18451 GPT_3_5_TURBO_16K_0613: 'gpt-3.5-turbo-16k-0613', 18452 18452 } as const; 18453 18453 18454 - export type ChatModel = (typeof ChatModel)[keyof typeof ChatModel]; 18454 + export type ChatModel2 = (typeof ChatModel2)[keyof typeof ChatModel2]; 18455 18455 18456 18456 export type CreateThreadAndRunRequestWithoutStream = { 18457 18457 /** ··· 18567 18567 /** 18568 18568 * The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used. 18569 18569 */ 18570 - model?: string | AssistantSupportedModels; 18571 - reasoning_effort?: ReasoningEffort; 18570 + model?: string | AssistantSupportedModels2; 18571 + reasoning_effort?: ReasoningEffort2; 18572 18572 /** 18573 18573 * Overrides the [instructions](https://platform.openai.com/docs/api-reference/assistants/createAssistant) of the assistant. This is useful for modifying the behavior on a per-run basis. 18574 18574 */ ··· 18648 18648 /** 18649 18649 * The status of the run, which can be either `queued`, `in_progress`, `requires_action`, `cancelling`, `cancelled`, `failed`, `completed`, `incomplete`, or `expired`. 18650 18650 */ 18651 - export type RunStatus = (typeof RunStatus)[keyof typeof RunStatus]; 18651 + export type RunStatus2 = (typeof RunStatus2)[keyof typeof RunStatus2]; 18652 18652 18653 18653 /** 18654 18654 * The delta containing the fields that have changed on the run step. ··· 20419 20419 /** 20420 20420 * Return only events with a `type` in one of these values. For example, `project.created`. For all options, see the documentation for the [audit log object](https://platform.openai.com/docs/api-reference/audit-logs/object). 20421 20421 */ 20422 - 'event_types[]'?: Array<AuditLogEventType>; 20422 + 'event_types[]'?: Array<AuditLogEventType2>; 20423 20423 /** 20424 20424 * Return only events performed by these actors. Can be a user ID, a service account ID, or an api key tracking ID. 20425 20425 */ ··· 22143 22143 * parameter for Response creation above for more information. 22144 22144 * 22145 22145 */ 22146 - include?: Array<Includable>; 22146 + include?: Array<Includable2>; 22147 22147 /** 22148 22148 * If set to true, the model response data will be streamed to the client 22149 22149 * as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format). ··· 22251 22251 * parameter for Response creation above for more information. 22252 22252 * 22253 22253 */ 22254 - include?: Array<Includable>; 22254 + include?: Array<Includable2>; 22255 22255 }; 22256 22256 url: '/responses/{response_id}/input_items'; 22257 22257 };
+7 -6
packages/codegen-core/src/__tests__/bimap.test.ts
··· 8 8 // set and get 9 9 expect(bimap.set(1, 'a')).toBe(bimap); 10 10 expect(bimap.set(2, 'b')).toBe(bimap); 11 - // get, getKey 11 + // get, getKeys 12 12 expect(bimap.get(1)).toBe('a'); 13 13 expect(bimap.get(2)).toBe('b'); 14 - expect(bimap.getKey('a')).toBe(1); 15 - expect(bimap.getKey('b')).toBe(2); 14 + expect(bimap.getKeys('a')).toEqual(new Set([1])); 15 + expect(bimap.getKeys('b')).toEqual(new Set([2])); 16 16 // hasKey, hasValue 17 17 expect(bimap.hasKey(1)).toBe(true); 18 18 expect(bimap.hasKey(2)).toBe(true); ··· 52 52 // Overwrite value for existing key 53 53 bimap.set(1, 'z'); 54 54 expect(bimap.get(1)).toBe('z'); 55 - expect(bimap.getKey('z')).toBe(1); 55 + expect(bimap.getKeys('z')).toEqual(new Set([1])); 56 56 // Overwrite key for existing value 57 57 bimap.set(3, 'z'); 58 - expect(bimap.getKey('z')).toBe(3); 59 - expect(bimap.get(1)).toBeUndefined(); 58 + expect(bimap.getKeys('z')).toEqual(new Set([1, 3])); 59 + expect(bimap.get(1)).toBe('z'); 60 60 // Iteration after overwrite 61 61 expect(Array.from(bimap)).toEqual([ 62 + [1, 'z'], 62 63 [2, 'y'], 63 64 [3, 'z'], 64 65 ]);
+2
packages/codegen-core/src/__tests__/files.test.ts
··· 17 17 extension: undefined, 18 18 external: undefined, 19 19 id: expect.any(Number), 20 + localNames: new Set(), 20 21 name: 'Foo', 21 22 path: undefined, 22 23 resolvedNames: expect.any(Object), ··· 58 59 extension: undefined, 59 60 external: undefined, 60 61 id: expect.any(Number), 62 + localNames: new Set(), 61 63 name: 'Bar', 62 64 path: '/bar', 63 65 resolvedNames: expect.any(Object),
+39 -28
packages/codegen-core/src/__tests__/symbols.test.ts
··· 13 13 14 14 // Register a symbol with meta 15 15 const symbol1 = registry.register({ 16 - meta: { 17 - foo: 'bar', 18 - }, 16 + meta: { foo: 'bar' }, 17 + name: '', 19 18 placeholder: 'Foo', 20 19 }); 21 - expect(symbol1).toEqual({ 22 - id: expect.any(Number), 23 - meta: { 24 - foo: 'bar', 25 - }, 26 - placeholder: 'Foo', 27 - }); 20 + expect(symbol1).toEqual( 21 + expect.objectContaining({ 22 + _dependencies: new Set(), 23 + exportFrom: [], 24 + exported: false, 25 + id: expect.any(Number), 26 + importKind: 'named', 27 + kind: 'var', 28 + meta: { 29 + foo: 'bar', 30 + }, 31 + name: '', 32 + placeholder: 'Foo', 33 + }), 34 + ); 28 35 29 36 // get by id and meta 30 37 expect(registry.get(symbol1.id)).toEqual(symbol1); ··· 35 42 expect(registry.isRegistered({ foo: 'bar' })).toBe(true); 36 43 37 44 // Registering again with same meta creates a new symbol 38 - const symbol1b = registry.register({ meta: { foo: 'bar' } }); 45 + const symbol1b = registry.register({ 46 + meta: { foo: 'bar' }, 47 + name: '', 48 + }); 39 49 expect(symbol1b).not.toEqual(symbol1); 40 50 41 - // Registering with id overrides the symbol 42 - const symbol1c = registry.register({ id: symbol1.id }); 43 - expect(symbol1c).not.toEqual(symbol1); 44 - expect(symbol1c.id).toBe(symbol1.id); 45 - 46 51 // Reference returns same symbol 47 52 const ref1 = registry.reference({ foo: 'bar' }); 48 - expect(ref1).toEqual(symbol1c); 53 + expect(ref1).toEqual(symbol1); 49 54 50 55 // Register a new symbol with different meta 51 56 const symbol2 = registry.register({ 52 57 exportFrom: ['x'], 53 58 meta: { bar: 'baz' }, 59 + name: '', 54 60 placeholder: 'Bar', 55 61 }); 56 - expect(symbol2).toEqual({ 57 - exportFrom: ['x'], 58 - id: expect.any(Number), 59 - meta: { bar: 'baz' }, 60 - placeholder: 'Bar', 61 - }); 62 + expect(symbol2).toEqual( 63 + expect.objectContaining({ 64 + dependencies: new Set(), 65 + exportFrom: ['x'], 66 + id: expect.any(Number), 67 + meta: { bar: 'baz' }, 68 + name: '', 69 + placeholder: 'Bar', 70 + }), 71 + ); 62 72 63 73 // Registered symbols are yielded in order 64 74 const registered = Array.from(registry.registered()); ··· 79 89 expect(registry.isRegistered(symRef.id)).toBe(false); 80 90 const symRegistered = registry.register({ 81 91 meta: { qux: true }, 92 + name: '', 82 93 placeholder: 'Qux', 83 94 }); 84 95 expect(registry.isRegistered(symRegistered.id)).toBe(true); ··· 122 133 const refAD = registry.reference({ a: 0, d: 0 }); 123 134 const refAC = registry.reference({ a: 0, c: 0 }); 124 135 125 - expect(symC).toEqual(refA); 126 - expect(symC).toEqual(refAB); 127 - expect(symC).toEqual(refAC); 128 - expect(symC).not.toEqual(refAD); 129 - expect(symC).not.toEqual(refB); 136 + expect(refA.canonical).toEqual(symC); 137 + expect(refAB.canonical).toEqual(symC); 138 + expect(refAC.canonical).toEqual(symC); 139 + expect(refAD.canonical).not.toEqual(symC); 140 + expect(refB.canonical).not.toEqual(symC); 130 141 expect(symC.meta).toEqual({ a: 0, b: 0, c: 0 }); 131 142 }); 132 143
+17 -11
packages/codegen-core/src/bimap/bimap.ts
··· 2 2 3 3 export class BiMap<Key, Value> implements IBiMap<Key, Value> { 4 4 private map = new Map<Key, Value>(); 5 - private reverse = new Map<Value, Key>(); 5 + private reverse = new Map<Value, Set<Key>>(); 6 6 7 7 delete(key: Key): boolean { 8 8 const value = this.map.get(key); ··· 13 13 } 14 14 15 15 deleteValue(value: Value): boolean { 16 - const key = this.reverse.get(value); 17 - if (key !== undefined) { 18 - this.map.delete(key); 16 + const keys = this.reverse.get(value); 17 + if (keys) { 18 + for (const key of keys) { 19 + this.map.delete(key); 20 + } 19 21 } 20 22 return this.reverse.delete(value); 21 23 } ··· 28 30 return this.map.get(key); 29 31 } 30 32 31 - getKey(value: Value): Key | undefined { 33 + getKeys(value: Value): Set<Key> | undefined { 32 34 return this.reverse.get(value); 33 35 } 34 36 ··· 47 49 set(key: Key, value: Value): this { 48 50 const oldValue = this.map.get(key); 49 51 if (oldValue !== undefined && oldValue !== value) { 50 - this.reverse.delete(oldValue); 51 - } 52 - const oldKey = this.reverse.get(value); 53 - if (oldKey !== undefined && oldKey !== key) { 54 - this.map.delete(oldKey); 52 + const oldKeys = this.reverse.get(oldValue); 53 + if (oldKeys) { 54 + oldKeys.delete(key); 55 + if (oldKeys.size === 0) { 56 + this.reverse.delete(oldValue); 57 + } 58 + } 55 59 } 56 60 this.map.set(key, value); 57 - this.reverse.set(value, key); 61 + const keys = this.reverse.get(value) ?? new Set<Key>(); 62 + keys.add(key); 63 + this.reverse.set(value, keys); 58 64 return this; 59 65 } 60 66
+2 -2
packages/codegen-core/src/bimap/types.d.ts
··· 30 30 */ 31 31 get(key: Key): Value | undefined; 32 32 /** 33 - * Gets the key associated with a value. 33 + * Gets the keys associated with a value. 34 34 * 35 35 * @param value The value to look up. 36 36 */ 37 - getKey(value: Value): Key | undefined; 37 + getKeys(value: Value): Set<Key> | undefined; 38 38 /** 39 39 * Checks if a key exists in the map. 40 40 *
+5 -5
packages/codegen-core/src/bindings/utils.ts
··· 1 1 import type { IFileOut } from '../files/types'; 2 - import type { ISymbolOut } from '../symbols/types'; 2 + import type { Symbol } from '../symbols/symbol'; 3 3 import type { IBinding } from './types'; 4 4 5 5 export const createBinding = ({ ··· 10 10 }: { 11 11 file: IFileOut; 12 12 modulePath: string; 13 - symbol: ISymbolOut; 13 + symbol: Symbol; 14 14 symbolFile: IFileOut; 15 15 }): IBinding => { 16 16 const names: Array<string> = []; ··· 48 48 } 49 49 } else if (symbol.name && fileResolvedName !== symbol.name) { 50 50 name = symbol.name; 51 - binding.aliases[name] = symbol.placeholder; 51 + binding.aliases[name] = symbol.placeholder!; 52 52 } 53 53 } 54 - names.push(name); 54 + names.push(name!); 55 55 if (symbol.kind === 'type') { 56 - typeNames.push(name); 56 + typeNames.push(name!); 57 57 } 58 58 } 59 59 // cast type names to names to allow for cleaner API,
packages/codegen-core/src/extensions/types.d.ts packages/codegen-core/src/extensions.d.ts
+1
packages/codegen-core/src/files/registry.ts
··· 100 100 ...result, 101 101 ...file, // clone to avoid mutation 102 102 id, 103 + localNames: new Set(), 103 104 resolvedNames: result?.resolvedNames ?? new BiMap(), 104 105 symbols: result?.symbols ?? { 105 106 body: [],
+4
packages/codegen-core/src/files/types.d.ts
··· 53 53 */ 54 54 readonly id: number; 55 55 /** 56 + * Names declared in local (non‑top‑level) scopes within this file. 57 + */ 58 + readonly localNames: Set<string>; 59 + /** 56 60 * Map holding resolved names for symbols in this file. 57 61 */ 58 62 readonly resolvedNames: IBiMap<number, string>;
+4 -3
packages/codegen-core/src/index.ts
··· 4 4 export type { 5 5 IProjectRenderMeta as ProjectRenderMeta, 6 6 ISymbolMeta as SymbolMeta, 7 - } from './extensions/types'; 7 + } from './extensions'; 8 8 export type { 9 9 IFileOut as File, 10 10 IFileIdentifier as FileIdentifier, 11 11 IFileIn as FileIn, 12 12 } from './files/types'; 13 - export type { IOutput as Output } from './output/types'; 13 + export type { IOutput as Output } from './output'; 14 14 export { Project } from './project/project'; 15 15 export type { IProject } from './project/types'; 16 16 export type { IRenderer as Renderer } from './renderer/types'; 17 17 export { renderIds } from './renderer/utils'; 18 + export { Symbol } from './symbols/symbol'; 18 19 export type { 19 - ISymbolOut as Symbol, 20 20 ISymbolIdentifier as SymbolIdentifier, 21 21 ISymbolIn as SymbolIn, 22 22 } from './symbols/types'; 23 + export type { ISyntaxNode as SyntaxNode } from './syntax-node';
packages/codegen-core/src/output/types.d.ts packages/codegen-core/src/output.d.ts
+4 -4
packages/codegen-core/src/project/project.ts
··· 1 1 import path from 'node:path'; 2 2 3 - import type { IProjectRenderMeta } from '../extensions/types'; 3 + import type { IProjectRenderMeta } from '../extensions'; 4 4 import { FileRegistry } from '../files/registry'; 5 5 import type { IFileOut, IFileSelector } from '../files/types'; 6 - import type { IOutput } from '../output/types'; 6 + import type { IOutput } from '../output'; 7 7 import type { IRenderer } from '../renderer/types'; 8 8 import { SymbolRegistry } from '../symbols/registry'; 9 - import type { ISymbolOut } from '../symbols/types'; 9 + import type { Symbol } from '../symbols/symbol'; 10 10 import type { IProject } from './types'; 11 11 12 12 const externalSourceSymbol = '@'; ··· 133 133 return Array.from(fileIds ?? []).map((fileId) => this.files.get(fileId)!); 134 134 } 135 135 136 - private symbolToFileSelector(symbol: ISymbolOut): IFileSelector { 136 + private symbolToFileSelector(symbol: Symbol): IFileSelector { 137 137 if (symbol.external) { 138 138 return [externalSourceSymbol, symbol.external]; 139 139 }
+2 -2
packages/codegen-core/src/project/types.d.ts
··· 1 - import type { IProjectRenderMeta } from '../extensions/types'; 1 + import type { IProjectRenderMeta } from '../extensions'; 2 2 import type { IFileOut, IFileRegistry } from '../files/types'; 3 - import type { IOutput } from '../output/types'; 3 + import type { IOutput } from '../output'; 4 4 import type { IRenderer } from '../renderer/types'; 5 5 import type { ISymbolRegistry } from '../symbols/types'; 6 6
+1 -1
packages/codegen-core/src/renderer/types.d.ts
··· 1 - import type { IProjectRenderMeta } from '../extensions/types'; 1 + import type { IProjectRenderMeta } from '../extensions'; 2 2 import type { IFileOut } from '../files/types'; 3 3 import type { IProject } from '../project/types'; 4 4
+18 -28
packages/codegen-core/src/symbols/registry.ts
··· 1 - import type { ISymbolMeta } from '../extensions/types'; 2 - import { wrapId } from '../renderer/utils'; 3 - import type { 4 - ISymbolIdentifier, 5 - ISymbolIn, 6 - ISymbolOut, 7 - ISymbolRegistry, 8 - } from './types'; 1 + import type { ISymbolMeta } from '../extensions'; 2 + import { Symbol } from './symbol'; 3 + import type { ISymbolIdentifier, ISymbolIn, ISymbolRegistry } from './types'; 9 4 10 5 type IndexEntry = [string, unknown]; 11 6 type IndexKeySpace = ReadonlyArray<IndexEntry>; ··· 23 18 private registerOrder: Set<SymbolId> = new Set(); 24 19 private stubCache: Map<QueryCacheKey, SymbolId> = new Map(); 25 20 private stubs: Set<SymbolId> = new Set(); 26 - private values: Map<SymbolId, ISymbolOut> = new Map(); 21 + private values: Map<SymbolId, Symbol> = new Map(); 27 22 28 - get(identifier: ISymbolIdentifier): ISymbolOut | undefined { 23 + get(identifier: ISymbolIdentifier): Symbol | undefined { 29 24 return typeof identifier === 'number' 30 25 ? this.values.get(identifier) 31 26 : this.query(identifier)[0]; ··· 48 43 return symbol ? this.registerOrder.has(symbol.id) : false; 49 44 } 50 45 51 - query(filter: ISymbolMeta): ReadonlyArray<ISymbolOut> { 46 + query(filter: ISymbolMeta): ReadonlyArray<Symbol> { 52 47 const cacheKey = this.buildCacheKey(filter); 53 48 const cachedIds = this.queryCache.get(cacheKey); 54 49 if (cachedIds) { ··· 87 82 return resultIds.map((symbolId) => this.values.get(symbolId)!); 88 83 } 89 84 90 - reference(meta: ISymbolMeta): ISymbolOut { 85 + reference(meta: ISymbolMeta): Symbol { 91 86 const [registered] = this.query(meta); 92 87 if (registered) return registered; 88 + 93 89 const cacheKey = this.buildCacheKey(meta); 94 90 const cachedId = this.stubCache.get(cacheKey); 95 91 if (cachedId !== undefined) return this.values.get(cachedId)!; 96 - const id = this.id; 97 - const stub: ISymbolOut = { 98 - id, 99 - meta, 100 - placeholder: wrapId(String(id)), 101 - }; 92 + 93 + const stub = new Symbol({ meta, name: '' }, this.id); 94 + 102 95 this.values.set(stub.id, stub); 103 96 this.stubs.add(stub.id); 104 97 this.stubCache.set(cacheKey, stub.id); 105 98 return stub; 106 99 } 107 100 108 - register(symbol: ISymbolIn): ISymbolOut { 109 - const id = symbol.id !== undefined ? symbol.id : this.id; 110 - const result: ISymbolOut = { 111 - ...symbol, // clone to avoid mutation 112 - id, 113 - placeholder: symbol.placeholder ?? wrapId(String(id)), 114 - }; 101 + register(symbol: ISymbolIn): Symbol { 102 + const result = new Symbol(symbol, this.id); 103 + 115 104 this.values.set(result.id, result); 116 105 this.registerOrder.add(result.id); 106 + 117 107 if (result.meta) { 118 108 const indexKeySpace = this.buildIndexKeySpace(result.meta); 119 109 this.indexSymbol(result.id, indexKeySpace); ··· 123 113 return result; 124 114 } 125 115 126 - *registered(): IterableIterator<ISymbolOut> { 116 + *registered(): IterableIterator<Symbol> { 127 117 for (const id of this.registerOrder.values()) { 128 118 yield this.values.get(id)!; 129 119 } ··· 192 182 return true; 193 183 } 194 184 195 - private replaceStubs(symbol: ISymbolOut, indexKeySpace: IndexKeySpace): void { 185 + private replaceStubs(symbol: Symbol, indexKeySpace: IndexKeySpace): void { 196 186 for (const stubId of this.stubs.values()) { 197 187 const stub = this.values.get(stubId); 198 188 if ( ··· 201 191 ) { 202 192 const cacheKey = this.buildCacheKey(stub.meta); 203 193 this.stubCache.delete(cacheKey); 204 - this.values.set(stubId, Object.assign(stub, symbol)); 205 194 this.stubs.delete(stubId); 195 + stub.setCanonical(symbol); 206 196 } 207 197 } 208 198 }
+316
packages/codegen-core/src/symbols/symbol.ts
··· 1 + import type { ISymbolMeta } from '../extensions'; 2 + import type { IFileOut } from '../files/types'; 3 + import { wrapId } from '../renderer/utils'; 4 + import type { ISyntaxNode } from '../syntax-node'; 5 + import type { ISymbolIn, SymbolImportKind, SymbolKind } from './types'; 6 + 7 + export class Symbol { 8 + /** 9 + * Canonical symbol this stub resolves to, if any. 10 + * 11 + * Stubs created during DSL construction may later be associated 12 + * with a fully registered symbol. Once set, all property lookups 13 + * should defer to the canonical symbol. 14 + * 15 + * @private 16 + */ 17 + private _canonical?: Symbol; 18 + /** 19 + * Private set of direct symbol dependencies. 20 + * 21 + * @private 22 + */ 23 + private readonly _dependencies = new Set<Symbol>(); 24 + /** 25 + * True if this symbol is exported from its defining file. 26 + * 27 + * @default false 28 + */ 29 + private _exported: boolean; 30 + /** 31 + * Names of files (without extension) from which this symbol is re-exported. 32 + * 33 + * @default [] 34 + */ 35 + private _exportFrom: ReadonlyArray<string>; 36 + /** 37 + * External module name if this symbol is imported from a module not managed 38 + * by the project (e.g. "zod", "lodash"). 39 + * 40 + * @default undefined 41 + */ 42 + private _external?: string; 43 + /** 44 + * The file this symbol is ultimately emitted into. 45 + * 46 + * @private 47 + */ 48 + private _file?: IFileOut; 49 + /** 50 + * The alias-resolved, conflict-free emitted name. 51 + * 52 + * @private 53 + */ 54 + private _finalName?: string; 55 + /** 56 + * Custom strategy to determine file output path. 57 + * 58 + * @returns The file path to output the symbol to, or undefined to fallback to default behavior. 59 + */ 60 + private _getFilePath?: (symbol: Symbol) => string | undefined; 61 + /** 62 + * How this symbol should be imported (namespace/default/named). 63 + * 64 + * @default 'named' 65 + */ 66 + private _importKind: SymbolImportKind; 67 + /** 68 + * Kind of symbol (class, type, alias, etc.). 69 + * 70 + * @default 'var' 71 + */ 72 + private _kind: SymbolKind; 73 + /** 74 + * Arbitrary user metadata. 75 + * 76 + * @default undefined 77 + */ 78 + private _meta?: ISymbolMeta; 79 + /** 80 + * Intended user-facing name before conflict resolution. 81 + * 82 + * @example "UserModel" 83 + */ 84 + private _name: string; 85 + /** 86 + * Root DSL node that defines this symbol. 87 + * 88 + * @private 89 + */ 90 + private _rootNode?: ISyntaxNode; 91 + 92 + /** 93 + * Globally unique, stable symbol ID. 94 + */ 95 + readonly id: number; 96 + /** 97 + * Placeholder name for the symbol to be replaced later with the final value. 98 + * 99 + * @deprecated 100 + * @example "_heyapi_31_" 101 + */ 102 + readonly placeholder: string; 103 + 104 + constructor(input: ISymbolIn, id: number) { 105 + this._exported = input.exported ?? false; 106 + this._exportFrom = input.exportFrom ?? []; 107 + this._external = input.external; 108 + this._getFilePath = input.getFilePath; 109 + this.id = id; 110 + this._importKind = input.importKind ?? 'named'; 111 + this._kind = input.kind ?? 'var'; 112 + this._meta = input.meta; 113 + this._name = input.name; 114 + this.placeholder = input.placeholder || wrapId(String(id)); 115 + } 116 + 117 + /** 118 + * Returns the canonical symbol for this instance. 119 + * 120 + * If this symbol was created as a stub, this getter returns 121 + * the fully registered canonical symbol. Otherwise, it returns 122 + * the symbol itself. 123 + */ 124 + get canonical(): Symbol { 125 + return this._canonical ?? this; 126 + } 127 + 128 + /** 129 + * Read-only access to dependencies. 130 + */ 131 + get dependencies(): ReadonlySet<Symbol> { 132 + return this.canonical._dependencies; 133 + } 134 + 135 + /** 136 + * Indicates whether this symbol is exported from its defining file. 137 + */ 138 + get exported(): boolean { 139 + return this.canonical._exported; 140 + } 141 + 142 + /** 143 + * Names of files (without extension) that re-export this symbol. 144 + */ 145 + get exportFrom(): ReadonlyArray<string> { 146 + return this.canonical._exportFrom; 147 + } 148 + 149 + /** 150 + * External module from which this symbol originates, if any. 151 + */ 152 + get external(): string | undefined { 153 + return this.canonical._external; 154 + } 155 + 156 + /** 157 + * Read‑only accessor for the assigned output file. 158 + */ 159 + get file(): IFileOut | undefined { 160 + return this.canonical._file; 161 + } 162 + 163 + /** 164 + * Read‑only accessor for the resolved final emitted name. 165 + */ 166 + get finalName(): string { 167 + return ( 168 + this.canonical._finalName || 169 + this.canonical.placeholder || 170 + this.canonical.name 171 + ); 172 + } 173 + 174 + get getFilePath(): ((symbol: Symbol) => string | undefined) | undefined { 175 + return this.canonical._getFilePath; 176 + } 177 + 178 + /** 179 + * How this symbol should be imported (named/default/namespace). 180 + */ 181 + get importKind(): SymbolImportKind { 182 + return this.canonical._importKind; 183 + } 184 + 185 + /** 186 + * The symbol's kind (class, type, alias, variable, etc.). 187 + */ 188 + get kind(): SymbolKind { 189 + return this.canonical._kind; 190 + } 191 + 192 + /** 193 + * Arbitrary user‑provided metadata associated with this symbol. 194 + */ 195 + get meta(): ISymbolMeta | undefined { 196 + return this.canonical._meta; 197 + } 198 + 199 + get name(): string { 200 + return this.canonical._name; 201 + } 202 + 203 + /** 204 + * Read‑only accessor for the defining DSL root node. 205 + */ 206 + get rootNode(): ISyntaxNode | undefined { 207 + return this.canonical._rootNode; 208 + } 209 + 210 + /** 211 + * Add a direct dependency on another symbol. 212 + */ 213 + addDependency(symbol: Symbol): void { 214 + if (symbol !== this) this._dependencies.add(symbol); 215 + } 216 + 217 + /** 218 + * Marks this symbol as a stub and assigns its canonical symbol. 219 + * 220 + * After calling this, all semantic queries (name, kind, file, 221 + * meta, etc.) should reflect the canonical symbol's values. 222 + * 223 + * @param symbol — The canonical symbol this stub should resolve to. 224 + */ 225 + setCanonical(symbol: Symbol): void { 226 + this._canonical = symbol; 227 + } 228 + 229 + /** 230 + * Marks the symbol as exported from its file. 231 + * 232 + * @param exported — Whether the symbol is exported. 233 + */ 234 + setExported(exported: boolean): void { 235 + this._exported = exported; 236 + } 237 + 238 + /** 239 + * Records file names that re‑export this symbol. 240 + * 241 + * @param list — Source files re‑exporting this symbol. 242 + */ 243 + setExportFrom(list: ReadonlyArray<string>): void { 244 + this._exportFrom = list; 245 + } 246 + 247 + /** 248 + * Assigns the output file this symbol will be emitted into. 249 + * 250 + * This may only be set once. 251 + */ 252 + setFile(file: IFileOut): void { 253 + if (this._file && this._file !== file) { 254 + throw new Error('Symbol is already assigned to a different file.'); 255 + } 256 + this._file = file; 257 + } 258 + 259 + /** 260 + * Assigns the conflict‑resolved final local name for this symbol. 261 + * 262 + * This may only be set once. 263 + */ 264 + setFinalName(name: string): void { 265 + if (this._finalName && this._finalName !== name) { 266 + throw new Error('Symbol finalName has already been resolved.'); 267 + } 268 + this._finalName = name; 269 + } 270 + 271 + /** 272 + * Sets how this symbol should be imported. 273 + * 274 + * @param kind — The import strategy (named/default/namespace). 275 + */ 276 + setImportKind(kind: SymbolImportKind): void { 277 + this._importKind = kind; 278 + } 279 + 280 + /** 281 + * Sets the symbol's kind (class, type, alias, variable, etc.). 282 + * 283 + * @param kind — The new symbol kind. 284 + */ 285 + setKind(kind: SymbolKind): void { 286 + this._kind = kind; 287 + } 288 + 289 + /** 290 + * Updates the intended user‑facing name for this symbol. 291 + * 292 + * @param name — The new name. 293 + */ 294 + setName(name: string): void { 295 + this._name = name; 296 + } 297 + 298 + /** 299 + * Binds the DSL node that defines this symbol. 300 + * 301 + * This may only be set once. 302 + */ 303 + setRootNode(node: ISyntaxNode): void { 304 + if (this._rootNode && this._rootNode !== node) { 305 + throw new Error('Symbol is already bound to a different root DSL node.'); 306 + } 307 + this._rootNode = node; 308 + } 309 + 310 + /** 311 + * Returns a debug‑friendly string representation identifying the symbol. 312 + */ 313 + toString(): string { 314 + return `[Symbol ${this.name}#${this.id}]`; 315 + } 316 + }
+27 -19
packages/codegen-core/src/symbols/types.d.ts
··· 1 - import type { ISymbolMeta } from '../extensions/types'; 1 + import type { ISymbolMeta } from '../extensions'; 2 + import type { Symbol } from './symbol'; 2 3 3 4 export type ISymbolIdentifier = number | ISymbolMeta; 5 + 6 + export type SymbolImportKind = 'namespace' | 'default' | 'named'; 7 + 8 + export type SymbolKind = 9 + | 'alias' // export { a as a2 } from 'a'; 10 + | 'class' 11 + | 'enum' 12 + | 'function' 13 + | 'interface' 14 + | 'namespace' 15 + | 'type' 16 + | 'var'; 4 17 5 18 export type ISymbolIn = { 6 19 /** ··· 27 40 * 28 41 * @returns The file path to output the symbol to, or undefined to fallback to default behavior. 29 42 */ 30 - getFilePath?: (symbol: ISymbolOut) => string | undefined; 31 - /** 32 - * Unique symbol ID. If one is not provided, it will be auto-generated. 33 - */ 34 - readonly id?: number; 43 + getFilePath?: Symbol['getFilePath']; 35 44 /** 36 45 * Kind of import if this symbol represents an import. 37 46 */ 38 - importKind?: 'namespace' | 'default' | 'named'; 47 + importKind?: SymbolImportKind; 39 48 /** 40 49 * Kind of symbol. 41 50 */ 42 - kind?: 'class' | 'function' | 'type'; 51 + kind?: SymbolKind; 43 52 /** 44 53 * Arbitrary metadata about the symbol. 45 54 * ··· 47 56 */ 48 57 meta?: ISymbolMeta; 49 58 /** 50 - * The desired name for the symbol within its file. If there are multiple symbols 51 - * with the same desired name, this might not end up being the actual name. 59 + * The intended, user-facing name of the symbol before any conflict resolution. 60 + * It is **not** guaranteed to be the final emitted name — aliasing may occur if the 61 + * file contains conflicting local identifiers or other symbols with the same intended name. 52 62 * 53 63 * @example "UserModel" 54 64 */ 55 - name?: string; 65 + name: string; 56 66 /** 57 67 * Placeholder name for the symbol to be replaced later with the final value. 58 68 * 69 + * @deprecated 59 70 * @example "_heyapi_31_" 60 71 */ 61 72 readonly placeholder?: string; 62 73 }; 63 74 64 - export type ISymbolOut = Omit<ISymbolIn, 'id' | 'placeholder'> & 65 - Pick<Required<ISymbolIn>, 'id' | 'placeholder'>; 66 - 67 75 export interface ISymbolRegistry { 68 76 /** 69 77 * Get a symbol. ··· 71 79 * @param identifier Symbol identifier to reference. 72 80 * @returns The symbol, or undefined if not found. 73 81 */ 74 - get(identifier: ISymbolIdentifier): ISymbolOut | undefined; 82 + get(identifier: ISymbolIdentifier): Symbol | undefined; 75 83 /** 76 84 * Returns the value associated with a symbol ID. 77 85 * ··· 105 113 * @param filter Metadata filter to query symbols by. 106 114 * @returns Array of symbols matching the filter. 107 115 */ 108 - query(filter: ISymbolMeta): ReadonlyArray<ISymbolOut>; 116 + query(filter: ISymbolMeta): ReadonlyArray<Symbol>; 109 117 /** 110 118 * References a symbol. 111 119 * 112 120 * @param meta Metadata filter to reference symbol by. 113 121 * @returns The referenced symbol. 114 122 */ 115 - reference(meta: ISymbolMeta): ISymbolOut; 123 + reference(meta: ISymbolMeta): Symbol; 116 124 /** 117 125 * Register a symbol globally. 118 126 * ··· 121 129 * @param symbol Symbol to register. 122 130 * @returns The registered symbol. 123 131 */ 124 - register(symbol: ISymbolIn): ISymbolOut; 132 + register(symbol: ISymbolIn): Symbol; 125 133 /** 126 134 * Get all symbols in the order they were registered. 127 135 * 128 136 * @returns Array of all registered symbols, in insert order. 129 137 */ 130 - registered(): IterableIterator<ISymbolOut>; 138 + registered(): IterableIterator<Symbol>; 131 139 /** 132 140 * Sets a value for a symbol by its ID. 133 141 *
+20
packages/codegen-core/src/syntax-node.d.ts
··· 1 + import type { Symbol } from './symbols/symbol'; 2 + 3 + export interface ISyntaxNode { 4 + /** 5 + * Return local names introduced by this node. 6 + */ 7 + getLocalNames(): Iterable<string>; 8 + /** 9 + * Return symbols referenced directly by this node. 10 + */ 11 + getSymbols(): Iterable<Symbol>; 12 + /** 13 + * Rewrite local identifiers based on a rename map. 14 + */ 15 + rewriteIdentifiers(map: Map<string, string>): void; 16 + /** 17 + * Walk this node and its children with a visitor. 18 + */ 19 + traverse(visitor: (node: ISyntaxNode) => void): void; 20 + }
+2
packages/codegen-core/tsconfig.base.json
··· 1 1 { 2 2 "compilerOptions": { 3 + "composite": true, 3 4 "declaration": true, 5 + "declarationMap": true, 4 6 "esModuleInterop": true, 5 7 "module": "ESNext", 6 8 "moduleResolution": "Bundler",
-1
packages/codegen-core/tsconfig.json
··· 1 1 { 2 2 "extends": "./tsconfig.base.json", 3 3 "compilerOptions": { 4 - "declaration": false, 5 4 "esModuleInterop": true, 6 5 "resolveJsonModule": true, 7 6 "skipLibCheck": true
+1 -1
packages/openapi-ts-tests/main/test/__snapshots__/2.0.x/plugins/valibot/default/valibot.gen.ts
··· 267 267 * This is a model with one property containing a circular reference 268 268 */ 269 269 export const vModelWithCircularReference: v.GenericSchema = v.object({ 270 - prop: v.optional(v.lazy(() => vModelWithCircularReference)) 270 + prop: v.optional(v.lazy(() => vModelWithCircularReference2)) 271 271 }); 272 272 273 273 /**
+1 -1
packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/plugins/valibot/default/valibot.gen.ts
··· 343 343 * This is a model with one property containing a circular reference 344 344 */ 345 345 export const vModelWithCircularReference: v.GenericSchema = v.object({ 346 - prop: v.optional(v.lazy(() => vModelWithCircularReference)) 346 + prop: v.optional(v.lazy(() => vModelWithCircularReference2)) 347 347 }); 348 348 349 349 /**
+2 -2
packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/validators/valibot.gen.ts
··· 6 6 7 7 export const vFoo: v.GenericSchema = v.optional(v.union([v.object({ 8 8 foo: v.optional(v.pipe(v.string(), v.regex(/^\d{3}-\d{2}-\d{4}$/))), 9 - bar: v.optional(v.lazy(() => vBar)), 10 - baz: v.optional(v.array(v.lazy(() => vFoo))), 9 + bar: v.optional(v.lazy(() => vBar2)), 10 + baz: v.optional(v.array(v.lazy(() => vFoo2))), 11 11 qux: v.optional(v.pipe(v.number(), v.integer(), v.gtValue(0)), 0) 12 12 }), v.null()]), null); 13 13
+1 -1
packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/plugins/valibot/default/valibot.gen.ts
··· 343 343 * This is a model with one property containing a circular reference 344 344 */ 345 345 export const vModelWithCircularReference: v.GenericSchema = v.object({ 346 - prop: v.optional(v.lazy(() => vModelWithCircularReference)) 346 + prop: v.optional(v.lazy(() => vModelWithCircularReference2)) 347 347 }); 348 348 349 349 /**
+1 -1
packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/validators-circular-ref-2/valibot.gen.ts
··· 3 3 import * as v from 'valibot'; 4 4 5 5 export const vBar: v.GenericSchema = v.strictObject({ 6 - bar: v.union([v.array(v.lazy(() => vBar)), v.null()]) 6 + bar: v.union([v.array(v.lazy(() => vBar2)), v.null()]) 7 7 }); 8 8 9 9 export const vFoo = v.strictObject({
+2 -2
packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/validators-circular-ref/valibot.gen.ts
··· 3 3 import * as v from 'valibot'; 4 4 5 5 export const vBar: v.GenericSchema = v.object({ 6 - bar: v.optional(v.array(v.lazy(() => vBar))) 6 + bar: v.optional(v.array(v.lazy(() => vBar2))) 7 7 }); 8 8 9 9 export const vFoo = v.object({ 10 10 foo: v.optional(vBar) 11 11 }); 12 12 13 - export const vBaz: v.GenericSchema = v.lazy(() => vQux); 13 + export const vBaz: v.GenericSchema = v.lazy(() => vQux2); 14 14 15 15 /** 16 16 * description caused circular reference error
+2 -2
packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/validators-metadata/valibot.gen.ts
··· 13 13 */ 14 14 export const vFoo: v.GenericSchema = v.optional(v.union([v.object({ 15 15 foo: v.optional(v.pipe(v.pipe(v.string(), v.regex(/^\d{3}-\d{2}-\d{4}$/)), v.metadata({ description: 'This is foo property.' }))), 16 - bar: v.optional(v.lazy(() => vBar)), 17 - baz: v.optional(v.pipe(v.array(v.lazy(() => vFoo)), v.metadata({ description: 'This is baz property.' }))), 16 + bar: v.optional(v.lazy(() => vBar2)), 17 + baz: v.optional(v.pipe(v.array(v.lazy(() => vFoo4)), v.metadata({ description: 'This is baz property.' }))), 18 18 qux: v.optional(v.pipe(v.pipe(v.number(), v.integer(), v.gtValue(0)), v.metadata({ description: 'This is qux property.' })), 0) 19 19 }), v.null()]), null); 20 20
+2 -2
packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/validators-types/valibot.gen.ts
··· 13 13 */ 14 14 export const vFoo: v.GenericSchema = v.optional(v.union([v.object({ 15 15 foo: v.optional(v.pipe(v.string(), v.regex(/^\d{3}-\d{2}-\d{4}$/))), 16 - bar: v.optional(v.lazy(() => vBar)), 17 - baz: v.optional(v.array(v.lazy(() => vFoo))), 16 + bar: v.optional(v.lazy(() => vBar2)), 17 + baz: v.optional(v.array(v.lazy(() => vFoo4))), 18 18 qux: v.optional(v.pipe(v.number(), v.integer(), v.gtValue(0)), 0) 19 19 }), v.null()]), null); 20 20
+2 -2
packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/validators/valibot.gen.ts
··· 13 13 */ 14 14 export const vFoo: v.GenericSchema = v.optional(v.union([v.object({ 15 15 foo: v.optional(v.pipe(v.string(), v.regex(/^\d{3}-\d{2}-\d{4}$/))), 16 - bar: v.optional(v.lazy(() => vBar)), 17 - baz: v.optional(v.array(v.lazy(() => vFoo))), 16 + bar: v.optional(v.lazy(() => vBar2)), 17 + baz: v.optional(v.array(v.lazy(() => vFoo4))), 18 18 qux: v.optional(v.pipe(v.number(), v.integer(), v.gtValue(0)), 0) 19 19 }), v.null()]), null); 20 20
+19 -19
packages/openapi-ts-tests/sdks/__snapshots__/method-class-conflict/class/sdk.gen.ts
··· 39 39 } 40 40 41 41 public static get api() { 42 - return Api; 42 + return Api2; 43 43 } 44 44 } 45 45 ··· 64 64 } 65 65 66 66 public static get api() { 67 - return Api; 67 + return Api2; 68 68 } 69 69 } 70 70 ··· 89 89 } 90 90 91 91 public static get api() { 92 - return Api; 92 + return Api2; 93 93 } 94 94 } 95 95 ··· 159 159 } 160 160 161 161 public static get api() { 162 - return Api; 162 + return Api2; 163 163 } 164 164 } 165 165 ··· 172 172 } 173 173 174 174 public static get api() { 175 - return Api; 175 + return Api2; 176 176 } 177 177 } 178 178 ··· 231 231 } 232 232 233 233 public static get api() { 234 - return Api; 234 + return Api2; 235 235 } 236 236 } 237 237 ··· 241 241 } 242 242 243 243 public static get api() { 244 - return Api; 244 + return Api2; 245 245 } 246 246 } 247 247 ··· 277 277 } 278 278 279 279 public static get api() { 280 - return Api; 280 + return Api2; 281 281 } 282 282 } 283 283 ··· 302 302 } 303 303 304 304 public static get api() { 305 - return Api; 305 + return Api2; 306 306 } 307 307 } 308 308 ··· 312 312 } 313 313 314 314 public static get api() { 315 - return Api; 315 + return Api2; 316 316 } 317 317 } 318 318 ··· 363 363 } 364 364 365 365 public static get api() { 366 - return Api; 366 + return Api2; 367 367 } 368 368 } 369 369 ··· 418 418 } 419 419 420 420 public static get api() { 421 - return Api; 421 + return Api2; 422 422 } 423 423 } 424 424 ··· 439 439 } 440 440 441 441 public static get api() { 442 - return Api; 442 + return Api2; 443 443 } 444 444 } 445 445 ··· 449 449 } 450 450 451 451 public static get api() { 452 - return Api; 452 + return Api2; 453 453 } 454 454 } 455 455 ··· 494 494 } 495 495 496 496 public static get api() { 497 - return Api; 497 + return Api2; 498 498 } 499 499 } 500 500 ··· 530 530 } 531 531 532 532 public static get api() { 533 - return Api; 533 + return Api2; 534 534 } 535 535 } 536 536 ··· 600 600 } 601 601 602 602 public static get api() { 603 - return Api; 603 + return Api2; 604 604 } 605 605 } 606 606 ··· 693 693 } 694 694 695 695 public static get accountingCompanies2() { 696 - return AccountingCompanies; 696 + return AccountingCompanies2; 697 697 } 698 698 699 699 static accountingCompanyMemberships2 = AccountingCompanyMemberships; ··· 735 735 736 736 export class MapIdentityApi { 737 737 public static get api() { 738 - return Api; 738 + return Api2; 739 739 } 740 740 } 741 741
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/2.0.x/mini/default/zod.gen.ts
··· 294 294 */ 295 295 export const zModelWithCircularReference = z.object({ 296 296 get prop() { 297 - return z.optional(z.lazy((): any => zModelWithCircularReference)); 297 + return z.optional(z.lazy((): any => zModelWithCircularReference2)); 298 298 } 299 299 }); 300 300
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/2.0.x/v3/default/zod.gen.ts
··· 293 293 * This is a model with one property containing a circular reference 294 294 */ 295 295 export const zModelWithCircularReference: z.AnyZodObject = z.object({ 296 - prop: z.lazy(() => zModelWithCircularReference).optional() 296 + prop: z.lazy(() => zModelWithCircularReference2).optional() 297 297 }); 298 298 299 299 /**
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/2.0.x/v4/default/zod.gen.ts
··· 294 294 */ 295 295 export const zModelWithCircularReference = z.object({ 296 296 get prop() { 297 - return z.optional(z.lazy((): any => zModelWithCircularReference)); 297 + return z.optional(z.lazy((): any => zModelWithCircularReference2)); 298 298 } 299 299 }); 300 300
+5 -5
packages/openapi-ts-tests/zod/v3/__snapshots__/3.0.x/mini/circular/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 get quux() { 7 - return z.optional(z.lazy((): any => zQuux)); 7 + return z.optional(z.lazy((): any => zQuux2)); 8 8 } 9 9 }); 10 10 11 11 export const zBar = z.object({ 12 12 get bar() { 13 - return z.optional(z.lazy((): any => zBar)); 13 + return z.optional(z.lazy((): any => zBar2)); 14 14 }, 15 15 get baz() { 16 - return z.optional(z.lazy((): any => zBaz)); 16 + return z.optional(z.lazy((): any => zBaz2)); 17 17 } 18 18 }); 19 19 20 20 export const zBaz = z.object({ 21 21 get quux() { 22 - return z.optional(z.lazy((): any => zQuux)); 22 + return z.optional(z.lazy((): any => zQuux2)); 23 23 } 24 24 }); 25 25 26 26 export const zQux = z.union([ 27 27 z.intersection(z.object({ 28 28 type: z.literal('struct') 29 - }), z.lazy(() => z.lazy((): any => zCorge))), 29 + }), z.lazy(() => z.lazy((): any => zCorge2))), 30 30 z.intersection(z.object({ 31 31 type: z.literal('array') 32 32 }), zFoo)
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/3.0.x/mini/default/zod.gen.ts
··· 392 392 */ 393 393 export const zModelWithCircularReference = z.object({ 394 394 get prop() { 395 - return z.optional(z.lazy((): any => zModelWithCircularReference)); 395 + return z.optional(z.lazy((): any => zModelWithCircularReference2)); 396 396 } 397 397 }); 398 398
+2 -2
packages/openapi-ts-tests/zod/v3/__snapshots__/3.0.x/mini/validators/zod.gen.ts
··· 8 8 z.object({ 9 9 foo: z.optional(z.string().check(z.regex(/^\d{3}-\d{2}-\d{4}$/))), 10 10 get bar() { 11 - return z.optional(z.lazy((): any => zBar)); 11 + return z.optional(z.lazy((): any => zBar2)); 12 12 }, 13 13 get baz() { 14 - return z.optional(z.array(z.lazy((): any => zFoo))); 14 + return z.optional(z.array(z.lazy((): any => zFoo2))); 15 15 }, 16 16 qux: z._default(z.optional(z.int().check(z.gt(0))), 0) 17 17 }),
+5 -5
packages/openapi-ts-tests/zod/v3/__snapshots__/3.0.x/v3/circular/zod.gen.ts
··· 3 3 import { z } from 'zod'; 4 4 5 5 export const zFoo: z.AnyZodObject = z.object({ 6 - quux: z.lazy(() => zQuux).optional() 6 + quux: z.lazy(() => zQuux2).optional() 7 7 }); 8 8 9 9 export const zBar: z.AnyZodObject = z.object({ 10 - bar: z.lazy(() => zBar).optional(), 11 - baz: z.lazy(() => zBaz).optional() 10 + bar: z.lazy(() => zBar2).optional(), 11 + baz: z.lazy(() => zBaz2).optional() 12 12 }); 13 13 14 14 export const zBaz: z.AnyZodObject = z.object({ 15 - quux: z.lazy(() => zQuux).optional() 15 + quux: z.lazy(() => zQuux2).optional() 16 16 }); 17 17 18 18 export const zQux: z.ZodTypeAny = z.union([ 19 19 z.object({ 20 20 type: z.literal('struct') 21 - }).and(z.lazy(() => zCorge)), 21 + }).and(z.lazy(() => zCorge2)), 22 22 z.object({ 23 23 type: z.literal('array') 24 24 }).and(zFoo)
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/3.0.x/v3/default/zod.gen.ts
··· 391 391 * This is a model with one property containing a circular reference 392 392 */ 393 393 export const zModelWithCircularReference: z.AnyZodObject = z.object({ 394 - prop: z.lazy(() => zModelWithCircularReference).optional() 394 + prop: z.lazy(() => zModelWithCircularReference2).optional() 395 395 }); 396 396 397 397 /**
+2 -2
packages/openapi-ts-tests/zod/v3/__snapshots__/3.0.x/v3/validators/zod.gen.ts
··· 7 7 export const zFoo: z.ZodTypeAny = z.union([ 8 8 z.object({ 9 9 foo: z.string().regex(/^\d{3}-\d{2}-\d{4}$/).optional(), 10 - bar: z.lazy(() => zBar).optional(), 11 - baz: z.array(z.lazy(() => zFoo)).optional(), 10 + bar: z.lazy(() => zBar2).optional(), 11 + baz: z.array(z.lazy(() => zFoo2)).optional(), 12 12 qux: z.number().int().gt(0).optional().default(0) 13 13 }), 14 14 z.null()
+5 -5
packages/openapi-ts-tests/zod/v3/__snapshots__/3.0.x/v4/circular/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 get quux() { 7 - return z.optional(z.lazy((): any => zQuux)); 7 + return z.optional(z.lazy((): any => zQuux2)); 8 8 } 9 9 }); 10 10 11 11 export const zBar = z.object({ 12 12 get bar() { 13 - return z.optional(z.lazy((): any => zBar)); 13 + return z.optional(z.lazy((): any => zBar2)); 14 14 }, 15 15 get baz() { 16 - return z.optional(z.lazy((): any => zBaz)); 16 + return z.optional(z.lazy((): any => zBaz2)); 17 17 } 18 18 }); 19 19 20 20 export const zBaz = z.object({ 21 21 get quux() { 22 - return z.optional(z.lazy((): any => zQuux)); 22 + return z.optional(z.lazy((): any => zQuux2)); 23 23 } 24 24 }); 25 25 26 26 export const zQux = z.union([ 27 27 z.object({ 28 28 type: z.literal('struct') 29 - }).and(z.lazy(() => z.lazy((): any => zCorge))), 29 + }).and(z.lazy(() => z.lazy((): any => zCorge2))), 30 30 z.object({ 31 31 type: z.literal('array') 32 32 }).and(zFoo)
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/3.0.x/v4/default/zod.gen.ts
··· 392 392 */ 393 393 export const zModelWithCircularReference = z.object({ 394 394 get prop() { 395 - return z.optional(z.lazy((): any => zModelWithCircularReference)); 395 + return z.optional(z.lazy((): any => zModelWithCircularReference2)); 396 396 } 397 397 }); 398 398
+2 -2
packages/openapi-ts-tests/zod/v3/__snapshots__/3.0.x/v4/validators/zod.gen.ts
··· 8 8 z.object({ 9 9 foo: z.optional(z.string().regex(/^\d{3}-\d{2}-\d{4}$/)), 10 10 get bar() { 11 - return z.optional(z.lazy((): any => zBar)); 11 + return z.optional(z.lazy((): any => zBar2)); 12 12 }, 13 13 get baz() { 14 - return z.optional(z.array(z.lazy((): any => zFoo))); 14 + return z.optional(z.array(z.lazy((): any => zFoo2))); 15 15 }, 16 16 qux: z.optional(z.int().gt(0)).default(0) 17 17 }),
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/mini/default/zod.gen.ts
··· 395 395 */ 396 396 export const zModelWithCircularReference = z.object({ 397 397 get prop() { 398 - return z.optional(z.lazy((): any => zModelWithCircularReference)); 398 + return z.optional(z.lazy((): any => zModelWithCircularReference2)); 399 399 } 400 400 }); 401 401
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/mini/validators-circular-ref-2/zod.gen.ts
··· 4 4 5 5 export const zBar = z.object({ 6 6 bar: z.union([ 7 - z.array(z.lazy((): any => zBar)), 7 + z.array(z.lazy((): any => zBar2)), 8 8 z.null() 9 9 ]) 10 10 });
+2 -2
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/mini/validators-circular-ref/zod.gen.ts
··· 4 4 5 5 export const zBar = z.object({ 6 6 get bar() { 7 - return z.optional(z.array(z.lazy((): any => zBar))); 7 + return z.optional(z.array(z.lazy((): any => zBar2))); 8 8 } 9 9 }); 10 10 ··· 12 12 foo: z.optional(zBar) 13 13 }); 14 14 15 - export const zBaz = z.lazy((): any => zQux); 15 + export const zBaz = z.lazy((): any => zQux2); 16 16 17 17 /** 18 18 * description caused circular reference error
+2 -2
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/mini/validators-dates/zod.gen.ts
··· 15 15 z.object({ 16 16 foo: z.optional(z.string().check(z.regex(/^\d{3}-\d{2}-\d{4}$/))), 17 17 get bar() { 18 - return z.optional(z.lazy((): any => zBar)); 18 + return z.optional(z.lazy((): any => zBar2)); 19 19 }, 20 20 get baz() { 21 - return z.optional(z.array(z.lazy((): any => zFoo))); 21 + return z.optional(z.array(z.lazy((): any => zFoo4))); 22 22 }, 23 23 qux: z._default(z.optional(z.int().check(z.gt(0))), 0) 24 24 }),
+2 -2
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/mini/validators-metadata/zod.gen.ts
··· 17 17 description: 'This is foo property.' 18 18 })), 19 19 get bar() { 20 - return z.optional(z.lazy((): any => zBar)); 20 + return z.optional(z.lazy((): any => zBar2)); 21 21 }, 22 22 get baz() { 23 - return z.optional(z.array(z.lazy((): any => zFoo)).register(z.globalRegistry, { 23 + return z.optional(z.array(z.lazy((): any => zFoo4)).register(z.globalRegistry, { 24 24 description: 'This is baz property.' 25 25 })); 26 26 },
+2 -2
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/mini/validators-types/zod.gen.ts
··· 19 19 z.object({ 20 20 foo: z.optional(z.string().check(z.regex(/^\d{3}-\d{2}-\d{4}$/))), 21 21 get bar() { 22 - return z.optional(z.lazy((): any => zBar)); 22 + return z.optional(z.lazy((): any => zBar2)); 23 23 }, 24 24 get baz() { 25 - return z.optional(z.array(z.lazy((): any => zFoo))); 25 + return z.optional(z.array(z.lazy((): any => zFoo4))); 26 26 }, 27 27 qux: z._default(z.optional(z.int().check(z.gt(0))), 0) 28 28 }),
+2 -2
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/mini/validators/zod.gen.ts
··· 15 15 z.object({ 16 16 foo: z.optional(z.string().check(z.regex(/^\d{3}-\d{2}-\d{4}$/))), 17 17 get bar() { 18 - return z.optional(z.lazy((): any => zBar)); 18 + return z.optional(z.lazy((): any => zBar2)); 19 19 }, 20 20 get baz() { 21 - return z.optional(z.array(z.lazy((): any => zFoo))); 21 + return z.optional(z.array(z.lazy((): any => zFoo4))); 22 22 }, 23 23 qux: z._default(z.optional(z.int().check(z.gt(0))), 0) 24 24 }),
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v3/default/zod.gen.ts
··· 394 394 * This is a model with one property containing a circular reference 395 395 */ 396 396 export const zModelWithCircularReference: z.AnyZodObject = z.object({ 397 - prop: z.lazy(() => zModelWithCircularReference).optional() 397 + prop: z.lazy(() => zModelWithCircularReference2).optional() 398 398 }); 399 399 400 400 /**
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v3/validators-circular-ref-2/zod.gen.ts
··· 4 4 5 5 export const zBar: z.AnyZodObject = z.object({ 6 6 bar: z.union([ 7 - z.array(z.lazy(() => zBar)), 7 + z.array(z.lazy(() => zBar2)), 8 8 z.null() 9 9 ]) 10 10 });
+2 -2
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v3/validators-circular-ref/zod.gen.ts
··· 3 3 import { z } from 'zod'; 4 4 5 5 export const zBar: z.AnyZodObject = z.object({ 6 - bar: z.array(z.lazy(() => zBar)).optional() 6 + bar: z.array(z.lazy(() => zBar2)).optional() 7 7 }); 8 8 9 9 export const zFoo = z.object({ 10 10 foo: zBar.optional() 11 11 }); 12 12 13 - export const zBaz: z.ZodTypeAny = z.lazy(() => zQux); 13 + export const zBaz: z.ZodTypeAny = z.lazy(() => zQux2); 14 14 15 15 /** 16 16 * description caused circular reference error
+2 -2
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v3/validators-dates/zod.gen.ts
··· 14 14 export const zFoo: z.ZodTypeAny = z.union([ 15 15 z.object({ 16 16 foo: z.string().regex(/^\d{3}-\d{2}-\d{4}$/).optional(), 17 - bar: z.lazy(() => zBar).optional(), 18 - baz: z.array(z.lazy(() => zFoo)).optional(), 17 + bar: z.lazy(() => zBar2).optional(), 18 + baz: z.array(z.lazy(() => zFoo4)).optional(), 19 19 qux: z.number().int().gt(0).optional().default(0) 20 20 }), 21 21 z.null()
+2 -2
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v3/validators-metadata/zod.gen.ts
··· 14 14 export const zFoo: z.ZodTypeAny = z.union([ 15 15 z.object({ 16 16 foo: z.string().regex(/^\d{3}-\d{2}-\d{4}$/).describe('This is foo property.').optional(), 17 - bar: z.lazy(() => zBar).optional(), 18 - baz: z.array(z.lazy(() => zFoo)).describe('This is baz property.').optional(), 17 + bar: z.lazy(() => zBar2).optional(), 18 + baz: z.array(z.lazy(() => zFoo4)).describe('This is baz property.').optional(), 19 19 qux: z.number().int().gt(0).describe('This is qux property.').optional().default(0) 20 20 }), 21 21 z.null()
+2 -2
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v3/validators-types/zod.gen.ts
··· 18 18 export const zFoo: z.ZodTypeAny = z.union([ 19 19 z.object({ 20 20 foo: z.string().regex(/^\d{3}-\d{2}-\d{4}$/).optional(), 21 - bar: z.lazy(() => zBar).optional(), 22 - baz: z.array(z.lazy(() => zFoo)).optional(), 21 + bar: z.lazy(() => zBar2).optional(), 22 + baz: z.array(z.lazy(() => zFoo4)).optional(), 23 23 qux: z.number().int().gt(0).optional().default(0) 24 24 }), 25 25 z.null()
+2 -2
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v3/validators/zod.gen.ts
··· 14 14 export const zFoo: z.ZodTypeAny = z.union([ 15 15 z.object({ 16 16 foo: z.string().regex(/^\d{3}-\d{2}-\d{4}$/).optional(), 17 - bar: z.lazy(() => zBar).optional(), 18 - baz: z.array(z.lazy(() => zFoo)).optional(), 17 + bar: z.lazy(() => zBar2).optional(), 18 + baz: z.array(z.lazy(() => zFoo4)).optional(), 19 19 qux: z.number().int().gt(0).optional().default(0) 20 20 }), 21 21 z.null()
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v4/default/zod.gen.ts
··· 395 395 */ 396 396 export const zModelWithCircularReference = z.object({ 397 397 get prop() { 398 - return z.optional(z.lazy((): any => zModelWithCircularReference)); 398 + return z.optional(z.lazy((): any => zModelWithCircularReference2)); 399 399 } 400 400 }); 401 401
+1 -1
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v4/validators-circular-ref-2/zod.gen.ts
··· 4 4 5 5 export const zBar = z.object({ 6 6 bar: z.union([ 7 - z.array(z.lazy((): any => zBar)), 7 + z.array(z.lazy((): any => zBar2)), 8 8 z.null() 9 9 ]) 10 10 });
+2 -2
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v4/validators-circular-ref/zod.gen.ts
··· 4 4 5 5 export const zBar = z.object({ 6 6 get bar() { 7 - return z.optional(z.array(z.lazy((): any => zBar))); 7 + return z.optional(z.array(z.lazy((): any => zBar2))); 8 8 } 9 9 }); 10 10 ··· 12 12 foo: z.optional(zBar) 13 13 }); 14 14 15 - export const zBaz = z.lazy((): any => zQux); 15 + export const zBaz = z.lazy((): any => zQux2); 16 16 17 17 /** 18 18 * description caused circular reference error
+2 -2
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v4/validators-dates/zod.gen.ts
··· 15 15 z.object({ 16 16 foo: z.optional(z.string().regex(/^\d{3}-\d{2}-\d{4}$/)), 17 17 get bar() { 18 - return z.optional(z.lazy((): any => zBar)); 18 + return z.optional(z.lazy((): any => zBar2)); 19 19 }, 20 20 get baz() { 21 - return z.optional(z.array(z.lazy((): any => zFoo))); 21 + return z.optional(z.array(z.lazy((): any => zFoo4))); 22 22 }, 23 23 qux: z.optional(z.int().gt(0)).default(0) 24 24 }),
+2 -2
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v4/validators-metadata/zod.gen.ts
··· 17 17 description: 'This is foo property.' 18 18 })), 19 19 get bar() { 20 - return z.optional(z.lazy((): any => zBar)); 20 + return z.optional(z.lazy((): any => zBar2)); 21 21 }, 22 22 get baz() { 23 - return z.optional(z.array(z.lazy((): any => zFoo)).register(z.globalRegistry, { 23 + return z.optional(z.array(z.lazy((): any => zFoo4)).register(z.globalRegistry, { 24 24 description: 'This is baz property.' 25 25 })); 26 26 },
+2 -2
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v4/validators-types/zod.gen.ts
··· 19 19 z.object({ 20 20 foo: z.optional(z.string().regex(/^\d{3}-\d{2}-\d{4}$/)), 21 21 get bar() { 22 - return z.optional(z.lazy((): any => zBar)); 22 + return z.optional(z.lazy((): any => zBar2)); 23 23 }, 24 24 get baz() { 25 - return z.optional(z.array(z.lazy((): any => zFoo))); 25 + return z.optional(z.array(z.lazy((): any => zFoo4))); 26 26 }, 27 27 qux: z.optional(z.int().gt(0)).default(0) 28 28 }),
+2 -2
packages/openapi-ts-tests/zod/v3/__snapshots__/3.1.x/v4/validators/zod.gen.ts
··· 15 15 z.object({ 16 16 foo: z.optional(z.string().regex(/^\d{3}-\d{2}-\d{4}$/)), 17 17 get bar() { 18 - return z.optional(z.lazy((): any => zBar)); 18 + return z.optional(z.lazy((): any => zBar2)); 19 19 }, 20 20 get baz() { 21 - return z.optional(z.array(z.lazy((): any => zFoo))); 21 + return z.optional(z.array(z.lazy((): any => zFoo4))); 22 22 }, 23 23 qux: z.optional(z.int().gt(0)).default(0) 24 24 }),
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/2.0.x/mini/default/zod.gen.ts
··· 294 294 */ 295 295 export const zModelWithCircularReference = z.object({ 296 296 get prop() { 297 - return z.optional(z.lazy((): any => zModelWithCircularReference)); 297 + return z.optional(z.lazy((): any => zModelWithCircularReference2)); 298 298 } 299 299 }); 300 300
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/2.0.x/v3/default/zod.gen.ts
··· 293 293 * This is a model with one property containing a circular reference 294 294 */ 295 295 export const zModelWithCircularReference: z.AnyZodObject = z.object({ 296 - prop: z.lazy(() => zModelWithCircularReference).optional() 296 + prop: z.lazy(() => zModelWithCircularReference2).optional() 297 297 }); 298 298 299 299 /**
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/2.0.x/v4/default/zod.gen.ts
··· 294 294 */ 295 295 export const zModelWithCircularReference = z.object({ 296 296 get prop() { 297 - return z.optional(z.lazy((): any => zModelWithCircularReference)); 297 + return z.optional(z.lazy((): any => zModelWithCircularReference2)); 298 298 } 299 299 }); 300 300
+5 -5
packages/openapi-ts-tests/zod/v4/__snapshots__/3.0.x/mini/circular/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 get quux() { 7 - return z.optional(z.lazy((): any => zQuux)); 7 + return z.optional(z.lazy((): any => zQuux2)); 8 8 } 9 9 }); 10 10 11 11 export const zBar = z.object({ 12 12 get bar() { 13 - return z.optional(z.lazy((): any => zBar)); 13 + return z.optional(z.lazy((): any => zBar2)); 14 14 }, 15 15 get baz() { 16 - return z.optional(z.lazy((): any => zBaz)); 16 + return z.optional(z.lazy((): any => zBaz2)); 17 17 } 18 18 }); 19 19 20 20 export const zBaz = z.object({ 21 21 get quux() { 22 - return z.optional(z.lazy((): any => zQuux)); 22 + return z.optional(z.lazy((): any => zQuux2)); 23 23 } 24 24 }); 25 25 26 26 export const zQux = z.union([ 27 27 z.intersection(z.object({ 28 28 type: z.literal('struct') 29 - }), z.lazy(() => z.lazy((): any => zCorge))), 29 + }), z.lazy(() => z.lazy((): any => zCorge2))), 30 30 z.intersection(z.object({ 31 31 type: z.literal('array') 32 32 }), zFoo)
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/3.0.x/mini/default/zod.gen.ts
··· 392 392 */ 393 393 export const zModelWithCircularReference = z.object({ 394 394 get prop() { 395 - return z.optional(z.lazy((): any => zModelWithCircularReference)); 395 + return z.optional(z.lazy((): any => zModelWithCircularReference2)); 396 396 } 397 397 }); 398 398
+2 -2
packages/openapi-ts-tests/zod/v4/__snapshots__/3.0.x/mini/validators/zod.gen.ts
··· 8 8 z.object({ 9 9 foo: z.optional(z.string().check(z.regex(/^\d{3}-\d{2}-\d{4}$/))), 10 10 get bar() { 11 - return z.optional(z.lazy((): any => zBar)); 11 + return z.optional(z.lazy((): any => zBar2)); 12 12 }, 13 13 get baz() { 14 - return z.optional(z.array(z.lazy((): any => zFoo))); 14 + return z.optional(z.array(z.lazy((): any => zFoo2))); 15 15 }, 16 16 qux: z._default(z.optional(z.int().check(z.gt(0))), 0) 17 17 }),
+5 -5
packages/openapi-ts-tests/zod/v4/__snapshots__/3.0.x/v3/circular/zod.gen.ts
··· 3 3 import { z } from 'zod/v3'; 4 4 5 5 export const zFoo: z.AnyZodObject = z.object({ 6 - quux: z.lazy(() => zQuux).optional() 6 + quux: z.lazy(() => zQuux2).optional() 7 7 }); 8 8 9 9 export const zBar: z.AnyZodObject = z.object({ 10 - bar: z.lazy(() => zBar).optional(), 11 - baz: z.lazy(() => zBaz).optional() 10 + bar: z.lazy(() => zBar2).optional(), 11 + baz: z.lazy(() => zBaz2).optional() 12 12 }); 13 13 14 14 export const zBaz: z.AnyZodObject = z.object({ 15 - quux: z.lazy(() => zQuux).optional() 15 + quux: z.lazy(() => zQuux2).optional() 16 16 }); 17 17 18 18 export const zQux: z.ZodTypeAny = z.union([ 19 19 z.object({ 20 20 type: z.literal('struct') 21 - }).and(z.lazy(() => zCorge)), 21 + }).and(z.lazy(() => zCorge2)), 22 22 z.object({ 23 23 type: z.literal('array') 24 24 }).and(zFoo)
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/3.0.x/v3/default/zod.gen.ts
··· 391 391 * This is a model with one property containing a circular reference 392 392 */ 393 393 export const zModelWithCircularReference: z.AnyZodObject = z.object({ 394 - prop: z.lazy(() => zModelWithCircularReference).optional() 394 + prop: z.lazy(() => zModelWithCircularReference2).optional() 395 395 }); 396 396 397 397 /**
+2 -2
packages/openapi-ts-tests/zod/v4/__snapshots__/3.0.x/v3/validators/zod.gen.ts
··· 7 7 export const zFoo: z.ZodTypeAny = z.union([ 8 8 z.object({ 9 9 foo: z.string().regex(/^\d{3}-\d{2}-\d{4}$/).optional(), 10 - bar: z.lazy(() => zBar).optional(), 11 - baz: z.array(z.lazy(() => zFoo)).optional(), 10 + bar: z.lazy(() => zBar2).optional(), 11 + baz: z.array(z.lazy(() => zFoo2)).optional(), 12 12 qux: z.number().int().gt(0).optional().default(0) 13 13 }), 14 14 z.null()
+5 -5
packages/openapi-ts-tests/zod/v4/__snapshots__/3.0.x/v4/circular/zod.gen.ts
··· 4 4 5 5 export const zFoo = z.object({ 6 6 get quux() { 7 - return z.optional(z.lazy((): any => zQuux)); 7 + return z.optional(z.lazy((): any => zQuux2)); 8 8 } 9 9 }); 10 10 11 11 export const zBar = z.object({ 12 12 get bar() { 13 - return z.optional(z.lazy((): any => zBar)); 13 + return z.optional(z.lazy((): any => zBar2)); 14 14 }, 15 15 get baz() { 16 - return z.optional(z.lazy((): any => zBaz)); 16 + return z.optional(z.lazy((): any => zBaz2)); 17 17 } 18 18 }); 19 19 20 20 export const zBaz = z.object({ 21 21 get quux() { 22 - return z.optional(z.lazy((): any => zQuux)); 22 + return z.optional(z.lazy((): any => zQuux2)); 23 23 } 24 24 }); 25 25 26 26 export const zQux = z.union([ 27 27 z.object({ 28 28 type: z.literal('struct') 29 - }).and(z.lazy(() => z.lazy((): any => zCorge))), 29 + }).and(z.lazy(() => z.lazy((): any => zCorge2))), 30 30 z.object({ 31 31 type: z.literal('array') 32 32 }).and(zFoo)
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/3.0.x/v4/default/zod.gen.ts
··· 392 392 */ 393 393 export const zModelWithCircularReference = z.object({ 394 394 get prop() { 395 - return z.optional(z.lazy((): any => zModelWithCircularReference)); 395 + return z.optional(z.lazy((): any => zModelWithCircularReference2)); 396 396 } 397 397 }); 398 398
+2 -2
packages/openapi-ts-tests/zod/v4/__snapshots__/3.0.x/v4/validators/zod.gen.ts
··· 8 8 z.object({ 9 9 foo: z.optional(z.string().regex(/^\d{3}-\d{2}-\d{4}$/)), 10 10 get bar() { 11 - return z.optional(z.lazy((): any => zBar)); 11 + return z.optional(z.lazy((): any => zBar2)); 12 12 }, 13 13 get baz() { 14 - return z.optional(z.array(z.lazy((): any => zFoo))); 14 + return z.optional(z.array(z.lazy((): any => zFoo2))); 15 15 }, 16 16 qux: z.optional(z.int().gt(0)).default(0) 17 17 }),
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/mini/default/zod.gen.ts
··· 395 395 */ 396 396 export const zModelWithCircularReference = z.object({ 397 397 get prop() { 398 - return z.optional(z.lazy((): any => zModelWithCircularReference)); 398 + return z.optional(z.lazy((): any => zModelWithCircularReference2)); 399 399 } 400 400 }); 401 401
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/mini/validators-circular-ref-2/zod.gen.ts
··· 4 4 5 5 export const zBar = z.object({ 6 6 bar: z.union([ 7 - z.array(z.lazy((): any => zBar)), 7 + z.array(z.lazy((): any => zBar2)), 8 8 z.null() 9 9 ]) 10 10 });
+2 -2
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/mini/validators-circular-ref/zod.gen.ts
··· 4 4 5 5 export const zBar = z.object({ 6 6 get bar() { 7 - return z.optional(z.array(z.lazy((): any => zBar))); 7 + return z.optional(z.array(z.lazy((): any => zBar2))); 8 8 } 9 9 }); 10 10 ··· 12 12 foo: z.optional(zBar) 13 13 }); 14 14 15 - export const zBaz = z.lazy((): any => zQux); 15 + export const zBaz = z.lazy((): any => zQux2); 16 16 17 17 /** 18 18 * description caused circular reference error
+2 -2
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/mini/validators-dates/zod.gen.ts
··· 15 15 z.object({ 16 16 foo: z.optional(z.string().check(z.regex(/^\d{3}-\d{2}-\d{4}$/))), 17 17 get bar() { 18 - return z.optional(z.lazy((): any => zBar)); 18 + return z.optional(z.lazy((): any => zBar2)); 19 19 }, 20 20 get baz() { 21 - return z.optional(z.array(z.lazy((): any => zFoo))); 21 + return z.optional(z.array(z.lazy((): any => zFoo4))); 22 22 }, 23 23 qux: z._default(z.optional(z.int().check(z.gt(0))), 0) 24 24 }),
+2 -2
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/mini/validators-metadata/zod.gen.ts
··· 17 17 description: 'This is foo property.' 18 18 })), 19 19 get bar() { 20 - return z.optional(z.lazy((): any => zBar)); 20 + return z.optional(z.lazy((): any => zBar2)); 21 21 }, 22 22 get baz() { 23 - return z.optional(z.array(z.lazy((): any => zFoo)).register(z.globalRegistry, { 23 + return z.optional(z.array(z.lazy((): any => zFoo4)).register(z.globalRegistry, { 24 24 description: 'This is baz property.' 25 25 })); 26 26 },
+2 -2
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/mini/validators-types/zod.gen.ts
··· 19 19 z.object({ 20 20 foo: z.optional(z.string().check(z.regex(/^\d{3}-\d{2}-\d{4}$/))), 21 21 get bar() { 22 - return z.optional(z.lazy((): any => zBar)); 22 + return z.optional(z.lazy((): any => zBar2)); 23 23 }, 24 24 get baz() { 25 - return z.optional(z.array(z.lazy((): any => zFoo))); 25 + return z.optional(z.array(z.lazy((): any => zFoo4))); 26 26 }, 27 27 qux: z._default(z.optional(z.int().check(z.gt(0))), 0) 28 28 }),
+2 -2
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/mini/validators/zod.gen.ts
··· 15 15 z.object({ 16 16 foo: z.optional(z.string().check(z.regex(/^\d{3}-\d{2}-\d{4}$/))), 17 17 get bar() { 18 - return z.optional(z.lazy((): any => zBar)); 18 + return z.optional(z.lazy((): any => zBar2)); 19 19 }, 20 20 get baz() { 21 - return z.optional(z.array(z.lazy((): any => zFoo))); 21 + return z.optional(z.array(z.lazy((): any => zFoo4))); 22 22 }, 23 23 qux: z._default(z.optional(z.int().check(z.gt(0))), 0) 24 24 }),
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v3/default/zod.gen.ts
··· 394 394 * This is a model with one property containing a circular reference 395 395 */ 396 396 export const zModelWithCircularReference: z.AnyZodObject = z.object({ 397 - prop: z.lazy(() => zModelWithCircularReference).optional() 397 + prop: z.lazy(() => zModelWithCircularReference2).optional() 398 398 }); 399 399 400 400 /**
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v3/validators-circular-ref-2/zod.gen.ts
··· 4 4 5 5 export const zBar: z.AnyZodObject = z.object({ 6 6 bar: z.union([ 7 - z.array(z.lazy(() => zBar)), 7 + z.array(z.lazy(() => zBar2)), 8 8 z.null() 9 9 ]) 10 10 });
+2 -2
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v3/validators-circular-ref/zod.gen.ts
··· 3 3 import { z } from 'zod/v3'; 4 4 5 5 export const zBar: z.AnyZodObject = z.object({ 6 - bar: z.array(z.lazy(() => zBar)).optional() 6 + bar: z.array(z.lazy(() => zBar2)).optional() 7 7 }); 8 8 9 9 export const zFoo = z.object({ 10 10 foo: zBar.optional() 11 11 }); 12 12 13 - export const zBaz: z.ZodTypeAny = z.lazy(() => zQux); 13 + export const zBaz: z.ZodTypeAny = z.lazy(() => zQux2); 14 14 15 15 /** 16 16 * description caused circular reference error
+2 -2
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v3/validators-dates/zod.gen.ts
··· 14 14 export const zFoo: z.ZodTypeAny = z.union([ 15 15 z.object({ 16 16 foo: z.string().regex(/^\d{3}-\d{2}-\d{4}$/).optional(), 17 - bar: z.lazy(() => zBar).optional(), 18 - baz: z.array(z.lazy(() => zFoo)).optional(), 17 + bar: z.lazy(() => zBar2).optional(), 18 + baz: z.array(z.lazy(() => zFoo4)).optional(), 19 19 qux: z.number().int().gt(0).optional().default(0) 20 20 }), 21 21 z.null()
+2 -2
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v3/validators-metadata/zod.gen.ts
··· 14 14 export const zFoo: z.ZodTypeAny = z.union([ 15 15 z.object({ 16 16 foo: z.string().regex(/^\d{3}-\d{2}-\d{4}$/).describe('This is foo property.').optional(), 17 - bar: z.lazy(() => zBar).optional(), 18 - baz: z.array(z.lazy(() => zFoo)).describe('This is baz property.').optional(), 17 + bar: z.lazy(() => zBar2).optional(), 18 + baz: z.array(z.lazy(() => zFoo4)).describe('This is baz property.').optional(), 19 19 qux: z.number().int().gt(0).describe('This is qux property.').optional().default(0) 20 20 }), 21 21 z.null()
+2 -2
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v3/validators-types/zod.gen.ts
··· 18 18 export const zFoo: z.ZodTypeAny = z.union([ 19 19 z.object({ 20 20 foo: z.string().regex(/^\d{3}-\d{2}-\d{4}$/).optional(), 21 - bar: z.lazy(() => zBar).optional(), 22 - baz: z.array(z.lazy(() => zFoo)).optional(), 21 + bar: z.lazy(() => zBar2).optional(), 22 + baz: z.array(z.lazy(() => zFoo4)).optional(), 23 23 qux: z.number().int().gt(0).optional().default(0) 24 24 }), 25 25 z.null()
+2 -2
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v3/validators/zod.gen.ts
··· 14 14 export const zFoo: z.ZodTypeAny = z.union([ 15 15 z.object({ 16 16 foo: z.string().regex(/^\d{3}-\d{2}-\d{4}$/).optional(), 17 - bar: z.lazy(() => zBar).optional(), 18 - baz: z.array(z.lazy(() => zFoo)).optional(), 17 + bar: z.lazy(() => zBar2).optional(), 18 + baz: z.array(z.lazy(() => zFoo4)).optional(), 19 19 qux: z.number().int().gt(0).optional().default(0) 20 20 }), 21 21 z.null()
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v4/default/zod.gen.ts
··· 395 395 */ 396 396 export const zModelWithCircularReference = z.object({ 397 397 get prop() { 398 - return z.optional(z.lazy((): any => zModelWithCircularReference)); 398 + return z.optional(z.lazy((): any => zModelWithCircularReference2)); 399 399 } 400 400 }); 401 401
+1 -1
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v4/validators-circular-ref-2/zod.gen.ts
··· 4 4 5 5 export const zBar = z.object({ 6 6 bar: z.union([ 7 - z.array(z.lazy((): any => zBar)), 7 + z.array(z.lazy((): any => zBar2)), 8 8 z.null() 9 9 ]) 10 10 });
+2 -2
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v4/validators-circular-ref/zod.gen.ts
··· 4 4 5 5 export const zBar = z.object({ 6 6 get bar() { 7 - return z.optional(z.array(z.lazy((): any => zBar))); 7 + return z.optional(z.array(z.lazy((): any => zBar2))); 8 8 } 9 9 }); 10 10 ··· 12 12 foo: z.optional(zBar) 13 13 }); 14 14 15 - export const zBaz = z.lazy((): any => zQux); 15 + export const zBaz = z.lazy((): any => zQux2); 16 16 17 17 /** 18 18 * description caused circular reference error
+2 -2
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v4/validators-dates/zod.gen.ts
··· 15 15 z.object({ 16 16 foo: z.optional(z.string().regex(/^\d{3}-\d{2}-\d{4}$/)), 17 17 get bar() { 18 - return z.optional(z.lazy((): any => zBar)); 18 + return z.optional(z.lazy((): any => zBar2)); 19 19 }, 20 20 get baz() { 21 - return z.optional(z.array(z.lazy((): any => zFoo))); 21 + return z.optional(z.array(z.lazy((): any => zFoo4))); 22 22 }, 23 23 qux: z.optional(z.int().gt(0)).default(0) 24 24 }),
+2 -2
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v4/validators-metadata/zod.gen.ts
··· 17 17 description: 'This is foo property.' 18 18 })), 19 19 get bar() { 20 - return z.optional(z.lazy((): any => zBar)); 20 + return z.optional(z.lazy((): any => zBar2)); 21 21 }, 22 22 get baz() { 23 - return z.optional(z.array(z.lazy((): any => zFoo)).register(z.globalRegistry, { 23 + return z.optional(z.array(z.lazy((): any => zFoo4)).register(z.globalRegistry, { 24 24 description: 'This is baz property.' 25 25 })); 26 26 },
+2 -2
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v4/validators-types/zod.gen.ts
··· 19 19 z.object({ 20 20 foo: z.optional(z.string().regex(/^\d{3}-\d{2}-\d{4}$/)), 21 21 get bar() { 22 - return z.optional(z.lazy((): any => zBar)); 22 + return z.optional(z.lazy((): any => zBar2)); 23 23 }, 24 24 get baz() { 25 - return z.optional(z.array(z.lazy((): any => zFoo))); 25 + return z.optional(z.array(z.lazy((): any => zFoo4))); 26 26 }, 27 27 qux: z.optional(z.int().gt(0)).default(0) 28 28 }),
+2 -2
packages/openapi-ts-tests/zod/v4/__snapshots__/3.1.x/v4/validators/zod.gen.ts
··· 15 15 z.object({ 16 16 foo: z.optional(z.string().regex(/^\d{3}-\d{2}-\d{4}$/)), 17 17 get bar() { 18 - return z.optional(z.lazy((): any => zBar)); 18 + return z.optional(z.lazy((): any => zBar2)); 19 19 }, 20 20 get baz() { 21 - return z.optional(z.array(z.lazy((): any => zFoo))); 21 + return z.optional(z.array(z.lazy((): any => zFoo4))); 22 22 }, 23 23 qux: z.optional(z.int().gt(0)).default(0) 24 24 }),
+3 -3
packages/openapi-ts/src/generate/__tests__/renderer.test.ts
··· 5 5 // Minimal local BiMap for tests to avoid importing runtime-only class 6 6 class LocalBiMap<Key, Value> { 7 7 private map = new Map<Key, Value>(); 8 - private reverse = new Map<Value, Key>(); 8 + private reverse = new Map<Value, Set<Key>>(); 9 9 get(key: Key) { 10 10 return this.map.get(key); 11 11 } 12 - getKey(value: Value) { 12 + getKeys(value: Value) { 13 13 return this.reverse.get(value); 14 14 } 15 15 set(key: Key, value: Value) { 16 16 this.map.set(key, value); 17 - this.reverse.set(value, key); 17 + this.reverse.set(value, new Set([key])); 18 18 return this; 19 19 } 20 20 hasValue(value: Value) {
+47 -23
packages/openapi-ts/src/generate/renderer.ts
··· 1 1 import path from 'node:path'; 2 2 3 3 import type { 4 - BiMap, 5 4 Binding, 6 5 File, 7 6 IProject, ··· 491 490 return lines; 492 491 } 493 492 494 - private getUniqueName(base: string, names: BiMap<number, string>): string { 495 - let index = 2; 496 - let name = base; 497 - while (names.hasValue(name)) { 498 - name = `${base}${index}`; 499 - index += 1; 493 + private getUniqueName({ 494 + base, 495 + file, 496 + index, 497 + project, 498 + symbol, 499 + }: { 500 + base: string; 501 + file: File; 502 + index: number; 503 + project: IProject; 504 + symbol: Symbol; 505 + }): string { 506 + let name = index > 1 ? `${base}${index}` : base; 507 + if (!file.resolvedNames.hasValue(name)) { 508 + return name; 509 + } 510 + const conflictIds = file.resolvedNames.getKeys(name) ?? new Set(); 511 + const conflictSymbols = [...conflictIds] 512 + .map((id) => project.symbols.get(id)) 513 + .filter((s): s is NonNullable<typeof s> => s !== undefined); 514 + if (conflictSymbols.length > 0) { 515 + const conflictKinds = conflictSymbols.map((s) => s.kind); 516 + // avoid conflicts between class and type of the same name 517 + if ( 518 + (symbol.kind === 'type' && 519 + (conflictKinds.includes('type') || 520 + conflictKinds.includes('class'))) || 521 + (symbol.kind !== 'type' && 522 + conflictKinds.some((kind) => kind !== 'type')) || 523 + (symbol.kind === 'class' && conflictKinds.includes('type')) 524 + ) { 525 + name = this.getUniqueName({ 526 + base, 527 + file, 528 + index: index + 1, 529 + project, 530 + symbol, 531 + }); 532 + } 500 533 } 501 534 return name; 502 535 } ··· 516 549 if (!symbol.name) return; 517 550 const [symbolFile] = project.symbolIdToFiles(symbol.id); 518 551 const symbolFileResolvedName = symbolFile?.resolvedNames.get(symbol.id); 519 - let name = ensureValidIdentifier(symbolFileResolvedName ?? symbol.name); 520 - const conflictId = file.resolvedNames.getKey(name); 521 - if (conflictId !== undefined) { 522 - const conflictSymbol = project.symbols.get(conflictId); 523 - if (conflictSymbol) { 524 - const kinds = [conflictSymbol.kind, symbol.kind]; 525 - if ( 526 - kinds.every((kind) => kind === 'type') || 527 - kinds.every((kind) => kind !== 'type') || 528 - // avoid conflicts between class and type of the same name 529 - (kinds.includes('class') && kinds.includes('type')) 530 - ) { 531 - name = this.getUniqueName(name, file.resolvedNames); 532 - } 533 - } 534 - } 552 + const name = this.getUniqueName({ 553 + base: ensureValidIdentifier(symbolFileResolvedName ?? symbol.name), 554 + file, 555 + index: 1, 556 + project, 557 + symbol, 558 + }); 535 559 file.resolvedNames.set(symbol.id, name); 536 560 return name; 537 561 }
+11 -11
packages/openapi-ts/src/plugins/@angular/common/httpRequests.ts
··· 133 133 resource: '@angular/core.Injectable', 134 134 }); 135 135 const symbolClass = plugin.registerSymbol({ 136 - exported: true, 137 136 meta: { 138 137 category: 'utility', 139 138 resource: 'class', ··· 148 147 name: currentClass.className, 149 148 }), 150 149 }); 151 - const node = $.class(symbolClass.placeholder) 152 - .export(symbolClass.exported) 150 + const node = $.class(symbolClass) 151 + .export() 153 152 .$if(currentClass.root, (c) => 154 153 c.decorator( 155 - symbolInjectable.placeholder, 154 + symbolInjectable, 156 155 $.object().prop('providedIn', $.literal('root')), 157 156 ), 158 157 ) ··· 181 180 }); 182 181 183 182 const symbol = plugin.registerSymbol({ 184 - exported: true, 185 183 meta: { 186 184 category: 'utility', 187 185 resource: 'operation', ··· 269 267 .param('options', (p) => 270 268 p 271 269 .required(isRequiredOptions) 272 - .type(`${symbolOptions.placeholder}<${dataType}, ThrowOnError>`), 270 + .type($.type(symbolOptions).generic(dataType).generic('ThrowOnError')), 273 271 ) 274 272 .generic('ThrowOnError', (g) => g.extends('boolean').default(false)) 275 - .returns(`${symbolHttpRequest.placeholder}<unknown>`) 273 + .returns($.type(symbolHttpRequest).generic('unknown')) 276 274 .do( 277 275 $.return( 278 276 generateRequestCallExpression({ ··· 314 312 }); 315 313 const dataType = symbolDataType?.placeholder || 'unknown'; 316 314 317 - return $.const(symbol.placeholder) 318 - .export(symbol.exported) 315 + return $.const(symbol) 316 + .export() 319 317 .$if(createOperationComment(operation), (c, v) => c.doc(v)) 320 318 .assign( 321 319 $.func() 322 320 .param('options', (p) => 323 321 p 324 322 .required(isRequiredOptions) 325 - .type(`${symbolOptions.placeholder}<${dataType}, ThrowOnError>`), 323 + .type( 324 + $.type(symbolOptions).generic(dataType).generic('ThrowOnError'), 325 + ), 326 326 ) 327 327 .generic('ThrowOnError', (g) => g.extends('boolean').default(false)) 328 - .returns(`${symbolHttpRequest.placeholder}<unknown>`) 328 + .returns($.type(symbolHttpRequest).generic('unknown')) 329 329 .do( 330 330 $.return( 331 331 generateRequestCallExpression({
+5 -7
packages/openapi-ts/src/plugins/@angular/common/httpResources.ts
··· 136 136 resource: '@angular/core.Injectable', 137 137 }); 138 138 const symbolClass = plugin.registerSymbol({ 139 - exported: true, 140 139 name: buildName({ 141 140 config: { 142 141 case: 'preserve', ··· 145 144 name: currentClass.className, 146 145 }), 147 146 }); 148 - const node = $.class(symbolClass.placeholder) 149 - .export(symbolClass.exported) 147 + const node = $.class(symbolClass) 148 + .export() 150 149 .$if(currentClass.root, (c) => 151 150 c.decorator( 152 - symbolInjectable.placeholder, 151 + symbolInjectable, 153 152 $.object().prop('providedIn', $.literal('root')), 154 153 ), 155 154 ) ··· 178 177 }); 179 178 180 179 const symbol = plugin.registerSymbol({ 181 - exported: true, 182 180 name: plugin.config.httpResources.methodNameBuilder(operation), 183 181 }); 184 182 const node = generateAngularResourceFunction({ ··· 387 385 }); 388 386 const dataType = symbolDataType?.placeholder || 'unknown'; 389 387 390 - return $.const(symbol.placeholder) 391 - .export(symbol.exported) 388 + return $.const(symbol) 389 + .export() 392 390 .$if(createOperationComment(operation), (c, v) => c.doc(v)) 393 391 .assign( 394 392 $.func()
+2 -3
packages/openapi-ts/src/plugins/@hey-api/client-core/client.ts
··· 85 85 ]; 86 86 87 87 const symbolClient = plugin.registerSymbol({ 88 - exported: true, 89 88 meta: { 90 89 category: 'client', 91 90 }, 92 91 name: 'client', 93 92 }); 94 - const statement = $.const(symbolClient.placeholder) 95 - .export(symbolClient.exported) 93 + const statement = $.const(symbolClient) 94 + .export() 96 95 .assign( 97 96 $(symbolCreateClient.placeholder).$if( 98 97 symbolCreateClientConfig,
+2 -4
packages/openapi-ts/src/plugins/@hey-api/client-core/createClientConfig.ts
··· 23 23 name: 'ClientOptions', 24 24 }); 25 25 const symbolCreateClientConfig = plugin.registerSymbol({ 26 - exported: true, 27 - kind: 'type', 28 26 name: 'CreateClientConfig', 29 27 }); 30 28 31 29 const typeCreateClientConfig = $.type 32 - .alias(symbolCreateClientConfig.placeholder) 33 - .export(symbolCreateClientConfig.exported) 30 + .alias(symbolCreateClientConfig) 31 + .export() 34 32 .doc([ 35 33 'The `createClientConfig()` function will be called on client initialization', 36 34 "and the returned object will become the client's initial configuration.",
+6 -9
packages/openapi-ts/src/plugins/@hey-api/schemas/plugin.ts
··· 369 369 for (const name in context.spec.definitions) { 370 370 const schema = context.spec.definitions[name]!; 371 371 const symbol = plugin.registerSymbol({ 372 - exported: true, 373 372 meta: { 374 373 category: 'schema', 375 374 resource: 'definition', ··· 383 382 plugin, 384 383 schema, 385 384 }); 386 - const statement = $.const(symbol.placeholder) 387 - .export(symbol.exported) 385 + const statement = $.const(symbol) 386 + .export() 388 387 .assign( 389 388 $( 390 389 $.fromValue(obj, { ··· 410 409 for (const name in context.spec.components.schemas) { 411 410 const schema = context.spec.components.schemas[name]!; 412 411 const symbol = plugin.registerSymbol({ 413 - exported: true, 414 412 meta: { 415 413 category: 'schema', 416 414 resource: 'definition', ··· 424 422 plugin, 425 423 schema, 426 424 }); 427 - const statement = $.const(symbol.placeholder) 428 - .export(symbol.exported) 425 + const statement = $.const(symbol) 426 + .export() 429 427 .assign( 430 428 $( 431 429 $.fromValue(obj, { ··· 451 449 for (const name in context.spec.components.schemas) { 452 450 const schema = context.spec.components.schemas[name]!; 453 451 const symbol = plugin.registerSymbol({ 454 - exported: true, 455 452 meta: { 456 453 category: 'schema', 457 454 resource: 'definition', ··· 465 462 plugin, 466 463 schema, 467 464 }); 468 - const statement = $.const(symbol.placeholder) 469 - .export(symbol.exported) 465 + const statement = $.const(symbol) 466 + .export() 470 467 .assign( 471 468 $( 472 469 $.fromValue(obj, {
+6 -14
packages/openapi-ts/src/plugins/@hey-api/sdk/shared/class.ts
··· 56 56 }): TsDsl => { 57 57 const defaultKey = 'defaultKey'; 58 58 const instances = 'instances'; 59 - return $.class(symbol.placeholder) 60 - .export(symbol.exported) 59 + return $.class(symbol) 61 60 .generic('T') 62 61 .field(defaultKey, (f) => 63 62 f.private().readonly().assign($.literal('default')), ··· 122 121 category: 'external', 123 122 resource: 'client.Client', 124 123 }); 125 - return $.class(symbol.placeholder) 126 - .export(symbol.exported) 124 + return $.class(symbol) 127 125 .field('client', (f) => f.protected().type(symbolClient.placeholder)) 128 126 .newline() 129 127 .init((i) => ··· 311 309 312 310 const symbolHeyApiClient = plugin.config.instance 313 311 ? plugin.registerSymbol({ 314 - exported: false, 315 - kind: 'class', 316 312 meta: { 317 313 category: 'utility', 318 314 resource: 'class', ··· 324 320 : undefined; 325 321 const symbolHeyApiRegistry = plugin.config.instance 326 322 ? plugin.registerSymbol({ 327 - exported: false, 328 - kind: 'class', 329 323 meta: { 330 324 category: 'utility', 331 325 resource: 'class', ··· 420 414 } 421 415 422 416 const symbol = plugin.registerSymbol({ 423 - exported: true, 424 - kind: 'class', 425 417 meta: { 426 418 category: 'utility', 427 419 resource: 'class', ··· 485 477 currentClass.nodes.unshift(registryNode, $.newline()); 486 478 } 487 479 488 - const node = $.class(symbol.placeholder) 489 - .export(symbol.exported) 490 - .extends(symbolHeyApiClient?.placeholder) 480 + const node = $.class(symbol) 481 + .export() 482 + .extends(symbolHeyApiClient) 491 483 .$if(currentClass.root && isAngularClient, (c) => 492 484 c.decorator( 493 485 plugin.referenceSymbol({ 494 486 category: 'external', 495 487 resource: '@angular/core.Injectable', 496 - }).placeholder, 488 + }), 497 489 $.object().prop('providedIn', $.literal('root')), 498 490 ), 499 491 )
+2 -3
packages/openapi-ts/src/plugins/@hey-api/sdk/shared/functions.ts
··· 67 67 plugin, 68 68 }); 69 69 const symbol = plugin.registerSymbol({ 70 - exported: true, 71 70 meta: { 72 71 category: 'sdk', 73 72 path: event._path, ··· 82 81 plugin, 83 82 }), 84 83 }); 85 - const node = $.const(symbol.placeholder) 86 - .export(symbol.exported) 84 + const node = $.const(symbol) 85 + .export() 87 86 .$if(createOperationComment(operation), (c, v) => c.doc(v)) 88 87 .assign( 89 88 $.func()
+2 -4
packages/openapi-ts/src/plugins/@hey-api/sdk/shared/typeOptions.ts
··· 35 35 name: 'Options', 36 36 }); 37 37 const symbolOptions = plugin.registerSymbol({ 38 - exported: true, 39 - kind: 'type', 40 38 meta: { 41 39 category: 'type', 42 40 resource: 'client-options', ··· 46 44 }); 47 45 48 46 const typeOptions = $.type 49 - .alias(symbolOptions.placeholder) 50 - .export(symbolOptions.exported) 47 + .alias(symbolOptions) 48 + .export() 51 49 .$if( 52 50 isNuxtClient, 53 51 (t) =>
+2 -3
packages/openapi-ts/src/plugins/@hey-api/transformers/plugin.ts
··· 337 337 }); 338 338 if (!nodes.length) return; 339 339 const symbol = plugin.registerSymbol({ 340 - exported: true, 341 340 meta: { 342 341 category: 'transform', 343 342 resource: 'operation', ··· 352 351 name: operation.id, 353 352 }), 354 353 }); 355 - const value = $.const(symbol.placeholder) 356 - .export(symbol.exported) 354 + const value = $.const(symbol) 355 + .export() 357 356 .assign( 358 357 // TODO: parser - add types, generate types without transforms 359 358 $.func()
+2 -2
packages/openapi-ts/src/plugins/@hey-api/typescript/shared/clientOptions.ts
··· 51 51 } 52 52 53 53 const node = $.type 54 - .alias(symbolClientOptions.placeholder) 55 - .export(symbolClientOptions.exported) 54 + .alias(symbolClientOptions) 55 + .export() 56 56 .type( 57 57 $.type 58 58 .object()
+71 -17
packages/openapi-ts/src/plugins/@hey-api/typescript/shared/export.ts
··· 1 - import type { Symbol } from '@hey-api/codegen-core'; 2 - 3 1 import type { IR } from '~/ir/types'; 2 + import { buildName } from '~/openApi/shared/utils/name'; 4 3 import { createSchemaComment } from '~/plugins/shared/utils/schema'; 5 4 import type { MaybeTsDsl, TypeTsDsl } from '~/ts-dsl'; 6 5 import { $ } from '~/ts-dsl'; 6 + import { pathToJsonPointer, refToName } from '~/utils/ref'; 7 7 import { numberRegExp } from '~/utils/regexp'; 8 8 import { stringCase } from '~/utils/stringCase'; 9 9 10 10 import type { HeyApiTypeScriptPlugin } from '../types'; 11 + import type { IrSchemaToAstOptions } from './types'; 11 12 12 13 const schemaToEnumObject = ({ 13 14 plugin, ··· 83 84 export const exportType = ({ 84 85 plugin, 85 86 schema, 86 - symbol, 87 + state, 87 88 type, 88 - }: { 89 - plugin: HeyApiTypeScriptPlugin['Instance']; 89 + }: IrSchemaToAstOptions & { 90 90 schema: IR.SchemaObject; 91 - symbol: Symbol; 92 91 type: MaybeTsDsl<TypeTsDsl>; 93 92 }) => { 93 + const $ref = pathToJsonPointer(state.path.value); 94 + 94 95 // root enums have an additional export 95 96 if (schema.type === 'enum' && plugin.config.enums.enabled) { 96 97 const enumObject = schemaToEnumObject({ plugin, schema }); ··· 106 107 ); 107 108 } 108 109 109 - const objectNode = $.const(symbol.placeholder) 110 + const symbolObject = plugin.registerSymbol({ 111 + meta: { 112 + category: 'utility', 113 + path: state.path.value, 114 + resource: 'definition', 115 + resourceId: $ref, 116 + tags: state.tags?.value, 117 + tool: 'typescript', 118 + }, 119 + name: buildName({ 120 + config: plugin.config.definitions, 121 + name: refToName($ref), 122 + }), 123 + }); 124 + const objectNode = $.const(symbolObject) 110 125 .export() 111 126 .$if(createSchemaComment(schema), (c, v) => c.doc(v)) 112 127 .assign( ··· 118 133 ), 119 134 ).as('const'), 120 135 ); 136 + plugin.setSymbolValue(symbolObject, objectNode); 121 137 138 + const symbol = plugin.registerSymbol({ 139 + meta: { 140 + category: 'type', 141 + path: state.path.value, 142 + resource: 'definition', 143 + resourceId: $ref, 144 + tags: state.tags?.value, 145 + tool: 'typescript', 146 + }, 147 + name: buildName({ 148 + config: plugin.config.definitions, 149 + name: refToName($ref), 150 + }), 151 + }); 122 152 const node = $.type 123 - .alias(symbol.placeholder) 153 + .alias(symbol) 124 154 .export() 125 155 .$if(createSchemaComment(schema), (t, v) => t.doc(v)) 126 - .type( 127 - $.type(symbol.placeholder) 128 - .idx($.type(symbol.placeholder).typeof().keyof()) 129 - .typeof(), 130 - ); 131 - plugin.setSymbolValue(symbol, [objectNode, node]); 156 + .type($.type(symbol).idx($.type(symbol).typeof().keyof()).typeof()); 157 + plugin.setSymbolValue(symbol, node); 132 158 return; 133 159 } else if ( 134 160 plugin.config.enums.mode === 'typescript' || ··· 139 165 (type) => type !== 'number' && type !== 'string', 140 166 ); 141 167 if (shouldCreateTypeScriptEnum) { 142 - const enumNode = $.enum(symbol.placeholder) 168 + const symbol = plugin.registerSymbol({ 169 + meta: { 170 + category: 'type', 171 + path: state.path.value, 172 + resource: 'definition', 173 + resourceId: $ref, 174 + tags: state.tags?.value, 175 + tool: 'typescript', 176 + }, 177 + name: buildName({ 178 + config: plugin.config.definitions, 179 + name: refToName($ref), 180 + }), 181 + }); 182 + const enumNode = $.enum(symbol) 143 183 .export() 144 184 .$if(createSchemaComment(schema), (e, v) => e.doc(v)) 145 185 .const(plugin.config.enums.mode === 'typescript-const') ··· 156 196 } 157 197 } 158 198 199 + const symbol = plugin.registerSymbol({ 200 + meta: { 201 + category: 'type', 202 + path: state.path.value, 203 + resource: 'definition', 204 + resourceId: $ref, 205 + tags: state.tags?.value, 206 + tool: 'typescript', 207 + }, 208 + name: buildName({ 209 + config: plugin.config.definitions, 210 + name: refToName($ref), 211 + }), 212 + }); 159 213 const node = $.type 160 - .alias(symbol.placeholder) 161 - .export(symbol.exported) 214 + .alias(symbol) 215 + .export() 162 216 .$if(createSchemaComment(schema), (t, v) => t.doc(v)) 163 217 .type(type); 164 218 plugin.setSymbolValue(symbol, node);
+10 -20
packages/openapi-ts/src/plugins/@hey-api/typescript/shared/operation.ts
··· 121 121 data.required = dataRequired; 122 122 123 123 const symbol = plugin.registerSymbol({ 124 - exported: true, 125 - kind: 'type', 126 124 meta: { 127 125 category: 'type', 128 126 path: state.path.value, ··· 138 136 }), 139 137 }); 140 138 const node = $.type 141 - .alias(symbol.placeholder) 142 - .export(symbol.exported) 139 + .alias(symbol) 140 + .export() 143 141 .type( 144 142 irSchemaToAst({ 145 143 plugin, ··· 164 162 165 163 if (errors) { 166 164 const symbolErrors = plugin.registerSymbol({ 167 - exported: true, 168 - kind: 'type', 169 165 meta: { 170 166 category: 'type', 171 167 path: state.path.value, ··· 181 177 }), 182 178 }); 183 179 const node = $.type 184 - .alias(symbolErrors.placeholder) 185 - .export(symbolErrors.exported) 180 + .alias(symbolErrors) 181 + .export() 186 182 .type( 187 183 irSchemaToAst({ 188 184 plugin, ··· 194 190 195 191 if (error) { 196 192 const symbol = plugin.registerSymbol({ 197 - exported: true, 198 - kind: 'type', 199 193 meta: { 200 194 category: 'type', 201 195 path: state.path.value, ··· 214 208 }), 215 209 }); 216 210 const node = $.type 217 - .alias(symbol.placeholder) 218 - .export(symbol.exported) 211 + .alias(symbol) 212 + .export() 219 213 .type( 220 214 $.type(symbolErrors.placeholder).idx( 221 215 $.type(symbolErrors.placeholder).keyof(), ··· 227 221 228 222 if (responses) { 229 223 const symbolResponses = plugin.registerSymbol({ 230 - exported: true, 231 - kind: 'type', 232 224 meta: { 233 225 category: 'type', 234 226 path: state.path.value, ··· 244 236 }), 245 237 }); 246 238 const node = $.type 247 - .alias(symbolResponses.placeholder) 248 - .export(symbolResponses.exported) 239 + .alias(symbolResponses) 240 + .export() 249 241 .type( 250 242 irSchemaToAst({ 251 243 plugin, ··· 257 249 258 250 if (response) { 259 251 const symbol = plugin.registerSymbol({ 260 - exported: true, 261 - kind: 'type', 262 252 meta: { 263 253 category: 'type', 264 254 path: state.path.value, ··· 277 267 }), 278 268 }); 279 269 const node = $.type 280 - .alias(symbol.placeholder) 281 - .export(symbol.exported) 270 + .alias(symbol) 271 + .export() 282 272 .type( 283 273 $.type(symbolResponses.placeholder).idx( 284 274 $.type(symbolResponses.placeholder).keyof(),
+4 -8
packages/openapi-ts/src/plugins/@hey-api/typescript/shared/webhook.ts
··· 24 24 25 25 if (operation.body) { 26 26 const symbolWebhookPayload = plugin.registerSymbol({ 27 - exported: true, 28 - kind: 'type', 29 27 meta: { 30 28 category: 'type', 31 29 path: state.path.value, ··· 44 42 }), 45 43 }); 46 44 const node = $.type 47 - .alias(symbolWebhookPayload.placeholder) 48 - .export(symbolWebhookPayload.exported) 45 + .alias(symbolWebhookPayload) 46 + .export() 49 47 .$if(createSchemaComment(operation.body.schema), (t, v) => t.doc(v)) 50 48 .type( 51 49 irSchemaToAst({ ··· 88 86 data.required = dataRequired; 89 87 90 88 const symbolWebhookRequest = plugin.registerSymbol({ 91 - exported: true, 92 - kind: 'type', 93 89 meta: { 94 90 category: 'type', 95 91 path: state.path.value, ··· 105 101 }), 106 102 }); 107 103 const node = $.type 108 - .alias(symbolWebhookRequest.placeholder) 109 - .export(symbolWebhookRequest.exported) 104 + .alias(symbolWebhookRequest) 105 + .export() 110 106 .type( 111 107 irSchemaToAst({ 112 108 plugin,
+2 -2
packages/openapi-ts/src/plugins/@hey-api/typescript/shared/webhooks.ts
··· 16 16 if (!webhookNames.length) return; 17 17 18 18 const node = $.type 19 - .alias(symbolWebhooks.placeholder) 20 - .export(symbolWebhooks.exported) 19 + .alias(symbolWebhooks) 20 + .export() 21 21 .type($.type.or(...webhookNames)); 22 22 plugin.setSymbolValue(symbolWebhooks, node); 23 23 };
+2 -28
packages/openapi-ts/src/plugins/@hey-api/typescript/v1/plugin.ts
··· 5 5 import { toRefs } from '~/plugins/shared/utils/refs'; 6 6 import type { MaybeTsDsl, TypeTsDsl } from '~/ts-dsl'; 7 7 import { $ } from '~/ts-dsl'; 8 - import { pathToJsonPointer, refToName } from '~/utils/ref'; 9 8 10 9 import { createClientOptions } from '../shared/clientOptions'; 11 10 import { exportType } from '../shared/export'; ··· 29 28 resource: 'definition', 30 29 resourceId: schema.$ref, 31 30 }); 32 - return $.type(symbol.placeholder); 31 + return $.type(symbol); 33 32 } 34 33 35 34 if (schema.type) { ··· 72 71 schema: IR.SchemaObject; 73 72 }) => { 74 73 const type = irSchemaToAst({ plugin, schema, state }); 75 - 76 - // Don't tag enums as 'type' since they export runtime artifacts (values) 77 - const isEnum = schema.type === 'enum' && plugin.config.enums.enabled; 78 - 79 - const $ref = pathToJsonPointer(state.path.value); 80 - const symbol = plugin.registerSymbol({ 81 - exported: true, 82 - kind: isEnum ? undefined : 'type', 83 - meta: { 84 - category: 'type', 85 - path: state.path.value, 86 - resource: 'definition', 87 - resourceId: $ref, 88 - tags: state.tags?.value, 89 - tool: 'typescript', 90 - }, 91 - name: buildName({ 92 - config: plugin.config.definitions, 93 - name: refToName($ref), 94 - }), 95 - }); 96 74 exportType({ 97 75 plugin, 98 76 schema, 99 - symbol, 77 + state, 100 78 type, 101 79 }); 102 80 }; ··· 104 82 export const handlerV1: HeyApiTypeScriptPlugin['Handler'] = ({ plugin }) => { 105 83 // reserve identifier for ClientOptions 106 84 const symbolClientOptions = plugin.registerSymbol({ 107 - exported: true, 108 - kind: 'type', 109 85 meta: { 110 86 category: 'type', 111 87 resource: 'client', ··· 121 97 }); 122 98 // reserve identifier for Webhooks 123 99 const symbolWebhooks = plugin.registerSymbol({ 124 - exported: true, 125 - kind: 'type', 126 100 meta: { 127 101 category: 'type', 128 102 resource: 'webhook',
+4 -8
packages/openapi-ts/src/plugins/@hey-api/typescript/v1/toAst/string.ts
··· 50 50 51 51 if (!plugin.getSymbol(queryTypeId)) { 52 52 const symbolTypeId = plugin.registerSymbol({ 53 - exported: true, 54 - kind: 'type', 55 53 meta: queryTypeId, 56 54 name: 'TypeID', 57 55 }); 58 56 const nodeTypeId = $.type 59 - .alias(symbolTypeId.placeholder) 60 - .export(symbolTypeId.exported) 57 + .alias(symbolTypeId) 58 + .export() 61 59 .generic('T', (g) => g.extends('string')) 62 60 .type( 63 61 $.type.template().add($.type('T')).add('_').add($.type('string')), ··· 67 65 68 66 const symbolTypeId = plugin.referenceSymbol(queryTypeId); 69 67 const symbolTypeName = plugin.registerSymbol({ 70 - exported: true, 71 - kind: 'type', 72 68 meta: query, 73 69 name: stringCase({ 74 70 case: plugin.config.case, ··· 76 72 }), 77 73 }); 78 74 const node = $.type 79 - .alias(symbolTypeName.placeholder) 80 - .export(symbolTypeName.exported) 75 + .alias(symbolTypeName) 76 + .export() 81 77 .type($.type(symbolTypeId.placeholder).generic($.type.literal(type))); 82 78 plugin.setSymbolValue(symbolTypeName, node); 83 79 }
+2 -3
packages/openapi-ts/src/plugins/@pinia/colada/mutationOptions.ts
··· 72 72 o.prop('meta', v), 73 73 ); 74 74 const symbolMutationOptions = plugin.registerSymbol({ 75 - exported: true, 76 75 name: buildName({ 77 76 config: plugin.config.mutationOptions, 78 77 name: operation.id, 79 78 }), 80 79 }); 81 - const statement = $.const(symbolMutationOptions.placeholder) 82 - .export(symbolMutationOptions.exported) 80 + const statement = $.const(symbolMutationOptions) 81 + .export() 83 82 .$if(plugin.config.comments && createOperationComment(operation), (c, v) => 84 83 c.doc(v), 85 84 )
+5 -7
packages/openapi-ts/src/plugins/@pinia/colada/queryKey.ts
··· 66 66 name: 'serializeQueryKeyValue', 67 67 }); 68 68 69 - const fn = $.const(symbolCreateQueryKey.placeholder).assign( 69 + const fn = $.const(symbolCreateQueryKey).assign( 70 70 $.func() 71 71 .param('id', (p) => p.type('string')) 72 72 .param('options', (p) => p.optional().type(TOptionsType)) ··· 163 163 tool: 'sdk', 164 164 }); 165 165 const symbolQueryKeyType = plugin.registerSymbol({ 166 - exported: true, 167 - kind: 'type', 168 166 meta: { 169 167 category: 'type', 170 168 resource: 'QueryKey', ··· 173 171 name: 'QueryKey', 174 172 }); 175 173 const queryKeyType = $.type 176 - .alias(symbolQueryKeyType.placeholder) 177 - .export(symbolQueryKeyType.exported) 174 + .alias(symbolQueryKeyType) 175 + .export() 178 176 .generic(TOptionsType, (g) => g.extends($.type(symbolOptions.placeholder))) 179 177 .type( 180 178 $.type.tuple( ··· 210 208 }) => { 211 209 const typeData = useTypeData({ operation, plugin }); 212 210 const { strippedTypeData } = getPublicTypeData({ plugin, typeData }); 213 - const statement = $.const(symbol.placeholder) 214 - .export(symbol.exported) 211 + const statement = $.const(symbol) 212 + .export() 215 213 .assign( 216 214 $.func() 217 215 .param('options', (p) =>
+2 -4
packages/openapi-ts/src/plugins/@pinia/colada/queryOptions.ts
··· 51 51 let keyExpression: ReturnType<typeof $.call>; 52 52 if (plugin.config.queryKeys.enabled) { 53 53 const symbolQueryKey = plugin.registerSymbol({ 54 - exported: true, 55 54 name: buildName({ 56 55 config: plugin.config.queryKeys, 57 56 name: operation.id, ··· 125 124 ); 126 125 127 126 const symbolQueryOptionsFn = plugin.registerSymbol({ 128 - exported: true, 129 127 meta: { 130 128 category: 'hook', 131 129 resource: 'operation', ··· 142 140 category: 'external', 143 141 resource: `${plugin.name}.defineQueryOptions`, 144 142 }); 145 - const statement = $.const(symbolQueryOptionsFn.placeholder) 146 - .export(symbolQueryOptionsFn.exported) 143 + const statement = $.const(symbolQueryOptionsFn) 144 + .export() 147 145 .$if(plugin.config.comments && createOperationComment(operation), (c, v) => 148 146 c.doc(v), 149 147 )
+5 -7
packages/openapi-ts/src/plugins/@tanstack/query-core/queryKey.ts
··· 53 53 .generic(TOptionsType) 54 54 .idx(0); 55 55 56 - const fn = $.const(symbolCreateQueryKey.placeholder).assign( 56 + const fn = $.const(symbolCreateQueryKey).assign( 57 57 $.func() 58 58 .param('id', (p) => p.type('string')) 59 59 .param('options', (p) => p.optional().type(TOptionsType)) ··· 132 132 tool: 'sdk', 133 133 }); 134 134 const symbolQueryKeyType = plugin.registerSymbol({ 135 - exported: true, 136 - kind: 'type', 137 135 meta: { 138 136 category: 'type', 139 137 resource: 'QueryKey', ··· 142 140 name: 'QueryKey', 143 141 }); 144 142 const queryKeyType = $.type 145 - .alias(symbolQueryKeyType.placeholder) 146 - .export(symbolQueryKeyType.exported) 143 + .alias(symbolQueryKeyType) 144 + .export() 147 145 .generic(TOptionsType, (g) => g.extends(symbolOptions.placeholder)) 148 146 .type( 149 147 $.type.tuple( ··· 176 174 typeQueryKey?: string; 177 175 }) => { 178 176 const typeData = useTypeData({ operation, plugin }); 179 - const statement = $.const(symbol.placeholder) 180 - .export(symbol.exported) 177 + const statement = $.const(symbol) 178 + .export() 181 179 .assign( 182 180 $.func() 183 181 .param('options', (p) =>
+3 -5
packages/openapi-ts/src/plugins/@tanstack/query-core/v5/infiniteQueryOptions.ts
··· 36 36 }), 37 37 }); 38 38 39 - const fn = $.const(symbolCreateInfiniteParams.placeholder).assign( 39 + const fn = $.const(symbolCreateInfiniteParams).assign( 40 40 $.func() 41 41 .generic('K', (g) => 42 42 g.extends( ··· 169 169 }); 170 170 171 171 const symbolInfiniteQueryKey = plugin.registerSymbol({ 172 - exported: true, 173 172 name: buildName({ 174 173 config: plugin.config.infiniteQueryKeys, 175 174 name: operation.id, ··· 231 230 } 232 231 233 232 const symbolInfiniteQueryOptionsFn = plugin.registerSymbol({ 234 - exported: true, 235 233 name: buildName({ 236 234 config: plugin.config.infiniteQueryOptions, 237 235 name: operation.id, 238 236 }), 239 237 }); 240 - const statement = $.const(symbolInfiniteQueryOptionsFn.placeholder) 241 - .export(symbolInfiniteQueryOptionsFn.exported) 238 + const statement = $.const(symbolInfiniteQueryOptionsFn) 239 + .export() 242 240 .$if(plugin.config.comments && createOperationComment(operation), (c, v) => 243 241 c.doc(v), 244 242 )
+2 -3
packages/openapi-ts/src/plugins/@tanstack/query-core/v5/mutationOptions.ts
··· 51 51 52 52 const mutationOptionsFn = 'mutationOptions'; 53 53 const symbolMutationOptions = plugin.registerSymbol({ 54 - exported: true, 55 54 name: buildName({ 56 55 config: plugin.config.mutationOptions, 57 56 name: operation.id, 58 57 }), 59 58 }); 60 - const statement = $.const(symbolMutationOptions.placeholder) 61 - .export(symbolMutationOptions.exported) 59 + const statement = $.const(symbolMutationOptions) 60 + .export() 62 61 .$if(plugin.config.comments && createOperationComment(operation), (c, v) => 63 62 c.doc(v), 64 63 )
+2 -4
packages/openapi-ts/src/plugins/@tanstack/query-core/v5/queryOptions.ts
··· 54 54 }); 55 55 56 56 const symbolQueryKey = plugin.registerSymbol({ 57 - exported: true, 58 57 name: buildName({ 59 58 config: plugin.config.queryKeys, 60 59 name: operation.id, ··· 107 106 ); 108 107 109 108 const symbolQueryOptionsFn = plugin.registerSymbol({ 110 - exported: plugin.config.queryOptions.exported, 111 109 meta: { 112 110 category: 'hook', 113 111 resource: 'operation', ··· 122 120 }); 123 121 // TODO: add type error 124 122 // TODO: AxiosError<PutSubmissionMetaError> 125 - const statement = $.const(symbolQueryOptionsFn.placeholder) 126 - .export(symbolQueryOptionsFn.exported) 123 + const statement = $.const(symbolQueryOptionsFn) 124 + .export(plugin.config.queryOptions.exported) 127 125 .$if(plugin.config.comments && createOperationComment(operation), (c, v) => 128 126 c.doc(v), 129 127 )
+2 -3
packages/openapi-ts/src/plugins/@tanstack/query-core/v5/useQuery.ts
··· 28 28 } 29 29 30 30 const symbolUseQueryFn = plugin.registerSymbol({ 31 - exported: true, 32 31 name: buildName({ 33 32 config: plugin.config.useQuery, 34 33 name: operation.id, ··· 53 52 role: 'queryOptions', 54 53 tool: plugin.name, 55 54 }); 56 - const statement = $.const(symbolUseQueryFn.placeholder) 57 - .export(symbolUseQueryFn.exported) 55 + const statement = $.const(symbolUseQueryFn) 56 + .export() 58 57 .$if(plugin.config.comments && createOperationComment(operation), (c, v) => 59 58 c.doc(v), 60 59 )
+4 -4
packages/openapi-ts/src/plugins/arktype/shared/export.ts
··· 26 26 resource: 'arktype.type', 27 27 }); 28 28 29 - const statement = $.const(symbol.placeholder) 30 - .export(symbol.exported) 29 + const statement = $.const(symbol) 30 + .export() 31 31 .$if(plugin.config.comments && createSchemaComment(schema), (c, v) => 32 32 c.doc(v), 33 33 ) ··· 46 46 47 47 if (typeInferSymbol) { 48 48 const inferType = $.type 49 - .alias(typeInferSymbol.placeholder) 50 - .export(typeInferSymbol.exported) 49 + .alias(typeInferSymbol) 50 + .export() 51 51 .type( 52 52 $.type(symbol.placeholder).attr(identifiers.type.infer).typeofType(), 53 53 );
-3
packages/openapi-ts/src/plugins/arktype/v2/plugin.ts
··· 243 243 const ast = irSchemaToAst({ plugin, schema, state }); 244 244 const baseName = refToName($ref); 245 245 const symbol = plugin.registerSymbol({ 246 - exported: true, 247 246 meta: { 248 247 category: 'schema', 249 248 path: state.path.value, ··· 259 258 }); 260 259 const typeInferSymbol = plugin.config.definitions.types.infer.enabled 261 260 ? plugin.registerSymbol({ 262 - exported: true, 263 - kind: 'type', 264 261 meta: { 265 262 category: 'type', 266 263 path: state.path.value,
+1 -6
packages/openapi-ts/src/plugins/fastify/plugin.ts
··· 154 154 }); 155 155 156 156 const symbolRouteHandlers = plugin.registerSymbol({ 157 - exported: true, 158 - kind: 'type', 159 157 name: 'RouteHandlers', 160 158 }); 161 159 ··· 174 172 }, 175 173 ); 176 174 177 - const node = $.type 178 - .alias(symbolRouteHandlers.placeholder) 179 - .export(symbolRouteHandlers.exported) 180 - .type(type); 175 + const node = $.type.alias(symbolRouteHandlers).export().type(type); 181 176 plugin.setSymbolValue(symbolRouteHandlers, node); 182 177 };
+2 -3
packages/openapi-ts/src/plugins/swr/v2/useSwr.ts
··· 27 27 resource: 'swr', 28 28 }); 29 29 const symbolUseQueryFn = plugin.registerSymbol({ 30 - exported: true, 31 30 name: buildName({ 32 31 config: plugin.config.useSwr, 33 32 name: operation.id, ··· 48 47 ); 49 48 } 50 49 51 - const statement = $.const(symbolUseQueryFn.placeholder) 52 - .export(symbolUseQueryFn.exported) 50 + const statement = $.const(symbolUseQueryFn) 51 + .export() 53 52 .$if(plugin.config.comments && createOperationComment(operation), (c, v) => 54 53 c.doc(v), 55 54 )
+2 -2
packages/openapi-ts/src/plugins/valibot/shared/export.ts
··· 24 24 resource: 'valibot.v', 25 25 }); 26 26 27 - const statement = $.const(symbol.placeholder) 28 - .export(symbol.exported) 27 + const statement = $.const(symbol) 28 + .export() 29 29 .$if(plugin.config.comments && createSchemaComment(schema), (c, v) => 30 30 c.doc(v), 31 31 )
-2
packages/openapi-ts/src/plugins/valibot/shared/operation.ts
··· 117 117 118 118 const ast = getAst(schemaData, state.path.value); 119 119 const symbol = plugin.registerSymbol({ 120 - exported: true, 121 120 meta: { 122 121 category: 'schema', 123 122 path: state.path.value, ··· 149 148 const path = [...state.path.value, 'responses']; 150 149 const ast = getAst(response, path); 151 150 const symbol = plugin.registerSymbol({ 152 - exported: true, 153 151 meta: { 154 152 category: 'schema', 155 153 path,
-1
packages/openapi-ts/src/plugins/valibot/shared/webhook.ts
··· 116 116 117 117 const ast = getAst(schemaData, state.path.value); 118 118 const symbol = plugin.registerSymbol({ 119 - exported: true, 120 119 meta: { 121 120 category: 'schema', 122 121 path: state.path.value,
-1
packages/openapi-ts/src/plugins/valibot/v1/plugin.ts
··· 161 161 const ast = irSchemaToAst({ plugin, schema, state }); 162 162 const baseName = refToName($ref); 163 163 const symbol = plugin.registerSymbol({ 164 - exported: true, 165 164 meta: { 166 165 category: 'schema', 167 166 path: state.path.value,
-3
packages/openapi-ts/src/plugins/zod/mini/plugin.ts
··· 183 183 const ast = irSchemaToAst({ plugin, schema, state }); 184 184 const baseName = refToName($ref); 185 185 const symbol = plugin.registerSymbol({ 186 - exported: true, 187 186 meta: { 188 187 category: 'schema', 189 188 path: state.path.value, ··· 199 198 }); 200 199 const typeInferSymbol = plugin.config.definitions.types.infer.enabled 201 200 ? plugin.registerSymbol({ 202 - exported: true, 203 - kind: 'type', 204 201 meta: { 205 202 category: 'type', 206 203 path: state.path.value,
+4 -4
packages/openapi-ts/src/plugins/zod/shared/export.ts
··· 26 26 resource: 'zod.z', 27 27 }); 28 28 29 - const statement = $.const(symbol.placeholder) 30 - .export(symbol.exported) 29 + const statement = $.const(symbol) 30 + .export() 31 31 .$if(plugin.config.comments && createSchemaComment(schema), (c, v) => 32 32 c.doc(v), 33 33 ) ··· 37 37 38 38 if (typeInferSymbol) { 39 39 const inferType = $.type 40 - .alias(typeInferSymbol.placeholder) 41 - .export(typeInferSymbol.exported) 40 + .alias(typeInferSymbol) 41 + .export() 42 42 .type( 43 43 $.type(z.placeholder) 44 44 .attr(identifiers.infer)
-6
packages/openapi-ts/src/plugins/zod/shared/operation.ts
··· 117 117 118 118 const ast = getAst(schemaData, state.path.value); 119 119 const symbol = plugin.registerSymbol({ 120 - exported: true, 121 120 meta: { 122 121 category: 'schema', 123 122 path: state.path.value, ··· 134 133 }); 135 134 const typeInferSymbol = plugin.config.requests.types.infer.enabled 136 135 ? plugin.registerSymbol({ 137 - exported: true, 138 - kind: 'type', 139 136 meta: { 140 137 category: 'type', 141 138 path: state.path.value, ··· 169 166 const path = [...state.path.value, 'responses']; 170 167 const ast = getAst(response, path); 171 168 const symbol = plugin.registerSymbol({ 172 - exported: true, 173 169 meta: { 174 170 category: 'schema', 175 171 path, ··· 186 182 }); 187 183 const typeInferSymbol = plugin.config.responses.types.infer.enabled 188 184 ? plugin.registerSymbol({ 189 - exported: true, 190 - kind: 'type', 191 185 meta: { 192 186 category: 'type', 193 187 path,
-3
packages/openapi-ts/src/plugins/zod/shared/webhook.ts
··· 116 116 117 117 const ast = getAst(schemaData, state.path.value); 118 118 const symbol = plugin.registerSymbol({ 119 - exported: true, 120 119 meta: { 121 120 category: 'schema', 122 121 path: state.path.value, ··· 133 132 }); 134 133 const typeInferSymbol = plugin.config.webhooks.types.infer.enabled 135 134 ? plugin.registerSymbol({ 136 - exported: true, 137 - kind: 'type', 138 135 meta: { 139 136 category: 'type', 140 137 path: state.path.value,
-3
packages/openapi-ts/src/plugins/zod/v3/plugin.ts
··· 171 171 const ast = irSchemaToAst({ plugin, schema, state }); 172 172 const baseName = refToName($ref); 173 173 const symbol = plugin.registerSymbol({ 174 - exported: true, 175 174 meta: { 176 175 category: 'schema', 177 176 path: state.path.value, ··· 187 186 }); 188 187 const typeInferSymbol = plugin.config.definitions.types.infer.enabled 189 188 ? plugin.registerSymbol({ 190 - exported: true, 191 - kind: 'type', 192 189 meta: { 193 190 category: 'type', 194 191 path: state.path.value,
-3
packages/openapi-ts/src/plugins/zod/v4/plugin.ts
··· 181 181 const ast = irSchemaToAst({ plugin, schema, state }); 182 182 const baseName = refToName($ref); 183 183 const symbol = plugin.registerSymbol({ 184 - exported: true, 185 184 meta: { 186 185 category: 'schema', 187 186 path: state.path.value, ··· 197 196 }); 198 197 const typeInferSymbol = plugin.config.definitions.types.infer.enabled 199 198 ? plugin.registerSymbol({ 200 - exported: true, 201 - kind: 'type', 202 199 meta: { 203 200 category: 'type', 204 201 path: state.path.value,
+55 -1
packages/openapi-ts/src/ts-dsl/base.ts
··· 1 + // TODO: symbol should be protected, but needs to be public to satisfy types 2 + import type { Symbol, SyntaxNode } from '@hey-api/codegen-core'; 1 3 import ts from 'typescript'; 2 4 3 5 export type MaybeArray<T> = T | ReadonlyArray<T>; 4 6 5 - export interface ITsDsl<T extends ts.Node = ts.Node> { 7 + export interface ITsDsl<T extends ts.Node = ts.Node> extends SyntaxNode { 8 + /** Render this DSL node into a concrete TypeScript AST node. */ 6 9 $render(): T; 7 10 } 8 11 12 + export type Constructor<T = ITsDsl> = new (...args: ReadonlyArray<any>) => T; 13 + 9 14 export abstract class TsDsl<T extends ts.Node = ts.Node> implements ITsDsl<T> { 15 + /** Walk this node and its children with a visitor. */ 16 + abstract traverse(visitor: (node: SyntaxNode) => void): void; 17 + 18 + /** Render this DSL node into a concrete TypeScript AST node. */ 10 19 abstract $render(): T; 20 + 21 + /** Parent DSL node in the constructed syntax tree. */ 22 + protected parent?: TsDsl<any>; 23 + 24 + /** The codegen symbol associated with this node. */ 25 + symbol?: Symbol; 11 26 12 27 /** Conditionally applies a callback to this builder. */ 13 28 $if<T extends TsDsl, V, R extends TsDsl = T>( ··· 84 99 return this; 85 100 } 86 101 102 + /** Returns all locally declared names within this node. */ 103 + getLocalNames(): Iterable<string> { 104 + return []; 105 + } 106 + 107 + /** Returns all symbols referenced by this node (directly or through children). */ 108 + getSymbols(): Iterable<Symbol> { 109 + return []; 110 + } 111 + 112 + /** Rewrites internal identifier nodes after final name resolution. */ 113 + // eslint-disable-next-line @typescript-eslint/no-unused-vars 114 + rewriteIdentifiers(_map: Map<string, string>): void { 115 + // noop 116 + } 117 + 118 + /** Assigns the parent DSL node, enforcing a single-parent invariant. */ 119 + setParent(parent: TsDsl<any>): this { 120 + if (this.parent && this.parent !== parent) { 121 + throw new Error( 122 + `DSL node already has a parent (${this.parent.constructor.name}); cannot reassign to ${parent.constructor.name}.`, 123 + ); 124 + } 125 + this.parent = parent; 126 + return this; 127 + } 128 + 87 129 protected $maybeId<T extends string | ts.Expression>( 88 130 expr: T, 89 131 ): T extends string ? ts.Identifier : T { ··· 132 174 return this.unwrap(value as any) as TypeOfMaybe<I>; 133 175 } 134 176 177 + /** Returns the root symbol associated with this DSL subtree. */ 178 + protected getRootSymbol(): Symbol | undefined { 179 + // eslint-disable-next-line @typescript-eslint/no-this-alias 180 + let n: TsDsl<any> | undefined = this; 181 + while (n) { 182 + if (n.symbol) return n.symbol; 183 + n = n.parent; 184 + } 185 + return undefined; 186 + } 187 + 188 + /** Unwraps nested DSL nodes into raw TypeScript AST nodes. */ 135 189 protected unwrap<I>(value: I): I extends TsDsl<infer N> ? N : I { 136 190 return ( 137 191 value instanceof TsDsl ? value.$render() : value
+48 -19
packages/openapi-ts/src/ts-dsl/decl/class.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { Symbol, SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 19 20 import { MethodTsDsl } from './method'; 20 21 21 22 export class ClassTsDsl extends TsDsl<ts.ClassDeclaration> { 22 - protected heritageClauses: Array<ts.HeritageClause> = []; 23 + protected baseClass?: Symbol | string; 23 24 protected body: Array<MaybeTsDsl<ts.ClassElement | NewlineTsDsl>> = []; 24 25 protected modifiers = createModifierAccessor(this); 25 26 protected name: string; 26 27 27 - constructor(name: string) { 28 + constructor(name: Symbol | string) { 28 29 super(); 29 - this.name = name; 30 + if (typeof name === 'string') { 31 + this.name = name; 32 + return; 33 + } 34 + this.name = name.finalName; 35 + this.symbol = name; 36 + this.symbol.setKind('class'); 37 + this.symbol.setRootNode(this); 30 38 } 31 39 32 40 /** Adds one or more class members (fields, methods, etc.). */ 33 41 do(...items: ReadonlyArray<MaybeTsDsl<ts.ClassElement | ts.Node>>): this { 34 - // @ts-expect-error --- IGNORE --- 35 - this.body.push(...items); 42 + for (const item of items) { 43 + if (item && typeof item === 'object' && 'setParent' in item) { 44 + item.setParent(this); 45 + } 46 + // @ts-expect-error --- IGNORE --- 47 + this.body.push(item); 48 + } 36 49 return this; 37 50 } 38 51 39 - /** Adds a base class to extend from. */ 40 - extends(base?: string | ts.Expression | false | null): this { 52 + /** Records a base class to extend from without rendering early. */ 53 + extends(base?: Symbol | string): this { 41 54 if (!base) return this; 42 - this.heritageClauses.push( 43 - ts.factory.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [ 44 - ts.factory.createExpressionWithTypeArguments( 45 - this.$maybeId(base), 46 - undefined, 47 - ), 48 - ]), 49 - ); 55 + this.baseClass = base; 56 + if (typeof base !== 'string') { 57 + const symbol = this.getRootSymbol(); 58 + if (symbol) symbol.addDependency(base); 59 + } 50 60 return this; 51 61 } 52 62 53 63 /** Adds a class field. */ 54 64 field(name: string, fn?: (f: FieldTsDsl) => void): this { 55 - const f = new FieldTsDsl(name, fn); 65 + const f = new FieldTsDsl(name, fn).setParent(this); 56 66 this.body.push(f); 57 67 return this; 58 68 } 59 69 60 70 /** Adds a class constructor. */ 61 71 init(fn?: (i: InitTsDsl) => void): this { 62 - const i = new InitTsDsl(fn); 72 + const i = new InitTsDsl(fn).setParent(this); 63 73 this.body.push(i); 64 74 return this; 65 75 } 66 76 67 77 /** Adds a class method. */ 68 78 method(name: string, fn?: (m: MethodTsDsl) => void): this { 69 - const m = new MethodTsDsl(name, fn); 79 + const m = new MethodTsDsl(name, fn).setParent(this); 70 80 this.body.push(m); 71 81 return this; 72 82 } ··· 75 85 newline(): this { 76 86 this.body.push(new NewlineTsDsl()); 77 87 return this; 88 + } 89 + 90 + /** Walk this node and its children with a visitor. */ 91 + traverse(visitor: (node: SyntaxNode) => void): void { 92 + console.log(visitor); 78 93 } 79 94 80 95 /** Builds the `ClassDeclaration` node. */ ··· 84 99 [...this.$decorators(), ...this.modifiers.list()], 85 100 this.name, 86 101 this.$generics(), 87 - this.heritageClauses, 102 + this._renderHeritage(), 88 103 body, 89 104 ); 105 + } 106 + 107 + /** Builds heritage clauses (extends). */ 108 + private _renderHeritage(): ReadonlyArray<ts.HeritageClause> { 109 + if (!this.baseClass) return []; 110 + const id = 111 + typeof this.baseClass === 'string' 112 + ? this.$maybeId(this.baseClass) 113 + : this.$maybeId(this.baseClass.finalName); 114 + return [ 115 + ts.factory.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [ 116 + ts.factory.createExpressionWithTypeArguments(id, undefined), 117 + ]), 118 + ]; 90 119 } 91 120 } 92 121
+19 -8
packages/openapi-ts/src/ts-dsl/decl/decorator.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-empty-object-type, @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { Symbol, SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 7 8 import { ArgsMixin } from '../mixins/args'; 8 9 9 10 export class DecoratorTsDsl extends TsDsl<ts.Decorator> { 10 - protected name: string | ts.Expression; 11 + protected name: Symbol | string | MaybeTsDsl<ts.Expression>; 11 12 12 13 constructor( 13 - name: string | ts.Expression, 14 + name: Symbol | string | MaybeTsDsl<ts.Expression>, 14 15 ...args: ReadonlyArray<string | MaybeTsDsl<ts.Expression>> 15 16 ) { 16 17 super(); 17 18 this.name = name; 19 + if (typeof name !== 'string' && 'id' in name) { 20 + const symbol = this.getRootSymbol(); 21 + if (symbol) symbol.addDependency(name); 22 + } 18 23 this.args(...args); 24 + } 25 + 26 + /** Walk this node and its children with a visitor. */ 27 + traverse(visitor: (node: SyntaxNode) => void): void { 28 + console.log(visitor); 19 29 } 20 30 21 31 $render(): ts.Decorator { 32 + const target = 33 + typeof this.name !== 'string' && 'id' in this.name 34 + ? this.$maybeId(this.name.finalName) 35 + : this.$node(this.name); 36 + 22 37 const args = this.$args(); 23 38 return ts.factory.createDecorator( 24 39 args.length 25 - ? ts.factory.createCallExpression( 26 - this.$maybeId(this.name), 27 - undefined, 28 - args, 29 - ) 30 - : this.$maybeId(this.name), 40 + ? ts.factory.createCallExpression(target, undefined, args) 41 + : target, 31 42 ); 32 43 } 33 44 }
+15 -2
packages/openapi-ts/src/ts-dsl/decl/enum.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { Symbol, SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 20 21 private _name: string | ts.Identifier; 21 22 protected modifiers = createModifierAccessor(this); 22 23 23 - constructor(name: string | ts.Identifier, fn?: (e: EnumTsDsl) => void) { 24 + constructor(name: Symbol | string, fn?: (e: EnumTsDsl) => void) { 24 25 super(); 25 - this._name = name; 26 + if (typeof name === 'string') { 27 + this._name = name; 28 + } else { 29 + this._name = name.finalName; 30 + this.symbol = name; 31 + this.symbol.setKind('enum'); 32 + this.symbol.setRootNode(this); 33 + } 26 34 fn?.(this); 27 35 } 28 36 ··· 37 45 members(...members: ReadonlyArray<EnumMemberTsDsl>): this { 38 46 this._members.push(...members); 39 47 return this; 48 + } 49 + 50 + /** Walk this node and its children with a visitor. */ 51 + traverse(visitor: (node: SyntaxNode) => void): void { 52 + console.log(visitor); 40 53 } 41 54 42 55 /** Renders the enum declaration. */
+6
packages/openapi-ts/src/ts-dsl/decl/field.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import { TsDsl, TypeTsDsl } from '../base'; ··· 31 32 type(type: string | TypeTsDsl): this { 32 33 this._type = type instanceof TypeTsDsl ? type : new TypeExprTsDsl(type); 33 34 return this; 35 + } 36 + 37 + /** Walk this node and its children with a visitor. */ 38 + traverse(visitor: (node: SyntaxNode) => void): void { 39 + console.log(visitor); 34 40 } 35 41 36 42 /** Builds the `PropertyDeclaration` node. */
+22 -9
packages/openapi-ts/src/ts-dsl/decl/func.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { Symbol, SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import { TsDsl, TypeTsDsl } from '../base'; ··· 29 30 ? ts.FunctionExpression 30 31 : ts.ArrowFunction 31 32 > { 32 - protected mode: FuncMode; 33 + protected mode?: FuncMode; 33 34 protected modifiers = createModifierAccessor(this); 34 35 protected name?: string; 35 36 protected _returns?: TypeTsDsl; 36 37 37 38 constructor(); 38 39 constructor(fn: (f: ImplFuncTsDsl<'arrow'>) => void); 39 - constructor(name: string); 40 - constructor(name: string, fn: (f: ImplFuncTsDsl<'decl'>) => void); 40 + constructor(name: Symbol | string); 41 + constructor(name: Symbol | string, fn: (f: ImplFuncTsDsl<'decl'>) => void); 41 42 constructor( 42 - nameOrFn?: string | ((f: ImplFuncTsDsl<'arrow'>) => void), 43 + nameOrFn?: Symbol | string | ((f: ImplFuncTsDsl<'arrow'>) => void), 43 44 fn?: (f: ImplFuncTsDsl<'decl'>) => void, 44 45 ) { 45 46 super(); 46 - if (typeof nameOrFn === 'string') { 47 - this.name = nameOrFn; 47 + if (typeof nameOrFn === 'function') { 48 + this.mode = 'arrow'; 49 + nameOrFn(this as unknown as FuncTsDsl<'arrow'>); 50 + } else if (nameOrFn) { 48 51 this.mode = 'decl'; 52 + if (typeof nameOrFn === 'string') { 53 + this.name = nameOrFn; 54 + } else { 55 + this.name = nameOrFn.finalName; 56 + this.symbol = nameOrFn; 57 + this.symbol.setKind('function'); 58 + this.symbol.setRootNode(this); 59 + } 49 60 fn?.(this as unknown as FuncTsDsl<'decl'>); 50 - } else { 51 - this.mode = 'arrow'; 52 - nameOrFn?.(this as unknown as FuncTsDsl<'arrow'>); 53 61 } 54 62 } 55 63 ··· 75 83 returns(type: string | TypeTsDsl): this { 76 84 this._returns = type instanceof TypeTsDsl ? type : new TypeExprTsDsl(type); 77 85 return this; 86 + } 87 + 88 + /** Walk this node and its children with a visitor. */ 89 + traverse(visitor: (node: SyntaxNode) => void): void { 90 + console.log(visitor); 78 91 } 79 92 80 93 $render(): M extends 'decl'
+6
packages/openapi-ts/src/ts-dsl/decl/getter.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import { TsDsl } from '../base'; ··· 25 26 super(); 26 27 this.name = name; 27 28 fn?.(this); 29 + } 30 + 31 + /** Walk this node and its children with a visitor. */ 32 + traverse(visitor: (node: SyntaxNode) => void): void { 33 + console.log(visitor); 28 34 } 29 35 30 36 $render(): ts.GetAccessorDeclaration {
+6
packages/openapi-ts/src/ts-dsl/decl/init.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import { TsDsl } from '../base'; ··· 20 21 constructor(fn?: (i: InitTsDsl) => void) { 21 22 super(); 22 23 fn?.(this); 24 + } 25 + 26 + /** Walk this node and its children with a visitor. */ 27 + traverse(visitor: (node: SyntaxNode) => void): void { 28 + console.log(visitor); 23 29 } 24 30 25 31 /** Builds the `ConstructorDeclaration` node. */
+6
packages/openapi-ts/src/ts-dsl/decl/member.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-empty-object-type, @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 22 23 } else { 23 24 this.value(value); 24 25 } 26 + } 27 + 28 + /** Walk this node and its children with a visitor. */ 29 + traverse(visitor: (node: SyntaxNode) => void): void { 30 + console.log(visitor); 25 31 } 26 32 27 33 /** Sets the enum member value. */
+6
packages/openapi-ts/src/ts-dsl/decl/method.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import { TsDsl, TypeTsDsl } from '../base'; ··· 36 37 returns(type: string | TypeTsDsl): this { 37 38 this._returns = type instanceof TypeTsDsl ? type : new TypeExprTsDsl(type); 38 39 return this; 40 + } 41 + 42 + /** Walk this node and its children with a visitor. */ 43 + traverse(visitor: (node: SyntaxNode) => void): void { 44 + console.log(visitor); 39 45 } 40 46 41 47 /** Builds the `MethodDeclaration` node. */
+6
packages/openapi-ts/src/ts-dsl/decl/param.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import { TsDsl, TypeTsDsl } from '../base'; ··· 25 26 } else { 26 27 name(this); 27 28 } 29 + } 30 + 31 + /** Walk this node and its children with a visitor. */ 32 + traverse(visitor: (node: SyntaxNode) => void): void { 33 + console.log(visitor); 28 34 } 29 35 30 36 /** Sets the parameter type. */
+6
packages/openapi-ts/src/ts-dsl/decl/pattern.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import type { MaybeArray } from '../base'; ··· 42 43 spread(name: string): this { 43 44 this._spread = name; 44 45 return this; 46 + } 47 + 48 + /** Walk this node and its children with a visitor. */ 49 + traverse(visitor: (node: SyntaxNode) => void): void { 50 + console.log(visitor); 45 51 } 46 52 47 53 /** Builds and returns a BindingName (ObjectBindingPattern, ArrayBindingPattern, or Identifier). */
+6
packages/openapi-ts/src/ts-dsl/decl/setter.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import { TsDsl } from '../base'; ··· 25 26 super(); 26 27 this.name = name; 27 28 fn?.(this); 29 + } 30 + 31 + /** Walk this node and its children with a visitor. */ 32 + traverse(visitor: (node: SyntaxNode) => void): void { 33 + console.log(visitor); 28 34 } 29 35 30 36 $render(): ts.SetAccessorDeclaration {
+6
packages/openapi-ts/src/ts-dsl/expr/array.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 47 48 spread(expr: MaybeTsDsl<ts.Expression>): this { 48 49 this._elements.push({ expr, kind: 'spread' }); 49 50 return this; 51 + } 52 + 53 + /** Walk this node and its children with a visitor. */ 54 + traverse(visitor: (node: SyntaxNode) => void): void { 55 + console.log(visitor); 50 56 } 51 57 52 58 $render(): ts.ArrayLiteralExpression {
+6
packages/openapi-ts/src/ts-dsl/expr/as.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl, TypeTsDsl } from '../base'; ··· 18 19 super(); 19 20 this.expr = expr; 20 21 this.type = type; 22 + } 23 + 24 + /** Walk this node and its children with a visitor. */ 25 + traverse(visitor: (node: SyntaxNode) => void): void { 26 + console.log(visitor); 21 27 } 22 28 23 29 $render() {
+6
packages/openapi-ts/src/ts-dsl/expr/attr.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import { validTypescriptIdentifierRegExp } from '~/utils/regexp'; ··· 26 27 super(); 27 28 this.left = left; 28 29 this.right = right; 30 + } 31 + 32 + /** Walk this node and its children with a visitor. */ 33 + traverse(visitor: (node: SyntaxNode) => void): void { 34 + console.log(visitor); 29 35 } 30 36 31 37 $render(): ts.PropertyAccessExpression | ts.ElementAccessExpression {
+6
packages/openapi-ts/src/ts-dsl/expr/await.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-empty-object-type, @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 12 13 constructor(expr: string | MaybeTsDsl<ts.Expression>) { 13 14 super(); 14 15 this._awaitExpr = expr; 16 + } 17 + 18 + /** Walk this node and its children with a visitor. */ 19 + traverse(visitor: (node: SyntaxNode) => void): void { 20 + console.log(visitor); 15 21 } 16 22 17 23 $render(): ts.AwaitExpression {
+6
packages/openapi-ts/src/ts-dsl/expr/binary.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 117 118 /** Multiplication — `this * expr` */ 118 119 times(expr: Expr): this { 119 120 return this.opAndExpr('*', expr); 121 + } 122 + 123 + /** Walk this node and its children with a visitor. */ 124 + traverse(visitor: (node: SyntaxNode) => void): void { 125 + console.log(visitor); 120 126 } 121 127 122 128 $render(): ts.BinaryExpression {
+6
packages/openapi-ts/src/ts-dsl/expr/call.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 21 22 this.args( 22 23 ...args.filter((a): a is NonNullable<typeof a> => a !== undefined), 23 24 ); 25 + } 26 + 27 + /** Walk this node and its children with a visitor. */ 28 + traverse(visitor: (node: SyntaxNode) => void): void { 29 + console.log(visitor); 24 30 } 25 31 26 32 $render(): ts.CallExpression {
+6
packages/openapi-ts/src/ts-dsl/expr/expr.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import type ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 15 16 constructor(id: string | MaybeTsDsl<ts.Expression>) { 16 17 super(); 17 18 this._exprInput = id; 19 + } 20 + 21 + /** Walk this node and its children with a visitor. */ 22 + traverse(visitor: (node: SyntaxNode) => void): void { 23 + console.log(visitor); 18 24 } 19 25 20 26 $render(): ts.Expression {
+6
packages/openapi-ts/src/ts-dsl/expr/id.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import { TsDsl } from '../base'; ··· 8 9 constructor(name: string) { 9 10 super(); 10 11 this.name = name; 12 + } 13 + 14 + /** Walk this node and its children with a visitor. */ 15 + traverse(visitor: (node: SyntaxNode) => void): void { 16 + console.log(visitor); 11 17 } 12 18 13 19 $render(): ts.Identifier {
+6
packages/openapi-ts/src/ts-dsl/expr/literal.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging, @typescript-eslint/no-empty-object-type */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import { TsDsl } from '../base'; ··· 12 13 constructor(value: string | number | boolean | null) { 13 14 super(); 14 15 this.value = value; 16 + } 17 + 18 + /** Walk this node and its children with a visitor. */ 19 + traverse(visitor: (node: SyntaxNode) => void): void { 20 + console.log(visitor); 15 21 } 16 22 17 23 $render(): ts.LiteralTypeNode['literal'] {
+6
packages/openapi-ts/src/ts-dsl/expr/new.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 18 19 super(); 19 20 this.classExpr = classExpr; 20 21 this.args(...args); 22 + } 23 + 24 + /** Walk this node and its children with a visitor. */ 25 + traverse(visitor: (node: SyntaxNode) => void): void { 26 + console.log(visitor); 21 27 } 22 28 23 29 /** Builds the `NewExpression` node. */
+6
packages/openapi-ts/src/ts-dsl/expr/object.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 69 70 spread(expr: ExprFn): this { 70 71 this._props.push(new ObjectPropTsDsl({ kind: 'spread' }).value(expr)); 71 72 return this; 73 + } 74 + 75 + /** Walk this node and its children with a visitor. */ 76 + traverse(visitor: (node: SyntaxNode) => void): void { 77 + console.log(visitor); 72 78 } 73 79 74 80 /** Builds and returns the object literal expression. */
+6
packages/openapi-ts/src/ts-dsl/expr/prefix.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import type { MaybeTsDsl } from '../base'; ··· 38 39 op(op: ts.PrefixUnaryOperator): this { 39 40 this._op = op; 40 41 return this; 42 + } 43 + 44 + /** Walk this node and its children with a visitor. */ 45 + traverse(visitor: (node: SyntaxNode) => void): void { 46 + console.log(visitor); 41 47 } 42 48 43 49 /** Renders the prefix unary expression node. */
+6
packages/openapi-ts/src/ts-dsl/expr/prop.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-empty-object-type, @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 33 34 /** Returns true when all required builder calls are present. */ 34 35 get isValid(): boolean { 35 36 return this.missingRequiredCalls().length === 0; 37 + } 38 + 39 + /** Walk this node and its children with a visitor. */ 40 + traverse(visitor: (node: SyntaxNode) => void): void { 41 + console.log(visitor); 36 42 } 37 43 38 44 value(value: Expr | Stmt | ((p: ObjectPropTsDsl) => void)) {
+6
packages/openapi-ts/src/ts-dsl/expr/regexp.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import { TsDsl } from '../base'; ··· 18 19 super(); 19 20 this.pattern = pattern; 20 21 this.flags = flags; 22 + } 23 + 24 + /** Walk this node and its children with a visitor. */ 25 + traverse(visitor: (node: SyntaxNode) => void): void { 26 + console.log(visitor); 21 27 } 22 28 23 29 /** Emits a RegularExpressionLiteral node. */
+6
packages/openapi-ts/src/ts-dsl/expr/template.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import type { MaybeTsDsl } from '../base'; ··· 16 17 add(value: string | MaybeTsDsl<ts.Expression>): this { 17 18 this.parts.push(value); 18 19 return this; 20 + } 21 + 22 + /** Walk this node and its children with a visitor. */ 23 + traverse(visitor: (node: SyntaxNode) => void): void { 24 + console.log(visitor); 19 25 } 20 26 21 27 $render(): ts.TemplateExpression | ts.NoSubstitutionTemplateLiteral {
+6
packages/openapi-ts/src/ts-dsl/expr/ternary.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import type { MaybeTsDsl } from '../base'; ··· 26 27 otherwise(expr: string | MaybeTsDsl<ts.Expression>) { 27 28 this._else = expr; 28 29 return this; 30 + } 31 + 32 + /** Walk this node and its children with a visitor. */ 33 + traverse(visitor: (node: SyntaxNode) => void): void { 34 + console.log(visitor); 29 35 } 30 36 31 37 $render(): ts.ConditionalExpression {
+6
packages/openapi-ts/src/ts-dsl/expr/typeof.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-empty-object-type, @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 13 14 constructor(expr: string | MaybeTsDsl<ts.Expression>) { 14 15 super(); 15 16 this._expr = expr; 17 + } 18 + 19 + /** Walk this node and its children with a visitor. */ 20 + traverse(visitor: (node: SyntaxNode) => void): void { 21 + console.log(visitor); 16 22 } 17 23 18 24 $render(): ts.TypeOfExpression {
+6
packages/openapi-ts/src/ts-dsl/layout/doc.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import type { MaybeArray } from '../base'; ··· 56 57 ); 57 58 58 59 return node; 60 + } 61 + 62 + /** Walk this node and its children with a visitor. */ 63 + traverse(visitor: (node: SyntaxNode) => void): void { 64 + console.log(visitor); 59 65 } 60 66 61 67 $render(): ts.Node {
+6
packages/openapi-ts/src/ts-dsl/layout/hint.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import type { MaybeArray } from '../base'; ··· 38 39 } 39 40 40 41 return node; 42 + } 43 + 44 + /** Walk this node and its children with a visitor. */ 45 + traverse(visitor: (node: SyntaxNode) => void): void { 46 + console.log(visitor); 41 47 } 42 48 43 49 $render(): ts.Node {
+6
packages/openapi-ts/src/ts-dsl/layout/newline.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import type ts from 'typescript'; 2 3 3 4 import { TsDsl } from '../base'; 4 5 import { IdTsDsl } from '../expr/id'; 5 6 6 7 export class NewlineTsDsl extends TsDsl<ts.Identifier> { 8 + /** Walk this node and its children with a visitor. */ 9 + traverse(visitor: (node: SyntaxNode) => void): void { 10 + console.log(visitor); 11 + } 12 + 7 13 $render(): ts.Identifier { 8 14 return this.$node(new IdTsDsl('\n')); 9 15 }
+6
packages/openapi-ts/src/ts-dsl/layout/note.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import type { MaybeArray } from '../base'; ··· 36 37 ); 37 38 38 39 return node; 40 + } 41 + 42 + /** Walk this node and its children with a visitor. */ 43 + traverse(visitor: (node: SyntaxNode) => void): void { 44 + console.log(visitor); 39 45 } 40 46 41 47 $render(): ts.Node {
-1
packages/openapi-ts/src/ts-dsl/mixins/apply.ts
··· 19 19 Object.getOwnPropertyDescriptors(sourceProto), 20 20 )) { 21 21 if (key === 'constructor') continue; 22 - if (key === '$render' && !descriptor.value.mixin) continue; 23 22 Object.defineProperty(targetProto, key, descriptor); 24 23 } 25 24 }
+1 -5
packages/openapi-ts/src/ts-dsl/mixins/args.ts
··· 6 6 /** 7 7 * Adds `.arg()` and `.args()` for managing expression arguments in call-like nodes. 8 8 */ 9 - export class ArgsMixin extends TsDsl { 9 + export abstract class ArgsMixin extends TsDsl { 10 10 protected _args?: Array<string | MaybeTsDsl<ts.Expression>>; 11 11 12 12 /** Adds a single expression argument. */ ··· 25 25 protected $args(): ReadonlyArray<ts.Expression> { 26 26 if (!this._args) return []; 27 27 return this.$node(this._args).map((arg) => this.$maybeId(arg)); 28 - } 29 - 30 - $render(): ts.Node { 31 - throw new Error('noop'); 32 28 } 33 29 }
+6 -7
packages/openapi-ts/src/ts-dsl/mixins/decorator.ts
··· 1 + import type { Symbol } from '@hey-api/codegen-core'; 1 2 import type ts from 'typescript'; 2 3 3 4 import type { MaybeTsDsl } from '../base'; 4 5 import { TsDsl } from '../base'; 5 6 import { DecoratorTsDsl } from '../decl/decorator'; 6 7 7 - export class DecoratorMixin extends TsDsl { 8 + export abstract class DecoratorMixin extends TsDsl { 8 9 protected decorators?: Array<DecoratorTsDsl>; 9 10 10 11 /** Adds a decorator (e.g. `@sealed({ in: 'root' })`). */ 11 12 decorator( 12 - name: string | ts.Expression, 13 + name: Symbol | string | MaybeTsDsl<ts.Expression>, 13 14 ...args: ReadonlyArray<string | MaybeTsDsl<ts.Expression>> 14 15 ): this { 15 - (this.decorators ??= []).push(new DecoratorTsDsl(name, ...args)); 16 + (this.decorators ??= []).push( 17 + new DecoratorTsDsl(name, ...args).setParent(this), 18 + ); 16 19 return this; 17 20 } 18 21 ··· 20 23 protected $decorators(): ReadonlyArray<ts.Decorator> { 21 24 if (!this.decorators) return []; 22 25 return this.$node(this.decorators); 23 - } 24 - 25 - $render(): ts.Node { 26 - throw new Error('noop'); 27 26 } 28 27 }
+1 -5
packages/openapi-ts/src/ts-dsl/mixins/do.ts
··· 7 7 /** 8 8 * Adds `.do()` for appending statements or expressions to a body. 9 9 */ 10 - export class DoMixin extends TsDsl { 10 + export abstract class DoMixin extends TsDsl { 11 11 protected _do?: Array<MaybeTsDsl<ts.Expression | ts.Statement>>; 12 12 13 13 /** Adds one or more expressions/statements to the body. */ ··· 20 20 protected $do(): ReadonlyArray<ts.Statement> { 21 21 if (!this._do) return []; 22 22 return this.$node(this._do.map((item) => new StmtTsDsl(item))); 23 - } 24 - 25 - $render(): ts.Node { 26 - throw new Error('noop'); 27 23 } 28 24 }
+2 -7
packages/openapi-ts/src/ts-dsl/mixins/doc.ts
··· 1 - import type { ITsDsl, MaybeArray } from '../base'; 1 + import type { Constructor, ITsDsl, MaybeArray } from '../base'; 2 2 import { DocTsDsl } from '../layout/doc'; 3 3 4 - export function DocMixin< 5 - TBase extends new (...args: ReadonlyArray<any>) => ITsDsl, 6 - >(Base: TBase) { 4 + export function DocMixin<TBase extends Constructor>(Base: TBase) { 7 5 const $renderBase = Base.prototype.$render; 8 6 9 7 class Mixin extends Base { ··· 19 17 return this._doc ? this._doc.apply(node) : node; 20 18 } 21 19 } 22 - 23 - // @ts-expect-error 24 - Mixin.prototype.$render.mixin = true; 25 20 26 21 return Mixin; 27 22 }
+2 -7
packages/openapi-ts/src/ts-dsl/mixins/hint.ts
··· 1 - import type { ITsDsl, MaybeArray } from '../base'; 1 + import type { Constructor, ITsDsl, MaybeArray } from '../base'; 2 2 import { HintTsDsl } from '../layout/hint'; 3 3 4 - export function HintMixin< 5 - TBase extends new (...args: ReadonlyArray<any>) => ITsDsl, 6 - >(Base: TBase) { 4 + export function HintMixin<TBase extends Constructor>(Base: TBase) { 7 5 const $renderBase = Base.prototype.$render; 8 6 9 7 class Mixin extends Base { ··· 19 17 return this._hint ? this._hint.apply(node) : node; 20 18 } 21 19 } 22 - 23 - // @ts-expect-error 24 - Mixin.prototype.$render.mixin = true; 25 20 26 21 return Mixin; 27 22 }
+42 -29
packages/openapi-ts/src/ts-dsl/mixins/modifiers.ts
··· 1 + import type { Symbol } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import type { TsDsl } from '../base'; ··· 15 16 * Adds a modifier of the specified kind to the modifiers list if the condition is true. 16 17 * 17 18 * @param kind - The syntax kind of the modifier to add. 18 - * @param condition - Whether to add the modifier (default: true). 19 + * @param condition - Whether to add the modifier. 19 20 * @returns The parent DSL node for chaining. 20 21 */ 21 - function _m(kind: ts.ModifierSyntaxKind, condition = true): Parent { 22 - if (condition) { 23 - modifiers.push(ts.factory.createModifier(kind)); 24 - } 22 + function _m(kind: ts.ModifierSyntaxKind, condition: boolean): Parent { 23 + if (condition) modifiers.push(ts.factory.createModifier(kind)); 25 24 return parent; 26 25 } 27 26 ··· 41 40 42 41 type Target = object & { 43 42 _m?(kind: ts.ModifierSyntaxKind, condition?: boolean): unknown; 43 + symbol?: Symbol; 44 44 }; 45 45 46 46 /** ··· 53 53 * @param condition - Whether to add the modifier (default: true). 54 54 * @returns The target object for chaining. 55 55 */ 56 - abstract<T extends Target>(this: T, condition: boolean = true): T { 57 - return this._m!(ts.SyntaxKind.AbstractKeyword, condition) as T; 56 + abstract<T extends Target>(this: T, condition?: boolean): T { 57 + const cond = arguments.length === 0 ? true : Boolean(condition); 58 + return this._m!(ts.SyntaxKind.AbstractKeyword, cond) as T; 58 59 } 59 60 } 60 61 ··· 68 69 * @param condition - Whether to add the modifier (default: true). 69 70 * @returns The target object for chaining. 70 71 */ 71 - async<T extends Target>(this: T, condition: boolean = true): T { 72 - return this._m!(ts.SyntaxKind.AsyncKeyword, condition) as T; 72 + async<T extends Target>(this: T, condition?: boolean): T { 73 + const cond = arguments.length === 0 ? true : Boolean(condition); 74 + return this._m!(ts.SyntaxKind.AsyncKeyword, cond) as T; 73 75 } 74 76 } 75 77 ··· 83 85 * @param condition - Whether to add the modifier (default: true). 84 86 * @returns The target object for chaining. 85 87 */ 86 - const<T extends Target>(this: T, condition: boolean = true): T { 87 - return this._m!(ts.SyntaxKind.ConstKeyword, condition) as T; 88 + const<T extends Target>(this: T, condition?: boolean): T { 89 + const cond = arguments.length === 0 ? true : Boolean(condition); 90 + return this._m!(ts.SyntaxKind.ConstKeyword, cond) as T; 88 91 } 89 92 } 90 93 ··· 98 101 * @param condition - Whether to add the modifier (default: true). 99 102 * @returns The target object for chaining. 100 103 */ 101 - declare<T extends Target>(this: T, condition: boolean = true): T { 102 - return this._m!(ts.SyntaxKind.DeclareKeyword, condition) as T; 104 + declare<T extends Target>(this: T, condition?: boolean): T { 105 + const cond = arguments.length === 0 ? true : Boolean(condition); 106 + return this._m!(ts.SyntaxKind.DeclareKeyword, cond) as T; 103 107 } 104 108 } 105 109 ··· 113 117 * @param condition - Whether to add the modifier (default: true). 114 118 * @returns The target object for chaining. 115 119 */ 116 - default<T extends Target>(this: T, condition: boolean = true): T { 117 - return this._m!(ts.SyntaxKind.DefaultKeyword, condition) as T; 120 + default<T extends Target>(this: T, condition?: boolean): T { 121 + const cond = arguments.length === 0 ? true : Boolean(condition); 122 + return this._m!(ts.SyntaxKind.DefaultKeyword, cond) as T; 118 123 } 119 124 } 120 125 ··· 128 133 * @param condition - Whether to add the modifier (default: true). 129 134 * @returns The target object for chaining. 130 135 */ 131 - export<T extends Target>(this: T, condition: boolean = true): T { 132 - return this._m!(ts.SyntaxKind.ExportKeyword, condition) as T; 136 + export<T extends Target>(this: T, condition?: boolean): T { 137 + const cond = arguments.length === 0 ? true : Boolean(condition); 138 + if (this.symbol) this.symbol.setExported(cond); 139 + return this._m!(ts.SyntaxKind.ExportKeyword, cond) as T; 133 140 } 134 141 } 135 142 ··· 143 150 * @param condition - Whether to add the modifier (default: true). 144 151 * @returns The target object for chaining. 145 152 */ 146 - override<T extends Target>(this: T, condition: boolean = true): T { 147 - return this._m!(ts.SyntaxKind.OverrideKeyword, condition) as T; 153 + override<T extends Target>(this: T, condition?: boolean): T { 154 + const cond = arguments.length === 0 ? true : Boolean(condition); 155 + return this._m!(ts.SyntaxKind.OverrideKeyword, cond) as T; 148 156 } 149 157 } 150 158 ··· 158 166 * @param condition - Whether to add the modifier (default: true). 159 167 * @returns The target object for chaining. 160 168 */ 161 - private<T extends Target>(this: T, condition: boolean = true): T { 162 - return this._m!(ts.SyntaxKind.PrivateKeyword, condition) as T; 169 + private<T extends Target>(this: T, condition?: boolean): T { 170 + const cond = arguments.length === 0 ? true : Boolean(condition); 171 + return this._m!(ts.SyntaxKind.PrivateKeyword, cond) as T; 163 172 } 164 173 } 165 174 ··· 173 182 * @param condition - Whether to add the modifier (default: true). 174 183 * @returns The target object for chaining. 175 184 */ 176 - protected<T extends Target>(this: T, condition: boolean = true): T { 177 - return this._m!(ts.SyntaxKind.ProtectedKeyword, condition) as T; 185 + protected<T extends Target>(this: T, condition?: boolean): T { 186 + const cond = arguments.length === 0 ? true : Boolean(condition); 187 + return this._m!(ts.SyntaxKind.ProtectedKeyword, cond) as T; 178 188 } 179 189 } 180 190 ··· 188 198 * @param condition - Whether to add the modifier (default: true). 189 199 * @returns The target object for chaining. 190 200 */ 191 - public<T extends Target>(this: T, condition: boolean = true): T { 192 - return this._m!(ts.SyntaxKind.PublicKeyword, condition) as T; 201 + public<T extends Target>(this: T, condition?: boolean): T { 202 + const cond = arguments.length === 0 ? true : Boolean(condition); 203 + return this._m!(ts.SyntaxKind.PublicKeyword, cond) as T; 193 204 } 194 205 } 195 206 ··· 203 214 * @param condition - Whether to add the modifier (default: true). 204 215 * @returns The target object for chaining. 205 216 */ 206 - readonly<T extends Target>(this: T, condition: boolean = true): T { 207 - return this._m!(ts.SyntaxKind.ReadonlyKeyword, condition) as T; 217 + readonly<T extends Target>(this: T, condition?: boolean): T { 218 + const cond = arguments.length === 0 ? true : Boolean(condition); 219 + return this._m!(ts.SyntaxKind.ReadonlyKeyword, cond) as T; 208 220 } 209 221 } 210 222 ··· 218 230 * @param condition - Whether to add the modifier (default: true). 219 231 * @returns The target object for chaining. 220 232 */ 221 - static<T extends Target>(this: T, condition: boolean = true): T { 222 - return this._m!(ts.SyntaxKind.StaticKeyword, condition) as T; 233 + static<T extends Target>(this: T, condition?: boolean): T { 234 + const cond = arguments.length === 0 ? true : Boolean(condition); 235 + return this._m!(ts.SyntaxKind.StaticKeyword, cond) as T; 223 236 } 224 237 }
+2 -7
packages/openapi-ts/src/ts-dsl/mixins/note.ts
··· 1 - import type { ITsDsl, MaybeArray } from '../base'; 1 + import type { Constructor, ITsDsl, MaybeArray } from '../base'; 2 2 import { NoteTsDsl } from '../layout/note'; 3 3 4 - export function NoteMixin< 5 - TBase extends new (...args: ReadonlyArray<any>) => ITsDsl, 6 - >(Base: TBase) { 4 + export function NoteMixin<TBase extends Constructor>(Base: TBase) { 7 5 const $renderBase = Base.prototype.$render; 8 6 9 7 class Mixin extends Base { ··· 19 17 return this._note ? this._note.apply(node) : node; 20 18 } 21 19 } 22 - 23 - // @ts-expect-error 24 - Mixin.prototype.$render.mixin = true; 25 20 26 21 return Mixin; 27 22 }
+1 -5
packages/openapi-ts/src/ts-dsl/mixins/param.ts
··· 3 3 import { type MaybeTsDsl, TsDsl } from '../base'; 4 4 import { ParamTsDsl } from '../decl/param'; 5 5 6 - export class ParamMixin extends TsDsl { 6 + export abstract class ParamMixin extends TsDsl { 7 7 protected _params?: Array<MaybeTsDsl<ts.ParameterDeclaration>>; 8 8 9 9 /** Adds a parameter. */ ··· 26 26 protected $params(): ReadonlyArray<ts.ParameterDeclaration> { 27 27 if (!this._params) return []; 28 28 return this.$node(this._params); 29 - } 30 - 31 - $render(): ts.Node { 32 - throw new Error('noop'); 33 29 } 34 30 }
+1 -5
packages/openapi-ts/src/ts-dsl/mixins/pattern.ts
··· 7 7 /** 8 8 * Mixin providing `.array()`, `.object()`, and `.spread()` methods for defining destructuring patterns. 9 9 */ 10 - export class PatternMixin extends TsDsl { 10 + export abstract class PatternMixin extends TsDsl { 11 11 protected pattern?: PatternTsDsl; 12 12 13 13 /** Defines an array binding pattern. */ ··· 33 33 /** Renders the pattern into a `BindingName`. */ 34 34 protected $pattern(): ts.BindingName | undefined { 35 35 return this.$node(this.pattern); 36 - } 37 - 38 - $render(): ts.Node { 39 - throw new Error('noop'); 40 36 } 41 37 }
+1 -5
packages/openapi-ts/src/ts-dsl/mixins/type-args.ts
··· 3 3 import type { MaybeTsDsl, TypeTsDsl } from '../base'; 4 4 import { TsDsl } from '../base'; 5 5 6 - export class TypeArgsMixin extends TsDsl { 6 + export abstract class TypeArgsMixin extends TsDsl { 7 7 protected _generics?: Array<string | MaybeTsDsl<TypeTsDsl>>; 8 8 9 9 /** Adds a single type argument (e.g. `string` in `Foo<string>`). */ ··· 21 21 /** Returns the type arguments as an array of ts.TypeNode nodes. */ 22 22 protected $generics(): ReadonlyArray<ts.TypeNode> | undefined { 23 23 return this.$type(this._generics); 24 - } 25 - 26 - $render(): ts.Node { 27 - throw new Error('noop'); 28 24 } 29 25 }
+1 -5
packages/openapi-ts/src/ts-dsl/mixins/type-params.ts
··· 4 4 import { TsDsl } from '../base'; 5 5 import { TypeParamTsDsl } from '../type/param'; 6 6 7 - export class TypeParamsMixin extends TsDsl { 7 + export abstract class TypeParamsMixin extends TsDsl { 8 8 protected _generics?: Array<string | MaybeTsDsl<TypeParamTsDsl>>; 9 9 10 10 /** Adds a single type parameter (e.g. `T` in `Array<T>`). */ ··· 28 28 const node = typeof g === 'string' ? new TypeParamTsDsl(g) : g; 29 29 return this.$node(node); 30 30 }); 31 - } 32 - 33 - $render(): ts.Node { 34 - throw new Error('noop'); 35 31 } 36 32 }
+1 -5
packages/openapi-ts/src/ts-dsl/mixins/value.ts
··· 3 3 import type { MaybeTsDsl } from '../base'; 4 4 import { TsDsl } from '../base'; 5 5 6 - export class ValueMixin extends TsDsl { 6 + export abstract class ValueMixin extends TsDsl { 7 7 protected value?: string | MaybeTsDsl<ts.Expression>; 8 8 9 9 /** Sets the initializer expression (e.g. `= expr`). */ ··· 14 14 15 15 protected $value(): ts.Expression | undefined { 16 16 return this.$node(this.value); 17 - } 18 - 19 - $render(): ts.Node { 20 - throw new Error('noop'); 21 17 } 22 18 }
+6
packages/openapi-ts/src/ts-dsl/stmt/if.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-empty-object-type, @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 23 24 otherwise(...statements: ReadonlyArray<MaybeTsDsl<ts.Statement>>): this { 24 25 this._else = statements; 25 26 return this; 27 + } 28 + 29 + /** Walk this node and its children with a visitor. */ 30 + traverse(visitor: (node: SyntaxNode) => void): void { 31 + console.log(visitor); 26 32 } 27 33 28 34 $render(): ts.IfStatement {
+6
packages/openapi-ts/src/ts-dsl/stmt/return.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-empty-object-type, @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 12 13 constructor(expr?: string | MaybeTsDsl<ts.Expression>) { 13 14 super(); 14 15 this._returnExpr = expr; 16 + } 17 + 18 + /** Walk this node and its children with a visitor. */ 19 + traverse(visitor: (node: SyntaxNode) => void): void { 20 + console.log(visitor); 15 21 } 16 22 17 23 $render(): ts.ReturnStatement {
+6
packages/openapi-ts/src/ts-dsl/stmt/stmt.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import { TsDsl } from '../base'; ··· 8 9 constructor(inner: ts.Expression | ts.Statement | TsDsl<any>) { 9 10 super(); 10 11 this._inner = inner; 12 + } 13 + 14 + /** Walk this node and its children with a visitor. */ 15 + traverse(visitor: (node: SyntaxNode) => void): void { 16 + console.log(visitor); 11 17 } 12 18 13 19 $render(): ts.Statement {
+6
packages/openapi-ts/src/ts-dsl/stmt/throw.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import type { MaybeTsDsl } from '../base'; ··· 18 19 message(value: string | MaybeTsDsl<ts.Expression>): this { 19 20 this.msg = value; 20 21 return this; 22 + } 23 + 24 + /** Walk this node and its children with a visitor. */ 25 + traverse(visitor: (node: SyntaxNode) => void): void { 26 + console.log(visitor); 21 27 } 22 28 23 29 $render(): ts.ThrowStatement {
+17 -2
packages/openapi-ts/src/ts-dsl/stmt/var.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { Symbol, SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import { TsDsl, TypeTsDsl } from '../base'; ··· 20 21 protected name?: string; 21 22 protected _type?: TypeTsDsl; 22 23 23 - constructor(name?: string) { 24 + constructor(name?: Symbol | string) { 24 25 super(); 25 - this.name = name; 26 + if (name) { 27 + if (typeof name === 'string') { 28 + this.name = name; 29 + } else { 30 + this.name = name.finalName; 31 + this.symbol = name; 32 + this.symbol.setKind('var'); 33 + this.symbol.setRootNode(this); 34 + } 35 + } 26 36 } 27 37 28 38 const(): this { ··· 33 43 let(): this { 34 44 this.kind = ts.NodeFlags.Let; 35 45 return this; 46 + } 47 + 48 + /** Walk this node and its children with a visitor. */ 49 + traverse(visitor: (node: SyntaxNode) => void): void { 50 + console.log(visitor); 36 51 } 37 52 38 53 /** Sets the variable type. */
+6
packages/openapi-ts/src/ts-dsl/token.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import { TsDsl } from './base'; ··· 53 54 return (this as TokenTsDsl<ts.SyntaxKind.DotDotDotToken>).kind( 54 55 ts.SyntaxKind.DotDotDotToken, 55 56 ); 57 + } 58 + 59 + /** Walk this node and its children with a visitor. */ 60 + traverse(visitor: (node: SyntaxNode) => void): void { 61 + console.log(visitor); 56 62 } 57 63 58 64 /** Renders the final token */
+16 -3
packages/openapi-ts/src/ts-dsl/type/alias.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { Symbol, SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 9 10 import { TypeParamsMixin } from '../mixins/type-params'; 10 11 11 12 export class TypeAliasTsDsl extends TsDsl<ts.TypeAliasDeclaration> { 12 - protected value?: MaybeTsDsl<ts.TypeNode>; 13 13 protected modifiers = createModifierAccessor(this); 14 14 protected name: string; 15 + protected value?: MaybeTsDsl<ts.TypeNode>; 15 16 16 - constructor(name: string, fn?: (t: TypeAliasTsDsl) => void) { 17 + constructor(name: Symbol | string, fn?: (t: TypeAliasTsDsl) => void) { 17 18 super(); 18 - this.name = name; 19 + if (typeof name === 'string') { 20 + this.name = name; 21 + } else { 22 + this.name = name.finalName; 23 + this.symbol = name; 24 + this.symbol.setKind('type'); 25 + this.symbol.setRootNode(this); 26 + } 19 27 fn?.(this); 28 + } 29 + 30 + /** Walk this node and its children with a visitor. */ 31 + traverse(visitor: (node: SyntaxNode) => void): void { 32 + console.log(visitor); 20 33 } 21 34 22 35 /** Sets the type expression on the right-hand side of `= ...`. */
+6
packages/openapi-ts/src/ts-dsl/type/and.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import { TypeTsDsl } from '../base'; ··· 8 9 constructor(...nodes: Array<string | ts.TypeNode | TypeTsDsl>) { 9 10 super(); 10 11 this.types(...nodes); 12 + } 13 + 14 + /** Walk this node and its children with a visitor. */ 15 + traverse(visitor: (node: SyntaxNode) => void): void { 16 + console.log(visitor); 11 17 } 12 18 13 19 types(...nodes: Array<string | ts.TypeNode | TypeTsDsl>): this {
+21 -9
packages/openapi-ts/src/ts-dsl/type/attr.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-empty-object-type, @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { Symbol, SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 7 8 import { TypeExprMixin } from '../mixins/type-expr'; 8 9 9 10 export class TypeAttrTsDsl extends TypeTsDsl<ts.QualifiedName> { 10 - protected _base?: string | MaybeTsDsl<ts.EntityName>; 11 - protected right: string | ts.Identifier; 11 + protected _base?: Symbol | string | MaybeTsDsl<ts.EntityName>; 12 + protected right: Symbol | string | ts.Identifier; 12 13 13 14 constructor( 14 - base: string | MaybeTsDsl<ts.EntityName>, 15 + base: Symbol | string | MaybeTsDsl<ts.EntityName>, 15 16 right: string | ts.Identifier, 16 17 ); 17 - constructor(right: string | ts.Identifier); 18 + constructor(right: Symbol | string | ts.Identifier); 18 19 constructor( 19 - baseOrRight: string | MaybeTsDsl<ts.EntityName>, 20 - maybeRight?: string | ts.Identifier, 20 + baseOrRight: Symbol | string | MaybeTsDsl<ts.EntityName>, 21 + maybeRight?: Symbol | string | ts.Identifier, 21 22 ) { 22 23 super(); 23 24 if (maybeRight) { ··· 29 30 } 30 31 } 31 32 32 - base(base?: string | MaybeTsDsl<ts.EntityName>): this { 33 + base(base?: Symbol | string | MaybeTsDsl<ts.EntityName>): this { 33 34 this._base = base; 34 35 return this; 35 36 } 36 37 38 + /** Walk this node and its children with a visitor. */ 39 + traverse(visitor: (node: SyntaxNode) => void): void { 40 + console.log(visitor); 41 + } 42 + 37 43 $render(): ts.QualifiedName { 38 44 if (!this._base) { 39 45 throw new Error('TypeAttrTsDsl: missing base for qualified name'); 40 46 } 41 - const left = this.$node(this._base); 47 + const left = 48 + typeof this._base !== 'string' && this._base && 'id' in this._base 49 + ? this.$node(this._base.finalName) 50 + : this.$node(this._base); 42 51 if (!ts.isEntityName(left)) { 43 52 throw new Error('TypeAttrTsDsl: base must be an EntityName'); 44 53 } 45 - const right = this.$maybeId(this.right); 54 + const right = 55 + typeof this.right !== 'string' && this.right && 'id' in this.right 56 + ? this.$maybeId(this.right.finalName) 57 + : this.$maybeId(this.right); 46 58 return ts.factory.createQualifiedName(left, right); 47 59 } 48 60 }
+29 -12
packages/openapi-ts/src/ts-dsl/type/expr.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { Symbol, SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import { TypeTsDsl } from '../base'; ··· 11 12 import { TypeAttrTsDsl } from './attr'; 12 13 13 14 export class TypeExprTsDsl extends TypeTsDsl<ts.TypeReferenceNode> { 14 - protected _exprInput?: string | ts.Identifier | TypeAttrTsDsl; 15 + protected _exprInput?: Symbol | string | TypeAttrTsDsl; 15 16 16 17 constructor(); 17 18 constructor(fn: (t: TypeExprTsDsl) => void); 18 - constructor(name: string); 19 - constructor(name: string, fn?: (t: TypeExprTsDsl) => void); 19 + constructor(name: Symbol | string); 20 + constructor(name: Symbol | string, fn?: (t: TypeExprTsDsl) => void); 20 21 constructor( 21 - nameOrFn?: string | ((t: TypeExprTsDsl) => void), 22 + name?: Symbol | string | ((t: TypeExprTsDsl) => void), 22 23 fn?: (t: TypeExprTsDsl) => void, 23 24 ) { 24 25 super(); 25 - if (typeof nameOrFn === 'string') { 26 - this._exprInput = nameOrFn; 27 - fn?.(this); 28 - } else { 29 - nameOrFn?.(this); 26 + if (name) { 27 + if (typeof name === 'function') { 28 + name(this); 29 + } else { 30 + this._exprInput = name; 31 + if (typeof name !== 'string') { 32 + const symbol = this.getRootSymbol(); 33 + if (symbol) symbol.addDependency(name); 34 + } 35 + fn?.(this); 36 + } 30 37 } 31 38 } 32 39 ··· 36 43 right instanceof TypeAttrTsDsl 37 44 ? right.base(this._exprInput) 38 45 : new TypeAttrTsDsl(this._exprInput!, right); 46 + this._exprInput = this._exprInput.setParent(this); 39 47 return this; 48 + } 49 + 50 + /** Walk this node and its children with a visitor. */ 51 + traverse(visitor: (node: SyntaxNode) => void): void { 52 + console.log(visitor); 40 53 } 41 54 42 55 $render(): ts.TypeReferenceNode { 43 - if (!this._exprInput) 44 - throw new Error('TypeExpr must have either an expression or an object'); 56 + if (!this._exprInput) throw new Error('TypeExpr must have an expression'); 57 + const typeName = 58 + typeof this._exprInput === 'string' || 59 + this._exprInput instanceof TypeAttrTsDsl 60 + ? this.$type(this._exprInput) 61 + : this._exprInput.finalName; 45 62 return ts.factory.createTypeReferenceNode( 46 63 // @ts-expect-error --- need to fix types 47 - this.$type(this._exprInput), 64 + typeName, 48 65 this.$generics(), 49 66 ); 50 67 }
+6
packages/openapi-ts/src/ts-dsl/type/func.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import { TypeTsDsl } from '../base'; ··· 15 16 returns(type: string | TypeTsDsl): this { 16 17 this._returns = type instanceof TypeTsDsl ? type : new TypeExprTsDsl(type); 17 18 return this; 19 + } 20 + 21 + /** Walk this node and its children with a visitor. */ 22 + traverse(visitor: (node: SyntaxNode) => void): void { 23 + console.log(visitor); 18 24 } 19 25 20 26 $render(): ts.FunctionTypeNode {
+6
packages/openapi-ts/src/ts-dsl/type/idx-sig.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 30 31 key(type: Type): this { 31 32 this._key = type; 32 33 return this; 34 + } 35 + 36 + /** Walk this node and its children with a visitor. */ 37 + traverse(visitor: (node: SyntaxNode) => void): void { 38 + console.log(visitor); 33 39 } 34 40 35 41 /** Sets the property type. */
+6
packages/openapi-ts/src/ts-dsl/type/idx.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-empty-object-type, @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 30 31 index(index: string | MaybeTsDsl<ts.TypeNode> | number): this { 31 32 this._index = index; 32 33 return this; 34 + } 35 + 36 + /** Walk this node and its children with a visitor. */ 37 + traverse(visitor: (node: SyntaxNode) => void): void { 38 + console.log(visitor); 33 39 } 34 40 35 41 $render(): ts.IndexedAccessTypeNode {
+6
packages/openapi-ts/src/ts-dsl/type/literal.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import { TypeTsDsl } from '../base'; ··· 9 10 constructor(value: string | number | boolean | null) { 10 11 super(); 11 12 this.value = value; 13 + } 14 + 15 + /** Walk this node and its children with a visitor. */ 16 + traverse(visitor: (node: SyntaxNode) => void): void { 17 + console.log(visitor); 12 18 } 13 19 14 20 $render(): ts.LiteralTypeNode {
+6
packages/openapi-ts/src/ts-dsl/type/mapped.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import type { MaybeTsDsl } from '../base'; ··· 63 64 required(): this { 64 65 this.questionToken = new TokenTsDsl().minus(); 65 66 return this; 67 + } 68 + 69 + /** Walk this node and its children with a visitor. */ 70 + traverse(visitor: (node: SyntaxNode) => void): void { 71 + console.log(visitor); 66 72 } 67 73 68 74 /** Sets the mapped value type: `[K in X]: ValueType` */
+6
packages/openapi-ts/src/ts-dsl/type/object.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import { TypeTsDsl } from '../base'; ··· 29 30 const prop = new TypePropTsDsl(name, fn); 30 31 this.props.push(prop); 31 32 return this; 33 + } 34 + 35 + /** Walk this node and its children with a visitor. */ 36 + traverse(visitor: (node: SyntaxNode) => void): void { 37 + console.log(visitor); 32 38 } 33 39 34 40 $render(): ts.TypeNode {
+6
packages/openapi-ts/src/ts-dsl/type/operator.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import type { MaybeTsDsl } from '../base'; ··· 44 45 this.operator(ts.SyntaxKind.ReadonlyKeyword); 45 46 this.type(type); 46 47 return this; 48 + } 49 + 50 + /** Walk this node and its children with a visitor. */ 51 + traverse(visitor: (node: SyntaxNode) => void): void { 52 + console.log(visitor); 47 53 } 48 54 49 55 /** Sets the target type of the operator. */
+6
packages/openapi-ts/src/ts-dsl/type/or.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import { TypeTsDsl } from '../base'; ··· 8 9 constructor(...nodes: Array<string | ts.TypeNode | TypeTsDsl>) { 9 10 super(); 10 11 this.types(...nodes); 12 + } 13 + 14 + /** Walk this node and its children with a visitor. */ 15 + traverse(visitor: (node: SyntaxNode) => void): void { 16 + console.log(visitor); 11 17 } 12 18 13 19 types(...nodes: Array<string | ts.TypeNode | TypeTsDsl>): this {
+6
packages/openapi-ts/src/ts-dsl/type/param.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import type { MaybeTsDsl } from '../base'; ··· 25 26 extends(constraint: string | MaybeTsDsl<TypeTsDsl> | boolean): this { 26 27 this.constraint = constraint; 27 28 return this; 29 + } 30 + 31 + /** Walk this node and its children with a visitor. */ 32 + traverse(visitor: (node: SyntaxNode) => void): void { 33 + console.log(visitor); 28 34 } 29 35 30 36 $render(): ts.TypeParameterDeclaration {
+6
packages/openapi-ts/src/ts-dsl/type/prop.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 19 20 super(); 20 21 this.name = name; 21 22 fn(this); 23 + } 24 + 25 + /** Walk this node and its children with a visitor. */ 26 + traverse(visitor: (node: SyntaxNode) => void): void { 27 + console.log(visitor); 22 28 } 23 29 24 30 /** Sets the property type. */
+6
packages/openapi-ts/src/ts-dsl/type/query.ts
··· 1 1 /* eslint-disable @typescript-eslint/no-empty-object-type, @typescript-eslint/no-unsafe-declaration-merging */ 2 + import type { SyntaxNode } from '@hey-api/codegen-core'; 2 3 import ts from 'typescript'; 3 4 4 5 import type { MaybeTsDsl } from '../base'; ··· 15 16 constructor(expr: string | MaybeTsDsl<TypeTsDsl | ts.Expression>) { 16 17 super(); 17 18 this._expr = expr; 19 + } 20 + 21 + /** Walk this node and its children with a visitor. */ 22 + traverse(visitor: (node: SyntaxNode) => void): void { 23 + console.log(visitor); 18 24 } 19 25 20 26 $render(): ts.TypeQueryNode {
+6
packages/openapi-ts/src/ts-dsl/type/template.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import type { MaybeTsDsl } from '../base'; ··· 15 16 add(part: string | MaybeTsDsl<ts.TypeNode>): this { 16 17 this.parts.push(part); 17 18 return this; 19 + } 20 + 21 + /** Walk this node and its children with a visitor. */ 22 + traverse(visitor: (node: SyntaxNode) => void): void { 23 + console.log(visitor); 18 24 } 19 25 20 26 /** Renders a TemplateLiteralTypeNode. */
+6
packages/openapi-ts/src/ts-dsl/type/tuple.ts
··· 1 + import type { SyntaxNode } from '@hey-api/codegen-core'; 1 2 import ts from 'typescript'; 2 3 3 4 import { TypeTsDsl } from '../base'; ··· 13 14 elements(...types: Array<string | ts.TypeNode | TypeTsDsl>): this { 14 15 this._elements.push(...types); 15 16 return this; 17 + } 18 + 19 + /** Walk this node and its children with a visitor. */ 20 + traverse(visitor: (node: SyntaxNode) => void): void { 21 + console.log(visitor); 16 22 } 17 23 18 24 $render(): ts.TupleTypeNode {