Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Append file extension based on runtime #936

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
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
15 changes: 15 additions & 0 deletions packages/openapi-ts/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// global.d.ts
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this file for the utils/runtime module?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, if not TypeScript (node) thinks it is an undeclared type since it is not aware of Deno and Bun (rightfully so)


declare const Deno:
| {
version: { deno: string; typescript: string; v8: string };
// Add more Deno-specific properties here if needed
}
| undefined;

declare const Bun:
| {
version: string;
// Add more Bun-specific properties here if needed
}
| undefined;
4 changes: 3 additions & 1 deletion packages/openapi-ts/src/generate/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import { createRequire } from 'node:module';
import path from 'node:path';

import { getConfig, isStandaloneClient } from '../utils/config';
import { appendExt } from '../utils/extension';
import { ensureDirSync } from './utils';

const require = createRequire(import.meta.url);

export const clientModulePath = () => {
const config = getConfig();
return config.client.bundle ? './client' : config.client.name;

return appendExt(config.client.bundle ? './client' : config.client.name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to add extension to node_modules imports too? This may generate code like '@hey-api/client-fetch.ts'

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, only for relative/absolute paths or importing specific files.

I see, Id have to check then how to differentiate if its coming from core or an external package...

};

export const clientOptionsTypeName = () => 'Options';
Expand Down
2 changes: 2 additions & 0 deletions packages/openapi-ts/src/generate/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import path from 'node:path';

import type { Client } from '../types/client';
import { getConfig } from '../utils/config';
import { getExt } from '../utils/extension';
import { getHttpRequestName } from '../utils/getHttpRequestName';
import type { Templates } from '../utils/handlebars';

Expand All @@ -27,6 +28,7 @@ export const generateCore = async (

if (config.exportCore) {
const context = {
ext: getExt(),
httpRequest: getHttpRequestName(config.client),
server: config.base !== undefined ? config.base : client.server,
version: client.version,
Expand Down
15 changes: 8 additions & 7 deletions packages/openapi-ts/src/generate/indexFile.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { compiler, TypeScriptFile } from '../compiler';
import type { Files } from '../types/utils';
import { getConfig } from '../utils/config';
import { appendExt } from '../utils/extension';

export const generateIndexFile = async ({
files,
Expand All @@ -18,7 +19,7 @@ export const generateIndexFile = async ({
files.index.add(
compiler.exportNamedDeclaration({
exports: config.name,
module: `./${config.name}`,
module: appendExt(`./${config.name}`),
}),
);
}
Expand All @@ -27,37 +28,37 @@ export const generateIndexFile = async ({
files.index.add(
compiler.exportNamedDeclaration({
exports: 'ApiError',
module: './core/ApiError',
module: appendExt('./core/ApiError'),
}),
);
if (config.services.response === 'response') {
files.index.add(
compiler.exportNamedDeclaration({
exports: { asType: true, name: 'ApiResult' },
module: './core/ApiResult',
module: appendExt('./core/ApiResult'),
}),
);
}
if (config.name) {
files.index.add(
compiler.exportNamedDeclaration({
exports: 'BaseHttpRequest',
module: './core/BaseHttpRequest',
module: appendExt('./core/BaseHttpRequest'),
}),
);
}
if (config.client.name !== 'angular') {
files.index.add(
compiler.exportNamedDeclaration({
exports: ['CancelablePromise', 'CancelError'],
module: './core/CancelablePromise',
module: appendExt('./core/CancelablePromise'),
}),
);
}
files.index.add(
compiler.exportNamedDeclaration({
exports: ['OpenAPI', { asType: true, name: 'OpenAPIConfig' }],
module: './core/OpenAPI',
module: appendExt('./core/OpenAPI'),
}),
);
}
Expand All @@ -73,7 +74,7 @@ export const generateIndexFile = async ({

files.index.add(
compiler.exportAllDeclaration({
module: `./${file.getName(false)}`,
module: appendExt(`./${file.getName(false)}`),
}),
);
});
Expand Down
13 changes: 7 additions & 6 deletions packages/openapi-ts/src/generate/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type { Files } from '../types/utils';
import { camelCase } from '../utils/camelCase';
import { getConfig, isStandaloneClient } from '../utils/config';
import { escapeComment, escapeName } from '../utils/escape';
import { appendExt } from '../utils/extension';
import { reservedWordsRegExp } from '../utils/reservedWords';
import { transformServiceName } from '../utils/transform';
import { setUniqueTypeName } from '../utils/type';
Expand Down Expand Up @@ -776,33 +777,33 @@ export const generateServices = async ({
} else {
files.services.import({
asType: true,
module: './core/CancelablePromise',
module: appendExt('./core/CancelablePromise'),
name: 'CancelablePromise',
});
}

if (config.services.response === 'response') {
files.services.import({
asType: true,
module: './core/ApiResult',
module: appendExt('./core/ApiResult'),
name: 'ApiResult',
});
}

if (config.name) {
files.services.import({
asType: config.client.name !== 'angular',
module: './core/BaseHttpRequest',
module: appendExt('./core/BaseHttpRequest'),
name: 'BaseHttpRequest',
});
} else {
files.services.import({
module: './core/OpenAPI',
module: appendExt('./core/OpenAPI'),
name: 'OpenAPI',
});
files.services.import({
alias: '__request',
module: './core/request',
module: appendExt('./core/request'),
name: 'request',
});
}
Expand Down Expand Up @@ -838,7 +839,7 @@ export const generateServices = async ({
files.services.import({
// this detection could be done safer, but it shouldn't cause any issues
asType: !imported.endsWith('Transformer'),
module: `./${files.types.getName(false)}`,
module: appendExt(`./${files.types.getName(false)}`),
name: imported,
});
},
Expand Down
20 changes: 10 additions & 10 deletions packages/openapi-ts/src/templates/client.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@
import { NgModule} from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

import { AngularHttpRequest } from './core/AngularHttpRequest';
import { BaseHttpRequest } from './core/BaseHttpRequest';
import type { OpenAPIConfig } from './core/OpenAPI';
import { OpenAPI } from './core/OpenAPI';
import { Interceptors } from './core/OpenAPI';
import { AngularHttpRequest } from './core/AngularHttpRequest{{ext}}';
import { BaseHttpRequest } from './core/BaseHttpRequest{{ext}}';
import type { OpenAPIConfig } from './core/OpenAPI{{ext}}';
import { OpenAPI } from './core/OpenAPI{{ext}}';
import { Interceptors } from './core/OpenAPI{{ext}}';
{{else}}
import type { BaseHttpRequest } from './core/BaseHttpRequest';
import type { OpenAPIConfig } from './core/OpenAPI';
import { Interceptors } from './core/OpenAPI';
import { {{{httpRequest}}} } from './core/{{{httpRequest}}}';
import type { BaseHttpRequest } from './core/BaseHttpRequest{{ext}}';
import type { OpenAPIConfig } from './core/OpenAPI{{ext}}';
import { Interceptors } from './core/OpenAPI{{ext}}';
import { {{{httpRequest}}} } from './core/{{{httpRequest}}}{{ext}}';
{{/equals}}

{{#if services}}
{{#each services}}
import { {{{transformServiceName name}}} } from './services.gen';
import { {{{transformServiceName name}}} } from './services.gen{{ext}}';
{{/each}}
{{/if}}

Expand Down
4 changes: 2 additions & 2 deletions packages/openapi-ts/src/templates/core/ApiError.hbs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiRequestOptions } from './ApiRequestOptions';
import type { ApiResult } from './ApiResult';
import type { ApiRequestOptions } from './ApiRequestOptions{{ext}}';
import type { ApiResult } from './ApiResult{{ext}}';

export class ApiError extends Error {
public readonly url: string;
Expand Down
10 changes: 5 additions & 5 deletions packages/openapi-ts/src/templates/core/BaseHttpRequest.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
import type { HttpClient } from '@angular/common/http';
import type { Observable } from 'rxjs';

import type { ApiRequestOptions } from './ApiRequestOptions';
import type { OpenAPIConfig } from './OpenAPI';
import type { ApiRequestOptions } from './ApiRequestOptions{{ext}}';
import type { OpenAPIConfig } from './OpenAPI{{ext}}';
{{else}}
import type { ApiRequestOptions } from './ApiRequestOptions';
import type { CancelablePromise } from './CancelablePromise';
import type { OpenAPIConfig } from './OpenAPI';
import type { ApiRequestOptions } from './ApiRequestOptions{{ext}}';
import type { CancelablePromise } from './CancelablePromise{{ext}}';
import type { OpenAPIConfig } from './OpenAPI{{ext}}';
{{/equals}}

export abstract class BaseHttpRequest {
Expand Down
20 changes: 10 additions & 10 deletions packages/openapi-ts/src/templates/core/HttpRequest.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import { Inject, Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import type { Observable } from 'rxjs';

import type { ApiRequestOptions } from './ApiRequestOptions';
import { BaseHttpRequest } from './BaseHttpRequest';
import type { OpenAPIConfig } from './OpenAPI';
import { OpenAPI } from './OpenAPI';
import { request as __request } from './request';
import type { ApiRequestOptions } from './ApiRequestOptions{{ext}}';
import { BaseHttpRequest } from './BaseHttpRequest{{ext}}';
import type { OpenAPIConfig } from './OpenAPI{{ext}}';
import { OpenAPI } from './OpenAPI{{ext}}';
import { request as __request } from './request{{ext}}';
{{else}}
import type { ApiRequestOptions } from './ApiRequestOptions';
import { BaseHttpRequest } from './BaseHttpRequest';
import type { CancelablePromise } from './CancelablePromise';
import type { OpenAPIConfig } from './OpenAPI';
import { request as __request } from './request';
import type { ApiRequestOptions } from './ApiRequestOptions{{ext}}';
import { BaseHttpRequest } from './BaseHttpRequest{{ext}}';
import type { CancelablePromise } from './CancelablePromise{{ext}}';
import type { OpenAPIConfig } from './OpenAPI{{ext}}';
import { request as __request } from './request{{ext}}';
{{/equals}}

{{#equals @root.$config.client.name 'angular'}}
Expand Down
2 changes: 1 addition & 1 deletion packages/openapi-ts/src/templates/core/OpenAPI.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { AxiosRequestConfig, AxiosResponse } from 'axios';
{{#equals @root.$config.client.name 'node'}}
import type { RequestInit, Response } from 'node-fetch';
{{/equals}}
import type { ApiRequestOptions } from './ApiRequestOptions';
import type { ApiRequestOptions } from './ApiRequestOptions{{ext}}';

type Headers = Record<string, string>;
type Middleware<T> = (value: T) => T | Promise<T>;
Expand Down
8 changes: 4 additions & 4 deletions packages/openapi-ts/src/templates/core/angular/request.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { forkJoin, of, throwError } from 'rxjs';
import { catchError, map, switchMap } from 'rxjs/operators';
import type { Observable } from 'rxjs';

import { ApiError } from './ApiError';
import type { ApiRequestOptions } from './ApiRequestOptions';
import type { ApiResult } from './ApiResult';
import type { OpenAPIConfig } from './OpenAPI';
import { ApiError } from './ApiError{{ext}}';
import type { ApiRequestOptions } from './ApiRequestOptions{{ext}}';
import type { ApiResult } from './ApiResult{{ext}}';
import type { OpenAPIConfig } from './OpenAPI{{ext}}';

{{>functions/isString}}

Expand Down
12 changes: 6 additions & 6 deletions packages/openapi-ts/src/templates/core/axios/request.hbs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import axios from 'axios';
import type { AxiosError, AxiosRequestConfig, AxiosResponse, AxiosInstance } from 'axios';

import { ApiError } from './ApiError';
import type { ApiRequestOptions } from './ApiRequestOptions';
import type { ApiResult } from './ApiResult';
import { CancelablePromise } from './CancelablePromise';
import type { OnCancel } from './CancelablePromise';
import type { OpenAPIConfig } from './OpenAPI';
import { ApiError } from './ApiError{{ext}}';
import type { ApiRequestOptions } from './ApiRequestOptions{{ext}}';
import type { ApiResult } from './ApiResult{{ext}}';
import { CancelablePromise } from './CancelablePromise{{ext}}';
import type { OnCancel } from './CancelablePromise{{ext}}';
import type { OpenAPIConfig } from './OpenAPI{{ext}}';

{{>functions/isString}}

Expand Down
12 changes: 6 additions & 6 deletions packages/openapi-ts/src/templates/core/fetch/request.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import fetch, { FormData, Headers } from 'node-fetch';
import type { RequestInit, Response } from 'node-fetch';

{{/equals}}
import { ApiError } from './ApiError';
import type { ApiRequestOptions } from './ApiRequestOptions';
import type { ApiResult } from './ApiResult';
import { CancelablePromise } from './CancelablePromise';
import type { OnCancel } from './CancelablePromise';
import type { OpenAPIConfig } from './OpenAPI';
import { ApiError } from './ApiError{{ext}}';
import type { ApiRequestOptions } from './ApiRequestOptions{{ext}}';
import type { ApiResult } from './ApiResult{{ext}}';
import { CancelablePromise } from './CancelablePromise{{ext}}';
import type { OnCancel } from './CancelablePromise{{ext}}';
import type { OpenAPIConfig } from './OpenAPI{{ext}}';

{{>functions/isString}}

Expand Down
12 changes: 6 additions & 6 deletions packages/openapi-ts/src/templates/core/xhr/request.hbs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { ApiError } from './ApiError';
import type { ApiRequestOptions } from './ApiRequestOptions';
import type { ApiResult } from './ApiResult';
import { CancelablePromise } from './CancelablePromise';
import type { OnCancel } from './CancelablePromise';
import type { OpenAPIConfig } from './OpenAPI';
import { ApiError } from './ApiError{{ext}}';
import type { ApiRequestOptions } from './ApiRequestOptions{{ext}}';
import type { ApiResult } from './ApiResult{{ext}}';
import { CancelablePromise } from './CancelablePromise{{ext}}';
import type { OnCancel } from './CancelablePromise{{ext}}';
import type { OpenAPIConfig } from './OpenAPI{{ext}}';

{{>functions/isString}}

Expand Down
19 changes: 19 additions & 0 deletions packages/openapi-ts/src/utils/extension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { isDenoRuntime } from './runtime';

/**
* Appends the file extension to a file name based on the current runtime
*
* Some TS runtimes require using the complete path for import/export,
* including the extension
*/
export const appendExt = (fileName: string): string => {
if (isDenoRuntime()) {
return `${fileName}.ts`;
}
return fileName;
};

/**
* Returns the file extension based on the current runtime
*/
export const getExt = (): string => appendExt('');
12 changes: 12 additions & 0 deletions packages/openapi-ts/src/utils/runtime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Runtime detection functions

export const isNodeRuntime = (): boolean =>
typeof process !== 'undefined' &&
typeof process.versions !== 'undefined' &&
typeof process.versions.node !== 'undefined';

export const isDenoRuntime = (): boolean =>
typeof Deno !== 'undefined' && typeof Deno.version !== 'undefined';

export const isBunRuntime = (): boolean =>
typeof Bun !== 'undefined' && typeof Bun.version !== 'undefined';
7 changes: 6 additions & 1 deletion packages/openapi-ts/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,10 @@
},
"exclude": ["node_modules", "**/__mocks__"],
"files": ["./src/types/hbs.d.ts"],
"include": ["./src/**/*.ts", "rollup.config.ts", "rollup.dts.config.ts"]
"include": [
"global.d.ts",
"./src/**/*.ts",
"rollup.config.ts",
"rollup.dts.config.ts"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need to add this file?

]
}
Loading