appflare 0.2.25 → 0.2.27
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/Documentation.md +758 -758
- package/cli/commands/index.ts +238 -238
- package/cli/generate.ts +178 -178
- package/cli/index.ts +120 -120
- package/cli/load-config.ts +184 -184
- package/cli/schema-compiler.ts +1183 -1183
- package/cli/templates/auth/README.md +156 -156
- package/cli/templates/auth/config.ts +61 -61
- package/cli/templates/auth/route-config.ts +1 -1
- package/cli/templates/auth/route-handler.ts +1 -1
- package/cli/templates/auth/route-request-utils.ts +5 -5
- package/cli/templates/auth/route.config.ts +18 -18
- package/cli/templates/auth/route.handler.ts +18 -18
- package/cli/templates/auth/route.request-utils.ts +55 -55
- package/cli/templates/auth/route.ts +14 -14
- package/cli/templates/core/README.md +266 -266
- package/cli/templates/core/app-creation.ts +19 -19
- package/cli/templates/core/client/appflare.ts +112 -112
- package/cli/templates/core/client/handlers/index.ts +748 -748
- package/cli/templates/core/client/handlers.ts +1 -1
- package/cli/templates/core/client/index.ts +7 -7
- package/cli/templates/core/client/storage.ts +205 -180
- package/cli/templates/core/client/types.ts +186 -184
- package/cli/templates/core/client-modules/appflare.ts +1 -1
- package/cli/templates/core/client-modules/handlers.ts +1 -1
- package/cli/templates/core/client-modules/index.ts +1 -1
- package/cli/templates/core/client-modules/storage.ts +1 -1
- package/cli/templates/core/client-modules/types.ts +1 -1
- package/cli/templates/core/client.artifacts.ts +39 -39
- package/cli/templates/core/client.ts +4 -4
- package/cli/templates/core/drizzle.ts +15 -15
- package/cli/templates/core/export.ts +14 -14
- package/cli/templates/core/handlers.route.ts +24 -24
- package/cli/templates/core/handlers.ts +1 -1
- package/cli/templates/core/imports.ts +9 -9
- package/cli/templates/core/server.ts +38 -38
- package/cli/templates/core/types.ts +6 -6
- package/cli/templates/core/wrangler.ts +109 -109
- package/cli/templates/dashboard/builders/functions/index.ts +17 -17
- package/cli/templates/dashboard/builders/functions/render-page/header.ts +20 -20
- package/cli/templates/dashboard/builders/functions/render-page/index.ts +33 -33
- package/cli/templates/dashboard/builders/functions/render-page/request-panel.ts +171 -171
- package/cli/templates/dashboard/builders/functions/render-page/result-panel.ts +85 -85
- package/cli/templates/dashboard/builders/functions/render-page/scripts.ts +554 -554
- package/cli/templates/dashboard/builders/navigation.ts +122 -122
- package/cli/templates/dashboard/builders/storage/index.ts +13 -13
- package/cli/templates/dashboard/builders/storage/routes/create-directory-route.ts +29 -29
- package/cli/templates/dashboard/builders/storage/routes/delete-route.ts +18 -18
- package/cli/templates/dashboard/builders/storage/routes/download-route.ts +23 -23
- package/cli/templates/dashboard/builders/storage/routes/index.ts +22 -22
- package/cli/templates/dashboard/builders/storage/routes/list-route.ts +25 -25
- package/cli/templates/dashboard/builders/storage/routes/preview-route.ts +21 -21
- package/cli/templates/dashboard/builders/storage/routes/upload-route.ts +21 -21
- package/cli/templates/dashboard/builders/storage/runtime/helpers.ts +72 -72
- package/cli/templates/dashboard/builders/storage/runtime/storage-page.ts +130 -130
- package/cli/templates/dashboard/builders/table-routes/common/drawer-panel.ts +27 -27
- package/cli/templates/dashboard/builders/table-routes/common/pagination.ts +30 -30
- package/cli/templates/dashboard/builders/table-routes/common/search-bar.ts +23 -23
- package/cli/templates/dashboard/builders/table-routes/fragments.ts +217 -217
- package/cli/templates/dashboard/builders/table-routes/helpers.ts +45 -45
- package/cli/templates/dashboard/builders/table-routes/index.ts +8 -8
- package/cli/templates/dashboard/builders/table-routes/table/actions-cell.ts +71 -71
- package/cli/templates/dashboard/builders/table-routes/table/get-route.ts +291 -291
- package/cli/templates/dashboard/builders/table-routes/table/index.ts +80 -80
- package/cli/templates/dashboard/builders/table-routes/table/post-routes.ts +163 -163
- package/cli/templates/dashboard/builders/table-routes/table-route.ts +7 -7
- package/cli/templates/dashboard/builders/table-routes/users/get-route.ts +69 -69
- package/cli/templates/dashboard/builders/table-routes/users/html/modals.ts +57 -57
- package/cli/templates/dashboard/builders/table-routes/users/html/page.ts +27 -27
- package/cli/templates/dashboard/builders/table-routes/users/html/table.ts +128 -128
- package/cli/templates/dashboard/builders/table-routes/users/index.ts +32 -32
- package/cli/templates/dashboard/builders/table-routes/users/post-routes.ts +150 -150
- package/cli/templates/dashboard/builders/table-routes/users/redirect.ts +14 -14
- package/cli/templates/dashboard/builders/table-routes/users-route.ts +10 -10
- package/cli/templates/dashboard/components/dashboard-home.ts +23 -23
- package/cli/templates/dashboard/components/layout.ts +388 -388
- package/cli/templates/dashboard/components/login-page.ts +65 -65
- package/cli/templates/dashboard/index.ts +61 -61
- package/cli/templates/dashboard/types.ts +9 -9
- package/cli/templates/handlers/README.md +353 -353
- package/cli/templates/handlers/auth.ts +37 -37
- package/cli/templates/handlers/execution.ts +42 -42
- package/cli/templates/handlers/generators/context/context-creation.ts +101 -101
- package/cli/templates/handlers/generators/context/error-helpers.ts +11 -11
- package/cli/templates/handlers/generators/context/scheduler.ts +24 -24
- package/cli/templates/handlers/generators/context/storage-api.ts +82 -112
- package/cli/templates/handlers/generators/context/storage-helpers.ts +59 -59
- package/cli/templates/handlers/generators/context/types.ts +18 -18
- package/cli/templates/handlers/generators/context.ts +43 -43
- package/cli/templates/handlers/generators/execution.ts +15 -15
- package/cli/templates/handlers/generators/handlers.ts +13 -13
- package/cli/templates/handlers/generators/registration/modules/cron.ts +26 -26
- package/cli/templates/handlers/generators/registration/modules/realtime/auth.ts +75 -75
- package/cli/templates/handlers/generators/registration/modules/realtime/durable-object.ts +144 -144
- package/cli/templates/handlers/generators/registration/modules/realtime/index.ts +14 -14
- package/cli/templates/handlers/generators/registration/modules/realtime/publisher.ts +102 -102
- package/cli/templates/handlers/generators/registration/modules/realtime/routes.ts +164 -164
- package/cli/templates/handlers/generators/registration/modules/realtime/types.ts +30 -30
- package/cli/templates/handlers/generators/registration/modules/realtime/utils.ts +516 -516
- package/cli/templates/handlers/generators/registration/modules/scheduler.ts +56 -56
- package/cli/templates/handlers/generators/registration/modules/storage.ts +192 -194
- package/cli/templates/handlers/generators/registration/sections.ts +210 -210
- package/cli/templates/handlers/generators/types/context.ts +67 -66
- package/cli/templates/handlers/generators/types/core.ts +106 -106
- package/cli/templates/handlers/generators/types/operations.ts +135 -135
- package/cli/templates/handlers/generators/types/query-definitions/filter-and-where-types.ts +259 -259
- package/cli/templates/handlers/generators/types/query-definitions/query-api-types.ts +135 -135
- package/cli/templates/handlers/generators/types/query-definitions/query-helper-functions.ts +1031 -1031
- package/cli/templates/handlers/generators/types/query-definitions/schema-and-table-types.ts +246 -246
- package/cli/templates/handlers/generators/types/query-definitions.ts +13 -13
- package/cli/templates/handlers/generators/types/query-runtime/handled-error.ts +13 -13
- package/cli/templates/handlers/generators/types/query-runtime/runtime-aggregate-and-footer.ts +174 -174
- package/cli/templates/handlers/generators/types/query-runtime/runtime-read.ts +121 -121
- package/cli/templates/handlers/generators/types/query-runtime/runtime-setup.ts +45 -45
- package/cli/templates/handlers/generators/types/query-runtime/runtime-write.ts +676 -676
- package/cli/templates/handlers/generators/types/query-runtime.ts +15 -15
- package/cli/templates/handlers/index.ts +43 -43
- package/cli/templates/handlers/operations.ts +116 -116
- package/cli/templates/handlers/registration.ts +91 -91
- package/cli/templates/handlers/types.ts +15 -15
- package/cli/templates/handlers/utils.ts +48 -48
- package/cli/types.ts +110 -110
- package/cli/utils/handler-discovery.ts +466 -466
- package/cli/utils/json-utils.ts +24 -24
- package/cli/utils/path-utils.ts +19 -19
- package/cli/utils/schema-discovery.ts +399 -399
- package/dist/cli/index.js +95 -99
- package/dist/cli/index.mjs +95 -99
- package/index.ts +18 -18
- package/package.json +58 -58
- package/react/index.ts +5 -5
- package/react/use-infinite-query.ts +252 -252
- package/react/use-mutation.ts +89 -89
- package/react/use-query.ts +207 -207
- package/schema.ts +415 -415
- package/test-better-auth-hash.ts +2 -2
- package/tsconfig.json +6 -6
- package/tsup.config.ts +82 -82
- package/dist/cli/index.d.mts +0 -2
- package/dist/cli/index.d.ts +0 -2
package/react/use-mutation.ts
CHANGED
|
@@ -1,89 +1,89 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type UseMutationOptions,
|
|
3
|
-
type UseMutationResult,
|
|
4
|
-
useMutation as useTanstackMutation,
|
|
5
|
-
} from "@tanstack/react-query";
|
|
6
|
-
|
|
7
|
-
type AppflareRequestErrorLike = {
|
|
8
|
-
message: string;
|
|
9
|
-
status?: number;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
type AppflareRequestResultLike<TData> = {
|
|
13
|
-
data: TData | null;
|
|
14
|
-
error: AppflareRequestErrorLike | null;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
type AppflareRequiredInputKeys<TInput extends Record<string, unknown>> = {
|
|
18
|
-
[K in keyof TInput]-?: undefined extends TInput[K] ? never : K;
|
|
19
|
-
}[keyof TInput];
|
|
20
|
-
|
|
21
|
-
type AppflareHasRequiredInputKeys<TInput extends Record<string, unknown>> = [
|
|
22
|
-
AppflareRequiredInputKeys<TInput>,
|
|
23
|
-
] extends [never]
|
|
24
|
-
? false
|
|
25
|
-
: true;
|
|
26
|
-
|
|
27
|
-
type AppflareRouteRunArgs<TInput extends Record<string, unknown>> =
|
|
28
|
-
AppflareHasRequiredInputKeys<TInput> extends true
|
|
29
|
-
? [args: TInput, options?: any]
|
|
30
|
-
: [args?: TInput, options?: any];
|
|
31
|
-
|
|
32
|
-
type AppflareMutationVariables<TArgs extends Record<string, unknown>> =
|
|
33
|
-
AppflareHasRequiredInputKeys<TArgs> extends true ? TArgs : TArgs | void;
|
|
34
|
-
|
|
35
|
-
type AppflareMutationLike<TArgs extends Record<string, unknown>, TData> = {
|
|
36
|
-
run: (
|
|
37
|
-
...params: AppflareRouteRunArgs<TArgs>
|
|
38
|
-
) => Promise<AppflareRequestResultLike<TData>>;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
function toError(error: AppflareRequestErrorLike): Error {
|
|
42
|
-
const next = new Error(error.message);
|
|
43
|
-
if (error.status !== undefined) {
|
|
44
|
-
(next as Error & { status?: number }).status = error.status;
|
|
45
|
-
}
|
|
46
|
-
return next;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function useMutation<
|
|
50
|
-
TArgs extends Record<string, unknown>,
|
|
51
|
-
TData,
|
|
52
|
-
TContext = unknown,
|
|
53
|
-
>(
|
|
54
|
-
mutation: AppflareMutationLike<TArgs, TData>,
|
|
55
|
-
mutationOptions?: Omit<
|
|
56
|
-
UseMutationOptions<
|
|
57
|
-
TData,
|
|
58
|
-
Error,
|
|
59
|
-
AppflareMutationVariables<TArgs>,
|
|
60
|
-
TContext
|
|
61
|
-
>,
|
|
62
|
-
"mutationFn"
|
|
63
|
-
>,
|
|
64
|
-
): UseMutationResult<TData, Error, AppflareMutationVariables<TArgs>, TContext> {
|
|
65
|
-
return useTanstackMutation<
|
|
66
|
-
TData,
|
|
67
|
-
Error,
|
|
68
|
-
AppflareMutationVariables<TArgs>,
|
|
69
|
-
TContext
|
|
70
|
-
>({
|
|
71
|
-
...(mutationOptions as Omit<
|
|
72
|
-
UseMutationOptions<
|
|
73
|
-
TData,
|
|
74
|
-
Error,
|
|
75
|
-
AppflareMutationVariables<TArgs>,
|
|
76
|
-
TContext
|
|
77
|
-
>,
|
|
78
|
-
"mutationFn"
|
|
79
|
-
>),
|
|
80
|
-
mutationFn: async (args: AppflareMutationVariables<TArgs>) => {
|
|
81
|
-
const response = await mutation.run((args ?? {}) as TArgs);
|
|
82
|
-
if (response.error) {
|
|
83
|
-
throw toError(response.error);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return response.data as TData;
|
|
87
|
-
},
|
|
88
|
-
});
|
|
89
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
type UseMutationOptions,
|
|
3
|
+
type UseMutationResult,
|
|
4
|
+
useMutation as useTanstackMutation,
|
|
5
|
+
} from "@tanstack/react-query";
|
|
6
|
+
|
|
7
|
+
type AppflareRequestErrorLike = {
|
|
8
|
+
message: string;
|
|
9
|
+
status?: number;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
type AppflareRequestResultLike<TData> = {
|
|
13
|
+
data: TData | null;
|
|
14
|
+
error: AppflareRequestErrorLike | null;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type AppflareRequiredInputKeys<TInput extends Record<string, unknown>> = {
|
|
18
|
+
[K in keyof TInput]-?: undefined extends TInput[K] ? never : K;
|
|
19
|
+
}[keyof TInput];
|
|
20
|
+
|
|
21
|
+
type AppflareHasRequiredInputKeys<TInput extends Record<string, unknown>> = [
|
|
22
|
+
AppflareRequiredInputKeys<TInput>,
|
|
23
|
+
] extends [never]
|
|
24
|
+
? false
|
|
25
|
+
: true;
|
|
26
|
+
|
|
27
|
+
type AppflareRouteRunArgs<TInput extends Record<string, unknown>> =
|
|
28
|
+
AppflareHasRequiredInputKeys<TInput> extends true
|
|
29
|
+
? [args: TInput, options?: any]
|
|
30
|
+
: [args?: TInput, options?: any];
|
|
31
|
+
|
|
32
|
+
type AppflareMutationVariables<TArgs extends Record<string, unknown>> =
|
|
33
|
+
AppflareHasRequiredInputKeys<TArgs> extends true ? TArgs : TArgs | void;
|
|
34
|
+
|
|
35
|
+
type AppflareMutationLike<TArgs extends Record<string, unknown>, TData> = {
|
|
36
|
+
run: (
|
|
37
|
+
...params: AppflareRouteRunArgs<TArgs>
|
|
38
|
+
) => Promise<AppflareRequestResultLike<TData>>;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
function toError(error: AppflareRequestErrorLike): Error {
|
|
42
|
+
const next = new Error(error.message);
|
|
43
|
+
if (error.status !== undefined) {
|
|
44
|
+
(next as Error & { status?: number }).status = error.status;
|
|
45
|
+
}
|
|
46
|
+
return next;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function useMutation<
|
|
50
|
+
TArgs extends Record<string, unknown>,
|
|
51
|
+
TData,
|
|
52
|
+
TContext = unknown,
|
|
53
|
+
>(
|
|
54
|
+
mutation: AppflareMutationLike<TArgs, TData>,
|
|
55
|
+
mutationOptions?: Omit<
|
|
56
|
+
UseMutationOptions<
|
|
57
|
+
TData,
|
|
58
|
+
Error,
|
|
59
|
+
AppflareMutationVariables<TArgs>,
|
|
60
|
+
TContext
|
|
61
|
+
>,
|
|
62
|
+
"mutationFn"
|
|
63
|
+
>,
|
|
64
|
+
): UseMutationResult<TData, Error, AppflareMutationVariables<TArgs>, TContext> {
|
|
65
|
+
return useTanstackMutation<
|
|
66
|
+
TData,
|
|
67
|
+
Error,
|
|
68
|
+
AppflareMutationVariables<TArgs>,
|
|
69
|
+
TContext
|
|
70
|
+
>({
|
|
71
|
+
...(mutationOptions as Omit<
|
|
72
|
+
UseMutationOptions<
|
|
73
|
+
TData,
|
|
74
|
+
Error,
|
|
75
|
+
AppflareMutationVariables<TArgs>,
|
|
76
|
+
TContext
|
|
77
|
+
>,
|
|
78
|
+
"mutationFn"
|
|
79
|
+
>),
|
|
80
|
+
mutationFn: async (args: AppflareMutationVariables<TArgs>) => {
|
|
81
|
+
const response = await mutation.run((args ?? {}) as TArgs);
|
|
82
|
+
if (response.error) {
|
|
83
|
+
throw toError(response.error);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return response.data as TData;
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
}
|
package/react/use-query.ts
CHANGED
|
@@ -1,207 +1,207 @@
|
|
|
1
|
-
import {
|
|
2
|
-
hashKey,
|
|
3
|
-
type QueryKey,
|
|
4
|
-
type UseQueryOptions,
|
|
5
|
-
type UseQueryResult,
|
|
6
|
-
useQuery as useTanstackQuery,
|
|
7
|
-
useQueryClient,
|
|
8
|
-
} from "@tanstack/react-query";
|
|
9
|
-
import { useEffect, useMemo, useRef } from "react";
|
|
10
|
-
|
|
11
|
-
type AppflareRequestErrorLike = {
|
|
12
|
-
message: string;
|
|
13
|
-
status?: number;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
type AppflareRequestResultLike<TData> = {
|
|
17
|
-
data: TData | null;
|
|
18
|
-
error: AppflareRequestErrorLike | null;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
type AppflareRealtimeSubscriptionLike = {
|
|
22
|
-
remove: () => void;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
type AppflareRealtimeQueryUpdateLike<TData> = {
|
|
26
|
-
event: "query:update";
|
|
27
|
-
payload: {
|
|
28
|
-
queryName: string;
|
|
29
|
-
signature: string;
|
|
30
|
-
data: TData;
|
|
31
|
-
};
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
type AppflareRequiredInputKeys<TInput extends Record<string, unknown>> = {
|
|
35
|
-
[K in keyof TInput]-?: undefined extends TInput[K] ? never : K;
|
|
36
|
-
}[keyof TInput];
|
|
37
|
-
|
|
38
|
-
type AppflareHasRequiredInputKeys<TInput extends Record<string, unknown>> = [
|
|
39
|
-
AppflareRequiredInputKeys<TInput>,
|
|
40
|
-
] extends [never]
|
|
41
|
-
? false
|
|
42
|
-
: true;
|
|
43
|
-
|
|
44
|
-
type AppflareRouteRunArgs<TInput extends Record<string, unknown>> =
|
|
45
|
-
AppflareHasRequiredInputKeys<TInput> extends true
|
|
46
|
-
? [args: TInput, options?: any]
|
|
47
|
-
: [args?: TInput, options?: any];
|
|
48
|
-
|
|
49
|
-
type AppflareQueryLike<TArgs extends Record<string, unknown>, TData> = {
|
|
50
|
-
run: (
|
|
51
|
-
...params: AppflareRouteRunArgs<TArgs>
|
|
52
|
-
) => Promise<AppflareRequestResultLike<TData>>;
|
|
53
|
-
subscribe?: (options: {
|
|
54
|
-
args?: TArgs;
|
|
55
|
-
authToken?: string;
|
|
56
|
-
requestOptions?: any;
|
|
57
|
-
signal?: AbortSignal;
|
|
58
|
-
onChange: (
|
|
59
|
-
data: TData,
|
|
60
|
-
update: AppflareRealtimeQueryUpdateLike<TData>,
|
|
61
|
-
) => void;
|
|
62
|
-
onError?: (error: unknown) => void;
|
|
63
|
-
}) => AppflareRealtimeSubscriptionLike;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
export type UseAppflareQueryOptions<
|
|
67
|
-
TArgs extends Record<string, unknown>,
|
|
68
|
-
TData,
|
|
69
|
-
TSelected = TData,
|
|
70
|
-
TKey extends QueryKey = QueryKey,
|
|
71
|
-
> = {
|
|
72
|
-
realtime?: {
|
|
73
|
-
enabled?: boolean;
|
|
74
|
-
authToken?: string;
|
|
75
|
-
requestOptions?: any;
|
|
76
|
-
onChange?: (
|
|
77
|
-
data: TData,
|
|
78
|
-
update: AppflareRealtimeQueryUpdateLike<TData>,
|
|
79
|
-
) => void;
|
|
80
|
-
onError?: (error: unknown) => void;
|
|
81
|
-
};
|
|
82
|
-
requestOptions?: any;
|
|
83
|
-
queryOptions?: Omit<
|
|
84
|
-
UseQueryOptions<TData, Error, TSelected, TKey>,
|
|
85
|
-
"queryFn" | "queryKey"
|
|
86
|
-
> & {
|
|
87
|
-
queryKey?: TKey;
|
|
88
|
-
};
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
type UseQueryCallParams<
|
|
92
|
-
TArgs extends Record<string, unknown>,
|
|
93
|
-
TData,
|
|
94
|
-
TSelected,
|
|
95
|
-
TKey extends QueryKey,
|
|
96
|
-
> =
|
|
97
|
-
AppflareHasRequiredInputKeys<TArgs> extends true
|
|
98
|
-
? [
|
|
99
|
-
args: TArgs,
|
|
100
|
-
options?: UseAppflareQueryOptions<TArgs, TData, TSelected, TKey>,
|
|
101
|
-
]
|
|
102
|
-
: [
|
|
103
|
-
args?: TArgs,
|
|
104
|
-
options?: UseAppflareQueryOptions<TArgs, TData, TSelected, TKey>,
|
|
105
|
-
];
|
|
106
|
-
|
|
107
|
-
function toError(error: AppflareRequestErrorLike): Error {
|
|
108
|
-
const next = new Error(error.message);
|
|
109
|
-
if (error.status !== undefined) {
|
|
110
|
-
(next as Error & { status?: number }).status = error.status;
|
|
111
|
-
}
|
|
112
|
-
return next;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export function useQuery<
|
|
116
|
-
TArgs extends Record<string, unknown>,
|
|
117
|
-
TData,
|
|
118
|
-
TSelected = TData,
|
|
119
|
-
TKey extends QueryKey = QueryKey,
|
|
120
|
-
>(
|
|
121
|
-
query: AppflareQueryLike<TArgs, TData>,
|
|
122
|
-
...params: UseQueryCallParams<TArgs, TData, TSelected, TKey>
|
|
123
|
-
): UseQueryResult<TSelected, Error> {
|
|
124
|
-
const args = (params[0] ?? {}) as TArgs;
|
|
125
|
-
const options = params[1];
|
|
126
|
-
const queryClient = useQueryClient();
|
|
127
|
-
const realtimeOnChangeRef = useRef(options?.realtime?.onChange);
|
|
128
|
-
const realtimeOnErrorRef = useRef(options?.realtime?.onError);
|
|
129
|
-
|
|
130
|
-
useEffect(() => {
|
|
131
|
-
realtimeOnChangeRef.current = options?.realtime?.onChange;
|
|
132
|
-
realtimeOnErrorRef.current = options?.realtime?.onError;
|
|
133
|
-
}, [options?.realtime?.onChange, options?.realtime?.onError]);
|
|
134
|
-
|
|
135
|
-
const resolvedQueryKey = useMemo(() => {
|
|
136
|
-
return (
|
|
137
|
-
options?.queryOptions?.queryKey ??
|
|
138
|
-
(["appflare", "query", query, args] as unknown as TKey)
|
|
139
|
-
);
|
|
140
|
-
}, [args, options?.queryOptions?.queryKey, query]);
|
|
141
|
-
|
|
142
|
-
const resolvedQueryKeyHash = useMemo(
|
|
143
|
-
() => hashKey(resolvedQueryKey as QueryKey),
|
|
144
|
-
[resolvedQueryKey],
|
|
145
|
-
);
|
|
146
|
-
|
|
147
|
-
const realtimeArgsHash = useMemo(() => hashKey([args] as QueryKey), [args]);
|
|
148
|
-
|
|
149
|
-
const realtimeRequestOptionsHash = useMemo(
|
|
150
|
-
() => hashKey([options?.realtime?.requestOptions] as QueryKey),
|
|
151
|
-
[options?.realtime?.requestOptions],
|
|
152
|
-
);
|
|
153
|
-
|
|
154
|
-
const result = useTanstackQuery<TData, Error, TSelected, TKey>({
|
|
155
|
-
...(options?.queryOptions as Omit<
|
|
156
|
-
UseQueryOptions<TData, Error, TSelected, TKey>,
|
|
157
|
-
"queryFn" | "queryKey"
|
|
158
|
-
>),
|
|
159
|
-
queryKey: resolvedQueryKey,
|
|
160
|
-
queryFn: async () => {
|
|
161
|
-
const response = await query.run(args, options?.requestOptions);
|
|
162
|
-
if (response.error) {
|
|
163
|
-
throw toError(response.error);
|
|
164
|
-
}
|
|
165
|
-
return response.data as TData;
|
|
166
|
-
},
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
useEffect(() => {
|
|
170
|
-
if (options?.realtime?.enabled === false || !query.subscribe) {
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const controller = new AbortController();
|
|
175
|
-
const subscription = query.subscribe({
|
|
176
|
-
args,
|
|
177
|
-
authToken: options.realtime?.authToken,
|
|
178
|
-
requestOptions: options.realtime?.requestOptions,
|
|
179
|
-
signal: controller.signal,
|
|
180
|
-
onChange: (data, update) => {
|
|
181
|
-
queryClient.setQueryData<TData>(resolvedQueryKey, data as TData);
|
|
182
|
-
realtimeOnChangeRef.current?.(
|
|
183
|
-
data as TData,
|
|
184
|
-
update as AppflareRealtimeQueryUpdateLike<TData>,
|
|
185
|
-
);
|
|
186
|
-
},
|
|
187
|
-
onError: (error) => {
|
|
188
|
-
realtimeOnErrorRef.current?.(error);
|
|
189
|
-
},
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
return () => {
|
|
193
|
-
controller.abort();
|
|
194
|
-
subscription.remove();
|
|
195
|
-
};
|
|
196
|
-
}, [
|
|
197
|
-
realtimeArgsHash,
|
|
198
|
-
options?.realtime?.authToken,
|
|
199
|
-
options?.realtime?.enabled,
|
|
200
|
-
realtimeRequestOptionsHash,
|
|
201
|
-
query.subscribe,
|
|
202
|
-
queryClient,
|
|
203
|
-
resolvedQueryKeyHash,
|
|
204
|
-
]);
|
|
205
|
-
|
|
206
|
-
return result;
|
|
207
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
hashKey,
|
|
3
|
+
type QueryKey,
|
|
4
|
+
type UseQueryOptions,
|
|
5
|
+
type UseQueryResult,
|
|
6
|
+
useQuery as useTanstackQuery,
|
|
7
|
+
useQueryClient,
|
|
8
|
+
} from "@tanstack/react-query";
|
|
9
|
+
import { useEffect, useMemo, useRef } from "react";
|
|
10
|
+
|
|
11
|
+
type AppflareRequestErrorLike = {
|
|
12
|
+
message: string;
|
|
13
|
+
status?: number;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
type AppflareRequestResultLike<TData> = {
|
|
17
|
+
data: TData | null;
|
|
18
|
+
error: AppflareRequestErrorLike | null;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
type AppflareRealtimeSubscriptionLike = {
|
|
22
|
+
remove: () => void;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
type AppflareRealtimeQueryUpdateLike<TData> = {
|
|
26
|
+
event: "query:update";
|
|
27
|
+
payload: {
|
|
28
|
+
queryName: string;
|
|
29
|
+
signature: string;
|
|
30
|
+
data: TData;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
type AppflareRequiredInputKeys<TInput extends Record<string, unknown>> = {
|
|
35
|
+
[K in keyof TInput]-?: undefined extends TInput[K] ? never : K;
|
|
36
|
+
}[keyof TInput];
|
|
37
|
+
|
|
38
|
+
type AppflareHasRequiredInputKeys<TInput extends Record<string, unknown>> = [
|
|
39
|
+
AppflareRequiredInputKeys<TInput>,
|
|
40
|
+
] extends [never]
|
|
41
|
+
? false
|
|
42
|
+
: true;
|
|
43
|
+
|
|
44
|
+
type AppflareRouteRunArgs<TInput extends Record<string, unknown>> =
|
|
45
|
+
AppflareHasRequiredInputKeys<TInput> extends true
|
|
46
|
+
? [args: TInput, options?: any]
|
|
47
|
+
: [args?: TInput, options?: any];
|
|
48
|
+
|
|
49
|
+
type AppflareQueryLike<TArgs extends Record<string, unknown>, TData> = {
|
|
50
|
+
run: (
|
|
51
|
+
...params: AppflareRouteRunArgs<TArgs>
|
|
52
|
+
) => Promise<AppflareRequestResultLike<TData>>;
|
|
53
|
+
subscribe?: (options: {
|
|
54
|
+
args?: TArgs;
|
|
55
|
+
authToken?: string;
|
|
56
|
+
requestOptions?: any;
|
|
57
|
+
signal?: AbortSignal;
|
|
58
|
+
onChange: (
|
|
59
|
+
data: TData,
|
|
60
|
+
update: AppflareRealtimeQueryUpdateLike<TData>,
|
|
61
|
+
) => void;
|
|
62
|
+
onError?: (error: unknown) => void;
|
|
63
|
+
}) => AppflareRealtimeSubscriptionLike;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export type UseAppflareQueryOptions<
|
|
67
|
+
TArgs extends Record<string, unknown>,
|
|
68
|
+
TData,
|
|
69
|
+
TSelected = TData,
|
|
70
|
+
TKey extends QueryKey = QueryKey,
|
|
71
|
+
> = {
|
|
72
|
+
realtime?: {
|
|
73
|
+
enabled?: boolean;
|
|
74
|
+
authToken?: string;
|
|
75
|
+
requestOptions?: any;
|
|
76
|
+
onChange?: (
|
|
77
|
+
data: TData,
|
|
78
|
+
update: AppflareRealtimeQueryUpdateLike<TData>,
|
|
79
|
+
) => void;
|
|
80
|
+
onError?: (error: unknown) => void;
|
|
81
|
+
};
|
|
82
|
+
requestOptions?: any;
|
|
83
|
+
queryOptions?: Omit<
|
|
84
|
+
UseQueryOptions<TData, Error, TSelected, TKey>,
|
|
85
|
+
"queryFn" | "queryKey"
|
|
86
|
+
> & {
|
|
87
|
+
queryKey?: TKey;
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
type UseQueryCallParams<
|
|
92
|
+
TArgs extends Record<string, unknown>,
|
|
93
|
+
TData,
|
|
94
|
+
TSelected,
|
|
95
|
+
TKey extends QueryKey,
|
|
96
|
+
> =
|
|
97
|
+
AppflareHasRequiredInputKeys<TArgs> extends true
|
|
98
|
+
? [
|
|
99
|
+
args: TArgs,
|
|
100
|
+
options?: UseAppflareQueryOptions<TArgs, TData, TSelected, TKey>,
|
|
101
|
+
]
|
|
102
|
+
: [
|
|
103
|
+
args?: TArgs,
|
|
104
|
+
options?: UseAppflareQueryOptions<TArgs, TData, TSelected, TKey>,
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
function toError(error: AppflareRequestErrorLike): Error {
|
|
108
|
+
const next = new Error(error.message);
|
|
109
|
+
if (error.status !== undefined) {
|
|
110
|
+
(next as Error & { status?: number }).status = error.status;
|
|
111
|
+
}
|
|
112
|
+
return next;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function useQuery<
|
|
116
|
+
TArgs extends Record<string, unknown>,
|
|
117
|
+
TData,
|
|
118
|
+
TSelected = TData,
|
|
119
|
+
TKey extends QueryKey = QueryKey,
|
|
120
|
+
>(
|
|
121
|
+
query: AppflareQueryLike<TArgs, TData>,
|
|
122
|
+
...params: UseQueryCallParams<TArgs, TData, TSelected, TKey>
|
|
123
|
+
): UseQueryResult<TSelected, Error> {
|
|
124
|
+
const args = (params[0] ?? {}) as TArgs;
|
|
125
|
+
const options = params[1];
|
|
126
|
+
const queryClient = useQueryClient();
|
|
127
|
+
const realtimeOnChangeRef = useRef(options?.realtime?.onChange);
|
|
128
|
+
const realtimeOnErrorRef = useRef(options?.realtime?.onError);
|
|
129
|
+
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
realtimeOnChangeRef.current = options?.realtime?.onChange;
|
|
132
|
+
realtimeOnErrorRef.current = options?.realtime?.onError;
|
|
133
|
+
}, [options?.realtime?.onChange, options?.realtime?.onError]);
|
|
134
|
+
|
|
135
|
+
const resolvedQueryKey = useMemo(() => {
|
|
136
|
+
return (
|
|
137
|
+
options?.queryOptions?.queryKey ??
|
|
138
|
+
(["appflare", "query", query, args] as unknown as TKey)
|
|
139
|
+
);
|
|
140
|
+
}, [args, options?.queryOptions?.queryKey, query]);
|
|
141
|
+
|
|
142
|
+
const resolvedQueryKeyHash = useMemo(
|
|
143
|
+
() => hashKey(resolvedQueryKey as QueryKey),
|
|
144
|
+
[resolvedQueryKey],
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
const realtimeArgsHash = useMemo(() => hashKey([args] as QueryKey), [args]);
|
|
148
|
+
|
|
149
|
+
const realtimeRequestOptionsHash = useMemo(
|
|
150
|
+
() => hashKey([options?.realtime?.requestOptions] as QueryKey),
|
|
151
|
+
[options?.realtime?.requestOptions],
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
const result = useTanstackQuery<TData, Error, TSelected, TKey>({
|
|
155
|
+
...(options?.queryOptions as Omit<
|
|
156
|
+
UseQueryOptions<TData, Error, TSelected, TKey>,
|
|
157
|
+
"queryFn" | "queryKey"
|
|
158
|
+
>),
|
|
159
|
+
queryKey: resolvedQueryKey,
|
|
160
|
+
queryFn: async () => {
|
|
161
|
+
const response = await query.run(args, options?.requestOptions);
|
|
162
|
+
if (response.error) {
|
|
163
|
+
throw toError(response.error);
|
|
164
|
+
}
|
|
165
|
+
return response.data as TData;
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
useEffect(() => {
|
|
170
|
+
if (options?.realtime?.enabled === false || !query.subscribe) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const controller = new AbortController();
|
|
175
|
+
const subscription = query.subscribe({
|
|
176
|
+
args,
|
|
177
|
+
authToken: options.realtime?.authToken,
|
|
178
|
+
requestOptions: options.realtime?.requestOptions,
|
|
179
|
+
signal: controller.signal,
|
|
180
|
+
onChange: (data, update) => {
|
|
181
|
+
queryClient.setQueryData<TData>(resolvedQueryKey, data as TData);
|
|
182
|
+
realtimeOnChangeRef.current?.(
|
|
183
|
+
data as TData,
|
|
184
|
+
update as AppflareRealtimeQueryUpdateLike<TData>,
|
|
185
|
+
);
|
|
186
|
+
},
|
|
187
|
+
onError: (error) => {
|
|
188
|
+
realtimeOnErrorRef.current?.(error);
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
return () => {
|
|
193
|
+
controller.abort();
|
|
194
|
+
subscription.remove();
|
|
195
|
+
};
|
|
196
|
+
}, [
|
|
197
|
+
realtimeArgsHash,
|
|
198
|
+
options?.realtime?.authToken,
|
|
199
|
+
options?.realtime?.enabled,
|
|
200
|
+
realtimeRequestOptionsHash,
|
|
201
|
+
query.subscribe,
|
|
202
|
+
queryClient,
|
|
203
|
+
resolvedQueryKeyHash,
|
|
204
|
+
]);
|
|
205
|
+
|
|
206
|
+
return result;
|
|
207
|
+
}
|