@questpie/admin 3.3.0 → 3.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -6
- package/dist/client/blocks/block-renderer.d.mts +2 -2
- package/dist/client/builder/admin-types.d.mts +3 -3
- package/dist/client/builder/types/action-types.d.mts +1 -1
- package/dist/client/builder/types/collection-types.d.mts +59 -2
- package/dist/client/modules/admin.d.mts +3 -0
- package/dist/client/modules/admin.mjs +3 -0
- package/dist/client/preview/block-scope-context.d.mts +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/views/auth/accept-invite-form.d.mts +2 -2
- package/dist/client/views/auth/auth-layout.d.mts +3 -3
- package/dist/client/views/auth/reset-password-form.d.mts +2 -2
- package/dist/client/views/auth/setup-form.d.mts +2 -2
- package/dist/client/views/collection/list-view.mjs +830 -0
- package/dist/client/views/collection/outline.mjs +363 -0
- package/dist/client/views/collection/table-view.mjs +6 -3
- package/dist/client/views/layout/admin-layout.d.mts +15 -1
- package/dist/client/views/layout/admin-layout.mjs +95 -31
- package/dist/client/views/pages/accept-invite-page.d.mts +2 -2
- package/dist/client/views/pages/dashboard-page.d.mts +2 -2
- package/dist/client/views/pages/forgot-password-page.d.mts +2 -2
- package/dist/client/views/pages/invite-page.d.mts +2 -2
- package/dist/client/views/pages/login-page.d.mts +2 -2
- package/dist/client.d.mts +6 -6
- package/dist/components/rich-text/rich-text-renderer.d.mts +2 -2
- package/dist/factories.d.mts +21 -0
- package/dist/factories.mjs +11 -0
- package/dist/fields.d.mts +4 -0
- package/dist/fields.mjs +5 -0
- package/dist/index.d.mts +6 -6
- package/dist/modules/admin.d.mts +10 -0
- package/dist/modules/admin.mjs +9 -0
- package/dist/modules/audit.d.mts +5 -0
- package/dist/modules/audit.mjs +5 -0
- package/dist/server/adapters/index.d.mts +2 -0
- package/dist/server/adapters/nextjs.d.mts +1 -0
- package/dist/server/augmentation/form-layout.d.mts +57 -2
- package/dist/server/augmentation/index.d.mts +3 -1
- package/dist/server/augmentation/shell.d.mts +48 -0
- package/dist/server/augmentation.d.mts +2 -1
- package/dist/server/auth-helpers.d.mts +1 -0
- package/dist/server/codegen/admin-client-template.mjs +11 -4
- package/dist/server/fields/blocks.d.mts +9 -2
- package/dist/server/fields/blocks.mjs +1 -1
- package/dist/server/fields/index.d.mts +2 -2
- package/dist/server/fields/index.mjs +2 -2
- package/dist/server/fields/rich-text.d.mts +9 -2
- package/dist/server/fields/rich-text.mjs +1 -1
- package/dist/server/modules/admin/.generated/module.d.mts +24 -19
- package/dist/server/modules/admin/.generated/module.mjs +5 -1
- package/dist/server/modules/admin/.generated/registries.d.mts +6 -4
- package/dist/server/modules/admin/client/.generated/module.d.mts +70 -70
- package/dist/server/modules/admin/client/.generated/module.mjs +3 -1
- package/dist/server/modules/admin/client/views/collection-form.d.mts +6 -0
- package/dist/server/modules/admin/client/views/collection-table.d.mts +6 -0
- package/dist/server/modules/admin/client/views/global-form.d.mts +6 -0
- package/dist/server/modules/admin/client/views/list-view.d.mts +6 -0
- package/dist/server/modules/admin/client/views/list-view.mjs +10 -0
- package/dist/server/modules/admin/collections/account.d.mts +50 -50
- 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/session.d.mts +42 -42
- package/dist/server/modules/admin/collections/user.d.mts +14 -14
- package/dist/server/modules/admin/collections/verification.d.mts +23 -23
- package/dist/server/modules/admin/dto/admin-config.dto.mjs +17 -0
- package/dist/server/modules/admin/index.d.mts +30 -31
- package/dist/server/modules/admin/routes/admin-config.d.mts +2 -17
- package/dist/server/modules/admin/routes/admin-config.mjs +21 -5
- package/dist/server/modules/admin/routes/execute-action.d.mts +9 -9
- package/dist/server/modules/admin/routes/execute-action.mjs +18 -12
- package/dist/server/modules/admin/routes/i18n-helpers.d.mts +4 -0
- package/dist/server/modules/admin/routes/preview.d.mts +11 -11
- package/dist/server/modules/admin/routes/reactive.d.mts +9 -9
- package/dist/server/modules/admin/routes/route-helpers.mjs +36 -1
- package/dist/server/modules/admin/routes/setup.d.mts +7 -14
- package/dist/server/modules/admin/routes/setup.mjs +16 -3
- package/dist/server/modules/admin/routes/widget-data.d.mts +5 -5
- package/dist/server/modules/admin/views/list-view.d.mts +8 -0
- package/dist/server/modules/admin/views/list-view.mjs +7 -0
- package/dist/server/modules/admin-preferences/collections/saved-views.d.mts +27 -27
- package/dist/server/modules/audit/collections/audit-log.d.mts +7 -2
- package/dist/server/modules/audit/index.d.mts +1 -1
- package/dist/server/plugin.d.mts +1 -1
- package/dist/server/plugin.mjs +28 -28
- package/dist/server.d.mts +7 -4
- package/dist/server.mjs +7 -7
- package/package.json +13 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { introspectBlocks } from "../block/introspection.mjs";
|
|
2
1
|
import { resolveDashboardCallback, resolveSidebarCallback } from "../../../proxy-factories.mjs";
|
|
2
|
+
import { introspectBlocks } from "../block/introspection.mjs";
|
|
3
3
|
import { adminConfigDTOSchema } from "../dto/admin-config.dto.mjs";
|
|
4
4
|
import { getAccessContext, getAdminConfig as getAdminConfig$1, getApp, getAppState, getCollectionState, getGlobalState } from "./route-helpers.mjs";
|
|
5
5
|
import { z } from "zod";
|
|
@@ -21,6 +21,21 @@ import { executeAccessRule, route } from "questpie";
|
|
|
21
21
|
* // { dashboard: {...}, sidebar: {...}, collections: {...}, globals: {...} }
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
|
+
function isPlainRecord(value) {
|
|
25
|
+
if (value === null || typeof value !== "object") return false;
|
|
26
|
+
const proto = Object.getPrototypeOf(value);
|
|
27
|
+
return proto === Object.prototype || proto === null;
|
|
28
|
+
}
|
|
29
|
+
function stripUndefinedDeep(value) {
|
|
30
|
+
if (Array.isArray(value)) return value.filter((item) => item !== void 0).map((item) => stripUndefinedDeep(item));
|
|
31
|
+
if (!isPlainRecord(value)) return value;
|
|
32
|
+
const result = {};
|
|
33
|
+
for (const [key, child] of Object.entries(value)) {
|
|
34
|
+
if (child === void 0) continue;
|
|
35
|
+
result[key] = stripUndefinedDeep(child);
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
24
39
|
/**
|
|
25
40
|
* Check if the current user has read access to a collection or global.
|
|
26
41
|
* Returns true if accessible, false if denied.
|
|
@@ -468,7 +483,7 @@ async function processDashboardItems(items, accessibleCollections, accessCtx) {
|
|
|
468
483
|
if (action.action?.type === "create") return accessibleCollections.has(action.action.collection);
|
|
469
484
|
return true;
|
|
470
485
|
});
|
|
471
|
-
const { loader: loader$1, access:
|
|
486
|
+
const { loader: loader$1, access: _access$1, filterFn: _filterFn$1, ...serializable$1 } = widget;
|
|
472
487
|
if (loader$1) serializable$1.hasLoader = true;
|
|
473
488
|
if (serializable$1.label && !serializable$1.title) serializable$1.title = serializable$1.label;
|
|
474
489
|
result.push({
|
|
@@ -478,7 +493,7 @@ async function processDashboardItems(items, accessibleCollections, accessCtx) {
|
|
|
478
493
|
});
|
|
479
494
|
continue;
|
|
480
495
|
}
|
|
481
|
-
const { loader, access, filterFn, ...serializable } = widget;
|
|
496
|
+
const { loader, access: _access, filterFn: _filterFn, ...serializable } = widget;
|
|
482
497
|
if (loader) serializable.hasLoader = true;
|
|
483
498
|
if (serializable.label && !serializable.title) serializable.title = serializable.label;
|
|
484
499
|
result.push(serializable);
|
|
@@ -497,7 +512,7 @@ const getAdminConfigOutputSchema = adminConfigDTOSchema;
|
|
|
497
512
|
* ```ts title="questpie/server/config/admin.ts"
|
|
498
513
|
* import { adminConfig } from "#questpie/factories";
|
|
499
514
|
*
|
|
500
|
-
* export
|
|
515
|
+
* export const config = adminConfig({
|
|
501
516
|
* dashboard: { items: [] },
|
|
502
517
|
* sidebar: { sections: [], items: [] },
|
|
503
518
|
* });
|
|
@@ -527,6 +542,7 @@ const getAdminConfig = route().post().schema(getAdminConfigSchema).outputSchema(
|
|
|
527
542
|
defaultCollection: uploadCollections.length === 1 ? uploadCollections[0] : void 0
|
|
528
543
|
};
|
|
529
544
|
if (adminCfg.branding) response.branding = adminCfg.branding;
|
|
545
|
+
if (adminCfg.shell) response.shell = adminCfg.shell;
|
|
530
546
|
if (adminCfg.dashboard) {
|
|
531
547
|
let dashboard;
|
|
532
548
|
if (isLegacyDashboardConfig(adminCfg.dashboard)) dashboard = adminCfg.dashboard;
|
|
@@ -555,7 +571,7 @@ const getAdminConfig = route().post().schema(getAdminConfigSchema).outputSchema(
|
|
|
555
571
|
if (appState.blocks && Object.keys(appState.blocks).length > 0) response.blocks = introspectBlocks(appState.blocks);
|
|
556
572
|
response.collections = filteredCollectionsMeta;
|
|
557
573
|
response.globals = filteredGlobalsMeta;
|
|
558
|
-
return response;
|
|
574
|
+
return stripUndefinedDeep(response);
|
|
559
575
|
});
|
|
560
576
|
/**
|
|
561
577
|
* Admin config route handlers.
|
|
@@ -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 questpie143 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: questpie143.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, questpie143.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: questpie143.JsonRouteDefinition<{
|
|
72
72
|
collection: string;
|
|
73
|
-
}, any,
|
|
73
|
+
}, any, questpie143.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: questpie143.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, questpie143.JsonRouteParams>;
|
|
87
|
+
getActionsConfig: questpie143.JsonRouteDefinition<{
|
|
88
88
|
collection: string;
|
|
89
|
-
}, any,
|
|
89
|
+
}, any, questpie143.JsonRouteParams>;
|
|
90
90
|
};
|
|
91
91
|
//#endregion
|
|
92
92
|
export { ExecuteActionRequest, ExecuteActionResponse, actionFunctions, executeAction, executeActionFn, getActionsConfig, getActionsConfigFn };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getApp,
|
|
1
|
+
import { getApp, getCollection, getCollectionCrud, getCollectionCruds, getGlobalCruds, getSession } from "./route-helpers.mjs";
|
|
2
2
|
import { translateAdminMessage } from "./i18n-helpers.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { route } from "questpie";
|
|
@@ -26,7 +26,7 @@ import { route } from "questpie";
|
|
|
26
26
|
* Returns action definitions without handlers (for client-side rendering).
|
|
27
27
|
*/
|
|
28
28
|
function getActionsConfig(app, collectionSlug) {
|
|
29
|
-
const collection$1 =
|
|
29
|
+
const collection$1 = getCollection(app, collectionSlug);
|
|
30
30
|
if (!collection$1) return null;
|
|
31
31
|
const actionsConfig = (collection$1.state || collection$1).adminActions;
|
|
32
32
|
if (!actionsConfig) return {
|
|
@@ -98,7 +98,7 @@ function serializeActionFormFields(fields) {
|
|
|
98
98
|
*/
|
|
99
99
|
async function executeAction(app, request, session) {
|
|
100
100
|
const { collection: collectionSlug, actionId, itemId, itemIds, data, locale } = request;
|
|
101
|
-
const collection$1 =
|
|
101
|
+
const collection$1 = getCollection(app, collectionSlug);
|
|
102
102
|
const t = (key, params) => translateAdminMessage(locale, key, params);
|
|
103
103
|
if (!collection$1) return {
|
|
104
104
|
success: false,
|
|
@@ -148,8 +148,8 @@ async function executeAction(app, request, session) {
|
|
|
148
148
|
itemId,
|
|
149
149
|
itemIds,
|
|
150
150
|
auth: appRec.auth,
|
|
151
|
-
collections:
|
|
152
|
-
globals:
|
|
151
|
+
collections: getCollectionCruds(app),
|
|
152
|
+
globals: getGlobalCruds(app),
|
|
153
153
|
db: appRec.db,
|
|
154
154
|
session,
|
|
155
155
|
locale
|
|
@@ -177,7 +177,7 @@ async function executeBuiltinAction(app, params) {
|
|
|
177
177
|
const { collectionSlug, actionId, itemId, itemIds, data, locale } = params;
|
|
178
178
|
const t = (key, messageParams) => translateAdminMessage(locale, key, messageParams);
|
|
179
179
|
const appRec = app;
|
|
180
|
-
const collectionCrud =
|
|
180
|
+
const collectionCrud = getCollectionCrud(app, collectionSlug);
|
|
181
181
|
const crudContext = {
|
|
182
182
|
db: appRec.db,
|
|
183
183
|
session: params.session,
|
|
@@ -186,7 +186,7 @@ async function executeBuiltinAction(app, params) {
|
|
|
186
186
|
try {
|
|
187
187
|
switch (actionId) {
|
|
188
188
|
case "create": {
|
|
189
|
-
const result = await appRec.create(collectionSlug, data || {});
|
|
189
|
+
const result = collectionCrud?.create ? await collectionCrud.create(data || {}, crudContext) : await appRec.create(collectionSlug, data || {});
|
|
190
190
|
return {
|
|
191
191
|
success: true,
|
|
192
192
|
result: {
|
|
@@ -207,7 +207,11 @@ async function executeBuiltinAction(app, params) {
|
|
|
207
207
|
toast: { message: t("action.itemIdRequired.save") }
|
|
208
208
|
}
|
|
209
209
|
};
|
|
210
|
-
await
|
|
210
|
+
if (collectionCrud?.updateById) await collectionCrud.updateById({
|
|
211
|
+
id: itemId,
|
|
212
|
+
data: data || {}
|
|
213
|
+
}, crudContext);
|
|
214
|
+
else await appRec.update(collectionSlug, itemId, data || {});
|
|
211
215
|
return {
|
|
212
216
|
success: true,
|
|
213
217
|
result: {
|
|
@@ -224,7 +228,8 @@ async function executeBuiltinAction(app, params) {
|
|
|
224
228
|
toast: { message: t("action.itemIdRequired.delete") }
|
|
225
229
|
}
|
|
226
230
|
};
|
|
227
|
-
await
|
|
231
|
+
if (collectionCrud?.deleteById) await collectionCrud.deleteById({ id: itemId }, crudContext);
|
|
232
|
+
else await appRec.delete(collectionSlug, itemId);
|
|
228
233
|
return {
|
|
229
234
|
success: true,
|
|
230
235
|
result: {
|
|
@@ -244,7 +249,8 @@ async function executeBuiltinAction(app, params) {
|
|
|
244
249
|
toast: { message: t("action.itemIdsRequired.bulkDelete") }
|
|
245
250
|
}
|
|
246
251
|
};
|
|
247
|
-
await Promise.all(itemIds.map((id) =>
|
|
252
|
+
if (collectionCrud?.deleteById) await Promise.all(itemIds.map((id) => collectionCrud.deleteById({ id }, crudContext)));
|
|
253
|
+
else await Promise.all(itemIds.map((id) => appRec.delete(collectionSlug, id)));
|
|
248
254
|
return {
|
|
249
255
|
success: true,
|
|
250
256
|
result: {
|
|
@@ -314,7 +320,7 @@ async function executeBuiltinAction(app, params) {
|
|
|
314
320
|
toast: { message: t("action.itemIdRequired.duplicate") }
|
|
315
321
|
}
|
|
316
322
|
};
|
|
317
|
-
const original = await appRec.findById(collectionSlug, itemId);
|
|
323
|
+
const original = collectionCrud?.findOne ? await collectionCrud.findOne({ where: { id: itemId } }, crudContext) : await appRec.findById(collectionSlug, itemId);
|
|
318
324
|
if (!original) return {
|
|
319
325
|
success: false,
|
|
320
326
|
result: {
|
|
@@ -323,7 +329,7 @@ async function executeBuiltinAction(app, params) {
|
|
|
323
329
|
}
|
|
324
330
|
};
|
|
325
331
|
const { id, createdAt, updatedAt, ...duplicateData } = original;
|
|
326
|
-
const duplicated = await appRec.create(collectionSlug, duplicateData);
|
|
332
|
+
const duplicated = collectionCrud?.create ? await collectionCrud.create(duplicateData, crudContext) : await appRec.create(collectionSlug, duplicateData);
|
|
327
333
|
return {
|
|
328
334
|
success: true,
|
|
329
335
|
result: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as questpie73 from "questpie";
|
|
2
2
|
|
|
3
3
|
//#region src/server/modules/admin/routes/preview.d.ts
|
|
4
4
|
|
|
@@ -25,13 +25,13 @@ interface PreviewTokenPayload {
|
|
|
25
25
|
* @returns Object with preview functions
|
|
26
26
|
*/
|
|
27
27
|
declare function createPreviewFunctions(secret?: PreviewSecretSource): {
|
|
28
|
-
mintPreviewToken:
|
|
28
|
+
mintPreviewToken: questpie73.JsonRouteDefinition<{
|
|
29
29
|
path: string;
|
|
30
30
|
ttlMs?: number | undefined;
|
|
31
|
-
}, any,
|
|
32
|
-
verifyPreviewToken:
|
|
31
|
+
}, any, questpie73.JsonRouteParams>;
|
|
32
|
+
verifyPreviewToken: questpie73.JsonRouteDefinition<{
|
|
33
33
|
token: string;
|
|
34
|
-
}, any,
|
|
34
|
+
}, any, questpie73.JsonRouteParams>;
|
|
35
35
|
};
|
|
36
36
|
/**
|
|
37
37
|
* Verify a preview token without RPC.
|
|
@@ -68,18 +68,18 @@ declare function createPreviewTokenVerifier(secret: string): (token: string) =>
|
|
|
68
68
|
* Used by the `adminModule` to register preview RPC functions.
|
|
69
69
|
*/
|
|
70
70
|
declare const previewFunctions: {
|
|
71
|
-
getPreviewUrl:
|
|
71
|
+
getPreviewUrl: questpie73.JsonRouteDefinition<{
|
|
72
72
|
collection: string;
|
|
73
73
|
record: Record<string, unknown>;
|
|
74
74
|
locale?: string | undefined;
|
|
75
|
-
}, any,
|
|
76
|
-
mintPreviewToken:
|
|
75
|
+
}, any, questpie73.JsonRouteParams>;
|
|
76
|
+
mintPreviewToken: questpie73.JsonRouteDefinition<{
|
|
77
77
|
path: string;
|
|
78
78
|
ttlMs?: number | undefined;
|
|
79
|
-
}, any,
|
|
80
|
-
verifyPreviewToken:
|
|
79
|
+
}, any, questpie73.JsonRouteParams>;
|
|
80
|
+
verifyPreviewToken: questpie73.JsonRouteDefinition<{
|
|
81
81
|
token: string;
|
|
82
|
-
}, any,
|
|
82
|
+
}, any, questpie73.JsonRouteParams>;
|
|
83
83
|
};
|
|
84
84
|
//#endregion
|
|
85
85
|
export { PreviewTokenPayload, createPreviewFunctions, createPreviewTokenVerifier, previewFunctions, verifyPreviewTokenDirect };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as questpie83 from "questpie";
|
|
2
2
|
|
|
3
3
|
//#region src/server/modules/admin/routes/reactive.d.ts
|
|
4
4
|
|
|
@@ -13,7 +13,7 @@ import * as questpie113 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: questpie83.JsonRouteDefinition<{
|
|
17
17
|
collection: string;
|
|
18
18
|
type: "collection" | "global";
|
|
19
19
|
requests: {
|
|
@@ -27,12 +27,12 @@ declare const batchReactive: questpie113.JsonRouteDefinition<{
|
|
|
27
27
|
}[];
|
|
28
28
|
formData?: Record<string, unknown> | undefined;
|
|
29
29
|
prevData?: Record<string, unknown> | null | undefined;
|
|
30
|
-
}, any,
|
|
30
|
+
}, any, questpie83.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: questpie83.JsonRouteDefinition<{
|
|
36
36
|
collection: string;
|
|
37
37
|
type: "collection" | "global";
|
|
38
38
|
field: string;
|
|
@@ -41,12 +41,12 @@ declare const fieldOptions: questpie113.JsonRouteDefinition<{
|
|
|
41
41
|
page: number;
|
|
42
42
|
limit: number;
|
|
43
43
|
siblingData?: Record<string, unknown> | null | undefined;
|
|
44
|
-
}, any,
|
|
44
|
+
}, any, questpie83.JsonRouteParams>;
|
|
45
45
|
/**
|
|
46
46
|
* Reactive functions bundle.
|
|
47
47
|
*/
|
|
48
48
|
declare const reactiveFunctions: {
|
|
49
|
-
readonly batchReactive:
|
|
49
|
+
readonly batchReactive: questpie83.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, questpie83.JsonRouteParams>;
|
|
64
|
+
readonly fieldOptions: questpie83.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, questpie83.JsonRouteParams>;
|
|
74
74
|
};
|
|
75
75
|
//#endregion
|
|
76
76
|
export { batchReactive, fieldOptions, reactiveFunctions };
|
|
@@ -60,6 +60,41 @@ function getAdminConfig(app) {
|
|
|
60
60
|
return getAppState(app).config?.admin || {};
|
|
61
61
|
}
|
|
62
62
|
/**
|
|
63
|
+
* Get registered collection definitions from the current or legacy app shape.
|
|
64
|
+
*/
|
|
65
|
+
function getCollections(app) {
|
|
66
|
+
const appRec = app;
|
|
67
|
+
if (typeof appRec.getCollections === "function") return appRec.getCollections();
|
|
68
|
+
return getAppState(app).collections ?? {};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get a registered collection definition by slug.
|
|
72
|
+
*/
|
|
73
|
+
function getCollection(app, collectionSlug) {
|
|
74
|
+
return getCollections(app)[collectionSlug];
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get collection CRUD APIs from the current or legacy app shape.
|
|
78
|
+
*/
|
|
79
|
+
function getCollectionCrud(app, collectionSlug) {
|
|
80
|
+
const appRec = app;
|
|
81
|
+
return appRec.collections?.[collectionSlug] ?? appRec.api?.collections?.[collectionSlug] ?? appRec._api?.collections?.[collectionSlug];
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Get all collection CRUD APIs from the current or legacy app shape.
|
|
85
|
+
*/
|
|
86
|
+
function getCollectionCruds(app) {
|
|
87
|
+
const appRec = app;
|
|
88
|
+
return appRec.collections ?? appRec.api?.collections ?? appRec._api?.collections;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Get all global CRUD APIs from the current or legacy app shape.
|
|
92
|
+
*/
|
|
93
|
+
function getGlobalCruds(app) {
|
|
94
|
+
const appRec = app;
|
|
95
|
+
return appRec.globals ?? appRec.api?.globals ?? appRec._api?.globals;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
63
98
|
* Build a ReactiveServerContext from route handler context.
|
|
64
99
|
*/
|
|
65
100
|
function buildServerContext(ctx) {
|
|
@@ -73,4 +108,4 @@ function buildServerContext(ctx) {
|
|
|
73
108
|
}
|
|
74
109
|
|
|
75
110
|
//#endregion
|
|
76
|
-
export { buildServerContext, getAccessContext, getAdminConfig, getApp, getAppState, getCollectionState, getGlobalState, getLocale, getSession };
|
|
111
|
+
export { buildServerContext, getAccessContext, getAdminConfig, getApp, getAppState, getCollection, getCollectionCrud, getCollectionCruds, getCollectionState, getGlobalCruds, getGlobalState, getLocale, getSession };
|
|
@@ -1,14 +1,7 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as questpie91 from "questpie";
|
|
2
2
|
|
|
3
3
|
//#region src/server/modules/admin/routes/setup.d.ts
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* Setup Functions
|
|
7
|
-
*
|
|
8
|
-
* Built-in functions for bootstrapping the first admin user.
|
|
9
|
-
* Solves the chicken-and-egg problem where invitation-based systems
|
|
10
|
-
* need an existing admin to create the first invitation.
|
|
11
|
-
*/
|
|
12
5
|
/**
|
|
13
6
|
* Check if setup is required (no admin users exist in the system).
|
|
14
7
|
*
|
|
@@ -20,7 +13,7 @@ import * as questpie129 from "questpie";
|
|
|
20
13
|
* }
|
|
21
14
|
* ```
|
|
22
15
|
*/
|
|
23
|
-
declare const isSetupRequired:
|
|
16
|
+
declare const isSetupRequired: questpie91.JsonRouteDefinition<Record<string, never>, any, questpie91.JsonRouteParams>;
|
|
24
17
|
/**
|
|
25
18
|
* Create the first admin user in the system.
|
|
26
19
|
* This function only works when no admin users exist (setup mode).
|
|
@@ -43,21 +36,21 @@ declare const isSetupRequired: questpie129.JsonRouteDefinition<Record<string, ne
|
|
|
43
36
|
* }
|
|
44
37
|
* ```
|
|
45
38
|
*/
|
|
46
|
-
declare const createFirstAdmin:
|
|
39
|
+
declare const createFirstAdmin: questpie91.JsonRouteDefinition<{
|
|
47
40
|
email: string;
|
|
48
41
|
password: string;
|
|
49
42
|
name: string;
|
|
50
|
-
}, any,
|
|
43
|
+
}, any, questpie91.JsonRouteParams>;
|
|
51
44
|
/**
|
|
52
45
|
* Bundle of setup-related functions.
|
|
53
46
|
*/
|
|
54
47
|
declare const setupFunctions: {
|
|
55
|
-
readonly isSetupRequired:
|
|
56
|
-
readonly createFirstAdmin:
|
|
48
|
+
readonly isSetupRequired: questpie91.JsonRouteDefinition<Record<string, never>, any, questpie91.JsonRouteParams>;
|
|
49
|
+
readonly createFirstAdmin: questpie91.JsonRouteDefinition<{
|
|
57
50
|
email: string;
|
|
58
51
|
password: string;
|
|
59
52
|
name: string;
|
|
60
|
-
}, any,
|
|
53
|
+
}, any, questpie91.JsonRouteParams>;
|
|
61
54
|
};
|
|
62
55
|
//#endregion
|
|
63
56
|
export { createFirstAdmin, isSetupRequired, setupFunctions };
|
|
@@ -28,6 +28,17 @@ const createFirstAdminOutputSchema = z.object({
|
|
|
28
28
|
}).optional(),
|
|
29
29
|
error: z.string().optional()
|
|
30
30
|
});
|
|
31
|
+
const adminUserContractMessage = "QUESTPIE Admin requires the canonical Better Auth \"user\" collection from adminModule/starterModule. The current \"user\" collection is missing required admin auth fields. Do not replace collection(\"user\") from scratch; merge starterModule.collections.user or adminModule.collections.user and extend it.";
|
|
32
|
+
function getAdminUserTableContract(userCollection) {
|
|
33
|
+
const table = userCollection?.table;
|
|
34
|
+
const missing = [
|
|
35
|
+
"id",
|
|
36
|
+
"role",
|
|
37
|
+
"emailVerified"
|
|
38
|
+
].filter((field$1) => !table?.[field$1]);
|
|
39
|
+
if (missing.length > 0) throw new Error(`${adminUserContractMessage} Missing field(s): ${missing.join(", ")}.`);
|
|
40
|
+
return table;
|
|
41
|
+
}
|
|
31
42
|
/**
|
|
32
43
|
* Check if setup is required (no admin users exist in the system).
|
|
33
44
|
*
|
|
@@ -42,7 +53,8 @@ const createFirstAdminOutputSchema = z.object({
|
|
|
42
53
|
const isSetupRequired = route().post().schema(isSetupRequiredSchema).outputSchema(isSetupRequiredOutputSchema).handler(async (ctx) => {
|
|
43
54
|
const app = getApp(ctx);
|
|
44
55
|
const userCollection = app.getCollectionConfig("user");
|
|
45
|
-
|
|
56
|
+
const userTable = getAdminUserTableContract(userCollection);
|
|
57
|
+
return { required: (await app.db.select({ count: sql$1`count(*)::int` }).from(userCollection.table).where(eq(userTable.role, "admin")))[0].count === 0 };
|
|
46
58
|
});
|
|
47
59
|
/**
|
|
48
60
|
* Create the first admin user in the system.
|
|
@@ -72,7 +84,8 @@ const createFirstAdmin = route().post().schema(createFirstAdminSchema).outputSch
|
|
|
72
84
|
const t = (key, params) => translateAdminMessage(locale, key, params);
|
|
73
85
|
const input = ctx.input;
|
|
74
86
|
const userCollection = app.getCollectionConfig("user");
|
|
75
|
-
|
|
87
|
+
const userTable = getAdminUserTableContract(userCollection);
|
|
88
|
+
if ((await app.db.select({ count: sql$1`count(*)::int` }).from(userCollection.table).where(eq(userTable.role, "admin")))[0].count > 0) return {
|
|
76
89
|
success: false,
|
|
77
90
|
error: t("auth.setupAlreadyCompleted")
|
|
78
91
|
};
|
|
@@ -89,7 +102,7 @@ const createFirstAdmin = route().post().schema(createFirstAdminSchema).outputSch
|
|
|
89
102
|
await app.db.update(userCollection.table).set({
|
|
90
103
|
role: "admin",
|
|
91
104
|
emailVerified: true
|
|
92
|
-
}).where(eq(
|
|
105
|
+
}).where(eq(userTable.id, signUpResult.user.id));
|
|
93
106
|
return {
|
|
94
107
|
success: true,
|
|
95
108
|
user: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as questpie69 from "questpie";
|
|
2
2
|
|
|
3
3
|
//#region src/server/modules/admin/routes/widget-data.d.ts
|
|
4
4
|
|
|
@@ -20,13 +20,13 @@ import * as questpie137 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: questpie69.JsonRouteDefinition<{
|
|
24
24
|
widgetId: string;
|
|
25
|
-
}, any,
|
|
25
|
+
}, any, questpie69.JsonRouteParams>;
|
|
26
26
|
declare const widgetDataFunctions: {
|
|
27
|
-
readonly fetchWidgetData:
|
|
27
|
+
readonly fetchWidgetData: questpie69.JsonRouteDefinition<{
|
|
28
28
|
widgetId: string;
|
|
29
|
-
}, any,
|
|
29
|
+
}, any, questpie69.JsonRouteParams>;
|
|
30
30
|
};
|
|
31
31
|
//#endregion
|
|
32
32
|
export { fetchWidgetData, widgetDataFunctions };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ListViewConfig } from "../../../augmentation/form-layout.mjs";
|
|
2
|
+
import { ViewDefinition } from "../../../augmentation/views.mjs";
|
|
3
|
+
import "../../../augmentation.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/server/modules/admin/views/list-view.d.ts
|
|
6
|
+
declare const _default: ViewDefinition<"list-view", "list", ListViewConfig>;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { _default };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { FilterOperator, FilterRule, SortConfig, ViewConfiguration } from "../../../../shared/types/saved-views.types.mjs";
|
|
2
2
|
import * as questpie_shared16 from "questpie/shared";
|
|
3
|
-
import * as
|
|
4
|
-
import * as
|
|
5
|
-
import * as
|
|
3
|
+
import * as questpie115 from "questpie";
|
|
4
|
+
import * as questpie_src_server_modules_core_fields_email_js2 from "questpie/src/server/modules/core/fields/email.js";
|
|
5
|
+
import * as questpie_src_server_modules_core_fields_json_js2 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: questpie115.CollectionBuilder<questpie_shared16.Override<questpie_shared16.Override<questpie115.EmptyCollectionState<"admin_saved_views", undefined, {
|
|
35
|
+
readonly text: typeof questpie115.text;
|
|
36
|
+
readonly textarea: typeof questpie115.textarea;
|
|
37
|
+
readonly email: typeof questpie_src_server_modules_core_fields_email_js2.email;
|
|
38
|
+
readonly url: typeof questpie115.url;
|
|
39
|
+
readonly number: typeof questpie115.number;
|
|
40
|
+
readonly boolean: typeof questpie115.boolean;
|
|
41
|
+
readonly date: typeof questpie115.date;
|
|
42
|
+
readonly datetime: typeof questpie115.datetime;
|
|
43
|
+
readonly time: typeof questpie115.time;
|
|
44
|
+
readonly select: typeof questpie115.select;
|
|
45
|
+
readonly upload: typeof questpie115.upload;
|
|
46
|
+
readonly relation: typeof questpie115.relation;
|
|
47
|
+
readonly object: typeof questpie115.object;
|
|
48
|
+
readonly json: typeof questpie_src_server_modules_core_fields_json_js2.json;
|
|
49
|
+
readonly from: typeof questpie115.from;
|
|
50
50
|
}>, {
|
|
51
51
|
fields: {
|
|
52
52
|
readonly userId: drizzle_orm5.NotNull<drizzle_orm_pg_core22.PgVarcharBuilder<[string, ...string[]]>>;
|
|
@@ -57,31 +57,31 @@ declare const savedViewsCollection: questpie69.CollectionBuilder<questpie_shared
|
|
|
57
57
|
};
|
|
58
58
|
localized: readonly string[];
|
|
59
59
|
fieldDefinitions: {
|
|
60
|
-
readonly userId:
|
|
60
|
+
readonly userId: questpie115.FieldWithMethods<Omit<questpie115.TextFieldState, "notNull" | "column"> & {
|
|
61
61
|
notNull: true;
|
|
62
62
|
column: drizzle_orm5.NotNull<drizzle_orm_pg_core22.PgVarcharBuilder<[string, ...string[]]>>;
|
|
63
63
|
} & {
|
|
64
64
|
label: questpie_shared16.I18nText;
|
|
65
|
-
},
|
|
66
|
-
readonly collectionName:
|
|
65
|
+
}, questpie115.TextFieldMethods>;
|
|
66
|
+
readonly collectionName: questpie115.FieldWithMethods<Omit<questpie115.TextFieldState, "notNull" | "column"> & {
|
|
67
67
|
notNull: true;
|
|
68
68
|
column: drizzle_orm5.NotNull<drizzle_orm_pg_core22.PgVarcharBuilder<[string, ...string[]]>>;
|
|
69
69
|
} & {
|
|
70
70
|
label: questpie_shared16.I18nText;
|
|
71
|
-
},
|
|
72
|
-
readonly name:
|
|
71
|
+
}, questpie115.TextFieldMethods>;
|
|
72
|
+
readonly name: questpie115.FieldWithMethods<Omit<questpie115.TextFieldState, "notNull" | "column"> & {
|
|
73
73
|
notNull: true;
|
|
74
74
|
column: drizzle_orm5.NotNull<drizzle_orm_pg_core22.PgVarcharBuilder<[string, ...string[]]>>;
|
|
75
75
|
} & {
|
|
76
76
|
label: questpie_shared16.I18nText;
|
|
77
|
-
},
|
|
78
|
-
readonly configuration:
|
|
77
|
+
}, questpie115.TextFieldMethods>;
|
|
78
|
+
readonly configuration: questpie115.Field<Omit<questpie115.JsonFieldState, "notNull" | "column"> & {
|
|
79
79
|
notNull: true;
|
|
80
80
|
column: drizzle_orm5.NotNull<drizzle_orm_pg_core22.PgJsonbBuilder>;
|
|
81
81
|
} & {
|
|
82
82
|
label: questpie_shared16.I18nText;
|
|
83
83
|
}>;
|
|
84
|
-
readonly isDefault:
|
|
84
|
+
readonly isDefault: questpie115.Field<Omit<questpie115.BooleanFieldState, "column" | "hasDefault"> & {
|
|
85
85
|
hasDefault: true;
|
|
86
86
|
column: drizzle_orm5.HasDefault<drizzle_orm_pg_core22.PgBooleanBuilder>;
|
|
87
87
|
} & {
|
|
@@ -7,7 +7,12 @@ import * as drizzle_orm0 from "drizzle-orm";
|
|
|
7
7
|
import * as questpie_src_server_fields_operators_builtin_js0 from "questpie/src/server/fields/operators/builtin.js";
|
|
8
8
|
|
|
9
9
|
//#region src/server/modules/audit/collections/audit-log.d.ts
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* The collection slug used by the audit log.
|
|
12
|
+
* Exported so hooks and jobs can reference the collection dynamically
|
|
13
|
+
* instead of hardcoding the name.
|
|
14
|
+
*/
|
|
15
|
+
declare const AUDIT_LOG_COLLECTION: "admin_audit_log";
|
|
11
16
|
/**
|
|
12
17
|
* Audit Log Collection
|
|
13
18
|
*
|
|
@@ -213,4 +218,4 @@ declare const auditLogCollection: questpie21.CollectionBuilder<questpie_shared0.
|
|
|
213
218
|
})[];
|
|
214
219
|
}>>;
|
|
215
220
|
//#endregion
|
|
216
|
-
export { auditLogCollection };
|
|
221
|
+
export { AUDIT_LOG_COLLECTION, auditLogCollection };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { auditLogCollection } from "./collections/audit-log.mjs";
|
|
1
|
+
import { AUDIT_LOG_COLLECTION, auditLogCollection } from "./collections/audit-log.mjs";
|
|
2
2
|
import { AuditModule, _module } from "./.generated/module.mjs";
|
|
3
3
|
import { AuditActorType, AuditContext, LogAuditEntryOptions, logAuditEntry } from "./log-audit-entry.mjs";
|