Skip to content

Commit 92dd0ef

Browse files
committed
Create base packages openapi-tanstack-query
1 parent ff93eac commit 92dd0ef

16 files changed

+2708
-8
lines changed

packages/openapi-fetch/src/index.d.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,7 @@ export type ClientMethod<
169169
: [Init & { [key: string]: unknown }]
170170
) => Promise<FetchResponse<Paths[Path][Method], Init, Media>>;
171171

172-
export default function createClient<Paths extends {}, Media extends MediaType = MediaType>(
173-
clientOptions?: ClientOptions,
174-
): {
172+
export interface Client<Paths extends {}, Media extends MediaType = MediaType> {
175173
/** Call a GET endpoint */
176174
GET: ClientMethod<Paths, "get", Media>;
177175
/** Call a PUT endpoint */
@@ -192,7 +190,11 @@ export default function createClient<Paths extends {}, Media extends MediaType =
192190
use(...middleware: Middleware[]): void;
193191
/** Unregister middleware */
194192
eject(...middleware: Middleware[]): void;
195-
};
193+
}
194+
195+
export default function createClient<Paths extends {}, Media extends MediaType = MediaType>(
196+
clientOptions?: ClientOptions,
197+
): Client<Paths, Media>;
196198

197199
/** Serialize primitive params to string */
198200
export declare function serializePrimitiveParam(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
examples
2+
test
3+
vitest.config.ts
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"$schema": "https://biomejs.dev/schemas/1.8.1/schema.json",
3+
"extends": ["../../biome.json"],
4+
"files": {
5+
"include": ["./src/", "./test/"],
6+
"ignore": ["**/fixtures/**/*"]
7+
},
8+
"linter": {
9+
"rules": {
10+
"complexity": {
11+
"noBannedTypes": "off"
12+
},
13+
"suspicious": {
14+
"noConfusingVoidType": "off"
15+
}
16+
}
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
{
2+
"name": "openapi-tanstack-query",
3+
"description": "Fast, type-safe fetch client for your OpenAPI schema. Only 5 kb (min). Works with React, Vue, Svelte, or vanilla JS.",
4+
"version": "0.0.1",
5+
"author": {
6+
"name": "Drew Powers",
7+
"email": "[email protected]"
8+
},
9+
"license": "MIT",
10+
"type": "module",
11+
"main": "./dist/index.js",
12+
"module": "./dist/index.js",
13+
"types": "./dist/index.d.ts",
14+
"exports": {
15+
".": {
16+
"import": {
17+
"types": "./dist/index.d.ts",
18+
"default": "./dist/index.js"
19+
},
20+
"require": {
21+
"types": "./dist/cjs/index.d.cts",
22+
"default": "./dist/cjs/index.cjs"
23+
}
24+
},
25+
"./*": "./*"
26+
},
27+
"homepage": "https://openapi-ts.dev",
28+
"repository": {
29+
"type": "git",
30+
"url": "https://github.com/openapi-ts/openapi-typescript",
31+
"directory": "packages/openapi-fetch"
32+
},
33+
"bugs": {
34+
"url": "https://github.com/openapi-ts/openapi-typescript/issues"
35+
},
36+
"keywords": [
37+
"openapi",
38+
"swagger",
39+
"rest",
40+
"api",
41+
"oapi_3",
42+
"oapi_3_1",
43+
"typescript",
44+
"fetch",
45+
"react",
46+
"vue",
47+
"svelte"
48+
],
49+
"scripts": {
50+
"build": "pnpm run build:clean && pnpm run build:js && pnpm run build:js-min && pnpm run build:cjs",
51+
"build:clean": "del-cli dist",
52+
"build:js": "mkdir -p dist && cp src/* dist",
53+
"build:js-min": "esbuild --bundle src/index.js --format=esm --minify --outfile=dist/index.min.js && cp dist/index.d.ts dist/index.min.d.ts",
54+
"build:cjs": "esbuild --bundle src/index.js --format=cjs --outfile=dist/cjs/index.cjs && cp dist/index.d.ts dist/cjs/index.d.cts",
55+
"format": "biome format . --write",
56+
"lint": "biome check .",
57+
"generate-types": "openapi-typescript test/fixtures/api.yaml -o test/fixtures/api.d.ts",
58+
"pretest": "pnpm run generate-types",
59+
"test": "pnpm run \"/^test:/\"",
60+
"test:js": "vitest run",
61+
"test:ts": "tsc --noEmit",
62+
"version": "pnpm run prepare && pnpm run build"
63+
},
64+
"dependencies": {
65+
"@tanstack/react-query": "^5.45.1",
66+
"nanoid": "^5.0.7",
67+
"openapi-fetch": "workspace:^",
68+
"openapi-typescript-helpers": "workspace:^"
69+
},
70+
"devDependencies": {
71+
"@testing-library/react": "^16.0.0",
72+
"@types/react": "18.3.1",
73+
"@vitejs/plugin-react": "^4.3.1",
74+
"axios": "^1.7.2",
75+
"del-cli": "^5.1.0",
76+
"esbuild": "^0.20.2",
77+
"execa": "^8.0.1",
78+
"msw": "^2.3.1",
79+
"openapi-typescript": "workspace:^",
80+
"openapi-typescript-codegen": "^0.25.0",
81+
"openapi-typescript-fetch": "^2.0.0",
82+
"react": "^18.3.1",
83+
"superagent": "^9.0.2",
84+
"typescript": "^5.4.5",
85+
"vitest": "^1.6.0"
86+
}
87+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import type { UseMutationResult, UseQueryResult } from "@tanstack/react-query";
2+
import type { MaybeOptionalInit, Client, FetchResponse } from "openapi-fetch";
3+
import type {
4+
ErrorResponse,
5+
FilterKeys,
6+
HasRequiredKeys,
7+
HttpMethod,
8+
MediaType,
9+
OperationRequestBodyContent,
10+
PathsWithMethod,
11+
ResponseObjectMap,
12+
SuccessResponse,
13+
} from "openapi-typescript-helpers";
14+
15+
export type UseQueryMethod<Paths extends Record<string, Record<HttpMethod, {}>>, Media extends MediaType> = <
16+
Method extends HttpMethod,
17+
Path extends PathsWithMethod<Paths, Method>,
18+
Init extends MaybeOptionalInit<Paths[Path], Method>,
19+
Response extends FetchResponse<Paths[Path][Method], Init, Media>,
20+
>(
21+
method: Method,
22+
url: Path,
23+
...init: HasRequiredKeys<Init> extends never
24+
? [(Init & { [key: string]: unknown })?] // note: the arbitrary [key: string]: addition MUST happen here after all the inference happens (otherwise TS can’t infer if it’s required or not)
25+
: [Init & { [key: string]: unknown }]
26+
) => UseQueryResult<NonNullable<Response["data"]>, NonNullable<Response["error"]>>;
27+
28+
export type UseMutationMethod<Paths extends Record<string, Record<HttpMethod, {}>>, Media extends MediaType> = <
29+
Method extends HttpMethod,
30+
Path extends PathsWithMethod<Paths, Method>,
31+
Init extends MaybeOptionalInit<Paths[Path], Method>,
32+
Response extends FetchResponse<Paths[Path][Method], Init, Media>,
33+
>(
34+
method: Method,
35+
url: Path,
36+
...init: HasRequiredKeys<Init> extends never
37+
? [(Init & { [key: string]: unknown })?] // note: the arbitrary [key: string]: addition MUST happen here after all the inference happens (otherwise TS can’t infer if it’s required or not)
38+
: [Init & { [key: string]: unknown }]
39+
) => UseMutationResult<NonNullable<Response["data"]>, NonNullable<Response["error"]>>;
40+
41+
export interface OpenapiQueryClient<Paths extends {}, Media extends MediaType = MediaType> {
42+
useQuery: UseQueryMethod<Paths, Media>;
43+
useMutation: UseMutationMethod<Paths, Media>;
44+
}
45+
46+
export default function createClient<Paths extends {}, Media extends MediaType = MediaType>(
47+
client: Client<Paths, Media>,
48+
): {
49+
useQuery: UseQueryMethod<Paths, Media>;
50+
useMutation: UseMutationMethod<Paths, Media>;
51+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { useMutation, useQuery } from "@tanstack/react-query";
2+
3+
/**
4+
* Create an openapi-fetch client.
5+
* @type {import("./index.js").default}
6+
*/
7+
export default function createClient(client) {
8+
return {
9+
useQuery: (method, url, init, options) =>
10+
useQuery({
11+
queryKey: [method, url, init],
12+
queryFn: async () => {
13+
const { data, error } = await client[method.toUpperCase()](url, init);
14+
if (error) {
15+
throw error;
16+
}
17+
return data;
18+
},
19+
...options,
20+
}),
21+
useMutation: (method, url, init, options) =>
22+
useMutation({
23+
mutationKey: [method, url, init],
24+
mutationFn: async () => {
25+
const { data, error } = await client[method.toUpperCase()](url, init);
26+
if (error) {
27+
throw error;
28+
}
29+
return data;
30+
},
31+
...options,
32+
}),
33+
};
34+
}

0 commit comments

Comments
 (0)