@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,22 +1,21 @@
|
|
|
1
|
-
import { isFirstUserRegistration, isRegistrationEnabled, authValidationService } from './chunk-
|
|
2
|
-
import { renderDocumentFormPage, renderAlert } from './chunk-
|
|
3
|
-
import { getCacheService, CACHE_CONFIGS, SettingsService, getLogger, getAppInstance, buildRouteList, CATEGORY_INFO } from './chunk-
|
|
4
|
-
import { DocumentTypeRegistry, requireAuth, requireRole, optionalAuth, isPluginActive, rateLimit, AuthManager, getJwtExpirySecondsFromDb, getJwtRefreshGraceSecondsFromDb, logActivity, generateCsrfToken } from './chunk-
|
|
5
|
-
import { DocumentsService, documentSecondsToMs, RbacService } from './chunk-
|
|
6
|
-
import { nanoid } from './chunk-
|
|
7
|
-
import { getCollectionRegistry, collectionRecordToRow, loadCollectionConfigs, getVisibleCollections, PluginService, PLUGIN_REGISTRY, findPluginByCodeName, isCodeCollectionInternal, isDbDocTypeInternal, invalidateTenantCache } from './chunk-
|
|
8
|
-
import { MigrationService } from './chunk-
|
|
9
|
-
import { renderCheckboxPage, renderAlert as renderAlert$1, renderTable, renderPagination, renderConfirmationDialog, getConfirmationDialogScript, renderAdminLayout, adminLayoutV2, renderForm } from './chunk-
|
|
10
|
-
import { init_admin_layout_catalyst_template, renderAdminLayoutCatalyst } from './chunk-
|
|
11
|
-
import { createServiceSingleton, definePlugin, getPluginDefinition, applySchemaDefaults, renderSchemaFields, parseFormDataToSettings } from './chunk-
|
|
1
|
+
import { isFirstUserRegistration, isRegistrationEnabled, authValidationService } from './chunk-VVYVFCML.js';
|
|
2
|
+
import { renderDocumentFormPage, renderAlert } from './chunk-RMRJGMDE.js';
|
|
3
|
+
import { getCacheService, CACHE_CONFIGS, SettingsService, getLogger, getAppInstance, buildRouteList, CATEGORY_INFO } from './chunk-2XAQTPAE.js';
|
|
4
|
+
import { DocumentTypeRegistry, requireAuth, requireRole, optionalAuth, isPluginActive, rateLimit, AuthManager, getJwtExpirySecondsFromDb, getJwtRefreshGraceSecondsFromDb, logActivity, generateCsrfToken } from './chunk-4UYJPHSV.js';
|
|
5
|
+
import { DocumentsService, documentSecondsToMs, RbacService } from './chunk-3TMTYJAJ.js';
|
|
6
|
+
import { nanoid } from './chunk-UWUP2VMT.js';
|
|
7
|
+
import { getCollectionRegistry, collectionRecordToRow, loadCollectionConfigs, getVisibleCollections, PluginService, PLUGIN_REGISTRY, findPluginByCodeName, isCodeCollectionInternal, isDbDocTypeInternal, invalidateTenantCache } from './chunk-4LVVMVQI.js';
|
|
8
|
+
import { MigrationService } from './chunk-5U75XP74.js';
|
|
9
|
+
import { renderCheckboxPage, renderAlert as renderAlert$1, renderTable, renderPagination, renderConfirmationDialog, getConfirmationDialogScript, renderAdminLayout, adminLayoutV2, renderForm } from './chunk-OBA2RYZN.js';
|
|
10
|
+
import { init_admin_layout_catalyst_template, renderAdminLayoutCatalyst } from './chunk-5V62WT6M.js';
|
|
11
|
+
import { createServiceSingleton, definePlugin, getPluginDefinition, applySchemaDefaults, renderSchemaFields, parseFormDataToSettings } from './chunk-7OTOXWEB.js';
|
|
12
12
|
import { hasHookSystem, getTypedHooks } from './chunk-RNZFGN4R.js';
|
|
13
13
|
import { QueryFilterBuilder, getBlocksFieldConfig, parseBlocksValue } from './chunk-QZGABF2M.js';
|
|
14
14
|
import { metricsTracker } from './chunk-FICTAGD4.js';
|
|
15
|
-
import { getCoreVersion } from './chunk-
|
|
15
|
+
import { getCoreVersion } from './chunk-JEX3UPZL.js';
|
|
16
16
|
import { escapeHtml, sanitizeRichText, sanitizeInput } from './chunk-TQABQWOP.js';
|
|
17
17
|
import { Hono } from 'hono';
|
|
18
18
|
import { z } from 'zod';
|
|
19
|
-
import { cors } from 'hono/cors';
|
|
20
19
|
import { setCookie, getCookie } from 'hono/cookie';
|
|
21
20
|
import { html, raw } from 'hono/html';
|
|
22
21
|
|
|
@@ -25,6 +24,7 @@ var DocumentPermissionsService = class {
|
|
|
25
24
|
constructor(db) {
|
|
26
25
|
this.db = db;
|
|
27
26
|
}
|
|
27
|
+
db;
|
|
28
28
|
// Deny wins. Overrides beat base grants. Empty ACL falls back to base grants.
|
|
29
29
|
async isAllowed(principalSet, rootId, permission, typeSettings, tenantId) {
|
|
30
30
|
const overrides = await this.getDocumentPermissions(rootId, principalSet, permission, tenantId);
|
|
@@ -133,6 +133,8 @@ var DocumentRepository = class {
|
|
|
133
133
|
this.tenantId = tenantId;
|
|
134
134
|
this.permissions = new DocumentPermissionsService(db);
|
|
135
135
|
}
|
|
136
|
+
db;
|
|
137
|
+
tenantId;
|
|
136
138
|
permissions;
|
|
137
139
|
// ─── Reads ───────────────────────────────────────────────────────────────
|
|
138
140
|
async getById(id) {
|
|
@@ -748,7 +750,7 @@ adminDocumentsRoutes.post("/types/:typeId/reindex", async (c) => {
|
|
|
748
750
|
const reindexTenant = effectiveTenantForType(getRequestTenant(c), docType.settings);
|
|
749
751
|
const reindexDenied = await denyIfNotAllowed(c, db, "", "manage", docType.settings, reindexTenant);
|
|
750
752
|
if (reindexDenied) return reindexDenied;
|
|
751
|
-
const { DocumentProjection } = await import('./document-projection-
|
|
753
|
+
const { DocumentProjection } = await import('./document-projection-4HG75S5S.js');
|
|
752
754
|
const projection = new DocumentProjection(db);
|
|
753
755
|
const rebuilt = await projection.reindexType(typeId, reindexTenant, docType.queryableFields);
|
|
754
756
|
return c.json({ rebuilt });
|
|
@@ -1260,16 +1262,6 @@ apiRoutes.use("*", async (c, next) => {
|
|
|
1260
1262
|
c.set("cacheEnabled", cacheEnabled);
|
|
1261
1263
|
await next();
|
|
1262
1264
|
});
|
|
1263
|
-
apiRoutes.use("*", cors({
|
|
1264
|
-
origin: (origin, c) => {
|
|
1265
|
-
const allowed = c.env?.CORS_ORIGINS;
|
|
1266
|
-
if (!allowed) return null;
|
|
1267
|
-
const list = allowed.split(",").map((s) => s.trim());
|
|
1268
|
-
return list.includes(origin) ? origin : null;
|
|
1269
|
-
},
|
|
1270
|
-
allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
|
|
1271
|
-
allowHeaders: ["Content-Type", "Authorization", "X-API-Key"]
|
|
1272
|
-
}));
|
|
1273
1265
|
function addTimingMeta(c, meta = {}, executionStartTime) {
|
|
1274
1266
|
const totalTime = Date.now() - c.get("startTime");
|
|
1275
1267
|
const executionTime = executionStartTime ? Date.now() - executionStartTime : void 0;
|
|
@@ -2202,6 +2194,8 @@ var MediaDocumentService = class {
|
|
|
2202
2194
|
this.db = db;
|
|
2203
2195
|
this.tenantId = tenantId;
|
|
2204
2196
|
}
|
|
2197
|
+
db;
|
|
2198
|
+
tenantId;
|
|
2205
2199
|
/** Create a media_asset document from R2 upload metadata. Published-on-create (immediately usable). */
|
|
2206
2200
|
async createFromUpload(meta, createdBy) {
|
|
2207
2201
|
const svc = new DocumentsService(this.db, { queryableFields: MEDIA_QUERYABLE, tenantId: this.tenantId, maxVersionsPerRoot: 5 });
|
|
@@ -2255,12 +2249,17 @@ var MediaDocumentService = class {
|
|
|
2255
2249
|
where.push("(json_extract(data, '$.filename') LIKE ? OR json_extract(data, '$.originalName') LIKE ? OR json_extract(data, '$.alt') LIKE ?)");
|
|
2256
2250
|
params.push(term, term, term);
|
|
2257
2251
|
}
|
|
2258
|
-
const listed = await
|
|
2252
|
+
const [listed, countResult] = await Promise.all([
|
|
2253
|
+
this.db.prepare(`SELECT * FROM documents WHERE ${where.join(" AND ")} ORDER BY updated_at DESC LIMIT ? OFFSET ?`).bind(...params, limit, offset).all(),
|
|
2254
|
+
this.db.prepare(`SELECT COUNT(*) AS total FROM documents WHERE ${where.join(" AND ")}`).bind(...params).first()
|
|
2255
|
+
]);
|
|
2259
2256
|
const files = (listed.results ?? []).map(rowToMinimalDoc);
|
|
2257
|
+
const total = countResult?.total ?? 0;
|
|
2260
2258
|
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();
|
|
2261
2259
|
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();
|
|
2262
2260
|
return {
|
|
2263
2261
|
files,
|
|
2262
|
+
total,
|
|
2264
2263
|
folders: (folderAgg.results ?? []).map((f) => ({ folder: f.folder, count: f.count, totalSize: f.totalSize ?? 0 })),
|
|
2265
2264
|
types: (typeAgg.results ?? []).map((t) => ({ type: t.type, count: t.count }))
|
|
2266
2265
|
};
|
|
@@ -3400,7 +3399,7 @@ adminApiRoutes.patch("/collections/:id", collectionsReadOnly);
|
|
|
3400
3399
|
adminApiRoutes.delete("/collections/:id", collectionsReadOnly);
|
|
3401
3400
|
adminApiRoutes.get("/migrations/status", async (c) => {
|
|
3402
3401
|
try {
|
|
3403
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
3402
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-HMX5SPN2.js');
|
|
3404
3403
|
const db = c.env.DB;
|
|
3405
3404
|
const migrationService = new MigrationService2(db);
|
|
3406
3405
|
const status = await migrationService.getMigrationStatus();
|
|
@@ -3443,7 +3442,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
|
|
|
3443
3442
|
});
|
|
3444
3443
|
adminApiRoutes.get("/migrations/validate", async (c) => {
|
|
3445
3444
|
try {
|
|
3446
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
3445
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-HMX5SPN2.js');
|
|
3447
3446
|
const db = c.env.DB;
|
|
3448
3447
|
const migrationService = new MigrationService2(db);
|
|
3449
3448
|
const validation = await migrationService.validateSchema();
|
|
@@ -3602,7 +3601,7 @@ function renderLoginPage(data, demoLoginActive = false) {
|
|
|
3602
3601
|
<!-- Form -->
|
|
3603
3602
|
<form
|
|
3604
3603
|
id="login-form"
|
|
3605
|
-
hx-post="/auth/login/form"
|
|
3604
|
+
hx-post="/auth/login/form${data.redirect ? `?redirect=${encodeURIComponent(data.redirect)}` : ""}"
|
|
3606
3605
|
hx-target="#form-response"
|
|
3607
3606
|
hx-swap="innerHTML"
|
|
3608
3607
|
class="space-y-6"
|
|
@@ -5590,6 +5589,79 @@ function renderDynamicField(field, options = {}) {
|
|
|
5590
5589
|
`;
|
|
5591
5590
|
break;
|
|
5592
5591
|
}
|
|
5592
|
+
case "json": {
|
|
5593
|
+
const jsonParsedValue = value !== null && value !== void 0 && typeof value !== "string" ? value : typeof value === "string" && value !== "" ? (() => {
|
|
5594
|
+
try {
|
|
5595
|
+
return JSON.parse(value);
|
|
5596
|
+
} catch {
|
|
5597
|
+
return value;
|
|
5598
|
+
}
|
|
5599
|
+
})() : null;
|
|
5600
|
+
const jsonDisplayValue = jsonParsedValue !== null && typeof jsonParsedValue !== "string" ? JSON.stringify(jsonParsedValue, null, 2) : typeof jsonParsedValue === "string" ? jsonParsedValue : "";
|
|
5601
|
+
const viewerId = `${fieldId}-viewer`;
|
|
5602
|
+
const textareaId = `${fieldId}-textarea`;
|
|
5603
|
+
const jsonDataAttr = escapeHtml2(JSON.stringify(jsonParsedValue ?? null));
|
|
5604
|
+
const isEmpty = jsonParsedValue === null || jsonDisplayValue === "";
|
|
5605
|
+
if (disabled) {
|
|
5606
|
+
fieldHTML = `
|
|
5607
|
+
<div
|
|
5608
|
+
id="${viewerId}"
|
|
5609
|
+
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"
|
|
5610
|
+
data-json-viewer
|
|
5611
|
+
data-json="${jsonDataAttr}"
|
|
5612
|
+
data-open="${opts.open ?? 2}"
|
|
5613
|
+
>${isEmpty ? '<span class="text-zinc-400 dark:text-zinc-500 italic">empty</span>' : ""}</div>
|
|
5614
|
+
${getJsonViewerScript()}
|
|
5615
|
+
`;
|
|
5616
|
+
} else {
|
|
5617
|
+
fieldHTML = `
|
|
5618
|
+
<div class="json-field-wrapper space-y-2">
|
|
5619
|
+
<div class="flex items-center justify-end">
|
|
5620
|
+
<button
|
|
5621
|
+
type="button"
|
|
5622
|
+
id="${fieldId}-toggle"
|
|
5623
|
+
class="text-xs text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-200 underline transition-colors"
|
|
5624
|
+
data-json-toggle
|
|
5625
|
+
data-viewer="${viewerId}"
|
|
5626
|
+
data-textarea="${textareaId}"
|
|
5627
|
+
data-hidden-input="${fieldId}"
|
|
5628
|
+
>Edit JSON</button>
|
|
5629
|
+
</div>
|
|
5630
|
+
|
|
5631
|
+
<div
|
|
5632
|
+
id="${viewerId}"
|
|
5633
|
+
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"
|
|
5634
|
+
data-json-viewer
|
|
5635
|
+
data-json="${jsonDataAttr}"
|
|
5636
|
+
data-open="${opts.open ?? 2}"
|
|
5637
|
+
>${isEmpty ? '<span class="text-zinc-400 dark:text-zinc-500 italic">empty \u2014 click "Edit JSON" to add data</span>' : ""}</div>
|
|
5638
|
+
|
|
5639
|
+
<textarea
|
|
5640
|
+
id="${textareaId}"
|
|
5641
|
+
rows="${opts.rows || 8}"
|
|
5642
|
+
placeholder="${opts.placeholder || "{}"}"
|
|
5643
|
+
class="${baseClasses} ${errorClasses} resize-y font-mono text-xs hidden"
|
|
5644
|
+
aria-label="${escapeHtml2(field.field_label)}"
|
|
5645
|
+
data-json-edit-area
|
|
5646
|
+
data-viewer="${viewerId}"
|
|
5647
|
+
data-hidden-input="${fieldId}"
|
|
5648
|
+
>${escapeHtml2(jsonDisplayValue)}</textarea>
|
|
5649
|
+
|
|
5650
|
+
<input
|
|
5651
|
+
type="hidden"
|
|
5652
|
+
id="${fieldId}"
|
|
5653
|
+
name="${fieldName}"
|
|
5654
|
+
value="${escapeHtml2(jsonDisplayValue)}"
|
|
5655
|
+
${required}
|
|
5656
|
+
>
|
|
5657
|
+
|
|
5658
|
+
<div id="${fieldId}-json-error" class="text-xs text-pink-500 dark:text-pink-400 hidden"></div>
|
|
5659
|
+
</div>
|
|
5660
|
+
${getJsonViewerScript()}
|
|
5661
|
+
`;
|
|
5662
|
+
}
|
|
5663
|
+
break;
|
|
5664
|
+
}
|
|
5593
5665
|
default:
|
|
5594
5666
|
fieldHTML = `
|
|
5595
5667
|
<input
|
|
@@ -6086,6 +6158,120 @@ function normalizeBlockField(fieldConfig, fieldName) {
|
|
|
6086
6158
|
options
|
|
6087
6159
|
};
|
|
6088
6160
|
}
|
|
6161
|
+
function getJsonViewerScript() {
|
|
6162
|
+
return `
|
|
6163
|
+
<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="">
|
|
6164
|
+
<script>
|
|
6165
|
+
(function() {
|
|
6166
|
+
var JS_URL = 'https://cdn.jsdelivr.net/npm/json-formatter-js@2.5.23/dist/json-formatter.umd.min.js';
|
|
6167
|
+
|
|
6168
|
+
function isDark() {
|
|
6169
|
+
return document.documentElement.classList.contains('dark') ||
|
|
6170
|
+
document.documentElement.dataset.theme === 'dark' ||
|
|
6171
|
+
window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
6172
|
+
}
|
|
6173
|
+
|
|
6174
|
+
function initViewer(el) {
|
|
6175
|
+
var raw = el.dataset.json;
|
|
6176
|
+
var open = parseInt(el.dataset.open || '2', 10);
|
|
6177
|
+
if (!raw || raw === 'null') return;
|
|
6178
|
+
var data;
|
|
6179
|
+
try { data = JSON.parse(raw); } catch(e) { el.textContent = raw; return; }
|
|
6180
|
+
var fmt = new JSONFormatter(data, open, {
|
|
6181
|
+
hoverPreviewEnabled: true,
|
|
6182
|
+
hoverPreviewArrayCount: 5,
|
|
6183
|
+
hoverPreviewFieldCount: 5,
|
|
6184
|
+
theme: isDark() ? 'dark' : '',
|
|
6185
|
+
animateOpen: true,
|
|
6186
|
+
animateClose: true,
|
|
6187
|
+
});
|
|
6188
|
+
el.innerHTML = '';
|
|
6189
|
+
el.appendChild(fmt.render());
|
|
6190
|
+
}
|
|
6191
|
+
|
|
6192
|
+
function initAllViewers() {
|
|
6193
|
+
document.querySelectorAll('[data-json-viewer]').forEach(function(el) { initViewer(el); });
|
|
6194
|
+
}
|
|
6195
|
+
|
|
6196
|
+
function ensureLoaded(cb) {
|
|
6197
|
+
if (window.JSONFormatter) { cb(); return; }
|
|
6198
|
+
if (window.__jsonFormatterCallbacks) { window.__jsonFormatterCallbacks.push(cb); return; }
|
|
6199
|
+
window.__jsonFormatterCallbacks = [cb];
|
|
6200
|
+
var s = document.createElement('script');
|
|
6201
|
+
s.src = JS_URL;
|
|
6202
|
+
s.onload = function() {
|
|
6203
|
+
(window.__jsonFormatterCallbacks || []).forEach(function(fn) { fn(); });
|
|
6204
|
+
window.__jsonFormatterCallbacks = null;
|
|
6205
|
+
};
|
|
6206
|
+
document.head.appendChild(s);
|
|
6207
|
+
}
|
|
6208
|
+
|
|
6209
|
+
if (!window.__sonicJsonViewerInit) {
|
|
6210
|
+
window.__sonicJsonViewerInit = true;
|
|
6211
|
+
|
|
6212
|
+
// Toggle between viewer and edit textarea
|
|
6213
|
+
document.addEventListener('click', function(e) {
|
|
6214
|
+
var btn = e.target.closest('[data-json-toggle]');
|
|
6215
|
+
if (!btn) return;
|
|
6216
|
+
var viewerId = btn.dataset.viewer;
|
|
6217
|
+
var textareaId = btn.dataset.textarea;
|
|
6218
|
+
var hiddenId = btn.dataset.hiddenInput;
|
|
6219
|
+
var viewer = document.getElementById(viewerId);
|
|
6220
|
+
var textarea = document.getElementById(textareaId);
|
|
6221
|
+
var hidden = document.getElementById(hiddenId);
|
|
6222
|
+
var errorEl = hidden ? document.getElementById(hiddenId + '-json-error') : null;
|
|
6223
|
+
if (!viewer || !textarea) return;
|
|
6224
|
+
var isEditing = !textarea.classList.contains('hidden');
|
|
6225
|
+
if (isEditing) {
|
|
6226
|
+
// Switching back to viewer \u2014 validate + refresh
|
|
6227
|
+
var raw = textarea.value.trim();
|
|
6228
|
+
if (raw) {
|
|
6229
|
+
try {
|
|
6230
|
+
var parsed = JSON.parse(raw);
|
|
6231
|
+
if (hidden) hidden.value = raw;
|
|
6232
|
+
viewer.dataset.json = JSON.stringify(parsed);
|
|
6233
|
+
ensureLoaded(function() { initViewer(viewer); });
|
|
6234
|
+
if (errorEl) { errorEl.textContent = ''; errorEl.classList.add('hidden'); }
|
|
6235
|
+
} catch(ex) {
|
|
6236
|
+
if (errorEl) { errorEl.textContent = 'Invalid JSON: ' + ex.message; errorEl.classList.remove('hidden'); }
|
|
6237
|
+
return;
|
|
6238
|
+
}
|
|
6239
|
+
} else {
|
|
6240
|
+
if (hidden) hidden.value = '';
|
|
6241
|
+
viewer.innerHTML = '<span class="text-zinc-400 dark:text-zinc-500 italic">empty</span>';
|
|
6242
|
+
}
|
|
6243
|
+
textarea.classList.add('hidden');
|
|
6244
|
+
viewer.classList.remove('hidden');
|
|
6245
|
+
btn.textContent = 'Edit JSON';
|
|
6246
|
+
} else {
|
|
6247
|
+
// Switching to edit \u2014 populate textarea from hidden input
|
|
6248
|
+
if (hidden && hidden.value) {
|
|
6249
|
+
try {
|
|
6250
|
+
textarea.value = JSON.stringify(JSON.parse(hidden.value), null, 2);
|
|
6251
|
+
} catch(e) {
|
|
6252
|
+
textarea.value = hidden.value;
|
|
6253
|
+
}
|
|
6254
|
+
}
|
|
6255
|
+
viewer.classList.add('hidden');
|
|
6256
|
+
textarea.classList.remove('hidden');
|
|
6257
|
+
btn.textContent = 'Preview';
|
|
6258
|
+
}
|
|
6259
|
+
});
|
|
6260
|
+
}
|
|
6261
|
+
|
|
6262
|
+
function run() {
|
|
6263
|
+
ensureLoaded(initAllViewers);
|
|
6264
|
+
}
|
|
6265
|
+
|
|
6266
|
+
if (document.readyState === 'loading') {
|
|
6267
|
+
document.addEventListener('DOMContentLoaded', run);
|
|
6268
|
+
} else {
|
|
6269
|
+
run();
|
|
6270
|
+
}
|
|
6271
|
+
})();
|
|
6272
|
+
</script>
|
|
6273
|
+
`;
|
|
6274
|
+
}
|
|
6089
6275
|
function getStructuredFieldScript() {
|
|
6090
6276
|
return `
|
|
6091
6277
|
${getReadFieldValueScript()}
|
|
@@ -6946,10 +7132,12 @@ var authRoutes = new Hono();
|
|
|
6946
7132
|
authRoutes.get("/login", async (c) => {
|
|
6947
7133
|
const error = c.req.query("error");
|
|
6948
7134
|
const message = c.req.query("message");
|
|
7135
|
+
const redirect = c.req.query("redirect");
|
|
6949
7136
|
const pageData = {
|
|
6950
7137
|
error: error || void 0,
|
|
6951
7138
|
message: message || void 0,
|
|
6952
|
-
version: c.get("appVersion")
|
|
7139
|
+
version: c.get("appVersion"),
|
|
7140
|
+
redirect: redirect && redirect.startsWith("/") ? redirect : void 0
|
|
6953
7141
|
};
|
|
6954
7142
|
const db = c.env.DB;
|
|
6955
7143
|
let demoLoginActive = false;
|
|
@@ -7093,7 +7281,7 @@ authRoutes.post(
|
|
|
7093
7281
|
}
|
|
7094
7282
|
const { email, password } = validation.data;
|
|
7095
7283
|
const normalizedEmail = email.toLowerCase();
|
|
7096
|
-
const { createAuth } = await import('./config-
|
|
7284
|
+
const { createAuth } = await import('./config-6FB2BXMP.js');
|
|
7097
7285
|
const auth = createAuth(c.env);
|
|
7098
7286
|
const baReq = new Request(new URL("/auth/sign-in/email", c.req.url).href, {
|
|
7099
7287
|
method: "POST",
|
|
@@ -7115,6 +7303,20 @@ authRoutes.post(
|
|
|
7115
7303
|
await setCsrfCookie(c);
|
|
7116
7304
|
const baBody = await baRes.json();
|
|
7117
7305
|
const user = baBody.user ?? {};
|
|
7306
|
+
const tokenTtl = await getJwtExpirySecondsFromDb(c.env.DB, c.env);
|
|
7307
|
+
const token = await AuthManager.generateToken(
|
|
7308
|
+
user.id,
|
|
7309
|
+
user.email,
|
|
7310
|
+
user.role ?? "viewer",
|
|
7311
|
+
c.env.JWT_SECRET,
|
|
7312
|
+
tokenTtl
|
|
7313
|
+
);
|
|
7314
|
+
setCookie(c, "auth_token", token, {
|
|
7315
|
+
httpOnly: true,
|
|
7316
|
+
secure: true,
|
|
7317
|
+
sameSite: "Strict",
|
|
7318
|
+
maxAge: tokenTtl
|
|
7319
|
+
});
|
|
7118
7320
|
return c.json({
|
|
7119
7321
|
user: {
|
|
7120
7322
|
id: user.id,
|
|
@@ -7122,7 +7324,8 @@ authRoutes.post(
|
|
|
7122
7324
|
firstName: user.name?.split(" ")[0] ?? "",
|
|
7123
7325
|
lastName: user.name?.split(" ").slice(1).join(" ") ?? "",
|
|
7124
7326
|
role: user.role ?? "viewer"
|
|
7125
|
-
}
|
|
7327
|
+
},
|
|
7328
|
+
token
|
|
7126
7329
|
});
|
|
7127
7330
|
} catch (error) {
|
|
7128
7331
|
console.error("Login error:", error);
|
|
@@ -7132,7 +7335,7 @@ authRoutes.post(
|
|
|
7132
7335
|
);
|
|
7133
7336
|
authRoutes.post("/logout", async (c) => {
|
|
7134
7337
|
try {
|
|
7135
|
-
const { createAuth } = await import('./config-
|
|
7338
|
+
const { createAuth } = await import('./config-6FB2BXMP.js');
|
|
7136
7339
|
const auth = createAuth(c.env);
|
|
7137
7340
|
const baReq = new Request(new URL("/auth/sign-out", c.req.url).href, {
|
|
7138
7341
|
method: "POST",
|
|
@@ -7148,7 +7351,7 @@ authRoutes.post("/logout", async (c) => {
|
|
|
7148
7351
|
});
|
|
7149
7352
|
authRoutes.get("/logout", async (c) => {
|
|
7150
7353
|
try {
|
|
7151
|
-
const { createAuth } = await import('./config-
|
|
7354
|
+
const { createAuth } = await import('./config-6FB2BXMP.js');
|
|
7152
7355
|
const auth = createAuth(c.env);
|
|
7153
7356
|
const baReq = new Request(new URL("/auth/sign-out", c.req.url).href, {
|
|
7154
7357
|
method: "POST",
|
|
@@ -7355,7 +7558,7 @@ authRoutes.post(
|
|
|
7355
7558
|
</div>
|
|
7356
7559
|
`);
|
|
7357
7560
|
}
|
|
7358
|
-
const { createAuth } = await import('./config-
|
|
7561
|
+
const { createAuth } = await import('./config-6FB2BXMP.js');
|
|
7359
7562
|
const auth = createAuth(c.env);
|
|
7360
7563
|
const baReq = new Request(new URL("/auth/sign-in/email", c.req.url).href, {
|
|
7361
7564
|
method: "POST",
|
|
@@ -7379,6 +7582,8 @@ authRoutes.post(
|
|
|
7379
7582
|
}
|
|
7380
7583
|
}
|
|
7381
7584
|
await setCsrfCookie(c);
|
|
7585
|
+
const rawRedirect = c.req.query("redirect");
|
|
7586
|
+
const redirectUrl = rawRedirect && rawRedirect.startsWith("/") ? rawRedirect : "/admin/content";
|
|
7382
7587
|
return c.html(html`
|
|
7383
7588
|
<div id="form-response">
|
|
7384
7589
|
<div class="rounded-lg bg-green-100 dark:bg-lime-500/10 p-4 ring-1 ring-green-400 dark:ring-lime-500/20">
|
|
@@ -7391,7 +7596,7 @@ authRoutes.post(
|
|
|
7391
7596
|
</div>
|
|
7392
7597
|
</div>
|
|
7393
7598
|
<script>
|
|
7394
|
-
setTimeout(() => { window.location.href = '
|
|
7599
|
+
setTimeout(() => { window.location.href = '${redirectUrl}'; }, 500);
|
|
7395
7600
|
</script>
|
|
7396
7601
|
</div>
|
|
7397
7602
|
</div>
|
|
@@ -12866,7 +13071,7 @@ adminContentRoutes.post("/documents/:typeId/:documentId/delete", async (c) => {
|
|
|
12866
13071
|
adminContentRoutes.get("/documents/:typeId/:rootId/versions", async (c) => {
|
|
12867
13072
|
const { typeId, rootId } = c.req.param();
|
|
12868
13073
|
const db = c.env.DB;
|
|
12869
|
-
const { renderVersionHistoryFragment } = await import('./admin-documents-form.template-
|
|
13074
|
+
const { renderVersionHistoryFragment } = await import('./admin-documents-form.template-DDSH6ROU.js');
|
|
12870
13075
|
const registry = new DocumentTypeRegistry(db);
|
|
12871
13076
|
const docType = await registry.findById(typeId);
|
|
12872
13077
|
if (!docType) return c.html("<div>Unknown type.</div>", 404);
|
|
@@ -14739,6 +14944,7 @@ var TenantService = class {
|
|
|
14739
14944
|
constructor(db) {
|
|
14740
14945
|
this.db = db;
|
|
14741
14946
|
}
|
|
14947
|
+
db;
|
|
14742
14948
|
async listTenants() {
|
|
14743
14949
|
const { results } = await this.db.prepare(`
|
|
14744
14950
|
SELECT * FROM auth_tenant
|
|
@@ -17614,7 +17820,7 @@ adminMediaRoutes.get("/", async (c) => {
|
|
|
17614
17820
|
const limit = 24;
|
|
17615
17821
|
const offset = (page - 1) * limit;
|
|
17616
17822
|
const mediaSvc = new MediaDocumentService(c.env.DB, getRequestTenant(c));
|
|
17617
|
-
const { files, folders: folderAgg, types: typeAgg } = await mediaSvc.list({ folder, type, limit, offset });
|
|
17823
|
+
const { files, total, folders: folderAgg, types: typeAgg } = await mediaSvc.list({ folder, type, limit, offset });
|
|
17618
17824
|
const mediaFiles = files.map((doc) => mediaDocToFile(doc));
|
|
17619
17825
|
const pageData = {
|
|
17620
17826
|
files: mediaFiles,
|
|
@@ -17624,8 +17830,8 @@ adminMediaRoutes.get("/", async (c) => {
|
|
|
17624
17830
|
currentType: type,
|
|
17625
17831
|
currentView: view,
|
|
17626
17832
|
currentPage: page,
|
|
17627
|
-
totalFiles:
|
|
17628
|
-
hasNextPage: mediaFiles.length
|
|
17833
|
+
totalFiles: total,
|
|
17834
|
+
hasNextPage: offset + mediaFiles.length < total,
|
|
17629
17835
|
user: {
|
|
17630
17836
|
name: user.email,
|
|
17631
17837
|
email: user.email,
|
|
@@ -17665,12 +17871,14 @@ adminMediaRoutes.get("/selector", async (c) => {
|
|
|
17665
17871
|
<input
|
|
17666
17872
|
type="search"
|
|
17667
17873
|
id="media-selector-search"
|
|
17874
|
+
name="search"
|
|
17668
17875
|
placeholder="Search files..."
|
|
17669
17876
|
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"
|
|
17670
17877
|
hx-get="/admin/media/selector"
|
|
17671
17878
|
hx-trigger="keyup changed delay:300ms"
|
|
17672
17879
|
hx-target="#media-selector-grid"
|
|
17673
|
-
hx-
|
|
17880
|
+
hx-swap="outerHTML"
|
|
17881
|
+
hx-select="#media-selector-grid"
|
|
17674
17882
|
>
|
|
17675
17883
|
</div>
|
|
17676
17884
|
|
|
@@ -19137,6 +19345,8 @@ function escapeHtmlAttr(value) {
|
|
|
19137
19345
|
}
|
|
19138
19346
|
function renderPluginSettingsPage(data) {
|
|
19139
19347
|
const { plugin, activity = [], user } = data;
|
|
19348
|
+
const hasUserSettings = Object.keys(plugin.settings || {}).some((k) => !k.startsWith("_"));
|
|
19349
|
+
const defaultTab = hasUserSettings ? "settings" : "info";
|
|
19140
19350
|
const pageContent = `
|
|
19141
19351
|
<div class="w-full px-4 sm:px-6 lg:px-8 py-6">
|
|
19142
19352
|
<!-- Header with Back Button -->
|
|
@@ -19147,13 +19357,24 @@ function renderPluginSettingsPage(data) {
|
|
|
19147
19357
|
${plugin.description}
|
|
19148
19358
|
</p>
|
|
19149
19359
|
</div>
|
|
19150
|
-
<div class="mt-4 sm:mt-0 sm:ml-16
|
|
19360
|
+
<div class="mt-4 sm:mt-0 sm:ml-16 flex items-center gap-3">
|
|
19151
19361
|
<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">
|
|
19152
19362
|
<svg class="-ml-0.5 mr-1.5 h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
19153
19363
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/>
|
|
19154
19364
|
</svg>
|
|
19155
19365
|
Back to Plugins
|
|
19156
19366
|
</a>
|
|
19367
|
+
${plugin.settings?._adminPath ? `
|
|
19368
|
+
<a
|
|
19369
|
+
href="${plugin.settings._adminPath}"
|
|
19370
|
+
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"
|
|
19371
|
+
>
|
|
19372
|
+
<svg class="-ml-0.5 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
19373
|
+
<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"/>
|
|
19374
|
+
</svg>
|
|
19375
|
+
View Page
|
|
19376
|
+
</a>
|
|
19377
|
+
` : ""}
|
|
19157
19378
|
</div>
|
|
19158
19379
|
</div>
|
|
19159
19380
|
|
|
@@ -19186,23 +19407,25 @@ function renderPluginSettingsPage(data) {
|
|
|
19186
19407
|
<!-- Tabs -->
|
|
19187
19408
|
<div class="mb-6">
|
|
19188
19409
|
<nav class="flex space-x-8" aria-label="Tabs">
|
|
19189
|
-
|
|
19410
|
+
${hasUserSettings ? `
|
|
19411
|
+
<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">
|
|
19190
19412
|
Settings
|
|
19191
|
-
</
|
|
19192
|
-
|
|
19193
|
-
|
|
19194
|
-
</button>
|
|
19195
|
-
<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">
|
|
19413
|
+
</a>
|
|
19414
|
+
` : ""}
|
|
19415
|
+
<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">
|
|
19196
19416
|
Information
|
|
19197
|
-
</
|
|
19417
|
+
</a>
|
|
19418
|
+
<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">
|
|
19419
|
+
Activity Log
|
|
19420
|
+
</a>
|
|
19198
19421
|
</nav>
|
|
19199
19422
|
</div>
|
|
19200
19423
|
|
|
19201
19424
|
<!-- Tab Content -->
|
|
19202
19425
|
<div id="tab-content">
|
|
19203
19426
|
<!-- Settings Tab -->
|
|
19204
|
-
<div id="settings-content" class="tab-content">
|
|
19205
|
-
${renderSettingsTab(plugin)}
|
|
19427
|
+
<div id="settings-content" class="tab-content hidden">
|
|
19428
|
+
${hasUserSettings ? renderSettingsTab(plugin) : ""}
|
|
19206
19429
|
</div>
|
|
19207
19430
|
|
|
19208
19431
|
<!-- Activity Tab -->
|
|
@@ -19218,27 +19441,42 @@ function renderPluginSettingsPage(data) {
|
|
|
19218
19441
|
</div>
|
|
19219
19442
|
|
|
19220
19443
|
<script>
|
|
19444
|
+
const VALID_TABS = [${hasUserSettings ? "'settings', " : ""}'activity', 'info'];
|
|
19445
|
+
|
|
19221
19446
|
function showTab(tabName) {
|
|
19222
|
-
|
|
19447
|
+
if (!VALID_TABS.includes(tabName)) tabName = '${defaultTab}';
|
|
19448
|
+
|
|
19223
19449
|
document.querySelectorAll('.tab-content').forEach(content => {
|
|
19224
19450
|
content.classList.add('hidden');
|
|
19225
19451
|
});
|
|
19226
|
-
|
|
19227
|
-
// Remove active class from all tabs
|
|
19452
|
+
|
|
19228
19453
|
document.querySelectorAll('.tab-button').forEach(tab => {
|
|
19229
19454
|
tab.classList.remove('active', 'border-blue-400', 'text-blue-400');
|
|
19230
19455
|
tab.classList.add('border-transparent', 'text-gray-400');
|
|
19231
19456
|
});
|
|
19232
|
-
|
|
19233
|
-
|
|
19234
|
-
|
|
19235
|
-
|
|
19236
|
-
// Add active class to selected tab
|
|
19457
|
+
|
|
19458
|
+
const contentEl = document.getElementById(tabName + '-content');
|
|
19459
|
+
if (contentEl) contentEl.classList.remove('hidden');
|
|
19460
|
+
|
|
19237
19461
|
const activeTab = document.getElementById(tabName + '-tab');
|
|
19238
|
-
activeTab
|
|
19239
|
-
|
|
19462
|
+
if (activeTab) {
|
|
19463
|
+
activeTab.classList.add('active', 'border-blue-400', 'text-blue-400');
|
|
19464
|
+
activeTab.classList.remove('border-transparent', 'text-gray-400');
|
|
19465
|
+
}
|
|
19466
|
+
|
|
19467
|
+
if (window.location.hash !== '#' + tabName) {
|
|
19468
|
+
history.replaceState(null, '', '#' + tabName);
|
|
19469
|
+
}
|
|
19470
|
+
}
|
|
19471
|
+
|
|
19472
|
+
function initTabFromHash() {
|
|
19473
|
+
const hash = window.location.hash.replace('#', '');
|
|
19474
|
+
showTab(VALID_TABS.includes(hash) ? hash : '${defaultTab}');
|
|
19240
19475
|
}
|
|
19241
19476
|
|
|
19477
|
+
window.addEventListener('hashchange', initTabFromHash);
|
|
19478
|
+
initTabFromHash();
|
|
19479
|
+
|
|
19242
19480
|
async function togglePlugin(pluginId, action) {
|
|
19243
19481
|
const button = event.target;
|
|
19244
19482
|
const originalText = button.textContent;
|
|
@@ -19411,6 +19649,7 @@ function renderToggleButton(plugin) {
|
|
|
19411
19649
|
function renderSettingsTab(plugin) {
|
|
19412
19650
|
const settings = plugin.settings || {};
|
|
19413
19651
|
const pluginId = plugin.id || plugin.name;
|
|
19652
|
+
const hasUserKeys = Object.keys(settings).some((k) => !k.startsWith("_"));
|
|
19414
19653
|
const customRenderer = pluginSettingsComponents[pluginId];
|
|
19415
19654
|
if (customRenderer) {
|
|
19416
19655
|
return `
|
|
@@ -19446,9 +19685,9 @@ function renderSettingsTab(plugin) {
|
|
|
19446
19685
|
`}
|
|
19447
19686
|
|
|
19448
19687
|
<form id="settings-form" class="space-y-6">
|
|
19449
|
-
${isAuthPlugin &&
|
|
19688
|
+
${isAuthPlugin && hasUserKeys ? renderAuthSettingsForm(settings) : isTurnstilePlugin && hasUserKeys ? renderTurnstileSettingsForm(settings) : hasUserKeys ? renderSettingsFields(settings) : renderNoSettings(plugin)}
|
|
19450
19689
|
|
|
19451
|
-
${
|
|
19690
|
+
${hasUserKeys ? `
|
|
19452
19691
|
<div class="flex items-center justify-end pt-6 border-t border-white/10">
|
|
19453
19692
|
<button
|
|
19454
19693
|
type="button"
|
|
@@ -19465,7 +19704,7 @@ function renderSettingsTab(plugin) {
|
|
|
19465
19704
|
`;
|
|
19466
19705
|
}
|
|
19467
19706
|
function renderSettingsFields(settings) {
|
|
19468
|
-
return Object.entries(settings).map(([key, value]) => {
|
|
19707
|
+
return Object.entries(settings).filter(([key]) => !key.startsWith("_")).map(([key, value]) => {
|
|
19469
19708
|
const fieldId = `setting_${key}`;
|
|
19470
19709
|
const displayName = key.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase());
|
|
19471
19710
|
if (typeof value === "boolean") {
|
|
@@ -19654,6 +19893,38 @@ function renderActivityTab(activity) {
|
|
|
19654
19893
|
}
|
|
19655
19894
|
function renderInformationTab(plugin) {
|
|
19656
19895
|
return `
|
|
19896
|
+
${plugin.description ? `
|
|
19897
|
+
<!-- About -->
|
|
19898
|
+
<div class="backdrop-blur-md bg-black/20 rounded-xl border border-white/10 shadow-xl p-6 mb-6">
|
|
19899
|
+
<h2 class="text-xl font-semibold text-white mb-3">About</h2>
|
|
19900
|
+
<p class="text-gray-300 leading-relaxed">${plugin.description}</p>
|
|
19901
|
+
</div>
|
|
19902
|
+
` : ""}
|
|
19903
|
+
|
|
19904
|
+
${(plugin.settings?._routes?.length ?? 0) > 0 ? `
|
|
19905
|
+
<!-- Routes -->
|
|
19906
|
+
<div class="backdrop-blur-md bg-black/20 rounded-xl border border-white/10 shadow-xl p-6 mb-6">
|
|
19907
|
+
<h2 class="text-xl font-semibold text-white mb-4">Routes</h2>
|
|
19908
|
+
<div class="space-y-2">
|
|
19909
|
+
${plugin.settings._routes.map((r) => {
|
|
19910
|
+
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";
|
|
19911
|
+
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>`;
|
|
19912
|
+
const authBadge = r.requiresAuth ? `<span class="ml-2 text-xs text-amber-400/80">\u{1F512} auth</span>` : "";
|
|
19913
|
+
return `
|
|
19914
|
+
<div class="flex items-start gap-3 py-2 border-b border-white/5 last:border-0">
|
|
19915
|
+
<span class="shrink-0 inline-block px-2 py-0.5 rounded text-xs font-bold ${badge}">${r.method}</span>
|
|
19916
|
+
<div class="min-w-0">
|
|
19917
|
+
<div class="flex items-center gap-1 flex-wrap">
|
|
19918
|
+
${pathHtml}${authBadge}
|
|
19919
|
+
</div>
|
|
19920
|
+
${r.description ? `<p class="text-xs text-gray-400 mt-0.5">${r.description}</p>` : ""}
|
|
19921
|
+
</div>
|
|
19922
|
+
</div>`;
|
|
19923
|
+
}).join("")}
|
|
19924
|
+
</div>
|
|
19925
|
+
</div>
|
|
19926
|
+
` : ""}
|
|
19927
|
+
|
|
19657
19928
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
19658
19929
|
<!-- Plugin Details -->
|
|
19659
19930
|
<div class="backdrop-blur-md bg-black/20 rounded-xl border border-white/10 shadow-xl p-6">
|
|
@@ -20684,7 +20955,9 @@ adminPluginRoutes.post("/:id/configure", async (c) => {
|
|
|
20684
20955
|
description: def.description,
|
|
20685
20956
|
author: typeof def.author === "object" ? def.author?.name : def.author
|
|
20686
20957
|
});
|
|
20687
|
-
await pluginService.
|
|
20958
|
+
const existingPlugin = await pluginService.getPlugin(pluginId);
|
|
20959
|
+
const existingSettings = existingPlugin?.settings ?? {};
|
|
20960
|
+
await pluginService.updatePluginSettings(pluginId, { ...existingSettings, ...parsed });
|
|
20688
20961
|
return c.redirect(`/admin/plugins/${encodeURIComponent(pluginId)}/configure`);
|
|
20689
20962
|
} catch (error) {
|
|
20690
20963
|
console.error("Error saving schema settings:", error);
|
|
@@ -20786,7 +21059,9 @@ adminPluginRoutes.post("/:id/settings", async (c) => {
|
|
|
20786
21059
|
}
|
|
20787
21060
|
const settings = await c.req.json();
|
|
20788
21061
|
const pluginService = new PluginService(db);
|
|
20789
|
-
await pluginService.
|
|
21062
|
+
const existingPlugin = await pluginService.getPlugin(pluginId);
|
|
21063
|
+
const existingSettings = existingPlugin?.settings ?? {};
|
|
21064
|
+
await pluginService.updatePluginSettings(pluginId, { ...existingSettings, ...settings });
|
|
20790
21065
|
if (pluginId === "core-auth") {
|
|
20791
21066
|
try {
|
|
20792
21067
|
const cacheKv = c.env.CACHE_KV;
|
|
@@ -26638,6 +26913,6 @@ var ROUTES_INFO = {
|
|
|
26638
26913
|
reference: "https://github.com/sonicjs/sonicjs"
|
|
26639
26914
|
};
|
|
26640
26915
|
|
|
26641
|
-
export { DocumentRepository, ROUTES_INFO, TenantService, VALID_MEMBER_ROLES, adminCheckboxRoutes, adminCollectionsRoutes, adminDocumentsRoutes, adminLogsRoutes, adminMediaRoutes, adminPluginRoutes, adminSettingsRoutes, admin_api_default, admin_content_default, apiDocumentsRoutes, api_content_crud_default, api_default, api_media_default, api_system_default, auth_default, createUserProfilesPlugin, defineUserProfile, denyIfNotAllowed, dispatchHookEvent, getConfirmationDialogScript2 as getConfirmationDialogScript, getCustomData, getEmailService, getUserProfileConfig, getVariablesCached, hasEmailService, invalidateVariablesCache, isValidMemberRole, lexicalEditorPlugin, renderConfirmationDialog2 as renderConfirmationDialog, renderTable2 as renderTable, resolveDocScope, resolveVariablesInObject, router, router2, setEmailService, setVariablesCache, test_cleanup_default, userProfilesPlugin, userRoutes };
|
|
26642
|
-
//# sourceMappingURL=chunk-
|
|
26643
|
-
//# sourceMappingURL=chunk-
|
|
26916
|
+
export { DocumentRepository, ROUTES_INFO, TenantService, VALID_MEMBER_ROLES, adminCheckboxRoutes, adminCollectionsRoutes, adminDocumentsRoutes, adminLogsRoutes, adminMediaRoutes, adminPluginRoutes, adminSettingsRoutes, admin_api_default, admin_content_default, apiDocumentsRoutes, api_content_crud_default, api_default, api_media_default, api_system_default, auth_default, createDocumentSchema, createUserProfilesPlugin, defineUserProfile, denyIfNotAllowed, dispatchHookEvent, getConfirmationDialogScript2 as getConfirmationDialogScript, getCustomData, getEmailService, getUserProfileConfig, getVariablesCached, hasEmailService, invalidateVariablesCache, isValidMemberRole, lexicalEditorPlugin, renderConfirmationDialog2 as renderConfirmationDialog, renderTable2 as renderTable, resolveDocScope, resolveVariablesInObject, router, router2, setEmailService, setVariablesCache, test_cleanup_default, userProfilesPlugin, userRoutes };
|
|
26917
|
+
//# sourceMappingURL=chunk-ZP77LTN4.js.map
|
|
26918
|
+
//# sourceMappingURL=chunk-ZP77LTN4.js.map
|