Skip to content

Commit

Permalink
feat: allow clients to throw on error
Browse files Browse the repository at this point in the history
  • Loading branch information
mrlubos committed Jul 28, 2024
1 parent 810a4c2 commit e6b0040
Show file tree
Hide file tree
Showing 25 changed files with 203 additions and 164 deletions.
1 change: 0 additions & 1 deletion examples/openapi-ts-axios/openapi-ts.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { defineConfig } from '@hey-api/openapi-ts';

export default defineConfig({
base: 'https://petstore3.swagger.io/api/v3',
client: '@hey-api/client-axios',
input:
'https://raw.githubusercontent.com/swagger-api/swagger-petstore/master/src/main/resources/openapi.yaml',
Expand Down
1 change: 0 additions & 1 deletion examples/openapi-ts-fetch/openapi-ts.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { defineConfig } from '@hey-api/openapi-ts';

export default defineConfig({
base: 'https://petstore3.swagger.io/api/v3',
client: '@hey-api/client-fetch',
input:
'https://raw.githubusercontent.com/swagger-api/swagger-petstore/master/src/main/resources/openapi.yaml',
Expand Down
12 changes: 6 additions & 6 deletions examples/openapi-ts-fetch/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,26 @@ import {
import { useState } from 'react';

import { $Pet } from './client/schemas.gen';
import { addPet, getPetById, updatePet } from './client/services.gen';
import { addPet, client, getPetById, updatePet } from './client/services.gen';
import type { Pet } from './client/types.gen';

createClient({
// configure internal service client
client.setConfig({
// set default base url for requests
baseUrl: 'https://petstore3.swagger.io/api/v3',
// set default headers for requests
headers: {
Authorization: 'Bearer <token_from_global_client>',
Authorization: 'Bearer <token_from_service_client>',
},
});

const localClient = createClient({
// set default base url for requests made by this client
baseUrl: 'https://petstore3.swagger.io/api/v3',
global: false,
/**
* Set default headers only for requests made by this client. This is to
* demonstrate local clients and their configuration taking precedence over
* global configuration.
* internal service client.
*/
headers: {
Authorization: 'Bearer <token_from_local_client>',
Expand Down Expand Up @@ -97,7 +97,7 @@ function App() {

const onGetPetById = async () => {
const { data, error } = await getPetById({
client: localClient,
// client: localClient,
path: {
// random id 1-10
petId: Math.floor(Math.random() * (10 - 1 + 1) + 1),
Expand Down
8 changes: 7 additions & 1 deletion examples/openapi-ts-fetch/src/client/services.gen.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// This file is auto-generated by @hey-api/openapi-ts

import { client, type Options } from '@hey-api/client-fetch';
import {
createClient,
createConfig,
type Options,
} from '@hey-api/client-fetch';

import type {
AddPetData,
Expand Down Expand Up @@ -52,6 +56,8 @@ import type {
UploadFileResponse,
} from './types.gen';

export const client = createClient(createConfig());

/**
* Add a new pet to the store
* Add a new pet to the store
Expand Down
2 changes: 1 addition & 1 deletion examples/openapi-ts-fetch/src/client/types.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ export type CreateUsersWithListInputData = {
body?: Array<User>;
};

export type CreateUsersWithListInputResponse = User;
export type CreateUsersWithListInputResponse = User | unknown;

export type CreateUsersWithListInputError = unknown;

Expand Down
49 changes: 16 additions & 33 deletions packages/client-fetch/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import type { Client, Config, RequestOptions } from './types';
import {
createDefaultConfig,
createConfig,
createInterceptors,
createQuerySerializer,
getParseAs,
getUrl,
mergeConfigs,
mergeHeaders,
} from './utils';

Expand All @@ -13,42 +14,24 @@ type ReqInit = Omit<RequestInit, 'body' | 'headers'> & {
headers: ReturnType<typeof mergeHeaders>;
};

let globalConfig = createDefaultConfig();
export const createClient = (config: Config = {}): Client => {
let _config = mergeConfigs(createConfig(), config);

const globalInterceptors = createInterceptors<
Request,
Response,
RequestOptions
>();
const getConfig = (): Config => ({ ..._config });

export const createClient = (config: Config): Client => {
const defaultConfig = createDefaultConfig();
const _config = { ...defaultConfig, ...config };

if (_config.baseUrl?.endsWith('/')) {
_config.baseUrl = _config.baseUrl.substring(0, _config.baseUrl.length - 1);
}
_config.headers = mergeHeaders(defaultConfig.headers, _config.headers);

if (_config.global) {
globalConfig = { ..._config };
}

// @ts-ignore
const getConfig = () => (_config.root ? globalConfig : _config);
const setConfig = (config: Config): Config => {
_config = mergeConfigs(_config, config);
return getConfig();
};

const interceptors = _config.global
? globalInterceptors
: createInterceptors<Request, Response, RequestOptions>();
const interceptors = createInterceptors<Request, Response, RequestOptions>();

// @ts-ignore
const request: Client['request'] = async (options) => {
const config = getConfig();

const opts: RequestOptions = {
...config,
..._config,
...options,
headers: mergeHeaders(config.headers, options.headers),
headers: mergeHeaders(_config.headers, options.headers),
};
if (opts.body && opts.bodySerializer) {
opts.body = opts.bodySerializer(opts.body);
Expand Down Expand Up @@ -157,12 +140,12 @@ export const createClient = (config: Config): Client => {
post: (options) => request({ ...options, method: 'POST' }),
put: (options) => request({ ...options, method: 'PUT' }),
request,
setConfig,
trace: (options) => request({ ...options, method: 'TRACE' }),
};
};

export const client = createClient({
...globalConfig,
// @ts-ignore
root: true,
const c = createClient();
c.setConfig({
baseUrl: 'aaaa',
});
3 changes: 2 additions & 1 deletion packages/client-fetch/src/node/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export { client, createClient } from '../';
export { createClient } from '../';
export type { Client, Options, RequestResult } from '../types';
export {
createConfig,
formDataBodySerializer,
jsonBodySerializer,
urlSearchParamsBodySerializer,
Expand Down
9 changes: 2 additions & 7 deletions packages/client-fetch/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,6 @@ export interface Config
* @default globalThis.fetch
*/
fetch?: (request: Request) => ReturnType<typeof fetch>;
/**
* By default, options passed to this call will be applied to the global
* client instance. Set to false to create a local client instance.
* @default true
*/
global?: boolean;
/**
* An object containing any HTTP headers that you want to pre-populate your
* `Headers` object with.
Expand Down Expand Up @@ -99,7 +93,7 @@ export interface Config
responseTransformer?: (data: unknown) => Promise<unknown>;
}

interface RequestOptionsBase extends Omit<Config, 'global'> {
interface RequestOptionsBase extends Config {
path?: Record<string, unknown>;
query?: Record<string, unknown>;
url: string;
Expand Down Expand Up @@ -131,6 +125,7 @@ interface ClientBase<Request = unknown, Response = unknown, Options = unknown> {
post: MethodFn;
put: MethodFn;
request: RequestFn;
setConfig: (config: Config) => Config;
trace: MethodFn;
}

Expand Down
13 changes: 11 additions & 2 deletions packages/client-fetch/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,15 @@ export const getUrl = ({
return url;
};

export const mergeConfigs = (a: Config, b: Config): Config => {
const config = { ...a, ...b };
if (config.baseUrl?.endsWith('/')) {
config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
}
config.headers = mergeHeaders(a.headers, b.headers);
return config;
};

export const mergeHeaders = (
...headers: Array<Required<Config>['headers'] | undefined>
) => {
Expand Down Expand Up @@ -542,11 +551,11 @@ const defaultHeaders = {
'Content-Type': 'application/json',
};

export const createDefaultConfig = (): Config => ({
export const createConfig = (override: Config = {}): Config => ({
...jsonBodySerializer,
baseUrl: '',
fetch: globalThis.fetch,
global: true,
headers: defaultHeaders,
querySerializer: defaultQuerySerializer,
...override,
});
11 changes: 5 additions & 6 deletions packages/openapi-ts/src/compiler/classes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import ts from 'typescript';

import { createCallExpression } from './module';
import { createTypeNode } from './typedef';
import {
type AccessLevel,
Expand Down Expand Up @@ -124,14 +125,12 @@ export const createClassDeclaration = ({
if (decorator) {
modifiers = [
ts.factory.createDecorator(
// TODO: refactor to call `createCallExpression()` from 'compiler/function'
ts.factory.createCallExpression(
ts.factory.createIdentifier(decorator.name),
undefined,
decorator.args
createCallExpression({
functionName: decorator.name,
parameters: decorator.args
.map((arg) => toExpression({ value: arg }))
.filter(isType<ts.Expression>),
),
}),
),
...modifiers,
];
Expand Down
22 changes: 0 additions & 22 deletions packages/openapi-ts/src/compiler/function.ts

This file was deleted.

19 changes: 9 additions & 10 deletions packages/openapi-ts/src/compiler/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ import ts from 'typescript';

import * as classes from './classes';
import * as convert from './convert';
import * as functions from './function';
import * as module from './module';
import * as _return from './return';
import * as transform from './transform';
import * as typedef from './typedef';
import * as types from './types';
import { stringToTsNodes, tsNodeToString } from './utils';
import * as utils from './utils';

export type { Property } from './typedef';
export type { FunctionParameter } from './types';
Expand Down Expand Up @@ -104,15 +103,15 @@ export class TypeScriptFile {
if (this._imports.length) {
output = [
...output,
this._imports.map((node) => tsNodeToString({ node })).join('\n'),
this._imports.map((node) => utils.tsNodeToString({ node })).join('\n'),
];
}
output = [
...output,
...this._items.map((node) =>
typeof node === 'string'
? node
: tsNodeToString({ node, unescape: true }),
: utils.tsNodeToString({ node, unescape: true }),
),
];
return output.join(seperator);
Expand All @@ -138,12 +137,8 @@ export const compiler = {
},
export: {
all: module.createExportAllDeclaration,
const: module.createExportConstVariable,
named: module.createNamedExportDeclarations,
},
function: {
call: functions.createCallExpression,
},
import: {
named: module.createNamedImportDeclarations,
},
Expand Down Expand Up @@ -177,12 +172,16 @@ export const compiler = {
},
types: {
array: types.createArrayType,
call: module.createCallExpression,
const: module.createConstVariable,
enum: types.createEnumDeclaration,
function: types.createFunction,
object: types.createObjectType,
},
utils: {
toNode: stringToTsNodes,
toString: tsNodeToString,
isTsNode: utils.isTsNode,
ots: utils.ots,
toNode: utils.stringToTsNodes,
toString: utils.tsNodeToString,
},
};
Loading

0 comments on commit e6b0040

Please sign in to comment.