@kizunajs/tanstack-query 2.0.0-beta.12 → 2.0.0-beta.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -3
- package/dist/index.cjs +14 -13
- package/dist/index.d.cts +25 -20
- package/dist/index.d.mts +25 -20
- package/dist/index.mjs +13 -12
- package/package.json +5 -8
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @kizunajs/tanstack-query
|
|
2
2
|
|
|
3
|
-
`@kizunajs/tanstack-query` provides `new KizunaTanstackQuery()`, which builds TanStack Query options from a Kizuna
|
|
3
|
+
`@kizunajs/tanstack-query` provides `new KizunaTanstackQuery()`, which builds TanStack Query options from a generated Kizuna fetch client. Query keys, caching, and invalidation come from the routes you already wrote.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -13,9 +13,13 @@ pnpm add @kizunajs/tanstack-query
|
|
|
13
13
|
```ts
|
|
14
14
|
import { useQuery } from '@tanstack/react-query';
|
|
15
15
|
import { KizunaTanstackQuery } from '@kizunajs/tanstack-query';
|
|
16
|
-
import {
|
|
16
|
+
import { createClient } from './api-client.generated';
|
|
17
17
|
|
|
18
|
-
const api = new KizunaTanstackQuery(
|
|
18
|
+
const api = new KizunaTanstackQuery(
|
|
19
|
+
createClient({
|
|
20
|
+
baseUrl: 'http://localhost:3000',
|
|
21
|
+
})
|
|
22
|
+
);
|
|
19
23
|
|
|
20
24
|
const { data } = useQuery(
|
|
21
25
|
api.users.getUser.queryOptions({
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
let _tanstack_query_core = require("@tanstack/query-core");
|
|
3
|
-
let kizunajs = require("kizunajs");
|
|
4
|
-
let _kizunajs_fetch = require("@kizunajs/fetch");
|
|
5
3
|
//#region src/errors.ts
|
|
6
4
|
/**
|
|
7
5
|
* Thrown when a route returns a status the api does not declare. Declared
|
|
@@ -57,10 +55,9 @@ const buildQueryKey = (segments, input, type) => {
|
|
|
57
55
|
const buildPathKey = (segments) => [segments];
|
|
58
56
|
//#endregion
|
|
59
57
|
//#region src/proxy.ts
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
};
|
|
58
|
+
const routeOf = (value) => typeof value === "function" ? value["~route"] : void 0;
|
|
59
|
+
const declaresStatus = (route, status) => Object.hasOwn(route.responses, status);
|
|
60
|
+
const streamsStatus = (route, status) => route.responses[status]?.stream === true;
|
|
64
61
|
const withSignal = (args, signal) => {
|
|
65
62
|
if (signal === void 0) return args;
|
|
66
63
|
const { fetchOptions, ...rest } = args ?? {};
|
|
@@ -81,7 +78,7 @@ const isQueryMethod = (route) => route.method === "GET" || route.method === "HEA
|
|
|
81
78
|
const buildProcedure = (segments, route, clientFn) => {
|
|
82
79
|
const routeKey = segments.join(".");
|
|
83
80
|
const call = (args) => clientFn(args);
|
|
84
|
-
if (
|
|
81
|
+
if (route.streams) return {
|
|
85
82
|
streamOptions: (options) => {
|
|
86
83
|
const { input, refetchMode, ...rest } = options;
|
|
87
84
|
const skipped = input === _tanstack_query_core.skipToken;
|
|
@@ -90,7 +87,7 @@ const buildProcedure = (segments, route, clientFn) => {
|
|
|
90
87
|
queryFn: skipped ? _tanstack_query_core.skipToken : (0, _tanstack_query_core.experimental_streamedQuery)({
|
|
91
88
|
streamFn: async ({ signal }) => {
|
|
92
89
|
const result = await runRoute(clientFn, route, routeKey, input, signal);
|
|
93
|
-
if (!(
|
|
90
|
+
if (!streamsStatus(route, result.status)) throw new NonStreamResponseError(routeKey, result.status, result.body, result.headers);
|
|
94
91
|
return result.body;
|
|
95
92
|
},
|
|
96
93
|
...refetchMode === void 0 ? {} : { refetchMode }
|
|
@@ -146,7 +143,7 @@ const buildNode = (segments, clientNode) => {
|
|
|
146
143
|
for (const routeName of Object.keys(clientNode)) {
|
|
147
144
|
const child = clientNode[routeName];
|
|
148
145
|
const childSegments = [...segments, routeName];
|
|
149
|
-
const route =
|
|
146
|
+
const route = routeOf(child);
|
|
150
147
|
if (route) node[routeName] = buildProcedure(childSegments, route, child);
|
|
151
148
|
else if (child && typeof child === "object") node[routeName] = buildNode(childSegments, child);
|
|
152
149
|
}
|
|
@@ -156,15 +153,19 @@ function buildQueryProxy(client) {
|
|
|
156
153
|
return buildNode([], client);
|
|
157
154
|
}
|
|
158
155
|
/**
|
|
159
|
-
* Builds TanStack Query options from a fetch client. Every client
|
|
160
|
-
* carries the route it answers, so the client is the only argument.
|
|
156
|
+
* Builds TanStack Query options from a generated fetch client. Every client
|
|
157
|
+
* method carries the route it answers, so the client is the only argument.
|
|
161
158
|
*
|
|
162
159
|
* ```ts
|
|
163
160
|
* import { useQuery } from '@tanstack/react-query';
|
|
164
161
|
* import { KizunaTanstackQuery } from '@kizunajs/tanstack-query';
|
|
165
|
-
* import {
|
|
162
|
+
* import { createClient } from './api-client.generated.js';
|
|
166
163
|
*
|
|
167
|
-
* const api = new KizunaTanstackQuery(
|
|
164
|
+
* const api = new KizunaTanstackQuery(
|
|
165
|
+
* createClient({
|
|
166
|
+
* baseUrl: 'http://localhost:3000',
|
|
167
|
+
* })
|
|
168
|
+
* );
|
|
168
169
|
*
|
|
169
170
|
* useQuery(
|
|
170
171
|
* api.users.listUsers.queryOptions({
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { DataTag, DefaultError, InfiniteData, InfiniteQueryObserverOptions, MutationObserverOptions, QueryFunction, QueryFunctionContext, QueryObserverOptions, SkipToken } from "@tanstack/query-core";
|
|
2
|
-
import { RouteDefinition, Routes, StreamResponseDefinition } from "kizunajs";
|
|
3
|
-
import { Client, ClientArgs, ClientMethod, ClientResponse } from "@kizunajs/fetch";
|
|
4
2
|
|
|
5
3
|
//#region src/types.d.ts
|
|
6
4
|
type KizunaQueryKeyType = 'query' | 'infinite' | 'stream';
|
|
@@ -151,43 +149,50 @@ interface StreamProcedure<Args, Result> {
|
|
|
151
149
|
key: () => KizunaPathKey;
|
|
152
150
|
call: CallFn<Args, Result>;
|
|
153
151
|
}
|
|
154
|
-
|
|
152
|
+
/**
|
|
153
|
+
* A method on a client `@kizunajs/fetch` generates. Its `'~route'` names the
|
|
154
|
+
* HTTP method it sends and whether its response streams, which is all the
|
|
155
|
+
* proxy needs to choose its factories.
|
|
156
|
+
*/
|
|
157
|
+
type ClientMethod<Method extends string, Streams extends boolean, Args, Result> = ({} extends Args ? (args?: Args) => Promise<Result> : (args: Args) => Promise<Result>) & {
|
|
158
|
+
readonly '~route': {
|
|
159
|
+
readonly method: Method;
|
|
160
|
+
readonly streams: Streams;
|
|
161
|
+
};
|
|
162
|
+
};
|
|
155
163
|
/**
|
|
156
164
|
* Which factories a route gets: a streamed response takes `streamOptions`, a
|
|
157
165
|
* `GET` or `HEAD` takes the query factories, and everything else mutates.
|
|
158
166
|
*/
|
|
159
167
|
type ProcedureFor<Method, Streams, Args, Result> = Streams extends true ? StreamProcedure<Args, Result> : Method extends 'GET' | 'HEAD' ? QueryProcedure<Args, Result> : MutationProcedure<Args, Result>;
|
|
160
|
-
type Procedure<R extends RouteDefinition, Codes extends string> = ProcedureFor<R['method'], HasStream<R>, ClientArgs<R>, ClientResponse<R, Codes>>;
|
|
161
168
|
/**
|
|
162
|
-
* The
|
|
169
|
+
* The client's tree, each method carrying its query, mutation, or stream
|
|
170
|
+
* factories and each group its partial key.
|
|
163
171
|
*/
|
|
164
|
-
type KizunaQueryProxy<
|
|
165
|
-
/**
|
|
166
|
-
* The same tree, read off a generated client instead of off the routes. Each of
|
|
167
|
-
* its methods carries the method it calls and whether that response streams, so
|
|
168
|
-
* the client alone says which factories every route gets.
|
|
169
|
-
*/
|
|
170
|
-
type GeneratedQueryProxy<C> = { [K in keyof C as K extends string ? K : never]: C[K] extends ClientMethod<infer Method, infer Streams, infer Args, infer Result> ? ProcedureFor<Method, Streams, Args, Result> : C[K] extends object ? GeneratedQueryProxy<C[K]> & PathProcedures : never };
|
|
172
|
+
type KizunaQueryProxy<C> = { [K in keyof C as K extends string ? K : never]: C[K] extends ClientMethod<infer Method, infer Streams, infer Args, infer Result> ? ProcedureFor<Method, Streams, Args, Result> : C[K] extends object ? KizunaQueryProxy<C[K]> & PathProcedures : never };
|
|
171
173
|
interface KizunaTanstackQueryConstructor {
|
|
172
174
|
/**
|
|
173
|
-
* The client is the only argument: each of its methods carries
|
|
174
|
-
*
|
|
175
|
+
* The generated client is the only argument: each of its methods carries
|
|
176
|
+
* the route it answers.
|
|
175
177
|
*/
|
|
176
|
-
new <
|
|
177
|
-
new <C extends object>(client: C): GeneratedQueryProxy<C> & PathProcedures;
|
|
178
|
+
new <C extends object>(client: C): KizunaQueryProxy<C> & PathProcedures;
|
|
178
179
|
}
|
|
179
180
|
//#endregion
|
|
180
181
|
//#region src/proxy.d.ts
|
|
181
182
|
/**
|
|
182
|
-
* Builds TanStack Query options from a fetch client. Every client
|
|
183
|
-
* carries the route it answers, so the client is the only argument.
|
|
183
|
+
* Builds TanStack Query options from a generated fetch client. Every client
|
|
184
|
+
* method carries the route it answers, so the client is the only argument.
|
|
184
185
|
*
|
|
185
186
|
* ```ts
|
|
186
187
|
* import { useQuery } from '@tanstack/react-query';
|
|
187
188
|
* import { KizunaTanstackQuery } from '@kizunajs/tanstack-query';
|
|
188
|
-
* import {
|
|
189
|
+
* import { createClient } from './api-client.generated.js';
|
|
189
190
|
*
|
|
190
|
-
* const api = new KizunaTanstackQuery(
|
|
191
|
+
* const api = new KizunaTanstackQuery(
|
|
192
|
+
* createClient({
|
|
193
|
+
* baseUrl: 'http://localhost:3000',
|
|
194
|
+
* })
|
|
195
|
+
* );
|
|
191
196
|
*
|
|
192
197
|
* useQuery(
|
|
193
198
|
* api.users.listUsers.queryOptions({
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { DataTag, DefaultError, InfiniteData, InfiniteQueryObserverOptions, MutationObserverOptions, QueryFunction, QueryFunctionContext, QueryObserverOptions, SkipToken } from "@tanstack/query-core";
|
|
2
|
-
import { RouteDefinition, Routes, StreamResponseDefinition } from "kizunajs";
|
|
3
|
-
import { Client, ClientArgs, ClientMethod, ClientResponse } from "@kizunajs/fetch";
|
|
4
2
|
|
|
5
3
|
//#region src/types.d.ts
|
|
6
4
|
type KizunaQueryKeyType = 'query' | 'infinite' | 'stream';
|
|
@@ -151,43 +149,50 @@ interface StreamProcedure<Args, Result> {
|
|
|
151
149
|
key: () => KizunaPathKey;
|
|
152
150
|
call: CallFn<Args, Result>;
|
|
153
151
|
}
|
|
154
|
-
|
|
152
|
+
/**
|
|
153
|
+
* A method on a client `@kizunajs/fetch` generates. Its `'~route'` names the
|
|
154
|
+
* HTTP method it sends and whether its response streams, which is all the
|
|
155
|
+
* proxy needs to choose its factories.
|
|
156
|
+
*/
|
|
157
|
+
type ClientMethod<Method extends string, Streams extends boolean, Args, Result> = ({} extends Args ? (args?: Args) => Promise<Result> : (args: Args) => Promise<Result>) & {
|
|
158
|
+
readonly '~route': {
|
|
159
|
+
readonly method: Method;
|
|
160
|
+
readonly streams: Streams;
|
|
161
|
+
};
|
|
162
|
+
};
|
|
155
163
|
/**
|
|
156
164
|
* Which factories a route gets: a streamed response takes `streamOptions`, a
|
|
157
165
|
* `GET` or `HEAD` takes the query factories, and everything else mutates.
|
|
158
166
|
*/
|
|
159
167
|
type ProcedureFor<Method, Streams, Args, Result> = Streams extends true ? StreamProcedure<Args, Result> : Method extends 'GET' | 'HEAD' ? QueryProcedure<Args, Result> : MutationProcedure<Args, Result>;
|
|
160
|
-
type Procedure<R extends RouteDefinition, Codes extends string> = ProcedureFor<R['method'], HasStream<R>, ClientArgs<R>, ClientResponse<R, Codes>>;
|
|
161
168
|
/**
|
|
162
|
-
* The
|
|
169
|
+
* The client's tree, each method carrying its query, mutation, or stream
|
|
170
|
+
* factories and each group its partial key.
|
|
163
171
|
*/
|
|
164
|
-
type KizunaQueryProxy<
|
|
165
|
-
/**
|
|
166
|
-
* The same tree, read off a generated client instead of off the routes. Each of
|
|
167
|
-
* its methods carries the method it calls and whether that response streams, so
|
|
168
|
-
* the client alone says which factories every route gets.
|
|
169
|
-
*/
|
|
170
|
-
type GeneratedQueryProxy<C> = { [K in keyof C as K extends string ? K : never]: C[K] extends ClientMethod<infer Method, infer Streams, infer Args, infer Result> ? ProcedureFor<Method, Streams, Args, Result> : C[K] extends object ? GeneratedQueryProxy<C[K]> & PathProcedures : never };
|
|
172
|
+
type KizunaQueryProxy<C> = { [K in keyof C as K extends string ? K : never]: C[K] extends ClientMethod<infer Method, infer Streams, infer Args, infer Result> ? ProcedureFor<Method, Streams, Args, Result> : C[K] extends object ? KizunaQueryProxy<C[K]> & PathProcedures : never };
|
|
171
173
|
interface KizunaTanstackQueryConstructor {
|
|
172
174
|
/**
|
|
173
|
-
* The client is the only argument: each of its methods carries
|
|
174
|
-
*
|
|
175
|
+
* The generated client is the only argument: each of its methods carries
|
|
176
|
+
* the route it answers.
|
|
175
177
|
*/
|
|
176
|
-
new <
|
|
177
|
-
new <C extends object>(client: C): GeneratedQueryProxy<C> & PathProcedures;
|
|
178
|
+
new <C extends object>(client: C): KizunaQueryProxy<C> & PathProcedures;
|
|
178
179
|
}
|
|
179
180
|
//#endregion
|
|
180
181
|
//#region src/proxy.d.ts
|
|
181
182
|
/**
|
|
182
|
-
* Builds TanStack Query options from a fetch client. Every client
|
|
183
|
-
* carries the route it answers, so the client is the only argument.
|
|
183
|
+
* Builds TanStack Query options from a generated fetch client. Every client
|
|
184
|
+
* method carries the route it answers, so the client is the only argument.
|
|
184
185
|
*
|
|
185
186
|
* ```ts
|
|
186
187
|
* import { useQuery } from '@tanstack/react-query';
|
|
187
188
|
* import { KizunaTanstackQuery } from '@kizunajs/tanstack-query';
|
|
188
|
-
* import {
|
|
189
|
+
* import { createClient } from './api-client.generated.js';
|
|
189
190
|
*
|
|
190
|
-
* const api = new KizunaTanstackQuery(
|
|
191
|
+
* const api = new KizunaTanstackQuery(
|
|
192
|
+
* createClient({
|
|
193
|
+
* baseUrl: 'http://localhost:3000',
|
|
194
|
+
* })
|
|
195
|
+
* );
|
|
191
196
|
*
|
|
192
197
|
* useQuery(
|
|
193
198
|
* api.users.listUsers.queryOptions({
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { experimental_streamedQuery, skipToken } from "@tanstack/query-core";
|
|
2
|
-
import { routeStreams, streamStatuses } from "kizunajs";
|
|
3
|
-
import { routeOf } from "@kizunajs/fetch";
|
|
4
2
|
//#region src/errors.ts
|
|
5
3
|
/**
|
|
6
4
|
* Thrown when a route returns a status the api does not declare. Declared
|
|
@@ -56,10 +54,9 @@ const buildQueryKey = (segments, input, type) => {
|
|
|
56
54
|
const buildPathKey = (segments) => [segments];
|
|
57
55
|
//#endregion
|
|
58
56
|
//#region src/proxy.ts
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
};
|
|
57
|
+
const routeOf = (value) => typeof value === "function" ? value["~route"] : void 0;
|
|
58
|
+
const declaresStatus = (route, status) => Object.hasOwn(route.responses, status);
|
|
59
|
+
const streamsStatus = (route, status) => route.responses[status]?.stream === true;
|
|
63
60
|
const withSignal = (args, signal) => {
|
|
64
61
|
if (signal === void 0) return args;
|
|
65
62
|
const { fetchOptions, ...rest } = args ?? {};
|
|
@@ -80,7 +77,7 @@ const isQueryMethod = (route) => route.method === "GET" || route.method === "HEA
|
|
|
80
77
|
const buildProcedure = (segments, route, clientFn) => {
|
|
81
78
|
const routeKey = segments.join(".");
|
|
82
79
|
const call = (args) => clientFn(args);
|
|
83
|
-
if (
|
|
80
|
+
if (route.streams) return {
|
|
84
81
|
streamOptions: (options) => {
|
|
85
82
|
const { input, refetchMode, ...rest } = options;
|
|
86
83
|
const skipped = input === skipToken;
|
|
@@ -89,7 +86,7 @@ const buildProcedure = (segments, route, clientFn) => {
|
|
|
89
86
|
queryFn: skipped ? skipToken : experimental_streamedQuery({
|
|
90
87
|
streamFn: async ({ signal }) => {
|
|
91
88
|
const result = await runRoute(clientFn, route, routeKey, input, signal);
|
|
92
|
-
if (!
|
|
89
|
+
if (!streamsStatus(route, result.status)) throw new NonStreamResponseError(routeKey, result.status, result.body, result.headers);
|
|
93
90
|
return result.body;
|
|
94
91
|
},
|
|
95
92
|
...refetchMode === void 0 ? {} : { refetchMode }
|
|
@@ -155,15 +152,19 @@ function buildQueryProxy(client) {
|
|
|
155
152
|
return buildNode([], client);
|
|
156
153
|
}
|
|
157
154
|
/**
|
|
158
|
-
* Builds TanStack Query options from a fetch client. Every client
|
|
159
|
-
* carries the route it answers, so the client is the only argument.
|
|
155
|
+
* Builds TanStack Query options from a generated fetch client. Every client
|
|
156
|
+
* method carries the route it answers, so the client is the only argument.
|
|
160
157
|
*
|
|
161
158
|
* ```ts
|
|
162
159
|
* import { useQuery } from '@tanstack/react-query';
|
|
163
160
|
* import { KizunaTanstackQuery } from '@kizunajs/tanstack-query';
|
|
164
|
-
* import {
|
|
161
|
+
* import { createClient } from './api-client.generated.js';
|
|
165
162
|
*
|
|
166
|
-
* const api = new KizunaTanstackQuery(
|
|
163
|
+
* const api = new KizunaTanstackQuery(
|
|
164
|
+
* createClient({
|
|
165
|
+
* baseUrl: 'http://localhost:3000',
|
|
166
|
+
* })
|
|
167
|
+
* );
|
|
167
168
|
*
|
|
168
169
|
* useQuery(
|
|
169
170
|
* api.users.listUsers.queryOptions({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kizunajs/tanstack-query",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.14",
|
|
4
4
|
"description": "TanStack Query client for Kizuna.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"kizunajs",
|
|
@@ -56,10 +56,7 @@
|
|
|
56
56
|
"access": "public"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"@tanstack/query-core": "^5.69.0"
|
|
60
|
-
"zod": "^4.0.0",
|
|
61
|
-
"kizunajs": "2.0.0-beta.12",
|
|
62
|
-
"@kizunajs/fetch": "2.0.0-beta.12"
|
|
59
|
+
"@tanstack/query-core": "^5.69.0"
|
|
63
60
|
},
|
|
64
61
|
"devDependencies": {
|
|
65
62
|
"@tanstack/query-core": "^5.101.0",
|
|
@@ -73,11 +70,11 @@
|
|
|
73
70
|
"typescript": "^6.0.3",
|
|
74
71
|
"vue": "^3.5.0",
|
|
75
72
|
"zod": "^4.0.0",
|
|
76
|
-
"kizunajs": "2.0.0-beta.
|
|
77
|
-
"@kizunajs/fetch": "2.0.0-beta.
|
|
73
|
+
"kizunajs": "2.0.0-beta.14",
|
|
74
|
+
"@kizunajs/fetch": "2.0.0-beta.14"
|
|
78
75
|
},
|
|
79
76
|
"scripts": {
|
|
80
|
-
"build": "tsdown src/index.ts --format esm,cjs --dts --clean --external
|
|
77
|
+
"build": "tsdown src/index.ts --format esm,cjs --dts --clean --external @tanstack/query-core",
|
|
81
78
|
"typecheck": "tsc --noEmit"
|
|
82
79
|
}
|
|
83
80
|
}
|