@questpie/admin 0.0.1 → 1.0.1
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 +439 -424
- package/dist/auth-layout-M8K8_q5R.mjs +181 -0
- package/dist/auth-layout-M8K8_q5R.mjs.map +1 -0
- package/dist/bulk-upload-dialog-D7w7W1Hl.mjs +273 -0
- package/dist/bulk-upload-dialog-D7w7W1Hl.mjs.map +1 -0
- package/dist/{components/ui/card.mjs → card-BKHjBQfw.mjs} +8 -8
- package/dist/card-BKHjBQfw.mjs.map +1 -0
- package/dist/client/styles/index.css +434 -0
- package/dist/client-DbpZKSgH.d.mts +13585 -0
- package/dist/client-DbpZKSgH.d.mts.map +1 -0
- package/dist/client-njX1rZmi.mjs +22612 -0
- package/dist/client-njX1rZmi.mjs.map +1 -0
- package/dist/client.d.mts +3 -0
- package/dist/client.mjs +13 -0
- package/dist/content-locales-provider-BXvuIgfg.mjs +1650 -0
- package/dist/content-locales-provider-BXvuIgfg.mjs.map +1 -0
- package/dist/dashboard-page-B4PGEdc2.mjs +2500 -0
- package/dist/dashboard-page-B4PGEdc2.mjs.map +1 -0
- package/dist/dashboard-page-mCY0pgZv.mjs +3 -0
- package/dist/dropzone-Do3awXKd.mjs +634 -0
- package/dist/dropzone-Do3awXKd.mjs.map +1 -0
- package/dist/{views/auth/forgot-password-form.mjs → forgot-password-page-Bcp-An4Y.mjs} +87 -14
- package/dist/forgot-password-page-Bcp-An4Y.mjs.map +1 -0
- package/dist/forgot-password-page-CEwsdLwn.mjs +3 -0
- package/dist/index-B9Xwk4hi.d.mts +2753 -0
- package/dist/index-B9Xwk4hi.d.mts.map +1 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +13 -0
- package/dist/login-page-BUnpCbCa.mjs +3 -0
- package/dist/login-page-CP4gA-dl.mjs +298 -0
- package/dist/login-page-CP4gA-dl.mjs.map +1 -0
- package/dist/preview-utils-BKQ9-TMa.mjs +65 -0
- package/dist/preview-utils-BKQ9-TMa.mjs.map +1 -0
- package/dist/{views/auth/reset-password-form.mjs → reset-password-page-BqfDmLxA.mjs} +111 -14
- package/dist/reset-password-page-BqfDmLxA.mjs.map +1 -0
- package/dist/reset-password-page-CufHz3h3.mjs +3 -0
- package/dist/runtime-6VZM878K.mjs +69 -0
- package/dist/runtime-6VZM878K.mjs.map +1 -0
- package/dist/saved-views.types-BMsz5mCy.d.mts +42 -0
- package/dist/saved-views.types-BMsz5mCy.d.mts.map +1 -0
- package/dist/server.d.mts +250 -0
- package/dist/server.d.mts.map +1 -0
- package/dist/server.mjs +832 -0
- package/dist/server.mjs.map +1 -0
- package/dist/setup-page-BNNzt_Z6.mjs +3 -0
- package/dist/setup-page-YAP_fzqh.mjs +264 -0
- package/dist/setup-page-YAP_fzqh.mjs.map +1 -0
- package/dist/shared.d.mts +57 -0
- package/dist/shared.d.mts.map +1 -0
- package/dist/shared.mjs +3 -0
- package/dist/{hooks/use-auth.mjs → use-auth-BoLmWtmU.mjs} +42 -30
- package/dist/use-auth-BoLmWtmU.mjs.map +1 -0
- package/package.json +48 -198
- package/.turbo/turbo-build.log +0 -108
- package/CHANGELOG.md +0 -10
- package/STATUS.md +0 -917
- package/VALIDATION.md +0 -602
- package/components.json +0 -24
- package/dist/__tests__/setup.mjs +0 -38
- package/dist/__tests__/test-utils.mjs +0 -45
- package/dist/__tests__/vitest.d.mjs +0 -3
- package/dist/components/admin-app.mjs +0 -69
- package/dist/components/fields/array-field.mjs +0 -190
- package/dist/components/fields/checkbox-field.mjs +0 -34
- package/dist/components/fields/custom-field.mjs +0 -32
- package/dist/components/fields/date-field.mjs +0 -41
- package/dist/components/fields/datetime-field.mjs +0 -42
- package/dist/components/fields/email-field.mjs +0 -37
- package/dist/components/fields/embedded-collection.mjs +0 -253
- package/dist/components/fields/field-types.mjs +0 -1
- package/dist/components/fields/field-utils.mjs +0 -10
- package/dist/components/fields/field-wrapper.mjs +0 -34
- package/dist/components/fields/index.mjs +0 -23
- package/dist/components/fields/json-field.mjs +0 -243
- package/dist/components/fields/locale-badge.mjs +0 -16
- package/dist/components/fields/number-field.mjs +0 -39
- package/dist/components/fields/password-field.mjs +0 -37
- package/dist/components/fields/relation-field.mjs +0 -104
- package/dist/components/fields/relation-picker.mjs +0 -229
- package/dist/components/fields/relation-select.mjs +0 -188
- package/dist/components/fields/rich-text-editor/index.mjs +0 -897
- package/dist/components/fields/select-field.mjs +0 -41
- package/dist/components/fields/switch-field.mjs +0 -34
- package/dist/components/fields/text-field.mjs +0 -38
- package/dist/components/fields/textarea-field.mjs +0 -38
- package/dist/components/index.mjs +0 -59
- package/dist/components/primitives/checkbox-input.mjs +0 -127
- package/dist/components/primitives/date-input.mjs +0 -303
- package/dist/components/primitives/index.mjs +0 -12
- package/dist/components/primitives/number-input.mjs +0 -104
- package/dist/components/primitives/select-input.mjs +0 -177
- package/dist/components/primitives/tag-input.mjs +0 -135
- package/dist/components/primitives/text-input.mjs +0 -39
- package/dist/components/primitives/textarea-input.mjs +0 -37
- package/dist/components/primitives/toggle-input.mjs +0 -31
- package/dist/components/primitives/types.mjs +0 -12
- package/dist/components/ui/accordion.mjs +0 -55
- package/dist/components/ui/avatar.mjs +0 -54
- package/dist/components/ui/badge.mjs +0 -34
- package/dist/components/ui/button.mjs +0 -48
- package/dist/components/ui/checkbox.mjs +0 -21
- package/dist/components/ui/combobox.mjs +0 -163
- package/dist/components/ui/dialog.mjs +0 -95
- package/dist/components/ui/dropdown-menu.mjs +0 -138
- package/dist/components/ui/field.mjs +0 -113
- package/dist/components/ui/input-group.mjs +0 -82
- package/dist/components/ui/input.mjs +0 -17
- package/dist/components/ui/label.mjs +0 -15
- package/dist/components/ui/popover.mjs +0 -56
- package/dist/components/ui/scroll-area.mjs +0 -38
- package/dist/components/ui/select.mjs +0 -100
- package/dist/components/ui/separator.mjs +0 -16
- package/dist/components/ui/sheet.mjs +0 -90
- package/dist/components/ui/sidebar.mjs +0 -387
- package/dist/components/ui/skeleton.mjs +0 -14
- package/dist/components/ui/spinner.mjs +0 -16
- package/dist/components/ui/switch.mjs +0 -22
- package/dist/components/ui/table.mjs +0 -68
- package/dist/components/ui/tabs.mjs +0 -48
- package/dist/components/ui/textarea.mjs +0 -15
- package/dist/components/ui/tooltip.mjs +0 -44
- package/dist/config/component-registry.mjs +0 -38
- package/dist/config/index.mjs +0 -129
- package/dist/hooks/admin-provider.mjs +0 -70
- package/dist/hooks/index.mjs +0 -7
- package/dist/hooks/store.mjs +0 -178
- package/dist/hooks/use-collection-db.mjs +0 -146
- package/dist/hooks/use-collection.mjs +0 -112
- package/dist/hooks/use-global.mjs +0 -46
- package/dist/hooks/use-mobile.mjs +0 -20
- package/dist/lib/utils.mjs +0 -10
- package/dist/styles/index.css +0 -336
- package/dist/styles/index.mjs +0 -1
- package/dist/utils/index.mjs +0 -9
- package/dist/views/auth/auth-layout.mjs +0 -52
- package/dist/views/auth/index.mjs +0 -6
- package/dist/views/auth/login-form.mjs +0 -156
- package/dist/views/collection/auto-form-fields.mjs +0 -525
- package/dist/views/collection/collection-form.mjs +0 -91
- package/dist/views/collection/collection-list.mjs +0 -76
- package/dist/views/collection/form-field.mjs +0 -42
- package/dist/views/collection/index.mjs +0 -6
- package/dist/views/common/index.mjs +0 -4
- package/dist/views/common/locale-switcher.mjs +0 -39
- package/dist/views/common/version-history.mjs +0 -272
- package/dist/views/index.mjs +0 -9
- package/dist/views/layout/admin-layout.mjs +0 -40
- package/dist/views/layout/admin-router.mjs +0 -95
- package/dist/views/layout/admin-sidebar.mjs +0 -63
- package/dist/views/layout/index.mjs +0 -5
- package/src/__tests__/setup.ts +0 -44
- package/src/__tests__/test-utils.tsx +0 -49
- package/src/__tests__/vitest.d.ts +0 -9
- package/src/components/admin-app.tsx +0 -221
- package/src/components/fields/array-field.tsx +0 -237
- package/src/components/fields/checkbox-field.tsx +0 -47
- package/src/components/fields/custom-field.tsx +0 -50
- package/src/components/fields/date-field.tsx +0 -65
- package/src/components/fields/datetime-field.tsx +0 -67
- package/src/components/fields/email-field.tsx +0 -51
- package/src/components/fields/embedded-collection.tsx +0 -315
- package/src/components/fields/field-types.ts +0 -162
- package/src/components/fields/field-utils.ts +0 -6
- package/src/components/fields/field-wrapper.tsx +0 -52
- package/src/components/fields/index.ts +0 -66
- package/src/components/fields/json-field.tsx +0 -440
- package/src/components/fields/locale-badge.tsx +0 -15
- package/src/components/fields/number-field.tsx +0 -57
- package/src/components/fields/password-field.tsx +0 -51
- package/src/components/fields/relation-field.tsx +0 -243
- package/src/components/fields/relation-picker.tsx +0 -402
- package/src/components/fields/relation-select.tsx +0 -327
- package/src/components/fields/rich-text-editor/index.tsx +0 -1337
- package/src/components/fields/select-field.tsx +0 -61
- package/src/components/fields/switch-field.tsx +0 -47
- package/src/components/fields/text-field.tsx +0 -55
- package/src/components/fields/textarea-field.tsx +0 -55
- package/src/components/index.ts +0 -40
- package/src/components/primitives/checkbox-input.tsx +0 -193
- package/src/components/primitives/date-input.tsx +0 -401
- package/src/components/primitives/index.ts +0 -24
- package/src/components/primitives/number-input.tsx +0 -132
- package/src/components/primitives/select-input.tsx +0 -296
- package/src/components/primitives/tag-input.tsx +0 -200
- package/src/components/primitives/text-input.tsx +0 -49
- package/src/components/primitives/textarea-input.tsx +0 -46
- package/src/components/primitives/toggle-input.tsx +0 -36
- package/src/components/primitives/types.ts +0 -235
- package/src/components/ui/accordion.tsx +0 -72
- package/src/components/ui/avatar.tsx +0 -106
- package/src/components/ui/badge.tsx +0 -48
- package/src/components/ui/button.tsx +0 -53
- package/src/components/ui/card.tsx +0 -94
- package/src/components/ui/checkbox.tsx +0 -27
- package/src/components/ui/combobox.tsx +0 -290
- package/src/components/ui/dialog.tsx +0 -151
- package/src/components/ui/dropdown-menu.tsx +0 -254
- package/src/components/ui/field.tsx +0 -227
- package/src/components/ui/input-group.tsx +0 -149
- package/src/components/ui/input.tsx +0 -20
- package/src/components/ui/label.tsx +0 -18
- package/src/components/ui/popover.tsx +0 -88
- package/src/components/ui/scroll-area.tsx +0 -53
- package/src/components/ui/select.tsx +0 -192
- package/src/components/ui/separator.tsx +0 -23
- package/src/components/ui/sheet.tsx +0 -127
- package/src/components/ui/sidebar.tsx +0 -723
- package/src/components/ui/skeleton.tsx +0 -13
- package/src/components/ui/spinner.tsx +0 -10
- package/src/components/ui/switch.tsx +0 -32
- package/src/components/ui/table.tsx +0 -99
- package/src/components/ui/tabs.tsx +0 -82
- package/src/components/ui/textarea.tsx +0 -18
- package/src/components/ui/tooltip.tsx +0 -70
- package/src/config/component-registry.ts +0 -190
- package/src/config/index.ts +0 -1099
- package/src/hooks/README.md +0 -269
- package/src/hooks/admin-provider.tsx +0 -110
- package/src/hooks/index.ts +0 -41
- package/src/hooks/store.ts +0 -248
- package/src/hooks/use-auth.ts +0 -168
- package/src/hooks/use-collection-db.ts +0 -209
- package/src/hooks/use-collection.ts +0 -156
- package/src/hooks/use-global.ts +0 -69
- package/src/hooks/use-mobile.ts +0 -21
- package/src/lib/utils.ts +0 -6
- package/src/styles/index.css +0 -340
- package/src/utils/index.ts +0 -6
- package/src/views/auth/auth-layout.tsx +0 -77
- package/src/views/auth/forgot-password-form.tsx +0 -192
- package/src/views/auth/index.ts +0 -21
- package/src/views/auth/login-form.tsx +0 -229
- package/src/views/auth/reset-password-form.tsx +0 -232
- package/src/views/collection/auto-form-fields.tsx +0 -982
- package/src/views/collection/collection-form.tsx +0 -186
- package/src/views/collection/collection-list.tsx +0 -223
- package/src/views/collection/form-field.tsx +0 -52
- package/src/views/collection/index.ts +0 -15
- package/src/views/common/index.ts +0 -8
- package/src/views/common/locale-switcher.tsx +0 -45
- package/src/views/common/version-history.tsx +0 -406
- package/src/views/index.ts +0 -25
- package/src/views/layout/admin-layout.tsx +0 -117
- package/src/views/layout/admin-router.tsx +0 -206
- package/src/views/layout/admin-sidebar.tsx +0 -185
- package/src/views/layout/index.ts +0 -12
- package/tsconfig.json +0 -13
- package/tsconfig.tsbuildinfo +0 -1
- package/tsdown.config.ts +0 -13
- package/vitest.config.ts +0 -29
package/src/hooks/use-auth.ts
DELETED
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Auth client utilities for admin package
|
|
3
|
-
*
|
|
4
|
-
* Better Auth handles all auth state management internally.
|
|
5
|
-
* This module provides type-safe client creation helpers with
|
|
6
|
-
* full type inference from your CMS auth configuration.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```tsx
|
|
10
|
-
* // In your app, create the auth client once:
|
|
11
|
-
* import { createAdminAuthClient } from '@questpie/admin/hooks'
|
|
12
|
-
* import type { cms } from './server/cms'
|
|
13
|
-
*
|
|
14
|
-
* export const authClient = createAdminAuthClient<typeof cms>({
|
|
15
|
-
* baseURL: 'http://localhost:3000'
|
|
16
|
-
* })
|
|
17
|
-
*
|
|
18
|
-
* // Then use the built-in hooks:
|
|
19
|
-
* function MyComponent() {
|
|
20
|
-
* const { data: session, isPending, error } = authClient.useSession()
|
|
21
|
-
*
|
|
22
|
-
* if (isPending) return <div>Loading...</div>
|
|
23
|
-
* if (!session) return <LoginForm />
|
|
24
|
-
*
|
|
25
|
-
* return <div>Welcome {session.user.name}</div>
|
|
26
|
-
* }
|
|
27
|
-
* ```
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
import { createAuthClient } from "better-auth/react";
|
|
31
|
-
import type { Questpie } from "questpie";
|
|
32
|
-
import type { BetterAuthOptions } from "better-auth";
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Extract auth options type from Questpie instance
|
|
36
|
-
*/
|
|
37
|
-
type ExtractAuthOptions<T extends Questpie<any>> =
|
|
38
|
-
T extends Questpie<infer TConfig>
|
|
39
|
-
? TConfig["auth"] extends BetterAuthOptions
|
|
40
|
-
? TConfig["auth"]
|
|
41
|
-
: BetterAuthOptions
|
|
42
|
-
: BetterAuthOptions;
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Options for creating admin auth client
|
|
46
|
-
*/
|
|
47
|
-
export type AdminAuthClientOptions = {
|
|
48
|
-
/**
|
|
49
|
-
* Base URL of the CMS API
|
|
50
|
-
* @example 'http://localhost:3000'
|
|
51
|
-
*/
|
|
52
|
-
baseURL: string;
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Base path for auth routes
|
|
56
|
-
* @default '/cms/auth'
|
|
57
|
-
*/
|
|
58
|
-
basePath?: string;
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Custom fetch implementation
|
|
62
|
-
*/
|
|
63
|
-
fetchOptions?: {
|
|
64
|
-
credentials?: RequestCredentials;
|
|
65
|
-
headers?: Record<string, string>;
|
|
66
|
-
};
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Internal client options type that includes $InferAuth
|
|
71
|
-
*/
|
|
72
|
-
type InternalClientOptions<T extends Questpie<any>> = {
|
|
73
|
-
baseURL: string;
|
|
74
|
-
fetchOptions?: {
|
|
75
|
-
credentials?: RequestCredentials;
|
|
76
|
-
headers?: Record<string, string>;
|
|
77
|
-
};
|
|
78
|
-
$InferAuth: ExtractAuthOptions<T>;
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Create a type-safe Better Auth client for the admin UI
|
|
83
|
-
*
|
|
84
|
-
* The returned client includes full type inference from your CMS auth configuration:
|
|
85
|
-
* - `useSession()` - React hook for session state (typed based on your user/session schema)
|
|
86
|
-
* - `signIn` methods (email, social providers configured in CMS)
|
|
87
|
-
* - `signOut` - Sign out the current user
|
|
88
|
-
* - `signUp` - Register new users
|
|
89
|
-
* - Plugin-specific hooks (e.g., `useListAccounts` for admin plugin)
|
|
90
|
-
*
|
|
91
|
-
* @example
|
|
92
|
-
* ```tsx
|
|
93
|
-
* import { createAdminAuthClient } from '@questpie/admin/hooks'
|
|
94
|
-
* import type { cms } from './server/cms'
|
|
95
|
-
*
|
|
96
|
-
* // Create client with type inference from your CMS
|
|
97
|
-
* export const authClient = createAdminAuthClient<typeof cms>({
|
|
98
|
-
* baseURL: 'http://localhost:3000'
|
|
99
|
-
* })
|
|
100
|
-
*
|
|
101
|
-
* // Session data is fully typed based on your CMS auth config
|
|
102
|
-
* function App() {
|
|
103
|
-
* const { data: session, isPending } = authClient.useSession()
|
|
104
|
-
*
|
|
105
|
-
* if (isPending) return <Loading />
|
|
106
|
-
* if (!session) return <LoginPage authClient={authClient} />
|
|
107
|
-
*
|
|
108
|
-
* // session.user has all fields from your user schema
|
|
109
|
-
* return <AdminDashboard user={session.user} />
|
|
110
|
-
* }
|
|
111
|
-
* ```
|
|
112
|
-
*/
|
|
113
|
-
export function createAdminAuthClient<T extends Questpie<any>>(
|
|
114
|
-
options: AdminAuthClientOptions,
|
|
115
|
-
): ReturnType<typeof createAuthClient<InternalClientOptions<T>>> {
|
|
116
|
-
const basePath = options.basePath ?? "/cms/auth";
|
|
117
|
-
|
|
118
|
-
return createAuthClient<InternalClientOptions<T>>({
|
|
119
|
-
baseURL: `${options.baseURL}${basePath}`,
|
|
120
|
-
fetchOptions: {
|
|
121
|
-
credentials: options.fetchOptions?.credentials ?? "include",
|
|
122
|
-
headers: options.fetchOptions?.headers,
|
|
123
|
-
},
|
|
124
|
-
} as InternalClientOptions<T>);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Type helper to extract auth client type from CMS instance
|
|
129
|
-
*
|
|
130
|
-
* @example
|
|
131
|
-
* ```tsx
|
|
132
|
-
* import type { AdminAuthClient } from '@questpie/admin/hooks'
|
|
133
|
-
* import type { cms } from './server/cms'
|
|
134
|
-
*
|
|
135
|
-
* type MyAuthClient = AdminAuthClient<typeof cms>
|
|
136
|
-
* ```
|
|
137
|
-
*/
|
|
138
|
-
export type AdminAuthClient<T extends Questpie<any>> = ReturnType<
|
|
139
|
-
typeof createAdminAuthClient<T>
|
|
140
|
-
>;
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Type helper to extract session type from auth client
|
|
144
|
-
*
|
|
145
|
-
* @example
|
|
146
|
-
* ```tsx
|
|
147
|
-
* import type { AdminSession } from '@questpie/admin/hooks'
|
|
148
|
-
* import type { cms } from './server/cms'
|
|
149
|
-
*
|
|
150
|
-
* type MySession = AdminSession<typeof cms>
|
|
151
|
-
* // Includes: { user: { id, email, name, role, ... }, session: { ... } }
|
|
152
|
-
* ```
|
|
153
|
-
*/
|
|
154
|
-
export type AdminSession<T extends Questpie<any>> =
|
|
155
|
-
AdminAuthClient<T>["$Infer"]["Session"];
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Type helper to extract user type from CMS auth configuration
|
|
159
|
-
*
|
|
160
|
-
* @example
|
|
161
|
-
* ```tsx
|
|
162
|
-
* import type { AdminUser } from '@questpie/admin/hooks'
|
|
163
|
-
* import type { cms } from './server/cms'
|
|
164
|
-
*
|
|
165
|
-
* type MyUser = AdminUser<typeof cms>
|
|
166
|
-
* ```
|
|
167
|
-
*/
|
|
168
|
-
export type AdminUser<T extends Questpie<any>> = AdminSession<T>["user"];
|
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
import { useMemo } from "react";
|
|
2
|
-
import type { Collection } from "@tanstack/db";
|
|
3
|
-
import type { QuestpieClient } from "questpie/client";
|
|
4
|
-
import type { Questpie } from "questpie";
|
|
5
|
-
import { createQuestpieDBHelpers } from "@questpie/tanstack-query/db";
|
|
6
|
-
import { useAdminContext } from "./admin-provider";
|
|
7
|
-
import { useQueryClient } from "@tanstack/react-query";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Collection item type helper
|
|
11
|
-
* Extracts the item type from a collection's find method return type
|
|
12
|
-
*/
|
|
13
|
-
type CollectionItem<
|
|
14
|
-
T extends Questpie<any>,
|
|
15
|
-
K extends keyof QuestpieClient<T>["collections"],
|
|
16
|
-
> = Awaited<ReturnType<QuestpieClient<T>["collections"][K]["find"]>> extends {
|
|
17
|
-
docs: Array<infer TItem extends object>;
|
|
18
|
-
}
|
|
19
|
-
? TItem
|
|
20
|
-
: Record<string, unknown>;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Hook to get TanStack DB Collection for a CMS collection
|
|
24
|
-
* Provides offline-first, realtime-synced collection with optimistic updates
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* ```tsx
|
|
28
|
-
* function PostsList() {
|
|
29
|
-
* const posts = useCollection('posts', {
|
|
30
|
-
* baseFindOptions: { where: { published: { eq: true } } },
|
|
31
|
-
* realtime: true, // Enable realtime sync
|
|
32
|
-
* })
|
|
33
|
-
*
|
|
34
|
-
* return (
|
|
35
|
-
* <div>
|
|
36
|
-
* {posts.items.map(post => (
|
|
37
|
-
* <div key={post.id}>{post.title}</div>
|
|
38
|
-
* ))}
|
|
39
|
-
* </div>
|
|
40
|
-
* )
|
|
41
|
-
* }
|
|
42
|
-
* ```
|
|
43
|
-
*/
|
|
44
|
-
export function useCollection<
|
|
45
|
-
T extends Questpie<any>,
|
|
46
|
-
K extends keyof QuestpieClient<T>["collections"],
|
|
47
|
-
>(
|
|
48
|
-
collectionName: K,
|
|
49
|
-
options?: {
|
|
50
|
-
/**
|
|
51
|
-
* Base query options (filters, sorting, relations)
|
|
52
|
-
*/
|
|
53
|
-
baseFindOptions?: Parameters<QuestpieClient<T>["collections"][K]["find"]>[0];
|
|
54
|
-
/**
|
|
55
|
-
* Enable realtime sync via SSE
|
|
56
|
-
*/
|
|
57
|
-
realtime?:
|
|
58
|
-
| boolean
|
|
59
|
-
| {
|
|
60
|
-
enabled?: boolean;
|
|
61
|
-
baseURL?: string;
|
|
62
|
-
basePath?: string;
|
|
63
|
-
};
|
|
64
|
-
/**
|
|
65
|
-
* Custom key extractor (defaults to 'id')
|
|
66
|
-
*/
|
|
67
|
-
getKey?: (item: CollectionItem<T, K>) => string | number;
|
|
68
|
-
},
|
|
69
|
-
): Collection<CollectionItem<T, K>, string | number> {
|
|
70
|
-
const { client, locale } = useAdminContext<T>();
|
|
71
|
-
const queryClient = useQueryClient();
|
|
72
|
-
const localeKey = locale ?? "default";
|
|
73
|
-
|
|
74
|
-
const collection = useMemo(() => {
|
|
75
|
-
const dbHelpers = createQuestpieDBHelpers(client, {
|
|
76
|
-
keyPrefix: ["qcms", "locale", localeKey],
|
|
77
|
-
});
|
|
78
|
-
const collectionHelper = dbHelpers.collections[collectionName as string];
|
|
79
|
-
|
|
80
|
-
if (!collectionHelper) {
|
|
81
|
-
throw new Error(
|
|
82
|
-
`Collection "${String(collectionName)}" not found in CMS`,
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return collectionHelper.createCollection({
|
|
87
|
-
queryClient,
|
|
88
|
-
getKey: options?.getKey ?? ((item: any) => item.id),
|
|
89
|
-
baseFindOptions: options?.baseFindOptions,
|
|
90
|
-
realtime: options?.realtime ?? false,
|
|
91
|
-
} as any);
|
|
92
|
-
}, [
|
|
93
|
-
client,
|
|
94
|
-
queryClient,
|
|
95
|
-
collectionName,
|
|
96
|
-
localeKey,
|
|
97
|
-
options?.baseFindOptions,
|
|
98
|
-
options?.realtime,
|
|
99
|
-
options?.getKey,
|
|
100
|
-
]);
|
|
101
|
-
|
|
102
|
-
return collection as Collection<CollectionItem<T, K>, string | number>;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Hook to get a single item from collection by ID
|
|
107
|
-
* Uses TanStack DB Collection for offline-first access
|
|
108
|
-
*
|
|
109
|
-
* @example
|
|
110
|
-
* ```tsx
|
|
111
|
-
* function PostDetail({ id }: { id: string }) {
|
|
112
|
-
* const posts = useCollection('posts')
|
|
113
|
-
* const post = useCollectionItemById(posts, id)
|
|
114
|
-
*
|
|
115
|
-
* if (!post) return <div>Loading...</div>
|
|
116
|
-
*
|
|
117
|
-
* return <div>{post.title}</div>
|
|
118
|
-
* }
|
|
119
|
-
* ```
|
|
120
|
-
*/
|
|
121
|
-
export function useCollectionItemById<TItem extends object>(
|
|
122
|
-
collection: Collection<TItem, string | number>,
|
|
123
|
-
id: string | number,
|
|
124
|
-
): TItem | undefined {
|
|
125
|
-
return collection.toArray.find(
|
|
126
|
-
(item) => collection.config.getKey(item) === id,
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Hook to create item in collection
|
|
132
|
-
* Uses TanStack DB Collection with optimistic updates
|
|
133
|
-
*
|
|
134
|
-
* @example
|
|
135
|
-
* ```tsx
|
|
136
|
-
* function CreatePost() {
|
|
137
|
-
* const posts = useCollection('posts')
|
|
138
|
-
*
|
|
139
|
-
* const handleCreate = async () => {
|
|
140
|
-
* await posts.insert({
|
|
141
|
-
* title: 'New Post',
|
|
142
|
-
* content: 'Hello World'
|
|
143
|
-
* })
|
|
144
|
-
* }
|
|
145
|
-
*
|
|
146
|
-
* return <button onClick={handleCreate}>Create Post</button>
|
|
147
|
-
* }
|
|
148
|
-
* ```
|
|
149
|
-
*/
|
|
150
|
-
export function useCollectionInsert<
|
|
151
|
-
T extends Questpie<any>,
|
|
152
|
-
K extends keyof QuestpieClient<T>["collections"],
|
|
153
|
-
>(collectionName: K): any {
|
|
154
|
-
const collection = useCollection<T, K>(collectionName);
|
|
155
|
-
return collection.insert.bind(collection);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Hook to update item in collection
|
|
160
|
-
* Uses TanStack DB Collection with optimistic updates
|
|
161
|
-
*
|
|
162
|
-
* @example
|
|
163
|
-
* ```tsx
|
|
164
|
-
* function EditPost({ id }: { id: string }) {
|
|
165
|
-
* const posts = useCollection('posts')
|
|
166
|
-
* const post = useCollectionItemById(posts, id)
|
|
167
|
-
*
|
|
168
|
-
* const handleUpdate = async () => {
|
|
169
|
-
* await posts.update(id, {
|
|
170
|
-
* title: 'Updated Title'
|
|
171
|
-
* })
|
|
172
|
-
* }
|
|
173
|
-
*
|
|
174
|
-
* return <button onClick={handleUpdate}>Update</button>
|
|
175
|
-
* }
|
|
176
|
-
* ```
|
|
177
|
-
*/
|
|
178
|
-
export function useCollectionUpdate<
|
|
179
|
-
T extends Questpie<any>,
|
|
180
|
-
K extends keyof QuestpieClient<T>["collections"],
|
|
181
|
-
>(collectionName: K): any {
|
|
182
|
-
const collection = useCollection<T, K>(collectionName);
|
|
183
|
-
return collection.update.bind(collection);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Hook to delete item from collection
|
|
188
|
-
* Uses TanStack DB Collection with optimistic updates
|
|
189
|
-
*
|
|
190
|
-
* @example
|
|
191
|
-
* ```tsx
|
|
192
|
-
* function DeletePost({ id }: { id: string }) {
|
|
193
|
-
* const posts = useCollection('posts')
|
|
194
|
-
*
|
|
195
|
-
* const handleDelete = async () => {
|
|
196
|
-
* await posts.delete(id)
|
|
197
|
-
* }
|
|
198
|
-
*
|
|
199
|
-
* return <button onClick={handleDelete}>Delete</button>
|
|
200
|
-
* }
|
|
201
|
-
* ```
|
|
202
|
-
*/
|
|
203
|
-
export function useCollectionDelete<
|
|
204
|
-
T extends Questpie<any>,
|
|
205
|
-
K extends keyof QuestpieClient<T>["collections"],
|
|
206
|
-
>(collectionName: K): any {
|
|
207
|
-
const collection = useCollection<T, K>(collectionName);
|
|
208
|
-
return collection.delete.bind(collection);
|
|
209
|
-
}
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useQuery,
|
|
3
|
-
useMutation,
|
|
4
|
-
useQueryClient,
|
|
5
|
-
type UseQueryOptions,
|
|
6
|
-
type UseMutationOptions,
|
|
7
|
-
} from "@tanstack/react-query";
|
|
8
|
-
import type { QuestpieClient } from "questpie/client";
|
|
9
|
-
import type { Questpie } from "questpie";
|
|
10
|
-
import { createQuestpieQueryOptions } from "@questpie/tanstack-query";
|
|
11
|
-
|
|
12
|
-
import { useAdminContext } from "./admin-provider";
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Hook to fetch collection list with filters, sorting, pagination
|
|
16
|
-
*/
|
|
17
|
-
export function useCollectionList<
|
|
18
|
-
T extends Questpie<any>,
|
|
19
|
-
K extends keyof QuestpieClient<T>["collections"],
|
|
20
|
-
>(
|
|
21
|
-
collection: K,
|
|
22
|
-
options?: Parameters<QuestpieClient<T>["collections"][K]["find"]>[0],
|
|
23
|
-
queryOptions?: Omit<UseQueryOptions, "queryKey" | "queryFn">,
|
|
24
|
-
): any {
|
|
25
|
-
const { client, locale } = useAdminContext<T>();
|
|
26
|
-
const localeKey = locale ?? "default";
|
|
27
|
-
const keyPrefix = ["qcms", "locale", localeKey] as const;
|
|
28
|
-
const queryOpts = createQuestpieQueryOptions(client, { keyPrefix });
|
|
29
|
-
|
|
30
|
-
return useQuery({
|
|
31
|
-
...queryOpts.collections[collection as string].find(options as any),
|
|
32
|
-
...queryOptions,
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Hook to fetch single collection item
|
|
38
|
-
*/
|
|
39
|
-
export function useCollectionItem<
|
|
40
|
-
T extends Questpie<any>,
|
|
41
|
-
K extends keyof QuestpieClient<T>["collections"],
|
|
42
|
-
>(
|
|
43
|
-
collection: K,
|
|
44
|
-
id: string,
|
|
45
|
-
options?: Omit<
|
|
46
|
-
Parameters<QuestpieClient<T>["collections"][K]["findOne"]>[0],
|
|
47
|
-
"where"
|
|
48
|
-
>,
|
|
49
|
-
queryOptions?: Omit<UseQueryOptions, "queryKey" | "queryFn">,
|
|
50
|
-
): any {
|
|
51
|
-
const { client, locale } = useAdminContext<T>();
|
|
52
|
-
const localeKey = locale ?? "default";
|
|
53
|
-
const keyPrefix = ["qcms", "locale", localeKey] as const;
|
|
54
|
-
const queryOpts = createQuestpieQueryOptions(client, { keyPrefix });
|
|
55
|
-
|
|
56
|
-
return useQuery({
|
|
57
|
-
...queryOpts.collections[collection as string].findOne({
|
|
58
|
-
where: { id },
|
|
59
|
-
...options,
|
|
60
|
-
} as any),
|
|
61
|
-
...queryOptions,
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Hook to create collection item
|
|
67
|
-
*/
|
|
68
|
-
export function useCollectionCreate<
|
|
69
|
-
T extends Questpie<any>,
|
|
70
|
-
K extends keyof QuestpieClient<T>["collections"],
|
|
71
|
-
>(
|
|
72
|
-
collection: K,
|
|
73
|
-
mutationOptions?: Omit<UseMutationOptions, "mutationFn">,
|
|
74
|
-
): any {
|
|
75
|
-
const { client, locale } = useAdminContext<T>();
|
|
76
|
-
const queryClient = useQueryClient();
|
|
77
|
-
const localeKey = locale ?? "default";
|
|
78
|
-
const keyPrefix = ["qcms", "locale", localeKey] as const;
|
|
79
|
-
const queryOpts = createQuestpieQueryOptions(client, { keyPrefix });
|
|
80
|
-
|
|
81
|
-
const baseOptions = queryOpts.collections[collection as string].create();
|
|
82
|
-
|
|
83
|
-
return useMutation({
|
|
84
|
-
...baseOptions,
|
|
85
|
-
onSuccess: (data: any, variables: any, context: any) => {
|
|
86
|
-
// Invalidate list queries
|
|
87
|
-
queryClient.invalidateQueries({
|
|
88
|
-
queryKey: [...keyPrefix, "collections", collection, "find"],
|
|
89
|
-
});
|
|
90
|
-
(mutationOptions?.onSuccess as any)?.(data, variables, context);
|
|
91
|
-
},
|
|
92
|
-
...mutationOptions,
|
|
93
|
-
} as any);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Hook to update collection item
|
|
98
|
-
*/
|
|
99
|
-
export function useCollectionUpdate<
|
|
100
|
-
T extends Questpie<any>,
|
|
101
|
-
K extends keyof QuestpieClient<T>["collections"],
|
|
102
|
-
>(
|
|
103
|
-
collection: K,
|
|
104
|
-
mutationOptions?: Omit<UseMutationOptions, "mutationFn">,
|
|
105
|
-
): any {
|
|
106
|
-
const { client, locale } = useAdminContext<T>();
|
|
107
|
-
const queryClient = useQueryClient();
|
|
108
|
-
const localeKey = locale ?? "default";
|
|
109
|
-
const keyPrefix = ["qcms", "locale", localeKey] as const;
|
|
110
|
-
const queryOpts = createQuestpieQueryOptions(client, { keyPrefix });
|
|
111
|
-
|
|
112
|
-
const baseOptions = queryOpts.collections[collection as string].update();
|
|
113
|
-
|
|
114
|
-
return useMutation({
|
|
115
|
-
...baseOptions,
|
|
116
|
-
onSuccess: (data: any, variables: any, context: any) => {
|
|
117
|
-
// Invalidate list and detail queries
|
|
118
|
-
queryClient.invalidateQueries({
|
|
119
|
-
queryKey: [...keyPrefix, "collections", collection],
|
|
120
|
-
});
|
|
121
|
-
(mutationOptions?.onSuccess as any)?.(data, variables, context);
|
|
122
|
-
},
|
|
123
|
-
...mutationOptions,
|
|
124
|
-
} as any);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Hook to delete collection item
|
|
129
|
-
*/
|
|
130
|
-
export function useCollectionDelete<
|
|
131
|
-
T extends Questpie<any>,
|
|
132
|
-
K extends keyof QuestpieClient<T>["collections"],
|
|
133
|
-
>(
|
|
134
|
-
collection: K,
|
|
135
|
-
mutationOptions?: Omit<UseMutationOptions, "mutationFn">,
|
|
136
|
-
): any {
|
|
137
|
-
const { client, locale } = useAdminContext<T>();
|
|
138
|
-
const queryClient = useQueryClient();
|
|
139
|
-
const localeKey = locale ?? "default";
|
|
140
|
-
const keyPrefix = ["qcms", "locale", localeKey] as const;
|
|
141
|
-
const queryOpts = createQuestpieQueryOptions(client, { keyPrefix });
|
|
142
|
-
|
|
143
|
-
const baseOptions = queryOpts.collections[collection as string].delete();
|
|
144
|
-
|
|
145
|
-
return useMutation({
|
|
146
|
-
...baseOptions,
|
|
147
|
-
onSuccess: (data: any, variables: any, context: any) => {
|
|
148
|
-
// Invalidate list queries
|
|
149
|
-
queryClient.invalidateQueries({
|
|
150
|
-
queryKey: [...keyPrefix, "collections", collection],
|
|
151
|
-
});
|
|
152
|
-
(mutationOptions?.onSuccess as any)?.(data, variables, context);
|
|
153
|
-
},
|
|
154
|
-
...mutationOptions,
|
|
155
|
-
} as any);
|
|
156
|
-
}
|
package/src/hooks/use-global.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useQuery,
|
|
3
|
-
useMutation,
|
|
4
|
-
useQueryClient,
|
|
5
|
-
type UseQueryOptions,
|
|
6
|
-
type UseMutationOptions,
|
|
7
|
-
} from "@tanstack/react-query";
|
|
8
|
-
import type { QuestpieClient } from "questpie/client";
|
|
9
|
-
import type { Questpie } from "questpie";
|
|
10
|
-
import { createQuestpieQueryOptions } from "@questpie/tanstack-query";
|
|
11
|
-
import { useAdminContext } from "./admin-provider";
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Hook to fetch global settings
|
|
15
|
-
*/
|
|
16
|
-
export function useGlobal<
|
|
17
|
-
T extends Questpie<any>,
|
|
18
|
-
K extends keyof QuestpieClient<T>["globals"],
|
|
19
|
-
>(
|
|
20
|
-
globalName: K,
|
|
21
|
-
options?: Parameters<QuestpieClient<T>["globals"][K]["get"]>[0],
|
|
22
|
-
queryOptions?: Omit<UseQueryOptions, "queryKey" | "queryFn">,
|
|
23
|
-
): any {
|
|
24
|
-
const { client, locale } = useAdminContext<T>();
|
|
25
|
-
const localeKey = locale ?? "default";
|
|
26
|
-
const keyPrefix = ["qcms", "locale", localeKey] as const;
|
|
27
|
-
const queryOpts = createQuestpieQueryOptions(client, { keyPrefix });
|
|
28
|
-
|
|
29
|
-
return useQuery({
|
|
30
|
-
...queryOpts.globals[globalName as string].get(options as any),
|
|
31
|
-
...queryOptions,
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Hook to update global settings
|
|
37
|
-
*/
|
|
38
|
-
export function useGlobalUpdate<
|
|
39
|
-
T extends Questpie<any>,
|
|
40
|
-
K extends keyof QuestpieClient<T>["globals"],
|
|
41
|
-
>(
|
|
42
|
-
globalName: K,
|
|
43
|
-
mutationOptions?: UseMutationOptions<
|
|
44
|
-
Awaited<ReturnType<QuestpieClient<T>["globals"][K]["update"]>>,
|
|
45
|
-
Error,
|
|
46
|
-
{
|
|
47
|
-
data: Parameters<QuestpieClient<T>["globals"][K]["update"]>[0];
|
|
48
|
-
options?: Parameters<QuestpieClient<T>["globals"][K]["update"]>[1];
|
|
49
|
-
}
|
|
50
|
-
>,
|
|
51
|
-
): any {
|
|
52
|
-
const { client, locale } = useAdminContext<T>();
|
|
53
|
-
const queryClient = useQueryClient();
|
|
54
|
-
const localeKey = locale ?? "default";
|
|
55
|
-
const keyPrefix = ["qcms", "locale", localeKey] as const;
|
|
56
|
-
const queryOpts = createQuestpieQueryOptions(client, { keyPrefix });
|
|
57
|
-
|
|
58
|
-
return useMutation({
|
|
59
|
-
...queryOpts.globals[globalName as string].update(),
|
|
60
|
-
onSuccess: (...args) => {
|
|
61
|
-
// Invalidate global queries
|
|
62
|
-
queryClient.invalidateQueries({
|
|
63
|
-
queryKey: [...keyPrefix, "globals", globalName],
|
|
64
|
-
});
|
|
65
|
-
mutationOptions?.onSuccess?.(...args);
|
|
66
|
-
},
|
|
67
|
-
...mutationOptions,
|
|
68
|
-
});
|
|
69
|
-
}
|
package/src/hooks/use-mobile.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
|
|
3
|
-
const MOBILE_BREAKPOINT = 768;
|
|
4
|
-
|
|
5
|
-
export function useIsMobile() {
|
|
6
|
-
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(
|
|
7
|
-
undefined,
|
|
8
|
-
);
|
|
9
|
-
|
|
10
|
-
React.useEffect(() => {
|
|
11
|
-
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
12
|
-
const onChange = () => {
|
|
13
|
-
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
14
|
-
};
|
|
15
|
-
mql.addEventListener("change", onChange);
|
|
16
|
-
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
17
|
-
return () => mql.removeEventListener("change", onChange);
|
|
18
|
-
}, []);
|
|
19
|
-
|
|
20
|
-
return !!isMobile;
|
|
21
|
-
}
|