@questpie/admin 3.0.5 → 3.0.7

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.
Files changed (59) hide show
  1. package/README.md +99 -1
  2. package/dist/client/builder/types/field-types.d.mts +11 -0
  3. package/dist/client/components/brand-logo.d.mts +25 -0
  4. package/dist/client/components/brand-logo.mjs +174 -0
  5. package/dist/client/create-admin-client.d.mts +7 -0
  6. package/dist/client/create-admin-client.mjs +25 -0
  7. package/dist/client/hooks/use-brand.d.mts +22 -0
  8. package/dist/client/hooks/use-brand.mjs +52 -0
  9. package/dist/client/runtime/index.mjs +1 -1
  10. package/dist/client/runtime/provider.d.mts +4 -0
  11. package/dist/client/runtime/provider.mjs +38 -8
  12. package/dist/client/styles/base.css +4 -0
  13. package/dist/client/types/admin-config.d.mts +24 -0
  14. package/dist/client/views/auth/accept-invite-form.d.mts +2 -2
  15. package/dist/client/views/auth/auth-layout.d.mts +8 -3
  16. package/dist/client/views/auth/auth-layout.mjs +116 -102
  17. package/dist/client/views/auth/forgot-password-form.d.mts +2 -2
  18. package/dist/client/views/auth/login-form.d.mts +2 -2
  19. package/dist/client/views/auth/reset-password-form.d.mts +2 -2
  20. package/dist/client/views/auth/setup-form.d.mts +2 -2
  21. package/dist/client/views/collection/auto-form-fields.mjs +2 -0
  22. package/dist/client/views/collection/field-renderer.mjs +3 -2
  23. package/dist/client/views/globals/global-form-view.mjs +908 -863
  24. package/dist/client/views/layout/admin-sidebar.mjs +153 -141
  25. package/dist/client/views/pages/accept-invite-page.mjs +122 -144
  26. package/dist/client/views/pages/forgot-password-page.mjs +22 -30
  27. package/dist/client/views/pages/invite-page.mjs +24 -33
  28. package/dist/client/views/pages/login-page.d.mts +2 -2
  29. package/dist/client/views/pages/login-page.mjs +24 -32
  30. package/dist/client/views/pages/reset-password-page.d.mts +2 -2
  31. package/dist/client/views/pages/reset-password-page.mjs +77 -92
  32. package/dist/client/views/pages/setup-page.mjs +31 -39
  33. package/dist/client.d.mts +6 -2
  34. package/dist/client.mjs +5 -2
  35. package/dist/index.d.mts +6 -2
  36. package/dist/index.mjs +5 -2
  37. package/dist/server/augmentation/dashboard.d.mts +23 -5
  38. package/dist/server/augmentation/form-layout.d.mts +10 -0
  39. package/dist/server/augmentation/index.d.mts +1 -1
  40. package/dist/server/augmentation.d.mts +1 -1
  41. package/dist/server/modules/admin/collections/session.d.mts +42 -42
  42. package/dist/server/modules/admin/collections/user.d.mts +32 -32
  43. package/dist/server/modules/admin/collections/verification.d.mts +36 -36
  44. package/dist/server/modules/admin/dto/admin-config.dto.mjs +19 -1
  45. package/dist/server/modules/admin/index.d.mts +1 -1
  46. package/dist/server/modules/admin/routes/admin-config.d.mts +2 -2
  47. package/dist/server/modules/admin/routes/execute-action.d.mts +9 -9
  48. package/dist/server/modules/admin/routes/preview.d.mts +11 -11
  49. package/dist/server/modules/admin/routes/preview.mjs +1 -1
  50. package/dist/server/modules/admin/routes/reactive.d.mts +9 -9
  51. package/dist/server/modules/admin/routes/setup.d.mts +7 -7
  52. package/dist/server/modules/admin/routes/widget-data.d.mts +5 -5
  53. package/dist/server/modules/admin-preferences/collections/saved-views.d.mts +23 -23
  54. package/dist/server.d.mts +4 -4
  55. package/dist/shared/preview-utils.d.mts +34 -1
  56. package/dist/shared/preview-utils.mjs +79 -1
  57. package/dist/shared.d.mts +2 -2
  58. package/dist/shared.mjs +2 -2
  59. package/package.json +3 -3
@@ -1,6 +1,6 @@
1
1
  import { FilterOperator, FilterRule, SortConfig, ViewConfiguration } from "../../../../shared/types/saved-views.types.mjs";
2
2
  import * as questpie_shared15 from "questpie/shared";
