@sonicjs-cms/core 3.0.0-beta.2 → 3.0.0-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -49
- package/dist/admin-documents-form.template-DDSH6ROU.js +6 -0
- package/dist/{admin-documents-form.template-NLSI6Z42.js.map → admin-documents-form.template-DDSH6ROU.js.map} +1 -1
- package/dist/admin-documents-form.template-LSZKGA5J.cjs +19 -0
- package/dist/{admin-layout-catalyst.template-WHJGSWWD.js.map → admin-documents-form.template-LSZKGA5J.cjs.map} +1 -1
- package/dist/{filter-bar.template-DlVYMk-T.d.ts → admin-layout-catalyst.template-DrwDUfsE.d.cts} +25 -1
- package/dist/{filter-bar.template-DlVYMk-T.d.cts → admin-layout-catalyst.template-DrwDUfsE.d.ts} +25 -1
- package/dist/admin-layout-catalyst.template-KDHKVLXR.cjs +21 -0
- package/dist/{admin-layout-catalyst.template-ZK5HD545.cjs.map → admin-layout-catalyst.template-KDHKVLXR.cjs.map} +1 -1
- package/dist/admin-layout-catalyst.template-YQ4EMF2J.js +7 -0
- package/dist/{admin-documents-form.template-KN7JF66Q.cjs.map → admin-layout-catalyst.template-YQ4EMF2J.js.map} +1 -1
- package/dist/{app-Bo0X1OWX.d.ts → app-01M0dIwt.d.ts} +1 -1
- package/dist/{app-Do66yCcV.d.cts → app-aj39TGHB.d.cts} +1 -1
- package/dist/{chunk-ZEZ245PW.js → chunk-2XAQTPAE.js} +4 -236
- package/dist/chunk-2XAQTPAE.js.map +1 -0
- package/dist/{chunk-BDDABDAB.cjs → chunk-36Z3AKX3.cjs} +3 -239
- package/dist/chunk-36Z3AKX3.cjs.map +1 -0
- package/dist/{chunk-BLMTL57B.js → chunk-3TMTYJAJ.js} +26 -4
- package/dist/chunk-3TMTYJAJ.js.map +1 -0
- package/dist/{chunk-ZGGXCFR6.js → chunk-4LVVMVQI.js} +282 -4
- package/dist/chunk-4LVVMVQI.js.map +1 -0
- package/dist/{chunk-RZ6H7OZK.js → chunk-4UYJPHSV.js} +87 -12
- package/dist/chunk-4UYJPHSV.js.map +1 -0
- package/dist/{chunk-NLJVSER2.js → chunk-5U75XP74.js} +3 -2
- package/dist/chunk-5U75XP74.js.map +1 -0
- package/dist/{chunk-H2AXVCLS.cjs → chunk-5UXU3LP4.cjs} +141 -74
- package/dist/chunk-5UXU3LP4.cjs.map +1 -0
- package/dist/{chunk-3TB6AT6X.js → chunk-5V62WT6M.js} +35 -4
- package/dist/chunk-5V62WT6M.js.map +1 -0
- package/dist/{chunk-6OUHGKFD.js → chunk-7OTOXWEB.js} +3 -3
- package/dist/{chunk-6OUHGKFD.js.map → chunk-7OTOXWEB.js.map} +1 -1
- package/dist/{chunk-VXE42MYF.cjs → chunk-7RUW244J.cjs} +710 -434
- package/dist/chunk-7RUW244J.cjs.map +1 -0
- package/dist/{chunk-XW56B23A.cjs → chunk-A4KUJ3LD.cjs} +4 -4
- package/dist/{chunk-XW56B23A.cjs.map → chunk-A4KUJ3LD.cjs.map} +1 -1
- package/dist/{chunk-LRZIAW7U.cjs → chunk-AOUVUF32.cjs} +3 -3
- package/dist/chunk-AOUVUF32.cjs.map +1 -0
- package/dist/{chunk-WULONYGB.cjs → chunk-CRGUD4KC.cjs} +9 -9
- package/dist/{chunk-WULONYGB.cjs.map → chunk-CRGUD4KC.cjs.map} +1 -1
- package/dist/{chunk-AAWNRBRB.cjs → chunk-FCLKX2OS.cjs} +95 -20
- package/dist/chunk-FCLKX2OS.cjs.map +1 -0
- package/dist/{chunk-YHSQVQXX.js → chunk-GICS5AIO.js} +135 -68
- package/dist/chunk-GICS5AIO.js.map +1 -0
- package/dist/{chunk-NUKJ54GA.cjs → chunk-GMMCCIQO.cjs} +6 -6
- package/dist/{chunk-NUKJ54GA.cjs.map → chunk-GMMCCIQO.cjs.map} +1 -1
- package/dist/{chunk-NMPEMSU4.js → chunk-JEX3UPZL.js} +3 -3
- package/dist/chunk-JEX3UPZL.js.map +1 -0
- package/dist/{chunk-6JQOUUOB.js → chunk-JQISFW6U.js} +3 -3
- package/dist/{chunk-6JQOUUOB.js.map → chunk-JQISFW6U.js.map} +1 -1
- package/dist/{chunk-NAVPFIG5.cjs → chunk-K623Q6WD.cjs} +35 -3
- package/dist/chunk-K623Q6WD.cjs.map +1 -0
- package/dist/{chunk-JEQ7FLOD.cjs → chunk-KIGVVO6N.cjs} +16 -10
- package/dist/chunk-KIGVVO6N.cjs.map +1 -0
- package/dist/{chunk-QAYFOER6.cjs → chunk-KVBHB7QP.cjs} +285 -3
- package/dist/chunk-KVBHB7QP.cjs.map +1 -0
- package/dist/{chunk-2CB4KY7I.cjs → chunk-LTZ5WYOK.cjs} +29 -7
- package/dist/chunk-LTZ5WYOK.cjs.map +1 -0
- package/dist/{chunk-DNQCEKUK.cjs → chunk-N32OWET6.cjs} +5 -5
- package/dist/{chunk-DNQCEKUK.cjs.map → chunk-N32OWET6.cjs.map} +1 -1
- package/dist/{chunk-HDWE5FRJ.js → chunk-OBA2RYZN.js} +3 -3
- package/dist/{chunk-HDWE5FRJ.js.map → chunk-OBA2RYZN.js.map} +1 -1
- package/dist/{chunk-DSA4UX5B.cjs → chunk-OJC4G5JE.cjs} +3 -2
- package/dist/chunk-OJC4G5JE.cjs.map +1 -0
- package/dist/{chunk-MVIZJOO5.cjs → chunk-PXNTCCPE.cjs} +8 -8
- package/dist/{chunk-MVIZJOO5.cjs.map → chunk-PXNTCCPE.cjs.map} +1 -1
- package/dist/{chunk-EF2NQUIQ.js → chunk-RMRJGMDE.js} +3 -3
- package/dist/{chunk-EF2NQUIQ.js.map → chunk-RMRJGMDE.js.map} +1 -1
- package/dist/{chunk-IVPRUGTY.js → chunk-SOZUG52O.js} +4 -4
- package/dist/{chunk-IVPRUGTY.js.map → chunk-SOZUG52O.js.map} +1 -1
- package/dist/{chunk-GCDZZNIN.js → chunk-UWUP2VMT.js} +16 -10
- package/dist/chunk-UWUP2VMT.js.map +1 -0
- package/dist/{chunk-IESEVHXL.js → chunk-VVYVFCML.js} +12 -3
- package/dist/chunk-VVYVFCML.js.map +1 -0
- package/dist/{chunk-HIKBY7MS.cjs → chunk-XWVDSM2L.cjs} +12 -3
- package/dist/chunk-XWVDSM2L.cjs.map +1 -0
- package/dist/{chunk-VD2EA3WT.js → chunk-ZP77LTN4.js} +343 -68
- package/dist/chunk-ZP77LTN4.js.map +1 -0
- package/dist/{collection-config-JgHOpFCG.d.ts → collection-config-BTzAvKt2.d.cts} +25 -0
- package/dist/{collection-config-JgHOpFCG.d.cts → collection-config-BTzAvKt2.d.ts} +25 -0
- package/dist/config-6FB2BXMP.js +6 -0
- package/dist/{config-HFXANXCC.js.map → config-6FB2BXMP.js.map} +1 -1
- package/dist/config-OCH7S4WK.cjs +19 -0
- package/dist/{config-ON6FNMYX.cjs.map → config-OCH7S4WK.cjs.map} +1 -1
- package/dist/{define-plugin-BzNHc1ZI.d.ts → define-plugin-BYIey6sp.d.ts} +1 -1
- package/dist/{define-plugin-IWDKYaVm.d.cts → define-plugin-DsKiGu1q.d.cts} +1 -1
- package/dist/document-projection-4HG75S5S.js +4 -0
- package/dist/{document-projection-YYMC6I4U.js.map → document-projection-4HG75S5S.js.map} +1 -1
- package/dist/document-projection-JQHSTSFD.cjs +13 -0
- package/dist/{document-projection-TDWRJX3Z.cjs.map → document-projection-JQHSTSFD.cjs.map} +1 -1
- package/dist/index.cjs +1119 -440
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +200 -12
- package/dist/index.d.ts +200 -12
- package/dist/index.js +803 -137
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +37 -34
- package/dist/middleware.d.cts +2 -2
- package/dist/middleware.d.ts +2 -2
- package/dist/middleware.js +8 -5
- package/dist/migrations-HMX5SPN2.js +4 -0
- package/dist/{migrations-WCAVBD7C.js.map → migrations-HMX5SPN2.js.map} +1 -1
- package/dist/migrations-V73ARYV5.cjs +13 -0
- package/dist/{migrations-NJJWQUKK.cjs.map → migrations-V73ARYV5.cjs.map} +1 -1
- package/dist/{plugin-bootstrap-B8ThJU21.d.cts → plugin-bootstrap-BHWQ2df8.d.cts} +1 -1
- package/dist/{plugin-bootstrap-qu8hJgUt.d.ts → plugin-bootstrap-Bj4fxX1q.d.ts} +1 -1
- package/dist/plugins.cjs +40 -40
- package/dist/plugins.d.cts +2 -2
- package/dist/plugins.d.ts +2 -2
- package/dist/plugins.js +3 -3
- package/dist/rbac-7QZ4JZ2E.cjs +14 -0
- package/dist/{rbac-VONLJJKB.cjs.map → rbac-7QZ4JZ2E.cjs.map} +1 -1
- package/dist/rbac-Y43IEQOP.js +5 -0
- package/dist/{rbac-O73MFKDA.js.map → rbac-Y43IEQOP.js.map} +1 -1
- package/dist/routes.cjs +34 -34
- package/dist/routes.d.cts +2 -2
- package/dist/routes.d.ts +2 -2
- package/dist/routes.js +14 -14
- package/dist/services.cjs +42 -42
- package/dist/services.d.cts +16 -3
- package/dist/services.d.ts +16 -3
- package/dist/services.js +3 -3
- package/dist/{telemetry-B9vIV4wh.d.cts → telemetry-Cku1ax74.d.cts} +1 -1
- package/dist/{telemetry-B9vIV4wh.d.ts → telemetry-Cku1ax74.d.ts} +1 -1
- package/dist/templates.cjs +17 -17
- package/dist/templates.d.cts +2 -24
- package/dist/templates.d.ts +2 -24
- package/dist/templates.js +3 -3
- package/dist/{types-Dea1eNxU.d.ts → types-DT7XN5TX.d.cts} +1 -1
- package/dist/{types-Dea1eNxU.d.cts → types-DT7XN5TX.d.ts} +1 -1
- package/dist/types.d.cts +2 -2
- package/dist/types.d.ts +2 -2
- package/dist/utils.cjs +8 -8
- package/dist/utils.d.cts +2 -2
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +2 -2
- package/package.json +1 -1
- package/dist/admin-documents-form.template-KN7JF66Q.cjs +0 -19
- package/dist/admin-documents-form.template-NLSI6Z42.js +0 -6
- package/dist/admin-layout-catalyst.template-WHJGSWWD.js +0 -7
- package/dist/admin-layout-catalyst.template-ZK5HD545.cjs +0 -17
- package/dist/chunk-2CB4KY7I.cjs.map +0 -1
- package/dist/chunk-3TB6AT6X.js.map +0 -1
- package/dist/chunk-AAWNRBRB.cjs.map +0 -1
- package/dist/chunk-BDDABDAB.cjs.map +0 -1
- package/dist/chunk-BLMTL57B.js.map +0 -1
- package/dist/chunk-DSA4UX5B.cjs.map +0 -1
- package/dist/chunk-GCDZZNIN.js.map +0 -1
- package/dist/chunk-H2AXVCLS.cjs.map +0 -1
- package/dist/chunk-HIKBY7MS.cjs.map +0 -1
- package/dist/chunk-IESEVHXL.js.map +0 -1
- package/dist/chunk-JEQ7FLOD.cjs.map +0 -1
- package/dist/chunk-LRZIAW7U.cjs.map +0 -1
- package/dist/chunk-NAVPFIG5.cjs.map +0 -1
- package/dist/chunk-NLJVSER2.js.map +0 -1
- package/dist/chunk-NMPEMSU4.js.map +0 -1
- package/dist/chunk-QAYFOER6.cjs.map +0 -1
- package/dist/chunk-RZ6H7OZK.js.map +0 -1
- package/dist/chunk-VD2EA3WT.js.map +0 -1
- package/dist/chunk-VXE42MYF.cjs.map +0 -1
- package/dist/chunk-YHSQVQXX.js.map +0 -1
- package/dist/chunk-ZEZ245PW.js.map +0 -1
- package/dist/chunk-ZGGXCFR6.js.map +0 -1
- package/dist/config-HFXANXCC.js +0 -6
- package/dist/config-ON6FNMYX.cjs +0 -19
- package/dist/document-projection-TDWRJX3Z.cjs +0 -13
- package/dist/document-projection-YYMC6I4U.js +0 -4
- package/dist/migrations-NJJWQUKK.cjs +0 -13
- package/dist/migrations-WCAVBD7C.js +0 -4
- package/dist/rbac-O73MFKDA.js +0 -5
- package/dist/rbac-VONLJJKB.cjs +0 -14
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var
|
|
10
|
-
var
|
|
11
|
-
var
|
|
12
|
-
var
|
|
13
|
-
var
|
|
3
|
+
var chunkXWVDSM2L_cjs = require('./chunk-XWVDSM2L.cjs');
|
|
4
|
+
var chunkN32OWET6_cjs = require('./chunk-N32OWET6.cjs');
|
|
5
|
+
var chunk36Z3AKX3_cjs = require('./chunk-36Z3AKX3.cjs');
|
|
6
|
+
var chunkFCLKX2OS_cjs = require('./chunk-FCLKX2OS.cjs');
|
|
7
|
+
var chunkLTZ5WYOK_cjs = require('./chunk-LTZ5WYOK.cjs');
|
|
8
|
+
var chunkKIGVVO6N_cjs = require('./chunk-KIGVVO6N.cjs');
|
|
9
|
+
var chunkKVBHB7QP_cjs = require('./chunk-KVBHB7QP.cjs');
|
|
10
|
+
var chunkOJC4G5JE_cjs = require('./chunk-OJC4G5JE.cjs');
|
|
11
|
+
var chunkPXNTCCPE_cjs = require('./chunk-PXNTCCPE.cjs');
|
|
12
|
+
var chunkK623Q6WD_cjs = require('./chunk-K623Q6WD.cjs');
|
|
13
|
+
var chunkA4KUJ3LD_cjs = require('./chunk-A4KUJ3LD.cjs');
|
|
14
14
|
var chunkJ6JTWD2A_cjs = require('./chunk-J6JTWD2A.cjs');
|
|
15
15
|
var chunkIXUHXTHW_cjs = require('./chunk-IXUHXTHW.cjs');
|
|
16
16
|
var chunkRCQ2HIQD_cjs = require('./chunk-RCQ2HIQD.cjs');
|
|
17
|
-
var
|
|
17
|
+
var chunkAOUVUF32_cjs = require('./chunk-AOUVUF32.cjs');
|
|
18
18
|
var chunkMNWKYY5E_cjs = require('./chunk-MNWKYY5E.cjs');
|
|
19
19
|
var hono = require('hono');
|
|
20
20
|
var zod = require('zod');
|
|
21
|
-
var cors = require('hono/cors');
|
|
22
21
|
var cookie = require('hono/cookie');
|
|
23
22
|
var html = require('hono/html');
|
|
24
23
|
|
|
@@ -27,6 +26,7 @@ var DocumentPermissionsService = class {
|
|
|
27
26
|
constructor(db) {
|
|
28
27
|
this.db = db;
|
|
29
28
|
}
|
|
29
|
+
db;
|
|
30
30
|
// Deny wins. Overrides beat base grants. Empty ACL falls back to base grants.
|
|
31
31
|
async isAllowed(principalSet, rootId, permission, typeSettings, tenantId) {
|
|
32
32
|
const overrides = await this.getDocumentPermissions(rootId, principalSet, permission, tenantId);
|
|
@@ -74,7 +74,7 @@ var DocumentPermissionsService = class {
|
|
|
74
74
|
async grantPermission(opts) {
|
|
75
75
|
const { tenantId, rootId, principalType, principalId, permission, effect = "allow", createdBy } = opts;
|
|
76
76
|
const now = Math.floor(Date.now() / 1e3);
|
|
77
|
-
const id =
|
|
77
|
+
const id = chunkKIGVVO6N_cjs.nanoid();
|
|
78
78
|
await this.db.prepare(
|
|
79
79
|
`INSERT INTO document_permissions (id, tenant_id, root_id, principal_type, principal_id, permission, effect, inherited, created_at, created_by)
|
|
80
80
|
VALUES (?, ?, ?, ?, ?, ?, ?, 0, ?, ?)
|
|
@@ -135,6 +135,8 @@ var DocumentRepository = class {
|
|
|
135
135
|
this.tenantId = tenantId;
|
|
136
136
|
this.permissions = new DocumentPermissionsService(db);
|
|
137
137
|
}
|
|
138
|
+
db;
|
|
139
|
+
tenantId;
|
|
138
140
|
permissions;
|
|
139
141
|
// ─── Reads ───────────────────────────────────────────────────────────────
|
|
140
142
|
async getById(id) {
|
|
@@ -257,7 +259,7 @@ function getDocumentRequestContext(c) {
|
|
|
257
259
|
|
|
258
260
|
// src/routes/api-documents.ts
|
|
259
261
|
async function aclAllowsRead(db, tenantId, principalSet, row, preloadedType) {
|
|
260
|
-
const docType = preloadedType ?? await new
|
|
262
|
+
const docType = preloadedType ?? await new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db).findById(row.type_id);
|
|
261
263
|
if (!docType) return false;
|
|
262
264
|
return new DocumentRepository(db, tenantId).isAllowed(principalSet, row.root_id, "read", docType.settings);
|
|
263
265
|
}
|
|
@@ -275,7 +277,7 @@ apiDocumentsRoutes.get("/", async (c) => {
|
|
|
275
277
|
if (!typeId) {
|
|
276
278
|
return c.json({ error: "type query parameter is required" }, 400);
|
|
277
279
|
}
|
|
278
|
-
const registry = new
|
|
280
|
+
const registry = new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db);
|
|
279
281
|
const docType = await registry.findById(typeId);
|
|
280
282
|
if (!docType || !docType.isActive) {
|
|
281
283
|
return c.json({ error: "Unknown document type" }, 400);
|
|
@@ -357,7 +359,7 @@ apiDocumentsRoutes.get("/root/:rootId", async (c) => {
|
|
|
357
359
|
AND (expires_at IS NULL OR expires_at > ?) LIMIT 1`
|
|
358
360
|
).bind(rootId, now, now).first();
|
|
359
361
|
if (!row) return c.json({ error: "Not found" }, 404);
|
|
360
|
-
const docType = await new
|
|
362
|
+
const docType = await new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db).findById(row.type_id);
|
|
361
363
|
const effTenant = effectiveTenantForType(tenantId, docType?.settings);
|
|
362
364
|
if (row.tenant_id !== effTenant) return c.json({ error: "Not found" }, 404);
|
|
363
365
|
if (!await aclAllowsRead(db, effTenant, principalSet, row, docType)) {
|
|
@@ -393,7 +395,7 @@ apiDocumentsRoutes.get("/:id", async (c) => {
|
|
|
393
395
|
AND (expires_at IS NULL OR expires_at > ?) LIMIT 1`
|
|
394
396
|
).bind(id, now, now).first();
|
|
395
397
|
if (!row) return c.json({ error: "Not found" }, 404);
|
|
396
|
-
const docType = await new
|
|
398
|
+
const docType = await new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db).findById(row.type_id);
|
|
397
399
|
const effTenant = effectiveTenantForType(tenantId, docType?.settings);
|
|
398
400
|
if (row.tenant_id !== effTenant) return c.json({ error: "Not found" }, 404);
|
|
399
401
|
if (!await aclAllowsRead(db, effTenant, principalSet, row, docType)) {
|
|
@@ -463,17 +465,17 @@ async function resolveDocScope(c, db, by, opts = {}) {
|
|
|
463
465
|
const draft = opts.currentDraftOnly ? " AND is_current_draft = 1" : "";
|
|
464
466
|
const row = await db.prepare(`SELECT type_id, root_id, tenant_id FROM documents WHERE ${col} = ?${draft} LIMIT 1`).bind(val).first();
|
|
465
467
|
if (!row) return null;
|
|
466
|
-
const docType = await new
|
|
468
|
+
const docType = await new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db).findById(row.type_id);
|
|
467
469
|
const tenantId = effectiveTenantForType(getRequestTenant(c), docType?.settings);
|
|
468
470
|
if (row.tenant_id !== tenantId) return null;
|
|
469
471
|
return { typeId: row.type_id, rootId: row.root_id, tenantId, docType };
|
|
470
472
|
}
|
|
471
473
|
var adminDocumentsRoutes = new hono.Hono();
|
|
472
|
-
adminDocumentsRoutes.use("*",
|
|
473
|
-
adminDocumentsRoutes.use("*",
|
|
474
|
+
adminDocumentsRoutes.use("*", chunkFCLKX2OS_cjs.requireAuth());
|
|
475
|
+
adminDocumentsRoutes.use("*", chunkFCLKX2OS_cjs.requireRole(["admin", "editor"]));
|
|
474
476
|
adminDocumentsRoutes.get("/types", async (c) => {
|
|
475
477
|
try {
|
|
476
|
-
const registry = new
|
|
478
|
+
const registry = new chunkFCLKX2OS_cjs.DocumentTypeRegistry(c.env.DB);
|
|
477
479
|
const types = await registry.findAll();
|
|
478
480
|
return c.json({ data: types });
|
|
479
481
|
} catch (error) {
|
|
@@ -501,7 +503,7 @@ adminDocumentsRoutes.get("/", async (c) => {
|
|
|
501
503
|
if (!typeId) {
|
|
502
504
|
return c.json({ error: "type query parameter is required" }, 400);
|
|
503
505
|
}
|
|
504
|
-
const registry = new
|
|
506
|
+
const registry = new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db);
|
|
505
507
|
const docType = await registry.findById(typeId);
|
|
506
508
|
if (!docType || !docType.isActive) {
|
|
507
509
|
return c.json({ error: "Unknown document type" }, 400);
|
|
@@ -612,7 +614,7 @@ adminDocumentsRoutes.post("/", async (c) => {
|
|
|
612
614
|
const input = validation.data;
|
|
613
615
|
const db = c.env.DB;
|
|
614
616
|
const user = c.get("user");
|
|
615
|
-
const registry = new
|
|
617
|
+
const registry = new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db);
|
|
616
618
|
const docType = await registry.findById(input.typeId);
|
|
617
619
|
if (!docType || !docType.isActive) {
|
|
618
620
|
return c.json({ error: "Unknown document type" }, 400);
|
|
@@ -620,7 +622,7 @@ adminDocumentsRoutes.post("/", async (c) => {
|
|
|
620
622
|
const createDenied = await denyIfNotAllowed(c, db, "", "create", docType.settings);
|
|
621
623
|
if (createDenied) return createDenied;
|
|
622
624
|
const tenantId = effectiveTenantForType(getRequestTenant(c), docType.settings);
|
|
623
|
-
const svc = new
|
|
625
|
+
const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, {
|
|
624
626
|
queryableFields: docType.queryableFields,
|
|
625
627
|
typeSchemaVersion: docType.schemaVersion,
|
|
626
628
|
maxVersionsPerRoot: docType.settings.maxVersionsPerRoot,
|
|
@@ -658,7 +660,7 @@ adminDocumentsRoutes.put("/:rootId", async (c) => {
|
|
|
658
660
|
const docType = scope.docType;
|
|
659
661
|
const updateDenied = await denyIfNotAllowed(c, db, rootId, "update", docType?.settings, scope.tenantId);
|
|
660
662
|
if (updateDenied) return updateDenied;
|
|
661
|
-
const svc = new
|
|
663
|
+
const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, {
|
|
662
664
|
queryableFields: docType?.queryableFields ?? [],
|
|
663
665
|
typeSchemaVersion: docType?.schemaVersion,
|
|
664
666
|
maxVersionsPerRoot: docType?.settings.maxVersionsPerRoot,
|
|
@@ -683,7 +685,7 @@ adminDocumentsRoutes.post("/:id/publish", async (c) => {
|
|
|
683
685
|
const docType = scope.docType;
|
|
684
686
|
const publishDenied = await denyIfNotAllowed(c, db, scope.rootId, "publish", docType?.settings, scope.tenantId);
|
|
685
687
|
if (publishDenied) return publishDenied;
|
|
686
|
-
const svc = new
|
|
688
|
+
const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, {
|
|
687
689
|
queryableFields: docType?.queryableFields ?? [],
|
|
688
690
|
typeSchemaVersion: docType?.schemaVersion,
|
|
689
691
|
tenantId: scope.tenantId,
|
|
@@ -706,7 +708,7 @@ adminDocumentsRoutes.post("/:id/unpublish", async (c) => {
|
|
|
706
708
|
const docType = scope.docType;
|
|
707
709
|
const unpublishDenied = await denyIfNotAllowed(c, db, scope.rootId, "publish", docType?.settings, scope.tenantId);
|
|
708
710
|
if (unpublishDenied) return unpublishDenied;
|
|
709
|
-
const svc = new
|
|
711
|
+
const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, {
|
|
710
712
|
queryableFields: docType?.queryableFields ?? [],
|
|
711
713
|
tenantId: scope.tenantId
|
|
712
714
|
});
|
|
@@ -728,7 +730,7 @@ adminDocumentsRoutes.delete("/:id", async (c) => {
|
|
|
728
730
|
const docType = scope.docType;
|
|
729
731
|
const deleteDenied = await denyIfNotAllowed(c, db, scope.rootId, "delete", docType?.settings, scope.tenantId);
|
|
730
732
|
if (deleteDenied) return deleteDenied;
|
|
731
|
-
const svc = new
|
|
733
|
+
const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, { queryableFields: docType?.queryableFields ?? [], tenantId: scope.tenantId });
|
|
732
734
|
if (docType?.settings.pii) {
|
|
733
735
|
if (scope.rootId) await svc.erase(scope.rootId, scope.tenantId);
|
|
734
736
|
} else {
|
|
@@ -744,13 +746,13 @@ adminDocumentsRoutes.post("/types/:typeId/reindex", async (c) => {
|
|
|
744
746
|
try {
|
|
745
747
|
const { typeId } = c.req.param();
|
|
746
748
|
const db = c.env.DB;
|
|
747
|
-
const registry = new
|
|
749
|
+
const registry = new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db);
|
|
748
750
|
const docType = await registry.findById(typeId);
|
|
749
751
|
if (!docType) return c.json({ error: "Unknown document type" }, 400);
|
|
750
752
|
const reindexTenant = effectiveTenantForType(getRequestTenant(c), docType.settings);
|
|
751
753
|
const reindexDenied = await denyIfNotAllowed(c, db, "", "manage", docType.settings, reindexTenant);
|
|
752
754
|
if (reindexDenied) return reindexDenied;
|
|
753
|
-
const { DocumentProjection } = await import('./document-projection-
|
|
755
|
+
const { DocumentProjection } = await import('./document-projection-JQHSTSFD.cjs');
|
|
754
756
|
const projection = new DocumentProjection(db);
|
|
755
757
|
const rebuilt = await projection.reindexType(typeId, reindexTenant, docType.queryableFields);
|
|
756
758
|
return c.json({ rebuilt });
|
|
@@ -898,13 +900,13 @@ async function resolveContentVariables(contentData, db) {
|
|
|
898
900
|
// src/routes/api-content-crud.ts
|
|
899
901
|
var apiContentCrudRoutes = new hono.Hono();
|
|
900
902
|
async function resolveDocBacking(db, collectionIdOrName) {
|
|
901
|
-
const registry =
|
|
903
|
+
const registry = chunkKVBHB7QP_cjs.getCollectionRegistry();
|
|
902
904
|
const record = registry.getBySlugOrName(collectionIdOrName) ?? registry.getById(collectionIdOrName);
|
|
903
905
|
if (record) {
|
|
904
|
-
const docType2 = await new
|
|
906
|
+
const docType2 = await new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db).findById(record.name);
|
|
905
907
|
return docType2 ? { coll: { id: record.id, name: record.name }, docType: docType2 } : null;
|
|
906
908
|
}
|
|
907
|
-
const docType = await new
|
|
909
|
+
const docType = await new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db).findById(collectionIdOrName);
|
|
908
910
|
if (docType) {
|
|
909
911
|
return { coll: { id: collectionIdOrName, name: collectionIdOrName }, docType };
|
|
910
912
|
}
|
|
@@ -947,7 +949,7 @@ apiContentCrudRoutes.get("/check-slug", async (c) => {
|
|
|
947
949
|
}, 500);
|
|
948
950
|
}
|
|
949
951
|
});
|
|
950
|
-
apiContentCrudRoutes.get("/:id",
|
|
952
|
+
apiContentCrudRoutes.get("/:id", chunkFCLKX2OS_cjs.optionalAuth(), async (c) => {
|
|
951
953
|
try {
|
|
952
954
|
const id = c.req.param("id");
|
|
953
955
|
const db = c.env.DB;
|
|
@@ -957,7 +959,7 @@ apiContentCrudRoutes.get("/:id", chunkAAWNRBRB_cjs.optionalAuth(), async (c) =>
|
|
|
957
959
|
).bind(id, getRequestTenant(c)).first();
|
|
958
960
|
let transformedContent;
|
|
959
961
|
if (docRow) {
|
|
960
|
-
const coll =
|
|
962
|
+
const coll = chunkKVBHB7QP_cjs.getCollectionRegistry().getByName(docRow.type_id);
|
|
961
963
|
transformedContent = {
|
|
962
964
|
id: docRow.root_id,
|
|
963
965
|
title: docRow.title,
|
|
@@ -966,8 +968,8 @@ apiContentCrudRoutes.get("/:id", chunkAAWNRBRB_cjs.optionalAuth(), async (c) =>
|
|
|
966
968
|
collectionId: coll?.id ?? docRow.type_id,
|
|
967
969
|
data: docRow.data ? JSON.parse(docRow.data) : {},
|
|
968
970
|
// D29: document timestamps are SECONDS; legacy `content` API contract is MILLISECONDS.
|
|
969
|
-
created_at:
|
|
970
|
-
updated_at:
|
|
971
|
+
created_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(docRow.created_at),
|
|
972
|
+
updated_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(docRow.updated_at)
|
|
971
973
|
};
|
|
972
974
|
} else {
|
|
973
975
|
return c.json({ error: "Content not found" }, 404);
|
|
@@ -991,7 +993,7 @@ apiContentCrudRoutes.get("/:id", chunkAAWNRBRB_cjs.optionalAuth(), async (c) =>
|
|
|
991
993
|
}, 500);
|
|
992
994
|
}
|
|
993
995
|
});
|
|
994
|
-
apiContentCrudRoutes.post("/",
|
|
996
|
+
apiContentCrudRoutes.post("/", chunkFCLKX2OS_cjs.requireAuth(), chunkFCLKX2OS_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
995
997
|
try {
|
|
996
998
|
const db = c.env.DB;
|
|
997
999
|
const user = c.get("user");
|
|
@@ -1025,7 +1027,7 @@ apiContentCrudRoutes.post("/", chunkAAWNRBRB_cjs.requireAuth(), chunkAAWNRBRB_cj
|
|
|
1025
1027
|
return c.json({ error: "Write cancelled by plugin", details: String(err) }, 400);
|
|
1026
1028
|
}
|
|
1027
1029
|
const tenantId = getRequestTenant(c);
|
|
1028
|
-
const svc = new
|
|
1030
|
+
const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, {
|
|
1029
1031
|
queryableFields: backing.docType.queryableFields ?? [],
|
|
1030
1032
|
typeSchemaVersion: backing.docType.schemaVersion ?? 1,
|
|
1031
1033
|
maxVersionsPerRoot: backing.docType.settings?.maxVersionsPerRoot ?? 50,
|
|
@@ -1044,7 +1046,7 @@ apiContentCrudRoutes.post("/", chunkAAWNRBRB_cjs.requireAuth(), chunkAAWNRBRB_cj
|
|
|
1044
1046
|
}),
|
|
1045
1047
|
user?.userId
|
|
1046
1048
|
);
|
|
1047
|
-
const cache =
|
|
1049
|
+
const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
|
|
1048
1050
|
await cache.invalidate("content-filtered:*");
|
|
1049
1051
|
await cache.invalidate("collection-content-filtered:*");
|
|
1050
1052
|
dispatchHookEvent(
|
|
@@ -1054,7 +1056,7 @@ apiContentCrudRoutes.post("/", chunkAAWNRBRB_cjs.requireAuth(), chunkAAWNRBRB_cj
|
|
|
1054
1056
|
"fire-and-forget"
|
|
1055
1057
|
);
|
|
1056
1058
|
return c.json({
|
|
1057
|
-
data: { id: doc.rootId, title: doc.title, slug: doc.slug, status: doc.status, collectionId: backing.coll.id, data: doc.data, created_at:
|
|
1059
|
+
data: { id: doc.rootId, title: doc.title, slug: doc.slug, status: doc.status, collectionId: backing.coll.id, data: doc.data, created_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(doc.createdAt), updated_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(doc.updatedAt) }
|
|
1058
1060
|
}, 201);
|
|
1059
1061
|
}
|
|
1060
1062
|
return c.json({ error: "Collection is not document-backed" }, 400);
|
|
@@ -1066,7 +1068,7 @@ apiContentCrudRoutes.post("/", chunkAAWNRBRB_cjs.requireAuth(), chunkAAWNRBRB_cj
|
|
|
1066
1068
|
}, 500);
|
|
1067
1069
|
}
|
|
1068
1070
|
});
|
|
1069
|
-
apiContentCrudRoutes.put("/:id",
|
|
1071
|
+
apiContentCrudRoutes.put("/:id", chunkFCLKX2OS_cjs.requireAuth(), chunkFCLKX2OS_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
1070
1072
|
try {
|
|
1071
1073
|
const id = c.req.param("id");
|
|
1072
1074
|
const db = c.env.DB;
|
|
@@ -1088,8 +1090,8 @@ apiContentCrudRoutes.put("/:id", chunkAAWNRBRB_cjs.requireAuth(), chunkAAWNRBRB_
|
|
|
1088
1090
|
} catch (err) {
|
|
1089
1091
|
return c.json({ error: "Write cancelled by plugin", details: String(err) }, 400);
|
|
1090
1092
|
}
|
|
1091
|
-
const docType = await new
|
|
1092
|
-
const svc = new
|
|
1093
|
+
const docType = await new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db).findById(docRow.type_id);
|
|
1094
|
+
const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, {
|
|
1093
1095
|
queryableFields: docType?.queryableFields ?? [],
|
|
1094
1096
|
typeSchemaVersion: docType?.schemaVersion ?? 1,
|
|
1095
1097
|
maxVersionsPerRoot: docType?.settings?.maxVersionsPerRoot ?? 50,
|
|
@@ -1108,10 +1110,10 @@ apiContentCrudRoutes.put("/:id", chunkAAWNRBRB_cjs.requireAuth(), chunkAAWNRBRB_
|
|
|
1108
1110
|
} else if (body.status === "draft" && pub) {
|
|
1109
1111
|
await svc.unpublish(pub.id);
|
|
1110
1112
|
}
|
|
1111
|
-
const cache =
|
|
1113
|
+
const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
|
|
1112
1114
|
await cache.invalidate("content-filtered:*");
|
|
1113
1115
|
await cache.invalidate("collection-content-filtered:*");
|
|
1114
|
-
const coll =
|
|
1116
|
+
const coll = chunkKVBHB7QP_cjs.getCollectionRegistry().getByName(docRow.type_id);
|
|
1115
1117
|
const saved = await db.prepare("SELECT * FROM documents WHERE id = ?").bind(newDraft.id).first();
|
|
1116
1118
|
const savedData = saved?.data ? JSON.parse(saved.data) : {};
|
|
1117
1119
|
dispatchHookEvent(c, "content:after:update", { collection: docRow.type_id, id, data: savedData, user: actor }, "fire-and-forget");
|
|
@@ -1120,7 +1122,7 @@ apiContentCrudRoutes.put("/:id", chunkAAWNRBRB_cjs.requireAuth(), chunkAAWNRBRB_
|
|
|
1120
1122
|
dispatchHookEvent(c, "content:after:publish", { collection: docRow.type_id, id, data: savedData, user: actor }, "fire-and-forget");
|
|
1121
1123
|
}
|
|
1122
1124
|
return c.json({
|
|
1123
|
-
data: { id: saved.root_id, title: saved.title, slug: saved.slug, status: saved.status, collectionId: coll?.id ?? docRow.type_id, data: savedData, created_at:
|
|
1125
|
+
data: { id: saved.root_id, title: saved.title, slug: saved.slug, status: saved.status, collectionId: coll?.id ?? docRow.type_id, data: savedData, created_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(saved.created_at), updated_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(saved.updated_at) }
|
|
1124
1126
|
});
|
|
1125
1127
|
}
|
|
1126
1128
|
return c.json({ error: "Content not found" }, 404);
|
|
@@ -1132,7 +1134,7 @@ apiContentCrudRoutes.put("/:id", chunkAAWNRBRB_cjs.requireAuth(), chunkAAWNRBRB_
|
|
|
1132
1134
|
}, 500);
|
|
1133
1135
|
}
|
|
1134
1136
|
});
|
|
1135
|
-
apiContentCrudRoutes.delete("/:id",
|
|
1137
|
+
apiContentCrudRoutes.delete("/:id", chunkFCLKX2OS_cjs.requireAuth(), chunkFCLKX2OS_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
1136
1138
|
try {
|
|
1137
1139
|
const id = c.req.param("id");
|
|
1138
1140
|
const db = c.env.DB;
|
|
@@ -1148,7 +1150,7 @@ apiContentCrudRoutes.delete("/:id", chunkAAWNRBRB_cjs.requireAuth(), chunkAAWNRB
|
|
|
1148
1150
|
}
|
|
1149
1151
|
const now = Math.floor(Date.now() / 1e3);
|
|
1150
1152
|
await db.prepare("UPDATE documents SET deleted_at = ?, updated_at = ? WHERE root_id = ? AND tenant_id = ?").bind(now, now, id, tenantId).run();
|
|
1151
|
-
const cache =
|
|
1153
|
+
const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
|
|
1152
1154
|
await cache.invalidate("content-filtered:*");
|
|
1153
1155
|
await cache.invalidate("collection-content-filtered:*");
|
|
1154
1156
|
dispatchHookEvent(c, "content:after:delete", { collection: docRow.type_id, id, data: {}, user: actor }, "fire-and-forget");
|
|
@@ -1245,8 +1247,8 @@ function mapDocRowToContent(row, collectionId) {
|
|
|
1245
1247
|
collectionId,
|
|
1246
1248
|
data: row.data ? JSON.parse(row.data) : {},
|
|
1247
1249
|
// D29: document timestamps are SECONDS; the legacy `content` API contract is MILLISECONDS.
|
|
1248
|
-
created_at:
|
|
1249
|
-
updated_at:
|
|
1250
|
+
created_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(row.created_at),
|
|
1251
|
+
updated_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(row.updated_at)
|
|
1250
1252
|
};
|
|
1251
1253
|
}
|
|
1252
1254
|
var apiRoutes = new hono.Hono();
|
|
@@ -1258,20 +1260,10 @@ apiRoutes.use("*", async (c, next) => {
|
|
|
1258
1260
|
c.header("X-Response-Time", `${totalTime}ms`);
|
|
1259
1261
|
});
|
|
1260
1262
|
apiRoutes.use("*", async (c, next) => {
|
|
1261
|
-
const cacheEnabled = await
|
|
1263
|
+
const cacheEnabled = await chunkFCLKX2OS_cjs.isPluginActive(c.env.DB, "core-cache");
|
|
1262
1264
|
c.set("cacheEnabled", cacheEnabled);
|
|
1263
1265
|
await next();
|
|
1264
1266
|
});
|
|
1265
|
-
apiRoutes.use("*", cors.cors({
|
|
1266
|
-
origin: (origin, c) => {
|
|
1267
|
-
const allowed = c.env?.CORS_ORIGINS;
|
|
1268
|
-
if (!allowed) return null;
|
|
1269
|
-
const list = allowed.split(",").map((s) => s.trim());
|
|
1270
|
-
return list.includes(origin) ? origin : null;
|
|
1271
|
-
},
|
|
1272
|
-
allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
|
|
1273
|
-
allowHeaders: ["Content-Type", "Authorization", "X-API-Key"]
|
|
1274
|
-
}));
|
|
1275
1267
|
function addTimingMeta(c, meta = {}, executionStartTime) {
|
|
1276
1268
|
const totalTime = Date.now() - c.get("startTime");
|
|
1277
1269
|
const executionTime = executionStartTime ? Date.now() - executionStartTime : void 0;
|
|
@@ -1291,7 +1283,7 @@ apiRoutes.get("/", (c) => {
|
|
|
1291
1283
|
openapi: "3.0.0",
|
|
1292
1284
|
info: {
|
|
1293
1285
|
title: "SonicJS AI API",
|
|
1294
|
-
version:
|
|
1286
|
+
version: chunkAOUVUF32_cjs.getCoreVersion(),
|
|
1295
1287
|
description: "RESTful API for SonicJS headless CMS - a modern, AI-powered content management system built on Cloudflare Workers",
|
|
1296
1288
|
contact: {
|
|
1297
1289
|
name: "SonicJS Support",
|
|
@@ -1695,7 +1687,7 @@ apiRoutes.get("/collections", async (c) => {
|
|
|
1695
1687
|
try {
|
|
1696
1688
|
const db = c.env.DB;
|
|
1697
1689
|
const cacheEnabled = c.get("cacheEnabled");
|
|
1698
|
-
const cache =
|
|
1690
|
+
const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
|
|
1699
1691
|
const cacheKey = cache.generateKey("collections", "all");
|
|
1700
1692
|
if (cacheEnabled) {
|
|
1701
1693
|
const cacheResult = await cache.getWithSource(cacheKey);
|
|
@@ -1721,8 +1713,8 @@ apiRoutes.get("/collections", async (c) => {
|
|
|
1721
1713
|
}
|
|
1722
1714
|
c.header("X-Cache-Status", "MISS");
|
|
1723
1715
|
c.header("X-Cache-Source", "registry");
|
|
1724
|
-
const records =
|
|
1725
|
-
const transformedResults = records.map(
|
|
1716
|
+
const records = chunkKVBHB7QP_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal);
|
|
1717
|
+
const transformedResults = records.map(chunkKVBHB7QP_cjs.collectionRecordToRow);
|
|
1726
1718
|
const responseData = {
|
|
1727
1719
|
data: transformedResults,
|
|
1728
1720
|
meta: addTimingMeta(c, {
|
|
@@ -1743,7 +1735,7 @@ apiRoutes.get("/collections", async (c) => {
|
|
|
1743
1735
|
return c.json({ error: "Failed to fetch collections" }, 500);
|
|
1744
1736
|
}
|
|
1745
1737
|
});
|
|
1746
|
-
apiRoutes.get("/content",
|
|
1738
|
+
apiRoutes.get("/content", chunkFCLKX2OS_cjs.optionalAuth(), async (c) => {
|
|
1747
1739
|
const executionStart = Date.now();
|
|
1748
1740
|
try {
|
|
1749
1741
|
const db = c.env.DB;
|
|
@@ -1752,7 +1744,7 @@ apiRoutes.get("/content", chunkAAWNRBRB_cjs.optionalAuth(), async (c) => {
|
|
|
1752
1744
|
const collIdByName = /* @__PURE__ */ new Map();
|
|
1753
1745
|
let typeId;
|
|
1754
1746
|
let typeIds;
|
|
1755
|
-
const registry =
|
|
1747
|
+
const registry = chunkKVBHB7QP_cjs.getCollectionRegistry();
|
|
1756
1748
|
if (queryParams.collection) {
|
|
1757
1749
|
const collectionName = queryParams.collection;
|
|
1758
1750
|
const record = registry.getByName(collectionName);
|
|
@@ -1795,7 +1787,7 @@ apiRoutes.get("/content", chunkAAWNRBRB_cjs.optionalAuth(), async (c) => {
|
|
|
1795
1787
|
}, 400);
|
|
1796
1788
|
}
|
|
1797
1789
|
const cacheEnabled = c.get("cacheEnabled");
|
|
1798
|
-
const cache =
|
|
1790
|
+
const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
|
|
1799
1791
|
const cacheKey = cache.generateKey("content-filtered", JSON.stringify({ filter: normalizedFilter, query: queryResult.sql }));
|
|
1800
1792
|
if (cacheEnabled) {
|
|
1801
1793
|
const cacheResult = await cache.getWithSource(cacheKey);
|
|
@@ -1851,13 +1843,13 @@ apiRoutes.get("/content", chunkAAWNRBRB_cjs.optionalAuth(), async (c) => {
|
|
|
1851
1843
|
}, 500);
|
|
1852
1844
|
}
|
|
1853
1845
|
});
|
|
1854
|
-
apiRoutes.get("/collections/:collection/content",
|
|
1846
|
+
apiRoutes.get("/collections/:collection/content", chunkFCLKX2OS_cjs.optionalAuth(), async (c) => {
|
|
1855
1847
|
const executionStart = Date.now();
|
|
1856
1848
|
try {
|
|
1857
1849
|
const collection = c.req.param("collection");
|
|
1858
1850
|
const db = c.env.DB;
|
|
1859
1851
|
const queryParams = c.req.query();
|
|
1860
|
-
const record =
|
|
1852
|
+
const record = chunkKVBHB7QP_cjs.getCollectionRegistry().getBySlugOrName(collection);
|
|
1861
1853
|
if (!record || record.isActive === false) {
|
|
1862
1854
|
return c.json({ error: "Collection not found" }, 404);
|
|
1863
1855
|
}
|
|
@@ -1879,7 +1871,7 @@ apiRoutes.get("/collections/:collection/content", chunkAAWNRBRB_cjs.optionalAuth
|
|
|
1879
1871
|
}, 400);
|
|
1880
1872
|
}
|
|
1881
1873
|
const cacheEnabled = c.get("cacheEnabled");
|
|
1882
|
-
const cache =
|
|
1874
|
+
const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
|
|
1883
1875
|
const includeCollection = queryParams.include?.split(",").map((s) => s.trim()).includes("collection");
|
|
1884
1876
|
const cacheKey = cache.generateKey("collection-content-filtered", `${collection}:${JSON.stringify({ filter: normalizedFilter, query: queryResult.sql, includeCollection })}`);
|
|
1885
1877
|
if (cacheEnabled) {
|
|
@@ -1913,7 +1905,7 @@ apiRoutes.get("/collections/:collection/content", chunkAAWNRBRB_cjs.optionalAuth
|
|
|
1913
1905
|
const responseData = {
|
|
1914
1906
|
data: transformedResults,
|
|
1915
1907
|
meta: addTimingMeta(c, {
|
|
1916
|
-
...includeCollection ? { collection:
|
|
1908
|
+
...includeCollection ? { collection: chunkKVBHB7QP_cjs.collectionRecordToRow(record) } : {},
|
|
1917
1909
|
count: results.length,
|
|
1918
1910
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1919
1911
|
// D44: echo the caller's filter with the access policy applied (status=published forced for
|
|
@@ -1938,13 +1930,13 @@ apiRoutes.get("/collections/:collection/content", chunkAAWNRBRB_cjs.optionalAuth
|
|
|
1938
1930
|
}
|
|
1939
1931
|
});
|
|
1940
1932
|
apiRoutes.route("/content", api_content_crud_default);
|
|
1941
|
-
apiRoutes.get("/:collection",
|
|
1933
|
+
apiRoutes.get("/:collection", chunkFCLKX2OS_cjs.optionalAuth(), async (c) => {
|
|
1942
1934
|
const executionStart = Date.now();
|
|
1943
1935
|
try {
|
|
1944
1936
|
const collection = c.req.param("collection");
|
|
1945
1937
|
const db = c.env.DB;
|
|
1946
1938
|
const queryParams = c.req.query();
|
|
1947
|
-
const record =
|
|
1939
|
+
const record = chunkKVBHB7QP_cjs.getCollectionRegistry().getBySlugOrName(collection);
|
|
1948
1940
|
if (!record || record.isActive === false) {
|
|
1949
1941
|
return c.json({ error: "Collection not found" }, 404);
|
|
1950
1942
|
}
|
|
@@ -1963,7 +1955,7 @@ apiRoutes.get("/:collection", chunkAAWNRBRB_cjs.optionalAuth(), async (c) => {
|
|
|
1963
1955
|
const collectionCache = record.cache;
|
|
1964
1956
|
const collectionCacheDisabled = collectionCache?.enabled === false;
|
|
1965
1957
|
const cacheEnabled = c.get("cacheEnabled") && !collectionCacheDisabled;
|
|
1966
|
-
const cache =
|
|
1958
|
+
const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
|
|
1967
1959
|
const includeCollection = queryParams.include?.split(",").map((s) => s.trim()).includes("collection");
|
|
1968
1960
|
const cacheKey = cache.generateKey("collection-content-filtered", `${collection}:${JSON.stringify({ filter: normalizedFilter, query: queryResult.sql, includeCollection })}`);
|
|
1969
1961
|
if (cacheEnabled) {
|
|
@@ -1984,7 +1976,7 @@ apiRoutes.get("/:collection", chunkAAWNRBRB_cjs.optionalAuth(), async (c) => {
|
|
|
1984
1976
|
const responseData = {
|
|
1985
1977
|
data: transformedResults,
|
|
1986
1978
|
meta: addTimingMeta(c, {
|
|
1987
|
-
...includeCollection ? { collection:
|
|
1979
|
+
...includeCollection ? { collection: chunkKVBHB7QP_cjs.collectionRecordToRow(record) } : {},
|
|
1988
1980
|
count: results.length,
|
|
1989
1981
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1990
1982
|
filter: normalizePublicContentFilter(filter, role),
|
|
@@ -2002,12 +1994,12 @@ apiRoutes.get("/:collection", chunkAAWNRBRB_cjs.optionalAuth(), async (c) => {
|
|
|
2002
1994
|
return c.json({ error: "Failed to fetch content", details: error instanceof Error ? error.message : String(error) }, 500);
|
|
2003
1995
|
}
|
|
2004
1996
|
});
|
|
2005
|
-
apiRoutes.get("/:collection/:id",
|
|
1997
|
+
apiRoutes.get("/:collection/:id", chunkFCLKX2OS_cjs.optionalAuth(), async (c) => {
|
|
2006
1998
|
try {
|
|
2007
1999
|
const collection = c.req.param("collection");
|
|
2008
2000
|
const id = c.req.param("id");
|
|
2009
2001
|
const db = c.env.DB;
|
|
2010
|
-
const record =
|
|
2002
|
+
const record = chunkKVBHB7QP_cjs.getCollectionRegistry().getBySlugOrName(collection);
|
|
2011
2003
|
if (!record || record.isActive === false) {
|
|
2012
2004
|
return c.json({ error: "Collection not found" }, 404);
|
|
2013
2005
|
}
|
|
@@ -2016,7 +2008,7 @@ apiRoutes.get("/:collection/:id", chunkAAWNRBRB_cjs.optionalAuth(), async (c) =>
|
|
|
2016
2008
|
privileged ? "SELECT * FROM documents WHERE root_id = ? AND type_id = ? AND tenant_id = 'default' AND is_current_draft = 1 AND deleted_at IS NULL" : "SELECT * FROM documents WHERE root_id = ? AND type_id = ? AND tenant_id = 'default' AND is_published = 1 AND deleted_at IS NULL"
|
|
2017
2009
|
).bind(id, record.name).first();
|
|
2018
2010
|
if (!docRow) return c.json({ error: "Content not found" }, 404);
|
|
2019
|
-
const coll =
|
|
2011
|
+
const coll = chunkKVBHB7QP_cjs.getCollectionRegistry().getByName(docRow.type_id);
|
|
2020
2012
|
const transformedContent = {
|
|
2021
2013
|
id: docRow.root_id,
|
|
2022
2014
|
title: docRow.title,
|
|
@@ -2024,8 +2016,8 @@ apiRoutes.get("/:collection/:id", chunkAAWNRBRB_cjs.optionalAuth(), async (c) =>
|
|
|
2024
2016
|
status: docRow.status,
|
|
2025
2017
|
collectionId: coll?.id ?? docRow.type_id,
|
|
2026
2018
|
data: docRow.data ? JSON.parse(docRow.data) : {},
|
|
2027
|
-
created_at:
|
|
2028
|
-
updated_at:
|
|
2019
|
+
created_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(docRow.created_at),
|
|
2020
|
+
updated_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(docRow.updated_at)
|
|
2029
2021
|
};
|
|
2030
2022
|
dispatchHookEvent(c, "content:read", { collection: docRow.type_id, id: docRow.root_id, data: transformedContent.data }, "fire-and-forget");
|
|
2031
2023
|
return c.json({ data: transformedContent });
|
|
@@ -2034,7 +2026,7 @@ apiRoutes.get("/:collection/:id", chunkAAWNRBRB_cjs.optionalAuth(), async (c) =>
|
|
|
2034
2026
|
return c.json({ error: "Failed to fetch content", details: error instanceof Error ? error.message : String(error) }, 500);
|
|
2035
2027
|
}
|
|
2036
2028
|
});
|
|
2037
|
-
apiRoutes.post("/:collection",
|
|
2029
|
+
apiRoutes.post("/:collection", chunkFCLKX2OS_cjs.requireAuth(), chunkFCLKX2OS_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
2038
2030
|
try {
|
|
2039
2031
|
const collection = c.req.param("collection");
|
|
2040
2032
|
const db = c.env.DB;
|
|
@@ -2055,26 +2047,26 @@ apiRoutes.post("/:collection", chunkAAWNRBRB_cjs.requireAuth(), chunkAAWNRBRB_cj
|
|
|
2055
2047
|
} catch (err) {
|
|
2056
2048
|
return c.json({ error: "Write cancelled by plugin", details: String(err) }, 400);
|
|
2057
2049
|
}
|
|
2058
|
-
const svc = new
|
|
2050
|
+
const svc = new chunkLTZ5WYOK_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 });
|
|
2059
2051
|
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);
|
|
2060
|
-
const cache =
|
|
2052
|
+
const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
|
|
2061
2053
|
await cache.invalidate("content-filtered:*");
|
|
2062
2054
|
await cache.invalidate("collection-content-filtered:*");
|
|
2063
2055
|
dispatchHookEvent(c, "content:after:create", { collection: backing.coll.name, id: doc.rootId, data: doc.data ?? {}, user: actor }, "fire-and-forget");
|
|
2064
|
-
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:
|
|
2056
|
+
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: chunkLTZ5WYOK_cjs.documentSecondsToMs(doc.createdAt), updated_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(doc.updatedAt) } }, 201);
|
|
2065
2057
|
} catch (error) {
|
|
2066
2058
|
console.error("Error creating content:", error);
|
|
2067
2059
|
return c.json({ error: "Failed to create content", details: error instanceof Error ? error.message : String(error) }, 500);
|
|
2068
2060
|
}
|
|
2069
2061
|
});
|
|
2070
|
-
apiRoutes.put("/:collection/:id",
|
|
2062
|
+
apiRoutes.put("/:collection/:id", chunkFCLKX2OS_cjs.requireAuth(), chunkFCLKX2OS_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
2071
2063
|
try {
|
|
2072
2064
|
const collection = c.req.param("collection");
|
|
2073
2065
|
const id = c.req.param("id");
|
|
2074
2066
|
const db = c.env.DB;
|
|
2075
2067
|
const user = c.get("user");
|
|
2076
2068
|
const body = await c.req.json();
|
|
2077
|
-
const collRecord =
|
|
2069
|
+
const collRecord = chunkKVBHB7QP_cjs.getCollectionRegistry().getBySlugOrName(collection);
|
|
2078
2070
|
const typeName = collRecord?.name ?? collection;
|
|
2079
2071
|
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();
|
|
2080
2072
|
if (!docRow) return c.json({ error: "Content not found" }, 404);
|
|
@@ -2086,8 +2078,8 @@ apiRoutes.put("/:collection/:id", chunkAAWNRBRB_cjs.requireAuth(), chunkAAWNRBRB
|
|
|
2086
2078
|
} catch (err) {
|
|
2087
2079
|
return c.json({ error: "Write cancelled by plugin", details: String(err) }, 400);
|
|
2088
2080
|
}
|
|
2089
|
-
const docType = await new
|
|
2090
|
-
const svc = new
|
|
2081
|
+
const docType = await new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db).findById(docRow.type_id);
|
|
2082
|
+
const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, { queryableFields: docType?.queryableFields ?? [], typeSchemaVersion: docType?.schemaVersion ?? 1, maxVersionsPerRoot: docType?.settings?.maxVersionsPerRoot ?? 50, tenantId: "default", versioning: docType?.settings?.versioning ?? false });
|
|
2091
2083
|
const input = {};
|
|
2092
2084
|
if (body.title !== void 0) input.title = body.title;
|
|
2093
2085
|
if (body.slug !== void 0) input.slug = slugify(body.slug);
|
|
@@ -2100,28 +2092,28 @@ apiRoutes.put("/:collection/:id", chunkAAWNRBRB_cjs.requireAuth(), chunkAAWNRBRB
|
|
|
2100
2092
|
} else if (body.status === "draft" && pub) {
|
|
2101
2093
|
await svc.unpublish(pub.id);
|
|
2102
2094
|
}
|
|
2103
|
-
const cache =
|
|
2095
|
+
const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
|
|
2104
2096
|
await cache.invalidate("content-filtered:*");
|
|
2105
2097
|
await cache.invalidate("collection-content-filtered:*");
|
|
2106
|
-
const coll =
|
|
2098
|
+
const coll = chunkKVBHB7QP_cjs.getCollectionRegistry().getByName(docRow.type_id);
|
|
2107
2099
|
const saved = await db.prepare("SELECT * FROM documents WHERE id = ?").bind(newDraft.id).first();
|
|
2108
2100
|
const savedData = saved?.data ? JSON.parse(saved.data) : {};
|
|
2109
2101
|
dispatchHookEvent(c, "content:after:update", { collection: docRow.type_id, id, data: savedData, user: actor }, "fire-and-forget");
|
|
2110
2102
|
const nowPublished = body.status === "published" || body.status === void 0 && wasPublished;
|
|
2111
2103
|
if (nowPublished && !wasPublished) dispatchHookEvent(c, "content:after:publish", { collection: docRow.type_id, id, data: savedData, user: actor }, "fire-and-forget");
|
|
2112
|
-
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:
|
|
2104
|
+
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: chunkLTZ5WYOK_cjs.documentSecondsToMs(saved.created_at), updated_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(saved.updated_at) } });
|
|
2113
2105
|
} catch (error) {
|
|
2114
2106
|
console.error("Error updating content:", error);
|
|
2115
2107
|
return c.json({ error: "Failed to update content", details: error instanceof Error ? error.message : String(error) }, 500);
|
|
2116
2108
|
}
|
|
2117
2109
|
});
|
|
2118
|
-
apiRoutes.delete("/:collection/:id",
|
|
2110
|
+
apiRoutes.delete("/:collection/:id", chunkFCLKX2OS_cjs.requireAuth(), chunkFCLKX2OS_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
2119
2111
|
try {
|
|
2120
2112
|
const collection = c.req.param("collection");
|
|
2121
2113
|
const id = c.req.param("id");
|
|
2122
2114
|
const db = c.env.DB;
|
|
2123
2115
|
const user = c.get("user");
|
|
2124
|
-
const collRecord =
|
|
2116
|
+
const collRecord = chunkKVBHB7QP_cjs.getCollectionRegistry().getBySlugOrName(collection);
|
|
2125
2117
|
const typeName = collRecord?.name ?? collection;
|
|
2126
2118
|
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();
|
|
2127
2119
|
if (!docRow) return c.json({ error: "Content not found" }, 404);
|
|
@@ -2133,7 +2125,7 @@ apiRoutes.delete("/:collection/:id", chunkAAWNRBRB_cjs.requireAuth(), chunkAAWNR
|
|
|
2133
2125
|
}
|
|
2134
2126
|
const now = Math.floor(Date.now() / 1e3);
|
|
2135
2127
|
await db.prepare("UPDATE documents SET deleted_at = ?, updated_at = ? WHERE root_id = ? AND tenant_id = 'default'").bind(now, now, id).run();
|
|
2136
|
-
const cache =
|
|
2128
|
+
const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
|
|
2137
2129
|
await cache.invalidate("content-filtered:*");
|
|
2138
2130
|
await cache.invalidate("collection-content-filtered:*");
|
|
2139
2131
|
dispatchHookEvent(c, "content:after:delete", { collection: docRow.type_id, id, data: {}, user: actor }, "fire-and-forget");
|
|
@@ -2204,9 +2196,11 @@ var MediaDocumentService = class {
|
|
|
2204
2196
|
this.db = db;
|
|
2205
2197
|
this.tenantId = tenantId;
|
|
2206
2198
|
}
|
|
2199
|
+
db;
|
|
2200
|
+
tenantId;
|
|
2207
2201
|
/** Create a media_asset document from R2 upload metadata. Published-on-create (immediately usable). */
|
|
2208
2202
|
async createFromUpload(meta, createdBy) {
|
|
2209
|
-
const svc = new
|
|
2203
|
+
const svc = new chunkLTZ5WYOK_cjs.DocumentsService(this.db, { queryableFields: MEDIA_QUERYABLE, tenantId: this.tenantId, maxVersionsPerRoot: 5 });
|
|
2210
2204
|
return svc.create(
|
|
2211
2205
|
createDocumentSchema.parse({
|
|
2212
2206
|
typeId: "media_asset",
|
|
@@ -2257,12 +2251,17 @@ var MediaDocumentService = class {
|
|
|
2257
2251
|
where.push("(json_extract(data, '$.filename') LIKE ? OR json_extract(data, '$.originalName') LIKE ? OR json_extract(data, '$.alt') LIKE ?)");
|
|
2258
2252
|
params.push(term, term, term);
|
|
2259
2253
|
}
|
|
2260
|
-
const listed = await
|
|
2254
|
+
const [listed, countResult] = await Promise.all([
|
|
2255
|
+
this.db.prepare(`SELECT * FROM documents WHERE ${where.join(" AND ")} ORDER BY updated_at DESC LIMIT ? OFFSET ?`).bind(...params, limit, offset).all(),
|
|
2256
|
+
this.db.prepare(`SELECT COUNT(*) AS total FROM documents WHERE ${where.join(" AND ")}`).bind(...params).first()
|
|
2257
|
+
]);
|
|
2261
2258
|
const files = (listed.results ?? []).map(rowToMinimalDoc);
|
|
2259
|
+
const total = countResult?.total ?? 0;
|
|
2262
2260
|
const folderAgg = await this.db.prepare(`SELECT q_media_folder AS folder, COUNT(*) AS count, SUM(q_media_size) AS totalSize FROM documents WHERE ${base} GROUP BY q_media_folder ORDER BY q_media_folder`).bind(this.tenantId).all();
|
|
2263
2261
|
const typeAgg = await this.db.prepare(`SELECT CASE WHEN q_media_mime LIKE 'image/%' THEN 'images' WHEN q_media_mime LIKE 'video/%' THEN 'videos' WHEN q_media_mime IN ('application/pdf', 'text/plain') THEN 'documents' ELSE 'other' END AS type, COUNT(*) AS count FROM documents WHERE ${base} GROUP BY type`).bind(this.tenantId).all();
|
|
2264
2262
|
return {
|
|
2265
2263
|
files,
|
|
2264
|
+
total,
|
|
2266
2265
|
folders: (folderAgg.results ?? []).map((f) => ({ folder: f.folder, count: f.count, totalSize: f.totalSize ?? 0 })),
|
|
2267
2266
|
types: (typeAgg.results ?? []).map((t) => ({ type: t.type, count: t.count }))
|
|
2268
2267
|
};
|
|
@@ -2279,7 +2278,7 @@ var MediaDocumentService = class {
|
|
|
2279
2278
|
}
|
|
2280
2279
|
/** Update alt/caption/tags on a media_asset document (saveDraft + publish atomically). */
|
|
2281
2280
|
async updateMetadata(rootId, meta, updatedBy) {
|
|
2282
|
-
const svc = new
|
|
2281
|
+
const svc = new chunkLTZ5WYOK_cjs.DocumentsService(this.db, { queryableFields: MEDIA_QUERYABLE, tenantId: this.tenantId, maxVersionsPerRoot: 5 });
|
|
2283
2282
|
const newDraft = await svc.saveDraft(rootId, { data: meta }, updatedBy);
|
|
2284
2283
|
return svc.publish(newDraft.id, updatedBy);
|
|
2285
2284
|
}
|
|
@@ -2336,7 +2335,7 @@ var fileValidationSchema = zod.z.object({
|
|
|
2336
2335
|
// 50MB max
|
|
2337
2336
|
});
|
|
2338
2337
|
var apiMediaRoutes = new hono.Hono();
|
|
2339
|
-
apiMediaRoutes.use("*",
|
|
2338
|
+
apiMediaRoutes.use("*", chunkFCLKX2OS_cjs.requireAuth());
|
|
2340
2339
|
apiMediaRoutes.post("/upload", async (c) => {
|
|
2341
2340
|
try {
|
|
2342
2341
|
const user = c.get("user");
|
|
@@ -3034,7 +3033,7 @@ apiSystemRoutes.get("/info", (c) => {
|
|
|
3034
3033
|
apiSystemRoutes.get("/stats", async (c) => {
|
|
3035
3034
|
try {
|
|
3036
3035
|
const db = c.env.DB;
|
|
3037
|
-
const typeIds =
|
|
3036
|
+
const typeIds = chunkKVBHB7QP_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal).map((r) => r.name);
|
|
3038
3037
|
let contentStats = null;
|
|
3039
3038
|
if (typeIds.length > 0) {
|
|
3040
3039
|
const placeholders = typeIds.map(() => "?").join(",");
|
|
@@ -3109,12 +3108,12 @@ apiSystemRoutes.get("/env", (c) => {
|
|
|
3109
3108
|
});
|
|
3110
3109
|
var api_system_default = apiSystemRoutes;
|
|
3111
3110
|
var adminApiRoutes = new hono.Hono();
|
|
3112
|
-
adminApiRoutes.use("*",
|
|
3113
|
-
adminApiRoutes.use("*",
|
|
3111
|
+
adminApiRoutes.use("*", chunkFCLKX2OS_cjs.requireAuth());
|
|
3112
|
+
adminApiRoutes.use("*", chunkFCLKX2OS_cjs.requireRole(["admin", "editor"]));
|
|
3114
3113
|
adminApiRoutes.get("/stats", async (c) => {
|
|
3115
3114
|
try {
|
|
3116
3115
|
const db = c.env.DB;
|
|
3117
|
-
const userCollections =
|
|
3116
|
+
const userCollections = chunkKVBHB7QP_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal);
|
|
3118
3117
|
const collectionsCount = userCollections.length;
|
|
3119
3118
|
let contentCount = 0;
|
|
3120
3119
|
if (userCollections.length > 0) {
|
|
@@ -3205,7 +3204,7 @@ adminApiRoutes.get("/collections", async (c) => {
|
|
|
3205
3204
|
try {
|
|
3206
3205
|
const search = c.req.query("search") || "";
|
|
3207
3206
|
const includeInactive = c.req.query("includeInactive") === "true";
|
|
3208
|
-
let records =
|
|
3207
|
+
let records = chunkKVBHB7QP_cjs.getCollectionRegistry().list().filter((r) => !r.internal);
|
|
3209
3208
|
if (!includeInactive) records = records.filter((r) => r.isActive !== false);
|
|
3210
3209
|
if (search) {
|
|
3211
3210
|
const needle = search.toLowerCase();
|
|
@@ -3237,7 +3236,7 @@ adminApiRoutes.get("/collections", async (c) => {
|
|
|
3237
3236
|
adminApiRoutes.get("/collections/:id", async (c) => {
|
|
3238
3237
|
try {
|
|
3239
3238
|
const id = c.req.param("id");
|
|
3240
|
-
const registry =
|
|
3239
|
+
const registry = chunkKVBHB7QP_cjs.getCollectionRegistry();
|
|
3241
3240
|
const record = registry.getById(id) ?? registry.getByName(id);
|
|
3242
3241
|
if (!record) {
|
|
3243
3242
|
return c.json({ error: "Collection not found" }, 404);
|
|
@@ -3287,7 +3286,7 @@ adminApiRoutes.get("/references", async (c) => {
|
|
|
3287
3286
|
if (collectionParams.length === 0) {
|
|
3288
3287
|
return c.json({ error: "Collection is required" }, 400);
|
|
3289
3288
|
}
|
|
3290
|
-
const registry =
|
|
3289
|
+
const registry = chunkKVBHB7QP_cjs.getCollectionRegistry();
|
|
3291
3290
|
const matched = collectionParams.map((param) => registry.getById(param) ?? registry.getByName(param)).filter((r) => !!r);
|
|
3292
3291
|
const seen = /* @__PURE__ */ new Set();
|
|
3293
3292
|
const collections = matched.filter((r) => {
|
|
@@ -3402,7 +3401,7 @@ adminApiRoutes.patch("/collections/:id", collectionsReadOnly);
|
|
|
3402
3401
|
adminApiRoutes.delete("/collections/:id", collectionsReadOnly);
|
|
3403
3402
|
adminApiRoutes.get("/migrations/status", async (c) => {
|
|
3404
3403
|
try {
|
|
3405
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
3404
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-V73ARYV5.cjs');
|
|
3406
3405
|
const db = c.env.DB;
|
|
3407
3406
|
const migrationService = new MigrationService2(db);
|
|
3408
3407
|
const status = await migrationService.getMigrationStatus();
|
|
@@ -3445,7 +3444,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
|
|
|
3445
3444
|
});
|
|
3446
3445
|
adminApiRoutes.get("/migrations/validate", async (c) => {
|
|
3447
3446
|
try {
|
|
3448
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
3447
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-V73ARYV5.cjs');
|
|
3449
3448
|
const db = c.env.DB;
|
|
3450
3449
|
const migrationService = new MigrationService2(db);
|
|
3451
3450
|
const validation = await migrationService.validateSchema();
|
|
@@ -3595,8 +3594,8 @@ function renderLoginPage(data, demoLoginActive = false) {
|
|
|
3595
3594
|
<div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
|
|
3596
3595
|
<div class="bg-zinc-900 shadow-sm ring-1 ring-white/10 rounded-xl px-6 py-8 sm:px-10">
|
|
3597
3596
|
<!-- Alerts -->
|
|
3598
|
-
${data.error ? `<div class="mb-6">${
|
|
3599
|
-
${data.message ? `<div class="mb-6">${
|
|
3597
|
+
${data.error ? `<div class="mb-6">${chunkPXNTCCPE_cjs.renderAlert({ type: "error", message: data.error })}</div>` : ""}
|
|
3598
|
+
${data.message ? `<div class="mb-6">${chunkPXNTCCPE_cjs.renderAlert({ type: "success", message: data.message })}</div>` : ""}
|
|
3600
3599
|
|
|
3601
3600
|
<!-- Form Response (HTMX target) -->
|
|
3602
3601
|
<div id="form-response" class="mb-6"></div>
|
|
@@ -3604,7 +3603,7 @@ function renderLoginPage(data, demoLoginActive = false) {
|
|
|
3604
3603
|
<!-- Form -->
|
|
3605
3604
|
<form
|
|
3606
3605
|
id="login-form"
|
|
3607
|
-
hx-post="/auth/login/form"
|
|
3606
|
+
hx-post="/auth/login/form${data.redirect ? `?redirect=${encodeURIComponent(data.redirect)}` : ""}"
|
|
3608
3607
|
hx-target="#form-response"
|
|
3609
3608
|
hx-swap="innerHTML"
|
|
3610
3609
|
class="space-y-6"
|
|
@@ -3760,7 +3759,7 @@ function renderRegisterPage(data) {
|
|
|
3760
3759
|
<div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
|
|
3761
3760
|
<div class="bg-zinc-900 shadow-sm ring-1 ring-white/10 rounded-xl px-6 py-8 sm:px-10">
|
|
3762
3761
|
<!-- Alerts -->
|
|
3763
|
-
${data.error ? `<div class="mb-6">${
|
|
3762
|
+
${data.error ? `<div class="mb-6">${chunkPXNTCCPE_cjs.renderAlert({ type: "error", message: data.error })}</div>` : ""}
|
|
3764
3763
|
|
|
3765
3764
|
<!-- Form -->
|
|
3766
3765
|
<form
|
|
@@ -3860,7 +3859,7 @@ function renderRegisterPage(data) {
|
|
|
3860
3859
|
}
|
|
3861
3860
|
|
|
3862
3861
|
// src/services/email/email-service-singleton.ts
|
|
3863
|
-
var singleton =
|
|
3862
|
+
var singleton = chunkA4KUJ3LD_cjs.createServiceSingleton("EmailService");
|
|
3864
3863
|
function setEmailService(service2) {
|
|
3865
3864
|
singleton.set(service2);
|
|
3866
3865
|
}
|
|
@@ -3904,7 +3903,7 @@ function emptyProfile() {
|
|
|
3904
3903
|
return { custom: {} };
|
|
3905
3904
|
}
|
|
3906
3905
|
function service(db) {
|
|
3907
|
-
return new
|
|
3906
|
+
return new chunkLTZ5WYOK_cjs.DocumentsService(db, { tenantId: "default", maxVersionsPerRoot: 1, queryableFields: [] });
|
|
3908
3907
|
}
|
|
3909
3908
|
async function readProfileData(db, userId) {
|
|
3910
3909
|
const row = await db.prepare(
|
|
@@ -4668,7 +4667,7 @@ function getLexicalInitScript(settings = {}) {
|
|
|
4668
4667
|
</script>
|
|
4669
4668
|
`;
|
|
4670
4669
|
}
|
|
4671
|
-
var lexicalEditorPlugin =
|
|
4670
|
+
var lexicalEditorPlugin = chunkA4KUJ3LD_cjs.definePlugin({
|
|
4672
4671
|
id: "lexical-editor",
|
|
4673
4672
|
version: "1.0.0",
|
|
4674
4673
|
name: "Lexical Editor",
|
|
@@ -5592,6 +5591,79 @@ function renderDynamicField(field, options = {}) {
|
|
|
5592
5591
|
`;
|
|
5593
5592
|
break;
|
|
5594
5593
|
}
|
|
5594
|
+
case "json": {
|
|
5595
|
+
const jsonParsedValue = value !== null && value !== void 0 && typeof value !== "string" ? value : typeof value === "string" && value !== "" ? (() => {
|
|
5596
|
+
try {
|
|
5597
|
+
return JSON.parse(value);
|
|
5598
|
+
} catch {
|
|
5599
|
+
return value;
|
|
5600
|
+
}
|
|
5601
|
+
})() : null;
|
|
5602
|
+
const jsonDisplayValue = jsonParsedValue !== null && typeof jsonParsedValue !== "string" ? JSON.stringify(jsonParsedValue, null, 2) : typeof jsonParsedValue === "string" ? jsonParsedValue : "";
|
|
5603
|
+
const viewerId = `${fieldId}-viewer`;
|
|
5604
|
+
const textareaId = `${fieldId}-textarea`;
|
|
5605
|
+
const jsonDataAttr = escapeHtml2(JSON.stringify(jsonParsedValue ?? null));
|
|
5606
|
+
const isEmpty = jsonParsedValue === null || jsonDisplayValue === "";
|
|
5607
|
+
if (disabled) {
|
|
5608
|
+
fieldHTML = `
|
|
5609
|
+
<div
|
|
5610
|
+
id="${viewerId}"
|
|
5611
|
+
class="json-viewer-host rounded-lg px-3 py-2 text-xs bg-white dark:bg-zinc-800 shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 min-h-[2.5rem] overflow-auto"
|
|
5612
|
+
data-json-viewer
|
|
5613
|
+
data-json="${jsonDataAttr}"
|
|
5614
|
+
data-open="${opts.open ?? 2}"
|
|
5615
|
+
>${isEmpty ? '<span class="text-zinc-400 dark:text-zinc-500 italic">empty</span>' : ""}</div>
|
|
5616
|
+
${getJsonViewerScript()}
|
|
5617
|
+
`;
|
|
5618
|
+
} else {
|
|
5619
|
+
fieldHTML = `
|
|
5620
|
+
<div class="json-field-wrapper space-y-2">
|
|
5621
|
+
<div class="flex items-center justify-end">
|
|
5622
|
+
<button
|
|
5623
|
+
type="button"
|
|
5624
|
+
id="${fieldId}-toggle"
|
|
5625
|
+
class="text-xs text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-200 underline transition-colors"
|
|
5626
|
+
data-json-toggle
|
|
5627
|
+
data-viewer="${viewerId}"
|
|
5628
|
+
data-textarea="${textareaId}"
|
|
5629
|
+
data-hidden-input="${fieldId}"
|
|
5630
|
+
>Edit JSON</button>
|
|
5631
|
+
</div>
|
|
5632
|
+
|
|
5633
|
+
<div
|
|
5634
|
+
id="${viewerId}"
|
|
5635
|
+
class="json-viewer-host rounded-lg px-3 py-2 text-xs bg-white dark:bg-zinc-800 shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 min-h-[2.5rem] overflow-auto"
|
|
5636
|
+
data-json-viewer
|
|
5637
|
+
data-json="${jsonDataAttr}"
|
|
5638
|
+
data-open="${opts.open ?? 2}"
|
|
5639
|
+
>${isEmpty ? '<span class="text-zinc-400 dark:text-zinc-500 italic">empty \u2014 click "Edit JSON" to add data</span>' : ""}</div>
|
|
5640
|
+
|
|
5641
|
+
<textarea
|
|
5642
|
+
id="${textareaId}"
|
|
5643
|
+
rows="${opts.rows || 8}"
|
|
5644
|
+
placeholder="${opts.placeholder || "{}"}"
|
|
5645
|
+
class="${baseClasses} ${errorClasses} resize-y font-mono text-xs hidden"
|
|
5646
|
+
aria-label="${escapeHtml2(field.field_label)}"
|
|
5647
|
+
data-json-edit-area
|
|
5648
|
+
data-viewer="${viewerId}"
|
|
5649
|
+
data-hidden-input="${fieldId}"
|
|
5650
|
+
>${escapeHtml2(jsonDisplayValue)}</textarea>
|
|
5651
|
+
|
|
5652
|
+
<input
|
|
5653
|
+
type="hidden"
|
|
5654
|
+
id="${fieldId}"
|
|
5655
|
+
name="${fieldName}"
|
|
5656
|
+
value="${escapeHtml2(jsonDisplayValue)}"
|
|
5657
|
+
${required}
|
|
5658
|
+
>
|
|
5659
|
+
|
|
5660
|
+
<div id="${fieldId}-json-error" class="text-xs text-pink-500 dark:text-pink-400 hidden"></div>
|
|
5661
|
+
</div>
|
|
5662
|
+
${getJsonViewerScript()}
|
|
5663
|
+
`;
|
|
5664
|
+
}
|
|
5665
|
+
break;
|
|
5666
|
+
}
|
|
5595
5667
|
default:
|
|
5596
5668
|
fieldHTML = `
|
|
5597
5669
|
<input
|
|
@@ -6088,6 +6160,120 @@ function normalizeBlockField(fieldConfig, fieldName) {
|
|
|
6088
6160
|
options
|
|
6089
6161
|
};
|
|
6090
6162
|
}
|
|
6163
|
+
function getJsonViewerScript() {
|
|
6164
|
+
return `
|
|
6165
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/json-formatter-js@2.5.23/dist/json-formatter.min.css" id="json-formatter-css" onload="this.removeAttribute('onload')" onerror="">
|
|
6166
|
+
<script>
|
|
6167
|
+
(function() {
|
|
6168
|
+
var JS_URL = 'https://cdn.jsdelivr.net/npm/json-formatter-js@2.5.23/dist/json-formatter.umd.min.js';
|
|
6169
|
+
|
|
6170
|
+
function isDark() {
|
|
6171
|
+
return document.documentElement.classList.contains('dark') ||
|
|
6172
|
+
document.documentElement.dataset.theme === 'dark' ||
|
|
6173
|
+
window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
6174
|
+
}
|
|
6175
|
+
|
|
6176
|
+
function initViewer(el) {
|
|
6177
|
+
var raw = el.dataset.json;
|
|
6178
|
+
var open = parseInt(el.dataset.open || '2', 10);
|
|
6179
|
+
if (!raw || raw === 'null') return;
|
|
6180
|
+
var data;
|
|
6181
|
+
try { data = JSON.parse(raw); } catch(e) { el.textContent = raw; return; }
|
|
6182
|
+
var fmt = new JSONFormatter(data, open, {
|
|
6183
|
+
hoverPreviewEnabled: true,
|
|
6184
|
+
hoverPreviewArrayCount: 5,
|
|
6185
|
+
hoverPreviewFieldCount: 5,
|
|
6186
|
+
theme: isDark() ? 'dark' : '',
|
|
6187
|
+
animateOpen: true,
|
|
6188
|
+
animateClose: true,
|
|
6189
|
+
});
|
|
6190
|
+
el.innerHTML = '';
|
|
6191
|
+
el.appendChild(fmt.render());
|
|
6192
|
+
}
|
|
6193
|
+
|
|
6194
|
+
function initAllViewers() {
|
|
6195
|
+
document.querySelectorAll('[data-json-viewer]').forEach(function(el) { initViewer(el); });
|
|
6196
|
+
}
|
|
6197
|
+
|
|
6198
|
+
function ensureLoaded(cb) {
|
|
6199
|
+
if (window.JSONFormatter) { cb(); return; }
|
|
6200
|
+
if (window.__jsonFormatterCallbacks) { window.__jsonFormatterCallbacks.push(cb); return; }
|
|
6201
|
+
window.__jsonFormatterCallbacks = [cb];
|
|
6202
|
+
var s = document.createElement('script');
|
|
6203
|
+
s.src = JS_URL;
|
|
6204
|
+
s.onload = function() {
|
|
6205
|
+
(window.__jsonFormatterCallbacks || []).forEach(function(fn) { fn(); });
|
|
6206
|
+
window.__jsonFormatterCallbacks = null;
|
|
6207
|
+
};
|
|
6208
|
+
document.head.appendChild(s);
|
|
6209
|
+
}
|
|
6210
|
+
|
|
6211
|
+
if (!window.__sonicJsonViewerInit) {
|
|
6212
|
+
window.__sonicJsonViewerInit = true;
|
|
6213
|
+
|
|
6214
|
+
// Toggle between viewer and edit textarea
|
|
6215
|
+
document.addEventListener('click', function(e) {
|
|
6216
|
+
var btn = e.target.closest('[data-json-toggle]');
|
|
6217
|
+
if (!btn) return;
|
|
6218
|
+
var viewerId = btn.dataset.viewer;
|
|
6219
|
+
var textareaId = btn.dataset.textarea;
|
|
6220
|
+
var hiddenId = btn.dataset.hiddenInput;
|
|
6221
|
+
var viewer = document.getElementById(viewerId);
|
|
6222
|
+
var textarea = document.getElementById(textareaId);
|
|
6223
|
+
var hidden = document.getElementById(hiddenId);
|
|
6224
|
+
var errorEl = hidden ? document.getElementById(hiddenId + '-json-error') : null;
|
|
6225
|
+
if (!viewer || !textarea) return;
|
|
6226
|
+
var isEditing = !textarea.classList.contains('hidden');
|
|
6227
|
+
if (isEditing) {
|
|
6228
|
+
// Switching back to viewer \u2014 validate + refresh
|
|
6229
|
+
var raw = textarea.value.trim();
|
|
6230
|
+
if (raw) {
|
|
6231
|
+
try {
|
|
6232
|
+
var parsed = JSON.parse(raw);
|
|
6233
|
+
if (hidden) hidden.value = raw;
|
|
6234
|
+
viewer.dataset.json = JSON.stringify(parsed);
|
|
6235
|
+
ensureLoaded(function() { initViewer(viewer); });
|
|
6236
|
+
if (errorEl) { errorEl.textContent = ''; errorEl.classList.add('hidden'); }
|
|
6237
|
+
} catch(ex) {
|
|
6238
|
+
if (errorEl) { errorEl.textContent = 'Invalid JSON: ' + ex.message; errorEl.classList.remove('hidden'); }
|
|
6239
|
+
return;
|
|
6240
|
+
}
|
|
6241
|
+
} else {
|
|
6242
|
+
if (hidden) hidden.value = '';
|
|
6243
|
+
viewer.innerHTML = '<span class="text-zinc-400 dark:text-zinc-500 italic">empty</span>';
|
|
6244
|
+
}
|
|
6245
|
+
textarea.classList.add('hidden');
|
|
6246
|
+
viewer.classList.remove('hidden');
|
|
6247
|
+
btn.textContent = 'Edit JSON';
|
|
6248
|
+
} else {
|
|
6249
|
+
// Switching to edit \u2014 populate textarea from hidden input
|
|
6250
|
+
if (hidden && hidden.value) {
|
|
6251
|
+
try {
|
|
6252
|
+
textarea.value = JSON.stringify(JSON.parse(hidden.value), null, 2);
|
|
6253
|
+
} catch(e) {
|
|
6254
|
+
textarea.value = hidden.value;
|
|
6255
|
+
}
|
|
6256
|
+
}
|
|
6257
|
+
viewer.classList.add('hidden');
|
|
6258
|
+
textarea.classList.remove('hidden');
|
|
6259
|
+
btn.textContent = 'Preview';
|
|
6260
|
+
}
|
|
6261
|
+
});
|
|
6262
|
+
}
|
|
6263
|
+
|
|
6264
|
+
function run() {
|
|
6265
|
+
ensureLoaded(initAllViewers);
|
|
6266
|
+
}
|
|
6267
|
+
|
|
6268
|
+
if (document.readyState === 'loading') {
|
|
6269
|
+
document.addEventListener('DOMContentLoaded', run);
|
|
6270
|
+
} else {
|
|
6271
|
+
run();
|
|
6272
|
+
}
|
|
6273
|
+
})();
|
|
6274
|
+
</script>
|
|
6275
|
+
`;
|
|
6276
|
+
}
|
|
6091
6277
|
function getStructuredFieldScript() {
|
|
6092
6278
|
return `
|
|
6093
6279
|
${getReadFieldValueScript()}
|
|
@@ -6887,7 +7073,7 @@ api.put("/:userId", async (c) => {
|
|
|
6887
7073
|
await saveCustomData(db, userId, sanitized);
|
|
6888
7074
|
return c.json({ success: true });
|
|
6889
7075
|
});
|
|
6890
|
-
var userProfilesPlugin =
|
|
7076
|
+
var userProfilesPlugin = chunkA4KUJ3LD_cjs.definePlugin({
|
|
6891
7077
|
id: "user-profiles",
|
|
6892
7078
|
version: "1.0.0",
|
|
6893
7079
|
name: "User Profiles",
|
|
@@ -6925,8 +7111,8 @@ function renderPasswordResetEmail(resetLink, firstName) {
|
|
|
6925
7111
|
async function setCsrfCookie(c, maxAge) {
|
|
6926
7112
|
const secret = c.env?.JWT_SECRET || JWT_SECRET_FALLBACK;
|
|
6927
7113
|
const isDev = c.env?.ENVIRONMENT === "development" || !c.env?.ENVIRONMENT;
|
|
6928
|
-
const csrfToken = await
|
|
6929
|
-
const cookieMaxAge = await
|
|
7114
|
+
const csrfToken = await chunkFCLKX2OS_cjs.generateCsrfToken(secret);
|
|
7115
|
+
const cookieMaxAge = await chunkFCLKX2OS_cjs.getJwtExpirySecondsFromDb(c.env?.DB, c.env);
|
|
6930
7116
|
cookie.setCookie(c, "csrf_token", csrfToken, {
|
|
6931
7117
|
httpOnly: false,
|
|
6932
7118
|
secure: !isDev,
|
|
@@ -6948,10 +7134,12 @@ var authRoutes = new hono.Hono();
|
|
|
6948
7134
|
authRoutes.get("/login", async (c) => {
|
|
6949
7135
|
const error = c.req.query("error");
|
|
6950
7136
|
const message = c.req.query("message");
|
|
7137
|
+
const redirect = c.req.query("redirect");
|
|
6951
7138
|
const pageData = {
|
|
6952
7139
|
error: error || void 0,
|
|
6953
7140
|
message: message || void 0,
|
|
6954
|
-
version: c.get("appVersion")
|
|
7141
|
+
version: c.get("appVersion"),
|
|
7142
|
+
redirect: redirect && redirect.startsWith("/") ? redirect : void 0
|
|
6955
7143
|
};
|
|
6956
7144
|
const db = c.env.DB;
|
|
6957
7145
|
let demoLoginActive = false;
|
|
@@ -6964,9 +7152,9 @@ authRoutes.get("/login", async (c) => {
|
|
|
6964
7152
|
});
|
|
6965
7153
|
authRoutes.get("/register", async (c) => {
|
|
6966
7154
|
const db = c.env.DB;
|
|
6967
|
-
const isFirstUser = await
|
|
7155
|
+
const isFirstUser = await chunkXWVDSM2L_cjs.isFirstUserRegistration(db);
|
|
6968
7156
|
if (!isFirstUser) {
|
|
6969
|
-
const registrationEnabled = await
|
|
7157
|
+
const registrationEnabled = await chunkXWVDSM2L_cjs.isRegistrationEnabled(db);
|
|
6970
7158
|
if (!registrationEnabled) {
|
|
6971
7159
|
return c.redirect("/auth/login?error=Registration is currently disabled");
|
|
6972
7160
|
}
|
|
@@ -6983,13 +7171,13 @@ var loginSchema = zod.z.object({
|
|
|
6983
7171
|
});
|
|
6984
7172
|
authRoutes.post(
|
|
6985
7173
|
"/register",
|
|
6986
|
-
|
|
7174
|
+
chunkFCLKX2OS_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "register" }),
|
|
6987
7175
|
async (c) => {
|
|
6988
7176
|
try {
|
|
6989
7177
|
const db = c.env.DB;
|
|
6990
|
-
const isFirstUser = await
|
|
7178
|
+
const isFirstUser = await chunkXWVDSM2L_cjs.isFirstUserRegistration(db);
|
|
6991
7179
|
if (!isFirstUser) {
|
|
6992
|
-
const registrationEnabled = await
|
|
7180
|
+
const registrationEnabled = await chunkXWVDSM2L_cjs.isRegistrationEnabled(db);
|
|
6993
7181
|
if (!registrationEnabled) {
|
|
6994
7182
|
return c.json({ error: "Registration is currently disabled" }, 403);
|
|
6995
7183
|
}
|
|
@@ -7000,7 +7188,7 @@ authRoutes.post(
|
|
|
7000
7188
|
} catch (parseError) {
|
|
7001
7189
|
return c.json({ error: "Invalid JSON in request body" }, 400);
|
|
7002
7190
|
}
|
|
7003
|
-
const validationSchema = await
|
|
7191
|
+
const validationSchema = await chunkXWVDSM2L_cjs.authValidationService.buildRegistrationSchema(db);
|
|
7004
7192
|
let validatedData;
|
|
7005
7193
|
try {
|
|
7006
7194
|
validatedData = await validationSchema.parseAsync(requestData);
|
|
@@ -7012,14 +7200,14 @@ authRoutes.post(
|
|
|
7012
7200
|
}
|
|
7013
7201
|
const email = validatedData.email;
|
|
7014
7202
|
const password = validatedData.password;
|
|
7015
|
-
const firstName = validatedData.firstName ||
|
|
7016
|
-
const lastName = validatedData.lastName ||
|
|
7203
|
+
const firstName = validatedData.firstName || chunkXWVDSM2L_cjs.authValidationService.generateDefaultValue("firstName", validatedData);
|
|
7204
|
+
const lastName = validatedData.lastName || chunkXWVDSM2L_cjs.authValidationService.generateDefaultValue("lastName", validatedData);
|
|
7017
7205
|
const normalizedEmail = email.toLowerCase();
|
|
7018
7206
|
const existingUser = await db.prepare("SELECT id FROM auth_user WHERE email = ?").bind(normalizedEmail).first();
|
|
7019
7207
|
if (existingUser) {
|
|
7020
7208
|
return c.json({ error: "User with this email already exists" }, 400);
|
|
7021
7209
|
}
|
|
7022
|
-
const passwordHash = await
|
|
7210
|
+
const passwordHash = await chunkFCLKX2OS_cjs.AuthManager.hashPassword(password);
|
|
7023
7211
|
const userId = crypto.randomUUID();
|
|
7024
7212
|
const now = /* @__PURE__ */ new Date();
|
|
7025
7213
|
const nowSec = Math.floor(now.getTime() / 1e3);
|
|
@@ -7052,8 +7240,8 @@ authRoutes.post(
|
|
|
7052
7240
|
{ user: { id: userId, email: normalizedEmail, role: "viewer" } },
|
|
7053
7241
|
"fire-and-forget"
|
|
7054
7242
|
);
|
|
7055
|
-
const tokenTtl = await
|
|
7056
|
-
const token = await
|
|
7243
|
+
const tokenTtl = await chunkFCLKX2OS_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
|
|
7244
|
+
const token = await chunkFCLKX2OS_cjs.AuthManager.generateToken(userId, normalizedEmail, "viewer", c.env.JWT_SECRET, tokenTtl);
|
|
7057
7245
|
cookie.setCookie(c, "auth_token", token, {
|
|
7058
7246
|
httpOnly: true,
|
|
7059
7247
|
secure: true,
|
|
@@ -7085,7 +7273,7 @@ authRoutes.post(
|
|
|
7085
7273
|
);
|
|
7086
7274
|
authRoutes.post(
|
|
7087
7275
|
"/login",
|
|
7088
|
-
|
|
7276
|
+
chunkFCLKX2OS_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "login" }),
|
|
7089
7277
|
async (c) => {
|
|
7090
7278
|
try {
|
|
7091
7279
|
const body = await c.req.json();
|
|
@@ -7095,7 +7283,7 @@ authRoutes.post(
|
|
|
7095
7283
|
}
|
|
7096
7284
|
const { email, password } = validation.data;
|
|
7097
7285
|
const normalizedEmail = email.toLowerCase();
|
|
7098
|
-
const { createAuth } = await import('./config-
|
|
7286
|
+
const { createAuth } = await import('./config-OCH7S4WK.cjs');
|
|
7099
7287
|
const auth = createAuth(c.env);
|
|
7100
7288
|
const baReq = new Request(new URL("/auth/sign-in/email", c.req.url).href, {
|
|
7101
7289
|
method: "POST",
|
|
@@ -7117,6 +7305,20 @@ authRoutes.post(
|
|
|
7117
7305
|
await setCsrfCookie(c);
|
|
7118
7306
|
const baBody = await baRes.json();
|
|
7119
7307
|
const user = baBody.user ?? {};
|
|
7308
|
+
const tokenTtl = await chunkFCLKX2OS_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
|
|
7309
|
+
const token = await chunkFCLKX2OS_cjs.AuthManager.generateToken(
|
|
7310
|
+
user.id,
|
|
7311
|
+
user.email,
|
|
7312
|
+
user.role ?? "viewer",
|
|
7313
|
+
c.env.JWT_SECRET,
|
|
7314
|
+
tokenTtl
|
|
7315
|
+
);
|
|
7316
|
+
cookie.setCookie(c, "auth_token", token, {
|
|
7317
|
+
httpOnly: true,
|
|
7318
|
+
secure: true,
|
|
7319
|
+
sameSite: "Strict",
|
|
7320
|
+
maxAge: tokenTtl
|
|
7321
|
+
});
|
|
7120
7322
|
return c.json({
|
|
7121
7323
|
user: {
|
|
7122
7324
|
id: user.id,
|
|
@@ -7124,7 +7326,8 @@ authRoutes.post(
|
|
|
7124
7326
|
firstName: user.name?.split(" ")[0] ?? "",
|
|
7125
7327
|
lastName: user.name?.split(" ").slice(1).join(" ") ?? "",
|
|
7126
7328
|
role: user.role ?? "viewer"
|
|
7127
|
-
}
|
|
7329
|
+
},
|
|
7330
|
+
token
|
|
7128
7331
|
});
|
|
7129
7332
|
} catch (error) {
|
|
7130
7333
|
console.error("Login error:", error);
|
|
@@ -7134,7 +7337,7 @@ authRoutes.post(
|
|
|
7134
7337
|
);
|
|
7135
7338
|
authRoutes.post("/logout", async (c) => {
|
|
7136
7339
|
try {
|
|
7137
|
-
const { createAuth } = await import('./config-
|
|
7340
|
+
const { createAuth } = await import('./config-OCH7S4WK.cjs');
|
|
7138
7341
|
const auth = createAuth(c.env);
|
|
7139
7342
|
const baReq = new Request(new URL("/auth/sign-out", c.req.url).href, {
|
|
7140
7343
|
method: "POST",
|
|
@@ -7150,7 +7353,7 @@ authRoutes.post("/logout", async (c) => {
|
|
|
7150
7353
|
});
|
|
7151
7354
|
authRoutes.get("/logout", async (c) => {
|
|
7152
7355
|
try {
|
|
7153
|
-
const { createAuth } = await import('./config-
|
|
7356
|
+
const { createAuth } = await import('./config-OCH7S4WK.cjs');
|
|
7154
7357
|
const auth = createAuth(c.env);
|
|
7155
7358
|
const baReq = new Request(new URL("/auth/sign-out", c.req.url).href, {
|
|
7156
7359
|
method: "POST",
|
|
@@ -7164,7 +7367,7 @@ authRoutes.get("/logout", async (c) => {
|
|
|
7164
7367
|
clearCsrfCookie(c);
|
|
7165
7368
|
return c.redirect("/auth/login?message=You have been logged out successfully");
|
|
7166
7369
|
});
|
|
7167
|
-
authRoutes.get("/me",
|
|
7370
|
+
authRoutes.get("/me", chunkFCLKX2OS_cjs.requireAuth(), async (c) => {
|
|
7168
7371
|
try {
|
|
7169
7372
|
const user = c.get("user");
|
|
7170
7373
|
if (!user) {
|
|
@@ -7184,7 +7387,7 @@ authRoutes.get("/me", chunkAAWNRBRB_cjs.requireAuth(), async (c) => {
|
|
|
7184
7387
|
});
|
|
7185
7388
|
authRoutes.post(
|
|
7186
7389
|
"/refresh",
|
|
7187
|
-
|
|
7390
|
+
chunkFCLKX2OS_cjs.rateLimit({ max: 60, windowMs: 60 * 1e3, keyPrefix: "refresh" }),
|
|
7188
7391
|
async (c) => {
|
|
7189
7392
|
try {
|
|
7190
7393
|
let token = c.req.header("Authorization")?.replace("Bearer ", "");
|
|
@@ -7193,8 +7396,8 @@ authRoutes.post(
|
|
|
7193
7396
|
return c.json({ error: "Authentication required" }, 401);
|
|
7194
7397
|
}
|
|
7195
7398
|
const db = c.env.DB;
|
|
7196
|
-
const grace = await
|
|
7197
|
-
const payload = await
|
|
7399
|
+
const grace = await chunkFCLKX2OS_cjs.getJwtRefreshGraceSecondsFromDb(db, c.env);
|
|
7400
|
+
const payload = await chunkFCLKX2OS_cjs.AuthManager.verifyToken(token, c.env.JWT_SECRET, grace);
|
|
7198
7401
|
if (!payload) {
|
|
7199
7402
|
return c.json({ error: "Invalid or expired token" }, 401);
|
|
7200
7403
|
}
|
|
@@ -7202,8 +7405,8 @@ authRoutes.post(
|
|
|
7202
7405
|
if (!row || !row.is_active) {
|
|
7203
7406
|
return c.json({ error: "User is not active" }, 401);
|
|
7204
7407
|
}
|
|
7205
|
-
const tokenTtl = await
|
|
7206
|
-
const newToken = await
|
|
7408
|
+
const tokenTtl = await chunkFCLKX2OS_cjs.getJwtExpirySecondsFromDb(db, c.env);
|
|
7409
|
+
const newToken = await chunkFCLKX2OS_cjs.AuthManager.generateToken(row.id, row.email, row.role, c.env.JWT_SECRET, tokenTtl);
|
|
7207
7410
|
cookie.setCookie(c, "auth_token", newToken, {
|
|
7208
7411
|
httpOnly: true,
|
|
7209
7412
|
secure: true,
|
|
@@ -7223,13 +7426,13 @@ authRoutes.post(
|
|
|
7223
7426
|
);
|
|
7224
7427
|
authRoutes.post(
|
|
7225
7428
|
"/register/form",
|
|
7226
|
-
|
|
7429
|
+
chunkFCLKX2OS_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "register" }),
|
|
7227
7430
|
async (c) => {
|
|
7228
7431
|
try {
|
|
7229
7432
|
const db = c.env.DB;
|
|
7230
|
-
const isFirstUser = await
|
|
7433
|
+
const isFirstUser = await chunkXWVDSM2L_cjs.isFirstUserRegistration(db);
|
|
7231
7434
|
if (!isFirstUser) {
|
|
7232
|
-
const registrationEnabled = await
|
|
7435
|
+
const registrationEnabled = await chunkXWVDSM2L_cjs.isRegistrationEnabled(db);
|
|
7233
7436
|
if (!registrationEnabled) {
|
|
7234
7437
|
return c.html(html.html`
|
|
7235
7438
|
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded">
|
|
@@ -7247,7 +7450,7 @@ authRoutes.post(
|
|
|
7247
7450
|
};
|
|
7248
7451
|
const normalizedEmail = requestData.email?.toLowerCase();
|
|
7249
7452
|
requestData.email = normalizedEmail;
|
|
7250
|
-
const validationSchema = await
|
|
7453
|
+
const validationSchema = await chunkXWVDSM2L_cjs.authValidationService.buildRegistrationSchema(db);
|
|
7251
7454
|
const validation = await validationSchema.safeParseAsync(requestData);
|
|
7252
7455
|
if (!validation.success) {
|
|
7253
7456
|
return c.html(html.html`
|
|
@@ -7258,8 +7461,8 @@ authRoutes.post(
|
|
|
7258
7461
|
}
|
|
7259
7462
|
const validatedData = validation.data;
|
|
7260
7463
|
const password = validatedData.password;
|
|
7261
|
-
const firstName = validatedData.firstName ||
|
|
7262
|
-
const lastName = validatedData.lastName ||
|
|
7464
|
+
const firstName = validatedData.firstName || chunkXWVDSM2L_cjs.authValidationService.generateDefaultValue("firstName", validatedData);
|
|
7465
|
+
const lastName = validatedData.lastName || chunkXWVDSM2L_cjs.authValidationService.generateDefaultValue("lastName", validatedData);
|
|
7263
7466
|
const existingUser = await db.prepare("SELECT id FROM auth_user WHERE email = ?").bind(normalizedEmail).first();
|
|
7264
7467
|
if (existingUser) {
|
|
7265
7468
|
return c.html(html.html`
|
|
@@ -7268,7 +7471,7 @@ authRoutes.post(
|
|
|
7268
7471
|
</div>
|
|
7269
7472
|
`);
|
|
7270
7473
|
}
|
|
7271
|
-
const passwordHash = await
|
|
7474
|
+
const passwordHash = await chunkFCLKX2OS_cjs.AuthManager.hashPassword(password);
|
|
7272
7475
|
const role = isFirstUser ? "admin" : "viewer";
|
|
7273
7476
|
const userId = crypto.randomUUID();
|
|
7274
7477
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -7302,7 +7505,7 @@ authRoutes.post(
|
|
|
7302
7505
|
await saveCustomData(db, userId, sanitized);
|
|
7303
7506
|
}
|
|
7304
7507
|
}
|
|
7305
|
-
const rbacService = new
|
|
7508
|
+
const rbacService = new chunkLTZ5WYOK_cjs.RbacService(db);
|
|
7306
7509
|
await rbacService.addUserRoleByName(userId, role);
|
|
7307
7510
|
dispatchHookEvent(
|
|
7308
7511
|
c,
|
|
@@ -7310,8 +7513,8 @@ authRoutes.post(
|
|
|
7310
7513
|
{ user: { id: userId, email: normalizedEmail, role } },
|
|
7311
7514
|
"fire-and-forget"
|
|
7312
7515
|
);
|
|
7313
|
-
const tokenTtl = await
|
|
7314
|
-
const token = await
|
|
7516
|
+
const tokenTtl = await chunkFCLKX2OS_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
|
|
7517
|
+
const token = await chunkFCLKX2OS_cjs.AuthManager.generateToken(userId, normalizedEmail, role, c.env.JWT_SECRET, tokenTtl);
|
|
7315
7518
|
cookie.setCookie(c, "auth_token", token, {
|
|
7316
7519
|
httpOnly: true,
|
|
7317
7520
|
secure: false,
|
|
@@ -7343,7 +7546,7 @@ authRoutes.post(
|
|
|
7343
7546
|
);
|
|
7344
7547
|
authRoutes.post(
|
|
7345
7548
|
"/login/form",
|
|
7346
|
-
|
|
7549
|
+
chunkFCLKX2OS_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "login" }),
|
|
7347
7550
|
async (c) => {
|
|
7348
7551
|
try {
|
|
7349
7552
|
const formData = await c.req.formData();
|
|
@@ -7357,7 +7560,7 @@ authRoutes.post(
|
|
|
7357
7560
|
</div>
|
|
7358
7561
|
`);
|
|
7359
7562
|
}
|
|
7360
|
-
const { createAuth } = await import('./config-
|
|
7563
|
+
const { createAuth } = await import('./config-OCH7S4WK.cjs');
|
|
7361
7564
|
const auth = createAuth(c.env);
|
|
7362
7565
|
const baReq = new Request(new URL("/auth/sign-in/email", c.req.url).href, {
|
|
7363
7566
|
method: "POST",
|
|
@@ -7381,6 +7584,8 @@ authRoutes.post(
|
|
|
7381
7584
|
}
|
|
7382
7585
|
}
|
|
7383
7586
|
await setCsrfCookie(c);
|
|
7587
|
+
const rawRedirect = c.req.query("redirect");
|
|
7588
|
+
const redirectUrl = rawRedirect && rawRedirect.startsWith("/") ? rawRedirect : "/admin/content";
|
|
7384
7589
|
return c.html(html.html`
|
|
7385
7590
|
<div id="form-response">
|
|
7386
7591
|
<div class="rounded-lg bg-green-100 dark:bg-lime-500/10 p-4 ring-1 ring-green-400 dark:ring-lime-500/20">
|
|
@@ -7393,7 +7598,7 @@ authRoutes.post(
|
|
|
7393
7598
|
</div>
|
|
7394
7599
|
</div>
|
|
7395
7600
|
<script>
|
|
7396
|
-
setTimeout(() => { window.location.href = '
|
|
7601
|
+
setTimeout(() => { window.location.href = '${redirectUrl}'; }, 500);
|
|
7397
7602
|
</script>
|
|
7398
7603
|
</div>
|
|
7399
7604
|
</div>
|
|
@@ -7410,14 +7615,14 @@ authRoutes.post(
|
|
|
7410
7615
|
);
|
|
7411
7616
|
authRoutes.post(
|
|
7412
7617
|
"/seed-admin",
|
|
7413
|
-
|
|
7618
|
+
chunkFCLKX2OS_cjs.rateLimit({ max: 10, windowMs: 60 * 1e3, keyPrefix: "seed-admin" }),
|
|
7414
7619
|
async (c) => {
|
|
7415
7620
|
try {
|
|
7416
7621
|
const db = c.env.DB;
|
|
7417
|
-
const rbac = new
|
|
7622
|
+
const rbac = new chunkLTZ5WYOK_cjs.RbacService(db);
|
|
7418
7623
|
const results = [];
|
|
7419
7624
|
const upsertSeedUser = async (opts) => {
|
|
7420
|
-
const passwordHash = await
|
|
7625
|
+
const passwordHash = await chunkFCLKX2OS_cjs.AuthManager.hashPassword(opts.password);
|
|
7421
7626
|
const nowMs = Date.now();
|
|
7422
7627
|
const nowSec = Math.floor(nowMs / 1e3);
|
|
7423
7628
|
const existing = await db.prepare("SELECT id FROM auth_user WHERE email = ?").bind(opts.email).first();
|
|
@@ -7642,7 +7847,7 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
7642
7847
|
if (invitationAge > maxAge) {
|
|
7643
7848
|
return c.json({ error: "Invitation has expired" }, 400);
|
|
7644
7849
|
}
|
|
7645
|
-
const passwordHash = await
|
|
7850
|
+
const passwordHash = await chunkFCLKX2OS_cjs.AuthManager.hashPassword(password);
|
|
7646
7851
|
const updateStmt = db.prepare(`
|
|
7647
7852
|
UPDATE auth_user SET
|
|
7648
7853
|
password_hash = ?,
|
|
@@ -7659,8 +7864,8 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
7659
7864
|
Date.now(),
|
|
7660
7865
|
invitedUser.id
|
|
7661
7866
|
).run();
|
|
7662
|
-
const tokenTtl = await
|
|
7663
|
-
const authToken = await
|
|
7867
|
+
const tokenTtl = await chunkFCLKX2OS_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
|
|
7868
|
+
const authToken = await chunkFCLKX2OS_cjs.AuthManager.generateToken(invitedUser.id, invitedUser.email, invitedUser.role, c.env.JWT_SECRET, tokenTtl);
|
|
7664
7869
|
cookie.setCookie(c, "auth_token", authToken, {
|
|
7665
7870
|
httpOnly: true,
|
|
7666
7871
|
secure: true,
|
|
@@ -7676,7 +7881,7 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
7676
7881
|
});
|
|
7677
7882
|
authRoutes.post(
|
|
7678
7883
|
"/request-password-reset",
|
|
7679
|
-
|
|
7884
|
+
chunkFCLKX2OS_cjs.rateLimit({ max: 3, windowMs: 15 * 60 * 1e3, keyPrefix: "password-reset" }),
|
|
7680
7885
|
async (c) => {
|
|
7681
7886
|
try {
|
|
7682
7887
|
const formData = await c.req.formData();
|
|
@@ -7913,7 +8118,7 @@ authRoutes.post("/reset-password", async (c) => {
|
|
|
7913
8118
|
if (Date.now() > user.password_reset_expires) {
|
|
7914
8119
|
return c.json({ error: "Reset token has expired" }, 400);
|
|
7915
8120
|
}
|
|
7916
|
-
const newPasswordHash = await
|
|
8121
|
+
const newPasswordHash = await chunkFCLKX2OS_cjs.AuthManager.hashPassword(password);
|
|
7917
8122
|
try {
|
|
7918
8123
|
const historyStmt = db.prepare(`
|
|
7919
8124
|
INSERT INTO auth_password_history (id, user_id, password_hash, created_at)
|
|
@@ -8127,7 +8332,7 @@ app.post("/test-seed-defaults", async (c) => {
|
|
|
8127
8332
|
var test_cleanup_default = app;
|
|
8128
8333
|
|
|
8129
8334
|
// src/plugins/available/easy-mdx/index.ts
|
|
8130
|
-
|
|
8335
|
+
chunkA4KUJ3LD_cjs.definePlugin({
|
|
8131
8336
|
id: "easy-mdx",
|
|
8132
8337
|
version: "1.0.0",
|
|
8133
8338
|
name: "EasyMDE Markdown Editor",
|
|
@@ -8327,7 +8532,7 @@ function getMDXEditorInitScript(config) {
|
|
|
8327
8532
|
}
|
|
8328
8533
|
|
|
8329
8534
|
// src/plugins/available/tinymce-plugin/index.ts
|
|
8330
|
-
|
|
8535
|
+
chunkA4KUJ3LD_cjs.definePlugin({
|
|
8331
8536
|
id: "tinymce-plugin",
|
|
8332
8537
|
version: "1.0.0",
|
|
8333
8538
|
name: "TinyMCE",
|
|
@@ -8597,7 +8802,7 @@ function getQuillCDN(version = "2.0.2") {
|
|
|
8597
8802
|
</style>
|
|
8598
8803
|
`;
|
|
8599
8804
|
}
|
|
8600
|
-
|
|
8805
|
+
chunkA4KUJ3LD_cjs.definePlugin({
|
|
8601
8806
|
id: "quill-editor",
|
|
8602
8807
|
version: "1.0.0",
|
|
8603
8808
|
name: "Quill Editor",
|
|
@@ -8609,7 +8814,7 @@ chunkXW56B23A_cjs.definePlugin({
|
|
|
8609
8814
|
});
|
|
8610
8815
|
|
|
8611
8816
|
// src/templates/pages/admin-content-form.template.ts
|
|
8612
|
-
|
|
8817
|
+
chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
|
|
8613
8818
|
function renderContentFormPage(data, opts) {
|
|
8614
8819
|
const isEdit = data.isEdit || !!data.id;
|
|
8615
8820
|
const title = isEdit ? `Edit: ${data.title || "Content"}` : `New ${data.collection.display_name}`;
|
|
@@ -8691,8 +8896,8 @@ function renderContentFormPage(data, opts) {
|
|
|
8691
8896
|
<!-- Form Content -->
|
|
8692
8897
|
<div class="px-6 py-6">
|
|
8693
8898
|
<div id="form-messages">
|
|
8694
|
-
${data.error ?
|
|
8695
|
-
${data.success ?
|
|
8899
|
+
${data.error ? chunkPXNTCCPE_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
|
|
8900
|
+
${data.success ? chunkPXNTCCPE_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
|
|
8696
8901
|
</div>
|
|
8697
8902
|
|
|
8698
8903
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
@@ -8928,7 +9133,7 @@ function renderContentFormPage(data, opts) {
|
|
|
8928
9133
|
</div>
|
|
8929
9134
|
|
|
8930
9135
|
<!-- Confirmation Dialogs -->
|
|
8931
|
-
${
|
|
9136
|
+
${chunkPXNTCCPE_cjs.renderConfirmationDialog({
|
|
8932
9137
|
id: "duplicate-content-confirm",
|
|
8933
9138
|
title: "Duplicate Content",
|
|
8934
9139
|
message: "Create a copy of this content?",
|
|
@@ -8939,7 +9144,7 @@ function renderContentFormPage(data, opts) {
|
|
|
8939
9144
|
onConfirm: "performDuplicateContent()"
|
|
8940
9145
|
})}
|
|
8941
9146
|
|
|
8942
|
-
${
|
|
9147
|
+
${chunkPXNTCCPE_cjs.renderConfirmationDialog({
|
|
8943
9148
|
id: "delete-content-confirm",
|
|
8944
9149
|
title: "Delete Content",
|
|
8945
9150
|
message: "Are you sure you want to delete this content? This action cannot be undone.",
|
|
@@ -8950,7 +9155,7 @@ function renderContentFormPage(data, opts) {
|
|
|
8950
9155
|
onConfirm: `performDeleteContent('${data.id}')`
|
|
8951
9156
|
})}
|
|
8952
9157
|
|
|
8953
|
-
${
|
|
9158
|
+
${chunkPXNTCCPE_cjs.renderConfirmationDialog({
|
|
8954
9159
|
id: "delete-repeater-item-confirm",
|
|
8955
9160
|
title: "Delete Item",
|
|
8956
9161
|
message: "Are you sure you want to delete this item? This action cannot be undone.",
|
|
@@ -8961,7 +9166,7 @@ function renderContentFormPage(data, opts) {
|
|
|
8961
9166
|
onConfirm: "performRepeaterDelete()"
|
|
8962
9167
|
})}
|
|
8963
9168
|
|
|
8964
|
-
${
|
|
9169
|
+
${chunkPXNTCCPE_cjs.renderConfirmationDialog({
|
|
8965
9170
|
id: "delete-block-confirm",
|
|
8966
9171
|
title: "Delete Block",
|
|
8967
9172
|
message: "Are you sure you want to delete this block? This action cannot be undone.",
|
|
@@ -8972,7 +9177,7 @@ function renderContentFormPage(data, opts) {
|
|
|
8972
9177
|
onConfirm: "performRepeaterDelete()"
|
|
8973
9178
|
})}
|
|
8974
9179
|
|
|
8975
|
-
${
|
|
9180
|
+
${chunkPXNTCCPE_cjs.getConfirmationDialogScript()}
|
|
8976
9181
|
|
|
8977
9182
|
${data.lexicalEnabled ? getLexicalStyles() : "<!-- Lexical plugin not active -->"}
|
|
8978
9183
|
|
|
@@ -10058,11 +10263,11 @@ function renderContentFormPage(data, opts) {
|
|
|
10058
10263
|
content: pageContent,
|
|
10059
10264
|
version: data.version
|
|
10060
10265
|
};
|
|
10061
|
-
return
|
|
10266
|
+
return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
10062
10267
|
}
|
|
10063
10268
|
|
|
10064
10269
|
// src/templates/pages/admin-content-list.template.ts
|
|
10065
|
-
|
|
10270
|
+
chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
|
|
10066
10271
|
function renderContentListPage(data) {
|
|
10067
10272
|
const urlParams = new URLSearchParams();
|
|
10068
10273
|
if (data.modelName && data.modelName !== "all") urlParams.set("model", data.modelName);
|
|
@@ -10496,8 +10701,8 @@ function renderContentListPage(data) {
|
|
|
10496
10701
|
|
|
10497
10702
|
<!-- Content List -->
|
|
10498
10703
|
<div id="content-list">
|
|
10499
|
-
${
|
|
10500
|
-
${
|
|
10704
|
+
${chunkPXNTCCPE_cjs.renderTable(tableData)}
|
|
10705
|
+
${chunkPXNTCCPE_cjs.renderPagination(paginationData)}
|
|
10501
10706
|
</div>
|
|
10502
10707
|
|
|
10503
10708
|
</div>
|
|
@@ -10707,7 +10912,7 @@ function renderContentListPage(data) {
|
|
|
10707
10912
|
</script>
|
|
10708
10913
|
|
|
10709
10914
|
<!-- Confirmation Dialog for Bulk Actions -->
|
|
10710
|
-
${
|
|
10915
|
+
${chunkPXNTCCPE_cjs.renderConfirmationDialog({
|
|
10711
10916
|
id: "bulk-action-confirm",
|
|
10712
10917
|
title: "Confirm Bulk Action",
|
|
10713
10918
|
message: "Are you sure you want to perform this action? This operation will affect multiple items.",
|
|
@@ -10719,7 +10924,7 @@ function renderContentListPage(data) {
|
|
|
10719
10924
|
})}
|
|
10720
10925
|
|
|
10721
10926
|
<!-- Confirmation Dialog Script -->
|
|
10722
|
-
${
|
|
10927
|
+
${chunkPXNTCCPE_cjs.getConfirmationDialogScript()}
|
|
10723
10928
|
|
|
10724
10929
|
<!-- Advanced Search Modal -->
|
|
10725
10930
|
<div id="advancedSearchModal" class="hidden fixed inset-0 z-50 overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true">
|
|
@@ -11016,7 +11221,7 @@ function renderContentListPage(data) {
|
|
|
11016
11221
|
version: data.version,
|
|
11017
11222
|
content: pageContent
|
|
11018
11223
|
};
|
|
11019
|
-
return
|
|
11224
|
+
return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
11020
11225
|
}
|
|
11021
11226
|
|
|
11022
11227
|
// src/routes/admin-content-field-types.ts
|
|
@@ -11171,7 +11376,7 @@ function extractFieldData(fields, formData, options = {}) {
|
|
|
11171
11376
|
}
|
|
11172
11377
|
return { data, errors };
|
|
11173
11378
|
}
|
|
11174
|
-
adminContentRoutes.use("*",
|
|
11379
|
+
adminContentRoutes.use("*", chunkFCLKX2OS_cjs.requireAuth());
|
|
11175
11380
|
async function getCollectionFields(db, collectionId) {
|
|
11176
11381
|
console.log(`[getCollectionFields] Loading fields for collection: ${collectionId}`);
|
|
11177
11382
|
const collectionStmt = db.prepare("SELECT schema, queryable_fields FROM document_types WHERE id = ?");
|
|
@@ -11198,7 +11403,7 @@ async function getCollectionFields(db, collectionId) {
|
|
|
11198
11403
|
};
|
|
11199
11404
|
});
|
|
11200
11405
|
}
|
|
11201
|
-
const codeCollections2 = await
|
|
11406
|
+
const codeCollections2 = await chunkKVBHB7QP_cjs.loadCollectionConfigs();
|
|
11202
11407
|
const codeMatch = codeCollections2.find((c) => c.name === collectionId);
|
|
11203
11408
|
if (codeMatch && codeMatch.schema?.properties) {
|
|
11204
11409
|
console.log(`[getCollectionFields] DB doc type has no properties \u2014 using code collection schema`);
|
|
@@ -11230,7 +11435,7 @@ async function getCollectionFields(db, collectionId) {
|
|
|
11230
11435
|
}
|
|
11231
11436
|
}
|
|
11232
11437
|
console.log(`[getCollectionFields] Not in database, checking code collections`);
|
|
11233
|
-
const codeCollections = await
|
|
11438
|
+
const codeCollections = await chunkKVBHB7QP_cjs.loadCollectionConfigs();
|
|
11234
11439
|
console.log(`[getCollectionFields] Found ${codeCollections.length} code collections`);
|
|
11235
11440
|
const codeCollection = codeCollections.find((c) => c.name === collectionId);
|
|
11236
11441
|
if (codeCollection && codeCollection.schema) {
|
|
@@ -11266,7 +11471,7 @@ async function getCollectionFields(db, collectionId) {
|
|
|
11266
11471
|
}
|
|
11267
11472
|
async function getCollection(db, collectionId) {
|
|
11268
11473
|
console.log(`[getCollection] Loading collection by ID: ${collectionId}`);
|
|
11269
|
-
const cache =
|
|
11474
|
+
const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.collection);
|
|
11270
11475
|
return cache.getOrSet(
|
|
11271
11476
|
cache.generateKey("collection", collectionId),
|
|
11272
11477
|
async () => {
|
|
@@ -11284,7 +11489,7 @@ async function getCollection(db, collectionId) {
|
|
|
11284
11489
|
};
|
|
11285
11490
|
}
|
|
11286
11491
|
console.log(`[getCollection] Not in database, checking code collections`);
|
|
11287
|
-
const codeCollections = await
|
|
11492
|
+
const codeCollections = await chunkKVBHB7QP_cjs.loadCollectionConfigs();
|
|
11288
11493
|
const codeCollection = codeCollections.find((c) => c.name === collectionId);
|
|
11289
11494
|
if (codeCollection) {
|
|
11290
11495
|
console.log(`[getCollection] Found code collection: ${collectionId}`);
|
|
@@ -11303,7 +11508,7 @@ async function getCollection(db, collectionId) {
|
|
|
11303
11508
|
}
|
|
11304
11509
|
async function getDocBackingType(db, collectionName) {
|
|
11305
11510
|
if (!collectionName) return null;
|
|
11306
|
-
const dt = await new
|
|
11511
|
+
const dt = await new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db).findById(collectionName);
|
|
11307
11512
|
return dt && dt.isActive ? dt : null;
|
|
11308
11513
|
}
|
|
11309
11514
|
async function getCollectionByName(db, name) {
|
|
@@ -11320,7 +11525,7 @@ async function getCollectionByName(db, name) {
|
|
|
11320
11525
|
};
|
|
11321
11526
|
}
|
|
11322
11527
|
console.log(`[getCollectionByName] Not in database, checking code collections`);
|
|
11323
|
-
const codeCollections = await
|
|
11528
|
+
const codeCollections = await chunkKVBHB7QP_cjs.loadCollectionConfigs();
|
|
11324
11529
|
const codeCollection = codeCollections.find((c) => c.name === name);
|
|
11325
11530
|
if (codeCollection) {
|
|
11326
11531
|
console.log(`[getCollectionByName] Found code collection: ${name}`);
|
|
@@ -11336,7 +11541,7 @@ async function getCollectionByName(db, name) {
|
|
|
11336
11541
|
return null;
|
|
11337
11542
|
}
|
|
11338
11543
|
async function loadContentEditorFlags(db) {
|
|
11339
|
-
const flags = { workflowEnabled: await
|
|
11544
|
+
const flags = { workflowEnabled: await chunkFCLKX2OS_cjs.isPluginActive(db, "workflow") };
|
|
11340
11545
|
const editors = [
|
|
11341
11546
|
["tinymce-plugin", "tinymce"],
|
|
11342
11547
|
["quill-editor", "quill"],
|
|
@@ -11344,10 +11549,10 @@ async function loadContentEditorFlags(db) {
|
|
|
11344
11549
|
["lexical-editor", "lexical"]
|
|
11345
11550
|
];
|
|
11346
11551
|
for (const [plugin, key] of editors) {
|
|
11347
|
-
const enabled = await
|
|
11552
|
+
const enabled = await chunkFCLKX2OS_cjs.isPluginActive(db, plugin);
|
|
11348
11553
|
flags[`${key}Enabled`] = enabled;
|
|
11349
11554
|
if (enabled) {
|
|
11350
|
-
const ps = new
|
|
11555
|
+
const ps = new chunkKVBHB7QP_cjs.PluginService(db);
|
|
11351
11556
|
const p = await ps.getPlugin(plugin);
|
|
11352
11557
|
flags[`${key}Settings`] = p?.settings;
|
|
11353
11558
|
}
|
|
@@ -11355,7 +11560,7 @@ async function loadContentEditorFlags(db) {
|
|
|
11355
11560
|
return flags;
|
|
11356
11561
|
}
|
|
11357
11562
|
function makeDocService(db, docType, tenantId) {
|
|
11358
|
-
return new
|
|
11563
|
+
return new chunkLTZ5WYOK_cjs.DocumentsService(db, {
|
|
11359
11564
|
queryableFields: docType.queryableFields ?? [],
|
|
11360
11565
|
typeSchemaVersion: docType.schemaVersion ?? 1,
|
|
11361
11566
|
maxVersionsPerRoot: docType.settings?.maxVersionsPerRoot ?? 50,
|
|
@@ -11383,9 +11588,9 @@ adminContentRoutes.get("/", async (c) => {
|
|
|
11383
11588
|
const offset = (page - 1) * limit;
|
|
11384
11589
|
const collectionsStmt = db.prepare("SELECT id, name, display_name FROM document_types WHERE is_active = 1 ORDER BY display_name");
|
|
11385
11590
|
const { results: collectionsResults } = await collectionsStmt.all();
|
|
11386
|
-
const codeCollections = await
|
|
11591
|
+
const codeCollections = await chunkKVBHB7QP_cjs.loadCollectionConfigs();
|
|
11387
11592
|
const codeCollectionMap = new Map(codeCollections.map((c2) => [c2.name, c2]));
|
|
11388
|
-
const docTypeRegistry = new
|
|
11593
|
+
const docTypeRegistry = new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db);
|
|
11389
11594
|
const docTypes = (await docTypeRegistry.findAll()).filter((dt) => !dt.settings?.internal && !dt.isAuth);
|
|
11390
11595
|
const visibleTypeIds = new Set(docTypes.map((dt) => dt.id));
|
|
11391
11596
|
const allCollections = [
|
|
@@ -11397,7 +11602,7 @@ adminContentRoutes.get("/", async (c) => {
|
|
|
11397
11602
|
...allCollections.map((c2) => ({ name: c2.name, displayName: c2.displayName })),
|
|
11398
11603
|
...docTypes.filter((dt) => !collectionNames.has(dt.id)).map((dt) => ({ name: `doc:${dt.id}`, displayName: dt.displayName }))
|
|
11399
11604
|
];
|
|
11400
|
-
const newContentCollections = await
|
|
11605
|
+
const newContentCollections = await chunkKVBHB7QP_cjs.getVisibleCollections(db);
|
|
11401
11606
|
const docBackedCollection = !modelName.startsWith("doc:") && modelName !== "all" ? docTypes.find((dt) => dt.id === modelName) : void 0;
|
|
11402
11607
|
const isDocModel = modelName.startsWith("doc:") || !!docBackedCollection;
|
|
11403
11608
|
if (isDocModel) {
|
|
@@ -11674,9 +11879,9 @@ adminContentRoutes.get("/new", async (c) => {
|
|
|
11674
11879
|
const collectionsStmt = db2.prepare("SELECT id, name, display_name, description FROM document_types WHERE is_active = 1 ORDER BY display_name");
|
|
11675
11880
|
const { results } = await collectionsStmt.all();
|
|
11676
11881
|
const visibleTypeIds = new Set(
|
|
11677
|
-
(await new
|
|
11882
|
+
(await new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db2).findAll()).filter((dt) => !dt.settings?.internal && !dt.isAuth).map((dt) => dt.id)
|
|
11678
11883
|
);
|
|
11679
|
-
const codeCollections = await
|
|
11884
|
+
const codeCollections = await chunkKVBHB7QP_cjs.loadCollectionConfigs();
|
|
11680
11885
|
const dbCollectionNames = new Set((results || []).map((r) => r.name));
|
|
11681
11886
|
const allCollections = [
|
|
11682
11887
|
...codeCollections.filter((c2) => !dbCollectionNames.has(c2.name)).map((c2) => ({
|
|
@@ -11742,32 +11947,32 @@ adminContentRoutes.get("/new", async (c) => {
|
|
|
11742
11947
|
return c.html(renderContentFormPage(formData2));
|
|
11743
11948
|
}
|
|
11744
11949
|
const fields = await getCollectionFields(db, collection.id);
|
|
11745
|
-
const workflowEnabled = await
|
|
11746
|
-
const tinymceEnabled = await
|
|
11950
|
+
const workflowEnabled = await chunkFCLKX2OS_cjs.isPluginActive(db, "workflow");
|
|
11951
|
+
const tinymceEnabled = await chunkFCLKX2OS_cjs.isPluginActive(db, "tinymce-plugin");
|
|
11747
11952
|
let tinymceSettings;
|
|
11748
11953
|
if (tinymceEnabled) {
|
|
11749
|
-
const pluginService = new
|
|
11954
|
+
const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
|
|
11750
11955
|
const tinymcePlugin2 = await pluginService.getPlugin("tinymce-plugin");
|
|
11751
11956
|
tinymceSettings = tinymcePlugin2?.settings;
|
|
11752
11957
|
}
|
|
11753
|
-
const quillEnabled = await
|
|
11958
|
+
const quillEnabled = await chunkFCLKX2OS_cjs.isPluginActive(db, "quill-editor");
|
|
11754
11959
|
let quillSettings;
|
|
11755
11960
|
if (quillEnabled) {
|
|
11756
|
-
const pluginService = new
|
|
11961
|
+
const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
|
|
11757
11962
|
const quillPlugin = await pluginService.getPlugin("quill-editor");
|
|
11758
11963
|
quillSettings = quillPlugin?.settings;
|
|
11759
11964
|
}
|
|
11760
|
-
const mdxeditorEnabled = await
|
|
11965
|
+
const mdxeditorEnabled = await chunkFCLKX2OS_cjs.isPluginActive(db, "easy-mdx");
|
|
11761
11966
|
let mdxeditorSettings;
|
|
11762
11967
|
if (mdxeditorEnabled) {
|
|
11763
|
-
const pluginService = new
|
|
11968
|
+
const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
|
|
11764
11969
|
const mdxeditorPlugin = await pluginService.getPlugin("easy-mdx");
|
|
11765
11970
|
mdxeditorSettings = mdxeditorPlugin?.settings;
|
|
11766
11971
|
}
|
|
11767
|
-
const lexicalEnabled = await
|
|
11972
|
+
const lexicalEnabled = await chunkFCLKX2OS_cjs.isPluginActive(db, "lexical-editor");
|
|
11768
11973
|
let lexicalSettings;
|
|
11769
11974
|
if (lexicalEnabled) {
|
|
11770
|
-
const pluginService = new
|
|
11975
|
+
const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
|
|
11771
11976
|
const lexicalPlugin = await pluginService.getPlugin("lexical-editor");
|
|
11772
11977
|
lexicalSettings = lexicalPlugin?.settings;
|
|
11773
11978
|
}
|
|
@@ -11858,7 +12063,7 @@ adminContentRoutes.get("/:id/edit", async (c) => {
|
|
|
11858
12063
|
} : void 0
|
|
11859
12064
|
};
|
|
11860
12065
|
return c.html(renderContentFormPage(notFoundData));
|
|
11861
|
-
const cache =
|
|
12066
|
+
const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.content);
|
|
11862
12067
|
const content = await cache.getOrSet(
|
|
11863
12068
|
cache.generateKey("content", id),
|
|
11864
12069
|
async () => {
|
|
@@ -11895,32 +12100,32 @@ adminContentRoutes.get("/:id/edit", async (c) => {
|
|
|
11895
12100
|
};
|
|
11896
12101
|
const fields = await getCollectionFields(db, content.collection_id);
|
|
11897
12102
|
const contentData = content.data ? JSON.parse(content.data) : {};
|
|
11898
|
-
const workflowEnabled = await
|
|
11899
|
-
const tinymceEnabled = await
|
|
12103
|
+
const workflowEnabled = await chunkFCLKX2OS_cjs.isPluginActive(db, "workflow");
|
|
12104
|
+
const tinymceEnabled = await chunkFCLKX2OS_cjs.isPluginActive(db, "tinymce-plugin");
|
|
11900
12105
|
let tinymceSettings;
|
|
11901
12106
|
if (tinymceEnabled) {
|
|
11902
|
-
const pluginService = new
|
|
12107
|
+
const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
|
|
11903
12108
|
const tinymcePlugin2 = await pluginService.getPlugin("tinymce-plugin");
|
|
11904
12109
|
tinymceSettings = tinymcePlugin2?.settings;
|
|
11905
12110
|
}
|
|
11906
|
-
const quillEnabled = await
|
|
12111
|
+
const quillEnabled = await chunkFCLKX2OS_cjs.isPluginActive(db, "quill-editor");
|
|
11907
12112
|
let quillSettings;
|
|
11908
12113
|
if (quillEnabled) {
|
|
11909
|
-
const pluginService = new
|
|
12114
|
+
const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
|
|
11910
12115
|
const quillPlugin = await pluginService.getPlugin("quill-editor");
|
|
11911
12116
|
quillSettings = quillPlugin?.settings;
|
|
11912
12117
|
}
|
|
11913
|
-
const mdxeditorEnabled = await
|
|
12118
|
+
const mdxeditorEnabled = await chunkFCLKX2OS_cjs.isPluginActive(db, "easy-mdx");
|
|
11914
12119
|
let mdxeditorSettings;
|
|
11915
12120
|
if (mdxeditorEnabled) {
|
|
11916
|
-
const pluginService = new
|
|
12121
|
+
const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
|
|
11917
12122
|
const mdxeditorPlugin = await pluginService.getPlugin("easy-mdx");
|
|
11918
12123
|
mdxeditorSettings = mdxeditorPlugin?.settings;
|
|
11919
12124
|
}
|
|
11920
|
-
const lexicalEnabled = await
|
|
12125
|
+
const lexicalEnabled = await chunkFCLKX2OS_cjs.isPluginActive(db, "lexical-editor");
|
|
11921
12126
|
let lexicalSettings;
|
|
11922
12127
|
if (lexicalEnabled) {
|
|
11923
|
-
const pluginService = new
|
|
12128
|
+
const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
|
|
11924
12129
|
const lexicalPlugin = await pluginService.getPlugin("lexical-editor");
|
|
11925
12130
|
lexicalSettings = lexicalPlugin?.settings;
|
|
11926
12131
|
}
|
|
@@ -12041,7 +12246,7 @@ adminContentRoutes.post("/", async (c) => {
|
|
|
12041
12246
|
data,
|
|
12042
12247
|
publishOnCreate: status === "published"
|
|
12043
12248
|
}), user?.userId);
|
|
12044
|
-
const cache2 =
|
|
12249
|
+
const cache2 = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.content);
|
|
12045
12250
|
await cache2.invalidate(`content:list:${collectionId}:*`);
|
|
12046
12251
|
const redirectUrl2 = `/admin/content/${doc.rootId}/edit?success=Content created successfully!`;
|
|
12047
12252
|
return c.req.header("HX-Request") === "true" ? c.text("", 200, { "HX-Redirect": redirectUrl2 }) : c.redirect(redirectUrl2);
|
|
@@ -12071,7 +12276,7 @@ adminContentRoutes.post("/", async (c) => {
|
|
|
12071
12276
|
now,
|
|
12072
12277
|
now
|
|
12073
12278
|
).run();
|
|
12074
|
-
const cache =
|
|
12279
|
+
const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.content);
|
|
12075
12280
|
await cache.invalidate(`content:list:${collectionId}:*`);
|
|
12076
12281
|
const versionStmt = db.prepare(`
|
|
12077
12282
|
INSERT INTO content_versions (id, content_id, version, data, author_id, created_at)
|
|
@@ -12160,7 +12365,7 @@ adminContentRoutes.put("/:id", async (c) => {
|
|
|
12160
12365
|
const pub = await db.prepare("SELECT id FROM documents WHERE root_id = ? AND is_published = 1 AND tenant_id = ?").bind(id, tenantId).first();
|
|
12161
12366
|
if (status2 === "published") await svc.publish(newDraft.id, user?.userId);
|
|
12162
12367
|
else if (pub) await svc.unpublish(pub.id);
|
|
12163
|
-
await
|
|
12368
|
+
await chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.content).invalidate(`content:list:*`);
|
|
12164
12369
|
const redirectUrl2 = `/admin/content/${id}/edit?success=Content updated successfully!`;
|
|
12165
12370
|
return c.req.header("HX-Request") === "true" ? c.text("", 200, { "HX-Redirect": redirectUrl2 }) : c.redirect(redirectUrl2);
|
|
12166
12371
|
}
|
|
@@ -12241,7 +12446,7 @@ adminContentRoutes.put("/:id", async (c) => {
|
|
|
12241
12446
|
now,
|
|
12242
12447
|
id
|
|
12243
12448
|
).run();
|
|
12244
|
-
const cache =
|
|
12449
|
+
const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.content);
|
|
12245
12450
|
await cache.delete(cache.generateKey("content", id));
|
|
12246
12451
|
await cache.invalidate(`content:list:${existingContent.collection_id}:*`);
|
|
12247
12452
|
const existingData = JSON.parse(existingContent.data || "{}");
|
|
@@ -12293,7 +12498,7 @@ adminContentRoutes.put("/:id", async (c) => {
|
|
|
12293
12498
|
`);
|
|
12294
12499
|
}
|
|
12295
12500
|
});
|
|
12296
|
-
adminContentRoutes.post("/preview",
|
|
12501
|
+
adminContentRoutes.post("/preview", chunkFCLKX2OS_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
12297
12502
|
try {
|
|
12298
12503
|
const formData = await c.req.formData();
|
|
12299
12504
|
const collectionId = formData.get("collection_id");
|
|
@@ -12548,12 +12753,12 @@ adminContentRoutes.post("/bulk-action", async (c) => {
|
|
|
12548
12753
|
}
|
|
12549
12754
|
}
|
|
12550
12755
|
}
|
|
12551
|
-
const cache =
|
|
12756
|
+
const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.content);
|
|
12552
12757
|
for (const contentId of ids) {
|
|
12553
12758
|
await cache.delete(cache.generateKey("content", contentId));
|
|
12554
12759
|
}
|
|
12555
12760
|
await cache.invalidate("content:list:*");
|
|
12556
|
-
const apiCache =
|
|
12761
|
+
const apiCache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
|
|
12557
12762
|
await apiCache.invalidate("content-filtered:*");
|
|
12558
12763
|
await apiCache.invalidate("collection-content-filtered:*");
|
|
12559
12764
|
return c.json({ success: true, count: ids.length });
|
|
@@ -12572,7 +12777,7 @@ adminContentRoutes.delete("/:id", async (c) => {
|
|
|
12572
12777
|
if (docDel && await getDocBackingType(db, docDel.type_id)) {
|
|
12573
12778
|
const now2 = Math.floor(Date.now() / 1e3);
|
|
12574
12779
|
await db.prepare("UPDATE documents SET deleted_at = ?, updated_at = ? WHERE root_id = ? AND tenant_id = ?").bind(now2, now2, id, tenantId).run();
|
|
12575
|
-
await
|
|
12780
|
+
await chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.content).invalidate("content:list:*");
|
|
12576
12781
|
return c.html(`
|
|
12577
12782
|
<div id="content-list" hx-get="/admin/content?model=${docDel.type_id}" hx-trigger="load" hx-swap="outerHTML">
|
|
12578
12783
|
<div class="flex items-center justify-center p-8"><span class="text-zinc-500">Deleting\u2026</span></div>
|
|
@@ -12592,7 +12797,7 @@ adminContentRoutes.delete("/:id", async (c) => {
|
|
|
12592
12797
|
WHERE id = ?
|
|
12593
12798
|
`);
|
|
12594
12799
|
await deleteStmt.bind(now, id).run();
|
|
12595
|
-
const cache =
|
|
12800
|
+
const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.content);
|
|
12596
12801
|
await cache.delete(cache.generateKey("content", id));
|
|
12597
12802
|
await cache.invalidate("content:list:*");
|
|
12598
12803
|
return c.html(`
|
|
@@ -12612,7 +12817,7 @@ adminContentRoutes.delete("/:id", async (c) => {
|
|
|
12612
12817
|
return c.json({ success: false, error: "Failed to delete content" }, 500);
|
|
12613
12818
|
}
|
|
12614
12819
|
});
|
|
12615
|
-
adminContentRoutes.get("/:id/version/:version/preview",
|
|
12820
|
+
adminContentRoutes.get("/:id/version/:version/preview", chunkFCLKX2OS_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
12616
12821
|
try {
|
|
12617
12822
|
const id = c.req.param("id");
|
|
12618
12823
|
const version = parseInt(c.req.param("version") || "0");
|
|
@@ -12708,9 +12913,9 @@ function parseDocFormData(formData, queryableFields = []) {
|
|
|
12708
12913
|
return { title, slug, data };
|
|
12709
12914
|
}
|
|
12710
12915
|
async function getDocService(db, typeId, tenantId) {
|
|
12711
|
-
const registry = new
|
|
12916
|
+
const registry = new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db);
|
|
12712
12917
|
const docType = await registry.findById(typeId);
|
|
12713
|
-
const svc = new
|
|
12918
|
+
const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, {
|
|
12714
12919
|
queryableFields: docType?.queryableFields ?? [],
|
|
12715
12920
|
typeSchemaVersion: docType?.schemaVersion ?? 1,
|
|
12716
12921
|
maxVersionsPerRoot: docType?.settings?.maxVersionsPerRoot ?? 50,
|
|
@@ -12721,10 +12926,10 @@ async function getDocService(db, typeId, tenantId) {
|
|
|
12721
12926
|
}
|
|
12722
12927
|
adminContentRoutes.get("/documents/:typeId/new", async (c) => {
|
|
12723
12928
|
const { typeId } = c.req.param();
|
|
12724
|
-
const registry = new
|
|
12929
|
+
const registry = new chunkFCLKX2OS_cjs.DocumentTypeRegistry(c.env.DB);
|
|
12725
12930
|
const docType = await registry.findById(typeId);
|
|
12726
12931
|
if (!docType) return c.html("<p>Unknown document type.</p>", 404);
|
|
12727
|
-
return c.html(
|
|
12932
|
+
return c.html(chunkN32OWET6_cjs.renderDocumentFormPage({ docType, isEdit: false, user: userCtx(c) }));
|
|
12728
12933
|
});
|
|
12729
12934
|
adminContentRoutes.post("/documents/:typeId/new", async (c) => {
|
|
12730
12935
|
const { typeId } = c.req.param();
|
|
@@ -12746,17 +12951,17 @@ adminContentRoutes.post("/documents/:typeId/new", async (c) => {
|
|
|
12746
12951
|
}), user?.userId);
|
|
12747
12952
|
return c.redirect(`/admin/content/documents/${typeId}/${doc.rootId}/edit?message=Created+successfully`);
|
|
12748
12953
|
} catch (err) {
|
|
12749
|
-
const registry = new
|
|
12954
|
+
const registry = new chunkFCLKX2OS_cjs.DocumentTypeRegistry(c.env.DB);
|
|
12750
12955
|
const docType = await registry.findById(typeId);
|
|
12751
12956
|
if (!docType) return c.html("<p>Unknown document type.</p>", 404);
|
|
12752
|
-
return c.html(
|
|
12957
|
+
return c.html(chunkN32OWET6_cjs.renderDocumentFormPage({ docType, isEdit: false, user: userCtx(c), message: err?.message ?? "Failed to create", messageType: "error" }));
|
|
12753
12958
|
}
|
|
12754
12959
|
});
|
|
12755
12960
|
adminContentRoutes.get("/documents/:typeId/:rootId/edit", async (c) => {
|
|
12756
12961
|
const { typeId, rootId } = c.req.param();
|
|
12757
12962
|
const db = c.env.DB;
|
|
12758
12963
|
const message = c.req.query("message");
|
|
12759
|
-
const registry = new
|
|
12964
|
+
const registry = new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db);
|
|
12760
12965
|
const docType = await registry.findById(typeId);
|
|
12761
12966
|
if (!docType) return c.html("<p>Unknown document type.</p>", 404);
|
|
12762
12967
|
const tenantId = reqTenant(c);
|
|
@@ -12803,7 +13008,7 @@ adminContentRoutes.get("/documents/:typeId/:rootId/edit", async (c) => {
|
|
|
12803
13008
|
createdAt: draftRow.created_at,
|
|
12804
13009
|
updatedAt: draftRow.updated_at
|
|
12805
13010
|
};
|
|
12806
|
-
return c.html(
|
|
13011
|
+
return c.html(chunkN32OWET6_cjs.renderDocumentFormPage({ docType, doc, publishedDoc, isEdit: true, message, user: userCtx(c), versioningEnabled: docType?.settings?.versioning === true }));
|
|
12807
13012
|
});
|
|
12808
13013
|
adminContentRoutes.post("/documents/:typeId/:rootId", async (c) => {
|
|
12809
13014
|
const { typeId, rootId } = c.req.param();
|
|
@@ -12868,8 +13073,8 @@ adminContentRoutes.post("/documents/:typeId/:documentId/delete", async (c) => {
|
|
|
12868
13073
|
adminContentRoutes.get("/documents/:typeId/:rootId/versions", async (c) => {
|
|
12869
13074
|
const { typeId, rootId } = c.req.param();
|
|
12870
13075
|
const db = c.env.DB;
|
|
12871
|
-
const { renderVersionHistoryFragment } = await import('./admin-documents-form.template-
|
|
12872
|
-
const registry = new
|
|
13076
|
+
const { renderVersionHistoryFragment } = await import('./admin-documents-form.template-LSZKGA5J.cjs');
|
|
13077
|
+
const registry = new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db);
|
|
12873
13078
|
const docType = await registry.findById(typeId);
|
|
12874
13079
|
if (!docType) return c.html("<div>Unknown type.</div>", 404);
|
|
12875
13080
|
const result = await db.prepare(
|
|
@@ -12889,7 +13094,7 @@ adminContentRoutes.get("/documents/:typeId/:rootId/versions", async (c) => {
|
|
|
12889
13094
|
var admin_content_default = adminContentRoutes;
|
|
12890
13095
|
|
|
12891
13096
|
// src/templates/pages/admin-profile.template.ts
|
|
12892
|
-
|
|
13097
|
+
chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
|
|
12893
13098
|
function renderAvatarImage(avatarUrl, firstName, lastName) {
|
|
12894
13099
|
return `<div id="avatar-image-container" class="w-24 h-24 rounded-full mx-auto mb-4 overflow-hidden bg-gradient-to-br from-cyan-400 to-purple-400 flex items-center justify-center ring-4 ring-zinc-950/5 dark:ring-white/10">
|
|
12895
13100
|
${avatarUrl ? `<img src="${avatarUrl}" alt="Profile picture" class="w-full h-full object-cover">` : `<span class="text-2xl font-bold text-white">${firstName.charAt(0)}${lastName.charAt(0)}</span>`}
|
|
@@ -12909,8 +13114,8 @@ function renderProfilePage(data) {
|
|
|
12909
13114
|
</div>
|
|
12910
13115
|
|
|
12911
13116
|
<!-- Alert Messages -->
|
|
12912
|
-
${data.error ?
|
|
12913
|
-
${data.success ?
|
|
13117
|
+
${data.error ? chunkPXNTCCPE_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
|
|
13118
|
+
${data.success ? chunkPXNTCCPE_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
|
|
12914
13119
|
|
|
12915
13120
|
<!-- Profile Form -->
|
|
12916
13121
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
|
@@ -13287,7 +13492,7 @@ function renderProfilePage(data) {
|
|
|
13287
13492
|
version: data.version,
|
|
13288
13493
|
content: pageContent
|
|
13289
13494
|
};
|
|
13290
|
-
return
|
|
13495
|
+
return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
13291
13496
|
}
|
|
13292
13497
|
|
|
13293
13498
|
// src/templates/pages/admin-activity-logs.template.ts
|
|
@@ -13497,7 +13702,7 @@ function renderActivityLogsPage(data) {
|
|
|
13497
13702
|
user: data.user,
|
|
13498
13703
|
content: pageContent
|
|
13499
13704
|
};
|
|
13500
|
-
return
|
|
13705
|
+
return chunkPXNTCCPE_cjs.renderAdminLayout(layoutData);
|
|
13501
13706
|
}
|
|
13502
13707
|
function getActionBadgeClass(action) {
|
|
13503
13708
|
if (action.includes("login") || action.includes("logout")) {
|
|
@@ -13517,7 +13722,7 @@ function formatAction(action) {
|
|
|
13517
13722
|
}
|
|
13518
13723
|
|
|
13519
13724
|
// src/templates/pages/admin-user-edit.template.ts
|
|
13520
|
-
|
|
13725
|
+
chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
|
|
13521
13726
|
|
|
13522
13727
|
// src/templates/components/confirmation-dialog.template.ts
|
|
13523
13728
|
function renderConfirmationDialog2(options) {
|
|
@@ -13713,8 +13918,8 @@ function renderUserEditPage(data) {
|
|
|
13713
13918
|
|
|
13714
13919
|
<!-- Alert Messages -->
|
|
13715
13920
|
<div id="form-messages" class="mb-6 empty:mb-0">
|
|
13716
|
-
${data.error ?
|
|
13717
|
-
${data.success ?
|
|
13921
|
+
${data.error ? chunkPXNTCCPE_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
|
|
13922
|
+
${data.success ? chunkPXNTCCPE_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
|
|
13718
13923
|
</div>
|
|
13719
13924
|
|
|
13720
13925
|
<!-- User Edit Form -->
|
|
@@ -14036,11 +14241,11 @@ function renderUserEditPage(data) {
|
|
|
14036
14241
|
user: data.user,
|
|
14037
14242
|
content: pageContent
|
|
14038
14243
|
};
|
|
14039
|
-
return
|
|
14244
|
+
return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
14040
14245
|
}
|
|
14041
14246
|
|
|
14042
14247
|
// src/templates/pages/admin-user-new.template.ts
|
|
14043
|
-
|
|
14248
|
+
chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
|
|
14044
14249
|
function renderUserNewPage(data) {
|
|
14045
14250
|
const pageContent = `
|
|
14046
14251
|
<div>
|
|
@@ -14079,8 +14284,8 @@ function renderUserNewPage(data) {
|
|
|
14079
14284
|
|
|
14080
14285
|
<!-- Alert Messages -->
|
|
14081
14286
|
<div id="form-messages">
|
|
14082
|
-
${data.error ?
|
|
14083
|
-
${data.success ?
|
|
14287
|
+
${data.error ? chunkPXNTCCPE_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
|
|
14288
|
+
${data.success ? chunkPXNTCCPE_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
|
|
14084
14289
|
</div>
|
|
14085
14290
|
|
|
14086
14291
|
<!-- User New Form -->
|
|
@@ -14310,11 +14515,11 @@ function renderUserNewPage(data) {
|
|
|
14310
14515
|
user: data.user,
|
|
14311
14516
|
content: pageContent
|
|
14312
14517
|
};
|
|
14313
|
-
return
|
|
14518
|
+
return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
14314
14519
|
}
|
|
14315
14520
|
|
|
14316
14521
|
// src/templates/pages/admin-users-list.template.ts
|
|
14317
|
-
|
|
14522
|
+
chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
|
|
14318
14523
|
function renderUsersListPage(data) {
|
|
14319
14524
|
const columns = [
|
|
14320
14525
|
{
|
|
@@ -14470,8 +14675,8 @@ function renderUsersListPage(data) {
|
|
|
14470
14675
|
</div>
|
|
14471
14676
|
|
|
14472
14677
|
<!-- Alert Messages -->
|
|
14473
|
-
${data.error ?
|
|
14474
|
-
${data.success ?
|
|
14678
|
+
${data.error ? chunkPXNTCCPE_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
|
|
14679
|
+
${data.success ? chunkPXNTCCPE_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
|
|
14475
14680
|
|
|
14476
14681
|
<!-- Stats -->
|
|
14477
14682
|
<div class="mb-6">
|
|
@@ -14648,10 +14853,10 @@ function renderUsersListPage(data) {
|
|
|
14648
14853
|
</div>
|
|
14649
14854
|
|
|
14650
14855
|
<!-- Users Table -->
|
|
14651
|
-
${
|
|
14856
|
+
${chunkPXNTCCPE_cjs.renderTable(tableData)}
|
|
14652
14857
|
|
|
14653
14858
|
<!-- Pagination -->
|
|
14654
|
-
${data.pagination ?
|
|
14859
|
+
${data.pagination ? chunkPXNTCCPE_cjs.renderPagination(data.pagination) : ""}
|
|
14655
14860
|
</div>
|
|
14656
14861
|
|
|
14657
14862
|
<script>
|
|
@@ -14722,7 +14927,7 @@ function renderUsersListPage(data) {
|
|
|
14722
14927
|
version: data.version,
|
|
14723
14928
|
content: pageContent
|
|
14724
14929
|
};
|
|
14725
|
-
return
|
|
14930
|
+
return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
14726
14931
|
}
|
|
14727
14932
|
|
|
14728
14933
|
// src/plugins/core-plugins/multi-tenant-plugin/services/tenant-service.ts
|
|
@@ -14741,6 +14946,7 @@ var TenantService = class {
|
|
|
14741
14946
|
constructor(db) {
|
|
14742
14947
|
this.db = db;
|
|
14743
14948
|
}
|
|
14949
|
+
db;
|
|
14744
14950
|
async listTenants() {
|
|
14745
14951
|
const { results } = await this.db.prepare(`
|
|
14746
14952
|
SELECT * FROM auth_tenant
|
|
@@ -14801,7 +15007,7 @@ var TenantService = class {
|
|
|
14801
15007
|
SET name = ?, domain = ?, status = ?, notes = ?, updated_at = ?
|
|
14802
15008
|
WHERE slug = ?
|
|
14803
15009
|
`).bind(name, domain, status, notes, now, slug).run();
|
|
14804
|
-
|
|
15010
|
+
chunkKVBHB7QP_cjs.invalidateTenantCache();
|
|
14805
15011
|
const updated = await this.getTenantBySlug(slug);
|
|
14806
15012
|
if (!updated) throw new Error("Tenant not found");
|
|
14807
15013
|
return updated;
|
|
@@ -14819,7 +15025,7 @@ var TenantService = class {
|
|
|
14819
15025
|
throw new Error(`Tenant '${slug}' still owns ${docCount} document(s). Delete or migrate its content first.`);
|
|
14820
15026
|
}
|
|
14821
15027
|
await this.db.prepare(`DELETE FROM auth_tenant WHERE slug = ?`).bind(slug).run();
|
|
14822
|
-
|
|
15028
|
+
chunkKVBHB7QP_cjs.invalidateTenantCache();
|
|
14823
15029
|
}
|
|
14824
15030
|
// ─── Membership (auth_tenant_member) ───────────────────────────────────────
|
|
14825
15031
|
// Tenant resolution and the admin switcher are gated on membership: an authed user may only
|
|
@@ -15063,7 +15269,7 @@ var TenantService = class {
|
|
|
15063
15269
|
INSERT INTO auth_tenant (id, name, slug, status, domain, notes, metadata, created_at, updated_at)
|
|
15064
15270
|
VALUES (?, ?, ?, 'active', ?, ?, '{}', ?, ?)
|
|
15065
15271
|
`).bind(id, input.name, input.slug, input.domain, input.notes, now, now).run();
|
|
15066
|
-
|
|
15272
|
+
chunkKVBHB7QP_cjs.invalidateTenantCache();
|
|
15067
15273
|
const created = await this.getTenantBySlug(input.slug);
|
|
15068
15274
|
if (!created) throw new Error("Failed to create tenant");
|
|
15069
15275
|
return created;
|
|
@@ -15087,14 +15293,14 @@ function mapRowToTenant(row) {
|
|
|
15087
15293
|
|
|
15088
15294
|
// src/routes/admin-users.ts
|
|
15089
15295
|
var userRoutes = new hono.Hono();
|
|
15090
|
-
userRoutes.use("*",
|
|
15091
|
-
userRoutes.use("/users/*",
|
|
15092
|
-
userRoutes.use("/users",
|
|
15093
|
-
userRoutes.use("/invite-user",
|
|
15094
|
-
userRoutes.use("/resend-invitation/*",
|
|
15095
|
-
userRoutes.use("/cancel-invitation/*",
|
|
15096
|
-
userRoutes.use("/activity-logs",
|
|
15097
|
-
userRoutes.use("/activity-logs/*",
|
|
15296
|
+
userRoutes.use("*", chunkFCLKX2OS_cjs.requireAuth());
|
|
15297
|
+
userRoutes.use("/users/*", chunkFCLKX2OS_cjs.requireRole(["admin"]));
|
|
15298
|
+
userRoutes.use("/users", chunkFCLKX2OS_cjs.requireRole(["admin"]));
|
|
15299
|
+
userRoutes.use("/invite-user", chunkFCLKX2OS_cjs.requireRole(["admin"]));
|
|
15300
|
+
userRoutes.use("/resend-invitation/*", chunkFCLKX2OS_cjs.requireRole(["admin"]));
|
|
15301
|
+
userRoutes.use("/cancel-invitation/*", chunkFCLKX2OS_cjs.requireRole(["admin"]));
|
|
15302
|
+
userRoutes.use("/activity-logs", chunkFCLKX2OS_cjs.requireRole(["admin"]));
|
|
15303
|
+
userRoutes.use("/activity-logs/*", chunkFCLKX2OS_cjs.requireRole(["admin"]));
|
|
15098
15304
|
userRoutes.get("/", (c) => {
|
|
15099
15305
|
return c.redirect("/admin/dashboard");
|
|
15100
15306
|
});
|
|
@@ -15205,7 +15411,7 @@ userRoutes.put("/profile", async (c) => {
|
|
|
15205
15411
|
const language = formData.get("language")?.toString() || "en";
|
|
15206
15412
|
const emailNotifications = formData.get("email_notifications") === "1";
|
|
15207
15413
|
if (!firstName || !lastName || !email) {
|
|
15208
|
-
return c.html(
|
|
15414
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15209
15415
|
type: "error",
|
|
15210
15416
|
message: "First name, last name, and email are required.",
|
|
15211
15417
|
dismissible: true
|
|
@@ -15213,7 +15419,7 @@ userRoutes.put("/profile", async (c) => {
|
|
|
15213
15419
|
}
|
|
15214
15420
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
15215
15421
|
if (!emailRegex.test(email)) {
|
|
15216
|
-
return c.html(
|
|
15422
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15217
15423
|
type: "error",
|
|
15218
15424
|
message: "Please enter a valid email address.",
|
|
15219
15425
|
dismissible: true
|
|
@@ -15225,7 +15431,7 @@ userRoutes.put("/profile", async (c) => {
|
|
|
15225
15431
|
`);
|
|
15226
15432
|
const existingUser = await checkStmt.bind(email, user.userId).first();
|
|
15227
15433
|
if (existingUser) {
|
|
15228
|
-
return c.html(
|
|
15434
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15229
15435
|
type: "error",
|
|
15230
15436
|
message: "Email is already taken by another user.",
|
|
15231
15437
|
dismissible: true
|
|
@@ -15257,11 +15463,11 @@ userRoutes.put("/profile", async (c) => {
|
|
|
15257
15463
|
const validation = validateCustomData(sanitized, profileConfig);
|
|
15258
15464
|
if (!validation.valid) {
|
|
15259
15465
|
const errorMessages = Object.values(validation.errors).join(", ");
|
|
15260
|
-
return c.html(
|
|
15466
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({ type: "error", message: errorMessages, dismissible: true }), 400);
|
|
15261
15467
|
}
|
|
15262
15468
|
await saveCustomData(db, user.userId, sanitized);
|
|
15263
15469
|
}
|
|
15264
|
-
await
|
|
15470
|
+
await chunkFCLKX2OS_cjs.logActivity(
|
|
15265
15471
|
db,
|
|
15266
15472
|
user.userId,
|
|
15267
15473
|
"profile.update",
|
|
@@ -15271,14 +15477,14 @@ userRoutes.put("/profile", async (c) => {
|
|
|
15271
15477
|
c.req.header("x-forwarded-for") || c.req.header("cf-connecting-ip"),
|
|
15272
15478
|
c.req.header("user-agent")
|
|
15273
15479
|
);
|
|
15274
|
-
return c.html(
|
|
15480
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15275
15481
|
type: "success",
|
|
15276
15482
|
message: "Profile updated successfully!",
|
|
15277
15483
|
dismissible: true
|
|
15278
15484
|
}));
|
|
15279
15485
|
} catch (error) {
|
|
15280
15486
|
console.error("Profile update error:", error);
|
|
15281
|
-
return c.html(
|
|
15487
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15282
15488
|
type: "error",
|
|
15283
15489
|
message: "Failed to update profile. Please try again.",
|
|
15284
15490
|
dismissible: true
|
|
@@ -15292,7 +15498,7 @@ userRoutes.post("/profile/avatar", async (c) => {
|
|
|
15292
15498
|
const formData = await c.req.formData();
|
|
15293
15499
|
const avatarFile = formData.get("avatar");
|
|
15294
15500
|
if (!avatarFile || typeof avatarFile === "string" || !avatarFile.name) {
|
|
15295
|
-
return c.html(
|
|
15501
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15296
15502
|
type: "error",
|
|
15297
15503
|
message: "Please select an image file.",
|
|
15298
15504
|
dismissible: true
|
|
@@ -15300,7 +15506,7 @@ userRoutes.post("/profile/avatar", async (c) => {
|
|
|
15300
15506
|
}
|
|
15301
15507
|
const allowedTypes = ["image/jpeg", "image/png", "image/gif", "image/webp"];
|
|
15302
15508
|
if (!allowedTypes.includes(avatarFile.type)) {
|
|
15303
|
-
return c.html(
|
|
15509
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15304
15510
|
type: "error",
|
|
15305
15511
|
message: "Please upload a valid image file (JPEG, PNG, GIF, or WebP).",
|
|
15306
15512
|
dismissible: true
|
|
@@ -15308,7 +15514,7 @@ userRoutes.post("/profile/avatar", async (c) => {
|
|
|
15308
15514
|
}
|
|
15309
15515
|
const maxSize = 5 * 1024 * 1024;
|
|
15310
15516
|
if (avatarFile.size > maxSize) {
|
|
15311
|
-
return c.html(
|
|
15517
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15312
15518
|
type: "error",
|
|
15313
15519
|
message: "Image file must be smaller than 5MB.",
|
|
15314
15520
|
dismissible: true
|
|
@@ -15324,7 +15530,7 @@ userRoutes.post("/profile/avatar", async (c) => {
|
|
|
15324
15530
|
SELECT first_name, last_name FROM auth_user WHERE id = ?
|
|
15325
15531
|
`);
|
|
15326
15532
|
const userData = await userStmt.bind(user.userId).first();
|
|
15327
|
-
await
|
|
15533
|
+
await chunkFCLKX2OS_cjs.logActivity(
|
|
15328
15534
|
db,
|
|
15329
15535
|
user.userId,
|
|
15330
15536
|
"profile.avatar_update",
|
|
@@ -15334,7 +15540,7 @@ userRoutes.post("/profile/avatar", async (c) => {
|
|
|
15334
15540
|
c.req.header("x-forwarded-for") || c.req.header("cf-connecting-ip"),
|
|
15335
15541
|
c.req.header("user-agent")
|
|
15336
15542
|
);
|
|
15337
|
-
const alertHtml =
|
|
15543
|
+
const alertHtml = chunkN32OWET6_cjs.renderAlert({
|
|
15338
15544
|
type: "success",
|
|
15339
15545
|
message: "Profile picture updated successfully!",
|
|
15340
15546
|
dismissible: true
|
|
@@ -15348,7 +15554,7 @@ userRoutes.post("/profile/avatar", async (c) => {
|
|
|
15348
15554
|
return c.html(alertHtml + avatarImageWithOob);
|
|
15349
15555
|
} catch (error) {
|
|
15350
15556
|
console.error("Avatar upload error:", error);
|
|
15351
|
-
return c.html(
|
|
15557
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15352
15558
|
type: "error",
|
|
15353
15559
|
message: "Failed to upload profile picture. Please try again.",
|
|
15354
15560
|
dismissible: true
|
|
@@ -15364,21 +15570,21 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
15364
15570
|
const newPassword = formData.get("new_password")?.toString() || "";
|
|
15365
15571
|
const confirmPassword = formData.get("confirm_password")?.toString() || "";
|
|
15366
15572
|
if (!currentPassword || !newPassword || !confirmPassword) {
|
|
15367
|
-
return c.html(
|
|
15573
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15368
15574
|
type: "error",
|
|
15369
15575
|
message: "All password fields are required.",
|
|
15370
15576
|
dismissible: true
|
|
15371
15577
|
}));
|
|
15372
15578
|
}
|
|
15373
15579
|
if (newPassword !== confirmPassword) {
|
|
15374
|
-
return c.html(
|
|
15580
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15375
15581
|
type: "error",
|
|
15376
15582
|
message: "New passwords do not match.",
|
|
15377
15583
|
dismissible: true
|
|
15378
15584
|
}));
|
|
15379
15585
|
}
|
|
15380
15586
|
if (newPassword.length < 8) {
|
|
15381
|
-
return c.html(
|
|
15587
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15382
15588
|
type: "error",
|
|
15383
15589
|
message: "New password must be at least 8 characters long.",
|
|
15384
15590
|
dismissible: true
|
|
@@ -15389,21 +15595,21 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
15389
15595
|
`);
|
|
15390
15596
|
const userData = await userStmt.bind(user.userId).first();
|
|
15391
15597
|
if (!userData) {
|
|
15392
|
-
return c.html(
|
|
15598
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15393
15599
|
type: "error",
|
|
15394
15600
|
message: "User not found.",
|
|
15395
15601
|
dismissible: true
|
|
15396
15602
|
}));
|
|
15397
15603
|
}
|
|
15398
|
-
const validPassword = await
|
|
15604
|
+
const validPassword = await chunkFCLKX2OS_cjs.AuthManager.verifyPassword(currentPassword, userData.password_hash);
|
|
15399
15605
|
if (!validPassword) {
|
|
15400
|
-
return c.html(
|
|
15606
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15401
15607
|
type: "error",
|
|
15402
15608
|
message: "Current password is incorrect.",
|
|
15403
15609
|
dismissible: true
|
|
15404
15610
|
}));
|
|
15405
15611
|
}
|
|
15406
|
-
const newPasswordHash = await
|
|
15612
|
+
const newPasswordHash = await chunkFCLKX2OS_cjs.AuthManager.hashPassword(newPassword);
|
|
15407
15613
|
const historyStmt = db.prepare(`
|
|
15408
15614
|
INSERT INTO auth_password_history (id, user_id, password_hash, created_at)
|
|
15409
15615
|
VALUES (?, ?, ?, ?)
|
|
@@ -15419,7 +15625,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
15419
15625
|
WHERE id = ?
|
|
15420
15626
|
`);
|
|
15421
15627
|
await updateStmt.bind(newPasswordHash, Date.now(), user.userId).run();
|
|
15422
|
-
await
|
|
15628
|
+
await chunkFCLKX2OS_cjs.logActivity(
|
|
15423
15629
|
db,
|
|
15424
15630
|
user.userId,
|
|
15425
15631
|
"profile.password_change",
|
|
@@ -15429,14 +15635,14 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
15429
15635
|
c.req.header("x-forwarded-for") || c.req.header("cf-connecting-ip"),
|
|
15430
15636
|
c.req.header("user-agent")
|
|
15431
15637
|
);
|
|
15432
|
-
return c.html(
|
|
15638
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15433
15639
|
type: "success",
|
|
15434
15640
|
message: "Password updated successfully!",
|
|
15435
15641
|
dismissible: true
|
|
15436
15642
|
}));
|
|
15437
15643
|
} catch (error) {
|
|
15438
15644
|
console.error("Password change error:", error);
|
|
15439
|
-
return c.html(
|
|
15645
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15440
15646
|
type: "error",
|
|
15441
15647
|
message: "Failed to update password. Please try again.",
|
|
15442
15648
|
dismissible: true
|
|
@@ -15486,7 +15692,7 @@ userRoutes.get("/users", async (c) => {
|
|
|
15486
15692
|
`);
|
|
15487
15693
|
const countResult = await countStmt.bind(...params).first();
|
|
15488
15694
|
const totalUsers = countResult?.total || 0;
|
|
15489
|
-
await
|
|
15695
|
+
await chunkFCLKX2OS_cjs.logActivity(
|
|
15490
15696
|
db,
|
|
15491
15697
|
user.userId,
|
|
15492
15698
|
"users.list_view",
|
|
@@ -15557,7 +15763,7 @@ userRoutes.get("/users", async (c) => {
|
|
|
15557
15763
|
if (isApiRequest) {
|
|
15558
15764
|
return c.json({ error: "Failed to load users" }, 500);
|
|
15559
15765
|
}
|
|
15560
|
-
return c.html(
|
|
15766
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15561
15767
|
type: "error",
|
|
15562
15768
|
message: "Failed to load users. Please try again.",
|
|
15563
15769
|
dismissible: true
|
|
@@ -15588,7 +15794,7 @@ userRoutes.get("/users/new", async (c) => {
|
|
|
15588
15794
|
return c.html(renderUserNewPage(pageData));
|
|
15589
15795
|
} catch (error) {
|
|
15590
15796
|
console.error("User new page error:", error);
|
|
15591
|
-
return c.html(
|
|
15797
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15592
15798
|
type: "error",
|
|
15593
15799
|
message: "Failed to load user creation page. Please try again.",
|
|
15594
15800
|
dismissible: true
|
|
@@ -15622,12 +15828,12 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
15622
15828
|
const validation = validateCustomData(sanitized, profileConfig);
|
|
15623
15829
|
if (!validation.valid) {
|
|
15624
15830
|
const errorMessages = Object.values(validation.errors).join(", ");
|
|
15625
|
-
return c.html(
|
|
15831
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({ type: "error", message: errorMessages, dismissible: true }), 400);
|
|
15626
15832
|
}
|
|
15627
15833
|
sanitizedRegistrationCustom = sanitized;
|
|
15628
15834
|
}
|
|
15629
15835
|
if (!firstName || !lastName || !email || !password) {
|
|
15630
|
-
return c.html(
|
|
15836
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15631
15837
|
type: "error",
|
|
15632
15838
|
message: "First name, last name, email, and password are required.",
|
|
15633
15839
|
dismissible: true
|
|
@@ -15635,21 +15841,21 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
15635
15841
|
}
|
|
15636
15842
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
15637
15843
|
if (!emailRegex.test(email)) {
|
|
15638
|
-
return c.html(
|
|
15844
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15639
15845
|
type: "error",
|
|
15640
15846
|
message: "Please enter a valid email address.",
|
|
15641
15847
|
dismissible: true
|
|
15642
15848
|
}));
|
|
15643
15849
|
}
|
|
15644
15850
|
if (password.length < 8) {
|
|
15645
|
-
return c.html(
|
|
15851
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15646
15852
|
type: "error",
|
|
15647
15853
|
message: "Password must be at least 8 characters long.",
|
|
15648
15854
|
dismissible: true
|
|
15649
15855
|
}));
|
|
15650
15856
|
}
|
|
15651
15857
|
if (password !== confirmPassword) {
|
|
15652
|
-
return c.html(
|
|
15858
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15653
15859
|
type: "error",
|
|
15654
15860
|
message: "Passwords do not match.",
|
|
15655
15861
|
dismissible: true
|
|
@@ -15661,13 +15867,13 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
15661
15867
|
`);
|
|
15662
15868
|
const existingUser = await checkStmt.bind(email).first();
|
|
15663
15869
|
if (existingUser) {
|
|
15664
|
-
return c.html(
|
|
15870
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15665
15871
|
type: "error",
|
|
15666
15872
|
message: "Email is already taken.",
|
|
15667
15873
|
dismissible: true
|
|
15668
15874
|
}));
|
|
15669
15875
|
}
|
|
15670
|
-
const passwordHash = await
|
|
15876
|
+
const passwordHash = await chunkFCLKX2OS_cjs.AuthManager.hashPassword(password);
|
|
15671
15877
|
const userId = crypto.randomUUID();
|
|
15672
15878
|
const createStmt = db.prepare(`
|
|
15673
15879
|
INSERT INTO auth_user (
|
|
@@ -15692,7 +15898,7 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
15692
15898
|
if (sanitizedRegistrationCustom !== null && Object.keys(sanitizedRegistrationCustom).length > 0) {
|
|
15693
15899
|
await writeProfileData(db, userId, { custom: sanitizedRegistrationCustom }, user.userId);
|
|
15694
15900
|
}
|
|
15695
|
-
await
|
|
15901
|
+
await chunkFCLKX2OS_cjs.logActivity(
|
|
15696
15902
|
db,
|
|
15697
15903
|
user.userId,
|
|
15698
15904
|
"user!.create",
|
|
@@ -15706,7 +15912,7 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
15706
15912
|
return c.body(null, 200);
|
|
15707
15913
|
} catch (error) {
|
|
15708
15914
|
console.error("User creation error:", error);
|
|
15709
|
-
return c.html(
|
|
15915
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15710
15916
|
type: "error",
|
|
15711
15917
|
message: "Failed to create user!. Please try again.",
|
|
15712
15918
|
dismissible: true
|
|
@@ -15731,7 +15937,7 @@ userRoutes.get("/users/:id", async (c) => {
|
|
|
15731
15937
|
if (!userRecord) {
|
|
15732
15938
|
return c.json({ error: "User not found" }, 404);
|
|
15733
15939
|
}
|
|
15734
|
-
await
|
|
15940
|
+
await chunkFCLKX2OS_cjs.logActivity(
|
|
15735
15941
|
db,
|
|
15736
15942
|
user.userId,
|
|
15737
15943
|
"user!.view",
|
|
@@ -15776,7 +15982,7 @@ userRoutes.get("/users/:id/edit", async (c) => {
|
|
|
15776
15982
|
`);
|
|
15777
15983
|
const userToEdit = await userStmt.bind(userId).first();
|
|
15778
15984
|
if (!userToEdit) {
|
|
15779
|
-
return c.html(
|
|
15985
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15780
15986
|
type: "error",
|
|
15781
15987
|
message: "User not found",
|
|
15782
15988
|
dismissible: true
|
|
@@ -15846,7 +16052,7 @@ userRoutes.get("/users/:id/edit", async (c) => {
|
|
|
15846
16052
|
return c.html(renderUserEditPage(pageData));
|
|
15847
16053
|
} catch (error) {
|
|
15848
16054
|
console.error("User edit page error:", error);
|
|
15849
|
-
return c.html(
|
|
16055
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15850
16056
|
type: "error",
|
|
15851
16057
|
message: "Failed to load user. Please try again.",
|
|
15852
16058
|
dismissible: true
|
|
@@ -15879,12 +16085,12 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
15879
16085
|
const validation = validateCustomData(sanitized, profileConfig);
|
|
15880
16086
|
if (!validation.valid) {
|
|
15881
16087
|
const errorMessages = Object.values(validation.errors).join(", ");
|
|
15882
|
-
return c.html(
|
|
16088
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({ type: "error", message: errorMessages, dismissible: true }), 400);
|
|
15883
16089
|
}
|
|
15884
16090
|
sanitizedCustom = sanitized;
|
|
15885
16091
|
}
|
|
15886
16092
|
if (!email) {
|
|
15887
|
-
return c.html(
|
|
16093
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15888
16094
|
type: "error",
|
|
15889
16095
|
message: "Email is required.",
|
|
15890
16096
|
dismissible: true
|
|
@@ -15892,7 +16098,7 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
15892
16098
|
}
|
|
15893
16099
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
15894
16100
|
if (!emailRegex.test(email)) {
|
|
15895
|
-
return c.html(
|
|
16101
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15896
16102
|
type: "error",
|
|
15897
16103
|
message: "Please enter a valid email address.",
|
|
15898
16104
|
dismissible: true
|
|
@@ -15900,14 +16106,14 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
15900
16106
|
}
|
|
15901
16107
|
if (newPassword) {
|
|
15902
16108
|
if (newPassword.length < 8) {
|
|
15903
|
-
return c.html(
|
|
16109
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15904
16110
|
type: "error",
|
|
15905
16111
|
message: "Password must be at least 8 characters long.",
|
|
15906
16112
|
dismissible: true
|
|
15907
16113
|
}));
|
|
15908
16114
|
}
|
|
15909
16115
|
if (newPassword !== confirmPassword) {
|
|
15910
|
-
return c.html(
|
|
16116
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15911
16117
|
type: "error",
|
|
15912
16118
|
message: "Passwords do not match.",
|
|
15913
16119
|
dismissible: true
|
|
@@ -15920,7 +16126,7 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
15920
16126
|
`);
|
|
15921
16127
|
const existingUser = await checkStmt.bind(email, userId).first();
|
|
15922
16128
|
if (existingUser) {
|
|
15923
|
-
return c.html(
|
|
16129
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15924
16130
|
type: "error",
|
|
15925
16131
|
message: "Email is already taken by another user.",
|
|
15926
16132
|
dismissible: true
|
|
@@ -15945,7 +16151,7 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
15945
16151
|
userId
|
|
15946
16152
|
).run();
|
|
15947
16153
|
if (newPassword) {
|
|
15948
|
-
const passwordHash = await
|
|
16154
|
+
const passwordHash = await chunkFCLKX2OS_cjs.AuthManager.hashPassword(newPassword);
|
|
15949
16155
|
const updatePasswordStmt = db.prepare(`
|
|
15950
16156
|
UPDATE auth_user SET password_hash = ?, updated_at = ? WHERE id = ?
|
|
15951
16157
|
`);
|
|
@@ -15958,7 +16164,7 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
15958
16164
|
...sanitizedCustom !== null ? { custom: sanitizedCustom } : {}
|
|
15959
16165
|
}, user.userId);
|
|
15960
16166
|
}
|
|
15961
|
-
await
|
|
16167
|
+
await chunkFCLKX2OS_cjs.logActivity(
|
|
15962
16168
|
db,
|
|
15963
16169
|
user.userId,
|
|
15964
16170
|
"user.update",
|
|
@@ -15968,7 +16174,7 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
15968
16174
|
c.req.header("x-forwarded-for") || c.req.header("cf-connecting-ip"),
|
|
15969
16175
|
c.req.header("user-agent")
|
|
15970
16176
|
);
|
|
15971
|
-
return c.html(
|
|
16177
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15972
16178
|
type: "success",
|
|
15973
16179
|
message: "User updated successfully!",
|
|
15974
16180
|
dismissible: true,
|
|
@@ -15976,7 +16182,7 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
15976
16182
|
}));
|
|
15977
16183
|
} catch (error) {
|
|
15978
16184
|
console.error("User update error:", error);
|
|
15979
|
-
return c.html(
|
|
16185
|
+
return c.html(chunkN32OWET6_cjs.renderAlert({
|
|
15980
16186
|
type: "error",
|
|
15981
16187
|
message: "Failed to update user. Please try again.",
|
|
15982
16188
|
dismissible: true
|
|
@@ -16004,7 +16210,7 @@ userRoutes.post("/users/:id/toggle", async (c) => {
|
|
|
16004
16210
|
UPDATE auth_user SET is_active = ?, updated_at = ? WHERE id = ?
|
|
16005
16211
|
`);
|
|
16006
16212
|
await toggleStmt.bind(active ? 1 : 0, Date.now(), userId).run();
|
|
16007
|
-
await
|
|
16213
|
+
await chunkFCLKX2OS_cjs.logActivity(
|
|
16008
16214
|
db,
|
|
16009
16215
|
user.userId,
|
|
16010
16216
|
active ? "user.activate" : "user.deactivate",
|
|
@@ -16045,7 +16251,7 @@ userRoutes.delete("/users/:id", async (c) => {
|
|
|
16045
16251
|
DELETE FROM auth_user WHERE id = ?
|
|
16046
16252
|
`);
|
|
16047
16253
|
await deleteStmt.bind(userId).run();
|
|
16048
|
-
await
|
|
16254
|
+
await chunkFCLKX2OS_cjs.logActivity(
|
|
16049
16255
|
db,
|
|
16050
16256
|
user.userId,
|
|
16051
16257
|
"user!.hard_delete",
|
|
@@ -16064,7 +16270,7 @@ userRoutes.delete("/users/:id", async (c) => {
|
|
|
16064
16270
|
UPDATE auth_user SET is_active = 0, updated_at = ? WHERE id = ?
|
|
16065
16271
|
`);
|
|
16066
16272
|
await deleteStmt.bind(Date.now(), userId).run();
|
|
16067
|
-
await
|
|
16273
|
+
await chunkFCLKX2OS_cjs.logActivity(
|
|
16068
16274
|
db,
|
|
16069
16275
|
user.userId,
|
|
16070
16276
|
"user!.soft_delete",
|
|
@@ -16130,7 +16336,7 @@ userRoutes.post("/invite-user", async (c) => {
|
|
|
16130
16336
|
Date.now(),
|
|
16131
16337
|
Date.now()
|
|
16132
16338
|
).run();
|
|
16133
|
-
await
|
|
16339
|
+
await chunkFCLKX2OS_cjs.logActivity(
|
|
16134
16340
|
db,
|
|
16135
16341
|
user.userId,
|
|
16136
16342
|
"user!.invite_sent",
|
|
@@ -16187,7 +16393,7 @@ userRoutes.post("/resend-invitation/:id", async (c) => {
|
|
|
16187
16393
|
Date.now(),
|
|
16188
16394
|
userId
|
|
16189
16395
|
).run();
|
|
16190
|
-
await
|
|
16396
|
+
await chunkFCLKX2OS_cjs.logActivity(
|
|
16191
16397
|
db,
|
|
16192
16398
|
user.userId,
|
|
16193
16399
|
"user!.invitation_resent",
|
|
@@ -16223,7 +16429,7 @@ userRoutes.delete("/cancel-invitation/:id", async (c) => {
|
|
|
16223
16429
|
}
|
|
16224
16430
|
const deleteStmt = db.prepare(`DELETE FROM auth_user WHERE id = ?`);
|
|
16225
16431
|
await deleteStmt.bind(userId).run();
|
|
16226
|
-
await
|
|
16432
|
+
await chunkFCLKX2OS_cjs.logActivity(
|
|
16227
16433
|
db,
|
|
16228
16434
|
user.userId,
|
|
16229
16435
|
"user!.invitation_cancelled",
|
|
@@ -16472,7 +16678,7 @@ function getFileIcon(mimeType) {
|
|
|
16472
16678
|
}
|
|
16473
16679
|
|
|
16474
16680
|
// src/templates/pages/admin-media-library.template.ts
|
|
16475
|
-
|
|
16681
|
+
chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
|
|
16476
16682
|
function renderMediaLibraryPage(data) {
|
|
16477
16683
|
const pageContent = `
|
|
16478
16684
|
<div>
|
|
@@ -17407,7 +17613,7 @@ function renderMediaLibraryPage(data) {
|
|
|
17407
17613
|
version: data.version,
|
|
17408
17614
|
content: pageContent
|
|
17409
17615
|
};
|
|
17410
|
-
return
|
|
17616
|
+
return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
17411
17617
|
}
|
|
17412
17618
|
|
|
17413
17619
|
// src/templates/components/media-file-details.template.ts
|
|
@@ -17604,7 +17810,7 @@ var fileValidationSchema2 = zod.z.object({
|
|
|
17604
17810
|
// 50MB max
|
|
17605
17811
|
});
|
|
17606
17812
|
var adminMediaRoutes = new hono.Hono();
|
|
17607
|
-
adminMediaRoutes.use("*",
|
|
17813
|
+
adminMediaRoutes.use("*", chunkFCLKX2OS_cjs.requireAuth());
|
|
17608
17814
|
adminMediaRoutes.get("/", async (c) => {
|
|
17609
17815
|
try {
|
|
17610
17816
|
const user = c.get("user");
|
|
@@ -17616,7 +17822,7 @@ adminMediaRoutes.get("/", async (c) => {
|
|
|
17616
17822
|
const limit = 24;
|
|
17617
17823
|
const offset = (page - 1) * limit;
|
|
17618
17824
|
const mediaSvc = new MediaDocumentService(c.env.DB, getRequestTenant(c));
|
|
17619
|
-
const { files, folders: folderAgg, types: typeAgg } = await mediaSvc.list({ folder, type, limit, offset });
|
|
17825
|
+
const { files, total, folders: folderAgg, types: typeAgg } = await mediaSvc.list({ folder, type, limit, offset });
|
|
17620
17826
|
const mediaFiles = files.map((doc) => mediaDocToFile(doc));
|
|
17621
17827
|
const pageData = {
|
|
17622
17828
|
files: mediaFiles,
|
|
@@ -17626,8 +17832,8 @@ adminMediaRoutes.get("/", async (c) => {
|
|
|
17626
17832
|
currentType: type,
|
|
17627
17833
|
currentView: view,
|
|
17628
17834
|
currentPage: page,
|
|
17629
|
-
totalFiles:
|
|
17630
|
-
hasNextPage: mediaFiles.length
|
|
17835
|
+
totalFiles: total,
|
|
17836
|
+
hasNextPage: offset + mediaFiles.length < total,
|
|
17631
17837
|
user: {
|
|
17632
17838
|
name: user.email,
|
|
17633
17839
|
email: user.email,
|
|
@@ -17646,7 +17852,7 @@ adminMediaRoutes.get("/selector", async (c) => {
|
|
|
17646
17852
|
const { searchParams } = new URL(c.req.url);
|
|
17647
17853
|
const search = searchParams.get("search") || "";
|
|
17648
17854
|
const db = c.env.DB;
|
|
17649
|
-
const pluginService = new
|
|
17855
|
+
const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
|
|
17650
17856
|
const mediaPlugin = await pluginService.getPlugin("core-media");
|
|
17651
17857
|
if (!mediaPlugin || mediaPlugin.status !== "active") {
|
|
17652
17858
|
return c.html(html.html`
|
|
@@ -17667,12 +17873,14 @@ adminMediaRoutes.get("/selector", async (c) => {
|
|
|
17667
17873
|
<input
|
|
17668
17874
|
type="search"
|
|
17669
17875
|
id="media-selector-search"
|
|
17876
|
+
name="search"
|
|
17670
17877
|
placeholder="Search files..."
|
|
17671
17878
|
class="w-full rounded-lg bg-white dark:bg-zinc-800 px-4 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow"
|
|
17672
17879
|
hx-get="/admin/media/selector"
|
|
17673
17880
|
hx-trigger="keyup changed delay:300ms"
|
|
17674
17881
|
hx-target="#media-selector-grid"
|
|
17675
|
-
hx-
|
|
17882
|
+
hx-swap="outerHTML"
|
|
17883
|
+
hx-select="#media-selector-grid"
|
|
17676
17884
|
>
|
|
17677
17885
|
</div>
|
|
17678
17886
|
|
|
@@ -18020,7 +18228,7 @@ adminMediaRoutes.put("/:id", async (c) => {
|
|
|
18020
18228
|
`);
|
|
18021
18229
|
}
|
|
18022
18230
|
});
|
|
18023
|
-
adminMediaRoutes.delete("/cleanup",
|
|
18231
|
+
adminMediaRoutes.delete("/cleanup", chunkFCLKX2OS_cjs.requireRole("admin"), async (c) => {
|
|
18024
18232
|
try {
|
|
18025
18233
|
const db = c.env.DB;
|
|
18026
18234
|
const allMediaStmt = db.prepare("SELECT id, r2_key, filename FROM media WHERE deleted_at IS NULL");
|
|
@@ -18278,7 +18486,7 @@ function generateMediaItemHTML(file) {
|
|
|
18278
18486
|
}
|
|
18279
18487
|
|
|
18280
18488
|
// src/templates/pages/admin-plugins-list.template.ts
|
|
18281
|
-
|
|
18489
|
+
chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
|
|
18282
18490
|
function renderPluginsListPage(data) {
|
|
18283
18491
|
const categories = [
|
|
18284
18492
|
{ value: "content", label: "Content Management" },
|
|
@@ -18761,7 +18969,7 @@ function renderPluginsListPage(data) {
|
|
|
18761
18969
|
version: data.version,
|
|
18762
18970
|
content: pageContent
|
|
18763
18971
|
};
|
|
18764
|
-
return
|
|
18972
|
+
return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
18765
18973
|
}
|
|
18766
18974
|
function renderPluginCard(plugin) {
|
|
18767
18975
|
const statusColors = {
|
|
@@ -19139,6 +19347,8 @@ function escapeHtmlAttr(value) {
|
|
|
19139
19347
|
}
|
|
19140
19348
|
function renderPluginSettingsPage(data) {
|
|
19141
19349
|
const { plugin, activity = [], user } = data;
|
|
19350
|
+
const hasUserSettings = Object.keys(plugin.settings || {}).some((k) => !k.startsWith("_"));
|
|
19351
|
+
const defaultTab = hasUserSettings ? "settings" : "info";
|
|
19142
19352
|
const pageContent = `
|
|
19143
19353
|
<div class="w-full px-4 sm:px-6 lg:px-8 py-6">
|
|
19144
19354
|
<!-- Header with Back Button -->
|
|
@@ -19149,13 +19359,24 @@ function renderPluginSettingsPage(data) {
|
|
|
19149
19359
|
${plugin.description}
|
|
19150
19360
|
</p>
|
|
19151
19361
|
</div>
|
|
19152
|
-
<div class="mt-4 sm:mt-0 sm:ml-16
|
|
19362
|
+
<div class="mt-4 sm:mt-0 sm:ml-16 flex items-center gap-3">
|
|
19153
19363
|
<a href="/admin/plugins" class="inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm">
|
|
19154
19364
|
<svg class="-ml-0.5 mr-1.5 h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
19155
19365
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/>
|
|
19156
19366
|
</svg>
|
|
19157
19367
|
Back to Plugins
|
|
19158
19368
|
</a>
|
|
19369
|
+
${plugin.settings?._adminPath ? `
|
|
19370
|
+
<a
|
|
19371
|
+
href="${plugin.settings._adminPath}"
|
|
19372
|
+
class="inline-flex items-center justify-center gap-1.5 rounded-lg bg-gradient-to-r from-cyan-500 to-purple-600 hover:from-cyan-400 hover:to-purple-500 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm transition-all duration-200"
|
|
19373
|
+
>
|
|
19374
|
+
<svg class="-ml-0.5 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
19375
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/>
|
|
19376
|
+
</svg>
|
|
19377
|
+
View Page
|
|
19378
|
+
</a>
|
|
19379
|
+
` : ""}
|
|
19159
19380
|
</div>
|
|
19160
19381
|
</div>
|
|
19161
19382
|
|
|
@@ -19188,23 +19409,25 @@ function renderPluginSettingsPage(data) {
|
|
|
19188
19409
|
<!-- Tabs -->
|
|
19189
19410
|
<div class="mb-6">
|
|
19190
19411
|
<nav class="flex space-x-8" aria-label="Tabs">
|
|
19191
|
-
|
|
19412
|
+
${hasUserSettings ? `
|
|
19413
|
+
<a href="#settings" onclick="showTab('settings')" id="settings-tab" class="tab-button border-b-2 border-transparent py-2 px-1 text-sm font-medium text-gray-400 hover:text-gray-300">
|
|
19192
19414
|
Settings
|
|
19193
|
-
</
|
|
19194
|
-
|
|
19195
|
-
|
|
19196
|
-
</button>
|
|
19197
|
-
<button onclick="showTab('info')" id="info-tab" class="tab-button border-b-2 border-transparent py-2 px-1 text-sm font-medium text-gray-400 hover:text-gray-300">
|
|
19415
|
+
</a>
|
|
19416
|
+
` : ""}
|
|
19417
|
+
<a href="#info" onclick="showTab('info')" id="info-tab" class="tab-button border-b-2 border-transparent py-2 px-1 text-sm font-medium text-gray-400 hover:text-gray-300">
|
|
19198
19418
|
Information
|
|
19199
|
-
</
|
|
19419
|
+
</a>
|
|
19420
|
+
<a href="#activity" onclick="showTab('activity')" id="activity-tab" class="tab-button border-b-2 border-transparent py-2 px-1 text-sm font-medium text-gray-400 hover:text-gray-300">
|
|
19421
|
+
Activity Log
|
|
19422
|
+
</a>
|
|
19200
19423
|
</nav>
|
|
19201
19424
|
</div>
|
|
19202
19425
|
|
|
19203
19426
|
<!-- Tab Content -->
|
|
19204
19427
|
<div id="tab-content">
|
|
19205
19428
|
<!-- Settings Tab -->
|
|
19206
|
-
<div id="settings-content" class="tab-content">
|
|
19207
|
-
${renderSettingsTab(plugin)}
|
|
19429
|
+
<div id="settings-content" class="tab-content hidden">
|
|
19430
|
+
${hasUserSettings ? renderSettingsTab(plugin) : ""}
|
|
19208
19431
|
</div>
|
|
19209
19432
|
|
|
19210
19433
|
<!-- Activity Tab -->
|
|
@@ -19220,27 +19443,42 @@ function renderPluginSettingsPage(data) {
|
|
|
19220
19443
|
</div>
|
|
19221
19444
|
|
|
19222
19445
|
<script>
|
|
19446
|
+
const VALID_TABS = [${hasUserSettings ? "'settings', " : ""}'activity', 'info'];
|
|
19447
|
+
|
|
19223
19448
|
function showTab(tabName) {
|
|
19224
|
-
|
|
19449
|
+
if (!VALID_TABS.includes(tabName)) tabName = '${defaultTab}';
|
|
19450
|
+
|
|
19225
19451
|
document.querySelectorAll('.tab-content').forEach(content => {
|
|
19226
19452
|
content.classList.add('hidden');
|
|
19227
19453
|
});
|
|
19228
|
-
|
|
19229
|
-
// Remove active class from all tabs
|
|
19454
|
+
|
|
19230
19455
|
document.querySelectorAll('.tab-button').forEach(tab => {
|
|
19231
19456
|
tab.classList.remove('active', 'border-blue-400', 'text-blue-400');
|
|
19232
19457
|
tab.classList.add('border-transparent', 'text-gray-400');
|
|
19233
19458
|
});
|
|
19234
|
-
|
|
19235
|
-
|
|
19236
|
-
|
|
19237
|
-
|
|
19238
|
-
// Add active class to selected tab
|
|
19459
|
+
|
|
19460
|
+
const contentEl = document.getElementById(tabName + '-content');
|
|
19461
|
+
if (contentEl) contentEl.classList.remove('hidden');
|
|
19462
|
+
|
|
19239
19463
|
const activeTab = document.getElementById(tabName + '-tab');
|
|
19240
|
-
activeTab
|
|
19241
|
-
|
|
19464
|
+
if (activeTab) {
|
|
19465
|
+
activeTab.classList.add('active', 'border-blue-400', 'text-blue-400');
|
|
19466
|
+
activeTab.classList.remove('border-transparent', 'text-gray-400');
|
|
19467
|
+
}
|
|
19468
|
+
|
|
19469
|
+
if (window.location.hash !== '#' + tabName) {
|
|
19470
|
+
history.replaceState(null, '', '#' + tabName);
|
|
19471
|
+
}
|
|
19242
19472
|
}
|
|
19243
19473
|
|
|
19474
|
+
function initTabFromHash() {
|
|
19475
|
+
const hash = window.location.hash.replace('#', '');
|
|
19476
|
+
showTab(VALID_TABS.includes(hash) ? hash : '${defaultTab}');
|
|
19477
|
+
}
|
|
19478
|
+
|
|
19479
|
+
window.addEventListener('hashchange', initTabFromHash);
|
|
19480
|
+
initTabFromHash();
|
|
19481
|
+
|
|
19244
19482
|
async function togglePlugin(pluginId, action) {
|
|
19245
19483
|
const button = event.target;
|
|
19246
19484
|
const originalText = button.textContent;
|
|
@@ -19385,7 +19623,7 @@ function renderPluginSettingsPage(data) {
|
|
|
19385
19623
|
user,
|
|
19386
19624
|
content: pageContent
|
|
19387
19625
|
};
|
|
19388
|
-
return
|
|
19626
|
+
return chunkPXNTCCPE_cjs.renderAdminLayout(layoutData);
|
|
19389
19627
|
}
|
|
19390
19628
|
function renderStatusBadge(status) {
|
|
19391
19629
|
const statusColors = {
|
|
@@ -19413,6 +19651,7 @@ function renderToggleButton(plugin) {
|
|
|
19413
19651
|
function renderSettingsTab(plugin) {
|
|
19414
19652
|
const settings = plugin.settings || {};
|
|
19415
19653
|
const pluginId = plugin.id || plugin.name;
|
|
19654
|
+
const hasUserKeys = Object.keys(settings).some((k) => !k.startsWith("_"));
|
|
19416
19655
|
const customRenderer = pluginSettingsComponents[pluginId];
|
|
19417
19656
|
if (customRenderer) {
|
|
19418
19657
|
return `
|
|
@@ -19448,9 +19687,9 @@ function renderSettingsTab(plugin) {
|
|
|
19448
19687
|
`}
|
|
19449
19688
|
|
|
19450
19689
|
<form id="settings-form" class="space-y-6">
|
|
19451
|
-
${isAuthPlugin &&
|
|
19690
|
+
${isAuthPlugin && hasUserKeys ? renderAuthSettingsForm(settings) : isTurnstilePlugin && hasUserKeys ? renderTurnstileSettingsForm(settings) : hasUserKeys ? renderSettingsFields(settings) : renderNoSettings(plugin)}
|
|
19452
19691
|
|
|
19453
|
-
${
|
|
19692
|
+
${hasUserKeys ? `
|
|
19454
19693
|
<div class="flex items-center justify-end pt-6 border-t border-white/10">
|
|
19455
19694
|
<button
|
|
19456
19695
|
type="button"
|
|
@@ -19467,7 +19706,7 @@ function renderSettingsTab(plugin) {
|
|
|
19467
19706
|
`;
|
|
19468
19707
|
}
|
|
19469
19708
|
function renderSettingsFields(settings) {
|
|
19470
|
-
return Object.entries(settings).map(([key, value]) => {
|
|
19709
|
+
return Object.entries(settings).filter(([key]) => !key.startsWith("_")).map(([key, value]) => {
|
|
19471
19710
|
const fieldId = `setting_${key}`;
|
|
19472
19711
|
const displayName = key.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase());
|
|
19473
19712
|
if (typeof value === "boolean") {
|
|
@@ -19656,6 +19895,38 @@ function renderActivityTab(activity) {
|
|
|
19656
19895
|
}
|
|
19657
19896
|
function renderInformationTab(plugin) {
|
|
19658
19897
|
return `
|
|
19898
|
+
${plugin.description ? `
|
|
19899
|
+
<!-- About -->
|
|
19900
|
+
<div class="backdrop-blur-md bg-black/20 rounded-xl border border-white/10 shadow-xl p-6 mb-6">
|
|
19901
|
+
<h2 class="text-xl font-semibold text-white mb-3">About</h2>
|
|
19902
|
+
<p class="text-gray-300 leading-relaxed">${plugin.description}</p>
|
|
19903
|
+
</div>
|
|
19904
|
+
` : ""}
|
|
19905
|
+
|
|
19906
|
+
${(plugin.settings?._routes?.length ?? 0) > 0 ? `
|
|
19907
|
+
<!-- Routes -->
|
|
19908
|
+
<div class="backdrop-blur-md bg-black/20 rounded-xl border border-white/10 shadow-xl p-6 mb-6">
|
|
19909
|
+
<h2 class="text-xl font-semibold text-white mb-4">Routes</h2>
|
|
19910
|
+
<div class="space-y-2">
|
|
19911
|
+
${plugin.settings._routes.map((r) => {
|
|
19912
|
+
const badge = r.method === "GET" ? "bg-emerald-500/20 text-emerald-300 border border-emerald-500/30" : r.method === "POST" ? "bg-blue-500/20 text-blue-300 border border-blue-500/30" : r.method === "DELETE" ? "bg-red-500/20 text-red-300 border border-red-500/30" : "bg-white/10 text-gray-300 border border-white/20";
|
|
19913
|
+
const pathHtml = r.method === "GET" ? `<a href="${r.path}" class="font-mono text-sm text-blue-400 hover:text-blue-300 hover:underline">${r.path}</a>` : `<span class="font-mono text-sm text-gray-200">${r.path}</span>`;
|
|
19914
|
+
const authBadge = r.requiresAuth ? `<span class="ml-2 text-xs text-amber-400/80">\u{1F512} auth</span>` : "";
|
|
19915
|
+
return `
|
|
19916
|
+
<div class="flex items-start gap-3 py-2 border-b border-white/5 last:border-0">
|
|
19917
|
+
<span class="shrink-0 inline-block px-2 py-0.5 rounded text-xs font-bold ${badge}">${r.method}</span>
|
|
19918
|
+
<div class="min-w-0">
|
|
19919
|
+
<div class="flex items-center gap-1 flex-wrap">
|
|
19920
|
+
${pathHtml}${authBadge}
|
|
19921
|
+
</div>
|
|
19922
|
+
${r.description ? `<p class="text-xs text-gray-400 mt-0.5">${r.description}</p>` : ""}
|
|
19923
|
+
</div>
|
|
19924
|
+
</div>`;
|
|
19925
|
+
}).join("")}
|
|
19926
|
+
</div>
|
|
19927
|
+
</div>
|
|
19928
|
+
` : ""}
|
|
19929
|
+
|
|
19659
19930
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
19660
19931
|
<!-- Plugin Details -->
|
|
19661
19932
|
<div class="backdrop-blur-md bg-black/20 rounded-xl border border-white/10 shadow-xl p-6">
|
|
@@ -20453,8 +20724,8 @@ defineUserProfile({
|
|
|
20453
20724
|
|
|
20454
20725
|
// src/routes/admin-plugins.ts
|
|
20455
20726
|
var adminPluginRoutes = new hono.Hono();
|
|
20456
|
-
adminPluginRoutes.use("*",
|
|
20457
|
-
var AVAILABLE_PLUGINS = Object.values(
|
|
20727
|
+
adminPluginRoutes.use("*", chunkFCLKX2OS_cjs.requireAuth());
|
|
20728
|
+
var AVAILABLE_PLUGINS = Object.values(chunkKVBHB7QP_cjs.PLUGIN_REGISTRY).map((p) => ({
|
|
20458
20729
|
id: p.id,
|
|
20459
20730
|
name: p.codeName,
|
|
20460
20731
|
display_name: p.displayName,
|
|
@@ -20474,7 +20745,7 @@ adminPluginRoutes.get("/", async (c) => {
|
|
|
20474
20745
|
if (user?.role !== "admin") {
|
|
20475
20746
|
return c.text("Access denied", 403);
|
|
20476
20747
|
}
|
|
20477
|
-
const pluginService = new
|
|
20748
|
+
const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
|
|
20478
20749
|
let installedPlugins = [];
|
|
20479
20750
|
let stats = { total: 0, active: 0, inactive: 0, errors: 0, uninstalled: 0 };
|
|
20480
20751
|
try {
|
|
@@ -20546,10 +20817,10 @@ adminPluginRoutes.get("/:id", async (c) => {
|
|
|
20546
20817
|
if (user?.role !== "admin") {
|
|
20547
20818
|
return c.redirect("/admin/plugins");
|
|
20548
20819
|
}
|
|
20549
|
-
const pluginService = new
|
|
20820
|
+
const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
|
|
20550
20821
|
let plugin = await pluginService.getPlugin(pluginId);
|
|
20551
20822
|
if (!plugin) {
|
|
20552
|
-
const def =
|
|
20823
|
+
const def = chunkA4KUJ3LD_cjs.getPluginDefinition(pluginId);
|
|
20553
20824
|
if (!def) return c.text("Plugin not found", 404);
|
|
20554
20825
|
plugin = await pluginService.ensurePlugin(pluginId, {
|
|
20555
20826
|
displayName: def.displayName ?? pluginId,
|
|
@@ -20561,7 +20832,7 @@ adminPluginRoutes.get("/:id", async (c) => {
|
|
|
20561
20832
|
const activity = await pluginService.getPluginActivity(pluginId, 20);
|
|
20562
20833
|
let enrichedSettings = plugin.settings || {};
|
|
20563
20834
|
if (pluginId === "otp-login") {
|
|
20564
|
-
const settingsService = new
|
|
20835
|
+
const settingsService = new chunk36Z3AKX3_cjs.SettingsService(db);
|
|
20565
20836
|
const generalSettings = await settingsService.getGeneralSettings();
|
|
20566
20837
|
const siteName = generalSettings.siteName || "SonicJS";
|
|
20567
20838
|
const emailPlugin = await db.prepare(`
|
|
@@ -20640,14 +20911,14 @@ adminPluginRoutes.get("/:id/configure", async (c) => {
|
|
|
20640
20911
|
const user = c.get("user");
|
|
20641
20912
|
const pluginId = c.req.param("id");
|
|
20642
20913
|
if (user?.role !== "admin") return c.redirect("/admin/plugins");
|
|
20643
|
-
const def =
|
|
20914
|
+
const def = chunkA4KUJ3LD_cjs.getPluginDefinition(pluginId);
|
|
20644
20915
|
if (!def?.configSchema) return c.text("No schema-driven settings for this plugin", 404);
|
|
20645
20916
|
const db = c.env.DB;
|
|
20646
|
-
const pluginService = new
|
|
20917
|
+
const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
|
|
20647
20918
|
const plugin = await pluginService.getPlugin(pluginId);
|
|
20648
20919
|
const stored = plugin?.settings ?? {};
|
|
20649
|
-
const values =
|
|
20650
|
-
const fieldsHtml =
|
|
20920
|
+
const values = chunkA4KUJ3LD_cjs.applySchemaDefaults(def.configSchema, stored);
|
|
20921
|
+
const fieldsHtml = chunkA4KUJ3LD_cjs.renderSchemaFields(def.configSchema, values);
|
|
20651
20922
|
const displayName = plugin?.display_name ?? def.displayName ?? def.id;
|
|
20652
20923
|
return c.html(`<!DOCTYPE html>
|
|
20653
20924
|
<html lang="en"><head>
|
|
@@ -20674,19 +20945,21 @@ adminPluginRoutes.post("/:id/configure", async (c) => {
|
|
|
20674
20945
|
const user = c.get("user");
|
|
20675
20946
|
const pluginId = c.req.param("id");
|
|
20676
20947
|
if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
|
|
20677
|
-
const def =
|
|
20948
|
+
const def = chunkA4KUJ3LD_cjs.getPluginDefinition(pluginId);
|
|
20678
20949
|
if (!def?.configSchema) return c.text("No schema-driven settings for this plugin", 404);
|
|
20679
20950
|
const form = await c.req.formData();
|
|
20680
|
-
const parsed =
|
|
20951
|
+
const parsed = chunkA4KUJ3LD_cjs.parseFormDataToSettings(def.configSchema, form);
|
|
20681
20952
|
const db = c.env.DB;
|
|
20682
|
-
const pluginService = new
|
|
20953
|
+
const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
|
|
20683
20954
|
await pluginService.ensurePlugin(pluginId, {
|
|
20684
20955
|
displayName: def.displayName ?? pluginId,
|
|
20685
20956
|
version: def.version,
|
|
20686
20957
|
description: def.description,
|
|
20687
20958
|
author: typeof def.author === "object" ? def.author?.name : def.author
|
|
20688
20959
|
});
|
|
20689
|
-
await pluginService.
|
|
20960
|
+
const existingPlugin = await pluginService.getPlugin(pluginId);
|
|
20961
|
+
const existingSettings = existingPlugin?.settings ?? {};
|
|
20962
|
+
await pluginService.updatePluginSettings(pluginId, { ...existingSettings, ...parsed });
|
|
20690
20963
|
return c.redirect(`/admin/plugins/${encodeURIComponent(pluginId)}/configure`);
|
|
20691
20964
|
} catch (error) {
|
|
20692
20965
|
console.error("Error saving schema settings:", error);
|
|
@@ -20701,7 +20974,7 @@ adminPluginRoutes.post("/:id/activate", async (c) => {
|
|
|
20701
20974
|
if (user?.role !== "admin") {
|
|
20702
20975
|
return c.json({ error: "Access denied" }, 403);
|
|
20703
20976
|
}
|
|
20704
|
-
const pluginService = new
|
|
20977
|
+
const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
|
|
20705
20978
|
await pluginService.activatePlugin(pluginId);
|
|
20706
20979
|
return c.json({ success: true });
|
|
20707
20980
|
} catch (error) {
|
|
@@ -20718,7 +20991,7 @@ adminPluginRoutes.post("/:id/deactivate", async (c) => {
|
|
|
20718
20991
|
if (user?.role !== "admin") {
|
|
20719
20992
|
return c.json({ error: "Access denied" }, 403);
|
|
20720
20993
|
}
|
|
20721
|
-
const pluginService = new
|
|
20994
|
+
const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
|
|
20722
20995
|
await pluginService.deactivatePlugin(pluginId);
|
|
20723
20996
|
return c.json({ success: true });
|
|
20724
20997
|
} catch (error) {
|
|
@@ -20735,8 +21008,8 @@ adminPluginRoutes.post("/install", async (c) => {
|
|
|
20735
21008
|
return c.json({ error: "Access denied" }, 403);
|
|
20736
21009
|
}
|
|
20737
21010
|
const body = await c.req.json();
|
|
20738
|
-
const pluginService = new
|
|
20739
|
-
const registryEntry =
|
|
21011
|
+
const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
|
|
21012
|
+
const registryEntry = chunkKVBHB7QP_cjs.findPluginByCodeName(body.name) || chunkKVBHB7QP_cjs.PLUGIN_REGISTRY[body.name] || chunkKVBHB7QP_cjs.PLUGIN_REGISTRY[body.id];
|
|
20740
21013
|
if (!registryEntry) {
|
|
20741
21014
|
return c.json({ error: "Plugin not found in registry" }, 404);
|
|
20742
21015
|
}
|
|
@@ -20769,7 +21042,7 @@ adminPluginRoutes.post("/:id/uninstall", async (c) => {
|
|
|
20769
21042
|
if (user?.role !== "admin") {
|
|
20770
21043
|
return c.json({ error: "Access denied" }, 403);
|
|
20771
21044
|
}
|
|
20772
|
-
const pluginService = new
|
|
21045
|
+
const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
|
|
20773
21046
|
await pluginService.uninstallPlugin(pluginId);
|
|
20774
21047
|
return c.json({ success: true });
|
|
20775
21048
|
} catch (error) {
|
|
@@ -20787,8 +21060,10 @@ adminPluginRoutes.post("/:id/settings", async (c) => {
|
|
|
20787
21060
|
return c.json({ error: "Access denied" }, 403);
|
|
20788
21061
|
}
|
|
20789
21062
|
const settings = await c.req.json();
|
|
20790
|
-
const pluginService = new
|
|
20791
|
-
await pluginService.
|
|
21063
|
+
const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
|
|
21064
|
+
const existingPlugin = await pluginService.getPlugin(pluginId);
|
|
21065
|
+
const existingSettings = existingPlugin?.settings ?? {};
|
|
21066
|
+
await pluginService.updatePluginSettings(pluginId, { ...existingSettings, ...settings });
|
|
20792
21067
|
if (pluginId === "core-auth") {
|
|
20793
21068
|
try {
|
|
20794
21069
|
const cacheKv = c.env.CACHE_KV;
|
|
@@ -20820,7 +21095,7 @@ function formatLastUpdated(timestamp) {
|
|
|
20820
21095
|
}
|
|
20821
21096
|
|
|
20822
21097
|
// src/templates/pages/admin-logs-list.template.ts
|
|
20823
|
-
|
|
21098
|
+
chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
|
|
20824
21099
|
function renderLogsListPage(data) {
|
|
20825
21100
|
const { logs, pagination, filters, user } = data;
|
|
20826
21101
|
const content = `
|
|
@@ -21131,7 +21406,7 @@ function renderLogsListPage(data) {
|
|
|
21131
21406
|
user,
|
|
21132
21407
|
content
|
|
21133
21408
|
};
|
|
21134
|
-
return
|
|
21409
|
+
return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
21135
21410
|
}
|
|
21136
21411
|
function renderLogDetailsPage(data) {
|
|
21137
21412
|
const { log, user } = data;
|
|
@@ -21343,7 +21618,7 @@ function renderLogDetailsPage(data) {
|
|
|
21343
21618
|
</div>
|
|
21344
21619
|
</div>
|
|
21345
21620
|
`;
|
|
21346
|
-
return
|
|
21621
|
+
return chunkPXNTCCPE_cjs.adminLayoutV2({
|
|
21347
21622
|
title: `Log Details - ${log.id}`,
|
|
21348
21623
|
user,
|
|
21349
21624
|
content
|
|
@@ -21586,7 +21861,7 @@ function renderLogConfigPage(data) {
|
|
|
21586
21861
|
|
|
21587
21862
|
<script src="https://unpkg.com/htmx.org@1.9.6"></script>
|
|
21588
21863
|
`;
|
|
21589
|
-
return
|
|
21864
|
+
return chunkPXNTCCPE_cjs.adminLayoutV2({
|
|
21590
21865
|
title: "Log Configuration",
|
|
21591
21866
|
user,
|
|
21592
21867
|
content
|
|
@@ -21595,11 +21870,11 @@ function renderLogConfigPage(data) {
|
|
|
21595
21870
|
|
|
21596
21871
|
// src/routes/admin-logs.ts
|
|
21597
21872
|
var adminLogsRoutes = new hono.Hono();
|
|
21598
|
-
adminLogsRoutes.use("*",
|
|
21873
|
+
adminLogsRoutes.use("*", chunkFCLKX2OS_cjs.requireAuth());
|
|
21599
21874
|
adminLogsRoutes.get("/", async (c) => {
|
|
21600
21875
|
try {
|
|
21601
21876
|
const user = c.get("user");
|
|
21602
|
-
const logger =
|
|
21877
|
+
const logger = chunk36Z3AKX3_cjs.getLogger(c.env.DB);
|
|
21603
21878
|
const query = c.req.query();
|
|
21604
21879
|
const page = parseInt(query.page || "1");
|
|
21605
21880
|
const limit = parseInt(query.limit || "50");
|
|
@@ -21679,7 +21954,7 @@ adminLogsRoutes.get("/:id", async (c) => {
|
|
|
21679
21954
|
try {
|
|
21680
21955
|
const id = c.req.param("id");
|
|
21681
21956
|
const user = c.get("user");
|
|
21682
|
-
const logger =
|
|
21957
|
+
const logger = chunk36Z3AKX3_cjs.getLogger(c.env.DB);
|
|
21683
21958
|
const { logs } = await logger.getLogs({
|
|
21684
21959
|
limit: 1,
|
|
21685
21960
|
offset: 0,
|
|
@@ -21716,7 +21991,7 @@ adminLogsRoutes.get("/:id", async (c) => {
|
|
|
21716
21991
|
adminLogsRoutes.get("/config", async (c) => {
|
|
21717
21992
|
try {
|
|
21718
21993
|
const user = c.get("user");
|
|
21719
|
-
const logger =
|
|
21994
|
+
const logger = chunk36Z3AKX3_cjs.getLogger(c.env.DB);
|
|
21720
21995
|
const configs = await logger.getAllConfigs();
|
|
21721
21996
|
const pageData = {
|
|
21722
21997
|
configs,
|
|
@@ -21740,7 +22015,7 @@ adminLogsRoutes.post("/config/:category", async (c) => {
|
|
|
21740
22015
|
const level = formData.get("level");
|
|
21741
22016
|
const retention = parseInt(formData.get("retention"));
|
|
21742
22017
|
const maxSize = parseInt(formData.get("max_size"));
|
|
21743
|
-
const logger =
|
|
22018
|
+
const logger = chunk36Z3AKX3_cjs.getLogger(c.env.DB);
|
|
21744
22019
|
await logger.updateConfig(category, {
|
|
21745
22020
|
enabled,
|
|
21746
22021
|
level,
|
|
@@ -21769,7 +22044,7 @@ adminLogsRoutes.get("/export", async (c) => {
|
|
|
21769
22044
|
const category = query.category;
|
|
21770
22045
|
const startDate = query.start_date;
|
|
21771
22046
|
const endDate = query.end_date;
|
|
21772
|
-
const logger =
|
|
22047
|
+
const logger = chunk36Z3AKX3_cjs.getLogger(c.env.DB);
|
|
21773
22048
|
const filter = {
|
|
21774
22049
|
limit: 1e4,
|
|
21775
22050
|
// Export up to 10k logs
|
|
@@ -21850,7 +22125,7 @@ adminLogsRoutes.post("/cleanup", async (c) => {
|
|
|
21850
22125
|
error: "Unauthorized. Admin access required."
|
|
21851
22126
|
}, 403);
|
|
21852
22127
|
}
|
|
21853
|
-
const logger =
|
|
22128
|
+
const logger = chunk36Z3AKX3_cjs.getLogger(c.env.DB);
|
|
21854
22129
|
await logger.cleanupByRetention();
|
|
21855
22130
|
return c.html(html.html`
|
|
21856
22131
|
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded">
|
|
@@ -21872,7 +22147,7 @@ adminLogsRoutes.post("/search", async (c) => {
|
|
|
21872
22147
|
const search = formData.get("search");
|
|
21873
22148
|
const level = formData.get("level");
|
|
21874
22149
|
const category = formData.get("category");
|
|
21875
|
-
const logger =
|
|
22150
|
+
const logger = chunk36Z3AKX3_cjs.getLogger(c.env.DB);
|
|
21876
22151
|
const filter = {
|
|
21877
22152
|
limit: 20,
|
|
21878
22153
|
offset: 0,
|
|
@@ -21967,7 +22242,7 @@ adminCheckboxRoutes.get("/", (c) => {
|
|
|
21967
22242
|
role: user.role
|
|
21968
22243
|
} : void 0
|
|
21969
22244
|
};
|
|
21970
|
-
return c.html(
|
|
22245
|
+
return c.html(chunkPXNTCCPE_cjs.renderCheckboxPage(pageData));
|
|
21971
22246
|
});
|
|
21972
22247
|
|
|
21973
22248
|
// src/templates/pages/admin-dashboard.template.ts
|
|
@@ -22039,7 +22314,7 @@ function renderDashboardPage(data) {
|
|
|
22039
22314
|
version: data.version,
|
|
22040
22315
|
content: pageContent
|
|
22041
22316
|
};
|
|
22042
|
-
return
|
|
22317
|
+
return chunkPXNTCCPE_cjs.renderAdminLayout(layoutData);
|
|
22043
22318
|
}
|
|
22044
22319
|
function renderStatsCards(stats) {
|
|
22045
22320
|
const cards = [
|
|
@@ -22587,9 +22862,9 @@ function renderStorageUsage(databaseSizeBytes, mediaSizeBytes) {
|
|
|
22587
22862
|
}
|
|
22588
22863
|
|
|
22589
22864
|
// src/routes/admin-dashboard.ts
|
|
22590
|
-
var VERSION =
|
|
22865
|
+
var VERSION = chunkAOUVUF32_cjs.getCoreVersion();
|
|
22591
22866
|
var router = new hono.Hono();
|
|
22592
|
-
router.use("*",
|
|
22867
|
+
router.use("*", chunkFCLKX2OS_cjs.requireAuth());
|
|
22593
22868
|
router.get("/", async (c) => {
|
|
22594
22869
|
const user = c.get("user");
|
|
22595
22870
|
try {
|
|
@@ -22779,7 +23054,7 @@ router.get("/system-status", async (c) => {
|
|
|
22779
23054
|
});
|
|
22780
23055
|
|
|
22781
23056
|
// src/templates/pages/admin-collections-list.template.ts
|
|
22782
|
-
|
|
23057
|
+
chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
|
|
22783
23058
|
|
|
22784
23059
|
// src/templates/components/table.template.ts
|
|
22785
23060
|
function renderTable2(data) {
|
|
@@ -23261,11 +23536,11 @@ function renderCollectionsListPage(data) {
|
|
|
23261
23536
|
version: data.version,
|
|
23262
23537
|
content: pageContent
|
|
23263
23538
|
};
|
|
23264
|
-
return
|
|
23539
|
+
return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
23265
23540
|
}
|
|
23266
23541
|
|
|
23267
23542
|
// src/templates/pages/admin-collections-form.template.ts
|
|
23268
|
-
|
|
23543
|
+
chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
|
|
23269
23544
|
function getFieldTypeBadge(fieldType) {
|
|
23270
23545
|
const typeLabels = {
|
|
23271
23546
|
"text": "Text",
|
|
@@ -23438,8 +23713,8 @@ function renderCollectionFormPage(data) {
|
|
|
23438
23713
|
<!-- Form Content -->
|
|
23439
23714
|
<div class="px-6 py-6">
|
|
23440
23715
|
<div id="form-messages"></div>
|
|
23441
|
-
${data.error ?
|
|
23442
|
-
${data.success ?
|
|
23716
|
+
${data.error ? chunkN32OWET6_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
|
|
23717
|
+
${data.success ? chunkN32OWET6_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
|
|
23443
23718
|
|
|
23444
23719
|
<!-- Form Styling -->
|
|
23445
23720
|
<style>
|
|
@@ -23550,7 +23825,7 @@ function renderCollectionFormPage(data) {
|
|
|
23550
23825
|
}
|
|
23551
23826
|
</style>
|
|
23552
23827
|
|
|
23553
|
-
${
|
|
23828
|
+
${chunkPXNTCCPE_cjs.renderForm(formData)}
|
|
23554
23829
|
|
|
23555
23830
|
${isEdit && data.managed ? `
|
|
23556
23831
|
<!-- Read-Only Fields Display for Managed Collections -->
|
|
@@ -24548,13 +24823,13 @@ function renderCollectionFormPage(data) {
|
|
|
24548
24823
|
version: data.version,
|
|
24549
24824
|
content: pageContent
|
|
24550
24825
|
};
|
|
24551
|
-
return
|
|
24826
|
+
return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
24552
24827
|
}
|
|
24553
24828
|
|
|
24554
24829
|
// src/routes/admin-collections.ts
|
|
24555
|
-
|
|
24830
|
+
chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
|
|
24556
24831
|
var adminCollectionsRoutes = new hono.Hono();
|
|
24557
|
-
adminCollectionsRoutes.use("*",
|
|
24832
|
+
adminCollectionsRoutes.use("*", chunkFCLKX2OS_cjs.requireAuth());
|
|
24558
24833
|
adminCollectionsRoutes.get("/", async (c) => {
|
|
24559
24834
|
try {
|
|
24560
24835
|
const user = c.get("user");
|
|
@@ -24571,7 +24846,7 @@ adminCollectionsRoutes.get("/", async (c) => {
|
|
|
24571
24846
|
results = queryResults.results ?? [];
|
|
24572
24847
|
} catch (e) {
|
|
24573
24848
|
}
|
|
24574
|
-
const codeCollections =
|
|
24849
|
+
const codeCollections = chunkKVBHB7QP_cjs.getCollectionRegistry().list();
|
|
24575
24850
|
const codeCollectionsMap = new Map(
|
|
24576
24851
|
codeCollections.map((cfg) => {
|
|
24577
24852
|
const fieldCount = cfg.schema?.properties ? Object.keys(cfg.schema.properties).length : 0;
|
|
@@ -24585,7 +24860,7 @@ adminCollectionsRoutes.get("/", async (c) => {
|
|
|
24585
24860
|
field_count: fieldCount,
|
|
24586
24861
|
managed: cfg.managed !== false,
|
|
24587
24862
|
source_type: "code",
|
|
24588
|
-
internal:
|
|
24863
|
+
internal: chunkKVBHB7QP_cjs.isCodeCollectionInternal(cfg),
|
|
24589
24864
|
versioning: cfg.versioning === true
|
|
24590
24865
|
}];
|
|
24591
24866
|
})
|
|
@@ -24624,7 +24899,7 @@ adminCollectionsRoutes.get("/", async (c) => {
|
|
|
24624
24899
|
field_count: fieldCount,
|
|
24625
24900
|
managed: false,
|
|
24626
24901
|
source_type: row.source === "code" || row.source === "system" || row.source === "plugin" ? "code" : "user",
|
|
24627
|
-
internal:
|
|
24902
|
+
internal: chunkKVBHB7QP_cjs.isDbDocTypeInternal(row.source),
|
|
24628
24903
|
versioning: dbVersioning
|
|
24629
24904
|
};
|
|
24630
24905
|
});
|
|
@@ -24781,11 +25056,11 @@ export const myPlugin = definePlugin({
|
|
|
24781
25056
|
`;
|
|
24782
25057
|
const u = user;
|
|
24783
25058
|
return c.html(
|
|
24784
|
-
|
|
25059
|
+
chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
|
|
24785
25060
|
title: "Add a Collection",
|
|
24786
25061
|
pageTitle: "Add a Collection",
|
|
24787
25062
|
currentPath: "/admin/collections",
|
|
24788
|
-
version:
|
|
25063
|
+
version: chunkAOUVUF32_cjs.getCoreVersion(),
|
|
24789
25064
|
user: u ? { name: u.email ?? "Admin", email: u.email ?? "", role: u.role ?? "admin" } : void 0,
|
|
24790
25065
|
content
|
|
24791
25066
|
})
|
|
@@ -24802,7 +25077,7 @@ adminCollectionsRoutes.get("/:id", async (c) => {
|
|
|
24802
25077
|
collection = await stmt.bind(id).first();
|
|
24803
25078
|
} catch {
|
|
24804
25079
|
}
|
|
24805
|
-
const registryRecord =
|
|
25080
|
+
const registryRecord = chunkKVBHB7QP_cjs.getCollectionRegistry().getById(id) ?? chunkKVBHB7QP_cjs.getCollectionRegistry().getByName(id);
|
|
24806
25081
|
if (!collection && !registryRecord) {
|
|
24807
25082
|
const formData2 = {
|
|
24808
25083
|
isEdit: true,
|
|
@@ -24849,9 +25124,9 @@ adminCollectionsRoutes.get("/:id", async (c) => {
|
|
|
24849
25124
|
isCodeDriven = true;
|
|
24850
25125
|
}
|
|
24851
25126
|
const [tinymceActive, quillActive, mdxeditorActive] = await Promise.all([
|
|
24852
|
-
|
|
24853
|
-
|
|
24854
|
-
|
|
25127
|
+
chunkFCLKX2OS_cjs.isPluginActive(db, "tinymce-plugin"),
|
|
25128
|
+
chunkFCLKX2OS_cjs.isPluginActive(db, "quill-editor"),
|
|
25129
|
+
chunkFCLKX2OS_cjs.isPluginActive(db, "easy-mdx")
|
|
24855
25130
|
]);
|
|
24856
25131
|
const displayName = collection?.display_name ?? registryRecord?.displayName ?? id;
|
|
24857
25132
|
const formData = {
|
|
@@ -24871,9 +25146,9 @@ adminCollectionsRoutes.get("/:id", async (c) => {
|
|
|
24871
25146
|
console.error("Error fetching collection:", error);
|
|
24872
25147
|
const user = c.get("user");
|
|
24873
25148
|
const [tinymceActive, quillActive, mdxeditorActive] = await Promise.all([
|
|
24874
|
-
|
|
24875
|
-
|
|
24876
|
-
|
|
25149
|
+
chunkFCLKX2OS_cjs.isPluginActive(db, "tinymce-plugin"),
|
|
25150
|
+
chunkFCLKX2OS_cjs.isPluginActive(db, "quill-editor"),
|
|
25151
|
+
chunkFCLKX2OS_cjs.isPluginActive(db, "easy-mdx")
|
|
24877
25152
|
]);
|
|
24878
25153
|
const formData = {
|
|
24879
25154
|
isEdit: true,
|
|
@@ -24887,7 +25162,7 @@ adminCollectionsRoutes.get("/:id", async (c) => {
|
|
|
24887
25162
|
});
|
|
24888
25163
|
|
|
24889
25164
|
// src/templates/pages/admin-settings.template.ts
|
|
24890
|
-
|
|
25165
|
+
chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
|
|
24891
25166
|
function renderSettingsPage(data) {
|
|
24892
25167
|
const activeTab = data.activeTab || "general";
|
|
24893
25168
|
const pageContent = `
|
|
@@ -25277,7 +25552,7 @@ function renderSettingsPage(data) {
|
|
|
25277
25552
|
version: data.version,
|
|
25278
25553
|
content: pageContent
|
|
25279
25554
|
};
|
|
25280
|
-
return
|
|
25555
|
+
return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
25281
25556
|
}
|
|
25282
25557
|
function renderTabButton(tabId, label, iconPath, activeTab) {
|
|
25283
25558
|
const isActive = activeTab === tabId;
|
|
@@ -25822,7 +26097,7 @@ function renderDatabaseToolsSettings(settings) {
|
|
|
25822
26097
|
|
|
25823
26098
|
// src/routes/admin-settings.ts
|
|
25824
26099
|
var adminSettingsRoutes = new hono.Hono();
|
|
25825
|
-
adminSettingsRoutes.use("*",
|
|
26100
|
+
adminSettingsRoutes.use("*", chunkFCLKX2OS_cjs.requireAuth());
|
|
25826
26101
|
function getMockSettings(user) {
|
|
25827
26102
|
return {
|
|
25828
26103
|
general: {
|
|
@@ -25856,7 +26131,7 @@ adminSettingsRoutes.get("/", (c) => {
|
|
|
25856
26131
|
adminSettingsRoutes.get("/general", async (c) => {
|
|
25857
26132
|
const user = c.get("user");
|
|
25858
26133
|
const db = c.env.DB;
|
|
25859
|
-
const settingsService = new
|
|
26134
|
+
const settingsService = new chunk36Z3AKX3_cjs.SettingsService(db);
|
|
25860
26135
|
const generalSettings = await settingsService.getGeneralSettings(user?.email);
|
|
25861
26136
|
const mockSettings = getMockSettings(user);
|
|
25862
26137
|
mockSettings.general = generalSettings;
|
|
@@ -25875,7 +26150,7 @@ adminSettingsRoutes.get("/general", async (c) => {
|
|
|
25875
26150
|
adminSettingsRoutes.get("/security", async (c) => {
|
|
25876
26151
|
const user = c.get("user");
|
|
25877
26152
|
const db = c.env.DB;
|
|
25878
|
-
const settingsService = new
|
|
26153
|
+
const settingsService = new chunk36Z3AKX3_cjs.SettingsService(db);
|
|
25879
26154
|
const persisted = await settingsService.getSecuritySettings();
|
|
25880
26155
|
const mockSettings = getMockSettings(user);
|
|
25881
26156
|
mockSettings.security = {
|
|
@@ -25925,7 +26200,7 @@ adminSettingsRoutes.get("/database-tools", (c) => {
|
|
|
25925
26200
|
adminSettingsRoutes.get("/api/migrations/status", async (c) => {
|
|
25926
26201
|
try {
|
|
25927
26202
|
const db = c.env.DB;
|
|
25928
|
-
const migrationService = new
|
|
26203
|
+
const migrationService = new chunkOJC4G5JE_cjs.MigrationService(db);
|
|
25929
26204
|
const status = await migrationService.getMigrationStatus();
|
|
25930
26205
|
return c.json({
|
|
25931
26206
|
success: true,
|
|
@@ -25965,7 +26240,7 @@ adminSettingsRoutes.post("/api/migrations/run", async (c) => {
|
|
|
25965
26240
|
adminSettingsRoutes.get("/api/migrations/validate", async (c) => {
|
|
25966
26241
|
try {
|
|
25967
26242
|
const db = c.env.DB;
|
|
25968
|
-
const migrationService = new
|
|
26243
|
+
const migrationService = new chunkOJC4G5JE_cjs.MigrationService(db);
|
|
25969
26244
|
const validation = await migrationService.validateSchema();
|
|
25970
26245
|
return c.json({
|
|
25971
26246
|
success: true,
|
|
@@ -26134,7 +26409,7 @@ adminSettingsRoutes.post("/general", async (c) => {
|
|
|
26134
26409
|
}
|
|
26135
26410
|
const formData = await c.req.formData();
|
|
26136
26411
|
const db = c.env.DB;
|
|
26137
|
-
const settingsService = new
|
|
26412
|
+
const settingsService = new chunk36Z3AKX3_cjs.SettingsService(db);
|
|
26138
26413
|
const settings = {
|
|
26139
26414
|
siteName: formData.get("siteName"),
|
|
26140
26415
|
siteDescription: formData.get("siteDescription"),
|
|
@@ -26180,7 +26455,7 @@ adminSettingsRoutes.post("/security", async (c) => {
|
|
|
26180
26455
|
}
|
|
26181
26456
|
const formData = await c.req.formData();
|
|
26182
26457
|
const db = c.env.DB;
|
|
26183
|
-
const settingsService = new
|
|
26458
|
+
const settingsService = new chunk36Z3AKX3_cjs.SettingsService(db);
|
|
26184
26459
|
const jwtExpiresInRaw = formData.get("jwtExpiresIn")?.trim() || "";
|
|
26185
26460
|
const graceRaw = formData.get("jwtRefreshGraceSeconds")?.trim() || "";
|
|
26186
26461
|
if (!/^\d+(?:s|m|h|d)?$/i.test(jwtExpiresInRaw)) {
|
|
@@ -26223,7 +26498,7 @@ adminSettingsRoutes.post("/", async (c) => {
|
|
|
26223
26498
|
});
|
|
26224
26499
|
|
|
26225
26500
|
// src/templates/pages/admin-api-reference.template.ts
|
|
26226
|
-
|
|
26501
|
+
chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
|
|
26227
26502
|
function renderAuthBadge(auth) {
|
|
26228
26503
|
if (auth === true) {
|
|
26229
26504
|
return `
|
|
@@ -26364,7 +26639,7 @@ function renderAPIReferencePage(data) {
|
|
|
26364
26639
|
>
|
|
26365
26640
|
<option value="">All Categories</option>
|
|
26366
26641
|
${categories.map((category) => {
|
|
26367
|
-
const info =
|
|
26642
|
+
const info = chunk36Z3AKX3_cjs.CATEGORY_INFO[category];
|
|
26368
26643
|
const title = info ? info.title : category;
|
|
26369
26644
|
return `<option value="${category}">${title}</option>`;
|
|
26370
26645
|
}).join("\n ")}
|
|
@@ -26381,7 +26656,7 @@ function renderAPIReferencePage(data) {
|
|
|
26381
26656
|
<!-- API Categories -->
|
|
26382
26657
|
<div class="space-y-6">
|
|
26383
26658
|
${Object.entries(endpointsByCategory).map(([category, endpoints]) => {
|
|
26384
|
-
const info =
|
|
26659
|
+
const info = chunk36Z3AKX3_cjs.CATEGORY_INFO[category] || { title: category, description: "", icon: "📋" };
|
|
26385
26660
|
return `
|
|
26386
26661
|
<div class="api-category" data-category="${category}">
|
|
26387
26662
|
<div class="rounded-lg bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 overflow-hidden">
|
|
@@ -26554,20 +26829,20 @@ function renderAPIReferencePage(data) {
|
|
|
26554
26829
|
version: data.version,
|
|
26555
26830
|
content: pageContent
|
|
26556
26831
|
};
|
|
26557
|
-
return
|
|
26832
|
+
return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
26558
26833
|
}
|
|
26559
26834
|
|
|
26560
26835
|
// src/routes/admin-api-reference.ts
|
|
26561
|
-
var VERSION2 =
|
|
26836
|
+
var VERSION2 = chunkAOUVUF32_cjs.getCoreVersion();
|
|
26562
26837
|
var router2 = new hono.Hono();
|
|
26563
|
-
router2.use("*",
|
|
26838
|
+
router2.use("*", chunkFCLKX2OS_cjs.requireAuth());
|
|
26564
26839
|
router2.get("/", async (c) => {
|
|
26565
26840
|
const user = c.get("user");
|
|
26566
26841
|
try {
|
|
26567
|
-
const app2 =
|
|
26568
|
-
const baseEndpoints =
|
|
26842
|
+
const app2 = chunk36Z3AKX3_cjs.getAppInstance();
|
|
26843
|
+
const baseEndpoints = chunk36Z3AKX3_cjs.buildRouteList(app2);
|
|
26569
26844
|
const collectionRoutes = [];
|
|
26570
|
-
const collections =
|
|
26845
|
+
const collections = chunkKVBHB7QP_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal);
|
|
26571
26846
|
const methodOrder = { GET: 0, POST: 1, PUT: 2, PATCH: 3, DELETE: 4 };
|
|
26572
26847
|
for (const col of collections) {
|
|
26573
26848
|
const displayName = col.displayName || col.name;
|
|
@@ -26659,6 +26934,7 @@ exports.api_default = api_default;
|
|
|
26659
26934
|
exports.api_media_default = api_media_default;
|
|
26660
26935
|
exports.api_system_default = api_system_default;
|
|
26661
26936
|
exports.auth_default = auth_default;
|
|
26937
|
+
exports.createDocumentSchema = createDocumentSchema;
|
|
26662
26938
|
exports.createUserProfilesPlugin = createUserProfilesPlugin;
|
|
26663
26939
|
exports.defineUserProfile = defineUserProfile;
|
|
26664
26940
|
exports.denyIfNotAllowed = denyIfNotAllowed;
|
|
@@ -26683,5 +26959,5 @@ exports.setVariablesCache = setVariablesCache;
|
|
|
26683
26959
|
exports.test_cleanup_default = test_cleanup_default;
|
|
26684
26960
|
exports.userProfilesPlugin = userProfilesPlugin;
|
|
26685
26961
|
exports.userRoutes = userRoutes;
|
|
26686
|
-
//# sourceMappingURL=chunk-
|
|
26687
|
-
//# sourceMappingURL=chunk-
|
|
26962
|
+
//# sourceMappingURL=chunk-7RUW244J.cjs.map
|
|
26963
|
+
//# sourceMappingURL=chunk-7RUW244J.cjs.map
|