Skip to content

Commit

Permalink
feat(Commons): introduce options for request functions
Browse files Browse the repository at this point in the history
  • Loading branch information
mfal committed Sep 19, 2024
1 parent df0b8fa commit a602a76
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 4 deletions.
44 changes: 44 additions & 0 deletions packages/commons/src/core/ApiClientBase.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import axios from "axios";
import { jest } from "@jest/globals";
import ApiClientBase from "./ApiClientBase.js";

const requestFn = jest.fn();

jest.mock("axios");
const mockedAxios = axios as jest.Mocked<typeof axios>;
mockedAxios.create.mockReturnValue(mockedAxios);
mockedAxios.request.mockImplementation(requestFn as never);

class TestClient extends ApiClientBase {
public testRequest = this.requestFunctionFactory({
path: "/test",
method: "GET",
operationId: "test",
});
}
const testClient = new TestClient();

test("onBeforeRequest is called before actual request", async () => {
const onBeforeRequest = jest.fn(() => {
expect(requestFn).not.toHaveBeenCalled();
});

await testClient.testRequest(undefined, {
onBeforeRequest,
});

expect(onBeforeRequest).toHaveBeenCalledTimes(1);
expect(requestFn).toHaveBeenCalledTimes(1);
});

test("onBeforeRequest configured in default options is called before actual request", async () => {
const onBeforeRequest = jest.fn(() => {
expect(requestFn).not.toHaveBeenCalled();
});

testClient.defaultRequestOptions.onBeforeRequest = onBeforeRequest;
await testClient.testRequest(undefined);

expect(onBeforeRequest).toHaveBeenCalledTimes(1);
expect(requestFn).toHaveBeenCalledTimes(1);
});
29 changes: 25 additions & 4 deletions packages/commons/src/core/ApiClientBase.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,42 @@
import axios, { Axios, AxiosInstance, CreateAxiosDefaults } from "axios";
import { RequestObject, RequestFunction } from "../types/index.js";
import {
RequestObject,
RequestFunction,
RequestOptions,
} from "../types/index.js";
import { OpenAPIOperation } from "../types/index.js";
import Request from "./Request.js";

export abstract class ApiClientBase {
public axios: AxiosInstance;
public readonly axios: AxiosInstance;
public readonly defaultRequestOptions: RequestOptions = {};

public constructor(axiosConfig: AxiosInstance | CreateAxiosDefaults = axios) {
this.axios =
axiosConfig instanceof Axios ? axiosConfig : axios.create(axiosConfig);
}

private buildRequestOptions<TOp extends OpenAPIOperation>(
fromRequest: RequestOptions<TOp>,
): RequestOptions<TOp> {
return {
...this.defaultRequestOptions,
...fromRequest,
};
}

protected requestFunctionFactory<TOp extends OpenAPIOperation>(
operation: TOp,
): RequestFunction<TOp> {
return (conf?: RequestObject<TOp>) =>
new Request(operation, conf).execute(this.axios);
return (conf?: RequestObject<TOp>, opts: RequestOptions<TOp> = {}) => {
const { onBeforeRequest } = this.buildRequestOptions(opts);

const request = new Request(operation, conf);
if (onBeforeRequest) {
onBeforeRequest(request);
}
return request.execute(this.axios);
};
}
}

Expand Down
9 changes: 9 additions & 0 deletions packages/commons/src/types/RequestFunction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import {
OpenAPIOperation,
} from "./OpenAPIOperation.js";
import { NullableOnNoRequiredKeysDeep } from "./NullableOnNoRequiredKeysDeep.js";
import Request from "../core/Request.js";

export interface RequestOptions<
TOp extends OpenAPIOperation = OpenAPIOperation,
> {
onBeforeRequest?: (req: Request<TOp>) => void;
}

type UnboxPathParameters<T> = T extends { pathParameters: infer TPath }
? Omit<T, "pathParameters"> & TPath
Expand All @@ -18,10 +25,12 @@ export type ResponsePromise<TOp extends OpenAPIOperation> = Promise<

type RequestFunctionWithOptionalRequest<TOp extends OpenAPIOperation> = (
request?: RequestObject<TOp>,
opts?: RequestOptions<TOp>,
) => ResponsePromise<TOp>;

type RequestFunctionWithRequiredRequest<TOp extends OpenAPIOperation> = (
request: RequestObject<TOp>,
opts?: RequestOptions<TOp>,
) => ResponsePromise<TOp>;

export type RequestFunction<TOp extends OpenAPIOperation> =
Expand Down

0 comments on commit a602a76

Please sign in to comment.