From 48636aeacb7eb06520413c13331d826cb2364c83 Mon Sep 17 00:00:00 2001 From: hector Date: Tue, 19 Aug 2025 23:13:09 -0400 Subject: [PATCH 1/5] feat: add ReadMe API Registry utility functions --- .../src/config/__tests__/input.test.ts | 204 ++++++++++++++++++ .../src/utils/__tests__/readme.test.ts | 199 +++++++++++++++++ packages/openapi-ts/src/utils/readme.ts | 73 +++++++ 3 files changed, 476 insertions(+) create mode 100644 packages/openapi-ts/src/config/__tests__/input.test.ts create mode 100644 packages/openapi-ts/src/utils/__tests__/readme.test.ts create mode 100644 packages/openapi-ts/src/utils/readme.ts diff --git a/packages/openapi-ts/src/config/__tests__/input.test.ts b/packages/openapi-ts/src/config/__tests__/input.test.ts new file mode 100644 index 0000000000..96f44d8fc2 --- /dev/null +++ b/packages/openapi-ts/src/config/__tests__/input.test.ts @@ -0,0 +1,204 @@ +import { describe, expect, it } from 'vitest'; + +import type { UserConfig } from '../../types/config'; +import { getInput } from '../input'; + +describe('input config', () => { + describe('getInput', () => { + it('should handle string input', () => { + const userConfig: UserConfig = { + input: 'https://example.com/openapi.yaml', + output: 'src/client', + }; + + const result = getInput(userConfig); + expect(result.path).toBe('https://example.com/openapi.yaml'); + }); + + it('should transform ReadMe simple format input', () => { + const userConfig: UserConfig = { + input: 'readme:abc123', + output: 'src/client', + }; + + const result = getInput(userConfig); + expect(result.path).toBe( + 'https://dash.readme.com/api/v1/api-registry/abc123', + ); + }); + + it('should transform ReadMe full format input', () => { + const userConfig: UserConfig = { + input: 'readme:@myorg/myproject#uuid123', + output: 'src/client', + }; + + const result = getInput(userConfig); + expect(result.path).toBe( + 'https://dash.readme.com/api/v1/api-registry/uuid123', + ); + }); + + it('should handle ReadMe input with hyphens', () => { + const userConfig: UserConfig = { + input: 'readme:@my-org/my-project#test-uuid-123', + output: 'src/client', + }; + + const result = getInput(userConfig); + expect(result.path).toBe( + 'https://dash.readme.com/api/v1/api-registry/test-uuid-123', + ); + }); + + it('should handle object input with ReadMe path', () => { + const userConfig: UserConfig = { + input: { + fetch: { + headers: { + Authorization: 'Bearer token', + }, + }, + path: 'readme:abc123', + }, + output: 'src/client', + }; + + const result = getInput(userConfig); + expect(result.path).toBe( + 'https://dash.readme.com/api/v1/api-registry/abc123', + ); + }); + + it('should handle object input with ReadMe full format path', () => { + const userConfig: UserConfig = { + input: { + path: 'readme:@org/project#uuid', + watch: true, + }, + output: 'src/client', + }; + + const result = getInput(userConfig); + expect(result.path).toBe( + 'https://dash.readme.com/api/v1/api-registry/uuid', + ); + expect(result.watch.enabled).toBe(true); + }); + + it('should handle HeyAPI input format (existing functionality)', () => { + const userConfig: UserConfig = { + input: { + organization: 'myorg', + project: 'myproject', + }, + output: 'src/client', + }; + + const result = getInput(userConfig); + expect(result.path).toBe('https://get.heyapi.dev'); + }); + + it('should handle object input (existing functionality)', () => { + const userConfig: UserConfig = { + input: { + info: { title: 'Test API', version: '1.0.0' }, + openapi: '3.0.0', + }, + output: 'src/client', + }; + + const result = getInput(userConfig); + expect(result.path).toEqual({ + info: { title: 'Test API', version: '1.0.0' }, + openapi: '3.0.0', + }); + }); + + it('should not transform non-ReadMe string inputs', () => { + const inputs = [ + 'https://example.com/openapi.yaml', + './local-file.yaml', + '/absolute/path/to/file.json', + 'file.yaml', + ]; + + inputs.forEach((input) => { + const userConfig: UserConfig = { input, output: 'src/client' }; + const result = getInput(userConfig); + expect(result.path).toBe(input); + }); + }); + + it('should handle watch options with ReadMe inputs', () => { + const userConfig: UserConfig = { + input: 'readme:abc123', + output: 'src/client', + watch: { + enabled: true, + interval: 2000, + }, + }; + + const result = getInput(userConfig); + expect(result.path).toBe( + 'https://dash.readme.com/api/v1/api-registry/abc123', + ); + expect(result.watch.enabled).toBe(true); + expect(result.watch.interval).toBe(2000); + }); + + it('should preserve other input object properties when transforming ReadMe path', () => { + const userConfig: UserConfig = { + input: { + fetch: { + headers: { 'X-Custom': 'value' }, + }, + path: 'readme:test123', + watch: { enabled: true, interval: 1500 }, + }, + output: 'src/client', + }; + + const result = getInput(userConfig); + expect(result.path).toBe( + 'https://dash.readme.com/api/v1/api-registry/test123', + ); + // Note: fetch options are preserved in the input object, not in the result + // The watch options should be processed separately + expect(result.watch.enabled).toBe(true); + expect(result.watch.interval).toBe(1500); + }); + }); + + describe('error handling', () => { + it('should throw error for invalid ReadMe format', () => { + const userConfig: UserConfig = { + input: 'readme:', + output: 'src/client', + }; + + expect(() => getInput(userConfig)).toThrow('Invalid ReadMe input format'); + }); + + it('should throw error for invalid ReadMe UUID', () => { + const userConfig: UserConfig = { + input: 'readme:invalid uuid with spaces', + output: 'src/client', + }; + + expect(() => getInput(userConfig)).toThrow('Invalid ReadMe input format'); + }); + + it('should throw error for invalid ReadMe format in object input', () => { + const userConfig: UserConfig = { + input: { + path: 'readme:@org/project', + }, + output: 'src/client', + }; + + expect(() => getInput(userConfig)).toThrow('Invalid ReadMe input format'); + }); + }); +}); diff --git a/packages/openapi-ts/src/utils/__tests__/readme.test.ts b/packages/openapi-ts/src/utils/__tests__/readme.test.ts new file mode 100644 index 0000000000..a0dc36ab39 --- /dev/null +++ b/packages/openapi-ts/src/utils/__tests__/readme.test.ts @@ -0,0 +1,199 @@ +import { describe, expect, it } from 'vitest'; + +import { + getReadmeApiUrl, + isReadmeInput, + parseReadmeInput, + type ReadmeInput, + transformReadmeInput, +} from '../readme'; + +describe('readme utils', () => { + describe('isReadmeInput', () => { + it('should return true for valid ReadMe formats', () => { + expect(isReadmeInput('readme:abc123')).toBe(true); + expect(isReadmeInput('readme:@org/project#uuid123')).toBe(true); + expect(isReadmeInput('readme:test-uuid-with-hyphens')).toBe(true); + }); + + it('should return false for non-ReadMe inputs', () => { + expect(isReadmeInput('https://example.com')).toBe(false); + expect(isReadmeInput('./local-file.yaml')).toBe(false); + expect(isReadmeInput('random-string')).toBe(false); + expect(isReadmeInput('')).toBe(false); + expect(isReadmeInput('readme')).toBe(false); + expect(isReadmeInput('readmeabc123')).toBe(false); + }); + + it('should handle non-string inputs', () => { + expect(isReadmeInput(123 as any)).toBe(false); + expect(isReadmeInput(null as any)).toBe(false); + expect(isReadmeInput(undefined as any)).toBe(false); + expect(isReadmeInput({} as any)).toBe(false); + }); + }); + + describe('parseReadmeInput', () => { + it('should parse simple UUID format', () => { + const result = parseReadmeInput('readme:abc123'); + expect(result).toEqual({ uuid: 'abc123' }); + }); + + it('should parse UUID with hyphens', () => { + const result = parseReadmeInput('readme:test-uuid-123'); + expect(result).toEqual({ uuid: 'test-uuid-123' }); + }); + + it('should parse full format with organization and project', () => { + const result = parseReadmeInput('readme:@myorg/myproject#uuid123'); + expect(result).toEqual({ + organization: 'myorg', + project: 'myproject', + uuid: 'uuid123', + }); + }); + + it('should parse organization and project with hyphens', () => { + const result = parseReadmeInput('readme:@my-org/my-project#test-uuid'); + expect(result).toEqual({ + organization: 'my-org', + project: 'my-project', + uuid: 'test-uuid', + }); + }); + + it('should throw error for invalid formats', () => { + expect(() => parseReadmeInput('readme:')).toThrow( + 'Invalid ReadMe input format', + ); + expect(() => parseReadmeInput('readme:@org')).toThrow( + 'Invalid ReadMe input format', + ); + expect(() => parseReadmeInput('readme:@org/project')).toThrow( + 'Invalid ReadMe input format', + ); + expect(() => parseReadmeInput('readme:@org/project#')).toThrow( + 'Invalid ReadMe input format', + ); + expect(() => parseReadmeInput('https://example.com')).toThrow( + 'Invalid ReadMe input format', + ); + }); + + it('should throw error for invalid UUID characters', () => { + expect(() => parseReadmeInput('readme:abc@123')).toThrow( + 'Invalid ReadMe input format', + ); + expect(() => parseReadmeInput('readme:abc/123')).toThrow( + 'Invalid ReadMe input format', + ); + expect(() => parseReadmeInput('readme:abc#123')).toThrow( + 'Invalid ReadMe input format', + ); + expect(() => parseReadmeInput('readme:abc 123')).toThrow( + 'Invalid ReadMe input format', + ); + }); + + it('should handle empty UUID', () => { + expect(() => parseReadmeInput('readme:@org/project#')).toThrow( + 'Invalid ReadMe input format', + ); + }); + }); + + describe('getReadmeApiUrl', () => { + it('should generate correct API URL', () => { + expect(getReadmeApiUrl('abc123')).toBe( + 'https://dash.readme.com/api/v1/api-registry/abc123', + ); + expect(getReadmeApiUrl('test-uuid-with-hyphens')).toBe( + 'https://dash.readme.com/api/v1/api-registry/test-uuid-with-hyphens', + ); + }); + }); + + describe('transformReadmeInput', () => { + it('should transform simple UUID format to API URL', () => { + const result = transformReadmeInput('readme:abc123'); + expect(result).toBe('https://dash.readme.com/api/v1/api-registry/abc123'); + }); + + it('should transform full format to API URL', () => { + const result = transformReadmeInput('readme:@myorg/myproject#uuid123'); + expect(result).toBe( + 'https://dash.readme.com/api/v1/api-registry/uuid123', + ); + }); + + it('should throw error for invalid inputs', () => { + expect(() => transformReadmeInput('invalid')).toThrow( + 'Invalid ReadMe input format', + ); + expect(() => transformReadmeInput('readme:')).toThrow( + 'Invalid ReadMe input format', + ); + }); + }); + + describe('integration scenarios', () => { + const validInputs: Array<{ expected: ReadmeInput; input: string }> = [ + { expected: { uuid: 'simple123' }, input: 'readme:simple123' }, + { + expected: { uuid: 'uuid-with-hyphens' }, + input: 'readme:uuid-with-hyphens', + }, + { expected: { uuid: 'UUID123' }, input: 'readme:UUID123' }, + { + expected: { organization: 'org', project: 'proj', uuid: 'uuid' }, + input: 'readme:@org/proj#uuid', + }, + { + expected: { + organization: 'my-org', + project: 'my-project', + uuid: 'my-uuid', + }, + input: 'readme:@my-org/my-project#my-uuid', + }, + ]; + + it.each(validInputs)( + 'should handle $input correctly', + ({ expected, input }) => { + expect(isReadmeInput(input)).toBe(true); + expect(parseReadmeInput(input)).toEqual(expected); + expect(transformReadmeInput(input)).toBe( + `https://dash.readme.com/api/v1/api-registry/${expected.uuid}`, + ); + }, + ); + + const invalidInputs = [ + 'readme:', + 'readme:@', + 'readme:@org', + 'readme:@org/', + 'readme:@org/proj', + 'readme:@org/proj#', + 'readme:uuid with spaces', + 'readme:uuid@invalid', + 'readme:uuid/invalid', + 'readme:uuid#invalid', + 'https://example.com', + './local-file.yaml', + 'random-string', + '', + ]; + + it.each(invalidInputs)('should reject invalid input: %s', (input) => { + if (isReadmeInput(input)) { + expect(() => parseReadmeInput(input)).toThrow(); + } else { + expect(() => parseReadmeInput(input)).toThrow( + 'Invalid ReadMe input format', + ); + } + }); + }); +}); diff --git a/packages/openapi-ts/src/utils/readme.ts b/packages/openapi-ts/src/utils/readme.ts new file mode 100644 index 0000000000..583d276f61 --- /dev/null +++ b/packages/openapi-ts/src/utils/readme.ts @@ -0,0 +1,73 @@ +// Regular expression to match ReadMe input formats: +// readme:@organization/project#uuid or readme:uuid +const readmeInputRegExp = /^readme:(?:@([\w-]+)\/([\w-]+)#)?([\w-]+)$/; + +export interface ReadmeInput { + organization?: string; + project?: string; + uuid: string; +} + +/** + * Checks if the input string is a ReadMe format + * @param input - The input string to check + * @returns true if the input matches ReadMe format patterns + */ +export const isReadmeInput = (input: string): boolean => + typeof input === 'string' && input.startsWith('readme:'); + +/** + * Parses a ReadMe input string and extracts components + * @param input - ReadMe format string (readme:@org/project#uuid or readme:uuid) + * @returns Parsed ReadMe input components + * @throws Error if the input format is invalid + */ +export const parseReadmeInput = (input: string): ReadmeInput => { + if (!isReadmeInput(input)) { + throw new Error( + `Invalid ReadMe input format. Expected "readme:@organization/project#uuid" or "readme:uuid", received: ${input}`, + ); + } + + const match = input.match(readmeInputRegExp); + + if (!match) { + throw new Error( + `Invalid ReadMe input format. Expected "readme:@organization/project#uuid" or "readme:uuid", received: ${input}`, + ); + } + + const [, organization, project, uuid] = match; + + // Validate UUID format (basic validation for alphanumeric + hyphens) + if (!uuid || !/^[\w-]+$/.test(uuid)) { + throw new Error(`Invalid UUID format: ${uuid}`); + } + + const result: ReadmeInput = { uuid }; + + if (organization && project) { + result.organization = organization; + result.project = project; + } + + return result; +}; + +/** + * Generates the ReadMe API Registry URL for a given UUID + * @param uuid - The ReadMe API Registry UUID + * @returns The full API URL + */ +export const getReadmeApiUrl = (uuid: string): string => + `https://dash.readme.com/api/v1/api-registry/${uuid}`; + +/** + * Transforms a ReadMe input string to the corresponding API URL + * @param input - ReadMe format string + * @returns The ReadMe API Registry URL + */ +export const transformReadmeInput = (input: string): string => { + const parsed = parseReadmeInput(input); + return getReadmeApiUrl(parsed.uuid); +}; From 1a35b7795683d40093e4bed626163ba93f22e439 Mon Sep 17 00:00:00 2001 From: hector Date: Tue, 19 Aug 2025 23:17:00 -0400 Subject: [PATCH 2/5] feat: integrate ReadMe input format in configuration --- packages/openapi-ts/src/config/input.ts | 13 ++++++++++++- packages/openapi-ts/src/types/config.d.ts | 10 ++++++++-- packages/openapi-ts/src/types/input.d.ts | 10 ++++++++-- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/packages/openapi-ts/src/config/input.ts b/packages/openapi-ts/src/config/input.ts index 02ef5c758d..0b54e7802b 100644 --- a/packages/openapi-ts/src/config/input.ts +++ b/packages/openapi-ts/src/config/input.ts @@ -1,4 +1,5 @@ import type { Config, UserConfig } from '../types/config'; +import { isReadmeInput, transformReadmeInput } from '../utils/readme'; const defaultWatch: Config['input']['watch'] = { enabled: false, @@ -38,7 +39,12 @@ export const getInput = (userConfig: UserConfig): Config['input'] => { }; if (typeof userConfig.input === 'string') { - input.path = userConfig.input; + // Handle ReadMe input format transformation + if (isReadmeInput(userConfig.input)) { + input.path = transformReadmeInput(userConfig.input); + } else { + input.path = userConfig.input; + } } else if ( userConfig.input && (userConfig.input.path !== undefined || @@ -51,6 +57,11 @@ export const getInput = (userConfig: UserConfig): Config['input'] => { ...userConfig.input, }; + // Handle ReadMe input format transformation when path is specified + if (typeof input.path === 'string' && isReadmeInput(input.path)) { + input.path = transformReadmeInput(input.path); + } + // watch only remote files if (input.watch !== undefined) { input.watch = getWatch(input); diff --git a/packages/openapi-ts/src/types/config.d.ts b/packages/openapi-ts/src/types/config.d.ts index 460079172b..878003dee3 100644 --- a/packages/openapi-ts/src/types/config.d.ts +++ b/packages/openapi-ts/src/types/config.d.ts @@ -18,14 +18,20 @@ export interface UserConfig { */ dryRun?: boolean; /** - * Path to the OpenAPI specification. This can be either local or remote path. + * Path to the OpenAPI specification. This can be either: + * - local file + *. - remote path + * - ReadMe API Registry UUID (full and simplified formats) + * * Both JSON and YAML file formats are supported. You can also pass the parsed * object directly if you're fetching the file yourself. * * Alternatively, you can define a configuration object with more options. */ input: - | 'https://get.heyapi.dev//' + | `https://get.heyapi.dev/${string}/${string}` + | `readme:@${string}/${string}#${string}` + | `readme:${string}` | (string & {}) | (Record & { path?: never }) | Input; diff --git a/packages/openapi-ts/src/types/input.d.ts b/packages/openapi-ts/src/types/input.d.ts index 7341294fb1..6f051091c0 100644 --- a/packages/openapi-ts/src/types/input.d.ts +++ b/packages/openapi-ts/src/types/input.d.ts @@ -36,12 +36,18 @@ export type Input = { */ organization?: string; /** - * Path to the OpenAPI specification. This can be either local or remote path. + * Path to the OpenAPI specification. This can be either: + * - local file + *. - remote path + * - ReadMe API Registry UUID (full and simplified formats) + * * Both JSON and YAML file formats are supported. You can also pass the parsed * object directly if you're fetching the file yourself. */ path?: - | 'https://get.heyapi.dev//' + | `https://get.heyapi.dev/${string}/${string}` + | `readme:@${string}/${string}#${string}` + | `readme:${string}` | (string & {}) | Record; /** From dbd0a6a33ba80c41b74c88ce4e179fa50c22fd35 Mon Sep 17 00:00:00 2001 From: hector Date: Tue, 19 Aug 2025 23:18:36 -0400 Subject: [PATCH 3/5] docs: update documentation for ReadMe API Registry support --- docs/openapi-ts/configuration/input.md | 36 +++ .../openapi-ts-openai/src/client/types.gen.ts | 232 +++++++++--------- 2 files changed, 152 insertions(+), 116 deletions(-) diff --git a/docs/openapi-ts/configuration/input.md b/docs/openapi-ts/configuration/input.md index ad4e65b70e..000ad7f08b 100644 --- a/docs/openapi-ts/configuration/input.md +++ b/docs/openapi-ts/configuration/input.md @@ -52,6 +52,42 @@ export default { If you use an HTTPS URL with a self-signed certificate in development, you will need to set [`NODE_TLS_REJECT_UNAUTHORIZED=0`](https://github.com/hey-api/openapi-ts/issues/276#issuecomment-2043143501) in your environment. ::: +### ReadMe API Registry + +You can use ReadMe API Registry UUIDs to fetch OpenAPI specifications directly from ReadMe's platform. This is useful when API providers use ReadMe as their source of truth for API documentation. + +::: code-group + +```js [simple format] +export default { + input: 'readme:abc123def456', // [!code ++] +}; +``` + +```js [full format] +export default { + input: 'readme:@organization/project#abc123def456', // [!code ++] +}; +``` + +```js [object format] +export default { + input: { + path: 'readme:abc123def456', // [!code ++] + // ...other options + }, +}; +``` + +::: + +The ReadMe input formats are: + +- `readme:uuid` - Simple format using only the UUID +- `readme:@organization/project#uuid` - Full format including organization and project names + +Both formats will fetch the OpenAPI specification from `https://dash.readme.com/api/v1/api-registry/{uuid}`. + ### Hey API Platform options You might want to use the [Hey API Platform](/openapi-ts/integrations) to store your specifications. If you do so, the `input` object provides options to help with constructing the correct URL. diff --git a/examples/openapi-ts-openai/src/client/types.gen.ts b/examples/openapi-ts-openai/src/client/types.gen.ts index 9cbdacdb4e..78630ab514 100644 --- a/examples/openapi-ts-openai/src/client/types.gen.ts +++ b/examples/openapi-ts-openai/src/client/types.gen.ts @@ -194,48 +194,48 @@ export type AssistantStreamEvent = } & ErrorEvent); export const AssistantSupportedModels = { + GPT_3_5_TURBO: 'gpt-3.5-turbo', + GPT_3_5_TURBO_0125: 'gpt-3.5-turbo-0125', + GPT_3_5_TURBO_0613: 'gpt-3.5-turbo-0613', + GPT_3_5_TURBO_1106: 'gpt-3.5-turbo-1106', + GPT_3_5_TURBO_16K: 'gpt-3.5-turbo-16k', + GPT_3_5_TURBO_16K_0613: 'gpt-3.5-turbo-16k-0613', + GPT_4: 'gpt-4', GPT_4O: 'gpt-4o', GPT_4O_2024_05_13: 'gpt-4o-2024-05-13', GPT_4O_2024_08_06: 'gpt-4o-2024-08-06', GPT_4O_2024_11_20: 'gpt-4o-2024-11-20', - GPT_4_1: 'gpt-4.1', GPT_4O_MINI: 'gpt-4o-mini', - GPT_4_1_2025_04_14: 'gpt-4.1-2025-04-14', GPT_4O_MINI_2024_07_18: 'gpt-4o-mini-2024-07-18', - GPT_4_1_MINI: 'gpt-4.1-mini', GPT_4_0125_PREVIEW: 'gpt-4-0125-preview', - GPT_4_1_MINI_2025_04_14: 'gpt-4.1-mini-2025-04-14', - GPT_4: 'gpt-4', - GPT_4_1_NANO: 'gpt-4.1-nano', GPT_4_0314: 'gpt-4-0314', - GPT_5: 'gpt-5', GPT_4_0613: 'gpt-4-0613', - GPT_5_2025_08_07: 'gpt-5-2025-08-07', - GPT_3_5_TURBO: 'gpt-3.5-turbo', - GPT_5_MINI: 'gpt-5-mini', - GPT_3_5_TURBO_0613: 'gpt-3.5-turbo-0613', - GPT_5_MINI_2025_08_07: 'gpt-5-mini-2025-08-07', - GPT_3_5_TURBO_0125: 'gpt-3.5-turbo-0125', - GPT_5_NANO: 'gpt-5-nano', - GPT_3_5_TURBO_1106: 'gpt-3.5-turbo-1106', - GPT_3_5_TURBO_16K: 'gpt-3.5-turbo-16k', - GPT_5_NANO_2025_08_07: 'gpt-5-nano-2025-08-07', - GPT_3_5_TURBO_16K_0613: 'gpt-3.5-turbo-16k-0613', - GPT_4_1_NANO_2025_04_14: 'gpt-4.1-nano-2025-04-14', + GPT_4_1: 'gpt-4.1', GPT_4_1106_PREVIEW: 'gpt-4-1106-preview', - O1: 'o1', + GPT_4_1_2025_04_14: 'gpt-4.1-2025-04-14', + GPT_4_1_MINI: 'gpt-4.1-mini', + GPT_4_1_MINI_2025_04_14: 'gpt-4.1-mini-2025-04-14', + GPT_4_1_NANO: 'gpt-4.1-nano', + GPT_4_1_NANO_2025_04_14: 'gpt-4.1-nano-2025-04-14', GPT_4_32K: 'gpt-4-32k', - O3_MINI: 'o3-mini', GPT_4_32K_0314: 'gpt-4-32k-0314', - O3_MINI_2025_01_31: 'o3-mini-2025-01-31', GPT_4_32K_0613: 'gpt-4-32k-0613', - O1_2024_12_17: 'o1-2024-12-17', GPT_4_5_PREVIEW: 'gpt-4.5-preview', GPT_4_5_PREVIEW_2025_02_27: 'gpt-4.5-preview-2025-02-27', GPT_4_TURBO: 'gpt-4-turbo', GPT_4_TURBO_2024_04_09: 'gpt-4-turbo-2024-04-09', GPT_4_TURBO_PREVIEW: 'gpt-4-turbo-preview', GPT_4_VISION_PREVIEW: 'gpt-4-vision-preview', + GPT_5: 'gpt-5', + GPT_5_2025_08_07: 'gpt-5-2025-08-07', + GPT_5_MINI: 'gpt-5-mini', + GPT_5_MINI_2025_08_07: 'gpt-5-mini-2025-08-07', + GPT_5_NANO: 'gpt-5-nano', + GPT_5_NANO_2025_08_07: 'gpt-5-nano-2025-08-07', + O1: 'o1', + O1_2024_12_17: 'o1-2024-12-17', + O3_MINI: 'o3-mini', + O3_MINI_2025_01_31: 'o3-mini-2025-01-31', } as const; export type AssistantSupportedModels = @@ -702,38 +702,58 @@ export type AuditLog = { /** * The details for events with this `type`. */ - 'user.added'?: { - /** - * The user ID. - */ - id?: string; + 'rate_limit.updated'?: { /** - * The payload used to add the user to the project. + * The payload used to update the rate limits. */ - data?: { + changes_requested?: { /** - * The role of the user. Is either `owner` or `member`. + * The maximum batch input tokens per day. Only relevant for certain models. */ - role?: string; + batch_1_day_max_input_tokens?: number; + /** + * The maximum audio megabytes per minute. Only relevant for certain models. + */ + max_audio_megabytes_per_1_minute?: number; + /** + * The maximum images per minute. Only relevant for certain models. + */ + max_images_per_1_minute?: number; + /** + * The maximum requests per day. Only relevant for certain models. + */ + max_requests_per_1_day?: number; + /** + * The maximum requests per minute. + */ + max_requests_per_1_minute?: number; + /** + * The maximum tokens per minute. + */ + max_tokens_per_1_minute?: number; }; + /** + * The rate limit ID + */ + id?: string; }; /** * The details for events with this `type`. */ - 'user.updated'?: { - /** - * The project ID. - */ - id?: string; + 'service_account.created'?: { /** - * The payload used to update the user. + * The payload used to create the service account. */ - changes_requested?: { + data?: { /** - * The role of the user. Is either `owner` or `member`. + * The role of the service account. Is either `owner` or `member`. */ role?: string; }; + /** + * The service account ID. + */ + id?: string; }; /** * The details for events with this `type`. @@ -762,69 +782,49 @@ export type AuditLog = { */ id?: string; }; + type: AuditLogEventType; /** * The details for events with this `type`. */ - 'rate_limit.updated'?: { + 'user.added'?: { /** - * The payload used to update the rate limits. + * The payload used to add the user to the project. */ - changes_requested?: { - /** - * The maximum requests per minute. - */ - max_requests_per_1_minute?: number; - /** - * The maximum tokens per minute. - */ - max_tokens_per_1_minute?: number; - /** - * The maximum images per minute. Only relevant for certain models. - */ - max_images_per_1_minute?: number; - /** - * The maximum audio megabytes per minute. Only relevant for certain models. - */ - max_audio_megabytes_per_1_minute?: number; - /** - * The maximum requests per day. Only relevant for certain models. - */ - max_requests_per_1_day?: number; + data?: { /** - * The maximum batch input tokens per day. Only relevant for certain models. + * The role of the user. Is either `owner` or `member`. */ - batch_1_day_max_input_tokens?: number; + role?: string; }; /** - * The rate limit ID + * The user ID. */ id?: string; }; - type: AuditLogEventType; /** * The details for events with this `type`. */ - 'service_account.created'?: { - /** - * The payload used to create the service account. - */ - data?: { - /** - * The role of the service account. Is either `owner` or `member`. - */ - role?: string; - }; + 'user.deleted'?: { /** - * The service account ID. + * The user ID. */ id?: string; }; /** * The details for events with this `type`. */ - 'user.deleted'?: { + 'user.updated'?: { /** - * The user ID. + * The payload used to update the user. + */ + changes_requested?: { + /** + * The role of the user. Is either `owner` or `member`. + */ + role?: string; + }; + /** + * The project ID. */ id?: string; }; @@ -18135,54 +18135,29 @@ export type MessageContentDelta = } & MessageDeltaContentImageUrlObject); export const ChatModel = { - GPT_4_1: 'gpt-4.1', - GPT_4_1_2025_04_14: 'gpt-4.1-2025-04-14', - GPT_4_1_MINI: 'gpt-4.1-mini', - GPT_4_1_MINI_2025_04_14: 'gpt-4.1-mini-2025-04-14', - GPT_4_1_NANO: 'gpt-4.1-nano', + CHATGPT_4O_LATEST: 'chatgpt-4o-latest', + CODEX_MINI_LATEST: 'codex-mini-latest', + GPT_3_5_TURBO: 'gpt-3.5-turbo', + GPT_3_5_TURBO_0125: 'gpt-3.5-turbo-0125', + GPT_3_5_TURBO_0301: 'gpt-3.5-turbo-0301', + GPT_3_5_TURBO_0613: 'gpt-3.5-turbo-0613', + GPT_3_5_TURBO_1106: 'gpt-3.5-turbo-1106', + GPT_3_5_TURBO_16K: 'gpt-3.5-turbo-16k', + GPT_3_5_TURBO_16K_0613: 'gpt-3.5-turbo-16k-0613', + GPT_4: 'gpt-4', GPT_4O: 'gpt-4o', - GPT_4_1_NANO_2025_04_14: 'gpt-4.1-nano-2025-04-14', - GPT_4O_2024_08_06: 'gpt-4o-2024-08-06', - GPT_5: 'gpt-5', GPT_4O_2024_05_13: 'gpt-4o-2024-05-13', - GPT_5_2025_08_07: 'gpt-5-2025-08-07', + GPT_4O_2024_08_06: 'gpt-4o-2024-08-06', GPT_4O_2024_11_20: 'gpt-4o-2024-11-20', - GPT_5_CHAT_LATEST: 'gpt-5-chat-latest', GPT_4O_AUDIO_PREVIEW: 'gpt-4o-audio-preview', - GPT_5_MINI: 'gpt-5-mini', GPT_4O_AUDIO_PREVIEW_2024_10_01: 'gpt-4o-audio-preview-2024-10-01', - GPT_5_MINI_2025_08_07: 'gpt-5-mini-2025-08-07', GPT_4O_AUDIO_PREVIEW_2024_12_17: 'gpt-4o-audio-preview-2024-12-17', - GPT_5_NANO: 'gpt-5-nano', GPT_4O_AUDIO_PREVIEW_2025_06_03: 'gpt-4o-audio-preview-2025-06-03', - GPT_5_NANO_2025_08_07: 'gpt-5-nano-2025-08-07', - CHATGPT_4O_LATEST: 'chatgpt-4o-latest', - O1: 'o1', - CODEX_MINI_LATEST: 'codex-mini-latest', - O1_2024_12_17: 'o1-2024-12-17', GPT_4O_MINI: 'gpt-4o-mini', - O1_MINI: 'o1-mini', GPT_4O_MINI_2024_07_18: 'gpt-4o-mini-2024-07-18', - O3: 'o3', - GPT_4: 'gpt-4', - O3_2025_04_16: 'o3-2025-04-16', GPT_4O_MINI_AUDIO_PREVIEW: 'gpt-4o-mini-audio-preview', - O4_MINI: 'o4-mini', GPT_4O_MINI_AUDIO_PREVIEW_2024_12_17: 'gpt-4o-mini-audio-preview-2024-12-17', - O4_MINI_2025_04_16: 'o4-mini-2025-04-16', - GPT_3_5_TURBO: 'gpt-3.5-turbo', - O3_MINI: 'o3-mini', - GPT_3_5_TURBO_0301: 'gpt-3.5-turbo-0301', - O3_MINI_2025_01_31: 'o3-mini-2025-01-31', - GPT_3_5_TURBO_0613: 'gpt-3.5-turbo-0613', - O1_PREVIEW: 'o1-preview', - GPT_3_5_TURBO_0125: 'gpt-3.5-turbo-0125', - O1_PREVIEW_2024_09_12: 'o1-preview-2024-09-12', - GPT_3_5_TURBO_1106: 'gpt-3.5-turbo-1106', - O1_MINI_2024_09_12: 'o1-mini-2024-09-12', - GPT_3_5_TURBO_16K: 'gpt-3.5-turbo-16k', GPT_4O_MINI_SEARCH_PREVIEW: 'gpt-4o-mini-search-preview', - GPT_3_5_TURBO_16K_0613: 'gpt-3.5-turbo-16k-0613', GPT_4O_MINI_SEARCH_PREVIEW_2025_03_11: 'gpt-4o-mini-search-preview-2025-03-11', GPT_4O_SEARCH_PREVIEW: 'gpt-4o-search-preview', @@ -18190,7 +18165,13 @@ export const ChatModel = { GPT_4_0125_PREVIEW: 'gpt-4-0125-preview', GPT_4_0314: 'gpt-4-0314', GPT_4_0613: 'gpt-4-0613', + GPT_4_1: 'gpt-4.1', GPT_4_1106_PREVIEW: 'gpt-4-1106-preview', + GPT_4_1_2025_04_14: 'gpt-4.1-2025-04-14', + GPT_4_1_MINI: 'gpt-4.1-mini', + GPT_4_1_MINI_2025_04_14: 'gpt-4.1-mini-2025-04-14', + GPT_4_1_NANO: 'gpt-4.1-nano', + GPT_4_1_NANO_2025_04_14: 'gpt-4.1-nano-2025-04-14', GPT_4_32K: 'gpt-4-32k', GPT_4_32K_0314: 'gpt-4-32k-0314', GPT_4_32K_0613: 'gpt-4-32k-0613', @@ -18198,6 +18179,25 @@ export const ChatModel = { GPT_4_TURBO_2024_04_09: 'gpt-4-turbo-2024-04-09', GPT_4_TURBO_PREVIEW: 'gpt-4-turbo-preview', GPT_4_VISION_PREVIEW: 'gpt-4-vision-preview', + GPT_5: 'gpt-5', + GPT_5_2025_08_07: 'gpt-5-2025-08-07', + GPT_5_CHAT_LATEST: 'gpt-5-chat-latest', + GPT_5_MINI: 'gpt-5-mini', + GPT_5_MINI_2025_08_07: 'gpt-5-mini-2025-08-07', + GPT_5_NANO: 'gpt-5-nano', + GPT_5_NANO_2025_08_07: 'gpt-5-nano-2025-08-07', + O1: 'o1', + O1_2024_12_17: 'o1-2024-12-17', + O1_MINI: 'o1-mini', + O1_MINI_2024_09_12: 'o1-mini-2024-09-12', + O1_PREVIEW: 'o1-preview', + O1_PREVIEW_2024_09_12: 'o1-preview-2024-09-12', + O3: 'o3', + O3_2025_04_16: 'o3-2025-04-16', + O3_MINI: 'o3-mini', + O3_MINI_2025_01_31: 'o3-mini-2025-01-31', + O4_MINI: 'o4-mini', + O4_MINI_2025_04_16: 'o4-mini-2025-04-16', } as const; export type ChatModel = (typeof ChatModel)[keyof typeof ChatModel]; From 77c54c75856c696b4162360bf1cda9a76a8f13f2 Mon Sep 17 00:00:00 2001 From: hector Date: Tue, 19 Aug 2025 23:25:33 -0400 Subject: [PATCH 4/5] chore: fix typos in comments --- packages/openapi-ts/src/types/config.d.ts | 2 +- packages/openapi-ts/src/types/input.d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/openapi-ts/src/types/config.d.ts b/packages/openapi-ts/src/types/config.d.ts index 878003dee3..badda21182 100644 --- a/packages/openapi-ts/src/types/config.d.ts +++ b/packages/openapi-ts/src/types/config.d.ts @@ -20,7 +20,7 @@ export interface UserConfig { /** * Path to the OpenAPI specification. This can be either: * - local file - *. - remote path + * - remote path * - ReadMe API Registry UUID (full and simplified formats) * * Both JSON and YAML file formats are supported. You can also pass the parsed diff --git a/packages/openapi-ts/src/types/input.d.ts b/packages/openapi-ts/src/types/input.d.ts index 6f051091c0..3e68a00463 100644 --- a/packages/openapi-ts/src/types/input.d.ts +++ b/packages/openapi-ts/src/types/input.d.ts @@ -38,7 +38,7 @@ export type Input = { /** * Path to the OpenAPI specification. This can be either: * - local file - *. - remote path + * - remote path * - ReadMe API Registry UUID (full and simplified formats) * * Both JSON and YAML file formats are supported. You can also pass the parsed From e074a3600701badc7f220b283a55188dc85a5572 Mon Sep 17 00:00:00 2001 From: Lubos Date: Wed, 20 Aug 2025 17:48:08 +0800 Subject: [PATCH 5/5] Create soft-wolves-develop.md --- .changeset/soft-wolves-develop.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/soft-wolves-develop.md diff --git a/.changeset/soft-wolves-develop.md b/.changeset/soft-wolves-develop.md new file mode 100644 index 0000000000..457a104b66 --- /dev/null +++ b/.changeset/soft-wolves-develop.md @@ -0,0 +1,5 @@ +--- +"@hey-api/openapi-ts": patch +--- + +feat(parser): input supports ReadMe API Registry with `readme:` prefix