@sonicjs-cms/core 3.0.0-beta.25 → 3.0.0-beta.26
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/{app-01M0dIwt.d.ts → app-BP5IlK94.d.ts} +7 -7
- package/dist/{app-aj39TGHB.d.cts → app-fdq4K3vw.d.cts} +7 -7
- package/dist/catalog-56DR6OXI.cjs +41 -0
- package/dist/catalog-56DR6OXI.cjs.map +1 -0
- package/dist/catalog-6MB37KY7.js +4 -0
- package/dist/catalog-6MB37KY7.js.map +1 -0
- package/dist/{chunk-YAURVGUK.cjs → chunk-4DHPR7KR.cjs} +77 -17
- package/dist/chunk-4DHPR7KR.cjs.map +1 -0
- package/dist/{chunk-D7RLBBHE.js → chunk-5YSFQO7X.js} +40 -13
- package/dist/chunk-5YSFQO7X.js.map +1 -0
- package/dist/{chunk-RSBZITK3.cjs → chunk-6UAI4SGN.cjs} +3 -3
- package/dist/{chunk-RSBZITK3.cjs.map → chunk-6UAI4SGN.cjs.map} +1 -1
- package/dist/{chunk-2XAQTPAE.js → chunk-6X22VFEV.js} +8 -2
- package/dist/chunk-6X22VFEV.js.map +1 -0
- package/dist/{chunk-I7MIRRFJ.cjs → chunk-A22RBHO7.cjs} +11 -11
- package/dist/{chunk-I7MIRRFJ.cjs.map → chunk-A22RBHO7.cjs.map} +1 -1
- package/dist/{chunk-FVAK4C6L.js → chunk-AMP4BSJE.js} +3 -3
- package/dist/{chunk-FVAK4C6L.js.map → chunk-AMP4BSJE.js.map} +1 -1
- package/dist/{chunk-E7E3NL3Y.cjs → chunk-BRKXMRMB.cjs} +93 -93
- package/dist/chunk-BRKXMRMB.cjs.map +1 -0
- package/dist/{chunk-36Z3AKX3.cjs → chunk-C5LDQ3SH.cjs} +8 -2
- package/dist/chunk-C5LDQ3SH.cjs.map +1 -0
- package/dist/{chunk-2OXFMMA3.js → chunk-EEA476CJ.js} +84 -80
- package/dist/chunk-EEA476CJ.js.map +1 -0
- package/dist/chunk-F6BTBE4S.js +119 -0
- package/dist/chunk-F6BTBE4S.js.map +1 -0
- package/dist/chunk-FZGIU5AZ.cjs +128 -0
- package/dist/chunk-FZGIU5AZ.cjs.map +1 -0
- package/dist/{chunk-C54MH5UI.js → chunk-JD7BZU3A.js} +3 -3
- package/dist/{chunk-C54MH5UI.js.map → chunk-JD7BZU3A.js.map} +1 -1
- package/dist/{chunk-3KGY4IBW.js → chunk-JG5J434C.js} +3 -3
- package/dist/{chunk-3KGY4IBW.js.map → chunk-JG5J434C.js.map} +1 -1
- package/dist/{chunk-D6FWEYQE.cjs → chunk-KWQNB6UM.cjs} +4 -4
- package/dist/{chunk-D6FWEYQE.cjs.map → chunk-KWQNB6UM.cjs.map} +1 -1
- package/dist/{chunk-7P5OCUPS.js → chunk-OJFIQGZB.js} +107 -29
- package/dist/chunk-OJFIQGZB.js.map +1 -0
- package/dist/{chunk-JCBDXEY2.cjs → chunk-OLEOKHDX.cjs} +9 -2
- package/dist/chunk-OLEOKHDX.cjs.map +1 -0
- package/dist/{chunk-MOGK3U4A.cjs → chunk-PAS7GZBS.cjs} +40 -13
- package/dist/chunk-PAS7GZBS.cjs.map +1 -0
- package/dist/{chunk-2D3A4X52.js → chunk-RVOX2WH2.js} +74 -18
- package/dist/chunk-RVOX2WH2.js.map +1 -0
- package/dist/{chunk-BDQ55MWV.js → chunk-RXLI3ADU.js} +9 -2
- package/dist/chunk-RXLI3ADU.js.map +1 -0
- package/dist/{chunk-6OA77UM7.cjs → chunk-S2QN4LFD.cjs} +386 -306
- package/dist/chunk-S2QN4LFD.cjs.map +1 -0
- package/dist/{chunk-DLTT7QZU.cjs → chunk-SFGYZUWU.cjs} +3 -3
- package/dist/{chunk-DLTT7QZU.cjs.map → chunk-SFGYZUWU.cjs.map} +1 -1
- package/dist/{chunk-CWIGQYRR.js → chunk-UB5QSRO7.js} +5 -5
- package/dist/chunk-UB5QSRO7.js.map +1 -0
- package/dist/{chunk-F26HP3B6.js → chunk-UKIDWRA3.js} +4 -4
- package/dist/{chunk-F26HP3B6.js.map → chunk-UKIDWRA3.js.map} +1 -1
- package/dist/{chunk-BJ6NJL2E.cjs → chunk-XZUEGFXE.cjs} +5 -5
- package/dist/chunk-XZUEGFXE.cjs.map +1 -0
- package/dist/{collection-config-BTzAvKt2.d.cts → collection-config-U2dydD_O.d.cts} +14 -0
- package/dist/{collection-config-BTzAvKt2.d.ts → collection-config-U2dydD_O.d.ts} +14 -0
- package/dist/config-DOAWXZBG.js +6 -0
- package/dist/{config-4TIHSNW6.js.map → config-DOAWXZBG.js.map} +1 -1
- package/dist/{config-XN2ETAJ3.cjs → config-VLU73ZW7.cjs} +5 -5
- package/dist/{config-XN2ETAJ3.cjs.map → config-VLU73ZW7.cjs.map} +1 -1
- package/dist/index.cjs +600 -332
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -10
- package/dist/index.d.ts +17 -10
- package/dist/index.js +292 -25
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +46 -46
- package/dist/middleware.d.cts +6 -9
- package/dist/middleware.d.ts +6 -9
- package/dist/middleware.js +5 -5
- package/dist/migrations-6M6772UC.cjs +13 -0
- package/dist/{migrations-KU4V6T73.cjs.map → migrations-6M6772UC.cjs.map} +1 -1
- package/dist/migrations-GZ2HIB4I.js +4 -0
- package/dist/{migrations-JAHMI5MK.js.map → migrations-GZ2HIB4I.js.map} +1 -1
- package/dist/{plugin-bootstrap-BHWQ2df8.d.cts → plugin-bootstrap-CfVILQeP.d.ts} +1 -1
- package/dist/{plugin-bootstrap-Bj4fxX1q.d.ts → plugin-bootstrap-RY5pkoOT.d.cts} +1 -1
- package/dist/plugins.cjs +40 -40
- package/dist/plugins.js +3 -3
- package/dist/rbac-TFUOYIVN.cjs +14 -0
- package/dist/{rbac-AORZ6O3N.cjs.map → rbac-TFUOYIVN.cjs.map} +1 -1
- package/dist/rbac-XSNP76CV.js +5 -0
- package/dist/{rbac-P44772FP.js.map → rbac-XSNP76CV.js.map} +1 -1
- package/dist/routes.cjs +31 -30
- package/dist/routes.d.cts +3 -5
- package/dist/routes.d.ts +3 -5
- package/dist/routes.js +11 -10
- package/dist/services.cjs +30 -30
- package/dist/services.d.cts +9 -2
- package/dist/services.d.ts +9 -2
- package/dist/services.js +3 -3
- package/dist/types.d.cts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/utils.cjs +12 -12
- package/dist/utils.d.cts +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +2 -2
- package/package.json +3 -3
- package/dist/chunk-2D3A4X52.js.map +0 -1
- package/dist/chunk-2OXFMMA3.js.map +0 -1
- package/dist/chunk-2XAQTPAE.js.map +0 -1
- package/dist/chunk-36Z3AKX3.cjs.map +0 -1
- package/dist/chunk-6OA77UM7.cjs.map +0 -1
- package/dist/chunk-7P5OCUPS.js.map +0 -1
- package/dist/chunk-BDQ55MWV.js.map +0 -1
- package/dist/chunk-BJ6NJL2E.cjs.map +0 -1
- package/dist/chunk-CWIGQYRR.js.map +0 -1
- package/dist/chunk-D7RLBBHE.js.map +0 -1
- package/dist/chunk-E7E3NL3Y.cjs.map +0 -1
- package/dist/chunk-JCBDXEY2.cjs.map +0 -1
- package/dist/chunk-MOGK3U4A.cjs.map +0 -1
- package/dist/chunk-YAURVGUK.cjs.map +0 -1
- package/dist/config-4TIHSNW6.js +0 -6
- package/dist/migrations-JAHMI5MK.js +0 -4
- package/dist/migrations-KU4V6T73.cjs +0 -13
- package/dist/rbac-AORZ6O3N.cjs +0 -14
- package/dist/rbac-P44772FP.js +0 -5
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var chunkXWVDSM2L_cjs = require('./chunk-XWVDSM2L.cjs');
|
|
4
3
|
var chunkTT3TQSCZ_cjs = require('./chunk-TT3TQSCZ.cjs');
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
4
|
+
var chunkFZGIU5AZ_cjs = require('./chunk-FZGIU5AZ.cjs');
|
|
5
|
+
var chunkXWVDSM2L_cjs = require('./chunk-XWVDSM2L.cjs');
|
|
6
|
+
var chunkC5LDQ3SH_cjs = require('./chunk-C5LDQ3SH.cjs');
|
|
7
|
+
var chunkBRKXMRMB_cjs = require('./chunk-BRKXMRMB.cjs');
|
|
8
|
+
var chunkOLEOKHDX_cjs = require('./chunk-OLEOKHDX.cjs');
|
|
8
9
|
var chunkKIGVVO6N_cjs = require('./chunk-KIGVVO6N.cjs');
|
|
9
|
-
var
|
|
10
|
-
var
|
|
10
|
+
var chunk4DHPR7KR_cjs = require('./chunk-4DHPR7KR.cjs');
|
|
11
|
+
var chunkPAS7GZBS_cjs = require('./chunk-PAS7GZBS.cjs');
|
|
11
12
|
var chunkOUBUS74I_cjs = require('./chunk-OUBUS74I.cjs');
|
|
12
13
|
var chunkMI2YXCK4_cjs = require('./chunk-MI2YXCK4.cjs');
|
|
13
|
-
var
|
|
14
|
+
var chunkKWQNB6UM_cjs = require('./chunk-KWQNB6UM.cjs');
|
|
14
15
|
var chunkJ6JTWD2A_cjs = require('./chunk-J6JTWD2A.cjs');
|
|
15
|
-
var
|
|
16
|
+
var chunkSFGYZUWU_cjs = require('./chunk-SFGYZUWU.cjs');
|
|
16
17
|
var chunkRCQ2HIQD_cjs = require('./chunk-RCQ2HIQD.cjs');
|
|
17
|
-
var
|
|
18
|
+
var chunkXZUEGFXE_cjs = require('./chunk-XZUEGFXE.cjs');
|
|
18
19
|
var chunkMNWKYY5E_cjs = require('./chunk-MNWKYY5E.cjs');
|
|
19
20
|
var hono = require('hono');
|
|
20
21
|
var zod = require('zod');
|
|
@@ -272,7 +273,7 @@ function getDocumentRequestContext(c) {
|
|
|
272
273
|
|
|
273
274
|
// src/routes/api-documents.ts
|
|
274
275
|
async function aclAllowsRead(db, tenantId, principalSet, row, preloadedType) {
|
|
275
|
-
const docType = preloadedType ?? await new
|
|
276
|
+
const docType = preloadedType ?? await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(row.type_id);
|
|
276
277
|
if (!docType) return false;
|
|
277
278
|
return new DocumentRepository(db, tenantId).isAllowed(principalSet, row.root_id, "read", docType.settings);
|
|
278
279
|
}
|
|
@@ -290,7 +291,7 @@ apiDocumentsRoutes.get("/", async (c) => {
|
|
|
290
291
|
if (!typeId) {
|
|
291
292
|
return c.json({ error: "type query parameter is required" }, 400);
|
|
292
293
|
}
|
|
293
|
-
const registry = new
|
|
294
|
+
const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db);
|
|
294
295
|
const docType = await registry.findById(typeId);
|
|
295
296
|
if (!docType || !docType.isActive) {
|
|
296
297
|
return c.json({ error: "Unknown document type" }, 400);
|
|
@@ -372,7 +373,7 @@ apiDocumentsRoutes.get("/root/:rootId", async (c) => {
|
|
|
372
373
|
AND (expires_at IS NULL OR expires_at > ?) LIMIT 1`
|
|
373
374
|
).bind(rootId, now, now).first();
|
|
374
375
|
if (!row) return c.json({ error: "Not found" }, 404);
|
|
375
|
-
const docType = await new
|
|
376
|
+
const docType = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(row.type_id);
|
|
376
377
|
const effTenant = effectiveTenantForType(tenantId, docType?.settings);
|
|
377
378
|
if (row.tenant_id !== effTenant) return c.json({ error: "Not found" }, 404);
|
|
378
379
|
if (!await aclAllowsRead(db, effTenant, principalSet, row, docType)) {
|
|
@@ -408,7 +409,7 @@ apiDocumentsRoutes.get("/:id", async (c) => {
|
|
|
408
409
|
AND (expires_at IS NULL OR expires_at > ?) LIMIT 1`
|
|
409
410
|
).bind(id, now, now).first();
|
|
410
411
|
if (!row) return c.json({ error: "Not found" }, 404);
|
|
411
|
-
const docType = await new
|
|
412
|
+
const docType = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(row.type_id);
|
|
412
413
|
const effTenant = effectiveTenantForType(tenantId, docType?.settings);
|
|
413
414
|
if (row.tenant_id !== effTenant) return c.json({ error: "Not found" }, 404);
|
|
414
415
|
if (!await aclAllowsRead(db, effTenant, principalSet, row, docType)) {
|
|
@@ -478,17 +479,17 @@ async function resolveDocScope(c, db, by, opts = {}) {
|
|
|
478
479
|
const draft = opts.currentDraftOnly ? " AND is_current_draft = 1" : "";
|
|
479
480
|
const row = await db.prepare(`SELECT type_id, root_id, tenant_id FROM documents WHERE ${col} = ?${draft} LIMIT 1`).bind(val).first();
|
|
480
481
|
if (!row) return null;
|
|
481
|
-
const docType = await new
|
|
482
|
+
const docType = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(row.type_id);
|
|
482
483
|
const tenantId = effectiveTenantForType(getRequestTenant(c), docType?.settings);
|
|
483
484
|
if (row.tenant_id !== tenantId) return null;
|
|
484
485
|
return { typeId: row.type_id, rootId: row.root_id, tenantId, docType };
|
|
485
486
|
}
|
|
486
487
|
var adminDocumentsRoutes = new hono.Hono();
|
|
487
|
-
adminDocumentsRoutes.use("*",
|
|
488
|
-
adminDocumentsRoutes.use("*",
|
|
488
|
+
adminDocumentsRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
|
|
489
|
+
adminDocumentsRoutes.use("*", chunkBRKXMRMB_cjs.requireRole(["admin", "editor"]));
|
|
489
490
|
adminDocumentsRoutes.get("/types", async (c) => {
|
|
490
491
|
try {
|
|
491
|
-
const registry = new
|
|
492
|
+
const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(c.env.DB);
|
|
492
493
|
const types = await registry.findAll();
|
|
493
494
|
return c.json({ data: types });
|
|
494
495
|
} catch (error) {
|
|
@@ -516,7 +517,7 @@ adminDocumentsRoutes.get("/", async (c) => {
|
|
|
516
517
|
if (!typeId) {
|
|
517
518
|
return c.json({ error: "type query parameter is required" }, 400);
|
|
518
519
|
}
|
|
519
|
-
const registry = new
|
|
520
|
+
const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db);
|
|
520
521
|
const docType = await registry.findById(typeId);
|
|
521
522
|
if (!docType || !docType.isActive) {
|
|
522
523
|
return c.json({ error: "Unknown document type" }, 400);
|
|
@@ -627,7 +628,7 @@ adminDocumentsRoutes.post("/", async (c) => {
|
|
|
627
628
|
const input = validation.data;
|
|
628
629
|
const db = c.env.DB;
|
|
629
630
|
const user = c.get("user");
|
|
630
|
-
const registry = new
|
|
631
|
+
const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db);
|
|
631
632
|
const docType = await registry.findById(input.typeId);
|
|
632
633
|
if (!docType || !docType.isActive) {
|
|
633
634
|
return c.json({ error: "Unknown document type" }, 400);
|
|
@@ -635,7 +636,7 @@ adminDocumentsRoutes.post("/", async (c) => {
|
|
|
635
636
|
const createDenied = await denyIfNotAllowed(c, db, "", "create", docType.settings);
|
|
636
637
|
if (createDenied) return createDenied;
|
|
637
638
|
const tenantId = effectiveTenantForType(getRequestTenant(c), docType.settings);
|
|
638
|
-
const svc = new
|
|
639
|
+
const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, {
|
|
639
640
|
queryableFields: docType.queryableFields,
|
|
640
641
|
typeSchemaVersion: docType.schemaVersion,
|
|
641
642
|
maxVersionsPerRoot: docType.settings.maxVersionsPerRoot,
|
|
@@ -673,7 +674,7 @@ adminDocumentsRoutes.put("/:rootId", async (c) => {
|
|
|
673
674
|
const docType = scope.docType;
|
|
674
675
|
const updateDenied = await denyIfNotAllowed(c, db, rootId, "update", docType?.settings, scope.tenantId);
|
|
675
676
|
if (updateDenied) return updateDenied;
|
|
676
|
-
const svc = new
|
|
677
|
+
const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, {
|
|
677
678
|
queryableFields: docType?.queryableFields ?? [],
|
|
678
679
|
typeSchemaVersion: docType?.schemaVersion,
|
|
679
680
|
maxVersionsPerRoot: docType?.settings.maxVersionsPerRoot,
|
|
@@ -698,7 +699,7 @@ adminDocumentsRoutes.post("/:id/publish", async (c) => {
|
|
|
698
699
|
const docType = scope.docType;
|
|
699
700
|
const publishDenied = await denyIfNotAllowed(c, db, scope.rootId, "publish", docType?.settings, scope.tenantId);
|
|
700
701
|
if (publishDenied) return publishDenied;
|
|
701
|
-
const svc = new
|
|
702
|
+
const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, {
|
|
702
703
|
queryableFields: docType?.queryableFields ?? [],
|
|
703
704
|
typeSchemaVersion: docType?.schemaVersion,
|
|
704
705
|
tenantId: scope.tenantId,
|
|
@@ -721,7 +722,7 @@ adminDocumentsRoutes.post("/:id/unpublish", async (c) => {
|
|
|
721
722
|
const docType = scope.docType;
|
|
722
723
|
const unpublishDenied = await denyIfNotAllowed(c, db, scope.rootId, "publish", docType?.settings, scope.tenantId);
|
|
723
724
|
if (unpublishDenied) return unpublishDenied;
|
|
724
|
-
const svc = new
|
|
725
|
+
const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, {
|
|
725
726
|
queryableFields: docType?.queryableFields ?? [],
|
|
726
727
|
tenantId: scope.tenantId
|
|
727
728
|
});
|
|
@@ -743,7 +744,7 @@ adminDocumentsRoutes.delete("/:id", async (c) => {
|
|
|
743
744
|
const docType = scope.docType;
|
|
744
745
|
const deleteDenied = await denyIfNotAllowed(c, db, scope.rootId, "delete", docType?.settings, scope.tenantId);
|
|
745
746
|
if (deleteDenied) return deleteDenied;
|
|
746
|
-
const svc = new
|
|
747
|
+
const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, { queryableFields: docType?.queryableFields ?? [], tenantId: scope.tenantId });
|
|
747
748
|
if (docType?.settings.pii) {
|
|
748
749
|
if (scope.rootId) await svc.erase(scope.rootId, scope.tenantId);
|
|
749
750
|
} else {
|
|
@@ -759,7 +760,7 @@ adminDocumentsRoutes.post("/types/:typeId/reindex", async (c) => {
|
|
|
759
760
|
try {
|
|
760
761
|
const { typeId } = c.req.param();
|
|
761
762
|
const db = c.env.DB;
|
|
762
|
-
const registry = new
|
|
763
|
+
const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db);
|
|
763
764
|
const docType = await registry.findById(typeId);
|
|
764
765
|
if (!docType) return c.json({ error: "Unknown document type" }, 400);
|
|
765
766
|
const reindexTenant = effectiveTenantForType(getRequestTenant(c), docType.settings);
|
|
@@ -845,6 +846,34 @@ async function dispatchHookEvent(c, event, payload, mode = "fire-and-forget") {
|
|
|
845
846
|
return hooks.dispatch(event, payload);
|
|
846
847
|
}
|
|
847
848
|
|
|
849
|
+
// src/plugins/cache/services/swr.ts
|
|
850
|
+
var STALE_TTL_MS = 3e4;
|
|
851
|
+
var staleMap = /* @__PURE__ */ new Map();
|
|
852
|
+
function markStale(cacheKey, data, collection) {
|
|
853
|
+
staleMap.set(cacheKey, {
|
|
854
|
+
data,
|
|
855
|
+
collection,
|
|
856
|
+
expiresAt: Date.now() + STALE_TTL_MS
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
function getAndConsumeStale(cacheKey) {
|
|
860
|
+
const entry = staleMap.get(cacheKey);
|
|
861
|
+
if (!entry) return null;
|
|
862
|
+
if (Date.now() > entry.expiresAt) {
|
|
863
|
+
staleMap.delete(cacheKey);
|
|
864
|
+
return null;
|
|
865
|
+
}
|
|
866
|
+
staleMap.delete(cacheKey);
|
|
867
|
+
return entry.data;
|
|
868
|
+
}
|
|
869
|
+
function swrStats() {
|
|
870
|
+
const now = Date.now();
|
|
871
|
+
for (const [key, entry] of staleMap.entries()) {
|
|
872
|
+
if (now > entry.expiresAt) staleMap.delete(key);
|
|
873
|
+
}
|
|
874
|
+
return { count: staleMap.size };
|
|
875
|
+
}
|
|
876
|
+
|
|
848
877
|
// src/plugins/core-plugins/global-variables-plugin/variable-resolver.ts
|
|
849
878
|
var TOKEN_PATTERN = /\{([a-z0-9_]+)\}/g;
|
|
850
879
|
function resolveVariables(text, variables) {
|
|
@@ -913,13 +942,13 @@ async function resolveContentVariables(contentData, db) {
|
|
|
913
942
|
// src/routes/api-content-crud.ts
|
|
914
943
|
var apiContentCrudRoutes = new hono.Hono();
|
|
915
944
|
async function resolveDocBacking(db, collectionIdOrName) {
|
|
916
|
-
const registry =
|
|
945
|
+
const registry = chunk4DHPR7KR_cjs.getCollectionRegistry();
|
|
917
946
|
const record = registry.getBySlugOrName(collectionIdOrName) ?? registry.getById(collectionIdOrName);
|
|
918
947
|
if (record) {
|
|
919
|
-
const docType2 = await new
|
|
948
|
+
const docType2 = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(record.name);
|
|
920
949
|
return docType2 ? { coll: { id: record.id, name: record.name }, docType: docType2 } : null;
|
|
921
950
|
}
|
|
922
|
-
const docType = await new
|
|
951
|
+
const docType = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(collectionIdOrName);
|
|
923
952
|
if (docType) {
|
|
924
953
|
return { coll: { id: collectionIdOrName, name: collectionIdOrName }, docType };
|
|
925
954
|
}
|
|
@@ -962,7 +991,7 @@ apiContentCrudRoutes.get("/check-slug", async (c) => {
|
|
|
962
991
|
}, 500);
|
|
963
992
|
}
|
|
964
993
|
});
|
|
965
|
-
apiContentCrudRoutes.get("/:id",
|
|
994
|
+
apiContentCrudRoutes.get("/:id", chunkBRKXMRMB_cjs.optionalAuth(), async (c) => {
|
|
966
995
|
try {
|
|
967
996
|
const id = c.req.param("id");
|
|
968
997
|
const db = c.env.DB;
|
|
@@ -972,7 +1001,7 @@ apiContentCrudRoutes.get("/:id", chunkE7E3NL3Y_cjs.optionalAuth(), async (c) =>
|
|
|
972
1001
|
).bind(id, getRequestTenant(c)).first();
|
|
973
1002
|
let transformedContent;
|
|
974
1003
|
if (docRow) {
|
|
975
|
-
const coll =
|
|
1004
|
+
const coll = chunk4DHPR7KR_cjs.getCollectionRegistry().getByName(docRow.type_id);
|
|
976
1005
|
transformedContent = {
|
|
977
1006
|
id: docRow.root_id,
|
|
978
1007
|
title: docRow.title,
|
|
@@ -981,8 +1010,8 @@ apiContentCrudRoutes.get("/:id", chunkE7E3NL3Y_cjs.optionalAuth(), async (c) =>
|
|
|
981
1010
|
collectionId: coll?.id ?? docRow.type_id,
|
|
982
1011
|
data: docRow.data ? JSON.parse(docRow.data) : {},
|
|
983
1012
|
// D29: document timestamps are SECONDS; legacy `content` API contract is MILLISECONDS.
|
|
984
|
-
created_at:
|
|
985
|
-
updated_at:
|
|
1013
|
+
created_at: chunkOLEOKHDX_cjs.documentSecondsToMs(docRow.created_at),
|
|
1014
|
+
updated_at: chunkOLEOKHDX_cjs.documentSecondsToMs(docRow.updated_at)
|
|
986
1015
|
};
|
|
987
1016
|
} else {
|
|
988
1017
|
return c.json({ error: "Content not found" }, 404);
|
|
@@ -1032,7 +1061,7 @@ apiContentCrudRoutes.get("/:id", chunkE7E3NL3Y_cjs.optionalAuth(), async (c) =>
|
|
|
1032
1061
|
}, 500);
|
|
1033
1062
|
}
|
|
1034
1063
|
});
|
|
1035
|
-
apiContentCrudRoutes.post("/",
|
|
1064
|
+
apiContentCrudRoutes.post("/", chunkBRKXMRMB_cjs.requireAuth(), chunkBRKXMRMB_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
1036
1065
|
try {
|
|
1037
1066
|
const db = c.env.DB;
|
|
1038
1067
|
const user = c.get("user");
|
|
@@ -1066,7 +1095,7 @@ apiContentCrudRoutes.post("/", chunkE7E3NL3Y_cjs.requireAuth(), chunkE7E3NL3Y_cj
|
|
|
1066
1095
|
return c.json({ error: "Write cancelled by plugin", details: String(err) }, 400);
|
|
1067
1096
|
}
|
|
1068
1097
|
const tenantId = getRequestTenant(c);
|
|
1069
|
-
const svc = new
|
|
1098
|
+
const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, {
|
|
1070
1099
|
queryableFields: backing.docType.queryableFields ?? [],
|
|
1071
1100
|
typeSchemaVersion: backing.docType.schemaVersion ?? 1,
|
|
1072
1101
|
maxVersionsPerRoot: backing.docType.settings?.maxVersionsPerRoot ?? 50,
|
|
@@ -1085,7 +1114,7 @@ apiContentCrudRoutes.post("/", chunkE7E3NL3Y_cjs.requireAuth(), chunkE7E3NL3Y_cj
|
|
|
1085
1114
|
}),
|
|
1086
1115
|
user?.userId
|
|
1087
1116
|
);
|
|
1088
|
-
const cache =
|
|
1117
|
+
const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
|
|
1089
1118
|
await cache.invalidate("api:content-filtered:*");
|
|
1090
1119
|
await cache.invalidate(`api:collection-content-filtered:${backing.coll.name}:*`);
|
|
1091
1120
|
dispatchHookEvent(
|
|
@@ -1095,7 +1124,7 @@ apiContentCrudRoutes.post("/", chunkE7E3NL3Y_cjs.requireAuth(), chunkE7E3NL3Y_cj
|
|
|
1095
1124
|
"fire-and-forget"
|
|
1096
1125
|
);
|
|
1097
1126
|
return c.json({
|
|
1098
|
-
data: { id: doc.rootId, title: doc.title, slug: doc.slug, status: doc.status, collectionId: backing.coll.id, data: doc.data, created_at:
|
|
1127
|
+
data: { id: doc.rootId, title: doc.title, slug: doc.slug, status: doc.status, collectionId: backing.coll.id, data: doc.data, created_at: chunkOLEOKHDX_cjs.documentSecondsToMs(doc.createdAt), updated_at: chunkOLEOKHDX_cjs.documentSecondsToMs(doc.updatedAt) }
|
|
1099
1128
|
}, 201);
|
|
1100
1129
|
}
|
|
1101
1130
|
return c.json({ error: "Collection is not document-backed" }, 400);
|
|
@@ -1107,7 +1136,7 @@ apiContentCrudRoutes.post("/", chunkE7E3NL3Y_cjs.requireAuth(), chunkE7E3NL3Y_cj
|
|
|
1107
1136
|
}, 500);
|
|
1108
1137
|
}
|
|
1109
1138
|
});
|
|
1110
|
-
apiContentCrudRoutes.put("/:id",
|
|
1139
|
+
apiContentCrudRoutes.put("/:id", chunkBRKXMRMB_cjs.requireAuth(), chunkBRKXMRMB_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
1111
1140
|
try {
|
|
1112
1141
|
const id = c.req.param("id");
|
|
1113
1142
|
const db = c.env.DB;
|
|
@@ -1129,8 +1158,8 @@ apiContentCrudRoutes.put("/:id", chunkE7E3NL3Y_cjs.requireAuth(), chunkE7E3NL3Y_
|
|
|
1129
1158
|
} catch (err) {
|
|
1130
1159
|
return c.json({ error: "Write cancelled by plugin", details: String(err) }, 400);
|
|
1131
1160
|
}
|
|
1132
|
-
const docType = await new
|
|
1133
|
-
const svc = new
|
|
1161
|
+
const docType = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(docRow.type_id);
|
|
1162
|
+
const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, {
|
|
1134
1163
|
queryableFields: docType?.queryableFields ?? [],
|
|
1135
1164
|
typeSchemaVersion: docType?.schemaVersion ?? 1,
|
|
1136
1165
|
maxVersionsPerRoot: docType?.settings?.maxVersionsPerRoot ?? 50,
|
|
@@ -1149,10 +1178,10 @@ apiContentCrudRoutes.put("/:id", chunkE7E3NL3Y_cjs.requireAuth(), chunkE7E3NL3Y_
|
|
|
1149
1178
|
} else if (body.status === "draft" && pub) {
|
|
1150
1179
|
await svc.unpublish(pub.id);
|
|
1151
1180
|
}
|
|
1152
|
-
const cache =
|
|
1181
|
+
const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
|
|
1153
1182
|
await cache.invalidate("api:content-filtered:*");
|
|
1154
1183
|
await cache.invalidate(`api:collection-content-filtered:${docRow.type_id}:*`);
|
|
1155
|
-
const coll =
|
|
1184
|
+
const coll = chunk4DHPR7KR_cjs.getCollectionRegistry().getByName(docRow.type_id);
|
|
1156
1185
|
const saved = await db.prepare("SELECT * FROM documents WHERE id = ?").bind(newDraft.id).first();
|
|
1157
1186
|
const savedData = saved?.data ? JSON.parse(saved.data) : {};
|
|
1158
1187
|
dispatchHookEvent(c, "content:after:update", { collection: docRow.type_id, id, data: savedData, user: actor }, "fire-and-forget");
|
|
@@ -1161,7 +1190,7 @@ apiContentCrudRoutes.put("/:id", chunkE7E3NL3Y_cjs.requireAuth(), chunkE7E3NL3Y_
|
|
|
1161
1190
|
dispatchHookEvent(c, "content:after:publish", { collection: docRow.type_id, id, data: savedData, user: actor }, "fire-and-forget");
|
|
1162
1191
|
}
|
|
1163
1192
|
return c.json({
|
|
1164
|
-
data: { id: saved.root_id, title: saved.title, slug: saved.slug, status: saved.status, collectionId: coll?.id ?? docRow.type_id, data: savedData, created_at:
|
|
1193
|
+
data: { id: saved.root_id, title: saved.title, slug: saved.slug, status: saved.status, collectionId: coll?.id ?? docRow.type_id, data: savedData, created_at: chunkOLEOKHDX_cjs.documentSecondsToMs(saved.created_at), updated_at: chunkOLEOKHDX_cjs.documentSecondsToMs(saved.updated_at) }
|
|
1165
1194
|
});
|
|
1166
1195
|
}
|
|
1167
1196
|
return c.json({ error: "Content not found" }, 404);
|
|
@@ -1173,7 +1202,7 @@ apiContentCrudRoutes.put("/:id", chunkE7E3NL3Y_cjs.requireAuth(), chunkE7E3NL3Y_
|
|
|
1173
1202
|
}, 500);
|
|
1174
1203
|
}
|
|
1175
1204
|
});
|
|
1176
|
-
apiContentCrudRoutes.delete("/:id",
|
|
1205
|
+
apiContentCrudRoutes.delete("/:id", chunkBRKXMRMB_cjs.requireAuth(), chunkBRKXMRMB_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
1177
1206
|
try {
|
|
1178
1207
|
const id = c.req.param("id");
|
|
1179
1208
|
const db = c.env.DB;
|
|
@@ -1189,7 +1218,7 @@ apiContentCrudRoutes.delete("/:id", chunkE7E3NL3Y_cjs.requireAuth(), chunkE7E3NL
|
|
|
1189
1218
|
}
|
|
1190
1219
|
const now = Math.floor(Date.now() / 1e3);
|
|
1191
1220
|
await db.prepare("UPDATE documents SET deleted_at = ?, updated_at = ? WHERE root_id = ? AND tenant_id = ?").bind(now, now, id, tenantId).run();
|
|
1192
|
-
const cache =
|
|
1221
|
+
const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
|
|
1193
1222
|
await cache.invalidate("api:content-filtered:*");
|
|
1194
1223
|
await cache.invalidate(`api:collection-content-filtered:${docRow.type_id}:*`);
|
|
1195
1224
|
dispatchHookEvent(c, "content:after:delete", { collection: docRow.type_id, id, data: {}, user: actor }, "fire-and-forget");
|
|
@@ -1213,7 +1242,7 @@ function isAnonPrincipal(principalSet) {
|
|
|
1213
1242
|
async function typeReadAllowed(db, principalSet, docType, typeName) {
|
|
1214
1243
|
const perms = new DocumentPermissionsService(db);
|
|
1215
1244
|
if (perms.isAllowedSync(principalSet, [], "read", docType?.settings ?? {})) return true;
|
|
1216
|
-
const rbac = new
|
|
1245
|
+
const rbac = new chunkOLEOKHDX_cjs.RbacService(db);
|
|
1217
1246
|
let anyRbacRoleFound = false;
|
|
1218
1247
|
for (const p of principalSet) {
|
|
1219
1248
|
if (p.type !== "role") continue;
|
|
@@ -1302,8 +1331,8 @@ function mapDocRowToContent(row, collectionId) {
|
|
|
1302
1331
|
collectionId,
|
|
1303
1332
|
data: row.data ? JSON.parse(row.data) : {},
|
|
1304
1333
|
// D29: document timestamps are SECONDS; the legacy `content` API contract is MILLISECONDS.
|
|
1305
|
-
created_at:
|
|
1306
|
-
updated_at:
|
|
1334
|
+
created_at: chunkOLEOKHDX_cjs.documentSecondsToMs(row.created_at),
|
|
1335
|
+
updated_at: chunkOLEOKHDX_cjs.documentSecondsToMs(row.updated_at)
|
|
1307
1336
|
};
|
|
1308
1337
|
}
|
|
1309
1338
|
function projectFields(item, fields) {
|
|
@@ -1342,7 +1371,8 @@ apiRoutes.use("*", async (c, next) => {
|
|
|
1342
1371
|
c.header("X-Response-Time", `${totalTime}ms`);
|
|
1343
1372
|
});
|
|
1344
1373
|
apiRoutes.use("*", async (c, next) => {
|
|
1345
|
-
const
|
|
1374
|
+
const bypass = c.req.header("Cache-Control") === "no-cache";
|
|
1375
|
+
const cacheEnabled = !bypass && await chunk4DHPR7KR_cjs.isPluginActive(c.env.DB, "core-cache");
|
|
1346
1376
|
c.set("cacheEnabled", cacheEnabled);
|
|
1347
1377
|
await next();
|
|
1348
1378
|
});
|
|
@@ -1365,7 +1395,7 @@ apiRoutes.get("/", (c) => {
|
|
|
1365
1395
|
openapi: "3.0.0",
|
|
1366
1396
|
info: {
|
|
1367
1397
|
title: "SonicJS AI API",
|
|
1368
|
-
version:
|
|
1398
|
+
version: chunkXZUEGFXE_cjs.getCoreVersion(),
|
|
1369
1399
|
description: "RESTful API for SonicJS headless CMS - a modern, AI-powered content management system built on Cloudflare Workers",
|
|
1370
1400
|
contact: {
|
|
1371
1401
|
name: "SonicJS Support",
|
|
@@ -1769,7 +1799,7 @@ apiRoutes.get("/collections", async (c) => {
|
|
|
1769
1799
|
try {
|
|
1770
1800
|
const db = c.env.DB;
|
|
1771
1801
|
const cacheEnabled = c.get("cacheEnabled");
|
|
1772
|
-
const cache =
|
|
1802
|
+
const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
|
|
1773
1803
|
const cacheKey = cache.generateKey("collections", "all");
|
|
1774
1804
|
if (cacheEnabled) {
|
|
1775
1805
|
const cacheResult = await cache.getWithSource(cacheKey);
|
|
@@ -1795,8 +1825,8 @@ apiRoutes.get("/collections", async (c) => {
|
|
|
1795
1825
|
}
|
|
1796
1826
|
c.header("X-Cache-Status", "MISS");
|
|
1797
1827
|
c.header("X-Cache-Source", "registry");
|
|
1798
|
-
const records =
|
|
1799
|
-
const transformedResults = records.map(
|
|
1828
|
+
const records = chunk4DHPR7KR_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal);
|
|
1829
|
+
const transformedResults = records.map(chunk4DHPR7KR_cjs.collectionRecordToRow);
|
|
1800
1830
|
const responseData = {
|
|
1801
1831
|
data: transformedResults,
|
|
1802
1832
|
meta: addTimingMeta(c, {
|
|
@@ -1817,7 +1847,7 @@ apiRoutes.get("/collections", async (c) => {
|
|
|
1817
1847
|
return c.json({ error: "Failed to fetch collections" }, 500);
|
|
1818
1848
|
}
|
|
1819
1849
|
});
|
|
1820
|
-
apiRoutes.get("/content",
|
|
1850
|
+
apiRoutes.get("/content", chunkBRKXMRMB_cjs.optionalAuth(), async (c) => {
|
|
1821
1851
|
const executionStart = Date.now();
|
|
1822
1852
|
try {
|
|
1823
1853
|
const db = c.env.DB;
|
|
@@ -1831,7 +1861,7 @@ apiRoutes.get("/content", chunkE7E3NL3Y_cjs.optionalAuth(), async (c) => {
|
|
|
1831
1861
|
const collIdByName = /* @__PURE__ */ new Map();
|
|
1832
1862
|
let typeId;
|
|
1833
1863
|
let typeIds;
|
|
1834
|
-
const registry =
|
|
1864
|
+
const registry = chunk4DHPR7KR_cjs.getCollectionRegistry();
|
|
1835
1865
|
if (queryParams.collection) {
|
|
1836
1866
|
const collectionName = queryParams.collection;
|
|
1837
1867
|
const record = registry.getByName(collectionName);
|
|
@@ -1861,11 +1891,11 @@ apiRoutes.get("/content", chunkE7E3NL3Y_cjs.optionalAuth(), async (c) => {
|
|
|
1861
1891
|
return r.name;
|
|
1862
1892
|
});
|
|
1863
1893
|
}
|
|
1864
|
-
const filter =
|
|
1894
|
+
const filter = chunkSFGYZUWU_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
|
|
1865
1895
|
const normalizedFilter = augmentFilterForDocuments(filter, { typeId, typeIds, role });
|
|
1866
1896
|
if (!normalizedFilter.limit) normalizedFilter.limit = 50;
|
|
1867
1897
|
normalizedFilter.limit = Math.min(normalizedFilter.limit, 1e3);
|
|
1868
|
-
const builder = new
|
|
1898
|
+
const builder = new chunkSFGYZUWU_cjs.QueryFilterBuilder();
|
|
1869
1899
|
const queryResult = builder.build("documents", normalizedFilter);
|
|
1870
1900
|
if (queryResult.errors.length > 0) {
|
|
1871
1901
|
return c.json({
|
|
@@ -1873,8 +1903,8 @@ apiRoutes.get("/content", chunkE7E3NL3Y_cjs.optionalAuth(), async (c) => {
|
|
|
1873
1903
|
details: queryResult.errors
|
|
1874
1904
|
}, 400);
|
|
1875
1905
|
}
|
|
1876
|
-
const cacheEnabled = c.get("cacheEnabled") &&
|
|
1877
|
-
const cache =
|
|
1906
|
+
const cacheEnabled = c.get("cacheEnabled") && !cNeedsAcl;
|
|
1907
|
+
const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
|
|
1878
1908
|
const cacheKey = cache.generateKey("content-filtered", JSON.stringify({ filter: normalizedFilter, query: queryResult.sql }));
|
|
1879
1909
|
if (cacheEnabled) {
|
|
1880
1910
|
const cacheResult = await cache.getWithSource(cacheKey);
|
|
@@ -1895,8 +1925,20 @@ apiRoutes.get("/content", chunkE7E3NL3Y_cjs.optionalAuth(), async (c) => {
|
|
|
1895
1925
|
}
|
|
1896
1926
|
}, executionStart)
|
|
1897
1927
|
};
|
|
1928
|
+
chunkFZGIU5AZ_cjs.recordCatalogRequest({ cacheKey, collection: typeId ?? null, path: c.req.path, queryString: c.req.raw.url.split("?")[1] ?? "", source: cacheResult.source });
|
|
1929
|
+
chunkFZGIU5AZ_cjs.scheduleKvWrite(cacheKey, c.executionCtx);
|
|
1898
1930
|
return c.json(dataWithMeta);
|
|
1899
1931
|
}
|
|
1932
|
+
const swrData = getAndConsumeStale(cacheKey);
|
|
1933
|
+
if (swrData) {
|
|
1934
|
+
c.header("X-Cache-Status", "STALE");
|
|
1935
|
+
c.header("X-Cache-Source", "swr");
|
|
1936
|
+
chunkFZGIU5AZ_cjs.recordCatalogRequest({ cacheKey, collection: typeId ?? null, path: c.req.path, queryString: c.req.raw.url.split("?")[1] ?? "", source: "swr" });
|
|
1937
|
+
chunkFZGIU5AZ_cjs.scheduleKvWrite(cacheKey, c.executionCtx);
|
|
1938
|
+
return c.json({ ...swrData, meta: addTimingMeta(c, { ...swrData.meta, cache: { hit: true, source: "swr", stale: true } }, executionStart) });
|
|
1939
|
+
}
|
|
1940
|
+
chunkFZGIU5AZ_cjs.recordCatalogRequest({ cacheKey, collection: typeId ?? null, path: c.req.path, queryString: c.req.raw.url.split("?")[1] ?? "", source: "miss" });
|
|
1941
|
+
chunkFZGIU5AZ_cjs.scheduleKvWrite(cacheKey, c.executionCtx);
|
|
1900
1942
|
}
|
|
1901
1943
|
c.header("X-Cache-Status", "MISS");
|
|
1902
1944
|
c.header("X-Cache-Source", "database");
|
|
@@ -1905,7 +1947,7 @@ apiRoutes.get("/content", chunkE7E3NL3Y_cjs.optionalAuth(), async (c) => {
|
|
|
1905
1947
|
const { results } = await boundStmt.all();
|
|
1906
1948
|
let aclResults = results;
|
|
1907
1949
|
if (cNeedsAcl) {
|
|
1908
|
-
const typeReg = new
|
|
1950
|
+
const typeReg = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db);
|
|
1909
1951
|
const repo = new DocumentRepository(db, cTenantId);
|
|
1910
1952
|
const uniqueTypeIds = [...new Set(results.map((r) => r.type_id))];
|
|
1911
1953
|
const typeSettingsMap = /* @__PURE__ */ new Map();
|
|
@@ -1960,13 +2002,13 @@ apiRoutes.get("/content", chunkE7E3NL3Y_cjs.optionalAuth(), async (c) => {
|
|
|
1960
2002
|
}, 500);
|
|
1961
2003
|
}
|
|
1962
2004
|
});
|
|
1963
|
-
apiRoutes.get("/collections/:collection/content",
|
|
2005
|
+
apiRoutes.get("/collections/:collection/content", chunkBRKXMRMB_cjs.optionalAuth(), async (c) => {
|
|
1964
2006
|
const executionStart = Date.now();
|
|
1965
2007
|
try {
|
|
1966
2008
|
const collection = c.req.param("collection");
|
|
1967
2009
|
const db = c.env.DB;
|
|
1968
2010
|
const queryParams = c.req.query();
|
|
1969
|
-
const record =
|
|
2011
|
+
const record = chunk4DHPR7KR_cjs.getCollectionRegistry().getBySlugOrName(collection);
|
|
1970
2012
|
if (!record || record.isActive === false) {
|
|
1971
2013
|
return c.json({ error: "Collection not found" }, 404);
|
|
1972
2014
|
}
|
|
@@ -1978,18 +2020,18 @@ apiRoutes.get("/collections/:collection/content", chunkE7E3NL3Y_cjs.optionalAuth
|
|
|
1978
2020
|
const ccNeedsAcl = !ccAnon && !canReadNonPublicContent(role);
|
|
1979
2021
|
let ccDocType;
|
|
1980
2022
|
if (ccNeedsAcl) {
|
|
1981
|
-
ccDocType = await new
|
|
2023
|
+
ccDocType = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(record.name);
|
|
1982
2024
|
if (!await typeReadAllowed(db, ccPrincipalSet, ccDocType, record.name)) {
|
|
1983
2025
|
return c.json({ error: "Forbidden" }, 403);
|
|
1984
2026
|
}
|
|
1985
2027
|
}
|
|
1986
|
-
const filter =
|
|
2028
|
+
const filter = chunkSFGYZUWU_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
|
|
1987
2029
|
const normalizedFilter = augmentFilterForDocuments(filter, { typeId: collection, role });
|
|
1988
2030
|
if (!normalizedFilter.limit) {
|
|
1989
2031
|
normalizedFilter.limit = 50;
|
|
1990
2032
|
}
|
|
1991
2033
|
normalizedFilter.limit = Math.min(normalizedFilter.limit, 1e3);
|
|
1992
|
-
const builder = new
|
|
2034
|
+
const builder = new chunkSFGYZUWU_cjs.QueryFilterBuilder();
|
|
1993
2035
|
const queryResult = builder.build("documents", normalizedFilter);
|
|
1994
2036
|
if (queryResult.errors.length > 0) {
|
|
1995
2037
|
return c.json({
|
|
@@ -1997,8 +2039,8 @@ apiRoutes.get("/collections/:collection/content", chunkE7E3NL3Y_cjs.optionalAuth
|
|
|
1997
2039
|
details: queryResult.errors
|
|
1998
2040
|
}, 400);
|
|
1999
2041
|
}
|
|
2000
|
-
const cacheEnabled = c.get("cacheEnabled") &&
|
|
2001
|
-
const cache =
|
|
2042
|
+
const cacheEnabled = c.get("cacheEnabled") && !ccNeedsAcl;
|
|
2043
|
+
const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
|
|
2002
2044
|
const includeCollection = queryParams.include?.split(",").map((s) => s.trim()).includes("collection");
|
|
2003
2045
|
const cacheKey = cache.generateKey("collection-content-filtered", `${collection}:${JSON.stringify({ filter: normalizedFilter, query: queryResult.sql, includeCollection })}`);
|
|
2004
2046
|
if (cacheEnabled) {
|
|
@@ -2020,8 +2062,20 @@ apiRoutes.get("/collections/:collection/content", chunkE7E3NL3Y_cjs.optionalAuth
|
|
|
2020
2062
|
}
|
|
2021
2063
|
}, executionStart)
|
|
2022
2064
|
};
|
|
2065
|
+
chunkFZGIU5AZ_cjs.recordCatalogRequest({ cacheKey, collection: collection ?? null, path: c.req.path, queryString: c.req.raw.url.split("?")[1] ?? "", source: cacheResult.source });
|
|
2066
|
+
chunkFZGIU5AZ_cjs.scheduleKvWrite(cacheKey, c.executionCtx);
|
|
2023
2067
|
return c.json(dataWithMeta);
|
|
2024
2068
|
}
|
|
2069
|
+
const swrData = getAndConsumeStale(cacheKey);
|
|
2070
|
+
if (swrData) {
|
|
2071
|
+
c.header("X-Cache-Status", "STALE");
|
|
2072
|
+
c.header("X-Cache-Source", "swr");
|
|
2073
|
+
chunkFZGIU5AZ_cjs.recordCatalogRequest({ cacheKey, collection: collection ?? null, path: c.req.path, queryString: c.req.raw.url.split("?")[1] ?? "", source: "swr" });
|
|
2074
|
+
chunkFZGIU5AZ_cjs.scheduleKvWrite(cacheKey, c.executionCtx);
|
|
2075
|
+
return c.json({ ...swrData, meta: addTimingMeta(c, { ...swrData.meta, cache: { hit: true, source: "swr", stale: true } }, executionStart) });
|
|
2076
|
+
}
|
|
2077
|
+
chunkFZGIU5AZ_cjs.recordCatalogRequest({ cacheKey, collection: collection ?? null, path: c.req.path, queryString: c.req.raw.url.split("?")[1] ?? "", source: "miss" });
|
|
2078
|
+
chunkFZGIU5AZ_cjs.scheduleKvWrite(cacheKey, c.executionCtx);
|
|
2025
2079
|
}
|
|
2026
2080
|
c.header("X-Cache-Status", "MISS");
|
|
2027
2081
|
c.header("X-Cache-Source", "database");
|
|
@@ -2044,7 +2098,7 @@ apiRoutes.get("/collections/:collection/content", chunkE7E3NL3Y_cjs.optionalAuth
|
|
|
2044
2098
|
const responseData = {
|
|
2045
2099
|
data: transformedResults,
|
|
2046
2100
|
meta: addTimingMeta(c, {
|
|
2047
|
-
...includeCollection ? { collection:
|
|
2101
|
+
...includeCollection ? { collection: chunk4DHPR7KR_cjs.collectionRecordToRow(record) } : {},
|
|
2048
2102
|
count: ccAclResults.length,
|
|
2049
2103
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2050
2104
|
// D44: echo the caller's filter with the access policy applied (status=published forced for
|
|
@@ -2069,7 +2123,7 @@ apiRoutes.get("/collections/:collection/content", chunkE7E3NL3Y_cjs.optionalAuth
|
|
|
2069
2123
|
}
|
|
2070
2124
|
});
|
|
2071
2125
|
apiRoutes.route("/content", api_content_crud_default);
|
|
2072
|
-
apiRoutes.get("/:collection",
|
|
2126
|
+
apiRoutes.get("/:collection", chunkBRKXMRMB_cjs.optionalAuth(), async (c) => {
|
|
2073
2127
|
const executionStart = Date.now();
|
|
2074
2128
|
try {
|
|
2075
2129
|
const collection = c.req.param("collection");
|
|
@@ -2077,7 +2131,7 @@ apiRoutes.get("/:collection", chunkE7E3NL3Y_cjs.optionalAuth(), async (c) => {
|
|
|
2077
2131
|
const queryParams = c.req.query();
|
|
2078
2132
|
const projFields = parseFieldsParam(queryParams.fields);
|
|
2079
2133
|
if (queryParams.fields) delete queryParams.fields;
|
|
2080
|
-
const record =
|
|
2134
|
+
const record = chunk4DHPR7KR_cjs.getCollectionRegistry().getBySlugOrName(collection);
|
|
2081
2135
|
if (!record || record.isActive === false) {
|
|
2082
2136
|
return c.json({ error: "Collection not found" }, 404);
|
|
2083
2137
|
}
|
|
@@ -2089,24 +2143,24 @@ apiRoutes.get("/:collection", chunkE7E3NL3Y_cjs.optionalAuth(), async (c) => {
|
|
|
2089
2143
|
const needsAcl = !anon && !canReadNonPublicContent(role);
|
|
2090
2144
|
let docTypeForCheck;
|
|
2091
2145
|
if (needsAcl) {
|
|
2092
|
-
docTypeForCheck = await new
|
|
2146
|
+
docTypeForCheck = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(record.name);
|
|
2093
2147
|
if (!await typeReadAllowed(db, principalSet, docTypeForCheck, record.name)) {
|
|
2094
2148
|
return c.json({ error: "Forbidden" }, 403);
|
|
2095
2149
|
}
|
|
2096
2150
|
}
|
|
2097
|
-
const filter =
|
|
2151
|
+
const filter = chunkSFGYZUWU_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
|
|
2098
2152
|
const normalizedFilter = augmentFilterForDocuments(filter, { typeId: record.name, role });
|
|
2099
2153
|
if (!normalizedFilter.limit) normalizedFilter.limit = 50;
|
|
2100
2154
|
normalizedFilter.limit = Math.min(normalizedFilter.limit, 1e3);
|
|
2101
|
-
const builder = new
|
|
2155
|
+
const builder = new chunkSFGYZUWU_cjs.QueryFilterBuilder();
|
|
2102
2156
|
const queryResult = builder.build("documents", normalizedFilter);
|
|
2103
2157
|
if (queryResult.errors.length > 0) {
|
|
2104
2158
|
return c.json({ error: "Invalid filter parameters", details: queryResult.errors }, 400);
|
|
2105
2159
|
}
|
|
2106
2160
|
const collectionCache = record.cache;
|
|
2107
2161
|
const collectionCacheDisabled = collectionCache?.enabled === false;
|
|
2108
|
-
const cacheEnabled = c.get("cacheEnabled") && !collectionCacheDisabled && projFields.length === 0 &&
|
|
2109
|
-
const cache =
|
|
2162
|
+
const cacheEnabled = c.get("cacheEnabled") && !collectionCacheDisabled && projFields.length === 0 && !needsAcl;
|
|
2163
|
+
const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
|
|
2110
2164
|
const includeCollection = queryParams.include?.split(",").map((s) => s.trim()).includes("collection");
|
|
2111
2165
|
const cacheKey = cache.generateKey("collection-content-filtered", `${collection}:${JSON.stringify({ filter: normalizedFilter, query: queryResult.sql, includeCollection })}`);
|
|
2112
2166
|
if (cacheEnabled) {
|
|
@@ -2115,8 +2169,20 @@ apiRoutes.get("/:collection", chunkE7E3NL3Y_cjs.optionalAuth(), async (c) => {
|
|
|
2115
2169
|
c.header("X-Cache-Status", "HIT");
|
|
2116
2170
|
c.header("X-Cache-Source", cacheResult.source);
|
|
2117
2171
|
if (cacheResult.ttl) c.header("X-Cache-TTL", Math.floor(cacheResult.ttl).toString());
|
|
2172
|
+
chunkFZGIU5AZ_cjs.recordCatalogRequest({ cacheKey, collection: collection ?? null, path: c.req.path, queryString: c.req.raw.url.split("?")[1] ?? "", source: cacheResult.source });
|
|
2173
|
+
chunkFZGIU5AZ_cjs.scheduleKvWrite(cacheKey, c.executionCtx);
|
|
2118
2174
|
return c.json({ ...cacheResult.data, meta: addTimingMeta(c, { ...cacheResult.data.meta, cache: { hit: true, source: cacheResult.source, ttl: cacheResult.ttl ? Math.floor(cacheResult.ttl) : void 0 } }, executionStart) });
|
|
2119
2175
|
}
|
|
2176
|
+
const swrData = getAndConsumeStale(cacheKey);
|
|
2177
|
+
if (swrData) {
|
|
2178
|
+
c.header("X-Cache-Status", "STALE");
|
|
2179
|
+
c.header("X-Cache-Source", "swr");
|
|
2180
|
+
chunkFZGIU5AZ_cjs.recordCatalogRequest({ cacheKey, collection: collection ?? null, path: c.req.path, queryString: c.req.raw.url.split("?")[1] ?? "", source: "swr" });
|
|
2181
|
+
chunkFZGIU5AZ_cjs.scheduleKvWrite(cacheKey, c.executionCtx);
|
|
2182
|
+
return c.json({ ...swrData, meta: addTimingMeta(c, { ...swrData.meta, cache: { hit: true, source: "swr", stale: true } }, executionStart) });
|
|
2183
|
+
}
|
|
2184
|
+
chunkFZGIU5AZ_cjs.recordCatalogRequest({ cacheKey, collection: collection ?? null, path: c.req.path, queryString: c.req.raw.url.split("?")[1] ?? "", source: "miss" });
|
|
2185
|
+
chunkFZGIU5AZ_cjs.scheduleKvWrite(cacheKey, c.executionCtx);
|
|
2120
2186
|
}
|
|
2121
2187
|
c.header("X-Cache-Status", "MISS");
|
|
2122
2188
|
c.header("X-Cache-Source", "database");
|
|
@@ -2140,7 +2206,7 @@ apiRoutes.get("/:collection", chunkE7E3NL3Y_cjs.optionalAuth(), async (c) => {
|
|
|
2140
2206
|
const responseData = {
|
|
2141
2207
|
data: projFields.length ? transformedResults.map((item) => projectFields(item, projFields)) : transformedResults,
|
|
2142
2208
|
meta: addTimingMeta(c, {
|
|
2143
|
-
...includeCollection ? { collection:
|
|
2209
|
+
...includeCollection ? { collection: chunk4DHPR7KR_cjs.collectionRecordToRow(record) } : {},
|
|
2144
2210
|
count: aclResults.length,
|
|
2145
2211
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2146
2212
|
filter: normalizePublicContentFilter(filter, role),
|
|
@@ -2158,12 +2224,12 @@ apiRoutes.get("/:collection", chunkE7E3NL3Y_cjs.optionalAuth(), async (c) => {
|
|
|
2158
2224
|
return c.json({ error: "Failed to fetch content", details: error instanceof Error ? error.message : String(error) }, 500);
|
|
2159
2225
|
}
|
|
2160
2226
|
});
|
|
2161
|
-
apiRoutes.get("/:collection/:id",
|
|
2227
|
+
apiRoutes.get("/:collection/:id", chunkBRKXMRMB_cjs.optionalAuth(), async (c) => {
|
|
2162
2228
|
try {
|
|
2163
2229
|
const collection = c.req.param("collection");
|
|
2164
2230
|
const id = c.req.param("id");
|
|
2165
2231
|
const db = c.env.DB;
|
|
2166
|
-
const record =
|
|
2232
|
+
const record = chunk4DHPR7KR_cjs.getCollectionRegistry().getBySlugOrName(collection);
|
|
2167
2233
|
if (!record || record.isActive === false) {
|
|
2168
2234
|
return c.json({ error: "Collection not found" }, 404);
|
|
2169
2235
|
}
|
|
@@ -2176,7 +2242,7 @@ apiRoutes.get("/:collection/:id", chunkE7E3NL3Y_cjs.optionalAuth(), async (c) =>
|
|
|
2176
2242
|
const { tenantId: colTenantId, principalSet: colPrincipalSet } = getDocumentRequestContext(c);
|
|
2177
2243
|
const colNeedsAcl = !isAnonPrincipal(colPrincipalSet) && !canReadNonPublicContent(colRole);
|
|
2178
2244
|
if (colNeedsAcl) {
|
|
2179
|
-
const docType = await new
|
|
2245
|
+
const docType = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(record.name);
|
|
2180
2246
|
if (!await typeReadAllowed(db, colPrincipalSet, docType, record.name)) {
|
|
2181
2247
|
return c.json({ error: "Content not found" }, 404);
|
|
2182
2248
|
}
|
|
@@ -2189,7 +2255,7 @@ apiRoutes.get("/:collection/:id", chunkE7E3NL3Y_cjs.optionalAuth(), async (c) =>
|
|
|
2189
2255
|
}
|
|
2190
2256
|
}
|
|
2191
2257
|
const projFields = parseFieldsParam(c.req.query("fields"));
|
|
2192
|
-
const coll =
|
|
2258
|
+
const coll = chunk4DHPR7KR_cjs.getCollectionRegistry().getByName(docRow.type_id);
|
|
2193
2259
|
const transformedContent = {
|
|
2194
2260
|
id: docRow.root_id,
|
|
2195
2261
|
title: docRow.title,
|
|
@@ -2197,8 +2263,8 @@ apiRoutes.get("/:collection/:id", chunkE7E3NL3Y_cjs.optionalAuth(), async (c) =>
|
|
|
2197
2263
|
status: docRow.status,
|
|
2198
2264
|
collectionId: coll?.id ?? docRow.type_id,
|
|
2199
2265
|
data: docRow.data ? JSON.parse(docRow.data) : {},
|
|
2200
|
-
created_at:
|
|
2201
|
-
updated_at:
|
|
2266
|
+
created_at: chunkOLEOKHDX_cjs.documentSecondsToMs(docRow.created_at),
|
|
2267
|
+
updated_at: chunkOLEOKHDX_cjs.documentSecondsToMs(docRow.updated_at)
|
|
2202
2268
|
};
|
|
2203
2269
|
dispatchHookEvent(c, "content:read", { collection: docRow.type_id, id: docRow.root_id, data: transformedContent.data }, "fire-and-forget");
|
|
2204
2270
|
return c.json({ data: projFields.length ? projectFields(transformedContent, projFields) : transformedContent });
|
|
@@ -2207,7 +2273,7 @@ apiRoutes.get("/:collection/:id", chunkE7E3NL3Y_cjs.optionalAuth(), async (c) =>
|
|
|
2207
2273
|
return c.json({ error: "Failed to fetch content", details: error instanceof Error ? error.message : String(error) }, 500);
|
|
2208
2274
|
}
|
|
2209
2275
|
});
|
|
2210
|
-
apiRoutes.post("/:collection",
|
|
2276
|
+
apiRoutes.post("/:collection", chunkBRKXMRMB_cjs.requireAuth(), chunkBRKXMRMB_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
2211
2277
|
try {
|
|
2212
2278
|
const collection = c.req.param("collection");
|
|
2213
2279
|
const db = c.env.DB;
|
|
@@ -2228,26 +2294,29 @@ apiRoutes.post("/:collection", chunkE7E3NL3Y_cjs.requireAuth(), chunkE7E3NL3Y_cj
|
|
|
2228
2294
|
} catch (err) {
|
|
2229
2295
|
return c.json({ error: "Write cancelled by plugin", details: String(err) }, 400);
|
|
2230
2296
|
}
|
|
2231
|
-
const svc = new
|
|
2297
|
+
const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, { queryableFields: backing.docType.queryableFields ?? [], typeSchemaVersion: backing.docType.schemaVersion ?? 1, maxVersionsPerRoot: backing.docType.settings?.maxVersionsPerRoot ?? 50, tenantId: "default", versioning: backing.docType.settings?.versioning ?? false });
|
|
2232
2298
|
const doc = await svc.create(createDocumentSchema.parse({ typeId: backing.coll.name, tenantId: "default", locale: "default", title, slug: finalSlug, data: hookData, publishOnCreate: (status || "draft") === "published" }), user?.userId);
|
|
2233
|
-
const cache =
|
|
2299
|
+
const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
|
|
2300
|
+
const createAffectedKeys = (await cache.listKeys()).map((k) => k.key).filter((k) => k.startsWith("api:content-filtered:") || k.startsWith(`api:collection-content-filtered:${backing.coll.name}:`));
|
|
2301
|
+
const createStaleValues = await cache.getMany(createAffectedKeys);
|
|
2302
|
+
for (const [key, val] of createStaleValues) markStale(key, val, backing.coll.name);
|
|
2234
2303
|
await cache.invalidate("api:content-filtered:*");
|
|
2235
2304
|
await cache.invalidate(`api:collection-content-filtered:${backing.coll.name}:*`);
|
|
2236
2305
|
dispatchHookEvent(c, "content:after:create", { collection: backing.coll.name, id: doc.rootId, data: doc.data ?? {}, user: actor }, "fire-and-forget");
|
|
2237
|
-
return c.json({ data: { id: doc.rootId, title: doc.title, slug: doc.slug, status: doc.status, collectionId: backing.coll.id, data: doc.data, created_at:
|
|
2306
|
+
return c.json({ data: { id: doc.rootId, title: doc.title, slug: doc.slug, status: doc.status, collectionId: backing.coll.id, data: doc.data, created_at: chunkOLEOKHDX_cjs.documentSecondsToMs(doc.createdAt), updated_at: chunkOLEOKHDX_cjs.documentSecondsToMs(doc.updatedAt) } }, 201);
|
|
2238
2307
|
} catch (error) {
|
|
2239
2308
|
console.error("Error creating content:", error);
|
|
2240
2309
|
return c.json({ error: "Failed to create content", details: error instanceof Error ? error.message : String(error) }, 500);
|
|
2241
2310
|
}
|
|
2242
2311
|
});
|
|
2243
|
-
apiRoutes.put("/:collection/:id",
|
|
2312
|
+
apiRoutes.put("/:collection/:id", chunkBRKXMRMB_cjs.requireAuth(), chunkBRKXMRMB_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
2244
2313
|
try {
|
|
2245
2314
|
const collection = c.req.param("collection");
|
|
2246
2315
|
const id = c.req.param("id");
|
|
2247
2316
|
const db = c.env.DB;
|
|
2248
2317
|
const user = c.get("user");
|
|
2249
2318
|
const body = await c.req.json();
|
|
2250
|
-
const collRecord =
|
|
2319
|
+
const collRecord = chunk4DHPR7KR_cjs.getCollectionRegistry().getBySlugOrName(collection);
|
|
2251
2320
|
const typeName = collRecord?.name ?? collection;
|
|
2252
2321
|
const docRow = await db.prepare("SELECT root_id, type_id FROM documents WHERE root_id = ? AND type_id = ? AND tenant_id = 'default' AND is_current_draft = 1 AND deleted_at IS NULL").bind(id, typeName).first();
|
|
2253
2322
|
if (!docRow) return c.json({ error: "Content not found" }, 404);
|
|
@@ -2259,8 +2328,8 @@ apiRoutes.put("/:collection/:id", chunkE7E3NL3Y_cjs.requireAuth(), chunkE7E3NL3Y
|
|
|
2259
2328
|
} catch (err) {
|
|
2260
2329
|
return c.json({ error: "Write cancelled by plugin", details: String(err) }, 400);
|
|
2261
2330
|
}
|
|
2262
|
-
const docType = await new
|
|
2263
|
-
const svc = new
|
|
2331
|
+
const docType = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(docRow.type_id);
|
|
2332
|
+
const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, { queryableFields: docType?.queryableFields ?? [], typeSchemaVersion: docType?.schemaVersion ?? 1, maxVersionsPerRoot: docType?.settings?.maxVersionsPerRoot ?? 50, tenantId: "default", versioning: docType?.settings?.versioning ?? false });
|
|
2264
2333
|
const input = {};
|
|
2265
2334
|
if (body.title !== void 0) input.title = body.title;
|
|
2266
2335
|
if (body.slug !== void 0) input.slug = slugify(body.slug);
|
|
@@ -2273,28 +2342,31 @@ apiRoutes.put("/:collection/:id", chunkE7E3NL3Y_cjs.requireAuth(), chunkE7E3NL3Y
|
|
|
2273
2342
|
} else if (body.status === "draft" && pub) {
|
|
2274
2343
|
await svc.unpublish(pub.id);
|
|
2275
2344
|
}
|
|
2276
|
-
const cache =
|
|
2345
|
+
const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
|
|
2346
|
+
const updateAffectedKeys = (await cache.listKeys()).map((k) => k.key).filter((k) => k.startsWith("api:content-filtered:") || k.startsWith(`api:collection-content-filtered:${docRow.type_id}:`));
|
|
2347
|
+
const updateStaleValues = await cache.getMany(updateAffectedKeys);
|
|
2348
|
+
for (const [key, val] of updateStaleValues) markStale(key, val, docRow.type_id);
|
|
2277
2349
|
await cache.invalidate("api:content-filtered:*");
|
|
2278
2350
|
await cache.invalidate(`api:collection-content-filtered:${docRow.type_id}:*`);
|
|
2279
|
-
const coll =
|
|
2351
|
+
const coll = chunk4DHPR7KR_cjs.getCollectionRegistry().getByName(docRow.type_id);
|
|
2280
2352
|
const saved = await db.prepare("SELECT * FROM documents WHERE id = ?").bind(newDraft.id).first();
|
|
2281
2353
|
const savedData = saved?.data ? JSON.parse(saved.data) : {};
|
|
2282
2354
|
dispatchHookEvent(c, "content:after:update", { collection: docRow.type_id, id, data: savedData, user: actor }, "fire-and-forget");
|
|
2283
2355
|
const nowPublished = body.status === "published" || body.status === void 0 && wasPublished;
|
|
2284
2356
|
if (nowPublished && !wasPublished) dispatchHookEvent(c, "content:after:publish", { collection: docRow.type_id, id, data: savedData, user: actor }, "fire-and-forget");
|
|
2285
|
-
return c.json({ data: { id: saved.root_id, title: saved.title, slug: saved.slug, status: saved.status, collectionId: coll?.id ?? docRow.type_id, data: savedData, created_at:
|
|
2357
|
+
return c.json({ data: { id: saved.root_id, title: saved.title, slug: saved.slug, status: saved.status, collectionId: coll?.id ?? docRow.type_id, data: savedData, created_at: chunkOLEOKHDX_cjs.documentSecondsToMs(saved.created_at), updated_at: chunkOLEOKHDX_cjs.documentSecondsToMs(saved.updated_at) } });
|
|
2286
2358
|
} catch (error) {
|
|
2287
2359
|
console.error("Error updating content:", error);
|
|
2288
2360
|
return c.json({ error: "Failed to update content", details: error instanceof Error ? error.message : String(error) }, 500);
|
|
2289
2361
|
}
|
|
2290
2362
|
});
|
|
2291
|
-
apiRoutes.delete("/:collection/:id",
|
|
2363
|
+
apiRoutes.delete("/:collection/:id", chunkBRKXMRMB_cjs.requireAuth(), chunkBRKXMRMB_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
2292
2364
|
try {
|
|
2293
2365
|
const collection = c.req.param("collection");
|
|
2294
2366
|
const id = c.req.param("id");
|
|
2295
2367
|
const db = c.env.DB;
|
|
2296
2368
|
const user = c.get("user");
|
|
2297
|
-
const collRecord =
|
|
2369
|
+
const collRecord = chunk4DHPR7KR_cjs.getCollectionRegistry().getBySlugOrName(collection);
|
|
2298
2370
|
const typeName = collRecord?.name ?? collection;
|
|
2299
2371
|
const docRow = await db.prepare("SELECT type_id FROM documents WHERE root_id = ? AND type_id = ? AND tenant_id = 'default' AND deleted_at IS NULL LIMIT 1").bind(id, typeName).first();
|
|
2300
2372
|
if (!docRow) return c.json({ error: "Content not found" }, 404);
|
|
@@ -2306,7 +2378,10 @@ apiRoutes.delete("/:collection/:id", chunkE7E3NL3Y_cjs.requireAuth(), chunkE7E3N
|
|
|
2306
2378
|
}
|
|
2307
2379
|
const now = Math.floor(Date.now() / 1e3);
|
|
2308
2380
|
await db.prepare("UPDATE documents SET deleted_at = ?, updated_at = ? WHERE root_id = ? AND tenant_id = 'default'").bind(now, now, id).run();
|
|
2309
|
-
const cache =
|
|
2381
|
+
const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
|
|
2382
|
+
const deleteAffectedKeys = (await cache.listKeys()).map((k) => k.key).filter((k) => k.startsWith("api:content-filtered:") || k.startsWith(`api:collection-content-filtered:${docRow.type_id}:`));
|
|
2383
|
+
const deleteStaleValues = await cache.getMany(deleteAffectedKeys);
|
|
2384
|
+
for (const [key, val] of deleteStaleValues) markStale(key, val, docRow.type_id);
|
|
2310
2385
|
await cache.invalidate("api:content-filtered:*");
|
|
2311
2386
|
await cache.invalidate(`api:collection-content-filtered:${docRow.type_id}:*`);
|
|
2312
2387
|
dispatchHookEvent(c, "content:after:delete", { collection: docRow.type_id, id, data: {}, user: actor }, "fire-and-forget");
|
|
@@ -2381,7 +2456,7 @@ var MediaDocumentService = class {
|
|
|
2381
2456
|
tenantId;
|
|
2382
2457
|
/** Create a media_asset document from R2 upload metadata. Published-on-create (immediately usable). */
|
|
2383
2458
|
async createFromUpload(meta, createdBy) {
|
|
2384
|
-
const svc = new
|
|
2459
|
+
const svc = new chunkOLEOKHDX_cjs.DocumentsService(this.db, { queryableFields: MEDIA_QUERYABLE, tenantId: this.tenantId, maxVersionsPerRoot: 5 });
|
|
2385
2460
|
return svc.create(
|
|
2386
2461
|
createDocumentSchema.parse({
|
|
2387
2462
|
typeId: "media_asset",
|
|
@@ -2459,7 +2534,7 @@ var MediaDocumentService = class {
|
|
|
2459
2534
|
}
|
|
2460
2535
|
/** Update alt/caption/tags on a media_asset document (saveDraft + publish atomically). */
|
|
2461
2536
|
async updateMetadata(rootId, meta, updatedBy) {
|
|
2462
|
-
const svc = new
|
|
2537
|
+
const svc = new chunkOLEOKHDX_cjs.DocumentsService(this.db, { queryableFields: MEDIA_QUERYABLE, tenantId: this.tenantId, maxVersionsPerRoot: 5 });
|
|
2463
2538
|
const newDraft = await svc.saveDraft(rootId, { data: meta }, updatedBy);
|
|
2464
2539
|
return svc.publish(newDraft.id, updatedBy);
|
|
2465
2540
|
}
|
|
@@ -2516,7 +2591,7 @@ var fileValidationSchema = zod.z.object({
|
|
|
2516
2591
|
// 50MB max
|
|
2517
2592
|
});
|
|
2518
2593
|
var apiMediaRoutes = new hono.Hono();
|
|
2519
|
-
apiMediaRoutes.use("*",
|
|
2594
|
+
apiMediaRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
|
|
2520
2595
|
apiMediaRoutes.post("/upload", async (c) => {
|
|
2521
2596
|
try {
|
|
2522
2597
|
const user = c.get("user");
|
|
@@ -3218,7 +3293,7 @@ apiSystemRoutes.get("/info", (c) => {
|
|
|
3218
3293
|
apiSystemRoutes.get("/stats", async (c) => {
|
|
3219
3294
|
try {
|
|
3220
3295
|
const db = c.env.DB;
|
|
3221
|
-
const typeIds =
|
|
3296
|
+
const typeIds = chunk4DHPR7KR_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal).map((r) => r.name);
|
|
3222
3297
|
let contentStats = null;
|
|
3223
3298
|
if (typeIds.length > 0) {
|
|
3224
3299
|
const placeholders = typeIds.map(() => "?").join(",");
|
|
@@ -3293,12 +3368,12 @@ apiSystemRoutes.get("/env", (c) => {
|
|
|
3293
3368
|
});
|
|
3294
3369
|
var api_system_default = apiSystemRoutes;
|
|
3295
3370
|
var adminApiRoutes = new hono.Hono();
|
|
3296
|
-
adminApiRoutes.use("*",
|
|
3297
|
-
adminApiRoutes.use("*",
|
|
3371
|
+
adminApiRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
|
|
3372
|
+
adminApiRoutes.use("*", chunkBRKXMRMB_cjs.requireRole(["admin", "editor"]));
|
|
3298
3373
|
adminApiRoutes.get("/stats", async (c) => {
|
|
3299
3374
|
try {
|
|
3300
3375
|
const db = c.env.DB;
|
|
3301
|
-
const userCollections =
|
|
3376
|
+
const userCollections = chunk4DHPR7KR_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal);
|
|
3302
3377
|
const collectionsCount = userCollections.length;
|
|
3303
3378
|
let contentCount = 0;
|
|
3304
3379
|
if (userCollections.length > 0) {
|
|
@@ -3389,7 +3464,7 @@ adminApiRoutes.get("/collections", async (c) => {
|
|
|
3389
3464
|
try {
|
|
3390
3465
|
const search = c.req.query("search") || "";
|
|
3391
3466
|
const includeInactive = c.req.query("includeInactive") === "true";
|
|
3392
|
-
let records =
|
|
3467
|
+
let records = chunk4DHPR7KR_cjs.getCollectionRegistry().list().filter((r) => !r.internal);
|
|
3393
3468
|
if (!includeInactive) records = records.filter((r) => r.isActive !== false);
|
|
3394
3469
|
if (search) {
|
|
3395
3470
|
const needle = search.toLowerCase();
|
|
@@ -3421,7 +3496,7 @@ adminApiRoutes.get("/collections", async (c) => {
|
|
|
3421
3496
|
adminApiRoutes.get("/collections/:id", async (c) => {
|
|
3422
3497
|
try {
|
|
3423
3498
|
const id = c.req.param("id");
|
|
3424
|
-
const registry =
|
|
3499
|
+
const registry = chunk4DHPR7KR_cjs.getCollectionRegistry();
|
|
3425
3500
|
const record = registry.getById(id) ?? registry.getByName(id);
|
|
3426
3501
|
if (!record) {
|
|
3427
3502
|
return c.json({ error: "Collection not found" }, 404);
|
|
@@ -3471,7 +3546,7 @@ adminApiRoutes.get("/references", async (c) => {
|
|
|
3471
3546
|
if (collectionParams.length === 0) {
|
|
3472
3547
|
return c.json({ error: "Collection is required" }, 400);
|
|
3473
3548
|
}
|
|
3474
|
-
const registry =
|
|
3549
|
+
const registry = chunk4DHPR7KR_cjs.getCollectionRegistry();
|
|
3475
3550
|
const matched = collectionParams.map((param) => registry.getById(param) ?? registry.getByName(param)).filter((r) => !!r);
|
|
3476
3551
|
const seen = /* @__PURE__ */ new Set();
|
|
3477
3552
|
const collections = matched.filter((r) => {
|
|
@@ -3586,7 +3661,7 @@ adminApiRoutes.patch("/collections/:id", collectionsReadOnly);
|
|
|
3586
3661
|
adminApiRoutes.delete("/collections/:id", collectionsReadOnly);
|
|
3587
3662
|
adminApiRoutes.get("/migrations/status", async (c) => {
|
|
3588
3663
|
try {
|
|
3589
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
3664
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-6M6772UC.cjs');
|
|
3590
3665
|
const db = c.env.DB;
|
|
3591
3666
|
const migrationService = new MigrationService2(db);
|
|
3592
3667
|
const status = await migrationService.getMigrationStatus();
|
|
@@ -3629,7 +3704,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
|
|
|
3629
3704
|
});
|
|
3630
3705
|
adminApiRoutes.get("/migrations/validate", async (c) => {
|
|
3631
3706
|
try {
|
|
3632
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
3707
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-6M6772UC.cjs');
|
|
3633
3708
|
const db = c.env.DB;
|
|
3634
3709
|
const migrationService = new MigrationService2(db);
|
|
3635
3710
|
const validation = await migrationService.validateSchema();
|
|
@@ -4046,7 +4121,7 @@ function renderRegisterPage(data) {
|
|
|
4046
4121
|
}
|
|
4047
4122
|
|
|
4048
4123
|
// src/services/email/email-service-singleton.ts
|
|
4049
|
-
var singleton =
|
|
4124
|
+
var singleton = chunkKWQNB6UM_cjs.createServiceSingleton("EmailService");
|
|
4050
4125
|
function setEmailService(service2) {
|
|
4051
4126
|
singleton.set(service2);
|
|
4052
4127
|
}
|
|
@@ -4090,7 +4165,7 @@ function emptyProfile() {
|
|
|
4090
4165
|
return { custom: {} };
|
|
4091
4166
|
}
|
|
4092
4167
|
function service(db) {
|
|
4093
|
-
return new
|
|
4168
|
+
return new chunkOLEOKHDX_cjs.DocumentsService(db, { tenantId: "default", maxVersionsPerRoot: 1, queryableFields: [] });
|
|
4094
4169
|
}
|
|
4095
4170
|
async function readProfileData(db, userId) {
|
|
4096
4171
|
const row = await db.prepare(
|
|
@@ -4854,7 +4929,7 @@ function getLexicalInitScript(settings = {}) {
|
|
|
4854
4929
|
</script>
|
|
4855
4930
|
`;
|
|
4856
4931
|
}
|
|
4857
|
-
var lexicalEditorPlugin =
|
|
4932
|
+
var lexicalEditorPlugin = chunkKWQNB6UM_cjs.definePlugin({
|
|
4858
4933
|
id: "lexical-editor",
|
|
4859
4934
|
version: "1.0.0",
|
|
4860
4935
|
name: "Lexical Editor",
|
|
@@ -7263,7 +7338,7 @@ api.put("/:userId", async (c) => {
|
|
|
7263
7338
|
await saveCustomData(db, userId, sanitized);
|
|
7264
7339
|
return c.json({ success: true });
|
|
7265
7340
|
});
|
|
7266
|
-
var userProfilesPlugin =
|
|
7341
|
+
var userProfilesPlugin = chunkKWQNB6UM_cjs.definePlugin({
|
|
7267
7342
|
id: "user-profiles",
|
|
7268
7343
|
version: "1.0.0",
|
|
7269
7344
|
name: "User Profiles",
|
|
@@ -7280,6 +7355,15 @@ function createUserProfilesPlugin() {
|
|
|
7280
7355
|
return userProfilesPlugin;
|
|
7281
7356
|
}
|
|
7282
7357
|
|
|
7358
|
+
// src/services/demo-mode.ts
|
|
7359
|
+
var _demoModeActive = false;
|
|
7360
|
+
function setDemoModeActive() {
|
|
7361
|
+
_demoModeActive = true;
|
|
7362
|
+
}
|
|
7363
|
+
function isDemoModeActive() {
|
|
7364
|
+
return _demoModeActive;
|
|
7365
|
+
}
|
|
7366
|
+
|
|
7283
7367
|
// src/routes/auth.ts
|
|
7284
7368
|
var JWT_SECRET_FALLBACK = "your-super-secret-jwt-key-change-in-production";
|
|
7285
7369
|
var DEMO_EMAIL = "admin@sonicjs.com";
|
|
@@ -7316,8 +7400,8 @@ function renderPasswordResetEmail(resetLink, firstName) {
|
|
|
7316
7400
|
async function setCsrfCookie(c, maxAge) {
|
|
7317
7401
|
const secret = c.env?.JWT_SECRET || JWT_SECRET_FALLBACK;
|
|
7318
7402
|
const isDev = c.env?.ENVIRONMENT === "development" || !c.env?.ENVIRONMENT;
|
|
7319
|
-
const csrfToken = await
|
|
7320
|
-
const cookieMaxAge = await
|
|
7403
|
+
const csrfToken = await chunkBRKXMRMB_cjs.generateCsrfToken(secret);
|
|
7404
|
+
const cookieMaxAge = await chunkBRKXMRMB_cjs.getJwtExpirySecondsFromDb(c.env?.DB, c.env);
|
|
7321
7405
|
cookie.setCookie(c, "csrf_token", csrfToken, {
|
|
7322
7406
|
httpOnly: false,
|
|
7323
7407
|
secure: !isDev,
|
|
@@ -7346,13 +7430,7 @@ authRoutes.get("/login", async (c) => {
|
|
|
7346
7430
|
version: c.get("appVersion"),
|
|
7347
7431
|
redirect: redirect && redirect.startsWith("/") ? redirect : void 0
|
|
7348
7432
|
};
|
|
7349
|
-
const
|
|
7350
|
-
let demoLoginActive = false;
|
|
7351
|
-
try {
|
|
7352
|
-
const plugin = await db.prepare("SELECT * FROM plugins WHERE id = ? AND status = ?").bind("demo-login-prefill", "active").first();
|
|
7353
|
-
demoLoginActive = !!plugin;
|
|
7354
|
-
} catch (error2) {
|
|
7355
|
-
}
|
|
7433
|
+
const demoLoginActive = isDemoModeActive();
|
|
7356
7434
|
return c.html(renderLoginPage(pageData, demoLoginActive));
|
|
7357
7435
|
});
|
|
7358
7436
|
authRoutes.get("/register", async (c) => {
|
|
@@ -7376,7 +7454,7 @@ var loginSchema = zod.z.object({
|
|
|
7376
7454
|
});
|
|
7377
7455
|
authRoutes.post(
|
|
7378
7456
|
"/register",
|
|
7379
|
-
|
|
7457
|
+
chunkBRKXMRMB_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "register" }),
|
|
7380
7458
|
async (c) => {
|
|
7381
7459
|
try {
|
|
7382
7460
|
const db = c.env.DB;
|
|
@@ -7412,7 +7490,7 @@ authRoutes.post(
|
|
|
7412
7490
|
if (existingUser) {
|
|
7413
7491
|
return c.json({ error: "User with this email already exists" }, 400);
|
|
7414
7492
|
}
|
|
7415
|
-
const passwordHash = await
|
|
7493
|
+
const passwordHash = await chunkBRKXMRMB_cjs.AuthManager.hashPassword(password);
|
|
7416
7494
|
const userId = crypto.randomUUID();
|
|
7417
7495
|
const now = /* @__PURE__ */ new Date();
|
|
7418
7496
|
const nowSec = Math.floor(now.getTime() / 1e3);
|
|
@@ -7445,8 +7523,8 @@ authRoutes.post(
|
|
|
7445
7523
|
{ user: { id: userId, email: normalizedEmail, role: "viewer" } },
|
|
7446
7524
|
"fire-and-forget"
|
|
7447
7525
|
);
|
|
7448
|
-
const tokenTtl = await
|
|
7449
|
-
const token = await
|
|
7526
|
+
const tokenTtl = await chunkBRKXMRMB_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
|
|
7527
|
+
const token = await chunkBRKXMRMB_cjs.AuthManager.generateToken(userId, normalizedEmail, "viewer", c.env.JWT_SECRET, tokenTtl);
|
|
7450
7528
|
cookie.setCookie(c, "auth_token", token, {
|
|
7451
7529
|
httpOnly: true,
|
|
7452
7530
|
secure: true,
|
|
@@ -7478,7 +7556,7 @@ authRoutes.post(
|
|
|
7478
7556
|
);
|
|
7479
7557
|
authRoutes.post(
|
|
7480
7558
|
"/login",
|
|
7481
|
-
|
|
7559
|
+
chunkBRKXMRMB_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "login" }),
|
|
7482
7560
|
async (c) => {
|
|
7483
7561
|
try {
|
|
7484
7562
|
const body = await c.req.json();
|
|
@@ -7488,7 +7566,7 @@ authRoutes.post(
|
|
|
7488
7566
|
}
|
|
7489
7567
|
const { email, password } = validation.data;
|
|
7490
7568
|
const normalizedEmail = email.toLowerCase();
|
|
7491
|
-
const { createAuth } = await import('./config-
|
|
7569
|
+
const { createAuth } = await import('./config-VLU73ZW7.cjs');
|
|
7492
7570
|
const auth = createAuth(c.env, void 0, new URL(c.req.url).origin);
|
|
7493
7571
|
const baReq = new Request(new URL("/auth/sign-in/email", c.req.url).href, {
|
|
7494
7572
|
method: "POST",
|
|
@@ -7512,8 +7590,8 @@ authRoutes.post(
|
|
|
7512
7590
|
await setCsrfCookie(c);
|
|
7513
7591
|
const baBody = await baRes.json();
|
|
7514
7592
|
const user = baBody.user ?? {};
|
|
7515
|
-
const tokenTtl = await
|
|
7516
|
-
const token = await
|
|
7593
|
+
const tokenTtl = await chunkBRKXMRMB_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
|
|
7594
|
+
const token = await chunkBRKXMRMB_cjs.AuthManager.generateToken(
|
|
7517
7595
|
user.id,
|
|
7518
7596
|
user.email,
|
|
7519
7597
|
user.role ?? "viewer",
|
|
@@ -7547,7 +7625,7 @@ authRoutes.post(
|
|
|
7547
7625
|
);
|
|
7548
7626
|
authRoutes.post("/logout", async (c) => {
|
|
7549
7627
|
try {
|
|
7550
|
-
const { createAuth } = await import('./config-
|
|
7628
|
+
const { createAuth } = await import('./config-VLU73ZW7.cjs');
|
|
7551
7629
|
const auth = createAuth(c.env, void 0, new URL(c.req.url).origin);
|
|
7552
7630
|
const baReq = new Request(new URL("/auth/sign-out", c.req.url).href, {
|
|
7553
7631
|
method: "POST",
|
|
@@ -7564,7 +7642,7 @@ authRoutes.post("/logout", async (c) => {
|
|
|
7564
7642
|
});
|
|
7565
7643
|
authRoutes.get("/logout", async (c) => {
|
|
7566
7644
|
try {
|
|
7567
|
-
const { createAuth } = await import('./config-
|
|
7645
|
+
const { createAuth } = await import('./config-VLU73ZW7.cjs');
|
|
7568
7646
|
const auth = createAuth(c.env, void 0, new URL(c.req.url).origin);
|
|
7569
7647
|
const baReq = new Request(new URL("/auth/sign-out", c.req.url).href, {
|
|
7570
7648
|
method: "POST",
|
|
@@ -7579,7 +7657,7 @@ authRoutes.get("/logout", async (c) => {
|
|
|
7579
7657
|
clearCsrfCookie(c);
|
|
7580
7658
|
return c.redirect("/auth/login?message=You have been logged out successfully");
|
|
7581
7659
|
});
|
|
7582
|
-
authRoutes.get("/me",
|
|
7660
|
+
authRoutes.get("/me", chunkBRKXMRMB_cjs.requireAuth(), async (c) => {
|
|
7583
7661
|
try {
|
|
7584
7662
|
const user = c.get("user");
|
|
7585
7663
|
if (!user) {
|
|
@@ -7599,7 +7677,7 @@ authRoutes.get("/me", chunkE7E3NL3Y_cjs.requireAuth(), async (c) => {
|
|
|
7599
7677
|
});
|
|
7600
7678
|
authRoutes.post(
|
|
7601
7679
|
"/refresh",
|
|
7602
|
-
|
|
7680
|
+
chunkBRKXMRMB_cjs.rateLimit({ max: 60, windowMs: 60 * 1e3, keyPrefix: "refresh" }),
|
|
7603
7681
|
async (c) => {
|
|
7604
7682
|
try {
|
|
7605
7683
|
let token = c.req.header("Authorization")?.replace("Bearer ", "");
|
|
@@ -7608,8 +7686,8 @@ authRoutes.post(
|
|
|
7608
7686
|
return c.json({ error: "Authentication required" }, 401);
|
|
7609
7687
|
}
|
|
7610
7688
|
const db = c.env.DB;
|
|
7611
|
-
const grace = await
|
|
7612
|
-
const payload = await
|
|
7689
|
+
const grace = await chunkBRKXMRMB_cjs.getJwtRefreshGraceSecondsFromDb(db, c.env);
|
|
7690
|
+
const payload = await chunkBRKXMRMB_cjs.AuthManager.verifyToken(token, c.env.JWT_SECRET, grace);
|
|
7613
7691
|
if (!payload) {
|
|
7614
7692
|
return c.json({ error: "Invalid or expired token" }, 401);
|
|
7615
7693
|
}
|
|
@@ -7617,8 +7695,8 @@ authRoutes.post(
|
|
|
7617
7695
|
if (!row || !row.is_active) {
|
|
7618
7696
|
return c.json({ error: "User is not active" }, 401);
|
|
7619
7697
|
}
|
|
7620
|
-
const tokenTtl = await
|
|
7621
|
-
const newToken = await
|
|
7698
|
+
const tokenTtl = await chunkBRKXMRMB_cjs.getJwtExpirySecondsFromDb(db, c.env);
|
|
7699
|
+
const newToken = await chunkBRKXMRMB_cjs.AuthManager.generateToken(row.id, row.email, row.role, c.env.JWT_SECRET, tokenTtl);
|
|
7622
7700
|
cookie.setCookie(c, "auth_token", newToken, {
|
|
7623
7701
|
httpOnly: true,
|
|
7624
7702
|
secure: true,
|
|
@@ -7638,7 +7716,7 @@ authRoutes.post(
|
|
|
7638
7716
|
);
|
|
7639
7717
|
authRoutes.post(
|
|
7640
7718
|
"/register/form",
|
|
7641
|
-
|
|
7719
|
+
chunkBRKXMRMB_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "register" }),
|
|
7642
7720
|
async (c) => {
|
|
7643
7721
|
try {
|
|
7644
7722
|
const db = c.env.DB;
|
|
@@ -7683,7 +7761,7 @@ authRoutes.post(
|
|
|
7683
7761
|
</div>
|
|
7684
7762
|
`);
|
|
7685
7763
|
}
|
|
7686
|
-
const passwordHash = await
|
|
7764
|
+
const passwordHash = await chunkBRKXMRMB_cjs.AuthManager.hashPassword(password);
|
|
7687
7765
|
const role = isFirstUser ? "admin" : "viewer";
|
|
7688
7766
|
const userId = crypto.randomUUID();
|
|
7689
7767
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -7717,7 +7795,7 @@ authRoutes.post(
|
|
|
7717
7795
|
await saveCustomData(db, userId, sanitized);
|
|
7718
7796
|
}
|
|
7719
7797
|
}
|
|
7720
|
-
const rbacService = new
|
|
7798
|
+
const rbacService = new chunkOLEOKHDX_cjs.RbacService(db);
|
|
7721
7799
|
await rbacService.addUserRoleByName(userId, role);
|
|
7722
7800
|
dispatchHookEvent(
|
|
7723
7801
|
c,
|
|
@@ -7725,8 +7803,8 @@ authRoutes.post(
|
|
|
7725
7803
|
{ user: { id: userId, email: normalizedEmail, role } },
|
|
7726
7804
|
"fire-and-forget"
|
|
7727
7805
|
);
|
|
7728
|
-
const tokenTtl = await
|
|
7729
|
-
const token = await
|
|
7806
|
+
const tokenTtl = await chunkBRKXMRMB_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
|
|
7807
|
+
const token = await chunkBRKXMRMB_cjs.AuthManager.generateToken(userId, normalizedEmail, role, c.env.JWT_SECRET, tokenTtl);
|
|
7730
7808
|
cookie.setCookie(c, "auth_token", token, {
|
|
7731
7809
|
httpOnly: true,
|
|
7732
7810
|
secure: false,
|
|
@@ -7758,7 +7836,7 @@ authRoutes.post(
|
|
|
7758
7836
|
);
|
|
7759
7837
|
authRoutes.post(
|
|
7760
7838
|
"/login/form",
|
|
7761
|
-
|
|
7839
|
+
chunkBRKXMRMB_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "login" }),
|
|
7762
7840
|
async (c) => {
|
|
7763
7841
|
try {
|
|
7764
7842
|
const formData = await c.req.formData();
|
|
@@ -7772,7 +7850,7 @@ authRoutes.post(
|
|
|
7772
7850
|
</div>
|
|
7773
7851
|
`);
|
|
7774
7852
|
}
|
|
7775
|
-
const { createAuth } = await import('./config-
|
|
7853
|
+
const { createAuth } = await import('./config-VLU73ZW7.cjs');
|
|
7776
7854
|
const auth = createAuth(c.env, void 0, new URL(c.req.url).origin);
|
|
7777
7855
|
const baReq = new Request(new URL("/auth/sign-in/email", c.req.url).href, {
|
|
7778
7856
|
method: "POST",
|
|
@@ -7837,14 +7915,14 @@ authRoutes.post(
|
|
|
7837
7915
|
);
|
|
7838
7916
|
authRoutes.post(
|
|
7839
7917
|
"/seed-admin",
|
|
7840
|
-
|
|
7918
|
+
chunkBRKXMRMB_cjs.rateLimit({ max: 10, windowMs: 60 * 1e3, keyPrefix: "seed-admin" }),
|
|
7841
7919
|
async (c) => {
|
|
7842
7920
|
try {
|
|
7843
7921
|
const db = c.env.DB;
|
|
7844
|
-
const rbac = new
|
|
7922
|
+
const rbac = new chunkOLEOKHDX_cjs.RbacService(db);
|
|
7845
7923
|
const results = [];
|
|
7846
7924
|
const upsertSeedUser = async (opts) => {
|
|
7847
|
-
const passwordHash = await
|
|
7925
|
+
const passwordHash = await chunkBRKXMRMB_cjs.AuthManager.hashPassword(opts.password);
|
|
7848
7926
|
const nowMs = Date.now();
|
|
7849
7927
|
const nowSec = Math.floor(nowMs / 1e3);
|
|
7850
7928
|
const existing = await db.prepare("SELECT id FROM auth_user WHERE email = ?").bind(opts.email).first();
|
|
@@ -8069,7 +8147,7 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
8069
8147
|
if (invitationAge > maxAge) {
|
|
8070
8148
|
return c.json({ error: "Invitation has expired" }, 400);
|
|
8071
8149
|
}
|
|
8072
|
-
const passwordHash = await
|
|
8150
|
+
const passwordHash = await chunkBRKXMRMB_cjs.AuthManager.hashPassword(password);
|
|
8073
8151
|
const updateStmt = db.prepare(`
|
|
8074
8152
|
UPDATE auth_user SET
|
|
8075
8153
|
password_hash = ?,
|
|
@@ -8086,8 +8164,8 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
8086
8164
|
Date.now(),
|
|
8087
8165
|
invitedUser.id
|
|
8088
8166
|
).run();
|
|
8089
|
-
const tokenTtl = await
|
|
8090
|
-
const authToken = await
|
|
8167
|
+
const tokenTtl = await chunkBRKXMRMB_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
|
|
8168
|
+
const authToken = await chunkBRKXMRMB_cjs.AuthManager.generateToken(invitedUser.id, invitedUser.email, invitedUser.role, c.env.JWT_SECRET, tokenTtl);
|
|
8091
8169
|
cookie.setCookie(c, "auth_token", authToken, {
|
|
8092
8170
|
httpOnly: true,
|
|
8093
8171
|
secure: true,
|
|
@@ -8103,7 +8181,7 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
8103
8181
|
});
|
|
8104
8182
|
authRoutes.post(
|
|
8105
8183
|
"/request-password-reset",
|
|
8106
|
-
|
|
8184
|
+
chunkBRKXMRMB_cjs.rateLimit({ max: 3, windowMs: 15 * 60 * 1e3, keyPrefix: "password-reset" }),
|
|
8107
8185
|
async (c) => {
|
|
8108
8186
|
try {
|
|
8109
8187
|
const formData = await c.req.formData();
|
|
@@ -8340,7 +8418,7 @@ authRoutes.post("/reset-password", async (c) => {
|
|
|
8340
8418
|
if (Date.now() > user.password_reset_expires) {
|
|
8341
8419
|
return c.json({ error: "Reset token has expired" }, 400);
|
|
8342
8420
|
}
|
|
8343
|
-
const newPasswordHash = await
|
|
8421
|
+
const newPasswordHash = await chunkBRKXMRMB_cjs.AuthManager.hashPassword(password);
|
|
8344
8422
|
try {
|
|
8345
8423
|
const historyStmt = db.prepare(`
|
|
8346
8424
|
INSERT INTO auth_password_history (id, user_id, password_hash, created_at)
|
|
@@ -8554,7 +8632,7 @@ app.post("/test-seed-defaults", async (c) => {
|
|
|
8554
8632
|
var test_cleanup_default = app;
|
|
8555
8633
|
|
|
8556
8634
|
// src/plugins/available/easy-mdx/index.ts
|
|
8557
|
-
|
|
8635
|
+
chunkKWQNB6UM_cjs.definePlugin({
|
|
8558
8636
|
id: "easy-mdx",
|
|
8559
8637
|
version: "1.0.0",
|
|
8560
8638
|
name: "EasyMDE Markdown Editor",
|
|
@@ -8754,7 +8832,7 @@ function getMDXEditorInitScript(config) {
|
|
|
8754
8832
|
}
|
|
8755
8833
|
|
|
8756
8834
|
// src/plugins/available/tinymce-plugin/index.ts
|
|
8757
|
-
|
|
8835
|
+
chunkKWQNB6UM_cjs.definePlugin({
|
|
8758
8836
|
id: "tinymce-plugin",
|
|
8759
8837
|
version: "1.0.0",
|
|
8760
8838
|
name: "TinyMCE",
|
|
@@ -9024,7 +9102,7 @@ function getQuillCDN(version = "2.0.2") {
|
|
|
9024
9102
|
</style>
|
|
9025
9103
|
`;
|
|
9026
9104
|
}
|
|
9027
|
-
|
|
9105
|
+
chunkKWQNB6UM_cjs.definePlugin({
|
|
9028
9106
|
id: "quill-editor",
|
|
9029
9107
|
version: "1.0.0",
|
|
9030
9108
|
name: "Quill Editor",
|
|
@@ -11497,9 +11575,9 @@ function parseFieldValue(field, formData, options = {}) {
|
|
|
11497
11575
|
const { skipValidation = false } = options;
|
|
11498
11576
|
const value = formData.get(field.field_name);
|
|
11499
11577
|
const errors = [];
|
|
11500
|
-
const blocksConfig =
|
|
11578
|
+
const blocksConfig = chunkSFGYZUWU_cjs.getBlocksFieldConfig(field.field_options);
|
|
11501
11579
|
if (blocksConfig) {
|
|
11502
|
-
const parsed =
|
|
11580
|
+
const parsed = chunkSFGYZUWU_cjs.parseBlocksValue(value, blocksConfig);
|
|
11503
11581
|
if (!skipValidation && field.is_required && parsed.value.length === 0) {
|
|
11504
11582
|
parsed.errors.push(`${field.field_label} is required`);
|
|
11505
11583
|
}
|
|
@@ -11609,7 +11687,7 @@ function extractFieldData(fields, formData, options = {}) {
|
|
|
11609
11687
|
}
|
|
11610
11688
|
return { data, errors };
|
|
11611
11689
|
}
|
|
11612
|
-
adminContentRoutes.use("*",
|
|
11690
|
+
adminContentRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
|
|
11613
11691
|
async function getCollectionFields(db, collectionId) {
|
|
11614
11692
|
console.log(`[getCollectionFields] Loading fields for collection: ${collectionId}`);
|
|
11615
11693
|
const collectionStmt = db.prepare("SELECT schema, queryable_fields FROM document_types WHERE id = ?");
|
|
@@ -11636,7 +11714,7 @@ async function getCollectionFields(db, collectionId) {
|
|
|
11636
11714
|
};
|
|
11637
11715
|
});
|
|
11638
11716
|
}
|
|
11639
|
-
const codeCollections2 = await
|
|
11717
|
+
const codeCollections2 = await chunk4DHPR7KR_cjs.loadCollectionConfigs();
|
|
11640
11718
|
const codeMatch = codeCollections2.find((c) => c.name === collectionId);
|
|
11641
11719
|
if (codeMatch && codeMatch.schema?.properties) {
|
|
11642
11720
|
console.log(`[getCollectionFields] DB doc type has no properties \u2014 using code collection schema`);
|
|
@@ -11668,7 +11746,7 @@ async function getCollectionFields(db, collectionId) {
|
|
|
11668
11746
|
}
|
|
11669
11747
|
}
|
|
11670
11748
|
console.log(`[getCollectionFields] Not in database, checking code collections`);
|
|
11671
|
-
const codeCollections = await
|
|
11749
|
+
const codeCollections = await chunk4DHPR7KR_cjs.loadCollectionConfigs();
|
|
11672
11750
|
console.log(`[getCollectionFields] Found ${codeCollections.length} code collections`);
|
|
11673
11751
|
const codeCollection = codeCollections.find((c) => c.name === collectionId);
|
|
11674
11752
|
if (codeCollection && codeCollection.schema) {
|
|
@@ -11704,7 +11782,7 @@ async function getCollectionFields(db, collectionId) {
|
|
|
11704
11782
|
}
|
|
11705
11783
|
async function getCollection(db, collectionId) {
|
|
11706
11784
|
console.log(`[getCollection] Loading collection by ID: ${collectionId}`);
|
|
11707
|
-
const cache =
|
|
11785
|
+
const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.collection);
|
|
11708
11786
|
return cache.getOrSet(
|
|
11709
11787
|
cache.generateKey("collection", collectionId),
|
|
11710
11788
|
async () => {
|
|
@@ -11722,7 +11800,7 @@ async function getCollection(db, collectionId) {
|
|
|
11722
11800
|
};
|
|
11723
11801
|
}
|
|
11724
11802
|
console.log(`[getCollection] Not in database, checking code collections`);
|
|
11725
|
-
const codeCollections = await
|
|
11803
|
+
const codeCollections = await chunk4DHPR7KR_cjs.loadCollectionConfigs();
|
|
11726
11804
|
const codeCollection = codeCollections.find((c) => c.name === collectionId);
|
|
11727
11805
|
if (codeCollection) {
|
|
11728
11806
|
console.log(`[getCollection] Found code collection: ${collectionId}`);
|
|
@@ -11741,7 +11819,7 @@ async function getCollection(db, collectionId) {
|
|
|
11741
11819
|
}
|
|
11742
11820
|
async function getDocBackingType(db, collectionName) {
|
|
11743
11821
|
if (!collectionName) return null;
|
|
11744
|
-
const dt = await new
|
|
11822
|
+
const dt = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(collectionName);
|
|
11745
11823
|
return dt && dt.isActive ? dt : null;
|
|
11746
11824
|
}
|
|
11747
11825
|
async function getCollectionByName(db, name) {
|
|
@@ -11758,7 +11836,7 @@ async function getCollectionByName(db, name) {
|
|
|
11758
11836
|
};
|
|
11759
11837
|
}
|
|
11760
11838
|
console.log(`[getCollectionByName] Not in database, checking code collections`);
|
|
11761
|
-
const codeCollections = await
|
|
11839
|
+
const codeCollections = await chunk4DHPR7KR_cjs.loadCollectionConfigs();
|
|
11762
11840
|
const codeCollection = codeCollections.find((c) => c.name === name);
|
|
11763
11841
|
if (codeCollection) {
|
|
11764
11842
|
console.log(`[getCollectionByName] Found code collection: ${name}`);
|
|
@@ -11774,7 +11852,7 @@ async function getCollectionByName(db, name) {
|
|
|
11774
11852
|
return null;
|
|
11775
11853
|
}
|
|
11776
11854
|
async function loadContentEditorFlags(db) {
|
|
11777
|
-
const flags = { workflowEnabled: await
|
|
11855
|
+
const flags = { workflowEnabled: await chunk4DHPR7KR_cjs.isPluginActive(db, "workflow") };
|
|
11778
11856
|
const editors = [
|
|
11779
11857
|
["tinymce-plugin", "tinymce"],
|
|
11780
11858
|
["quill-editor", "quill"],
|
|
@@ -11782,10 +11860,10 @@ async function loadContentEditorFlags(db) {
|
|
|
11782
11860
|
["lexical-editor", "lexical"]
|
|
11783
11861
|
];
|
|
11784
11862
|
for (const [plugin, key] of editors) {
|
|
11785
|
-
const enabled = await
|
|
11863
|
+
const enabled = await chunk4DHPR7KR_cjs.isPluginActive(db, plugin);
|
|
11786
11864
|
flags[`${key}Enabled`] = enabled;
|
|
11787
11865
|
if (enabled) {
|
|
11788
|
-
const ps = new
|
|
11866
|
+
const ps = new chunk4DHPR7KR_cjs.PluginService(db);
|
|
11789
11867
|
const p = await ps.getPlugin(plugin);
|
|
11790
11868
|
flags[`${key}Settings`] = p?.settings;
|
|
11791
11869
|
}
|
|
@@ -11793,7 +11871,7 @@ async function loadContentEditorFlags(db) {
|
|
|
11793
11871
|
return flags;
|
|
11794
11872
|
}
|
|
11795
11873
|
function makeDocService(db, docType, tenantId) {
|
|
11796
|
-
return new
|
|
11874
|
+
return new chunkOLEOKHDX_cjs.DocumentsService(db, {
|
|
11797
11875
|
queryableFields: docType.queryableFields ?? [],
|
|
11798
11876
|
typeSchemaVersion: docType.schemaVersion ?? 1,
|
|
11799
11877
|
maxVersionsPerRoot: docType.settings?.maxVersionsPerRoot ?? 50,
|
|
@@ -11821,9 +11899,9 @@ adminContentRoutes.get("/", async (c) => {
|
|
|
11821
11899
|
const offset = (page - 1) * limit;
|
|
11822
11900
|
const collectionsStmt = db.prepare("SELECT id, name, display_name FROM document_types WHERE is_active = 1 ORDER BY display_name");
|
|
11823
11901
|
const { results: collectionsResults } = await collectionsStmt.all();
|
|
11824
|
-
const codeCollections = await
|
|
11902
|
+
const codeCollections = await chunk4DHPR7KR_cjs.loadCollectionConfigs();
|
|
11825
11903
|
const codeCollectionMap = new Map(codeCollections.map((c2) => [c2.name, c2]));
|
|
11826
|
-
const docTypeRegistry = new
|
|
11904
|
+
const docTypeRegistry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db);
|
|
11827
11905
|
const docTypes = (await docTypeRegistry.findAll()).filter((dt) => !dt.settings?.internal && !dt.isAuth);
|
|
11828
11906
|
const visibleTypeIds = new Set(docTypes.map((dt) => dt.id));
|
|
11829
11907
|
const allCollections = [
|
|
@@ -11835,7 +11913,7 @@ adminContentRoutes.get("/", async (c) => {
|
|
|
11835
11913
|
...allCollections.map((c2) => ({ name: c2.name, displayName: c2.displayName })),
|
|
11836
11914
|
...docTypes.filter((dt) => !collectionNames.has(dt.id)).map((dt) => ({ name: `doc:${dt.id}`, displayName: dt.displayName }))
|
|
11837
11915
|
];
|
|
11838
|
-
const newContentCollections = await
|
|
11916
|
+
const newContentCollections = await chunk4DHPR7KR_cjs.getVisibleCollections(db);
|
|
11839
11917
|
const docBackedCollection = !modelName.startsWith("doc:") && modelName !== "all" ? docTypes.find((dt) => dt.id === modelName) : void 0;
|
|
11840
11918
|
const isDocModel = modelName.startsWith("doc:") || !!docBackedCollection;
|
|
11841
11919
|
if (isDocModel) {
|
|
@@ -12120,9 +12198,9 @@ adminContentRoutes.get("/new", async (c) => {
|
|
|
12120
12198
|
const collectionsStmt = db2.prepare("SELECT id, name, display_name, description FROM document_types WHERE is_active = 1 ORDER BY display_name");
|
|
12121
12199
|
const { results } = await collectionsStmt.all();
|
|
12122
12200
|
const visibleTypeIds = new Set(
|
|
12123
|
-
(await new
|
|
12201
|
+
(await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db2).findAll()).filter((dt) => !dt.settings?.internal && !dt.isAuth).map((dt) => dt.id)
|
|
12124
12202
|
);
|
|
12125
|
-
const codeCollections = await
|
|
12203
|
+
const codeCollections = await chunk4DHPR7KR_cjs.loadCollectionConfigs();
|
|
12126
12204
|
const dbCollectionNames = new Set((results || []).map((r) => r.name));
|
|
12127
12205
|
const allCollections = [
|
|
12128
12206
|
...codeCollections.filter((c2) => !dbCollectionNames.has(c2.name)).map((c2) => ({
|
|
@@ -12188,32 +12266,32 @@ adminContentRoutes.get("/new", async (c) => {
|
|
|
12188
12266
|
return c.html(renderContentFormPage(formData2));
|
|
12189
12267
|
}
|
|
12190
12268
|
const fields = await getCollectionFields(db, collection.id);
|
|
12191
|
-
const workflowEnabled = await
|
|
12192
|
-
const tinymceEnabled = await
|
|
12269
|
+
const workflowEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "workflow");
|
|
12270
|
+
const tinymceEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "tinymce-plugin");
|
|
12193
12271
|
let tinymceSettings;
|
|
12194
12272
|
if (tinymceEnabled) {
|
|
12195
|
-
const pluginService = new
|
|
12273
|
+
const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
|
|
12196
12274
|
const tinymcePlugin2 = await pluginService.getPlugin("tinymce-plugin");
|
|
12197
12275
|
tinymceSettings = tinymcePlugin2?.settings;
|
|
12198
12276
|
}
|
|
12199
|
-
const quillEnabled = await
|
|
12277
|
+
const quillEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "quill-editor");
|
|
12200
12278
|
let quillSettings;
|
|
12201
12279
|
if (quillEnabled) {
|
|
12202
|
-
const pluginService = new
|
|
12280
|
+
const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
|
|
12203
12281
|
const quillPlugin = await pluginService.getPlugin("quill-editor");
|
|
12204
12282
|
quillSettings = quillPlugin?.settings;
|
|
12205
12283
|
}
|
|
12206
|
-
const mdxeditorEnabled = await
|
|
12284
|
+
const mdxeditorEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "easy-mdx");
|
|
12207
12285
|
let mdxeditorSettings;
|
|
12208
12286
|
if (mdxeditorEnabled) {
|
|
12209
|
-
const pluginService = new
|
|
12287
|
+
const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
|
|
12210
12288
|
const mdxeditorPlugin = await pluginService.getPlugin("easy-mdx");
|
|
12211
12289
|
mdxeditorSettings = mdxeditorPlugin?.settings;
|
|
12212
12290
|
}
|
|
12213
|
-
const lexicalEnabled = await
|
|
12291
|
+
const lexicalEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "lexical-editor");
|
|
12214
12292
|
let lexicalSettings;
|
|
12215
12293
|
if (lexicalEnabled) {
|
|
12216
|
-
const pluginService = new
|
|
12294
|
+
const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
|
|
12217
12295
|
const lexicalPlugin = await pluginService.getPlugin("lexical-editor");
|
|
12218
12296
|
lexicalSettings = lexicalPlugin?.settings;
|
|
12219
12297
|
}
|
|
@@ -12312,7 +12390,7 @@ adminContentRoutes.get("/:id/edit", async (c) => {
|
|
|
12312
12390
|
} : void 0
|
|
12313
12391
|
};
|
|
12314
12392
|
return c.html(renderContentFormPage(notFoundData));
|
|
12315
|
-
const cache =
|
|
12393
|
+
const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.content);
|
|
12316
12394
|
const content = await cache.getOrSet(
|
|
12317
12395
|
cache.generateKey("content", id),
|
|
12318
12396
|
async () => {
|
|
@@ -12349,32 +12427,32 @@ adminContentRoutes.get("/:id/edit", async (c) => {
|
|
|
12349
12427
|
};
|
|
12350
12428
|
const fields = await getCollectionFields(db, content.collection_id);
|
|
12351
12429
|
const contentData = content.data ? JSON.parse(content.data) : {};
|
|
12352
|
-
const workflowEnabled = await
|
|
12353
|
-
const tinymceEnabled = await
|
|
12430
|
+
const workflowEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "workflow");
|
|
12431
|
+
const tinymceEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "tinymce-plugin");
|
|
12354
12432
|
let tinymceSettings;
|
|
12355
12433
|
if (tinymceEnabled) {
|
|
12356
|
-
const pluginService = new
|
|
12434
|
+
const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
|
|
12357
12435
|
const tinymcePlugin2 = await pluginService.getPlugin("tinymce-plugin");
|
|
12358
12436
|
tinymceSettings = tinymcePlugin2?.settings;
|
|
12359
12437
|
}
|
|
12360
|
-
const quillEnabled = await
|
|
12438
|
+
const quillEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "quill-editor");
|
|
12361
12439
|
let quillSettings;
|
|
12362
12440
|
if (quillEnabled) {
|
|
12363
|
-
const pluginService = new
|
|
12441
|
+
const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
|
|
12364
12442
|
const quillPlugin = await pluginService.getPlugin("quill-editor");
|
|
12365
12443
|
quillSettings = quillPlugin?.settings;
|
|
12366
12444
|
}
|
|
12367
|
-
const mdxeditorEnabled = await
|
|
12445
|
+
const mdxeditorEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "easy-mdx");
|
|
12368
12446
|
let mdxeditorSettings;
|
|
12369
12447
|
if (mdxeditorEnabled) {
|
|
12370
|
-
const pluginService = new
|
|
12448
|
+
const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
|
|
12371
12449
|
const mdxeditorPlugin = await pluginService.getPlugin("easy-mdx");
|
|
12372
12450
|
mdxeditorSettings = mdxeditorPlugin?.settings;
|
|
12373
12451
|
}
|
|
12374
|
-
const lexicalEnabled = await
|
|
12452
|
+
const lexicalEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "lexical-editor");
|
|
12375
12453
|
let lexicalSettings;
|
|
12376
12454
|
if (lexicalEnabled) {
|
|
12377
|
-
const pluginService = new
|
|
12455
|
+
const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
|
|
12378
12456
|
const lexicalPlugin = await pluginService.getPlugin("lexical-editor");
|
|
12379
12457
|
lexicalSettings = lexicalPlugin?.settings;
|
|
12380
12458
|
}
|
|
@@ -12497,9 +12575,9 @@ adminContentRoutes.post("/", async (c) => {
|
|
|
12497
12575
|
data,
|
|
12498
12576
|
publishOnCreate: status === "published"
|
|
12499
12577
|
}), user?.userId);
|
|
12500
|
-
const cache2 =
|
|
12578
|
+
const cache2 = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.content);
|
|
12501
12579
|
await cache2.invalidate(`content:list:${collectionId}:*`);
|
|
12502
|
-
const apiCacheCreate =
|
|
12580
|
+
const apiCacheCreate = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
|
|
12503
12581
|
await apiCacheCreate.invalidate("api:content-filtered:*");
|
|
12504
12582
|
await apiCacheCreate.invalidate(`api:collection-content-filtered:${createDocType.id}:*`);
|
|
12505
12583
|
const redirectUrl2 = `/admin/content/${doc.rootId}/edit?success=Content created successfully!`;
|
|
@@ -12530,7 +12608,7 @@ adminContentRoutes.post("/", async (c) => {
|
|
|
12530
12608
|
now,
|
|
12531
12609
|
now
|
|
12532
12610
|
).run();
|
|
12533
|
-
const cache =
|
|
12611
|
+
const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.content);
|
|
12534
12612
|
await cache.invalidate(`content:list:${collectionId}:*`);
|
|
12535
12613
|
const versionStmt = db.prepare(`
|
|
12536
12614
|
INSERT INTO content_versions (id, content_id, version, data, author_id, created_at)
|
|
@@ -12619,8 +12697,8 @@ adminContentRoutes.put("/:id", async (c) => {
|
|
|
12619
12697
|
const pub = await db.prepare("SELECT id FROM documents WHERE root_id = ? AND is_published = 1 AND tenant_id = ?").bind(id, tenantId).first();
|
|
12620
12698
|
if (status2 === "published") await svc.publish(newDraft.id, user?.userId);
|
|
12621
12699
|
else if (pub) await svc.unpublish(pub.id);
|
|
12622
|
-
await
|
|
12623
|
-
const apiCacheEdit =
|
|
12700
|
+
await chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.content).invalidate(`content:list:*`);
|
|
12701
|
+
const apiCacheEdit = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
|
|
12624
12702
|
await apiCacheEdit.invalidate("api:content-filtered:*");
|
|
12625
12703
|
await apiCacheEdit.invalidate(`api:collection-content-filtered:${docRowU.type_id}:*`);
|
|
12626
12704
|
const isHTMX2 = c.req.header("HX-Request") === "true";
|
|
@@ -12722,7 +12800,7 @@ adminContentRoutes.put("/:id", async (c) => {
|
|
|
12722
12800
|
now,
|
|
12723
12801
|
id
|
|
12724
12802
|
).run();
|
|
12725
|
-
const cache =
|
|
12803
|
+
const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.content);
|
|
12726
12804
|
await cache.delete(cache.generateKey("content", id));
|
|
12727
12805
|
await cache.invalidate(`content:list:${existingContent.collection_id}:*`);
|
|
12728
12806
|
const existingData = JSON.parse(existingContent.data || "{}");
|
|
@@ -12774,7 +12852,7 @@ adminContentRoutes.put("/:id", async (c) => {
|
|
|
12774
12852
|
`);
|
|
12775
12853
|
}
|
|
12776
12854
|
});
|
|
12777
|
-
adminContentRoutes.post("/preview",
|
|
12855
|
+
adminContentRoutes.post("/preview", chunkBRKXMRMB_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
12778
12856
|
try {
|
|
12779
12857
|
const formData = await c.req.formData();
|
|
12780
12858
|
const collectionId = formData.get("collection_id");
|
|
@@ -13029,12 +13107,12 @@ adminContentRoutes.post("/bulk-action", async (c) => {
|
|
|
13029
13107
|
}
|
|
13030
13108
|
}
|
|
13031
13109
|
}
|
|
13032
|
-
const cache =
|
|
13110
|
+
const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.content);
|
|
13033
13111
|
for (const contentId of ids) {
|
|
13034
13112
|
await cache.delete(cache.generateKey("content", contentId));
|
|
13035
13113
|
}
|
|
13036
13114
|
await cache.invalidate("content:list:*");
|
|
13037
|
-
const apiCache =
|
|
13115
|
+
const apiCache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
|
|
13038
13116
|
await apiCache.invalidate("api:content-filtered:*");
|
|
13039
13117
|
await apiCache.invalidate("api:collection-content-filtered:*");
|
|
13040
13118
|
return c.json({ success: true, count: ids.length });
|
|
@@ -13053,8 +13131,8 @@ adminContentRoutes.delete("/:id", async (c) => {
|
|
|
13053
13131
|
if (docDel && await getDocBackingType(db, docDel.type_id)) {
|
|
13054
13132
|
const now2 = Math.floor(Date.now() / 1e3);
|
|
13055
13133
|
await db.prepare("UPDATE documents SET deleted_at = ?, updated_at = ? WHERE root_id = ? AND tenant_id = ?").bind(now2, now2, id, tenantId).run();
|
|
13056
|
-
await
|
|
13057
|
-
const apiCacheDel =
|
|
13134
|
+
await chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.content).invalidate("content:list:*");
|
|
13135
|
+
const apiCacheDel = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
|
|
13058
13136
|
await apiCacheDel.invalidate("api:content-filtered:*");
|
|
13059
13137
|
await apiCacheDel.invalidate(`api:collection-content-filtered:${docDel.type_id}:*`);
|
|
13060
13138
|
return c.html(`
|
|
@@ -13076,7 +13154,7 @@ adminContentRoutes.delete("/:id", async (c) => {
|
|
|
13076
13154
|
WHERE id = ?
|
|
13077
13155
|
`);
|
|
13078
13156
|
await deleteStmt.bind(now, id).run();
|
|
13079
|
-
const cache =
|
|
13157
|
+
const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.content);
|
|
13080
13158
|
await cache.delete(cache.generateKey("content", id));
|
|
13081
13159
|
await cache.invalidate("content:list:*");
|
|
13082
13160
|
return c.html(`
|
|
@@ -13096,7 +13174,7 @@ adminContentRoutes.delete("/:id", async (c) => {
|
|
|
13096
13174
|
return c.json({ success: false, error: "Failed to delete content" }, 500);
|
|
13097
13175
|
}
|
|
13098
13176
|
});
|
|
13099
|
-
adminContentRoutes.get("/:id/version/:version/preview",
|
|
13177
|
+
adminContentRoutes.get("/:id/version/:version/preview", chunkBRKXMRMB_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
13100
13178
|
try {
|
|
13101
13179
|
const id = c.req.param("id");
|
|
13102
13180
|
const version = parseInt(c.req.param("version") || "0");
|
|
@@ -13192,9 +13270,9 @@ function parseDocFormData(formData, queryableFields = []) {
|
|
|
13192
13270
|
return { title, slug, data };
|
|
13193
13271
|
}
|
|
13194
13272
|
async function getDocService(db, typeId, tenantId) {
|
|
13195
|
-
const registry = new
|
|
13273
|
+
const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db);
|
|
13196
13274
|
const docType = await registry.findById(typeId);
|
|
13197
|
-
const svc = new
|
|
13275
|
+
const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, {
|
|
13198
13276
|
queryableFields: docType?.queryableFields ?? [],
|
|
13199
13277
|
typeSchemaVersion: docType?.schemaVersion ?? 1,
|
|
13200
13278
|
maxVersionsPerRoot: docType?.settings?.maxVersionsPerRoot ?? 50,
|
|
@@ -13205,7 +13283,7 @@ async function getDocService(db, typeId, tenantId) {
|
|
|
13205
13283
|
}
|
|
13206
13284
|
adminContentRoutes.get("/documents/:typeId/new", async (c) => {
|
|
13207
13285
|
const { typeId } = c.req.param();
|
|
13208
|
-
const registry = new
|
|
13286
|
+
const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(c.env.DB);
|
|
13209
13287
|
const docType = await registry.findById(typeId);
|
|
13210
13288
|
if (!docType) return c.html("<p>Unknown document type.</p>", 404);
|
|
13211
13289
|
return c.html(chunkTT3TQSCZ_cjs.renderDocumentFormPage({ docType, isEdit: false, user: userCtx(c) }));
|
|
@@ -13230,7 +13308,7 @@ adminContentRoutes.post("/documents/:typeId/new", async (c) => {
|
|
|
13230
13308
|
}), user?.userId);
|
|
13231
13309
|
return c.redirect(`/admin/content/documents/${typeId}/${doc.rootId}/edit?message=Created+successfully`);
|
|
13232
13310
|
} catch (err) {
|
|
13233
|
-
const registry = new
|
|
13311
|
+
const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(c.env.DB);
|
|
13234
13312
|
const docType = await registry.findById(typeId);
|
|
13235
13313
|
if (!docType) return c.html("<p>Unknown document type.</p>", 404);
|
|
13236
13314
|
return c.html(chunkTT3TQSCZ_cjs.renderDocumentFormPage({ docType, isEdit: false, user: userCtx(c), message: err?.message ?? "Failed to create", messageType: "error" }));
|
|
@@ -13240,7 +13318,7 @@ adminContentRoutes.get("/documents/:typeId/:rootId/edit", async (c) => {
|
|
|
13240
13318
|
const { typeId, rootId } = c.req.param();
|
|
13241
13319
|
const db = c.env.DB;
|
|
13242
13320
|
const message = c.req.query("message");
|
|
13243
|
-
const registry = new
|
|
13321
|
+
const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db);
|
|
13244
13322
|
const docType = await registry.findById(typeId);
|
|
13245
13323
|
if (!docType) return c.html("<p>Unknown document type.</p>", 404);
|
|
13246
13324
|
const tenantId = reqTenant(c);
|
|
@@ -13353,7 +13431,7 @@ adminContentRoutes.get("/documents/:typeId/:rootId/versions", async (c) => {
|
|
|
13353
13431
|
const { typeId, rootId } = c.req.param();
|
|
13354
13432
|
const db = c.env.DB;
|
|
13355
13433
|
const { renderVersionHistoryFragment } = await import('./admin-documents-form.template-UWKGVAMW.cjs');
|
|
13356
|
-
const registry = new
|
|
13434
|
+
const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db);
|
|
13357
13435
|
const docType = await registry.findById(typeId);
|
|
13358
13436
|
if (!docType) return c.html("<div>Unknown type.</div>", 404);
|
|
13359
13437
|
const result = await db.prepare(
|
|
@@ -15286,7 +15364,7 @@ var TenantService = class {
|
|
|
15286
15364
|
SET name = ?, domain = ?, status = ?, notes = ?, updated_at = ?
|
|
15287
15365
|
WHERE slug = ?
|
|
15288
15366
|
`).bind(name, domain, status, notes, now, slug).run();
|
|
15289
|
-
|
|
15367
|
+
chunk4DHPR7KR_cjs.invalidateTenantCache();
|
|
15290
15368
|
const updated = await this.getTenantBySlug(slug);
|
|
15291
15369
|
if (!updated) throw new Error("Tenant not found");
|
|
15292
15370
|
return updated;
|
|
@@ -15304,7 +15382,7 @@ var TenantService = class {
|
|
|
15304
15382
|
throw new Error(`Tenant '${slug}' still owns ${docCount} document(s). Delete or migrate its content first.`);
|
|
15305
15383
|
}
|
|
15306
15384
|
await this.db.prepare(`DELETE FROM auth_tenant WHERE slug = ?`).bind(slug).run();
|
|
15307
|
-
|
|
15385
|
+
chunk4DHPR7KR_cjs.invalidateTenantCache();
|
|
15308
15386
|
}
|
|
15309
15387
|
// ─── Membership (auth_tenant_member) ───────────────────────────────────────
|
|
15310
15388
|
// Tenant resolution and the admin switcher are gated on membership: an authed user may only
|
|
@@ -15548,7 +15626,7 @@ var TenantService = class {
|
|
|
15548
15626
|
INSERT INTO auth_tenant (id, name, slug, status, domain, notes, metadata, created_at, updated_at)
|
|
15549
15627
|
VALUES (?, ?, ?, 'active', ?, ?, '{}', ?, ?)
|
|
15550
15628
|
`).bind(id, input.name, input.slug, input.domain, input.notes, now, now).run();
|
|
15551
|
-
|
|
15629
|
+
chunk4DHPR7KR_cjs.invalidateTenantCache();
|
|
15552
15630
|
const created = await this.getTenantBySlug(input.slug);
|
|
15553
15631
|
if (!created) throw new Error("Failed to create tenant");
|
|
15554
15632
|
return created;
|
|
@@ -15572,14 +15650,14 @@ function mapRowToTenant(row) {
|
|
|
15572
15650
|
|
|
15573
15651
|
// src/routes/admin-users.ts
|
|
15574
15652
|
var userRoutes = new hono.Hono();
|
|
15575
|
-
userRoutes.use("*",
|
|
15576
|
-
userRoutes.use("/users/*",
|
|
15577
|
-
userRoutes.use("/users",
|
|
15578
|
-
userRoutes.use("/invite-user",
|
|
15579
|
-
userRoutes.use("/resend-invitation/*",
|
|
15580
|
-
userRoutes.use("/cancel-invitation/*",
|
|
15581
|
-
userRoutes.use("/activity-logs",
|
|
15582
|
-
userRoutes.use("/activity-logs/*",
|
|
15653
|
+
userRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
|
|
15654
|
+
userRoutes.use("/users/*", chunkBRKXMRMB_cjs.requireRole(["admin"]));
|
|
15655
|
+
userRoutes.use("/users", chunkBRKXMRMB_cjs.requireRole(["admin"]));
|
|
15656
|
+
userRoutes.use("/invite-user", chunkBRKXMRMB_cjs.requireRole(["admin"]));
|
|
15657
|
+
userRoutes.use("/resend-invitation/*", chunkBRKXMRMB_cjs.requireRole(["admin"]));
|
|
15658
|
+
userRoutes.use("/cancel-invitation/*", chunkBRKXMRMB_cjs.requireRole(["admin"]));
|
|
15659
|
+
userRoutes.use("/activity-logs", chunkBRKXMRMB_cjs.requireRole(["admin"]));
|
|
15660
|
+
userRoutes.use("/activity-logs/*", chunkBRKXMRMB_cjs.requireRole(["admin"]));
|
|
15583
15661
|
userRoutes.get("/", (c) => {
|
|
15584
15662
|
return c.redirect("/admin/dashboard");
|
|
15585
15663
|
});
|
|
@@ -15608,7 +15686,7 @@ var LANGUAGES = [
|
|
|
15608
15686
|
{ value: "zh", label: "Chinese" }
|
|
15609
15687
|
];
|
|
15610
15688
|
async function fetchRoleOptions(db) {
|
|
15611
|
-
const roles = await new
|
|
15689
|
+
const roles = await new chunkOLEOKHDX_cjs.RbacService(db).getRoles();
|
|
15612
15690
|
return roles.map((r) => ({ value: r.id, label: r.display_name }));
|
|
15613
15691
|
}
|
|
15614
15692
|
userRoutes.get("/profile", async (c) => {
|
|
@@ -15744,7 +15822,7 @@ userRoutes.put("/profile", async (c) => {
|
|
|
15744
15822
|
}
|
|
15745
15823
|
await saveCustomData(db, user.userId, sanitized);
|
|
15746
15824
|
}
|
|
15747
|
-
await
|
|
15825
|
+
await chunkBRKXMRMB_cjs.logActivity(
|
|
15748
15826
|
db,
|
|
15749
15827
|
user.userId,
|
|
15750
15828
|
"profile.update",
|
|
@@ -15807,7 +15885,7 @@ userRoutes.post("/profile/avatar", async (c) => {
|
|
|
15807
15885
|
SELECT first_name, last_name FROM auth_user WHERE id = ?
|
|
15808
15886
|
`);
|
|
15809
15887
|
const userData = await userStmt.bind(user.userId).first();
|
|
15810
|
-
await
|
|
15888
|
+
await chunkBRKXMRMB_cjs.logActivity(
|
|
15811
15889
|
db,
|
|
15812
15890
|
user.userId,
|
|
15813
15891
|
"profile.avatar_update",
|
|
@@ -15878,7 +15956,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
15878
15956
|
dismissible: true
|
|
15879
15957
|
}));
|
|
15880
15958
|
}
|
|
15881
|
-
const validPassword = await
|
|
15959
|
+
const validPassword = await chunkBRKXMRMB_cjs.AuthManager.verifyPassword(currentPassword, userData.password_hash);
|
|
15882
15960
|
if (!validPassword) {
|
|
15883
15961
|
return c.html(chunkTT3TQSCZ_cjs.renderAlert({
|
|
15884
15962
|
type: "error",
|
|
@@ -15886,7 +15964,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
15886
15964
|
dismissible: true
|
|
15887
15965
|
}));
|
|
15888
15966
|
}
|
|
15889
|
-
const newPasswordHash = await
|
|
15967
|
+
const newPasswordHash = await chunkBRKXMRMB_cjs.AuthManager.hashPassword(newPassword);
|
|
15890
15968
|
const historyStmt = db.prepare(`
|
|
15891
15969
|
INSERT INTO auth_password_history (id, user_id, password_hash, created_at)
|
|
15892
15970
|
VALUES (?, ?, ?, ?)
|
|
@@ -15902,7 +15980,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
15902
15980
|
WHERE id = ?
|
|
15903
15981
|
`);
|
|
15904
15982
|
await updateStmt.bind(newPasswordHash, Date.now(), user.userId).run();
|
|
15905
|
-
await
|
|
15983
|
+
await chunkBRKXMRMB_cjs.logActivity(
|
|
15906
15984
|
db,
|
|
15907
15985
|
user.userId,
|
|
15908
15986
|
"profile.password_change",
|
|
@@ -15969,7 +16047,7 @@ userRoutes.get("/users", async (c) => {
|
|
|
15969
16047
|
`);
|
|
15970
16048
|
const countResult = await countStmt.bind(...params).first();
|
|
15971
16049
|
const totalUsers = countResult?.total || 0;
|
|
15972
|
-
await
|
|
16050
|
+
await chunkBRKXMRMB_cjs.logActivity(
|
|
15973
16051
|
db,
|
|
15974
16052
|
user.userId,
|
|
15975
16053
|
"users.list_view",
|
|
@@ -16090,7 +16168,7 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
16090
16168
|
const phone = chunkMNWKYY5E_cjs.sanitizeInput(formData.get("phone")?.toString()) || null;
|
|
16091
16169
|
const bio = chunkMNWKYY5E_cjs.sanitizeInput(formData.get("bio")?.toString()) || null;
|
|
16092
16170
|
const roleInput = formData.get("role")?.toString() || "";
|
|
16093
|
-
const validRoles = (await new
|
|
16171
|
+
const validRoles = (await new chunkOLEOKHDX_cjs.RbacService(db).getRoles()).map((r) => r.id);
|
|
16094
16172
|
const role = validRoles.includes(roleInput) ? roleInput : validRoles[0] ?? "admin";
|
|
16095
16173
|
const password = formData.get("password")?.toString() || "";
|
|
16096
16174
|
const confirmPassword = formData.get("confirm_password")?.toString() || "";
|
|
@@ -16151,7 +16229,7 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
16151
16229
|
dismissible: true
|
|
16152
16230
|
}));
|
|
16153
16231
|
}
|
|
16154
|
-
const passwordHash = await
|
|
16232
|
+
const passwordHash = await chunkBRKXMRMB_cjs.AuthManager.hashPassword(password);
|
|
16155
16233
|
const userId = crypto.randomUUID();
|
|
16156
16234
|
const createStmt = db.prepare(`
|
|
16157
16235
|
INSERT INTO auth_user (
|
|
@@ -16176,7 +16254,7 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
16176
16254
|
if (sanitizedRegistrationCustom !== null && Object.keys(sanitizedRegistrationCustom).length > 0) {
|
|
16177
16255
|
await writeProfileData(db, userId, { custom: sanitizedRegistrationCustom }, user.userId);
|
|
16178
16256
|
}
|
|
16179
|
-
await
|
|
16257
|
+
await chunkBRKXMRMB_cjs.logActivity(
|
|
16180
16258
|
db,
|
|
16181
16259
|
user.userId,
|
|
16182
16260
|
"user!.create",
|
|
@@ -16215,7 +16293,7 @@ userRoutes.get("/users/:id", async (c) => {
|
|
|
16215
16293
|
if (!userRecord) {
|
|
16216
16294
|
return c.json({ error: "User not found" }, 404);
|
|
16217
16295
|
}
|
|
16218
|
-
await
|
|
16296
|
+
await chunkBRKXMRMB_cjs.logActivity(
|
|
16219
16297
|
db,
|
|
16220
16298
|
user.userId,
|
|
16221
16299
|
"user!.view",
|
|
@@ -16349,7 +16427,7 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
16349
16427
|
const email = formData.get("email")?.toString()?.trim().toLowerCase() || "";
|
|
16350
16428
|
const phone = chunkMNWKYY5E_cjs.sanitizeInput(formData.get("phone")?.toString()) || null;
|
|
16351
16429
|
const roleInput = formData.get("role")?.toString() || "";
|
|
16352
|
-
const validRoles = (await new
|
|
16430
|
+
const validRoles = (await new chunkOLEOKHDX_cjs.RbacService(db).getRoles()).map((r) => r.id);
|
|
16353
16431
|
const role = validRoles.includes(roleInput) ? roleInput : validRoles[0] ?? "admin";
|
|
16354
16432
|
const isActive = formData.get("is_active") === "1";
|
|
16355
16433
|
const emailVerified = formData.get("email_verified") === "1";
|
|
@@ -16430,7 +16508,7 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
16430
16508
|
userId
|
|
16431
16509
|
).run();
|
|
16432
16510
|
if (newPassword) {
|
|
16433
|
-
const passwordHash = await
|
|
16511
|
+
const passwordHash = await chunkBRKXMRMB_cjs.AuthManager.hashPassword(newPassword);
|
|
16434
16512
|
const updatePasswordStmt = db.prepare(`
|
|
16435
16513
|
UPDATE auth_user SET password_hash = ?, updated_at = ? WHERE id = ?
|
|
16436
16514
|
`);
|
|
@@ -16443,7 +16521,7 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
16443
16521
|
...sanitizedCustom !== null ? { custom: sanitizedCustom } : {}
|
|
16444
16522
|
}, user.userId);
|
|
16445
16523
|
}
|
|
16446
|
-
await
|
|
16524
|
+
await chunkBRKXMRMB_cjs.logActivity(
|
|
16447
16525
|
db,
|
|
16448
16526
|
user.userId,
|
|
16449
16527
|
"user.update",
|
|
@@ -16489,7 +16567,7 @@ userRoutes.post("/users/:id/toggle", async (c) => {
|
|
|
16489
16567
|
UPDATE auth_user SET is_active = ?, updated_at = ? WHERE id = ?
|
|
16490
16568
|
`);
|
|
16491
16569
|
await toggleStmt.bind(active ? 1 : 0, Date.now(), userId).run();
|
|
16492
|
-
await
|
|
16570
|
+
await chunkBRKXMRMB_cjs.logActivity(
|
|
16493
16571
|
db,
|
|
16494
16572
|
user.userId,
|
|
16495
16573
|
active ? "user.activate" : "user.deactivate",
|
|
@@ -16530,7 +16608,7 @@ userRoutes.delete("/users/:id", async (c) => {
|
|
|
16530
16608
|
DELETE FROM auth_user WHERE id = ?
|
|
16531
16609
|
`);
|
|
16532
16610
|
await deleteStmt.bind(userId).run();
|
|
16533
|
-
await
|
|
16611
|
+
await chunkBRKXMRMB_cjs.logActivity(
|
|
16534
16612
|
db,
|
|
16535
16613
|
user.userId,
|
|
16536
16614
|
"user!.hard_delete",
|
|
@@ -16549,7 +16627,7 @@ userRoutes.delete("/users/:id", async (c) => {
|
|
|
16549
16627
|
UPDATE auth_user SET is_active = 0, updated_at = ? WHERE id = ?
|
|
16550
16628
|
`);
|
|
16551
16629
|
await deleteStmt.bind(Date.now(), userId).run();
|
|
16552
|
-
await
|
|
16630
|
+
await chunkBRKXMRMB_cjs.logActivity(
|
|
16553
16631
|
db,
|
|
16554
16632
|
user.userId,
|
|
16555
16633
|
"user!.soft_delete",
|
|
@@ -16615,7 +16693,7 @@ userRoutes.post("/invite-user", async (c) => {
|
|
|
16615
16693
|
Date.now(),
|
|
16616
16694
|
Date.now()
|
|
16617
16695
|
).run();
|
|
16618
|
-
await
|
|
16696
|
+
await chunkBRKXMRMB_cjs.logActivity(
|
|
16619
16697
|
db,
|
|
16620
16698
|
user.userId,
|
|
16621
16699
|
"user!.invite_sent",
|
|
@@ -16672,7 +16750,7 @@ userRoutes.post("/resend-invitation/:id", async (c) => {
|
|
|
16672
16750
|
Date.now(),
|
|
16673
16751
|
userId
|
|
16674
16752
|
).run();
|
|
16675
|
-
await
|
|
16753
|
+
await chunkBRKXMRMB_cjs.logActivity(
|
|
16676
16754
|
db,
|
|
16677
16755
|
user.userId,
|
|
16678
16756
|
"user!.invitation_resent",
|
|
@@ -16708,7 +16786,7 @@ userRoutes.delete("/cancel-invitation/:id", async (c) => {
|
|
|
16708
16786
|
}
|
|
16709
16787
|
const deleteStmt = db.prepare(`DELETE FROM auth_user WHERE id = ?`);
|
|
16710
16788
|
await deleteStmt.bind(userId).run();
|
|
16711
|
-
await
|
|
16789
|
+
await chunkBRKXMRMB_cjs.logActivity(
|
|
16712
16790
|
db,
|
|
16713
16791
|
user.userId,
|
|
16714
16792
|
"user!.invitation_cancelled",
|
|
@@ -18089,7 +18167,7 @@ var fileValidationSchema2 = zod.z.object({
|
|
|
18089
18167
|
// 50MB max
|
|
18090
18168
|
});
|
|
18091
18169
|
var adminMediaRoutes = new hono.Hono();
|
|
18092
|
-
adminMediaRoutes.use("*",
|
|
18170
|
+
adminMediaRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
|
|
18093
18171
|
adminMediaRoutes.get("/", async (c) => {
|
|
18094
18172
|
try {
|
|
18095
18173
|
const user = c.get("user");
|
|
@@ -18131,7 +18209,7 @@ adminMediaRoutes.get("/selector", async (c) => {
|
|
|
18131
18209
|
const { searchParams } = new URL(c.req.url);
|
|
18132
18210
|
const search = searchParams.get("search") || "";
|
|
18133
18211
|
const db = c.env.DB;
|
|
18134
|
-
const pluginService = new
|
|
18212
|
+
const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
|
|
18135
18213
|
const mediaPlugin = await pluginService.getPlugin("core-media");
|
|
18136
18214
|
if (!mediaPlugin || mediaPlugin.status !== "active") {
|
|
18137
18215
|
return c.html(html.html`
|
|
@@ -18507,7 +18585,7 @@ adminMediaRoutes.put("/:id", async (c) => {
|
|
|
18507
18585
|
`);
|
|
18508
18586
|
}
|
|
18509
18587
|
});
|
|
18510
|
-
adminMediaRoutes.delete("/cleanup",
|
|
18588
|
+
adminMediaRoutes.delete("/cleanup", chunkBRKXMRMB_cjs.requireRole("admin"), async (c) => {
|
|
18511
18589
|
try {
|
|
18512
18590
|
const db = c.env.DB;
|
|
18513
18591
|
const allMediaStmt = db.prepare("SELECT id, r2_key, filename FROM media WHERE deleted_at IS NULL");
|
|
@@ -19588,7 +19666,7 @@ function escapeHtmlAttr(value) {
|
|
|
19588
19666
|
}
|
|
19589
19667
|
function renderPluginSettingsPage(data) {
|
|
19590
19668
|
const { plugin, activity = [], user, settingsTabData } = data;
|
|
19591
|
-
const pluginDef =
|
|
19669
|
+
const pluginDef = chunkKWQNB6UM_cjs.getPluginDefinition(plugin.id || plugin.name);
|
|
19592
19670
|
const pluginId = plugin.id || plugin.name;
|
|
19593
19671
|
const hasUserSettings = pluginDef?.settingsTabContent != null || Object.keys(plugin.settings || {}).some((k) => !k.startsWith("_")) || hasCustomSettingsComponent(pluginId);
|
|
19594
19672
|
const defaultTab = hasUserSettings ? "settings" : "info";
|
|
@@ -19914,7 +19992,7 @@ function renderSettingsTab(plugin, settingsTabData) {
|
|
|
19914
19992
|
const settings = plugin.settings || {};
|
|
19915
19993
|
const pluginId = plugin.id || plugin.name;
|
|
19916
19994
|
const hasUserKeys = Object.keys(settings).some((k) => !k.startsWith("_"));
|
|
19917
|
-
const pluginDef =
|
|
19995
|
+
const pluginDef = chunkKWQNB6UM_cjs.getPluginDefinition(pluginId);
|
|
19918
19996
|
if (pluginDef?.settingsTabContent) {
|
|
19919
19997
|
return pluginDef.settingsTabContent.render({ plugin, settings, data: settingsTabData });
|
|
19920
19998
|
}
|
|
@@ -21161,8 +21239,8 @@ async function fetchActivePluginIds(db) {
|
|
|
21161
21239
|
}
|
|
21162
21240
|
async function reconcileMenuFromPlugins(db) {
|
|
21163
21241
|
try {
|
|
21164
|
-
const singletonEntries =
|
|
21165
|
-
const manifestEntries = Object.values(
|
|
21242
|
+
const singletonEntries = chunkKWQNB6UM_cjs.getPluginMenu();
|
|
21243
|
+
const manifestEntries = Object.values(chunk4DHPR7KR_cjs.PLUGIN_REGISTRY).filter(
|
|
21166
21244
|
(p) => p.adminMenu !== null
|
|
21167
21245
|
);
|
|
21168
21246
|
const byPluginId = /* @__PURE__ */ new Map();
|
|
@@ -21199,8 +21277,8 @@ async function reconcileMenuFromPlugins(db) {
|
|
|
21199
21277
|
|
|
21200
21278
|
// src/routes/admin-plugins.ts
|
|
21201
21279
|
var adminPluginRoutes = new hono.Hono();
|
|
21202
|
-
adminPluginRoutes.use("*",
|
|
21203
|
-
var AVAILABLE_PLUGINS = Object.values(
|
|
21280
|
+
adminPluginRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
|
|
21281
|
+
var AVAILABLE_PLUGINS = Object.values(chunk4DHPR7KR_cjs.PLUGIN_REGISTRY).map((p) => ({
|
|
21204
21282
|
id: p.id,
|
|
21205
21283
|
name: p.codeName,
|
|
21206
21284
|
display_name: p.displayName,
|
|
@@ -21220,7 +21298,7 @@ adminPluginRoutes.get("/", async (c) => {
|
|
|
21220
21298
|
if (user?.role !== "admin") {
|
|
21221
21299
|
return c.text("Access denied", 403);
|
|
21222
21300
|
}
|
|
21223
|
-
const pluginService = new
|
|
21301
|
+
const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
|
|
21224
21302
|
let installedPlugins = [];
|
|
21225
21303
|
let stats = { total: 0, active: 0, inactive: 0, errors: 0, uninstalled: 0 };
|
|
21226
21304
|
try {
|
|
@@ -21294,10 +21372,10 @@ adminPluginRoutes.get("/:id", async (c) => {
|
|
|
21294
21372
|
if (user?.role !== "admin") {
|
|
21295
21373
|
return c.redirect("/admin/plugins");
|
|
21296
21374
|
}
|
|
21297
|
-
const pluginService = new
|
|
21375
|
+
const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
|
|
21298
21376
|
let plugin = await pluginService.getPlugin(pluginId);
|
|
21299
21377
|
if (!plugin) {
|
|
21300
|
-
const def =
|
|
21378
|
+
const def = chunkKWQNB6UM_cjs.getPluginDefinition(pluginId);
|
|
21301
21379
|
if (!def) return c.text("Plugin not found", 404);
|
|
21302
21380
|
plugin = await pluginService.ensurePlugin(pluginId, {
|
|
21303
21381
|
displayName: def.displayName ?? pluginId,
|
|
@@ -21309,7 +21387,7 @@ adminPluginRoutes.get("/:id", async (c) => {
|
|
|
21309
21387
|
const activity = await pluginService.getPluginActivity(pluginId, 20);
|
|
21310
21388
|
let enrichedSettings = plugin.settings || {};
|
|
21311
21389
|
if (pluginId === "otp-login") {
|
|
21312
|
-
const settingsService = new
|
|
21390
|
+
const settingsService = new chunkC5LDQ3SH_cjs.SettingsService(db);
|
|
21313
21391
|
const generalSettings = await settingsService.getGeneralSettings();
|
|
21314
21392
|
const siteName = generalSettings.siteName || "SonicJS";
|
|
21315
21393
|
const emailPlugin = await db.prepare(`
|
|
@@ -21368,7 +21446,7 @@ adminPluginRoutes.get("/:id", async (c) => {
|
|
|
21368
21446
|
timestamp: item.timestamp,
|
|
21369
21447
|
user: item.userId || null
|
|
21370
21448
|
}));
|
|
21371
|
-
const pluginDef =
|
|
21449
|
+
const pluginDef = chunkKWQNB6UM_cjs.getPluginDefinition(pluginId);
|
|
21372
21450
|
let settingsTabData = void 0;
|
|
21373
21451
|
if (pluginDef?.settingsTabContent?.loadData) {
|
|
21374
21452
|
try {
|
|
@@ -21398,14 +21476,14 @@ adminPluginRoutes.get("/:id/configure", async (c) => {
|
|
|
21398
21476
|
const user = c.get("user");
|
|
21399
21477
|
const pluginId = c.req.param("id");
|
|
21400
21478
|
if (user?.role !== "admin") return c.redirect("/admin/plugins");
|
|
21401
|
-
const def =
|
|
21479
|
+
const def = chunkKWQNB6UM_cjs.getPluginDefinition(pluginId);
|
|
21402
21480
|
if (!def?.configSchema) return c.text("No schema-driven settings for this plugin", 404);
|
|
21403
21481
|
const db = c.env.DB;
|
|
21404
|
-
const pluginService = new
|
|
21482
|
+
const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
|
|
21405
21483
|
const plugin = await pluginService.getPlugin(pluginId);
|
|
21406
21484
|
const stored = plugin?.settings ?? {};
|
|
21407
|
-
const values =
|
|
21408
|
-
const fieldsHtml =
|
|
21485
|
+
const values = chunkKWQNB6UM_cjs.applySchemaDefaults(def.configSchema, stored);
|
|
21486
|
+
const fieldsHtml = chunkKWQNB6UM_cjs.renderSchemaFields(def.configSchema, values);
|
|
21409
21487
|
const displayName = plugin?.display_name ?? def.displayName ?? def.id;
|
|
21410
21488
|
return c.html(`<!DOCTYPE html>
|
|
21411
21489
|
<html lang="en"><head>
|
|
@@ -21432,12 +21510,12 @@ adminPluginRoutes.post("/:id/configure", async (c) => {
|
|
|
21432
21510
|
const user = c.get("user");
|
|
21433
21511
|
const pluginId = c.req.param("id");
|
|
21434
21512
|
if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
|
|
21435
|
-
const def =
|
|
21513
|
+
const def = chunkKWQNB6UM_cjs.getPluginDefinition(pluginId);
|
|
21436
21514
|
if (!def?.configSchema) return c.text("No schema-driven settings for this plugin", 404);
|
|
21437
21515
|
const form = await c.req.formData();
|
|
21438
|
-
const parsed =
|
|
21516
|
+
const parsed = chunkKWQNB6UM_cjs.parseFormDataToSettings(def.configSchema, form);
|
|
21439
21517
|
const db = c.env.DB;
|
|
21440
|
-
const pluginService = new
|
|
21518
|
+
const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
|
|
21441
21519
|
await pluginService.ensurePlugin(pluginId, {
|
|
21442
21520
|
displayName: def.displayName ?? pluginId,
|
|
21443
21521
|
version: def.version,
|
|
@@ -21461,7 +21539,7 @@ adminPluginRoutes.post("/:id/activate", async (c) => {
|
|
|
21461
21539
|
if (user?.role !== "admin") {
|
|
21462
21540
|
return c.json({ error: "Access denied" }, 403);
|
|
21463
21541
|
}
|
|
21464
|
-
const pluginService = new
|
|
21542
|
+
const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
|
|
21465
21543
|
await pluginService.activatePlugin(pluginId);
|
|
21466
21544
|
await reconcileMenuFromPlugins(db);
|
|
21467
21545
|
return c.json({ success: true });
|
|
@@ -21479,7 +21557,7 @@ adminPluginRoutes.post("/:id/deactivate", async (c) => {
|
|
|
21479
21557
|
if (user?.role !== "admin") {
|
|
21480
21558
|
return c.json({ error: "Access denied" }, 403);
|
|
21481
21559
|
}
|
|
21482
|
-
const pluginService = new
|
|
21560
|
+
const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
|
|
21483
21561
|
await pluginService.deactivatePlugin(pluginId);
|
|
21484
21562
|
await reconcileMenuFromPlugins(db);
|
|
21485
21563
|
return c.json({ success: true });
|
|
@@ -21497,8 +21575,8 @@ adminPluginRoutes.post("/install", async (c) => {
|
|
|
21497
21575
|
return c.json({ error: "Access denied" }, 403);
|
|
21498
21576
|
}
|
|
21499
21577
|
const body = await c.req.json();
|
|
21500
|
-
const pluginService = new
|
|
21501
|
-
const registryEntry =
|
|
21578
|
+
const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
|
|
21579
|
+
const registryEntry = chunk4DHPR7KR_cjs.findPluginByCodeName(body.name) || chunk4DHPR7KR_cjs.PLUGIN_REGISTRY[body.name] || chunk4DHPR7KR_cjs.PLUGIN_REGISTRY[body.id];
|
|
21502
21580
|
if (!registryEntry) {
|
|
21503
21581
|
return c.json({ error: "Plugin not found in registry" }, 404);
|
|
21504
21582
|
}
|
|
@@ -21531,7 +21609,7 @@ adminPluginRoutes.post("/:id/uninstall", async (c) => {
|
|
|
21531
21609
|
if (user?.role !== "admin") {
|
|
21532
21610
|
return c.json({ error: "Access denied" }, 403);
|
|
21533
21611
|
}
|
|
21534
|
-
const pluginService = new
|
|
21612
|
+
const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
|
|
21535
21613
|
await pluginService.uninstallPlugin(pluginId);
|
|
21536
21614
|
return c.json({ success: true });
|
|
21537
21615
|
} catch (error) {
|
|
@@ -21549,7 +21627,7 @@ adminPluginRoutes.post("/:id/settings", async (c) => {
|
|
|
21549
21627
|
return c.json({ error: "Access denied" }, 403);
|
|
21550
21628
|
}
|
|
21551
21629
|
const settings = await c.req.json();
|
|
21552
|
-
const pluginService = new
|
|
21630
|
+
const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
|
|
21553
21631
|
const existingPlugin = await pluginService.getPlugin(pluginId);
|
|
21554
21632
|
const existingSettings = existingPlugin?.settings ?? {};
|
|
21555
21633
|
await pluginService.updatePluginSettings(pluginId, { ...existingSettings, ...settings });
|
|
@@ -22359,11 +22437,11 @@ function renderLogConfigPage(data) {
|
|
|
22359
22437
|
|
|
22360
22438
|
// src/routes/admin-logs.ts
|
|
22361
22439
|
var adminLogsRoutes = new hono.Hono();
|
|
22362
|
-
adminLogsRoutes.use("*",
|
|
22440
|
+
adminLogsRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
|
|
22363
22441
|
adminLogsRoutes.get("/", async (c) => {
|
|
22364
22442
|
try {
|
|
22365
22443
|
const user = c.get("user");
|
|
22366
|
-
const logger =
|
|
22444
|
+
const logger = chunkC5LDQ3SH_cjs.getLogger(c.env.DB);
|
|
22367
22445
|
const query = c.req.query();
|
|
22368
22446
|
const page = parseInt(query.page || "1");
|
|
22369
22447
|
const limit = parseInt(query.limit || "50");
|
|
@@ -22443,7 +22521,7 @@ adminLogsRoutes.get("/:id", async (c) => {
|
|
|
22443
22521
|
try {
|
|
22444
22522
|
const id = c.req.param("id");
|
|
22445
22523
|
const user = c.get("user");
|
|
22446
|
-
const logger =
|
|
22524
|
+
const logger = chunkC5LDQ3SH_cjs.getLogger(c.env.DB);
|
|
22447
22525
|
const { logs } = await logger.getLogs({
|
|
22448
22526
|
limit: 1,
|
|
22449
22527
|
offset: 0,
|
|
@@ -22480,7 +22558,7 @@ adminLogsRoutes.get("/:id", async (c) => {
|
|
|
22480
22558
|
adminLogsRoutes.get("/config", async (c) => {
|
|
22481
22559
|
try {
|
|
22482
22560
|
const user = c.get("user");
|
|
22483
|
-
const logger =
|
|
22561
|
+
const logger = chunkC5LDQ3SH_cjs.getLogger(c.env.DB);
|
|
22484
22562
|
const configs = await logger.getAllConfigs();
|
|
22485
22563
|
const pageData = {
|
|
22486
22564
|
configs,
|
|
@@ -22504,7 +22582,7 @@ adminLogsRoutes.post("/config/:category", async (c) => {
|
|
|
22504
22582
|
const level = formData.get("level");
|
|
22505
22583
|
const retention = parseInt(formData.get("retention"));
|
|
22506
22584
|
const maxSize = parseInt(formData.get("max_size"));
|
|
22507
|
-
const logger =
|
|
22585
|
+
const logger = chunkC5LDQ3SH_cjs.getLogger(c.env.DB);
|
|
22508
22586
|
await logger.updateConfig(category, {
|
|
22509
22587
|
enabled,
|
|
22510
22588
|
level,
|
|
@@ -22533,7 +22611,7 @@ adminLogsRoutes.get("/export", async (c) => {
|
|
|
22533
22611
|
const category = query.category;
|
|
22534
22612
|
const startDate = query.start_date;
|
|
22535
22613
|
const endDate = query.end_date;
|
|
22536
|
-
const logger =
|
|
22614
|
+
const logger = chunkC5LDQ3SH_cjs.getLogger(c.env.DB);
|
|
22537
22615
|
const filter = {
|
|
22538
22616
|
limit: 1e4,
|
|
22539
22617
|
// Export up to 10k logs
|
|
@@ -22614,7 +22692,7 @@ adminLogsRoutes.post("/cleanup", async (c) => {
|
|
|
22614
22692
|
error: "Unauthorized. Admin access required."
|
|
22615
22693
|
}, 403);
|
|
22616
22694
|
}
|
|
22617
|
-
const logger =
|
|
22695
|
+
const logger = chunkC5LDQ3SH_cjs.getLogger(c.env.DB);
|
|
22618
22696
|
await logger.cleanupByRetention();
|
|
22619
22697
|
return c.html(html.html`
|
|
22620
22698
|
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded">
|
|
@@ -22636,7 +22714,7 @@ adminLogsRoutes.post("/search", async (c) => {
|
|
|
22636
22714
|
const search = formData.get("search");
|
|
22637
22715
|
const level = formData.get("level");
|
|
22638
22716
|
const category = formData.get("category");
|
|
22639
|
-
const logger =
|
|
22717
|
+
const logger = chunkC5LDQ3SH_cjs.getLogger(c.env.DB);
|
|
22640
22718
|
const filter = {
|
|
22641
22719
|
limit: 20,
|
|
22642
22720
|
offset: 0,
|
|
@@ -23351,9 +23429,9 @@ function renderStorageUsage(databaseSizeBytes, mediaSizeBytes) {
|
|
|
23351
23429
|
}
|
|
23352
23430
|
|
|
23353
23431
|
// src/routes/admin-dashboard.ts
|
|
23354
|
-
var VERSION =
|
|
23432
|
+
var VERSION = chunkXZUEGFXE_cjs.getCoreVersion();
|
|
23355
23433
|
var router = new hono.Hono();
|
|
23356
|
-
router.use("*",
|
|
23434
|
+
router.use("*", chunkBRKXMRMB_cjs.requireAuth());
|
|
23357
23435
|
router.get("/", async (c) => {
|
|
23358
23436
|
const user = c.get("user");
|
|
23359
23437
|
try {
|
|
@@ -25318,7 +25396,7 @@ function renderCollectionFormPage(data) {
|
|
|
25318
25396
|
// src/routes/admin-collections.ts
|
|
25319
25397
|
chunkMI2YXCK4_cjs.init_admin_layout_catalyst_template();
|
|
25320
25398
|
var adminCollectionsRoutes = new hono.Hono();
|
|
25321
|
-
adminCollectionsRoutes.use("*",
|
|
25399
|
+
adminCollectionsRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
|
|
25322
25400
|
adminCollectionsRoutes.get("/", async (c) => {
|
|
25323
25401
|
try {
|
|
25324
25402
|
const user = c.get("user");
|
|
@@ -25335,7 +25413,7 @@ adminCollectionsRoutes.get("/", async (c) => {
|
|
|
25335
25413
|
results = queryResults.results ?? [];
|
|
25336
25414
|
} catch (e) {
|
|
25337
25415
|
}
|
|
25338
|
-
const codeCollections =
|
|
25416
|
+
const codeCollections = chunk4DHPR7KR_cjs.getCollectionRegistry().list();
|
|
25339
25417
|
const codeCollectionsMap = new Map(
|
|
25340
25418
|
codeCollections.map((cfg) => {
|
|
25341
25419
|
const fieldCount = cfg.schema?.properties ? Object.keys(cfg.schema.properties).length : 0;
|
|
@@ -25349,7 +25427,7 @@ adminCollectionsRoutes.get("/", async (c) => {
|
|
|
25349
25427
|
field_count: fieldCount,
|
|
25350
25428
|
managed: cfg.managed !== false,
|
|
25351
25429
|
source_type: "code",
|
|
25352
|
-
internal:
|
|
25430
|
+
internal: chunk4DHPR7KR_cjs.isCodeCollectionInternal(cfg),
|
|
25353
25431
|
versioning: cfg.versioning === true
|
|
25354
25432
|
}];
|
|
25355
25433
|
})
|
|
@@ -25388,7 +25466,7 @@ adminCollectionsRoutes.get("/", async (c) => {
|
|
|
25388
25466
|
field_count: fieldCount,
|
|
25389
25467
|
managed: false,
|
|
25390
25468
|
source_type: row.source === "code" || row.source === "system" || row.source === "plugin" ? "code" : "user",
|
|
25391
|
-
internal:
|
|
25469
|
+
internal: chunk4DHPR7KR_cjs.isDbDocTypeInternal(row.source),
|
|
25392
25470
|
versioning: dbVersioning
|
|
25393
25471
|
};
|
|
25394
25472
|
});
|
|
@@ -25549,7 +25627,7 @@ export const myPlugin = definePlugin({
|
|
|
25549
25627
|
title: "Add a Collection",
|
|
25550
25628
|
pageTitle: "Add a Collection",
|
|
25551
25629
|
currentPath: "/admin/collections",
|
|
25552
|
-
version:
|
|
25630
|
+
version: chunkXZUEGFXE_cjs.getCoreVersion(),
|
|
25553
25631
|
user: u ? { name: u.email ?? "Admin", email: u.email ?? "", role: u.role ?? "admin" } : void 0,
|
|
25554
25632
|
content
|
|
25555
25633
|
})
|
|
@@ -25566,7 +25644,7 @@ adminCollectionsRoutes.get("/:id", async (c) => {
|
|
|
25566
25644
|
collection = await stmt.bind(id).first();
|
|
25567
25645
|
} catch {
|
|
25568
25646
|
}
|
|
25569
|
-
const registryRecord =
|
|
25647
|
+
const registryRecord = chunk4DHPR7KR_cjs.getCollectionRegistry().getById(id) ?? chunk4DHPR7KR_cjs.getCollectionRegistry().getByName(id);
|
|
25570
25648
|
if (!collection && !registryRecord) {
|
|
25571
25649
|
const formData2 = {
|
|
25572
25650
|
isEdit: true,
|
|
@@ -25613,9 +25691,9 @@ adminCollectionsRoutes.get("/:id", async (c) => {
|
|
|
25613
25691
|
isCodeDriven = true;
|
|
25614
25692
|
}
|
|
25615
25693
|
const [tinymceActive, quillActive, mdxeditorActive] = await Promise.all([
|
|
25616
|
-
|
|
25617
|
-
|
|
25618
|
-
|
|
25694
|
+
chunk4DHPR7KR_cjs.isPluginActive(db, "tinymce-plugin"),
|
|
25695
|
+
chunk4DHPR7KR_cjs.isPluginActive(db, "quill-editor"),
|
|
25696
|
+
chunk4DHPR7KR_cjs.isPluginActive(db, "easy-mdx")
|
|
25619
25697
|
]);
|
|
25620
25698
|
const displayName = collection?.display_name ?? registryRecord?.displayName ?? id;
|
|
25621
25699
|
const formData = {
|
|
@@ -25635,9 +25713,9 @@ adminCollectionsRoutes.get("/:id", async (c) => {
|
|
|
25635
25713
|
console.error("Error fetching collection:", error);
|
|
25636
25714
|
const user = c.get("user");
|
|
25637
25715
|
const [tinymceActive, quillActive, mdxeditorActive] = await Promise.all([
|
|
25638
|
-
|
|
25639
|
-
|
|
25640
|
-
|
|
25716
|
+
chunk4DHPR7KR_cjs.isPluginActive(db, "tinymce-plugin"),
|
|
25717
|
+
chunk4DHPR7KR_cjs.isPluginActive(db, "quill-editor"),
|
|
25718
|
+
chunk4DHPR7KR_cjs.isPluginActive(db, "easy-mdx")
|
|
25641
25719
|
]);
|
|
25642
25720
|
const formData = {
|
|
25643
25721
|
isEdit: true,
|
|
@@ -26586,7 +26664,7 @@ function renderDatabaseToolsSettings(settings) {
|
|
|
26586
26664
|
|
|
26587
26665
|
// src/routes/admin-settings.ts
|
|
26588
26666
|
var adminSettingsRoutes = new hono.Hono();
|
|
26589
|
-
adminSettingsRoutes.use("*",
|
|
26667
|
+
adminSettingsRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
|
|
26590
26668
|
function getMockSettings(user) {
|
|
26591
26669
|
return {
|
|
26592
26670
|
general: {
|
|
@@ -26620,7 +26698,7 @@ adminSettingsRoutes.get("/", (c) => {
|
|
|
26620
26698
|
adminSettingsRoutes.get("/general", async (c) => {
|
|
26621
26699
|
const user = c.get("user");
|
|
26622
26700
|
const db = c.env.DB;
|
|
26623
|
-
const settingsService = new
|
|
26701
|
+
const settingsService = new chunkC5LDQ3SH_cjs.SettingsService(db);
|
|
26624
26702
|
const generalSettings = await settingsService.getGeneralSettings(user?.email);
|
|
26625
26703
|
const mockSettings = getMockSettings(user);
|
|
26626
26704
|
mockSettings.general = generalSettings;
|
|
@@ -26639,7 +26717,7 @@ adminSettingsRoutes.get("/general", async (c) => {
|
|
|
26639
26717
|
adminSettingsRoutes.get("/security", async (c) => {
|
|
26640
26718
|
const user = c.get("user");
|
|
26641
26719
|
const db = c.env.DB;
|
|
26642
|
-
const settingsService = new
|
|
26720
|
+
const settingsService = new chunkC5LDQ3SH_cjs.SettingsService(db);
|
|
26643
26721
|
const persisted = await settingsService.getSecuritySettings();
|
|
26644
26722
|
const mockSettings = getMockSettings(user);
|
|
26645
26723
|
mockSettings.security = {
|
|
@@ -26689,7 +26767,7 @@ adminSettingsRoutes.get("/database-tools", (c) => {
|
|
|
26689
26767
|
adminSettingsRoutes.get("/api/migrations/status", async (c) => {
|
|
26690
26768
|
try {
|
|
26691
26769
|
const db = c.env.DB;
|
|
26692
|
-
const migrationService = new
|
|
26770
|
+
const migrationService = new chunkPAS7GZBS_cjs.MigrationService(db);
|
|
26693
26771
|
const status = await migrationService.getMigrationStatus();
|
|
26694
26772
|
return c.json({
|
|
26695
26773
|
success: true,
|
|
@@ -26729,7 +26807,7 @@ adminSettingsRoutes.post("/api/migrations/run", async (c) => {
|
|
|
26729
26807
|
adminSettingsRoutes.get("/api/migrations/validate", async (c) => {
|
|
26730
26808
|
try {
|
|
26731
26809
|
const db = c.env.DB;
|
|
26732
|
-
const migrationService = new
|
|
26810
|
+
const migrationService = new chunkPAS7GZBS_cjs.MigrationService(db);
|
|
26733
26811
|
const validation = await migrationService.validateSchema();
|
|
26734
26812
|
return c.json({
|
|
26735
26813
|
success: true,
|
|
@@ -26898,7 +26976,7 @@ adminSettingsRoutes.post("/general", async (c) => {
|
|
|
26898
26976
|
}
|
|
26899
26977
|
const formData = await c.req.formData();
|
|
26900
26978
|
const db = c.env.DB;
|
|
26901
|
-
const settingsService = new
|
|
26979
|
+
const settingsService = new chunkC5LDQ3SH_cjs.SettingsService(db);
|
|
26902
26980
|
const settings = {
|
|
26903
26981
|
siteName: formData.get("siteName"),
|
|
26904
26982
|
siteDescription: formData.get("siteDescription"),
|
|
@@ -26944,7 +27022,7 @@ adminSettingsRoutes.post("/security", async (c) => {
|
|
|
26944
27022
|
}
|
|
26945
27023
|
const formData = await c.req.formData();
|
|
26946
27024
|
const db = c.env.DB;
|
|
26947
|
-
const settingsService = new
|
|
27025
|
+
const settingsService = new chunkC5LDQ3SH_cjs.SettingsService(db);
|
|
26948
27026
|
const jwtExpiresInRaw = formData.get("jwtExpiresIn")?.trim() || "";
|
|
26949
27027
|
const graceRaw = formData.get("jwtRefreshGraceSeconds")?.trim() || "";
|
|
26950
27028
|
if (!/^\d+(?:s|m|h|d)?$/i.test(jwtExpiresInRaw)) {
|
|
@@ -27128,7 +27206,7 @@ function renderAPIReferencePage(data) {
|
|
|
27128
27206
|
>
|
|
27129
27207
|
<option value="">All Categories</option>
|
|
27130
27208
|
${categories.map((category) => {
|
|
27131
|
-
const info =
|
|
27209
|
+
const info = chunkC5LDQ3SH_cjs.CATEGORY_INFO[category];
|
|
27132
27210
|
const title = info ? info.title : category;
|
|
27133
27211
|
return `<option value="${category}">${title}</option>`;
|
|
27134
27212
|
}).join("\n ")}
|
|
@@ -27145,7 +27223,7 @@ function renderAPIReferencePage(data) {
|
|
|
27145
27223
|
<!-- API Categories -->
|
|
27146
27224
|
<div class="space-y-6">
|
|
27147
27225
|
${Object.entries(endpointsByCategory).map(([category, endpoints]) => {
|
|
27148
|
-
const info =
|
|
27226
|
+
const info = chunkC5LDQ3SH_cjs.CATEGORY_INFO[category] || { title: category, description: "", icon: "📋" };
|
|
27149
27227
|
return `
|
|
27150
27228
|
<div class="api-category" data-category="${category}">
|
|
27151
27229
|
<div class="rounded-lg bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 overflow-hidden">
|
|
@@ -27322,16 +27400,16 @@ function renderAPIReferencePage(data) {
|
|
|
27322
27400
|
}
|
|
27323
27401
|
|
|
27324
27402
|
// src/routes/admin-api-reference.ts
|
|
27325
|
-
var VERSION2 =
|
|
27403
|
+
var VERSION2 = chunkXZUEGFXE_cjs.getCoreVersion();
|
|
27326
27404
|
var router2 = new hono.Hono();
|
|
27327
|
-
router2.use("*",
|
|
27405
|
+
router2.use("*", chunkBRKXMRMB_cjs.requireAuth());
|
|
27328
27406
|
router2.get("/", async (c) => {
|
|
27329
27407
|
const user = c.get("user");
|
|
27330
27408
|
try {
|
|
27331
|
-
const app2 =
|
|
27332
|
-
const baseEndpoints =
|
|
27409
|
+
const app2 = chunkC5LDQ3SH_cjs.getAppInstance();
|
|
27410
|
+
const baseEndpoints = chunkC5LDQ3SH_cjs.buildRouteList(app2);
|
|
27333
27411
|
const collectionRoutes = [];
|
|
27334
|
-
const collections =
|
|
27412
|
+
const collections = chunk4DHPR7KR_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal);
|
|
27335
27413
|
const methodOrder = { GET: 0, POST: 1, PUT: 2, PATCH: 3, DELETE: 4 };
|
|
27336
27414
|
for (const col of collections) {
|
|
27337
27415
|
const displayName = col.displayName || col.name;
|
|
@@ -27446,11 +27524,13 @@ exports.resolveDocScope = resolveDocScope;
|
|
|
27446
27524
|
exports.resolveVariablesInObject = resolveVariablesInObject;
|
|
27447
27525
|
exports.router = router;
|
|
27448
27526
|
exports.router2 = router2;
|
|
27527
|
+
exports.setDemoModeActive = setDemoModeActive;
|
|
27449
27528
|
exports.setEmailService = setEmailService;
|
|
27450
27529
|
exports.setVariablesCache = setVariablesCache;
|
|
27530
|
+
exports.swrStats = swrStats;
|
|
27451
27531
|
exports.test_cleanup_default = test_cleanup_default;
|
|
27452
27532
|
exports.updateDocumentSchema = updateDocumentSchema;
|
|
27453
27533
|
exports.userProfilesPlugin = userProfilesPlugin;
|
|
27454
27534
|
exports.userRoutes = userRoutes;
|
|
27455
|
-
//# sourceMappingURL=chunk-
|
|
27456
|
-
//# sourceMappingURL=chunk-
|
|
27535
|
+
//# sourceMappingURL=chunk-S2QN4LFD.cjs.map
|
|
27536
|
+
//# sourceMappingURL=chunk-S2QN4LFD.cjs.map
|