Skip to content
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules/
examples/**/src/*.js
3 changes: 2 additions & 1 deletion examples/basic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
"version": "0.0.1",
"description": "",
"scripts": {
"dev": "tsc ./src/index.ts",
"dev": "tsc -p tsconfig.json",
"api-schema": "openapi-typescript http://localhost:3000/openapi.json -t -o ./src/schema.gen.ts"
},
"type": "module",
"keywords": [],
"author": "V3X Labs",
"license": "GPL-3.0-only",
Expand Down
4 changes: 3 additions & 1 deletion examples/basic/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { createFetch } from "openapi-hooks";
import { paths } from "./schema.gen";

const fetching = createFetch<paths>();
// Configure the fetcher with an explicit baseUrl so it works in Node.js as well
// as the browser.
const fetching = createFetch<paths>({ baseUrl: "http://localhost:3000" });

const response = await fetching('/site/{site_id}', 'get', {
path: {
Expand Down
53 changes: 53 additions & 0 deletions examples/basic/src/schema.gen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* This file was auto-generated by openapi-typescript.
* Do not make direct changes to the file.
*/

export interface paths {
"/site/{site_id}": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get: {
parameters: {
query?: never;
header?: never;
path: {
site_id: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description OK */
200: {
headers: {
[name: string]: unknown;
};
content?: never;
};
};
};
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
}
export type webhooks = Record<string, never>;
export interface components {
schemas: never;
responses: never;
parameters: never;
requestBodies: never;
headers: never;
pathItems: never;
}
export type $defs = Record<string, never>;
export type operations = Record<string, never>;
13 changes: 13 additions & 0 deletions examples/basic/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "es2022",
"module": "es2022",
"moduleResolution": "node",
"lib": ["es2022", "dom"],
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src"]
}
32 changes: 17 additions & 15 deletions packages/openapi-hooks/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
type Paths = {
[key: string]: {
[key: string]: any;
};
}

type HTTPMethod =
| 'get'
| 'put'
Expand All @@ -14,10 +8,14 @@ type HTTPMethod =
| 'patch'
| 'trace';

export type PathMethods<paths extends Paths, TPath extends keyof paths> = {
[TMethod in HTTPMethod]: paths[TPath][TMethod] extends undefined
? never
: TMethod;
export type PathMethods<TPaths, TPath extends keyof TPaths> = {
[TMethod in HTTPMethod]: TPaths[TPath] extends Record<string, any>
? TMethod extends keyof TPaths[TPath]
? TPaths[TPath][TMethod] extends undefined
? never
: TMethod
: never
: never;
}[HTTPMethod];

type AnyRequestBody = {
Expand Down Expand Up @@ -162,7 +160,7 @@ const decodeResponse = async (response, responseContentType) => {
}
};

export const createFetch = <paths extends Paths>(options?: OpenApiHookOptions) => {
export const createFetch = <TPaths>(options?: OpenApiHookOptions) => {
const { baseUrl = window.location.toString(), headers: defaultHeaders, onError } = options ?? {};

/**
Expand Down Expand Up @@ -249,13 +247,17 @@ export const createFetch = <paths extends Paths>(options?: OpenApiHookOptions) =
* @throws {Error} When an unsupported content type is encountered
*/
return async <
TPath extends keyof paths,
TMethod extends PathMethods<paths, TPath>,
TPath extends keyof TPaths,
TMethod extends PathMethods<TPaths, TPath>,
TOptions extends TRoute['parameters'] & ApiRequestBody<TRoute['requestBody']> & {
fetchOptions?: RequestInit;
},
TRoute extends AnyRoute = paths[TPath][TMethod] extends AnyRoute
? paths[TPath][TMethod]
TRoute extends AnyRoute = TPaths[TPath] extends Record<string, any>
? TMethod extends keyof TPaths[TPath]
? TPaths[TPath][TMethod] extends AnyRoute
? TPaths[TPath][TMethod]
: never
: never
: never,
>(
path: TPath,
Expand Down