Skip to content

Commit

Permalink
fix: handle tree-shakeable angular client case
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobinu committed Aug 26, 2024
1 parent 7e84960 commit 8f7a14f
Show file tree
Hide file tree
Showing 21 changed files with 3,176 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/ninety-windows-accept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hey-api/openapi-ts': patch
---

fix: handle tree-shakeable angular client case
1 change: 1 addition & 0 deletions packages/openapi-ts/src/compiler/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ export class TypeScriptFile {
}

export const compiler = {
anonymousFunction: types.createAnonymousFunction,
arrayLiteralExpression: types.createArrayLiteralExpression,
arrowFunction: types.createArrowFunction,
awaitExpression: types.createAwaitExpression,
Expand Down
38 changes: 38 additions & 0 deletions packages/openapi-ts/src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,44 @@ export const createArrowFunction = ({
return expression;
};

/**
* Create anonymous function type expression.
*/
export const createAnonymousFunction = ({
async,
comment,
multiLine,
parameters = [],
returnType,
statements = [],
types = [],
}: {
async?: boolean;
comment?: Comments;
multiLine?: boolean;
parameters?: FunctionParameter[];
returnType?: string | ts.TypeNode;
statements?: ts.Statement[];
types?: FunctionTypeParameter[];
}) => {
const expression = ts.factory.createFunctionExpression(
async ? [ts.factory.createModifier(ts.SyntaxKind.AsyncKeyword)] : undefined,
undefined,
undefined,
types ? toTypeParameters(types) : undefined,
toParameterDeclarations(parameters),
returnType ? createTypeNode(returnType) : undefined,
ts.factory.createBlock(statements, multiLine),
);

addLeadingComments({
comments: comment,
node: expression,
});

return expression;
};

Check warning on line 337 in packages/openapi-ts/src/compiler/types.ts

View check run for this annotation

Codecov / codecov/patch

packages/openapi-ts/src/compiler/types.ts#L305-L337

Added lines #L305 - L337 were not covered by tests

/**
* Create Array type expression.
* @param arr - The array to create.
Expand Down
8 changes: 6 additions & 2 deletions packages/openapi-ts/src/generate/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ const processService = ({

if (!config.services.asClass && !config.name) {
for (const operation of service.operations) {
const expression = compiler.arrowFunction({
const compileFunctionParams = {
parameters: toOperationParamType(client, operation),
returnType: isStandalone
? undefined
Expand All @@ -622,7 +622,11 @@ const processService = ({
onClientImport,
),
types: isStandalone ? [throwOnErrorTypeGeneric] : undefined,
});
};
const expression =
config.client.name === 'angular'
? compiler.anonymousFunction(compileFunctionParams)

Check warning on line 628 in packages/openapi-ts/src/generate/services.ts

View check run for this annotation

Codecov / codecov/patch

packages/openapi-ts/src/generate/services.ts#L628

Added line #L628 was not covered by tests
: compiler.arrowFunction(compileFunctionParams);
const statement = compiler.constVariable({
comment: toOperationComment(operation),
exportConst: true,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { ApiRequestOptions } from './ApiRequestOptions';
import type { ApiResult } from './ApiResult';

export class ApiError extends Error {
public readonly url: string;
public readonly status: number;
public readonly statusText: string;
public readonly body: unknown;
public readonly request: ApiRequestOptions;

constructor(request: ApiRequestOptions, response: ApiResult, message: string) {
super(message);

this.name = 'ApiError';
this.url = response.url;
this.status = response.status;
this.statusText = response.statusText;
this.body = response.body;
this.request = request;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export type ApiRequestOptions<T = unknown> = {
readonly body?: any;
readonly cookies?: Record<string, unknown>;
readonly errors?: Record<number | string, string>;
readonly formData?: Record<string, unknown> | any[] | Blob | File;
readonly headers?: Record<string, unknown>;
readonly mediaType?: string;
readonly method:
| 'DELETE'
| 'GET'
| 'HEAD'
| 'OPTIONS'
| 'PATCH'
| 'POST'
| 'PUT';
readonly path?: Record<string, unknown>;
readonly query?: Record<string, unknown>;
readonly responseHeader?: string;
readonly responseTransformer?: (data: unknown) => Promise<T>;
readonly url: string;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export type ApiResult<TData = any> = {
readonly body: TData;
readonly ok: boolean;
readonly status: number;
readonly statusText: string;
readonly url: string;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import type { HttpResponse } from '@angular/common/http';
import type { ApiRequestOptions } from './ApiRequestOptions';

type Headers = Record<string, string>;
type Middleware<T> = (value: T) => T | Promise<T>;
type Resolver<T> = (options: ApiRequestOptions<T>) => Promise<T>;

export class Interceptors<T> {
_fns: Middleware<T>[];

constructor() {
this._fns = [];
}

eject(fn: Middleware<T>): void {
const index = this._fns.indexOf(fn);
if (index !== -1) {
this._fns = [...this._fns.slice(0, index), ...this._fns.slice(index + 1)];
}
}

use(fn: Middleware<T>): void {
this._fns = [...this._fns, fn];
}
}

export type OpenAPIConfig = {
BASE: string;
CREDENTIALS: 'include' | 'omit' | 'same-origin';
ENCODE_PATH?: ((path: string) => string) | undefined;
HEADERS?: Headers | Resolver<Headers> | undefined;
PASSWORD?: string | Resolver<string> | undefined;
TOKEN?: string | Resolver<string> | undefined;
USERNAME?: string | Resolver<string> | undefined;
VERSION: string;
WITH_CREDENTIALS: boolean;
interceptors: {
response: Interceptors<HttpResponse<any>>;
};
};

export const OpenAPI: OpenAPIConfig = {
BASE: 'http://localhost:3000/base',
CREDENTIALS: 'include',
ENCODE_PATH: undefined,
HEADERS: undefined,
PASSWORD: undefined,
TOKEN: undefined,
USERNAME: undefined,
VERSION: '1.0',
WITH_CREDENTIALS: false,
interceptors: {
response: new Interceptors(),
},
};
Loading

0 comments on commit 8f7a14f

Please sign in to comment.