Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions packages/rtk-query-codegen-openapi/src/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export async function generateApi(
mergeReadWriteOnly = false,
httpResolverOptions,
useUnknown = false,
esmExtensions = false,
}: GenerationOptions
) {
const v3Doc = (v3DocCache[spec] ??= await getV3Doc(spec, httpResolverOptions));
Expand Down Expand Up @@ -163,7 +164,17 @@ export async function generateApi(
if (!apiFile.startsWith('.')) apiFile = `./${apiFile}`;
}
}
apiFile = apiFile.replace(/\.[jt]sx?$/, '');

if (esmExtensions === true) {
// Convert TS/JSX extensions to their JS equivalents
apiFile = apiFile
.replace(/\.mts$/, '.mjs')
.replace(/\.[jt]sx$/, '.jsx')
.replace(/\.ts$/, '.js');
} else {
// Remove all extensions
apiFile = apiFile.replace(/\.[jt]sx?$/, '');
}

return printer.printNode(
ts.EmitHint.Unspecified,
Expand Down Expand Up @@ -451,11 +462,7 @@ export async function generateApi(
const encodedValue =
encodeQueryParams && param.param?.in === 'query'
? factory.createConditionalExpression(
factory.createBinaryExpression(
value,
ts.SyntaxKind.ExclamationEqualsToken,
factory.createNull()
),
factory.createBinaryExpression(value, ts.SyntaxKind.ExclamationEqualsToken, factory.createNull()),
undefined,
factory.createCallExpression(factory.createIdentifier('encodeURIComponent'), undefined, [
factory.createCallExpression(factory.createIdentifier('String'), undefined, [value]),
Expand Down
5 changes: 5 additions & 0 deletions packages/rtk-query-codegen-openapi/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ export interface CommonOptions {
* @since 2.1.0
*/
useUnknown?: boolean;
/**
* @default false
* Will generate imports with file extension matching the expected compiled output of the api file
*/
esmExtensions?: boolean;
}

export type TextMatcher = string | RegExp | (string | RegExp)[];
Expand Down
83 changes: 83 additions & 0 deletions packages/rtk-query-codegen-openapi/test/generateEndpoints.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -647,3 +647,86 @@ describe('query parameters', () => {
expect(api).toMatchSnapshot();
});
});

describe('esmExtensions option', () => {
beforeAll(async () => {
if (!(await isDir(tmpDir))) {
await fs.mkdir(tmpDir, { recursive: true });
}
});

afterEach(async () => {
await rimraf(`${tmpDir}/*.ts`, { glob: true });
});

test('should convert .ts to .js when esmExtensions is true', async () => {
await generateEndpoints({
apiFile: './fixtures/emptyApi.ts',
outputFile: './test/tmp/out.ts',
schemaFile: resolve(__dirname, 'fixtures/petstore.json'),
filterEndpoints: [],
esmExtensions: true,
});
const content = await fs.readFile('./test/tmp/out.ts', 'utf8');
expect(content).toContain("import { api } from '../../fixtures/emptyApi.js'");
});

test('should convert .mts to .mjs when esmExtensions is true', async () => {
await generateEndpoints({
apiFile: './fixtures/emptyApi.mts',
outputFile: './test/tmp/out.ts',
schemaFile: resolve(__dirname, 'fixtures/petstore.json'),
filterEndpoints: [],
esmExtensions: true,
});
const content = await fs.readFile('./test/tmp/out.ts', 'utf8');
expect(content).toContain("import { api } from '../../fixtures/emptyApi.mjs'");
});

test('should preserve .jsx when esmExtensions is true', async () => {
await generateEndpoints({
apiFile: './fixtures/emptyApi.jsx',
outputFile: './test/tmp/out.ts',
schemaFile: resolve(__dirname, 'fixtures/petstore.json'),
filterEndpoints: [],
esmExtensions: true,
});
const content = await fs.readFile('./test/tmp/out.ts', 'utf8');
expect(content).toContain("import { api } from '../../fixtures/emptyApi.jsx'");
});

test('should convert .tsx to .jsx when esmExtensions is true', async () => {
await generateEndpoints({
apiFile: './fixtures/emptyApi.tsx',
outputFile: './test/tmp/out.ts',
schemaFile: resolve(__dirname, 'fixtures/petstore.json'),
filterEndpoints: [],
esmExtensions: true,
});
const content = await fs.readFile('./test/tmp/out.ts', 'utf8');
expect(content).toContain("import { api } from '../../fixtures/emptyApi.jsx'");
});

test('should strip extensions when esmExtensions is false', async () => {
await generateEndpoints({
apiFile: './fixtures/emptyApi.ts',
outputFile: './test/tmp/out.ts',
schemaFile: resolve(__dirname, 'fixtures/petstore.json'),
filterEndpoints: [],
esmExtensions: false,
});
const content = await fs.readFile('./test/tmp/out.ts', 'utf8');
expect(content).toContain("import { api } from '../../fixtures/emptyApi'");
});

test('should strip extensions when esmExtensions is undefined (default)', async () => {
await generateEndpoints({
apiFile: './fixtures/emptyApi.ts',
outputFile: './test/tmp/out.ts',
schemaFile: resolve(__dirname, 'fixtures/petstore.json'),
filterEndpoints: [],
});
const content = await fs.readFile('./test/tmp/out.ts', 'utf8');
expect(content).toContain("import { api } from '../../fixtures/emptyApi'");
});
});