@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,5 +1,5 @@
|
|
|
1
1
|
import * as questpie_shared0 from "questpie/shared";
|
|
2
|
-
import * as
|
|
2
|
+
import * as questpie21 from "questpie";
|
|
3
3
|
import * as questpie_src_server_modules_core_fields_email_js0 from "questpie/src/server/modules/core/fields/email.js";
|
|
4
4
|
import * as questpie_src_server_modules_core_fields_json_js0 from "questpie/src/server/modules/core/fields/json.js";
|
|
5
5
|
import * as drizzle_orm_pg_core0 from "drizzle-orm/pg-core";
|
|
@@ -19,22 +19,22 @@ import * as questpie_src_server_fields_operators_builtin_js0 from "questpie/src/
|
|
|
19
19
|
* - update: disallowed
|
|
20
20
|
* - read: allowed (for admin UI display)
|
|
21
21
|
*/
|
|
22
|
-
declare const auditLogCollection:
|
|
23
|
-
readonly text: typeof
|
|
24
|
-
readonly textarea: typeof
|
|
22
|
+
declare const auditLogCollection: questpie21.CollectionBuilder<questpie_shared0.Override<questpie_shared0.Override<questpie_shared0.Override<questpie_shared0.Override<questpie_shared0.Override<questpie_shared0.Override<questpie21.EmptyCollectionState<"admin_audit_log", undefined, {
|
|
23
|
+
readonly text: typeof questpie21.text;
|
|
24
|
+
readonly textarea: typeof questpie21.textarea;
|
|
25
25
|
readonly email: typeof questpie_src_server_modules_core_fields_email_js0.email;
|
|
26
|
-
readonly url: typeof
|
|
27
|
-
readonly number: typeof
|
|
28
|
-
readonly boolean: typeof
|
|
29
|
-
readonly date: typeof
|
|
30
|
-
readonly datetime: typeof
|
|
31
|
-
readonly time: typeof
|
|
32
|
-
readonly select: typeof
|
|
33
|
-
readonly upload: typeof
|
|
34
|
-
readonly relation: typeof
|
|
35
|
-
readonly object: typeof
|
|
26
|
+
readonly url: typeof questpie21.url;
|
|
27
|
+
readonly number: typeof questpie21.number;
|
|
28
|
+
readonly boolean: typeof questpie21.boolean;
|
|
29
|
+
readonly date: typeof questpie21.date;
|
|
30
|
+
readonly datetime: typeof questpie21.datetime;
|
|
31
|
+
readonly time: typeof questpie21.time;
|
|
32
|
+
readonly select: typeof questpie21.select;
|
|
33
|
+
readonly upload: typeof questpie21.upload;
|
|
34
|
+
readonly relation: typeof questpie21.relation;
|
|
35
|
+
readonly object: typeof questpie21.object;
|
|
36
36
|
readonly json: typeof questpie_src_server_modules_core_fields_json_js0.json;
|
|
37
|
-
readonly from: typeof
|
|
37
|
+
readonly from: typeof questpie21.from;
|
|
38
38
|
}>, {
|
|
39
39
|
fields: {
|
|
40
40
|
readonly action: drizzle_orm0.NotNull<drizzle_orm_pg_core0.PgVarcharBuilder<[string, ...string[]]>>;
|
|
@@ -52,98 +52,98 @@ declare const auditLogCollection: questpie16.CollectionBuilder<questpie_shared0.
|
|
|
52
52
|
localized: readonly string[];
|
|
53
53
|
fieldDefinitions: {
|
|
54
54
|
/** Action performed: create, update, delete, transition, custom */
|
|
55
|
-
readonly action:
|
|
55
|
+
readonly action: questpie21.FieldWithMethods<Omit<questpie21.TextFieldState, "notNull" | "column"> & {
|
|
56
56
|
notNull: true;
|
|
57
57
|
column: drizzle_orm0.NotNull<drizzle_orm_pg_core0.PgVarcharBuilder<[string, ...string[]]>>;
|
|
58
58
|
} & {
|
|
59
59
|
label: questpie_shared0.I18nText;
|
|
60
|
-
},
|
|
60
|
+
}, questpie21.TextFieldMethods>;
|
|
61
61
|
/** Resource type: collection, global, auth, system, custom */
|
|
62
|
-
readonly resourceType:
|
|
62
|
+
readonly resourceType: questpie21.FieldWithMethods<Omit<questpie21.TextFieldState, "notNull" | "column"> & {
|
|
63
63
|
notNull: true;
|
|
64
64
|
column: drizzle_orm0.NotNull<drizzle_orm_pg_core0.PgVarcharBuilder<[string, ...string[]]>>;
|
|
65
65
|
} & {
|
|
66
66
|
label: questpie_shared0.I18nText;
|
|
67
|
-
},
|
|
67
|
+
}, questpie21.TextFieldMethods>;
|
|
68
68
|
/** Resource slug (collection/global name) */
|
|
69
|
-
readonly resource:
|
|
69
|
+
readonly resource: questpie21.FieldWithMethods<Omit<questpie21.TextFieldState, "notNull" | "column"> & {
|
|
70
70
|
notNull: true;
|
|
71
71
|
column: drizzle_orm0.NotNull<drizzle_orm_pg_core0.PgVarcharBuilder<[string, ...string[]]>>;
|
|
72
72
|
} & {
|
|
73
73
|
label: questpie_shared0.I18nText;
|
|
74
|
-
},
|
|
74
|
+
}, questpie21.TextFieldMethods>;
|
|
75
75
|
/** ID of the specific record (null for globals) */
|
|
76
|
-
readonly resourceId:
|
|
76
|
+
readonly resourceId: questpie21.FieldWithMethods<questpie21.DefaultFieldState & {
|
|
77
77
|
type: "text";
|
|
78
78
|
data: string;
|
|
79
79
|
column: drizzle_orm_pg_core0.PgVarcharBuilder<[string, ...string[]]>;
|
|
80
80
|
operators: typeof questpie_src_server_fields_operators_builtin_js0.stringOps;
|
|
81
81
|
} & {
|
|
82
82
|
label: questpie_shared0.I18nText;
|
|
83
|
-
},
|
|
83
|
+
}, questpie21.TextFieldMethods>;
|
|
84
84
|
/** Denormalized display label for the affected record */
|
|
85
|
-
readonly resourceLabel:
|
|
85
|
+
readonly resourceLabel: questpie21.FieldWithMethods<questpie21.DefaultFieldState & {
|
|
86
86
|
type: "text";
|
|
87
87
|
data: string;
|
|
88
88
|
column: drizzle_orm_pg_core0.PgVarcharBuilder<[string, ...string[]]>;
|
|
89
89
|
operators: typeof questpie_src_server_fields_operators_builtin_js0.stringOps;
|
|
90
90
|
} & {
|
|
91
91
|
label: questpie_shared0.I18nText;
|
|
92
|
-
},
|
|
92
|
+
}, questpie21.TextFieldMethods>;
|
|
93
93
|
/** User who performed the action */
|
|
94
|
-
readonly userId:
|
|
94
|
+
readonly userId: questpie21.FieldWithMethods<questpie21.DefaultFieldState & {
|
|
95
95
|
type: "text";
|
|
96
96
|
data: string;
|
|
97
97
|
column: drizzle_orm_pg_core0.PgVarcharBuilder<[string, ...string[]]>;
|
|
98
98
|
operators: typeof questpie_src_server_fields_operators_builtin_js0.stringOps;
|
|
99
99
|
} & {
|
|
100
100
|
label: questpie_shared0.I18nText;
|
|
101
|
-
},
|
|
101
|
+
}, questpie21.TextFieldMethods>;
|
|
102
102
|
/** Denormalized user display name */
|
|
103
|
-
readonly userName:
|
|
103
|
+
readonly userName: questpie21.FieldWithMethods<questpie21.DefaultFieldState & {
|
|
104
104
|
type: "text";
|
|
105
105
|
data: string;
|
|
106
106
|
column: drizzle_orm_pg_core0.PgVarcharBuilder<[string, ...string[]]>;
|
|
107
107
|
operators: typeof questpie_src_server_fields_operators_builtin_js0.stringOps;
|
|
108
108
|
} & {
|
|
109
109
|
label: questpie_shared0.I18nText;
|
|
110
|
-
},
|
|
110
|
+
}, questpie21.TextFieldMethods>;
|
|
111
111
|
/** Locale context of the operation */
|
|
112
|
-
readonly locale:
|
|
112
|
+
readonly locale: questpie21.FieldWithMethods<questpie21.DefaultFieldState & {
|
|
113
113
|
type: "text";
|
|
114
114
|
data: string;
|
|
115
115
|
column: drizzle_orm_pg_core0.PgVarcharBuilder<[string, ...string[]]>;
|
|
116
116
|
operators: typeof questpie_src_server_fields_operators_builtin_js0.stringOps;
|
|
117
117
|
} & {
|
|
118
118
|
label: questpie_shared0.I18nText;
|
|
119
|
-
},
|
|
119
|
+
}, questpie21.TextFieldMethods>;
|
|
120
120
|
/** Field-level diffs: { field: { from, to } } or null */
|
|
121
|
-
readonly changes:
|
|
121
|
+
readonly changes: questpie21.Field<questpie21.DefaultFieldState & {
|
|
122
122
|
type: "json";
|
|
123
|
-
data:
|
|
123
|
+
data: questpie21.JsonValue;
|
|
124
124
|
column: drizzle_orm_pg_core0.PgJsonbBuilder;
|
|
125
125
|
operators: typeof questpie_src_server_fields_operators_builtin_js0.basicOps;
|
|
126
126
|
} & {
|
|
127
127
|
label: questpie_shared0.I18nText;
|
|
128
128
|
}>;
|
|
129
129
|
/** Extra context metadata */
|
|
130
|
-
readonly metadata:
|
|
130
|
+
readonly metadata: questpie21.Field<questpie21.DefaultFieldState & {
|
|
131
131
|
type: "json";
|
|
132
|
-
data:
|
|
132
|
+
data: questpie21.JsonValue;
|
|
133
133
|
column: drizzle_orm_pg_core0.PgJsonbBuilder;
|
|
134
134
|
operators: typeof questpie_src_server_fields_operators_builtin_js0.basicOps;
|
|
135
135
|
} & {
|
|
136
136
|
label: questpie_shared0.I18nText;
|
|
137
137
|
}>;
|
|
138
138
|
/** Human-readable title: "User Action ResourceType 'ResourceLabel'" */
|
|
139
|
-
readonly title:
|
|
139
|
+
readonly title: questpie21.FieldWithMethods<questpie21.DefaultFieldState & {
|
|
140
140
|
type: "text";
|
|
141
141
|
data: string;
|
|
142
142
|
column: drizzle_orm_pg_core0.PgVarcharBuilder<[string, ...string[]]>;
|
|
143
143
|
operators: typeof questpie_src_server_fields_operators_builtin_js0.stringOps;
|
|
144
144
|
} & {
|
|
145
145
|
label: questpie_shared0.I18nText;
|
|
146
|
-
},
|
|
146
|
+
}, questpie21.TextFieldMethods>;
|
|
147
147
|
};
|
|
148
148
|
}>, {
|
|
149
149
|
options: {
|
|
@@ -153,6 +153,8 @@ declare const auditLogCollection: questpie16.CollectionBuilder<questpie_shared0.
|
|
|
153
153
|
indexes: drizzle_orm_pg_core0.IndexBuilder[];
|
|
154
154
|
}>, {
|
|
155
155
|
access: Record<string, any>;
|
|
156
|
+
}>, {
|
|
157
|
+
hooks: Record<string, any>;
|
|
156
158
|
}> & Record<"admin", {
|
|
157
159
|
label: {
|
|
158
160
|
key: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { localizeAuditTitle } from "../config/localize-title.mjs";
|
|
2
|
+
import { collection, tryGetContext } from "questpie";
|
|
2
3
|
import { index } from "questpie/drizzle-pg-core";
|
|
3
4
|
|
|
4
5
|
//#region src/server/modules/audit/collections/audit-log.ts
|
|
@@ -41,7 +42,11 @@ const auditLogCollection = collection(AUDIT_LOG_COLLECTION).fields(({ f }) => ({
|
|
|
41
42
|
update: false,
|
|
42
43
|
delete: false,
|
|
43
44
|
read: true
|
|
44
|
-
}).
|
|
45
|
+
}).hooks({ afterRead: ({ data, locale }) => {
|
|
46
|
+
if (!data) return;
|
|
47
|
+
const localized = localizeAuditTitle(data, locale, tryGetContext()?.app);
|
|
48
|
+
if (localized) data.title = localized;
|
|
49
|
+
} }).set("admin", {
|
|
45
50
|
label: { key: "audit.collection.label" },
|
|
46
51
|
icon: {
|
|
47
52
|
type: "icon",
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { getAdminMessagesForLocale } from "../../../i18n/index.mjs";
|
|
2
|
+
import { isI18nTranslationKey, resolveI18nText } from "questpie/shared";
|
|
3
|
+
|
|
4
|
+
//#region src/server/modules/audit/config/localize-title.ts
|
|
5
|
+
function lookupMessage(messages, key) {
|
|
6
|
+
const value = messages[key];
|
|
7
|
+
if (typeof value === "string") return value;
|
|
8
|
+
if (value && typeof value === "object") {
|
|
9
|
+
const plural = value.other;
|
|
10
|
+
if (typeof plural === "string") return plural;
|
|
11
|
+
}
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
function makeTranslator(messages) {
|
|
15
|
+
return (key) => lookupMessage(messages, key) ?? key;
|
|
16
|
+
}
|
|
17
|
+
function getResourceLabel(app, resourceType, resource) {
|
|
18
|
+
if (!app) return null;
|
|
19
|
+
if (resourceType === "collection") {
|
|
20
|
+
const config = app.getCollectionConfig?.(resource);
|
|
21
|
+
return config?.state?.admin?.label ?? config?.state?.label ?? null;
|
|
22
|
+
}
|
|
23
|
+
if (resourceType === "global") {
|
|
24
|
+
const config = app.getGlobals?.()?.[resource];
|
|
25
|
+
return config?.state?.admin?.label ?? config?.state?.label ?? null;
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
function resolveLabel(label, locale, t) {
|
|
30
|
+
if (label == null) return null;
|
|
31
|
+
if (isI18nTranslationKey(label)) {
|
|
32
|
+
const resolved = t(label.key);
|
|
33
|
+
return resolved === label.key ? label.fallback ?? null : resolved;
|
|
34
|
+
}
|
|
35
|
+
return resolveI18nText(label, locale, t);
|
|
36
|
+
}
|
|
37
|
+
function interpolate(template, values) {
|
|
38
|
+
return template.replace(/\{\{\s*(\w+)\s*\}\}/g, (_m, k) => values[k] ?? `{{${k}}}`);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Recompute the audit log title in the viewer's locale.
|
|
42
|
+
* Returns null when no locale is provided so the caller can keep the stored value.
|
|
43
|
+
*/
|
|
44
|
+
function localizeAuditTitle(data, locale, app) {
|
|
45
|
+
if (!locale) return null;
|
|
46
|
+
const messages = getAdminMessagesForLocale(locale);
|
|
47
|
+
const t = makeTranslator(messages);
|
|
48
|
+
const action = String(data.action ?? "");
|
|
49
|
+
const resourceType = String(data.resourceType ?? "");
|
|
50
|
+
const resource = String(data.resource ?? "");
|
|
51
|
+
const userName = String(data.userName ?? "");
|
|
52
|
+
const actionText = lookupMessage(messages, `audit.action.${action}`) ?? action;
|
|
53
|
+
const resourceTypeText = lookupMessage(messages, `audit.resourceType.${resourceType}`) ?? resourceType;
|
|
54
|
+
const resourceName = resolveLabel(getResourceLabel(app, resourceType, resource), locale, t) ?? resource;
|
|
55
|
+
const rawLabel = typeof data.resourceLabel === "string" && data.resourceLabel.length > 0 ? data.resourceLabel : null;
|
|
56
|
+
const unnamed = lookupMessage(messages, "audit.unnamed") ?? "(unnamed)";
|
|
57
|
+
const resourceLabel = rawLabel ? `'${rawLabel}'` : unnamed;
|
|
58
|
+
return interpolate(lookupMessage(messages, "audit.title.template") ?? "{{userName}} {{action}} {{resourceType}} {{resourceLabel}}", {
|
|
59
|
+
userName,
|
|
60
|
+
action: actionText,
|
|
61
|
+
resourceType: `${resourceTypeText} ${resourceName}`,
|
|
62
|
+
resourceLabel
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
//#endregion
|
|
67
|
+
export { localizeAuditTitle };
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import { auditLogCollection } from "./collections/audit-log.mjs";
|
|
2
|
-
import { AuditModule, _module } from "./.generated/module.mjs";
|
|
2
|
+
import { AuditModule, _module } from "./.generated/module.mjs";
|
|
3
|
+
import { AuditActorType, AuditContext, LogAuditEntryOptions, logAuditEntry } from "./log-audit-entry.mjs";
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
//#region src/server/modules/audit/log-audit-entry.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Options for a custom audit log entry.
|
|
4
|
+
*/
|
|
5
|
+
type AuditActorType = "anonymous" | "system" | "user" | (string & {});
|
|
6
|
+
interface LogAuditEntryOptions {
|
|
7
|
+
/** Action performed (e.g., "create", "bulk-email", "archive", "migrate"). */
|
|
8
|
+
action: string;
|
|
9
|
+
/**
|
|
10
|
+
* Category of the affected resource.
|
|
11
|
+
* Built-in: "collection" | "global"
|
|
12
|
+
* Custom: "system" | "job" | "webhook" | any string
|
|
13
|
+
*/
|
|
14
|
+
resourceType: string;
|
|
15
|
+
/** Resource identifier (e.g., collection slug, job name). */
|
|
16
|
+
resource: string;
|
|
17
|
+
/** Optional ID of a specific record. */
|
|
18
|
+
resourceId?: string | null;
|
|
19
|
+
/** Display label for the affected resource (e.g., record title, job description). */
|
|
20
|
+
resourceLabel?: string | null;
|
|
21
|
+
/** Override actor user name (auto-resolved from session when omitted). */
|
|
22
|
+
userName?: string;
|
|
23
|
+
/** Override actor user ID (auto-resolved from session when omitted). */
|
|
24
|
+
userId?: string | null;
|
|
25
|
+
/** Override actor category stored in metadata. */
|
|
26
|
+
actorType?: AuditActorType;
|
|
27
|
+
/** Locale context of the operation. */
|
|
28
|
+
locale?: string | null;
|
|
29
|
+
/** Field-level changes, or arbitrary structured data. */
|
|
30
|
+
changes?: Record<string, unknown> | null;
|
|
31
|
+
/** Extra metadata (e.g., job payload, webhook source). */
|
|
32
|
+
metadata?: Record<string, unknown> | null;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Audit context — pass the hook/job context directly.
|
|
36
|
+
* Needs `collections` (or `app.collections`) and optionally `session`, `db`.
|
|
37
|
+
*/
|
|
38
|
+
interface AuditContext {
|
|
39
|
+
collections?: Record<string, any>;
|
|
40
|
+
app?: {
|
|
41
|
+
collections?: Record<string, any>;
|
|
42
|
+
getCollectionConfig?: (slug: string) => any;
|
|
43
|
+
getGlobals?: () => Record<string, any>;
|
|
44
|
+
};
|
|
45
|
+
session?: {
|
|
46
|
+
user?: Record<string, unknown> | null;
|
|
47
|
+
} | null;
|
|
48
|
+
accessMode?: string;
|
|
49
|
+
db?: unknown;
|
|
50
|
+
logger?: {
|
|
51
|
+
error?: (...args: any[]) => void;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Write a custom audit log entry.
|
|
56
|
+
*
|
|
57
|
+
* Use this in jobs, custom actions, webhooks, or anywhere you want
|
|
58
|
+
* to record a meaningful event in the audit trail.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* import { logAuditEntry } from "@questpie/admin/server";
|
|
63
|
+
*
|
|
64
|
+
* // Inside a job handler:
|
|
65
|
+
* await logAuditEntry(ctx, {
|
|
66
|
+
* action: "bulk-email",
|
|
67
|
+
* resourceType: "system",
|
|
68
|
+
* resource: "newsletter",
|
|
69
|
+
* resourceLabel: "Q1 Campaign",
|
|
70
|
+
* metadata: { sentCount: 1234, jobId: ctx.id },
|
|
71
|
+
* });
|
|
72
|
+
*
|
|
73
|
+
* // Inside a collection hook with session:
|
|
74
|
+
* await logAuditEntry(ctx, {
|
|
75
|
+
* action: "export",
|
|
76
|
+
* resourceType: "collection",
|
|
77
|
+
* resource: "orders",
|
|
78
|
+
* resourceLabel: "Monthly export",
|
|
79
|
+
* changes: { format: { from: null, to: "csv" } },
|
|
80
|
+
* });
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
declare function logAuditEntry(ctx: AuditContext, options: LogAuditEntryOptions): Promise<void>;
|
|
84
|
+
//#endregion
|
|
85
|
+
export { AuditActorType, AuditContext, LogAuditEntryOptions, logAuditEntry };
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { AUDIT_LOG_COLLECTION } from "./collections/audit-log.mjs";
|
|
2
|
+
import { tryGetContext } from "questpie";
|
|
3
|
+
|
|
4
|
+
//#region src/server/modules/audit/log-audit-entry.ts
|
|
5
|
+
function resolveCollections(ctx) {
|
|
6
|
+
return ctx.collections ?? ctx.app?.collections ?? null;
|
|
7
|
+
}
|
|
8
|
+
function resolveActor(ctx) {
|
|
9
|
+
const user = ctx.session?.user;
|
|
10
|
+
const userId = user?.id != null ? String(user.id) : null;
|
|
11
|
+
for (const candidate of [
|
|
12
|
+
user?.name,
|
|
13
|
+
user?.email,
|
|
14
|
+
userId
|
|
15
|
+
]) if (typeof candidate === "string" && candidate.trim().length > 0) return {
|
|
16
|
+
actorType: "user",
|
|
17
|
+
userId,
|
|
18
|
+
userName: candidate.trim()
|
|
19
|
+
};
|
|
20
|
+
if (ctx.accessMode === "system") return {
|
|
21
|
+
actorType: "system",
|
|
22
|
+
userId: "system",
|
|
23
|
+
userName: "System"
|
|
24
|
+
};
|
|
25
|
+
return {
|
|
26
|
+
actorType: "anonymous",
|
|
27
|
+
userId: null,
|
|
28
|
+
userName: "Anonymous"
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function getResourceTypeLabel(ctx, resourceType, resource) {
|
|
32
|
+
const stored = tryGetContext();
|
|
33
|
+
const app = ctx.app ?? stored?.app;
|
|
34
|
+
if (!app) return resource;
|
|
35
|
+
if (resourceType === "collection") {
|
|
36
|
+
const config = app.getCollectionConfig?.(resource);
|
|
37
|
+
const label = config?.state?.admin?.label ?? config?.state?.label;
|
|
38
|
+
if (typeof label === "string") return label;
|
|
39
|
+
return resource;
|
|
40
|
+
}
|
|
41
|
+
if (resourceType === "global") {
|
|
42
|
+
const config = app.getGlobals?.()?.[resource];
|
|
43
|
+
const label = config?.state?.admin?.label ?? config?.state?.label;
|
|
44
|
+
if (typeof label === "string") return label;
|
|
45
|
+
return resource;
|
|
46
|
+
}
|
|
47
|
+
return resource;
|
|
48
|
+
}
|
|
49
|
+
function resolveActorType(actor, options, userId) {
|
|
50
|
+
if (options.actorType) return options.actorType;
|
|
51
|
+
if (options.userId !== void 0 || options.userName !== void 0) return userId && userId !== "system" ? "user" : "system";
|
|
52
|
+
return actor.actorType;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Write a custom audit log entry.
|
|
56
|
+
*
|
|
57
|
+
* Use this in jobs, custom actions, webhooks, or anywhere you want
|
|
58
|
+
* to record a meaningful event in the audit trail.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* import { logAuditEntry } from "@questpie/admin/server";
|
|
63
|
+
*
|
|
64
|
+
* // Inside a job handler:
|
|
65
|
+
* await logAuditEntry(ctx, {
|
|
66
|
+
* action: "bulk-email",
|
|
67
|
+
* resourceType: "system",
|
|
68
|
+
* resource: "newsletter",
|
|
69
|
+
* resourceLabel: "Q1 Campaign",
|
|
70
|
+
* metadata: { sentCount: 1234, jobId: ctx.id },
|
|
71
|
+
* });
|
|
72
|
+
*
|
|
73
|
+
* // Inside a collection hook with session:
|
|
74
|
+
* await logAuditEntry(ctx, {
|
|
75
|
+
* action: "export",
|
|
76
|
+
* resourceType: "collection",
|
|
77
|
+
* resource: "orders",
|
|
78
|
+
* resourceLabel: "Monthly export",
|
|
79
|
+
* changes: { format: { from: null, to: "csv" } },
|
|
80
|
+
* });
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
async function logAuditEntry(ctx, options) {
|
|
84
|
+
const collections = resolveCollections(ctx);
|
|
85
|
+
if (!collections?.[AUDIT_LOG_COLLECTION]) {
|
|
86
|
+
ctx.logger?.error?.("[Audit] Cannot write audit entry — audit log collection not available");
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const actor = resolveActor(ctx);
|
|
90
|
+
const userName = options.userName ?? actor.userName;
|
|
91
|
+
const userId = options.userId !== void 0 ? options.userId : actor.userId;
|
|
92
|
+
const actorType = resolveActorType(actor, options, userId);
|
|
93
|
+
const resourceTypeLabel = getResourceTypeLabel(ctx, options.resourceType, options.resource);
|
|
94
|
+
const resourceLabel = options.resourceLabel ?? null;
|
|
95
|
+
const label = resourceLabel || "(unnamed)";
|
|
96
|
+
const title = `${userName} ${{
|
|
97
|
+
create: "created",
|
|
98
|
+
update: "updated",
|
|
99
|
+
delete: "deleted",
|
|
100
|
+
transition: "changed status of"
|
|
101
|
+
}[options.action] || options.action} ${resourceTypeLabel} '${label}'`;
|
|
102
|
+
await collections[AUDIT_LOG_COLLECTION].create({
|
|
103
|
+
action: options.action,
|
|
104
|
+
resourceType: options.resourceType,
|
|
105
|
+
resource: options.resource,
|
|
106
|
+
resourceId: options.resourceId ?? null,
|
|
107
|
+
resourceLabel,
|
|
108
|
+
userId,
|
|
109
|
+
userName,
|
|
110
|
+
locale: options.locale ?? null,
|
|
111
|
+
changes: options.changes ?? null,
|
|
112
|
+
metadata: {
|
|
113
|
+
actorType,
|
|
114
|
+
accessMode: ctx.accessMode ?? "system",
|
|
115
|
+
...options.metadata ?? {}
|
|
116
|
+
},
|
|
117
|
+
title
|
|
118
|
+
}, {
|
|
119
|
+
accessMode: "system",
|
|
120
|
+
db: ctx.db
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
//#endregion
|
|
125
|
+
export { logAuditEntry };
|
package/dist/server/plugin.mjs
CHANGED
|
@@ -267,7 +267,7 @@ function adminPlugin() {
|
|
|
267
267
|
view: {
|
|
268
268
|
dir: "views",
|
|
269
269
|
description: "Server-side view definition",
|
|
270
|
-
template: ({ kebab, camel }) => `import { view } from "@questpie/admin/server";\n\nexport const ${camel}View = view("${kebab}",
|
|
270
|
+
template: ({ kebab, camel }) => `import { view } from "@questpie/admin/server";\n\nexport const ${camel}View = view("${kebab}", {\n\tkind: "list",\n});\n`
|
|
271
271
|
},
|
|
272
272
|
component: {
|
|
273
273
|
dir: "components",
|
|
@@ -362,19 +362,19 @@ function adminPlugin() {
|
|
|
362
362
|
dir: "views",
|
|
363
363
|
extension: ".tsx",
|
|
364
364
|
description: "Client-side view component",
|
|
365
|
-
template: ({ kebab, pascal }) => `import {
|
|
365
|
+
template: ({ kebab, pascal }) => `import { type CollectionListViewProps, view } from "@questpie/admin/client";\n\nfunction ${pascal}View(_props: CollectionListViewProps) {\n\treturn (\n\t\t<div>\n\t\t\t<h2>${pascal} View</h2>\n\t\t\t{/* TODO: implement view */}\n\t\t</div>\n\t);\n}\n\nexport default view("${kebab}", {\n\tkind: "list",\n\tcomponent: ${pascal}View,\n});\n`
|
|
366
366
|
},
|
|
367
367
|
field: {
|
|
368
368
|
dir: "fields",
|
|
369
369
|
extension: ".tsx",
|
|
370
370
|
description: "Client-side field component",
|
|
371
|
-
template: ({ kebab, pascal }) => `import { field } from "@questpie/admin";\n\
|
|
371
|
+
template: ({ kebab, pascal }) => `import { type BaseFieldProps, field } from "@questpie/admin/client";\n\nfunction ${pascal}Field({ label, value, onChange, onBlur }: BaseFieldProps) {\n\treturn (\n\t\t<label>\n\t\t\t<span>{label ?? "${pascal}"}</span>\n\t\t\t<input\n\t\t\t\tvalue={typeof value === "string" ? value : ""}\n\t\t\t\tonChange={(event) => onChange?.(event.target.value)}\n\t\t\t\tonBlur={onBlur}\n\t\t\t/>\n\t\t</label>\n\t);\n}\n\nexport default field("${kebab}", {\n\tcomponent: ${pascal}Field,\n});\n`
|
|
372
372
|
},
|
|
373
373
|
widget: {
|
|
374
374
|
dir: "widgets",
|
|
375
375
|
extension: ".tsx",
|
|
376
376
|
description: "Client-side dashboard widget",
|
|
377
|
-
template: ({ kebab, pascal }) => `import {
|
|
377
|
+
template: ({ kebab, pascal }) => `import { type WidgetComponentProps, widget } from "@questpie/admin/client";\n\nfunction ${pascal}Widget(_props: WidgetComponentProps) {\n\treturn (\n\t\t<div>\n\t\t\t<h3>${pascal} Widget</h3>\n\t\t\t{/* TODO: implement widget */}\n\t\t</div>\n\t);\n}\n\nexport default widget("${kebab}", {\n\tcomponent: ${pascal}Widget,\n});\n`
|
|
378
378
|
}
|
|
379
379
|
},
|
|
380
380
|
generate: (ctx) => generateAdminClientTemplate(ctx)
|
package/dist/server.d.mts
CHANGED
|
@@ -15,10 +15,8 @@ import { BlocksPrefetchContext, createBlocksPrefetchHook, processBlocksDocument,
|
|
|
15
15
|
import "./server/block/index.mjs";
|
|
16
16
|
import { adminPlugin } from "./server/plugin.mjs";
|
|
17
17
|
import { AuthSession, GetAdminSessionOptions, RequireAdminAuthOptions, getAdminSession, isAdminUser, requireAdminAuth } from "./server/modules/admin/auth-helpers.mjs";
|
|
18
|
-
import "./server/auth-helpers.mjs";
|
|
19
18
|
import { NextAuthMiddlewareOptions, createNextAuthMiddleware, getNextAdminSession } from "./server/adapters/nextjs.mjs";
|
|
20
19
|
import { BeforeLoadContext, TanStackAuthGuardOptions, createTanStackAuthGuard, createTanStackSessionLoader } from "./server/adapters/tanstack.mjs";
|
|
21
|
-
import "./server/adapters/index.mjs";
|
|
22
20
|
import { ExecuteActionRequest, ExecuteActionResponse, actionFunctions, executeAction, executeActionFn, getActionsConfig, getActionsConfigFn } from "./server/modules/admin/routes/execute-action.mjs";
|
|
23
21
|
import { PreviewTokenPayload, createPreviewFunctions, createPreviewTokenVerifier, verifyPreviewTokenDirect } from "./server/modules/admin/routes/preview.mjs";
|
|
24
22
|
import { batchReactive, fieldOptions, reactiveFunctions } from "./server/modules/admin/routes/reactive.mjs";
|
|
@@ -29,7 +27,8 @@ import { savedViewsCollection } from "./server/modules/admin-preferences/collect
|
|
|
29
27
|
import { AdminModule, adminModule, adminRoutes } from "./server/modules/admin/index.mjs";
|
|
30
28
|
import { auditLogCollection } from "./server/modules/audit/collections/audit-log.mjs";
|
|
31
29
|
import { AuditModule, _module } from "./server/modules/audit/.generated/module.mjs";
|
|
30
|
+
import { AuditActorType, AuditContext, LogAuditEntryOptions, logAuditEntry } from "./server/modules/audit/log-audit-entry.mjs";
|
|
32
31
|
import "./server/modules/audit/index.mjs";
|
|
33
32
|
import { createActionCallbackProxy, createActionProxy, createComponentCallbackProxy, createComponentProxy, createDashboardCallbackContext, createDashboardContributionProxy, createFieldProxy, createSidebarCallbackContext, createSidebarContributionProxy, createViewCallbackProxy, createViewProxy, resolveDashboardCallback, resolveSidebarCallback } from "./server/proxy-factories.mjs";
|
|
34
33
|
import { component, editView, filterViewsByKind, listView, view } from "./server/registry-helpers.mjs";
|
|
35
|
-
export { type ActionReference, type ActionsConfigContext, type AdminBlockConfig, type AdminCollectionConfig, type AdminConfigContext, type AdminConfigInput, type AdminGlobalConfig, type AdminLocaleConfig, type AdminModule, type AnyBlockBuilder, type AnyBlockDefinition, type AuditModule, type AuthSession, BeforeLoadContext, BlockBuilder, type BlockBuilderState, type BlockCategoryConfig, type BlockDefinition, type BlockNode, type BlockPrefetchContext, type BlockPrefetchFn, type BlockPrefetchWith, type BlockPrefetchWithOptions, type BlockSchema, type BlockValues, type BlocksDocument, type BlocksFieldMeta, type BlocksPrefetchContext, type BuiltinActionType, type ComponentDefinition, type ComponentFactory, type ComponentReference, type ComponentType, type ComponentTypeRegistry, type DashboardActionFactory, type DashboardActionProxy, type DashboardCallback, type DashboardCallbackContext, type DashboardConfigContext, type DashboardContribution, type DashboardItemDef, type DashboardProxy, type DashboardSectionDef, type EditViewDefinition, type EditViewFactory, type ExecuteActionRequest, type ExecuteActionResponse, type ExpandWithResult, type ExpandedRecord, type FieldLayoutItem, type FilterOperator, type FilterRule, type FilterViewsByKind, type FormFieldLayoutItem, type FormReactiveConfig, type FormReactiveContext, type FormSectionLayout, type FormSidebarConfig, type FormTabConfig, type FormTabsLayout, type FormViewConfig, type FormViewConfigContext, type GetAdminSessionOptions, type InferBlockData, type InferBlockValues, type ListViewConfig, type ListViewConfigContext, type ListViewDefinition, type ListViewFactory, NextAuthMiddlewareOptions, type PreviewConfig, type PreviewTokenPayload, type RequireAdminAuthOptions, type RichTextFeature, type RichTextFieldMeta, type ServerActionContext, type ServerActionDefinition, type ServerActionDownload, type ServerActionEffects, type ServerActionError, type ServerActionForm, type ServerActionFormField, type ServerActionHandler, type ServerActionRedirect, type ServerActionResult, type ServerActionSuccess, type ServerActionsConfig, type ServerBrandingConfig, type ServerChartWidget, type ServerCustomWidget, type ServerDashboardAction, type ServerDashboardConfig, type ServerDashboardItem, type ServerDashboardSection, type ServerDashboardTab, type ServerDashboardTabs, type ServerDashboardWidget, type ServerProgressWidget, type ServerQuickAction, type ServerQuickActionsWidget, type ServerRecentItemsWidget, type ServerSidebarCollectionItem, type ServerSidebarConfig, type ServerSidebarDividerItem, type ServerSidebarGlobalItem, type ServerSidebarItem, type ServerSidebarLinkItem, type ServerSidebarPageItem, type ServerSidebarSection, type ServerStatsWidget, type ServerTableWidget, type ServerTimelineWidget, type ServerValueWidget, type SidebarCallback, type SidebarCallbackContext, type SidebarConfigContext, type SidebarContribution, type SidebarItemDef, type SidebarProxy, type SidebarSectionDef, type SortConfig, TanStackAuthGuardOptions, type TipTapDocument, type TipTapNode, type ViewConfiguration, type ViewDefinition, type ViewKind, type ViewKindRegistry, type WidgetAccessRule, type WidgetFetchContext, actionFunctions, adminConfig, adminFields, adminModule, adminPlugin, adminRoutes, auditLogCollection, _module as auditModule, batchReactive, block, component, createActionCallbackProxy, createActionProxy, createBlocksPrefetchHook, createComponentCallbackProxy, createComponentProxy, createDashboardCallbackContext, createDashboardContributionProxy, createFieldProxy, createFirstAdmin, createNextAuthMiddleware, createPreviewFunctions, createPreviewTokenVerifier, createSidebarCallbackContext, createSidebarContributionProxy, createTanStackAuthGuard, createTanStackSessionLoader, createViewCallbackProxy, createViewProxy, editView, executeAction, executeActionFn, fetchWidgetData, fieldOptions, filterViewsByKind, getActionsConfig, getActionsConfigFn, getAdminSession, getBlocksByCategory, getNextAdminSession, introspectBlock, introspectBlocks, isAdminUser, isSetupRequired, listView, processBlocksDocument, processDocumentBlocksPrefetch, reactiveFunctions, requireAdminAuth, resolveDashboardCallback, resolveSidebarCallback, savedViewsCollection, setupFunctions, verifyPreviewTokenDirect, view, widgetDataFunctions };
|
|
34
|
+
export { type ActionReference, type ActionsConfigContext, type AdminBlockConfig, type AdminCollectionConfig, type AdminConfigContext, type AdminConfigInput, type AdminGlobalConfig, type AdminLocaleConfig, type AdminModule, type AnyBlockBuilder, type AnyBlockDefinition, type AuditActorType, type AuditContext, type AuditModule, type AuthSession, BeforeLoadContext, BlockBuilder, type BlockBuilderState, type BlockCategoryConfig, type BlockDefinition, type BlockNode, type BlockPrefetchContext, type BlockPrefetchFn, type BlockPrefetchWith, type BlockPrefetchWithOptions, type BlockSchema, type BlockValues, type BlocksDocument, type BlocksFieldMeta, type BlocksPrefetchContext, type BuiltinActionType, type ComponentDefinition, type ComponentFactory, type ComponentReference, type ComponentType, type ComponentTypeRegistry, type DashboardActionFactory, type DashboardActionProxy, type DashboardCallback, type DashboardCallbackContext, type DashboardConfigContext, type DashboardContribution, type DashboardItemDef, type DashboardProxy, type DashboardSectionDef, type EditViewDefinition, type EditViewFactory, type ExecuteActionRequest, type ExecuteActionResponse, type ExpandWithResult, type ExpandedRecord, type FieldLayoutItem, type FilterOperator, type FilterRule, type FilterViewsByKind, type FormFieldLayoutItem, type FormReactiveConfig, type FormReactiveContext, type FormSectionLayout, type FormSidebarConfig, type FormTabConfig, type FormTabsLayout, type FormViewConfig, type FormViewConfigContext, type GetAdminSessionOptions, type InferBlockData, type InferBlockValues, type ListViewConfig, type ListViewConfigContext, type ListViewDefinition, type ListViewFactory, type LogAuditEntryOptions, NextAuthMiddlewareOptions, type PreviewConfig, type PreviewTokenPayload, type RequireAdminAuthOptions, type RichTextFeature, type RichTextFieldMeta, type ServerActionContext, type ServerActionDefinition, type ServerActionDownload, type ServerActionEffects, type ServerActionError, type ServerActionForm, type ServerActionFormField, type ServerActionHandler, type ServerActionRedirect, type ServerActionResult, type ServerActionSuccess, type ServerActionsConfig, type ServerBrandingConfig, type ServerChartWidget, type ServerCustomWidget, type ServerDashboardAction, type ServerDashboardConfig, type ServerDashboardItem, type ServerDashboardSection, type ServerDashboardTab, type ServerDashboardTabs, type ServerDashboardWidget, type ServerProgressWidget, type ServerQuickAction, type ServerQuickActionsWidget, type ServerRecentItemsWidget, type ServerSidebarCollectionItem, type ServerSidebarConfig, type ServerSidebarDividerItem, type ServerSidebarGlobalItem, type ServerSidebarItem, type ServerSidebarLinkItem, type ServerSidebarPageItem, type ServerSidebarSection, type ServerStatsWidget, type ServerTableWidget, type ServerTimelineWidget, type ServerValueWidget, type SidebarCallback, type SidebarCallbackContext, type SidebarConfigContext, type SidebarContribution, type SidebarItemDef, type SidebarProxy, type SidebarSectionDef, type SortConfig, TanStackAuthGuardOptions, type TipTapDocument, type TipTapNode, type ViewConfiguration, type ViewDefinition, type ViewKind, type ViewKindRegistry, type WidgetAccessRule, type WidgetFetchContext, actionFunctions, adminConfig, adminFields, adminModule, adminPlugin, adminRoutes, auditLogCollection, _module as auditModule, batchReactive, block, component, createActionCallbackProxy, createActionProxy, createBlocksPrefetchHook, createComponentCallbackProxy, createComponentProxy, createDashboardCallbackContext, createDashboardContributionProxy, createFieldProxy, createFirstAdmin, createNextAuthMiddleware, createPreviewFunctions, createPreviewTokenVerifier, createSidebarCallbackContext, createSidebarContributionProxy, createTanStackAuthGuard, createTanStackSessionLoader, createViewCallbackProxy, createViewProxy, editView, executeAction, executeActionFn, fetchWidgetData, fieldOptions, filterViewsByKind, getActionsConfig, getActionsConfigFn, getAdminSession, getBlocksByCategory, getNextAdminSession, introspectBlock, introspectBlocks, isAdminUser, isSetupRequired, listView, logAuditEntry, processBlocksDocument, processDocumentBlocksPrefetch, reactiveFunctions, requireAdminAuth, resolveDashboardCallback, resolveSidebarCallback, savedViewsCollection, setupFunctions, verifyPreviewTokenDirect, view, widgetDataFunctions };
|
package/dist/server.mjs
CHANGED
|
@@ -18,5 +18,6 @@ import { adminConfig } from "./server/augmentation/index.mjs";
|
|
|
18
18
|
import { adminModule, adminRoutes } from "./server/modules/admin/index.mjs";
|
|
19
19
|
import { auditLogCollection } from "./server/modules/audit/collections/audit-log.mjs";
|
|
20
20
|
import module_default from "./server/modules/audit/.generated/module.mjs";
|
|
21
|
+
import { logAuditEntry } from "./server/modules/audit/log-audit-entry.mjs";
|
|
21
22
|
|
|
22
|
-
export { BlockBuilder, actionFunctions, adminConfig, adminFields, adminModule, adminPlugin, adminRoutes, auditLogCollection, module_default as auditModule, batchReactive, block, component, createActionCallbackProxy, createActionProxy, createBlocksPrefetchHook, createComponentCallbackProxy, createComponentProxy, createDashboardCallbackContext, createDashboardContributionProxy, createFieldProxy, createFirstAdmin, createNextAuthMiddleware, createPreviewFunctions, createPreviewTokenVerifier, createSidebarCallbackContext, createSidebarContributionProxy, createTanStackAuthGuard, createTanStackSessionLoader, createViewCallbackProxy, createViewProxy, editView, executeAction, executeActionFn, fetchWidgetData, fieldOptions, filterViewsByKind, getActionsConfig, getActionsConfigFn, getAdminSession, getBlocksByCategory, getNextAdminSession, introspectBlock, introspectBlocks, isAdminUser, isSetupRequired, listView, processBlocksDocument, processDocumentBlocksPrefetch, reactiveFunctions, requireAdminAuth, resolveDashboardCallback, resolveSidebarCallback, savedViewsCollection, setupFunctions, verifyPreviewTokenDirect, view, widgetDataFunctions };
|
|
23
|
+
export { BlockBuilder, actionFunctions, adminConfig, adminFields, adminModule, adminPlugin, adminRoutes, auditLogCollection, module_default as auditModule, batchReactive, block, component, createActionCallbackProxy, createActionProxy, createBlocksPrefetchHook, createComponentCallbackProxy, createComponentProxy, createDashboardCallbackContext, createDashboardContributionProxy, createFieldProxy, createFirstAdmin, createNextAuthMiddleware, createPreviewFunctions, createPreviewTokenVerifier, createSidebarCallbackContext, createSidebarContributionProxy, createTanStackAuthGuard, createTanStackSessionLoader, createViewCallbackProxy, createViewProxy, editView, executeAction, executeActionFn, fetchWidgetData, fieldOptions, filterViewsByKind, getActionsConfig, getActionsConfigFn, getAdminSession, getBlocksByCategory, getNextAdminSession, introspectBlock, introspectBlocks, isAdminUser, isSetupRequired, listView, logAuditEntry, processBlocksDocument, processDocumentBlocksPrefetch, reactiveFunctions, requireAdminAuth, resolveDashboardCallback, resolveSidebarCallback, savedViewsCollection, setupFunctions, verifyPreviewTokenDirect, view, widgetDataFunctions };
|
|
@@ -76,11 +76,11 @@ declare function isDraftMode(cookieHeader: string | null | undefined): boolean;
|
|
|
76
76
|
*/
|
|
77
77
|
declare function createDraftModeCookie(enabled: boolean, maxAge?: number): string;
|
|
78
78
|
/**
|
|
79
|
-
*
|
|
80
|
-
* Falls back to SECRET if PREVIEW_SECRET is not set.
|
|
79
|
+
* Resolve a preview secret from an explicit value.
|
|
81
80
|
*
|
|
82
|
-
* @
|
|
81
|
+
* @deprecated Preview token signing now reads `app.config.secret` in server
|
|
82
|
+
* route handlers. Pass a secret explicitly when using standalone helpers.
|
|
83
83
|
*/
|
|
84
|
-
declare function getPreviewSecret(): string;
|
|
84
|
+
declare function getPreviewSecret(secret?: string): string;
|
|
85
85
|
//#endregion
|
|
86
86
|
export { ADMIN_API_PREFIX, DRAFT_MODE_COOKIE, createDraftModeCookie, getPreviewSecret, isAdminRequest, isDraftMode };
|
|
@@ -127,15 +127,13 @@ function createDraftModeCookie(enabled, maxAge = 3600) {
|
|
|
127
127
|
return `${DRAFT_MODE_COOKIE}=; Path=/; Max-Age=0; SameSite=Lax; HttpOnly`;
|
|
128
128
|
}
|
|
129
129
|
/**
|
|
130
|
-
*
|
|
131
|
-
* Falls back to SECRET if PREVIEW_SECRET is not set.
|
|
130
|
+
* Resolve a preview secret from an explicit value.
|
|
132
131
|
*
|
|
133
|
-
* @
|
|
132
|
+
* @deprecated Preview token signing now reads `app.config.secret` in server
|
|
133
|
+
* route handlers. Pass a secret explicitly when using standalone helpers.
|
|
134
134
|
*/
|
|
135
|
-
function getPreviewSecret() {
|
|
136
|
-
|
|
137
|
-
if (process.env.NODE_ENV === "production" && secret === "dev-preview-secret") console.warn("[preview] Using default secret in production. Set PREVIEW_SECRET or SECRET env var.");
|
|
138
|
-
return secret;
|
|
135
|
+
function getPreviewSecret(secret) {
|
|
136
|
+
return secret ?? "dev-preview-secret";
|
|
139
137
|
}
|
|
140
138
|
|
|
141
139
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@questpie/admin",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
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.
|
|
65
|
+
"@questpie/tanstack-query": "^3.3.0",
|
|
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.
|
|
91
|
+
"questpie": "^3.3.0",
|
|
92
92
|
"react-day-picker": "^9.12.0",
|
|
93
93
|
"react-hook-form": "^7.54.0",
|
|
94
94
|
"react-resizable-panels": "^4.4.2",
|