3
- import * as questpie73 from "questpie";
3
+ import * as questpie69 from "questpie";
4
4
  import * as questpie_src_server_modules_core_fields_email_js1 from "questpie/src/server/modules/core/fields/email.js";
5
5
  import * as questpie_src_server_modules_core_fields_json_js1 from "questpie/src/server/modules/core/fields/json.js";
6
6
  import * as drizzle_orm_pg_core22 from "drizzle-orm/pg-core";
@@ -33,22 +33,22 @@ import * as drizzle_orm5 from "drizzle-orm";
33
33
  * });
34
34
  * ```
35
35
  */
36
- declare const savedViewsCollection: questpie73.CollectionBuilder<questpie_shared15.Override<questpie_shared15.Override<questpie73.EmptyCollectionState<"admin_saved_views", undefined, {
37
- readonly text: typeof questpie73.text;
38
- readonly textarea: typeof questpie73.textarea;
36
+ declare const savedViewsCollection: questpie69.CollectionBuilder<questpie_shared15.Override<questpie_shared15.Override<questpie69.EmptyCollectionState<"admin_saved_views", undefined, {
37
+ readonly text: typeof questpie69.text;
38
+ readonly textarea: typeof questpie69.textarea;
39
39
  readonly email: typeof questpie_src_server_modules_core_fields_email_js1.email;
40
- readonly url: typeof questpie73.url;
41
- readonly number: typeof questpie73.number;
42
- readonly boolean: typeof questpie73.boolean;
43
- readonly date: typeof questpie73.date;
44
- readonly datetime: typeof questpie73.datetime;
45
- readonly time: typeof questpie73.time;
46
- readonly select: typeof questpie73.select;
47
- readonly upload: typeof questpie73.upload;
48
- readonly relation: typeof questpie73.relation;
49
- readonly object: typeof questpie73.object;
40
+ readonly url: typeof questpie69.url;
41
+ readonly number: typeof questpie69.number;
42
+ readonly boolean: typeof questpie69.boolean;
43
+ readonly date: typeof questpie69.date;
44
+ readonly datetime: typeof questpie69.datetime;
45
+ readonly time: typeof questpie69.time;
46
+ readonly select: typeof questpie69.select;
47
+ readonly upload: typeof questpie69.upload;
48
+ readonly relation: typeof questpie69.relation;
49
+ readonly object: typeof questpie69.object;
50
50
  readonly json: typeof questpie_src_server_modules_core_fields_json_js1.json;
51
- readonly from: typeof questpie73.from;
51
+ readonly from: typeof questpie69.from;
52
52
  }>, {
53
53
  fields: {
54
54
  readonly userId: drizzle_orm5.NotNull<drizzle_orm_pg_core22.PgVarcharBuilder<[string, ...string[]]>>;
@@ -59,31 +59,31 @@ declare const savedViewsCollection: questpie73.CollectionBuilder<questpie_shared
59
59
  };
60
60
  localized: readonly string[];
61
61
  fieldDefinitions: {
62
- readonly userId: questpie73.FieldWithMethods<Omit<questpie73.TextFieldState, "notNull" | "column"> & {
62
+ readonly userId: questpie69.FieldWithMethods<Omit<questpie69.TextFieldState, "notNull" | "column"> & {
63
63
  notNull: true;
64
64
  column: drizzle_orm5.NotNull<drizzle_orm_pg_core22.PgVarcharBuilder<[string, ...string[]]>>;
65
65
  } & {
66
66
  label: questpie_shared15.I18nText;
67
- }, questpie73.TextFieldMethods>;
68
- readonly collectionName: questpie73.FieldWithMethods<Omit<questpie73.TextFieldState, "notNull" | "column"> & {
67
+ }, questpie69.TextFieldMethods>;
68
+ readonly collectionName: questpie69.FieldWithMethods<Omit<questpie69.TextFieldState, "notNull" | "column"> & {
69
69
  notNull: true;
70
70
  column: drizzle_orm5.NotNull<drizzle_orm_pg_core22.PgVarcharBuilder<[string, ...string[]]>>;
71
71
  } & {
72
72
  label: questpie_shared15.I18nText;
73
- }, questpie73.TextFieldMethods>;
74
- readonly name: questpie73.FieldWithMethods<Omit<questpie73.TextFieldState, "notNull" | "column"> & {
73
+ }, questpie69.TextFieldMethods>;
74
+ readonly name: questpie69.FieldWithMethods<Omit<questpie69.TextFieldState, "notNull" | "column"> & {
75
75
  notNull: true;
76
76
  column: drizzle_orm5.NotNull<drizzle_orm_pg_core22.PgVarcharBuilder<[string, ...string[]]>>;
77
77
  } & {
78
78
  label: questpie_shared15.I18nText;
79
- }, questpie73.TextFieldMethods>;
80
- readonly configuration: questpie73.Field<Omit<questpie73.JsonFieldState, "notNull" | "column"> & {
79
+ }, questpie69.TextFieldMethods>;
80
+ readonly configuration: questpie69.Field<Omit<questpie69.JsonFieldState, "notNull" | "column"> & {
81
81
  notNull: true;
82
82
  column: drizzle_orm5.NotNull<drizzle_orm_pg_core22.PgJsonbBuilder>;
83
83
  } & {
84
84
  label: questpie_shared15.I18nText;
85
85
  }>;
86
- readonly isDefault: questpie73.Field<Omit<questpie73.BooleanFieldState, "column" | "hasDefault"> & {
86
+ readonly isDefault: questpie69.Field<Omit<questpie69.BooleanFieldState, "column" | "hasDefault"> & {
87
87
  hasDefault: true;
88
88
  column: drizzle_orm5.HasDefault<drizzle_orm_pg_core22.PgBooleanBuilder>;
89
89
  } & {
package/dist/server.d.mts CHANGED
@@ -6,10 +6,6 @@ import { ServerSidebarCollectionItem, ServerSidebarConfig, ServerSidebarDividerI
6
6
  import { ActionsConfigContext, BuiltinActionType, ServerActionContext, ServerActionDefinition, ServerActionDownload, ServerActionEffects, ServerActionError, ServerActionForm, ServerActionFormField, ServerActionHandler, ServerActionRedirect, ServerActionResult, ServerActionSuccess, ServerActionsConfig } from "./server/augmentation/actions.mjs";
7
7
  import { AdminConfigInput, adminConfig } from "./server/augmentation/index.mjs";
8
8
  import "./server/augmentation.mjs";
9
- import { adminPlugin } from "./server/plugin.mjs";
10
- import { AuthSession, GetAdminSessionOptions, RequireAdminAuthOptions, getAdminSession, isAdminUser, requireAdminAuth } from "./server/modules/admin/auth-helpers.mjs";
11
- import { NextAuthMiddlewareOptions, createNextAuthMiddleware, getNextAdminSession } from "./server/adapters/nextjs.mjs";
12
- import { BeforeLoadContext, TanStackAuthGuardOptions, createTanStackAuthGuard, createTanStackSessionLoader } from "./server/adapters/tanstack.mjs";
13
9
  import { BlockNode, BlockValues, BlocksDocument, BlocksFieldMeta } from "./server/fields/blocks.mjs";
14
10
  import { RichTextFeature, RichTextFieldMeta, TipTapDocument, TipTapNode } from "./server/fields/rich-text.mjs";
15
11
  import { adminFields } from "./server/fields/index.mjs";
@@ -17,6 +13,10 @@ import { AnyBlockBuilder, AnyBlockDefinition, BlockBuilder, BlockBuilderState, B
17
13
  import { BlockSchema, getBlocksByCategory, introspectBlock, introspectBlocks } from "./server/modules/admin/block/introspection.mjs";
18
14
  import { BlocksPrefetchContext, createBlocksPrefetchHook, processBlocksDocument, processDocumentBlocksPrefetch } from "./server/modules/admin/block/prefetch.mjs";
19
15
  import "./server/block/index.mjs";
16
+ import { adminPlugin } from "./server/plugin.mjs";
17
+ import { AuthSession, GetAdminSessionOptions, RequireAdminAuthOptions, getAdminSession, isAdminUser, requireAdminAuth } from "./server/modules/admin/auth-helpers.mjs";
18
+ import { NextAuthMiddlewareOptions, createNextAuthMiddleware, getNextAdminSession } from "./server/adapters/nextjs.mjs";
19
+ import { BeforeLoadContext, TanStackAuthGuardOptions, createTanStackAuthGuard, createTanStackSessionLoader } from "./server/adapters/tanstack.mjs";
20
20
  import { ExecuteActionRequest, ExecuteActionResponse, actionFunctions, executeAction, executeActionFn, getActionsConfig, getActionsConfigFn } from "./server/modules/admin/routes/execute-action.mjs";
21
21
  import { PreviewTokenPayload, createPreviewFunctions, createPreviewTokenVerifier, verifyPreviewTokenDirect } from "./server/modules/admin/routes/preview.mjs";
22
22
  import { batchReactive, fieldOptions, reactiveFunctions } from "./server/modules/admin/routes/reactive.mjs";
@@ -10,6 +10,39 @@
10
10
  * Set by /api/preview route, checked by page loaders.
11
11
  */
12
12
  declare const DRAFT_MODE_COOKIE = "__draft_mode";
13
+ /**
14
+ * URL prefix used by the admin SPA when mounted at the conventional
15
+ * `/admin` path. Kept for reference and as a fallback signal for setups
16
+ * that pre-date the header-based detection.
17
+ */
18
+ declare const ADMIN_API_PREFIX = "/admin/api/";
19
+ /**
20
+ * Whether the given request originates from the admin panel.
21
+ *
22
+ * Detection strategy (in order):
23
+ * 1. Presence of the `X-Questpie-Admin` request header — the canonical
24
+ * signal, injected by `createAdminClient` / `withAdminRequestHeader`.
25
+ * 2. URL path starts with {@link ADMIN_API_PREFIX} — fallback for clients
26
+ * that don't inject the header (e.g. pre-3.0.6 admin SDK consumers, or
27
+ * direct `curl` calls to `/admin/api/...`).
28
+ *
29
+ * Use inside collection/global `.access()` rules to grant admin-only
30
+ * scope (e.g. master counselor sees everything in the admin, but stays
31
+ * scoped to their own data on the frontend).
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * import { isAdminRequest } from "@questpie/admin/shared";
36
+ *
37
+ * .access({
38
+ * read: ({ session, request }) => {
39
+ * if (isAdminRequest(request) && isAdmin(session?.user)) return true;
40
+ * return { createdById: session?.user?.id };
41
+ * },
42
+ * })
43
+ * ```
44
+ */
45
+ declare function isAdminRequest(request?: Request | null): boolean;
13
46
  /**
14
47
  * Check if draft mode is enabled from cookie header.
15
48
  *
@@ -50,4 +83,4 @@ declare function createDraftModeCookie(enabled: boolean, maxAge?: number): strin
50
83
  */
