@questpie/admin 3.2.6 → 3.3.0
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/dist/client/components/admin-link.d.mts +2 -2
- package/dist/client/components/blocks/block-editor-provider.mjs +13 -0
- package/dist/client/components/fields/array-field.mjs +105 -122
- package/dist/client/components/fields/asset-preview-field.mjs +1 -1
- package/dist/client/components/fields/blocks-field/blocks-field.mjs +1 -1
- package/dist/client/components/fields/boolean-field.mjs +1 -1
- package/dist/client/components/fields/date-field.mjs +1 -1
- package/dist/client/components/fields/datetime-field.mjs +1 -1
- package/dist/client/components/fields/email-field.mjs +1 -1
- package/dist/client/components/fields/field-wrapper.mjs +44 -15
- package/dist/client/components/fields/number-field.mjs +1 -1
- package/dist/client/components/fields/object-array-field.mjs +179 -149
- package/dist/client/components/fields/object-field.mjs +96 -87
- package/dist/client/components/fields/relation-picker.mjs +1 -1
- package/dist/client/components/fields/relation-select.mjs +1 -1
- package/dist/client/components/fields/rich-text-editor/index.mjs +1 -1
- package/dist/client/components/fields/select-field.mjs +1 -1
- package/dist/client/components/fields/text-field.mjs +1 -1
- package/dist/client/components/fields/textarea-field.mjs +1 -1
- package/dist/client/components/fields/time-field.mjs +1 -1
- package/dist/client/components/fields/upload-field.mjs +1 -1
- package/dist/client/components/history-sidebar.mjs +10 -4
- package/dist/client/components/structured-diff.mjs +367 -0
- package/dist/client/components/ui/sidebar.mjs +1 -1
- package/dist/client/hooks/use-field-options.mjs +34 -15
- package/dist/client/hooks/use-transition-stage.mjs +2 -2
- package/dist/client/preview/preview-banner.d.mts +2 -2
- package/dist/client/preview/preview-field.d.mts +4 -4
- package/dist/client/preview/use-collection-preview.mjs +0 -35
- package/dist/client/utils/auto-expand-fields.mjs +1 -1
- package/dist/client/views/collection/auto-form-fields.mjs +23 -19
- package/dist/client/views/collection/cells/complex-cells.mjs +1 -1
- package/dist/client/views/collection/columns/build-columns.mjs +1 -1
- package/dist/client/views/collection/columns/column-defaults.mjs +17 -4
- package/dist/client/views/collection/field-renderer.mjs +19 -7
- package/dist/client/views/collection/form-view.mjs +10 -6
- package/dist/client/views/collection/table-view.mjs +19 -13
- package/dist/client/views/globals/global-form-view.mjs +47 -27
- package/dist/client/views/layout/admin-sidebar.mjs +2 -2
- package/dist/client/views/pages/login-page.d.mts +2 -2
- package/dist/client/views/pages/reset-password-page.d.mts +2 -2
- package/dist/client/views/pages/setup-page.d.mts +2 -2
- package/dist/client.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/server/adapters/nextjs.d.mts +0 -1
- package/dist/server/i18n/messages/cs.mjs +8 -0
- package/dist/server/i18n/messages/de.mjs +8 -0
- package/dist/server/i18n/messages/en.mjs +8 -0
- package/dist/server/i18n/messages/es.mjs +8 -0
- package/dist/server/i18n/messages/fr.mjs +8 -0
- package/dist/server/i18n/messages/pl.mjs +8 -0
- package/dist/server/i18n/messages/pt.mjs +8 -0
- package/dist/server/i18n/messages/sk.mjs +8 -0
- package/dist/server/modules/admin/.generated/module.d.mts +0 -1
- package/dist/server/modules/admin/collections/account.d.mts +46 -46
- package/dist/server/modules/admin/collections/admin-locks.d.mts +54 -54
- package/dist/server/modules/admin/collections/admin-preferences.d.mts +39 -39
- package/dist/server/modules/admin/collections/admin-saved-views.d.mts +47 -47
- package/dist/server/modules/admin/collections/apikey.d.mts +68 -68
- package/dist/server/modules/admin/collections/assets.d.mts +34 -34
- package/dist/server/modules/admin/collections/session.d.mts +38 -38
- package/dist/server/modules/admin/collections/user.d.mts +53 -53
- package/dist/server/modules/admin/collections/verification.d.mts +2 -2
- package/dist/server/modules/admin/routes/execute-action.d.mts +9 -9
- package/dist/server/modules/admin/routes/preview.d.mts +13 -8
- package/dist/server/modules/admin/routes/preview.mjs +83 -62
- package/dist/server/modules/admin/routes/reactive.d.mts +9 -9
- package/dist/server/modules/admin/routes/setup.d.mts +7 -7
- package/dist/server/modules/admin/routes/widget-data.d.mts +5 -5
- package/dist/server/modules/admin-preferences/collections/saved-views.d.mts +33 -33
- package/dist/server/modules/audit/.generated/module.d.mts +6 -6
- package/dist/server/modules/audit/collections/audit-log.d.mts +39 -37
- package/dist/server/modules/audit/collections/audit-log.mjs +7 -2
- package/dist/server/modules/audit/config/localize-title.mjs +67 -0
- package/dist/server/modules/audit/index.d.mts +2 -1
- package/dist/server/modules/audit/log-audit-entry.d.mts +85 -0
- package/dist/server/modules/audit/log-audit-entry.mjs +125 -0
- package/dist/server/plugin.mjs +4 -4
- package/dist/server.d.mts +2 -3
- package/dist/server.mjs +2 -1
- package/dist/shared/preview-utils.d.mts +4 -4
- package/dist/shared/preview-utils.mjs +5 -7
- package/package.json +3 -3
- package/dist/client/hooks/use-audit-history.mjs +0 -38
- package/dist/server/adapters/index.d.mts +0 -2
- package/dist/server/auth-helpers.d.mts +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ServerActionDefinition, ServerActionResult } from "../../../augmentation/actions.mjs";
|
|
2
2
|
import "../../../augmentation.mjs";
|
|
3
3
|
import { App } from "./route-helpers.mjs";
|
|
4
|
-
import * as
|
|
4
|
+
import * as questpie121 from "questpie";
|
|
5
5
|
|
|
6
6
|
//#region src/server/modules/admin/routes/execute-action.d.ts
|
|
7
7
|
|
|
@@ -56,37 +56,37 @@ declare function executeAction(app: App, request: ExecuteActionRequest, session?
|
|
|
56
56
|
* });
|
|
57
57
|
* ```
|
|
58
58
|
*/
|
|
59
|
-
declare const executeActionFn:
|
|
59
|
+
declare const executeActionFn: questpie121.JsonRouteDefinition<{
|
|
60
60
|
collection: string;
|
|
61
61
|
actionId: string;
|
|
62
62
|
itemId?: string | undefined;
|
|
63
63
|
itemIds?: string[] | undefined;
|
|
64
64
|
data?: Record<string, unknown> | undefined;
|
|
65
65
|
locale?: string | undefined;
|
|
66
|
-
}, any,
|
|
66
|
+
}, any, questpie121.JsonRouteParams>;
|
|
67
67
|
/**
|
|
68
68
|
* Get actions configuration for a collection.
|
|
69
69
|
* Returns action definitions without handlers for client rendering.
|
|
70
70
|
*/
|
|
71
|
-
declare const getActionsConfigFn:
|
|
71
|
+
declare const getActionsConfigFn: questpie121.JsonRouteDefinition<{
|
|
72
72
|
collection: string;
|
|
73
|
-
}, any,
|
|
73
|
+
}, any, questpie121.JsonRouteParams>;
|
|
74
74
|
/**
|
|
75
75
|
* QUESTPIE functions for action execution.
|
|
76
76
|
* These are registered on the `adminModule`.
|
|
77
77
|
*/
|
|
78
78
|
declare const actionFunctions: {
|
|
79
|
-
executeAction:
|
|
79
|
+
executeAction: questpie121.JsonRouteDefinition<{
|
|
80
80
|
collection: string;
|
|
81
81
|
actionId: string;
|
|
82
82
|
itemId?: string | undefined;
|
|
83
83
|
itemIds?: string[] | undefined;
|
|
84
84
|
data?: Record<string, unknown> | undefined;
|
|
85
85
|
locale?: string | undefined;
|
|
86
|
-
}, any,
|
|
87
|
-
getActionsConfig:
|
|
86
|
+
}, any, questpie121.JsonRouteParams>;
|
|
87
|
+
getActionsConfig: questpie121.JsonRouteDefinition<{
|
|
88
88
|
collection: string;
|
|
89
|
-
}, any,
|
|
89
|
+
}, any, questpie121.JsonRouteParams>;
|
|
90
90
|
};
|
|
91
91
|
//#endregion
|
|
92
92
|
export { ExecuteActionRequest, ExecuteActionResponse, actionFunctions, executeAction, executeActionFn, getActionsConfig, getActionsConfigFn };
|
|
@@ -10,6 +10,9 @@ import * as questpie141 from "questpie";
|
|
|
10
10
|
*
|
|
11
11
|
* Browser-safe utilities (isDraftMode, createDraftModeCookie, etc.) are in @questpie/admin/shared
|
|
12
12
|
*/
|
|
13
|
+
type PreviewSecretResolverContext = Record<string, any>;
|
|
14
|
+
type PreviewSecretResolver = (ctx: PreviewSecretResolverContext) => string | Promise<string>;
|
|
15
|
+
type PreviewSecretSource = string | PreviewSecretResolver;
|
|
13
16
|
interface PreviewTokenPayload {
|
|
14
17
|
path: string;
|
|
15
18
|
exp: number;
|
|
@@ -17,10 +20,11 @@ interface PreviewTokenPayload {
|
|
|
17
20
|
/**
|
|
18
21
|
* Create preview-related RPC functions.
|
|
19
22
|
*
|
|
20
|
-
* @param secret - Secret key for signing tokens
|
|
23
|
+
* @param secret - Secret key or resolver for signing tokens. Defaults to
|
|
24
|
+
* `app.config.secret` from the current route context.
|
|
21
25
|
* @returns Object with preview functions
|
|
22
26
|
*/
|
|
23
|
-
declare function createPreviewFunctions(secret
|
|
27
|
+
declare function createPreviewFunctions(secret?: PreviewSecretSource): {
|
|
24
28
|
mintPreviewToken: questpie141.JsonRouteDefinition<{
|
|
25
29
|
path: string;
|
|
26
30
|
ttlMs?: number | undefined;
|
|
@@ -37,29 +41,30 @@ declare function createPreviewFunctions(secret: string): {
|
|
|
37
41
|
* @param secret - The secret used to sign the token
|
|
38
42
|
* @returns The payload if valid, null otherwise
|
|
39
43
|
*/
|
|
40
|
-
declare function verifyPreviewTokenDirect(token: string, secret: string): PreviewTokenPayload | null
|
|
44
|
+
declare function verifyPreviewTokenDirect(token: string, secret: string): Promise<PreviewTokenPayload | null>;
|
|
41
45
|
/**
|
|
42
46
|
* Create a preview token verifier with bound secret.
|
|
43
47
|
* Use this in route handlers to avoid passing secret repeatedly.
|
|
44
48
|
*
|
|
45
|
-
* @param secret - The secret used to sign tokens
|
|
49
|
+
* @param secret - The secret used to sign tokens.
|
|
46
50
|
* @returns A verify function that only needs the token
|
|
47
51
|
*
|
|
48
52
|
* @example
|
|
49
53
|
* ```ts
|
|
50
54
|
* // Create once at module level
|
|
51
|
-
* const verifyPreviewToken = createPreviewTokenVerifier();
|
|
55
|
+
* const verifyPreviewToken = createPreviewTokenVerifier(secret);
|
|
52
56
|
*
|
|
53
57
|
* // Use in route handler
|
|
54
|
-
* const payload = verifyPreviewToken(token);
|
|
58
|
+
* const payload = await verifyPreviewToken(token);
|
|
55
59
|
* if (!payload) {
|
|
56
60
|
* return new Response("Invalid token", { status: 401 });
|
|
57
61
|
* }
|
|
58
62
|
* ```
|
|
59
63
|
*/
|
|
60
|
-
declare function createPreviewTokenVerifier(secret
|
|
64
|
+
declare function createPreviewTokenVerifier(secret: string): (token: string) => Promise<PreviewTokenPayload | null>;
|
|
61
65
|
/**
|
|
62
|
-
* Default preview functions bundle
|
|
66
|
+
* Default preview functions bundle. The route handlers resolve the token
|
|
67
|
+
* secret from `app.config.secret` at request time.
|
|
63
68
|
* Used by the `adminModule` to register preview RPC functions.
|
|
64
69
|
*/
|
|
65
70
|
declare const previewFunctions: {
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { getPreviewSecret } from "../../../../shared/preview-utils.mjs";
|
|
2
1
|
import { getApp, getCollectionState, getLocale, getSession } from "./route-helpers.mjs";
|
|
3
2
|
import { translateAdminMessage } from "./i18n-helpers.mjs";
|
|
4
3
|
import { z } from "zod";
|
|
5
4
|
import { ApiError, route } from "questpie";
|
|
6
|
-
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
7
5
|
|
|
8
6
|
//#region src/server/modules/admin/routes/preview.ts
|
|
9
7
|
/**
|
|
@@ -14,14 +12,72 @@ import { createHmac, timingSafeEqual } from "node:crypto";
|
|
|
14
12
|
*
|
|
15
13
|
* Browser-safe utilities (isDraftMode, createDraftModeCookie, etc.) are in @questpie/admin/shared
|
|
16
14
|
*/
|
|
15
|
+
const textEncoder = new TextEncoder();
|
|
16
|
+
const textDecoder = new TextDecoder();
|
|
17
|
+
function bytesFromBase64Input(input) {
|
|
18
|
+
if (typeof input === "string") return textEncoder.encode(input);
|
|
19
|
+
if (input instanceof Uint8Array) return input;
|
|
20
|
+
return new Uint8Array(input);
|
|
21
|
+
}
|
|
22
|
+
function bytesToBase64(bytes) {
|
|
23
|
+
let binary = "";
|
|
24
|
+
const chunkSize = 32768;
|
|
25
|
+
for (let i = 0; i < bytes.length; i += chunkSize) binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));
|
|
26
|
+
return btoa(binary);
|
|
27
|
+
}
|
|
28
|
+
function base64ToBytes(input) {
|
|
29
|
+
const binary = atob(input);
|
|
30
|
+
const bytes = new Uint8Array(binary.length);
|
|
31
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
32
|
+
return bytes;
|
|
33
|
+
}
|
|
17
34
|
function base64UrlEncode(input) {
|
|
18
|
-
return (
|
|
35
|
+
return bytesToBase64(bytesFromBase64Input(input)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
19
36
|
}
|
|
20
37
|
function base64UrlDecode(input) {
|
|
21
38
|
let base64 = input.replace(/-/g, "+").replace(/_/g, "/");
|
|
22
39
|
const padding = base64.length % 4;
|
|
23
40
|
if (padding) base64 += "=".repeat(4 - padding);
|
|
24
|
-
return
|
|
41
|
+
return textDecoder.decode(base64ToBytes(base64));
|
|
42
|
+
}
|
|
43
|
+
async function signPayload(payload, secret) {
|
|
44
|
+
const subtle = globalThis.crypto?.subtle;
|
|
45
|
+
if (!subtle) throw new Error("[preview] Web Crypto API is required to sign preview tokens.");
|
|
46
|
+
const key = await subtle.importKey("raw", textEncoder.encode(secret), {
|
|
47
|
+
name: "HMAC",
|
|
48
|
+
hash: "SHA-256"
|
|
49
|
+
}, false, ["sign"]);
|
|
50
|
+
return base64UrlEncode(await subtle.sign("HMAC", key, textEncoder.encode(payload)));
|
|
51
|
+
}
|
|
52
|
+
function timingSafeEqualAscii(a, b) {
|
|
53
|
+
const aBytes = textEncoder.encode(a);
|
|
54
|
+
const bBytes = textEncoder.encode(b);
|
|
55
|
+
let diff = aBytes.length ^ bBytes.length;
|
|
56
|
+
const maxLength = Math.max(aBytes.length, bBytes.length);
|
|
57
|
+
for (let i = 0; i < maxLength; i++) diff |= (aBytes[i] ?? 0) ^ (bBytes[i] ?? 0);
|
|
58
|
+
return diff === 0;
|
|
59
|
+
}
|
|
60
|
+
function defaultPreviewSecret(ctx) {
|
|
61
|
+
return getApp(ctx).config.secret ?? "dev-preview-secret";
|
|
62
|
+
}
|
|
63
|
+
async function resolvePreviewSecret(source, ctx) {
|
|
64
|
+
const secret = typeof source === "function" ? await source(ctx) : source;
|
|
65
|
+
if (!secret) throw new Error("[preview] Preview token secret must not be empty.");
|
|
66
|
+
return secret;
|
|
67
|
+
}
|
|
68
|
+
function parsePreviewTokenPayload(encodedPayload) {
|
|
69
|
+
try {
|
|
70
|
+
const payload = JSON.parse(base64UrlDecode(encodedPayload));
|
|
71
|
+
if (!payload?.exp || typeof payload.exp !== "number") return { error: "invalidPayload" };
|
|
72
|
+
if (payload.exp < Date.now()) return { error: "tokenExpired" };
|
|
73
|
+
if (!payload.path || typeof payload.path !== "string") return { error: "invalidPath" };
|
|
74
|
+
return { payload };
|
|
75
|
+
} catch {
|
|
76
|
+
return { error: "invalidPayload" };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async function verifyPreviewSignature(encodedPayload, signature, secret) {
|
|
80
|
+
return timingSafeEqualAscii(signature, await signPayload(encodedPayload, secret));
|
|
25
81
|
}
|
|
26
82
|
const mintPreviewTokenSchema = z.object({
|
|
27
83
|
path: z.string().min(1),
|
|
@@ -41,13 +97,11 @@ const DEFAULT_TTL_MS = 3600 * 1e3;
|
|
|
41
97
|
/**
|
|
42
98
|
* Create preview-related RPC functions.
|
|
43
99
|
*
|
|
44
|
-
* @param secret - Secret key for signing tokens
|
|
100
|
+
* @param secret - Secret key or resolver for signing tokens. Defaults to
|
|
101
|
+
* `app.config.secret` from the current route context.
|
|
45
102
|
* @returns Object with preview functions
|
|
46
103
|
*/
|
|
47
|
-
function createPreviewFunctions(secret) {
|
|
48
|
-
const signPayload = (payload) => {
|
|
49
|
-
return base64UrlEncode(createHmac("sha256", secret).update(payload).digest());
|
|
50
|
-
};
|
|
104
|
+
function createPreviewFunctions(secret = defaultPreviewSecret) {
|
|
51
105
|
return {
|
|
52
106
|
mintPreviewToken: route().post().schema(mintPreviewTokenSchema).outputSchema(mintPreviewTokenOutputSchema).handler(async (ctx) => {
|
|
53
107
|
const { input } = ctx;
|
|
@@ -62,7 +116,7 @@ function createPreviewFunctions(secret) {
|
|
|
62
116
|
};
|
|
63
117
|
const encodedPayload = base64UrlEncode(JSON.stringify(payload));
|
|
64
118
|
return {
|
|
65
|
-
token: `${encodedPayload}.${signPayload(encodedPayload)}`,
|
|
119
|
+
token: `${encodedPayload}.${await signPayload(encodedPayload, await resolvePreviewSecret(secret, ctx))}`,
|
|
66
120
|
expiresAt
|
|
67
121
|
};
|
|
68
122
|
}),
|
|
@@ -76,41 +130,19 @@ function createPreviewFunctions(secret) {
|
|
|
76
130
|
valid: false,
|
|
77
131
|
error: t("preview.invalidTokenFormat")
|
|
78
132
|
};
|
|
79
|
-
|
|
80
|
-
const signatureBuffer = Uint8Array.from(Buffer.from(signature));
|
|
81
|
-
const expectedBuffer = Uint8Array.from(Buffer.from(expectedSignature));
|
|
82
|
-
if (signatureBuffer.length !== expectedBuffer.length) return {
|
|
133
|
+
if (!await verifyPreviewSignature(encodedPayload, signature, await resolvePreviewSecret(secret, ctx))) return {
|
|
83
134
|
valid: false,
|
|
84
135
|
error: t("preview.invalidSignature")
|
|
85
136
|
};
|
|
86
|
-
|
|
137
|
+
const parsed = parsePreviewTokenPayload(encodedPayload);
|
|
138
|
+
if ("error" in parsed) return {
|
|
87
139
|
valid: false,
|
|
88
|
-
error: t(
|
|
140
|
+
error: t(`preview.${parsed.error}`)
|
|
141
|
+
};
|
|
142
|
+
return {
|
|
143
|
+
valid: true,
|
|
144
|
+
path: parsed.payload.path
|
|
89
145
|
};
|
|
90
|
-
try {
|
|
91
|
-
const payload = JSON.parse(base64UrlDecode(encodedPayload));
|
|
92
|
-
if (!payload?.exp || typeof payload.exp !== "number") return {
|
|
93
|
-
valid: false,
|
|
94
|
-
error: t("preview.invalidPayload")
|
|
95
|
-
};
|
|
96
|
-
if (payload.exp < Date.now()) return {
|
|
97
|
-
valid: false,
|
|
98
|
-
error: t("preview.tokenExpired")
|
|
99
|
-
};
|
|
100
|
-
if (!payload.path || typeof payload.path !== "string") return {
|
|
101
|
-
valid: false,
|
|
102
|
-
error: t("preview.invalidPath")
|
|
103
|
-
};
|
|
104
|
-
return {
|
|
105
|
-
valid: true,
|
|
106
|
-
path: payload.path
|
|
107
|
-
};
|
|
108
|
-
} catch {
|
|
109
|
-
return {
|
|
110
|
-
valid: false,
|
|
111
|
-
error: t("preview.invalidPayload")
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
146
|
})
|
|
115
147
|
};
|
|
116
148
|
}
|
|
@@ -122,47 +154,35 @@ function createPreviewFunctions(secret) {
|
|
|
122
154
|
* @param secret - The secret used to sign the token
|
|
123
155
|
* @returns The payload if valid, null otherwise
|
|
124
156
|
*/
|
|
125
|
-
function verifyPreviewTokenDirect(token, secret) {
|
|
157
|
+
async function verifyPreviewTokenDirect(token, secret) {
|
|
126
158
|
const [encodedPayload, signature] = token.split(".");
|
|
127
159
|
if (!encodedPayload || !signature) return null;
|
|
128
|
-
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
if (signatureBuffer.length !== expectedBuffer.length) return null;
|
|
132
|
-
if (!timingSafeEqual(signatureBuffer, expectedBuffer)) return null;
|
|
133
|
-
try {
|
|
134
|
-
const payload = JSON.parse(base64UrlDecode(encodedPayload));
|
|
135
|
-
if (!payload?.exp || typeof payload.exp !== "number") return null;
|
|
136
|
-
if (payload.exp < Date.now()) return null;
|
|
137
|
-
if (!payload.path || typeof payload.path !== "string") return null;
|
|
138
|
-
return payload;
|
|
139
|
-
} catch {
|
|
140
|
-
return null;
|
|
141
|
-
}
|
|
160
|
+
if (!await verifyPreviewSignature(encodedPayload, signature, secret)) return null;
|
|
161
|
+
const parsed = parsePreviewTokenPayload(encodedPayload);
|
|
162
|
+
return "payload" in parsed ? parsed.payload : null;
|
|
142
163
|
}
|
|
143
164
|
/**
|
|
144
165
|
* Create a preview token verifier with bound secret.
|
|
145
166
|
* Use this in route handlers to avoid passing secret repeatedly.
|
|
146
167
|
*
|
|
147
|
-
* @param secret - The secret used to sign tokens
|
|
168
|
+
* @param secret - The secret used to sign tokens.
|
|
148
169
|
* @returns A verify function that only needs the token
|
|
149
170
|
*
|
|
150
171
|
* @example
|
|
151
172
|
* ```ts
|
|
152
173
|
* // Create once at module level
|
|
153
|
-
* const verifyPreviewToken = createPreviewTokenVerifier();
|
|
174
|
+
* const verifyPreviewToken = createPreviewTokenVerifier(secret);
|
|
154
175
|
*
|
|
155
176
|
* // Use in route handler
|
|
156
|
-
* const payload = verifyPreviewToken(token);
|
|
177
|
+
* const payload = await verifyPreviewToken(token);
|
|
157
178
|
* if (!payload) {
|
|
158
179
|
* return new Response("Invalid token", { status: 401 });
|
|
159
180
|
* }
|
|
160
181
|
* ```
|
|
161
182
|
*/
|
|
162
183
|
function createPreviewTokenVerifier(secret) {
|
|
163
|
-
const resolvedSecret = secret ?? getPreviewSecret();
|
|
164
184
|
return (token) => {
|
|
165
|
-
return verifyPreviewTokenDirect(token,
|
|
185
|
+
return verifyPreviewTokenDirect(token, secret);
|
|
166
186
|
};
|
|
167
187
|
}
|
|
168
188
|
const getPreviewUrlSchema = z.object({
|
|
@@ -226,11 +246,12 @@ const getPreviewUrl = route().post().schema(getPreviewUrlSchema).outputSchema(ge
|
|
|
226
246
|
}
|
|
227
247
|
});
|
|
228
248
|
/**
|
|
229
|
-
* Default preview functions bundle
|
|
249
|
+
* Default preview functions bundle. The route handlers resolve the token
|
|
250
|
+
* secret from `app.config.secret` at request time.
|
|
230
251
|
* Used by the `adminModule` to register preview RPC functions.
|
|
231
252
|
*/
|
|
232
253
|
const previewFunctions = {
|
|
233
|
-
...createPreviewFunctions(
|
|
254
|
+
...createPreviewFunctions(),
|
|
234
255
|
getPreviewUrl
|
|
235
256
|
};
|
|
236
257
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as questpie113 from "questpie";
|
|
2
2
|
|
|
3
3
|
//#region src/server/modules/admin/routes/reactive.d.ts
|
|
4
4
|
|
|
@@ -13,7 +13,7 @@ import * as questpie133 from "questpie";
|
|
|
13
13
|
* Batch reactive endpoint.
|
|
14
14
|
* Executes multiple reactive handlers in a single request.
|
|
15
15
|
*/
|
|
16
|
-
declare const batchReactive:
|
|
16
|
+
declare const batchReactive: questpie113.JsonRouteDefinition<{
|
|
17
17
|
collection: string;
|
|
18
18
|
type: "collection" | "global";
|
|
19
19
|
requests: {
|
|
@@ -27,12 +27,12 @@ declare const batchReactive: questpie133.JsonRouteDefinition<{
|
|
|
27
27
|
}[];
|
|
28
28
|
formData?: Record<string, unknown> | undefined;
|
|
29
29
|
prevData?: Record<string, unknown> | null | undefined;
|
|
30
|
-
}, any,
|
|
30
|
+
}, any, questpie113.JsonRouteParams>;
|
|
31
31
|
/**
|
|
32
32
|
* Dynamic options endpoint.
|
|
33
33
|
* Fetches options for select/relation fields with search and pagination.
|
|
34
34
|
*/
|
|
35
|
-
declare const fieldOptions:
|
|
35
|
+
declare const fieldOptions: questpie113.JsonRouteDefinition<{
|
|
36
36
|
collection: string;
|
|
37
37
|
type: "collection" | "global";
|
|
38
38
|
field: string;
|
|
@@ -41,12 +41,12 @@ declare const fieldOptions: questpie133.JsonRouteDefinition<{
|
|
|
41
41
|
page: number;
|
|
42
42
|
limit: number;
|
|
43
43
|
siblingData?: Record<string, unknown> | null | undefined;
|
|
44
|
-
}, any,
|
|
44
|
+
}, any, questpie113.JsonRouteParams>;
|
|
45
45
|
/**
|
|
46
46
|
* Reactive functions bundle.
|
|
47
47
|
*/
|
|
48
48
|
declare const reactiveFunctions: {
|
|
49
|
-
readonly batchReactive:
|
|
49
|
+
readonly batchReactive: questpie113.JsonRouteDefinition<{
|
|
50
50
|
collection: string;
|
|
51
51
|
type: "collection" | "global";
|
|
52
52
|
requests: {
|
|
@@ -60,8 +60,8 @@ declare const reactiveFunctions: {
|
|
|
60
60
|
}[];
|
|
61
61
|
formData?: Record<string, unknown> | undefined;
|
|
62
62
|
prevData?: Record<string, unknown> | null | undefined;
|
|
63
|
-
}, any,
|
|
64
|
-
readonly fieldOptions:
|
|
63
|
+
}, any, questpie113.JsonRouteParams>;
|
|
64
|
+
readonly fieldOptions: questpie113.JsonRouteDefinition<{
|
|
65
65
|
collection: string;
|
|
66
66
|
type: "collection" | "global";
|
|
67
67
|
field: string;
|
|
@@ -70,7 +70,7 @@ declare const reactiveFunctions: {
|
|
|
70
70
|
page: number;
|
|
71
71
|
limit: number;
|
|
72
72
|
siblingData?: Record<string, unknown> | null | undefined;
|
|
73
|
-
}, any,
|
|
73
|
+
}, any, questpie113.JsonRouteParams>;
|
|
74
74
|
};
|
|
75
75
|
//#endregion
|
|
76
76
|
export { batchReactive, fieldOptions, reactiveFunctions };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as questpie129 from "questpie";
|
|
2
2
|
|
|
3
3
|
//#region src/server/modules/admin/routes/setup.d.ts
|
|
4
4
|
|
|
@@ -20,7 +20,7 @@ import * as questpie81 from "questpie";
|
|
|
20
20
|
* }
|
|
21
21
|
* ```
|
|
22
22
|
*/
|
|
23
|
-
declare const isSetupRequired:
|
|
23
|
+
declare const isSetupRequired: questpie129.JsonRouteDefinition<Record<string, never>, any, questpie129.JsonRouteParams>;
|
|
24
24
|
/**
|
|
25
25
|
* Create the first admin user in the system.
|
|
26
26
|
* This function only works when no admin users exist (setup mode).
|
|
@@ -43,21 +43,21 @@ declare const isSetupRequired: questpie81.JsonRouteDefinition<Record<string, nev
|
|
|
43
43
|
* }
|
|
44
44
|
* ```
|
|
45
45
|
*/
|
|
46
|
-
declare const createFirstAdmin:
|
|
46
|
+
declare const createFirstAdmin: questpie129.JsonRouteDefinition<{
|
|
47
47
|
email: string;
|
|
48
48
|
password: string;
|
|
49
49
|
name: string;
|
|
50
|
-
}, any,
|
|
50
|
+
}, any, questpie129.JsonRouteParams>;
|
|
51
51
|
/**
|
|
52
52
|
* Bundle of setup-related functions.
|
|
53
53
|
*/
|
|
54
54
|
declare const setupFunctions: {
|
|
55
|
-
readonly isSetupRequired:
|
|
56
|
-
readonly createFirstAdmin:
|
|
55
|
+
readonly isSetupRequired: questpie129.JsonRouteDefinition<Record<string, never>, any, questpie129.JsonRouteParams>;
|
|
56
|
+
readonly createFirstAdmin: questpie129.JsonRouteDefinition<{
|
|
57
57
|
email: string;
|
|
58
58
|
password: string;
|
|
59
59
|
name: string;
|
|
60
|
-
}, any,
|
|
60
|
+
}, any, questpie129.JsonRouteParams>;
|
|
61
61
|
};
|
|
62
62
|
//#endregion
|
|
63
63
|
export { createFirstAdmin, isSetupRequired, setupFunctions };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as questpie137 from "questpie";
|
|
2
2
|
|
|
3
3
|
//#region src/server/modules/admin/routes/widget-data.d.ts
|
|
4
4
|
|
|
@@ -20,13 +20,13 @@ import * as questpie69 from "questpie";
|
|
|
20
20
|
* const data = await client.routes.fetchWidgetData({ widgetId: "my-widget" });
|
|
21
21
|
* ```
|
|
22
22
|
*/
|
|
23
|
-
declare const fetchWidgetData:
|
|
23
|
+
declare const fetchWidgetData: questpie137.JsonRouteDefinition<{
|
|
24
24
|
widgetId: string;
|
|
25
|
-
}, any,
|
|
25
|
+
}, any, questpie137.JsonRouteParams>;
|
|
26
26
|
declare const widgetDataFunctions: {
|
|
27
|
-
readonly fetchWidgetData:
|
|
27
|
+
readonly fetchWidgetData: questpie137.JsonRouteDefinition<{
|
|
28
28
|
widgetId: string;
|
|
29
|
-
}, any,
|
|
29
|
+
}, any, questpie137.JsonRouteParams>;
|
|
30
30
|
};
|
|
31
31
|
//#endregion
|
|
32
32
|
export { fetchWidgetData, widgetDataFunctions };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { FilterOperator, FilterRule, SortConfig, ViewConfiguration } from "../../../../shared/types/saved-views.types.mjs";
|
|
2
|
-
import * as
|
|
3
|
-
import * as
|
|
4
|
-
import * as
|
|
5
|
-
import * as
|
|
2
|
+
import * as questpie_shared16 from "questpie/shared";
|
|
3
|
+
import * as questpie69 from "questpie";
|
|
4
|
+
import * as questpie_src_server_modules_core_fields_email_js1 from "questpie/src/server/modules/core/fields/email.js";
|
|
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";
|
|
7
7
|
import * as drizzle_orm5 from "drizzle-orm";
|
|
8
8
|
|
|
@@ -31,22 +31,22 @@ import * as drizzle_orm5 from "drizzle-orm";
|
|
|
31
31
|
* });
|
|
32
32
|
* ```
|
|
33
33
|
*/
|
|
34
|
-
declare const savedViewsCollection:
|
|
35
|
-
readonly text: typeof
|
|
36
|
-
readonly textarea: typeof
|
|
37
|
-
readonly email: typeof
|
|
38
|
-
readonly url: typeof
|
|
39
|
-
readonly number: typeof
|
|
40
|
-
readonly boolean: typeof
|
|
41
|
-
readonly date: typeof
|
|
42
|
-
readonly datetime: typeof
|
|
43
|
-
readonly time: typeof
|
|
44
|
-
readonly select: typeof
|
|
45
|
-
readonly upload: typeof
|
|
46
|
-
readonly relation: typeof
|
|
47
|
-
readonly object: typeof
|
|
48
|
-
readonly json: typeof
|
|
49
|
-
readonly from: typeof
|
|
34
|
+
declare const savedViewsCollection: questpie69.CollectionBuilder<questpie_shared16.Override<questpie_shared16.Override<questpie69.EmptyCollectionState<"admin_saved_views", undefined, {
|
|
35
|
+
readonly text: typeof questpie69.text;
|
|
36
|
+
readonly textarea: typeof questpie69.textarea;
|
|
37
|
+
readonly email: typeof questpie_src_server_modules_core_fields_email_js1.email;
|
|
38
|
+
readonly url: typeof questpie69.url;
|
|
39
|
+
readonly number: typeof questpie69.number;
|
|
40
|
+
readonly boolean: typeof questpie69.boolean;
|
|
41
|
+
readonly date: typeof questpie69.date;
|
|
42
|
+
readonly datetime: typeof questpie69.datetime;
|
|
43
|
+
readonly time: typeof questpie69.time;
|
|
44
|
+
readonly select: typeof questpie69.select;
|
|
45
|
+
readonly upload: typeof questpie69.upload;
|
|
46
|
+
readonly relation: typeof questpie69.relation;
|
|
47
|
+
readonly object: typeof questpie69.object;
|
|
48
|
+
readonly json: typeof questpie_src_server_modules_core_fields_json_js1.json;
|
|
49
|
+
readonly from: typeof questpie69.from;
|
|
50
50
|
}>, {
|
|
51
51
|
fields: {
|
|
52
52
|
readonly userId: drizzle_orm5.NotNull<drizzle_orm_pg_core22.PgVarcharBuilder<[string, ...string[]]>>;
|
|
@@ -57,35 +57,35 @@ declare const savedViewsCollection: questpie105.CollectionBuilder<questpie_share
|
|
|
57
57
|
};
|
|
58
58
|
localized: readonly string[];
|
|
59
59
|
fieldDefinitions: {
|
|
60
|
-
readonly userId:
|
|
60
|
+
readonly userId: questpie69.FieldWithMethods<Omit<questpie69.TextFieldState, "notNull" | "column"> & {
|
|
61
61
|
notNull: true;
|
|
62
62
|
column: drizzle_orm5.NotNull<drizzle_orm_pg_core22.PgVarcharBuilder<[string, ...string[]]>>;
|
|
63
63
|
} & {
|
|
64
|
-
label:
|
|
65
|
-
},
|
|
66
|
-
readonly collectionName:
|
|
64
|
+
label: questpie_shared16.I18nText;
|
|
65
|
+
}, questpie69.TextFieldMethods>;
|
|
66
|
+
readonly collectionName: questpie69.FieldWithMethods<Omit<questpie69.TextFieldState, "notNull" | "column"> & {
|
|
67
67
|
notNull: true;
|
|
68
68
|
column: drizzle_orm5.NotNull<drizzle_orm_pg_core22.PgVarcharBuilder<[string, ...string[]]>>;
|
|
69
69
|
} & {
|
|
70
|
-
label:
|
|
71
|
-
},
|
|
72
|
-
readonly name:
|
|
70
|
+
label: questpie_shared16.I18nText;
|
|
71
|
+
}, questpie69.TextFieldMethods>;
|
|
72
|
+
readonly name: questpie69.FieldWithMethods<Omit<questpie69.TextFieldState, "notNull" | "column"> & {
|
|
73
73
|
notNull: true;
|
|
74
74
|
column: drizzle_orm5.NotNull<drizzle_orm_pg_core22.PgVarcharBuilder<[string, ...string[]]>>;
|
|
75
75
|
} & {
|
|
76
|
-
label:
|
|
77
|
-
},
|
|
78
|
-
readonly configuration:
|
|
76
|
+
label: questpie_shared16.I18nText;
|
|
77
|
+
}, questpie69.TextFieldMethods>;
|
|
78
|
+
readonly configuration: questpie69.Field<Omit<questpie69.JsonFieldState, "notNull" | "column"> & {
|
|
79
79
|
notNull: true;
|
|
80
80
|
column: drizzle_orm5.NotNull<drizzle_orm_pg_core22.PgJsonbBuilder>;
|
|
81
81
|
} & {
|
|
82
|
-
label:
|
|
82
|
+
label: questpie_shared16.I18nText;
|
|
83
83
|
}>;
|
|
84
|
-
readonly isDefault:
|
|
84
|
+
readonly isDefault: questpie69.Field<Omit<questpie69.BooleanFieldState, "column" | "hasDefault"> & {
|
|
85
85
|
hasDefault: true;
|
|
86
86
|
column: drizzle_orm5.HasDefault<drizzle_orm_pg_core22.PgBooleanBuilder>;
|
|
87
87
|
} & {
|
|
88
|
-
label:
|
|
88
|
+
label: questpie_shared16.I18nText;
|
|
89
89
|
}>;
|
|
90
90
|
};
|
|
91
91
|
}>, {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { auditLogCollection } from "../collections/audit-log.mjs";
|
|
2
2
|
import { auditCleanupJob } from "../jobs/audit-cleanup.mjs";
|
|
3
|
-
import * as
|
|
3
|
+
import * as questpie16 from "questpie";
|
|
4
4
|
|
|
5
5
|
//#region src/server/modules/audit/.generated/module.d.ts
|
|
6
6
|
interface AuditCollections {
|
|
@@ -43,13 +43,13 @@ declare const _module: {
|
|
|
43
43
|
app: {
|
|
44
44
|
hooks: {
|
|
45
45
|
collections: {
|
|
46
|
-
afterChange: (ctx:
|
|
47
|
-
afterDelete: (ctx:
|
|
48
|
-
afterTransition: (ctx:
|
|
46
|
+
afterChange: (ctx: questpie16.GlobalCollectionHookContext) => Promise<void>;
|
|
47
|
+
afterDelete: (ctx: questpie16.GlobalCollectionHookContext) => Promise<void>;
|
|
48
|
+
afterTransition: (ctx: questpie16.GlobalCollectionTransitionHookContext) => Promise<void>;
|
|
49
49
|
};
|
|
50
50
|
globals: {
|
|
51
|
-
afterChange: (ctx:
|
|
52
|
-
afterTransition: (ctx:
|
|
51
|
+
afterChange: (ctx: questpie16.GlobalGlobalHookContext) => Promise<void>;
|
|
52
|
+
afterTransition: (ctx: questpie16.GlobalGlobalTransitionHookContext) => Promise<void>;
|
|
53
53
|
};
|
|
54
54
|
};
|
|
55
55
|
};
|