diff --git a/packages/rtk-query-codegen-openapi/src/index.ts b/packages/rtk-query-codegen-openapi/src/index.ts index 41a251d63d..7b68762719 100644 --- a/packages/rtk-query-codegen-openapi/src/index.ts +++ b/packages/rtk-query-codegen-openapi/src/index.ts @@ -8,6 +8,14 @@ export type { ConfigFile } from './types'; const require = createRequire(__filename); +export async function generateEndpoints( + options: Omit & { outputFile?: never } +): Promise; + +export async function generateEndpoints( + options: Omit & Required> +): Promise; + export async function generateEndpoints(options: GenerationOptions): Promise { const schemaLocation = options.schemaFile; diff --git a/packages/rtk-query-codegen-openapi/test/generateEndpoints.test-d.ts b/packages/rtk-query-codegen-openapi/test/generateEndpoints.test-d.ts new file mode 100644 index 0000000000..2d4ba28bc4 --- /dev/null +++ b/packages/rtk-query-codegen-openapi/test/generateEndpoints.test-d.ts @@ -0,0 +1,31 @@ +import { generateEndpoints } from '@rtk-query/codegen-openapi'; +import * as path from 'node:path'; + +const withoutOutputFile = { + apiFile: './fixtures/emptyApi.ts', + schemaFile: path.join(__dirname, 'fixtures', 'petstore.json'), +}; + +const withOutputFile = { + apiFile: './fixtures/emptyApi.ts', + outputFile: './test/tmp/out.ts', + schemaFile: path.join(__dirname, 'fixtures', 'petstore.json'), +}; + +describe('generateEndpoints return type narrowing', () => { + test('narrows to Promise when outputFile is omitted', () => { + expectTypeOf(generateEndpoints(withoutOutputFile)).toEqualTypeOf>(); + + expectTypeOf(generateEndpoints(withoutOutputFile)).resolves.toBeString(); + + expectTypeOf(generateEndpoints).toBeCallableWith(withoutOutputFile).returns.resolves.toBeString(); + }); + + test('narrows to Promise when outputFile is provided', () => { + expectTypeOf(generateEndpoints(withOutputFile)).toEqualTypeOf>(); + + expectTypeOf(generateEndpoints(withOutputFile)).resolves.toBeVoid(); + + expectTypeOf(generateEndpoints).toBeCallableWith(withOutputFile).returns.resolves.toBeVoid(); + }); +}); diff --git a/packages/rtk-query-codegen-openapi/test/generateEndpoints.test.ts b/packages/rtk-query-codegen-openapi/test/generateEndpoints.test.ts index 20c895219d..c452a4253b 100644 --- a/packages/rtk-query-codegen-openapi/test/generateEndpoints.test.ts +++ b/packages/rtk-query-codegen-openapi/test/generateEndpoints.test.ts @@ -933,3 +933,26 @@ describe('esmExtensions option', () => { expect(content).toContain("import { api } from '../../fixtures/emptyApi'"); }); }); + +describe('generateEndpoints return type narrowing', () => { + const schemaFile = resolve(__dirname, 'fixtures', 'petstore.json'); + + test('returns a string when outputFile is omitted', async () => { + const result = await generateEndpoints({ + apiFile: './fixtures/emptyApi.ts', + schemaFile, + }); + + expect(result).toBeTypeOf('string'); + }); + + test('returns void when outputFile is provided', async () => { + const result = await generateEndpoints({ + apiFile: './fixtures/emptyApi.ts', + outputFile: './test/tmp/out.ts', + schemaFile, + }); + + expect(result).toBeUndefined(); + }); +}); diff --git a/packages/rtk-query-codegen-openapi/vitest.config.mts b/packages/rtk-query-codegen-openapi/vitest.config.mts index de73ff27d2..d411d934b9 100644 --- a/packages/rtk-query-codegen-openapi/vitest.config.mts +++ b/packages/rtk-query-codegen-openapi/vitest.config.mts @@ -1,23 +1,42 @@ -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; +import * as path from 'node:path'; import tsconfigPaths from 'vite-tsconfig-paths'; import { defineConfig } from 'vitest/config'; - -// No __dirname under Node ESM -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); +import packageJson from './package.json' with { type: 'json' }; export default defineConfig({ - plugins: [tsconfigPaths({ projects: ['./tsconfig.json'] })], + plugins: [ + tsconfigPaths({ + configNames: ['tsconfig.json'], + projects: ['./tsconfig.json'], + root: import.meta.dirname, + }), + ], + + root: import.meta.dirname, + test: { + name: { + label: packageJson.name, + }, + alias: process.env.TEST_DIST ? { - '@rtk-query/codegen-openapi': path.join(__dirname, '../..', 'node_modules/@rtk-query/codegen-openapi'), + '@rtk-query/codegen-openapi': path.join(import.meta.dirname, '..', '..', 'node_modules', packageJson.name), } : undefined, + + dir: path.join(import.meta.dirname, 'test'), + root: import.meta.dirname, testTimeout: 10_000, + + typecheck: { + enabled: true, + tsconfig: path.join(import.meta.dirname, 'tsconfig.json'), + }, + pool: 'forks', globals: true, setupFiles: ['./test/vitest.setup.ts'], + watch: false, }, }); diff --git a/yarn.lock b/yarn.lock index 98e3fb4c30..65d31d73da 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10230,27 +10230,27 @@ __metadata: languageName: node linkType: hard -"@vitest/expect@npm:4.0.4": - version: 4.0.4 - resolution: "@vitest/expect@npm:4.0.4" +"@vitest/expect@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/expect@npm:4.0.18" dependencies: "@standard-schema/spec": "npm:^1.0.0" "@types/chai": "npm:^5.2.2" - "@vitest/spy": "npm:4.0.4" - "@vitest/utils": "npm:4.0.4" - chai: "npm:^6.0.1" + "@vitest/spy": "npm:4.0.18" + "@vitest/utils": "npm:4.0.18" + chai: "npm:^6.2.1" tinyrainbow: "npm:^3.0.3" - checksum: 10/7d6f4e501c5b84c63fd99259a2b0000b81b075fd62c1a4ff479c50136d46d6cf90bcdd514f6304bf972fbba148949fda23ebd2926fa26f0fd428f1010f1cff63 + checksum: 10/2115bff1bbcad460ce72032022e4dbcf8572c4b0fe07ca60f5644a8d96dd0dfa112986b5a1a5c5705f4548119b3b829c45d1de0838879211e0d6bb276b4ece73 languageName: node linkType: hard -"@vitest/mocker@npm:4.0.4": - version: 4.0.4 - resolution: "@vitest/mocker@npm:4.0.4" +"@vitest/mocker@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/mocker@npm:4.0.18" dependencies: - "@vitest/spy": "npm:4.0.4" + "@vitest/spy": "npm:4.0.18" estree-walker: "npm:^3.0.3" - magic-string: "npm:^0.30.19" + magic-string: "npm:^0.30.21" peerDependencies: msw: ^2.4.9 vite: ^6.0.0 || ^7.0.0-0 @@ -10259,54 +10259,54 @@ __metadata: optional: true vite: optional: true - checksum: 10/070ddbd7f9907482aa1812e01d13ff66cea540479435a857072fc7528f4b583d62f0600eed112b5780e9698812c944b679fc959e764670de23621eba9be9e177 + checksum: 10/46f584a4c1180dfb513137bc8db6e2e3b53e141adfe964307297e98321652d86a3f2a52d80cda1f810205bd5fdcab789bb8b52a532e68f175ef1e20be398218d languageName: node linkType: hard -"@vitest/pretty-format@npm:4.0.4": - version: 4.0.4 - resolution: "@vitest/pretty-format@npm:4.0.4" +"@vitest/pretty-format@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/pretty-format@npm:4.0.18" dependencies: tinyrainbow: "npm:^3.0.3" - checksum: 10/64b0430012f8c34748a39dd1ea061f51d17053086d961830e93a4083b7cda50d822d6db8154398d7f800e15e1efc45c6460d7c1c5f06e21f09a282663824b9c9 + checksum: 10/4cafc7c9853097345bd94e8761bf47c2c04e00d366ac56d79928182787ff83c512c96f1dc2ce9b6aeed4d3a8c23ce12254da203783108d3c096bc398eed2a62d languageName: node linkType: hard -"@vitest/runner@npm:4.0.4": - version: 4.0.4 - resolution: "@vitest/runner@npm:4.0.4" +"@vitest/runner@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/runner@npm:4.0.18" dependencies: - "@vitest/utils": "npm:4.0.4" + "@vitest/utils": "npm:4.0.18" pathe: "npm:^2.0.3" - checksum: 10/3bd7e8944d8770ae7dd7457fb83751def5cb4834766cb86b7231cc0fd77d4e889b5ec6da70ae82e06902b19c216f114a5a670e4422ba2db8384dee09dc24b832 + checksum: 10/d7deebf086d7e084f449733ecea6c9c81737a18aafece318cbe7500e45debea00fa9dbf9315fd38aa88550dd5240a791b885ac71665f89b154d71a6c63da5836 languageName: node linkType: hard -"@vitest/snapshot@npm:4.0.4": - version: 4.0.4 - resolution: "@vitest/snapshot@npm:4.0.4" +"@vitest/snapshot@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/snapshot@npm:4.0.18" dependencies: - "@vitest/pretty-format": "npm:4.0.4" - magic-string: "npm:^0.30.19" + "@vitest/pretty-format": "npm:4.0.18" + magic-string: "npm:^0.30.21" pathe: "npm:^2.0.3" - checksum: 10/dba29abb40e8a4e8931a9522076f0884a579280c440d1e7591c32c4f8d75366b18e3f78920eed13337909384767d0403d15f384275f22d7c0bc5c36a0c4f5482 + checksum: 10/50aa5fb7fca45c499c145cc2f20e53b8afb0990b53ff4a4e6447dd6f147437edc5316f22e2d82119e154c3cf7c59d44898e7b2faf7ba614ac1051cbe4d662a77 languageName: node linkType: hard -"@vitest/spy@npm:4.0.4": - version: 4.0.4 - resolution: "@vitest/spy@npm:4.0.4" - checksum: 10/f3bca9c53840c6f271d676a5b7a06535eb4a80e4b2e52e179ff56cb53f7f725ba1c683cb13d2ef1283057c09bf260634b9b9b318bd2a1755853c067bc9a0dd6a +"@vitest/spy@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/spy@npm:4.0.18" + checksum: 10/f7b1618ae13790105771dd2a8c973c63c018366fcc69b50f15ce5d12f9ac552efd3c1e6e5ae4ebdb6023d0b8d8f31fef2a0b1b77334284928db45c80c63de456 languageName: node linkType: hard -"@vitest/utils@npm:4.0.4": - version: 4.0.4 - resolution: "@vitest/utils@npm:4.0.4" +"@vitest/utils@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/utils@npm:4.0.18" dependencies: - "@vitest/pretty-format": "npm:4.0.4" + "@vitest/pretty-format": "npm:4.0.18" tinyrainbow: "npm:^3.0.3" - checksum: 10/032aa6fad679efe270015bd0ceec55915b3ff4597f5e0b4ee9ae2ac54d5e8a2f903ef64533cc73f05264d8959c01104a32283c2b0298f4e903a003c9bf427514 + checksum: 10/e8b2ad7bc35b2bc5590f9dc1d1a67644755da416b47ab7099a6f26792903fa0aacb81e6ba99f0f03858d9d3a1d76eeba65150a1a0849690a40817424e749c367 languageName: node linkType: hard @@ -12271,10 +12271,10 @@ __metadata: languageName: node linkType: hard -"chai@npm:^6.0.1": - version: 6.2.0 - resolution: "chai@npm:6.2.0" - checksum: 10/199422854e253d8711ea3f220365c6a850c450abf68b31131d2a0f703cbfc5cb48e6c81567e0adbe80e83cdcae6dba82d069a41a77c16bdf6703329c5c3447ef +"chai@npm:^6.2.1": + version: 6.2.2 + resolution: "chai@npm:6.2.2" + checksum: 10/13cda42cc40aa46da04a41cf7e5c61df6b6ae0b4e8a8c8b40e04d6947e4d7951377ea8c14f9fa7fe5aaa9e8bd9ba414f11288dc958d4cee6f5221b9436f2778f languageName: node linkType: hard @@ -14127,18 +14127,6 @@ __metadata: languageName: node linkType: hard -"debug@npm:^4.4.3": - version: 4.4.3 - resolution: "debug@npm:4.4.3" - dependencies: - ms: "npm:^2.1.3" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10/9ada3434ea2993800bd9a1e320bd4aa7af69659fb51cca685d390949434bc0a8873c21ed7c9b852af6f2455a55c6d050aa3937d52b3c69f796dab666f762acad - languageName: node - linkType: hard - "decamelize@npm:^1.2.0": version: 1.2.0 resolution: "decamelize@npm:1.2.0" @@ -16179,9 +16167,9 @@ __metadata: linkType: hard "expect-type@npm:^1.2.2": - version: 1.2.2 - resolution: "expect-type@npm:1.2.2" - checksum: 10/1703e6e47b575f79d801d87f24c639f4d0af71b327a822e6922d0ccb7eb3f6559abb240b8bd43bab6a477903de4cc322908e194d05132c18f52a217115e8e870 + version: 1.3.0 + resolution: "expect-type@npm:1.3.0" + checksum: 10/a5fada3d0c621649261f886e7d93e6bf80ce26d8a86e5d517e38301b8baec8450ab2cb94ba6e7a0a6bf2fc9ee55f54e1b06938ef1efa52ddcfeffbfa01acbbcc languageName: node linkType: hard @@ -21440,7 +21428,7 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.30.19": +"magic-string@npm:^0.30.21": version: 0.30.21 resolution: "magic-string@npm:0.30.21" dependencies: @@ -23874,6 +23862,13 @@ __metadata: languageName: node linkType: hard +"obug@npm:^2.1.1": + version: 2.1.1 + resolution: "obug@npm:2.1.1" + checksum: 10/bdcf9213361786688019345f3452b95a1dc73710e4b403c82a1994b98bad6abc31b26cb72a482128c5fd53ea9daf6fbb7d0e0e7b2b7e9c8be6d779deeccee07f + languageName: node + linkType: hard + "on-finished@npm:2.4.1": version: 2.4.1 resolution: "on-finished@npm:2.4.1" @@ -29894,6 +29889,13 @@ __metadata: languageName: node linkType: hard +"std-env@npm:^3.10.0": + version: 3.10.0 + resolution: "std-env@npm:3.10.0" + checksum: 10/19c9cda4f370b1ffae2b8b08c72167d8c3e5cfa972aaf5c6873f85d0ed2faa729407f5abb194dc33380708c00315002febb6f1e1b484736bfcf9361ad366013a + languageName: node + linkType: hard + "std-env@npm:^3.7.0": version: 3.9.0 resolution: "std-env@npm:3.9.0" @@ -29901,13 +29903,6 @@ __metadata: languageName: node linkType: hard -"std-env@npm:^3.9.0": - version: 3.10.0 - resolution: "std-env@npm:3.10.0" - checksum: 10/19c9cda4f370b1ffae2b8b08c72167d8c3e5cfa972aaf5c6873f85d0ed2faa729407f5abb194dc33380708c00315002febb6f1e1b484736bfcf9361ad366013a - languageName: node - linkType: hard - "stop-iteration-iterator@npm:^1.0.0": version: 1.1.0 resolution: "stop-iteration-iterator@npm:1.1.0" @@ -30834,6 +30829,13 @@ __metadata: languageName: node linkType: hard +"tinyexec@npm:^1.0.2": + version: 1.0.2 + resolution: "tinyexec@npm:1.0.2" + checksum: 10/cb709ed4240e873d3816e67f851d445f5676e0ae3a52931a60ff571d93d388da09108c8057b62351766133ee05ff3159dd56c3a0fbd39a5933c6639ce8771405 + languageName: node + linkType: hard + "tinyglobby@npm:^0.2.11, tinyglobby@npm:^0.2.12": version: 0.2.13 resolution: "tinyglobby@npm:0.2.13" @@ -32272,43 +32274,43 @@ __metadata: linkType: hard "vitest@npm:^4": - version: 4.0.4 - resolution: "vitest@npm:4.0.4" - dependencies: - "@vitest/expect": "npm:4.0.4" - "@vitest/mocker": "npm:4.0.4" - "@vitest/pretty-format": "npm:4.0.4" - "@vitest/runner": "npm:4.0.4" - "@vitest/snapshot": "npm:4.0.4" - "@vitest/spy": "npm:4.0.4" - "@vitest/utils": "npm:4.0.4" - debug: "npm:^4.4.3" + version: 4.0.18 + resolution: "vitest@npm:4.0.18" + dependencies: + "@vitest/expect": "npm:4.0.18" + "@vitest/mocker": "npm:4.0.18" + "@vitest/pretty-format": "npm:4.0.18" + "@vitest/runner": "npm:4.0.18" + "@vitest/snapshot": "npm:4.0.18" + "@vitest/spy": "npm:4.0.18" + "@vitest/utils": "npm:4.0.18" es-module-lexer: "npm:^1.7.0" expect-type: "npm:^1.2.2" - magic-string: "npm:^0.30.19" + magic-string: "npm:^0.30.21" + obug: "npm:^2.1.1" pathe: "npm:^2.0.3" picomatch: "npm:^4.0.3" - std-env: "npm:^3.9.0" + std-env: "npm:^3.10.0" tinybench: "npm:^2.9.0" - tinyexec: "npm:^0.3.2" + tinyexec: "npm:^1.0.2" tinyglobby: "npm:^0.2.15" tinyrainbow: "npm:^3.0.3" vite: "npm:^6.0.0 || ^7.0.0" why-is-node-running: "npm:^2.3.0" peerDependencies: "@edge-runtime/vm": "*" - "@types/debug": ^4.1.12 + "@opentelemetry/api": ^1.9.0 "@types/node": ^20.0.0 || ^22.0.0 || >=24.0.0 - "@vitest/browser-playwright": 4.0.4 - "@vitest/browser-preview": 4.0.4 - "@vitest/browser-webdriverio": 4.0.4 - "@vitest/ui": 4.0.4 + "@vitest/browser-playwright": 4.0.18 + "@vitest/browser-preview": 4.0.18 + "@vitest/browser-webdriverio": 4.0.18 + "@vitest/ui": 4.0.18 happy-dom: "*" jsdom: "*" peerDependenciesMeta: "@edge-runtime/vm": optional: true - "@types/debug": + "@opentelemetry/api": optional: true "@types/node": optional: true @@ -32326,7 +32328,7 @@ __metadata: optional: true bin: vitest: vitest.mjs - checksum: 10/5a7cd573e1a1daeaa7d874d9a676945aab67c1b5167119e903d50be33f3490f919ea575119efdc473a42d8c42b176bbbc31c12f3c7f1fdd2eb817cc8e162c10a + checksum: 10/6c6464ebcf3af83546862896fd1b5f10cb6607261bffce39df60033a288b8c1687ae1dd20002b6e4997a7a05303376d1eb58ce20afe63be052529a4378a8c165 languageName: node linkType: hard