51
84
  declare function getPreviewSecret(): string;
52
85
  //#endregion
53
- export { DRAFT_MODE_COOKIE, createDraftModeCookie, getPreviewSecret, isDraftMode };
86
+ export { ADMIN_API_PREFIX, DRAFT_MODE_COOKIE, createDraftModeCookie, getPreviewSecret, isAdminRequest, isDraftMode };
@@ -11,6 +11,84 @@
11
11
  */
12
12
  const DRAFT_MODE_COOKIE = "__draft_mode";
13
13
  /**
14
+ * Header injected by `createAdminClient` (and `withAdminRequestHeader`) on
15
+ * every admin SPA request. Inspected by {@link isAdminRequest} so access
16
+ * rules can branch on caller intent without depending on URL structure.
17
+ */
18
+ const ADMIN_REQUEST_HEADER = "x-questpie-admin";
19
+ /**
20
+ * URL prefix used by the admin SPA when mounted at the conventional
21
+ * `/admin` path. Kept for reference and as a fallback signal for setups
22
+ * that pre-date the header-based detection.
23
+ */
24
+ const ADMIN_API_PREFIX = "/admin/api/";
25
+ /**
26
+ * Whether the given request originates from the admin panel.
27
+ *
28
+ * Detection strategy (in order):
29
+ * 1. Presence of the `X-Questpie-Admin` request header — the canonical
30
+ * signal, injected by `createAdminClient` / `withAdminRequestHeader`.
31
+ * 2. URL path starts with {@link ADMIN_API_PREFIX} — fallback for clients
32
+ * that don't inject the header (e.g. pre-3.0.6 admin SDK consumers, or
33
+ * direct `curl` calls to `/admin/api/...`).
34
+ *
35
+ * Use inside collection/global `.access()` rules to grant admin-only
36
+ * scope (e.g. master counselor sees everything in the admin, but stays
37
+ * scoped to their own data on the frontend).
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * import { isAdminRequest } from "@questpie/admin/shared";
42
+ *
43
+ * .access({
44
+ * read: ({ session, request }) => {
45
+ * if (isAdminRequest(request) && isAdmin(session?.user)) return true;
46
+ * return { createdById: session?.user?.id };
47
+ * },
48
+ * })
49
+ * ```
50
+ */
51
+ function isAdminRequest(request) {
52
+ if (!request) return false;
53
+ if (request.headers?.get?.(ADMIN_REQUEST_HEADER)) return true;
54
+ try {
55
+ return new URL(request.url).pathname.startsWith(ADMIN_API_PREFIX);
56
+ } catch {
57
+ return false;
58
+ }
59
+ }
60
+ /**
61
+ * Wrap a `fetch` implementation so every outbound request carries the
62
+ * `X-Questpie-Admin` header. Used internally by
63
+ * `createAdminClient` — apps building a custom admin client (or using
64
+ * an alternate HTTP layer) can compose the wrapper themselves.
65
+ *
66
+ * @param baseFetch - The fetch implementation to wrap. Defaults to
67
+ * `globalThis.fetch`.
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * import { createClient } from "questpie/client";
72
+ * import { withAdminRequestHeader } from "@questpie/admin/shared";
73
+ *
74
+ * export const adminCmsClient = createClient<AppConfig>({
75
+ * baseURL: window.location.origin,
76
+ * basePath: "/api",
77
+ * fetch: withAdminRequestHeader(),
78
+ * });
79
+ * ```
80
+ */
81
+ function withAdminRequestHeader(baseFetch = globalThis.fetch) {
82
+ return ((input, init) => {
83
+ const headers = new Headers(init?.headers);
84
+ if (!headers.has(ADMIN_REQUEST_HEADER)) headers.set(ADMIN_REQUEST_HEADER, "1");
85
+ return baseFetch(input, {
86
+ ...init,
87
+ headers
88
+ });
89
+ });
90
+ }
91
+ /**
14
92
  * Check if draft mode is enabled from cookie header.
15
93
  *
16
94
  * @param cookieHeader - The Cookie header value from request
@@ -61,4 +139,4 @@ function getPreviewSecret() {
61
139
  }
62
140
 
63
141
  //#endregion
64
- export { DRAFT_MODE_COOKIE, createDraftModeCookie, getPreviewSecret, isDraftMode };
142
+ export { ADMIN_API_PREFIX, DRAFT_MODE_COOKIE, createDraftModeCookie, getPreviewSecret, isAdminRequest, isDraftMode, withAdminRequestHeader };
package/dist/shared.d.mts CHANGED
@@ -1,3 +1,3 @@
1
1
  import { FilterOperator, FilterRule, SortConfig, ViewConfiguration } from "./shared/types/saved-views.types.mjs";
2
- import { DRAFT_MODE_COOKIE, createDraftModeCookie, getPreviewSecret, isDraftMode } from "./shared/preview-utils.mjs";
3
- export { DRAFT_MODE_COOKIE, type FilterOperator, type FilterRule, type SortConfig, type ViewConfiguration, createDraftModeCookie, getPreviewSecret, isDraftMode };
2
+ import { ADMIN_API_PREFIX, DRAFT_MODE_COOKIE, createDraftModeCookie, getPreviewSecret, isAdminRequest, isDraftMode } from "./shared/preview-utils.mjs";
3
+ export { ADMIN_API_PREFIX, DRAFT_MODE_COOKIE, type FilterOperator, type FilterRule, type SortConfig, type ViewConfiguration, createDraftModeCookie, getPreviewSecret, isAdminRequest, isDraftMode };
package/dist/shared.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { DRAFT_MODE_COOKIE, createDraftModeCookie, getPreviewSecret, isDraftMode } from "./shared/preview-utils.mjs";
1
+ import { ADMIN_API_PREFIX, DRAFT_MODE_COOKIE, createDraftModeCookie, getPreviewSecret, isAdminRequest, isDraftMode } from "./shared/preview-utils.mjs";
2
2
 
3
- export { DRAFT_MODE_COOKIE, createDraftModeCookie, getPreviewSecret, isDraftMode };
3
+ export { ADMIN_API_PREFIX, DRAFT_MODE_COOKIE, createDraftModeCookie, getPreviewSecret, isAdminRequest, isDraftMode };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@questpie/admin",
3
- "version": "3.0.5",
3
+ "version": "3.0.7",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/questpie/questpie.git",
@@ -62,7 +62,7 @@
62
62
  "@fontsource-variable/jetbrains-mono": "^5.2.8",
63
63
  "@hookform/resolvers": "^5.1.0",
64
64
  "@iconify/react": "^6.0.2",
65
- "@questpie/tanstack-query": "^3.0.5",
65
+ "@questpie/tanstack-query": "^3.0.7",
66
66
  "@tailwindcss/vite": "^4.0.6",
67
67
  "@tiptap/core": "^2.x",
68
68
  "@tiptap/extension-character-count": "^2.x",
@@ -88,7 +88,7 @@
88
88
  "date-fns": "^4.1.0",
89
89
  "lowlight": "^3.x",
90
90
  "next-themes": "^0.4.6",
91
- "questpie": "^3.0.5",
91
+ "questpie": "^3.0.7",
92
92
  "react-day-picker": "^9.12.0",
93
93
  "react-hook-form": "^7.54.0",
94
94
  "react-resizable-panels": "^4.4.2",