@dyrected/core 2.5.44 → 2.5.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.js CHANGED
@@ -13,14 +13,14 @@ import {
13
13
  runCollectionHooks,
14
14
  saveWorkflowDraft,
15
15
  transitionWorkflow
16
- } from "./chunk-44O2LDPT.js";
16
+ } from "./chunk-FCXE5CVC.js";
17
17
 
18
- // src/app.js
18
+ // src/app.ts
19
19
  import { Hono } from "hono";
20
20
  import { cors } from "hono/cors";
21
21
  import { requestId } from "hono/request-id";
22
22
 
23
- // src/services/defaults.service.js
23
+ // src/services/defaults.service.ts
24
24
  var DefaultsService = class {
25
25
  /**
26
26
  * Recursively apply default values to a data object based on field definitions.
@@ -28,14 +28,12 @@ var DefaultsService = class {
28
28
  static apply(fields, data = {}) {
29
29
  const result = { ...data || {} };
30
30
  fields.forEach((field) => {
31
- if (field.type === "join")
32
- return;
31
+ if (field.type === "join") return;
33
32
  if (field.type === "row" && field.fields) {
34
33
  Object.assign(result, this.apply(field.fields, data));
35
34
  return;
36
35
  }
37
- if (!field.name)
38
- return;
36
+ if (!field.name) return;
39
37
  let value = result[field.name];
40
38
  if ((value === void 0 || value === null) && field.renameTo) {
41
39
  const legacyValue = result[field.renameTo];
@@ -48,12 +46,9 @@ var DefaultsService = class {
48
46
  if (field.defaultValue !== void 0) {
49
47
  result[field.name] = field.defaultValue;
50
48
  } else {
51
- if (field.type === "boolean")
52
- result[field.name] = false;
53
- else if (field.type === "array")
54
- result[field.name] = [];
55
- else if (field.type === "multiSelect")
56
- result[field.name] = [];
49
+ if (field.type === "boolean") result[field.name] = false;
50
+ else if (field.type === "array") result[field.name] = [];
51
+ else if (field.type === "multiSelect") result[field.name] = [];
57
52
  else if (field.type === "object") {
58
53
  result[field.name] = this.apply(field.fields || [], {});
59
54
  }
@@ -68,7 +63,7 @@ var DefaultsService = class {
68
63
  }
69
64
  };
70
65
 
71
- // src/services/population.service.js
66
+ // src/services/population.service.ts
72
67
  var PopulationService = class {
73
68
  db;
74
69
  collections;
@@ -121,31 +116,29 @@ var PopulationService = class {
121
116
  Object.assign(populatedDoc, rowPopulated);
122
117
  continue;
123
118
  }
124
- if (!field.name)
125
- continue;
119
+ if (!field.name) continue;
126
120
  const value = populatedDoc[field.name];
127
121
  if (field.type === "relationship" && field.relationTo && value) {
128
122
  const relatedCollection = this.collections.find((c) => c.slug === field.relationTo);
129
- if (!relatedCollection)
130
- continue;
123
+ if (!relatedCollection) continue;
131
124
  if (Array.isArray(value)) {
132
- populatedDoc[field.name] = await Promise.all(value.map(async (id) => {
133
- if (!id)
134
- return id;
135
- let doc = id;
136
- if (typeof id === "string") {
137
- doc = await this.db.findOne({ collection: field.relationTo, id });
138
- }
139
- if (!doc || typeof doc !== "object")
140
- return id;
141
- const docWithDefaults = DefaultsService.apply(relatedCollection.fields, doc);
142
- return this.populate({
143
- data: docWithDefaults,
144
- fields: relatedCollection.fields,
145
- currentDepth: currentDepth + 1,
146
- maxDepth
147
- });
148
- }));
125
+ populatedDoc[field.name] = await Promise.all(
126
+ value.map(async (id) => {
127
+ if (!id) return id;
128
+ let doc = id;
129
+ if (typeof id === "string") {
130
+ doc = await this.db.findOne({ collection: field.relationTo, id });
131
+ }
132
+ if (!doc || typeof doc !== "object") return id;
133
+ const docWithDefaults = DefaultsService.apply(relatedCollection.fields, doc);
134
+ return this.populate({
135
+ data: docWithDefaults,
136
+ fields: relatedCollection.fields,
137
+ currentDepth: currentDepth + 1,
138
+ maxDepth
139
+ });
140
+ })
141
+ );
149
142
  } else if (value) {
150
143
  let doc = value;
151
144
  if (typeof value === "string") {
@@ -194,17 +187,18 @@ var PopulationService = class {
194
187
  });
195
188
  }
196
189
  if (field.type === "blocks" && field.blocks && Array.isArray(value)) {
197
- populatedDoc[field.name] = await Promise.all(value.map(async (blockData) => {
198
- const blockConfig = field.blocks.find((b) => b.slug === blockData.blockType);
199
- if (!blockConfig)
200
- return blockData;
201
- return this.populate({
202
- data: blockData,
203
- fields: blockConfig.fields,
204
- currentDepth,
205
- maxDepth
206
- });
207
- }));
190
+ populatedDoc[field.name] = await Promise.all(
191
+ value.map(async (blockData) => {
192
+ const blockConfig = field.blocks.find((b) => b.slug === blockData.blockType);
193
+ if (!blockConfig) return blockData;
194
+ return this.populate({
195
+ data: blockData,
196
+ fields: blockConfig.fields,
197
+ currentDepth,
198
+ maxDepth
199
+ });
200
+ })
201
+ );
208
202
  }
209
203
  }
210
204
  return populatedDoc;
@@ -213,8 +207,7 @@ var PopulationService = class {
213
207
  * Helper to populate a PaginatedResult
214
208
  */
215
209
  async populateResult(result, fields, maxDepth) {
216
- if (maxDepth <= 0)
217
- return result;
210
+ if (maxDepth <= 0) return result;
218
211
  const populatedDocs = await this.populate({
219
212
  data: result.docs,
220
213
  fields,
@@ -228,7 +221,7 @@ var PopulationService = class {
228
221
  }
229
222
  };
230
223
 
231
- // src/services/audit.service.js
224
+ // src/services/audit.service.ts
232
225
  var AuditService = class {
233
226
  /**
234
227
  * Writes a single entry to the __audit collection.
@@ -256,7 +249,7 @@ var AuditService = class {
256
249
  }
257
250
  };
258
251
 
259
- // src/auth/password.js
252
+ // src/auth/password.ts
260
253
  import { promisify } from "util";
261
254
  import { scrypt, randomBytes, timingSafeEqual } from "crypto";
262
255
  var scryptAsync = promisify(scrypt);
@@ -269,23 +262,23 @@ async function hashPassword(plain) {
269
262
  }
270
263
  async function verifyPassword(plain, stored) {
271
264
  const [salt, storedHash] = stored.split(":");
272
- if (!salt || !storedHash)
273
- return false;
265
+ if (!salt || !storedHash) return false;
274
266
  const derivedKey = await scryptAsync(plain, salt, KEY_LEN);
275
267
  const storedBuffer = Buffer.from(storedHash, "hex");
276
- if (derivedKey.length !== storedBuffer.length)
277
- return false;
268
+ if (derivedKey.length !== storedBuffer.length) return false;
278
269
  return timingSafeEqual(derivedKey, storedBuffer);
279
270
  }
280
271
 
281
- // src/utils/readonly-db.js
272
+ // src/utils/readonly-db.ts
282
273
  var WRITE_METHODS = ["create", "update", "delete", "updateGlobal", "execute"];
283
274
  function createReadonlyDb(db) {
284
275
  return new Proxy(db, {
285
276
  get(target, prop) {
286
277
  if (WRITE_METHODS.includes(prop)) {
287
278
  return () => {
288
- throw new Error(`[dyrected] Write operation "${String(prop)}" is not allowed in this hook phase. Use afterChange/afterDelete hooks for write operations.`);
279
+ throw new Error(
280
+ `[dyrected] Write operation "${String(prop)}" is not allowed in this hook phase. Use afterChange/afterDelete hooks for write operations.`
281
+ );
289
282
  };
290
283
  }
291
284
  return Reflect.get(target, prop);
@@ -293,13 +286,11 @@ function createReadonlyDb(db) {
293
286
  });
294
287
  }
295
288
 
296
- // src/auth/jexl.js
289
+ // src/auth/jexl.ts
297
290
  import jexl from "jexl";
298
291
  async function evaluateAccess(expression, context) {
299
- if (expression === void 0 || expression === null)
300
- return false;
301
- if (typeof expression === "boolean")
302
- return expression;
292
+ if (expression === void 0 || expression === null) return false;
293
+ if (typeof expression === "boolean") return expression;
303
294
  try {
304
295
  const result = await jexl.eval(expression, context);
305
296
  return !!result;
@@ -309,7 +300,7 @@ async function evaluateAccess(expression, context) {
309
300
  }
310
301
  }
311
302
 
312
- // src/controllers/collection.controller.js
303
+ // src/controllers/collection.controller.ts
313
304
  var CollectionController = class {
314
305
  collection;
315
306
  constructor(collection) {
@@ -317,8 +308,8 @@ var CollectionController = class {
317
308
  }
318
309
  getDelegatedProvider(c) {
319
310
  const config = c.get("config");
320
- const authCollectionSlug = config.adminAuth?.collectionSlug || "__admins";
321
- if (this.collection.slug !== authCollectionSlug) {
311
+ const authCollection = getAdminAuthCollection(config);
312
+ if (!authCollection || this.collection.slug !== authCollection.slug) {
322
313
  return null;
323
314
  }
324
315
  return config.adminAuth?.providers?.find((p) => p.members) || null;
@@ -326,8 +317,7 @@ var CollectionController = class {
326
317
  async find(c) {
327
318
  const config = c.get("config");
328
319
  const db = config.db;
329
- if (!db)
330
- return c.json({ message: "Database not configured" }, 500);
320
+ if (!db) return c.json({ message: "Database not configured" }, 500);
331
321
  const provider = this.getDelegatedProvider(c);
332
322
  if (provider && provider.members?.list) {
333
323
  const limit2 = Number(c.req.query("limit")) || 10;
@@ -382,7 +372,7 @@ var CollectionController = class {
382
372
  if (this.collection.admin?.filterable === false) {
383
373
  where = void 0;
384
374
  } else {
385
- const { sanitizeWhereClause } = await import("./where-sanitizer-7Q4JXMX6.js");
375
+ const { sanitizeWhereClause } = await import("./where-sanitizer-WJ2W2QCE.js");
386
376
  where = sanitizeWhereClause(where, this.collection.fields);
387
377
  if (Object.keys(where).length === 0) {
388
378
  where = void 0;
@@ -445,13 +435,11 @@ var CollectionController = class {
445
435
  async findOne(c) {
446
436
  const config = c.get("config");
447
437
  const db = config.db;
448
- if (!db)
449
- return c.json({ message: "Database not configured" }, 500);
438
+ if (!db) return c.json({ message: "Database not configured" }, 500);
450
439
  const provider = this.getDelegatedProvider(c);
451
440
  if (provider && (provider.members?.get || provider.members?.list)) {
452
441
  const id2 = c.req.param("id");
453
- if (!id2)
454
- return c.json({ message: "Missing ID" }, 400);
442
+ if (!id2) return c.json({ message: "Missing ID" }, 400);
455
443
  const localDoc = await db.findOne({ collection: this.collection.slug, id: id2 });
456
444
  const externalSubject = localDoc?.externalSubject || id2;
457
445
  let member = null;
@@ -461,8 +449,7 @@ var CollectionController = class {
461
449
  const listResult = await provider.members.list({ req: c.req });
462
450
  member = listResult.docs.find((m) => m.id === externalSubject) || null;
463
451
  }
464
- if (!member)
465
- return c.json({ message: "Not Found" }, 404);
452
+ if (!member) return c.json({ message: "Not Found" }, 404);
466
453
  return c.json({
467
454
  ...member,
468
455
  id: localDoc ? localDoc.id : member.id,
@@ -473,15 +460,12 @@ var CollectionController = class {
473
460
  const id = c.req.param("id");
474
461
  const depth = c.req.query("depth") !== void 0 ? Number(c.req.query("depth")) : 10;
475
462
  const user = c.get("user");
476
- if (!id)
477
- return c.json({ message: "Missing ID" }, 400);
463
+ if (!id) return c.json({ message: "Missing ID" }, 400);
478
464
  let doc = await db.findOne({ collection: this.collection.slug, id });
479
- if (!doc)
480
- return c.json({ message: "Not Found" }, 404);
465
+ if (!doc) return c.json({ message: "Not Found" }, 404);
481
466
  if (this.collection.workflow) {
482
467
  doc = materializeWorkflowDocument(doc, this.collection.workflow, user);
483
- if (!doc)
484
- return c.json({ message: "Not Found" }, 404);
468
+ if (!doc) return c.json({ message: "Not Found" }, 404);
485
469
  }
486
470
  const docWithDefaults = DefaultsService.apply(this.collection.fields, doc);
487
471
  const docWithCollectionHooks = await runCollectionHooks(this.collection.hooks?.afterRead, {
@@ -506,8 +490,7 @@ var CollectionController = class {
506
490
  async create(c) {
507
491
  const config = c.get("config");
508
492
  const db = config.db;
509
- if (!db)
510
- return c.json({ message: "Database not configured" }, 500);
493
+ if (!db) return c.json({ message: "Database not configured" }, 500);
511
494
  const provider = this.getDelegatedProvider(c);
512
495
  if (provider && provider.members?.create) {
513
496
  const contentType2 = c.req.header("Content-Type") || "";
@@ -582,16 +565,13 @@ var CollectionController = class {
582
565
  async upload(c) {
583
566
  const config = c.get("config");
584
567
  const storage = config.storage;
585
- if (!storage)
586
- return c.json({ message: "Storage not configured" }, 500);
568
+ if (!storage) return c.json({ message: "Storage not configured" }, 500);
587
569
  const db = config.db;
588
- if (!db)
589
- return c.json({ message: "Database not configured" }, 500);
570
+ if (!db) return c.json({ message: "Database not configured" }, 500);
590
571
  const readonlyDb = createReadonlyDb(db);
591
572
  const formData = await c.req.formData();
592
573
  const file = formData.get("file");
593
- if (!file)
594
- return c.json({ message: "No file uploaded" }, 400);
574
+ if (!file) return c.json({ message: "No file uploaded" }, 400);
595
575
  const buffer = new Uint8Array(await file.arrayBuffer());
596
576
  const siteId = c.get("siteId");
597
577
  const workspaceId = c.get("workspaceId");
@@ -650,13 +630,11 @@ var CollectionController = class {
650
630
  async update(c) {
651
631
  const config = c.get("config");
652
632
  const db = config.db;
653
- if (!db)
654
- return c.json({ message: "Database not configured" }, 500);
633
+ if (!db) return c.json({ message: "Database not configured" }, 500);
655
634
  const provider = this.getDelegatedProvider(c);
656
635
  if (provider && provider.members?.update) {
657
636
  const id2 = c.req.param("id");
658
- if (!id2)
659
- return c.json({ message: "Missing ID" }, 400);
637
+ if (!id2) return c.json({ message: "Missing ID" }, 400);
660
638
  const body2 = await c.req.json();
661
639
  const localDoc = await db.findOne({ collection: this.collection.slug, id: id2 });
662
640
  const externalSubject = localDoc?.externalSubject || id2;
@@ -669,8 +647,7 @@ var CollectionController = class {
669
647
  }
670
648
  const readonlyDb = createReadonlyDb(db);
671
649
  const id = c.req.param("id");
672
- if (!id)
673
- return c.json({ message: "Missing ID" }, 400);
650
+ if (!id) return c.json({ message: "Missing ID" }, 400);
674
651
  const body = await c.req.json();
675
652
  const user = c.get("user");
676
653
  let data = { ...body };
@@ -684,8 +661,7 @@ var CollectionController = class {
684
661
  updatedBy: user?.sub ?? null
685
662
  });
686
663
  const originalDoc = await db.findOne({ collection: this.collection.slug, id });
687
- if (!originalDoc)
688
- return c.json({ message: "Not Found" }, 404);
664
+ if (!originalDoc) return c.json({ message: "Not Found" }, 404);
689
665
  let before = null;
690
666
  if (this.collection.audit) {
691
667
  before = originalDoc;
@@ -729,10 +705,8 @@ var CollectionController = class {
729
705
  }
730
706
  async transition(c) {
731
707
  const config = c.get("config");
732
- if (!config.db)
733
- return c.json({ message: "Database not configured" }, 500);
734
- if (!this.collection.workflow)
735
- return c.json({ message: "Workflows are not enabled for this collection" }, 404);
708
+ if (!config.db) return c.json({ message: "Database not configured" }, 500);
709
+ if (!this.collection.workflow) return c.json({ message: "Workflows are not enabled for this collection" }, 404);
736
710
  const id = c.req.param("id");
737
711
  const transitionName = c.req.param("transition");
738
712
  const body = await c.req.json().catch(() => ({}));
@@ -755,16 +729,12 @@ var CollectionController = class {
755
729
  }
756
730
  async workflowHistory(c) {
757
731
  const config = c.get("config");
758
- if (!config.db)
759
- return c.json({ message: "Database not configured" }, 500);
760
- if (!this.collection.workflow)
761
- return c.json({ message: "Workflows are not enabled for this collection" }, 404);
732
+ if (!config.db) return c.json({ message: "Database not configured" }, 500);
733
+ if (!this.collection.workflow) return c.json({ message: "Workflows are not enabled for this collection" }, 404);
762
734
  const documentId = c.req.param("id");
763
- if (!documentId)
764
- return c.json({ message: "Missing ID" }, 400);
735
+ if (!documentId) return c.json({ message: "Missing ID" }, 400);
765
736
  const document = await config.db.findOne({ collection: this.collection.slug, id: documentId });
766
- if (!document)
767
- return c.json({ message: "Not Found" }, 404);
737
+ if (!document) return c.json({ message: "Not Found" }, 404);
768
738
  const readAccess = this.collection.access?.read;
769
739
  if (readAccess !== void 0 && readAccess !== null) {
770
740
  const args = { user: c.get("user"), req: c.req, doc: document };
@@ -778,8 +748,7 @@ var CollectionController = class {
778
748
  });
779
749
  allowed = match.total > 0;
780
750
  }
781
- if (!allowed)
782
- return c.json({ error: true, message: `Access denied: read on ${this.collection.slug}` }, 403);
751
+ if (!allowed) return c.json({ error: true, message: `Access denied: read on ${this.collection.slug}` }, 403);
783
752
  }
784
753
  const result = await config.db.find({
785
754
  collection: WORKFLOW_HISTORY_COLLECTION,
@@ -803,17 +772,14 @@ var CollectionController = class {
803
772
  async changePassword(c) {
804
773
  const config = c.get("config");
805
774
  const db = config.db;
806
- if (!db)
807
- return c.json({ message: "Database not configured" }, 500);
775
+ if (!db) return c.json({ message: "Database not configured" }, 500);
808
776
  if (!this.collection.auth) {
809
777
  return c.json({ message: "This collection does not support authentication" }, 400);
810
778
  }
811
779
  const id = c.req.param("id");
812
- if (!id)
813
- return c.json({ message: "Missing ID" }, 400);
780
+ if (!id) return c.json({ message: "Missing ID" }, 400);
814
781
  const user = c.get("user");
815
- if (!user)
816
- return c.json({ message: "Authentication required" }, 401);
782
+ if (!user) return c.json({ message: "Authentication required" }, 401);
817
783
  const body = await c.req.json().catch(() => null);
818
784
  const { oldPassword, newPassword, confirmPassword } = body ?? {};
819
785
  if (!newPassword) {
@@ -835,8 +801,7 @@ var CollectionController = class {
835
801
  return c.json({ message: "Current password is required" }, 400);
836
802
  }
837
803
  const existing = await db.findOne({ collection: this.collection.slug, id });
838
- if (!existing)
839
- return c.json({ message: "User not found" }, 404);
804
+ if (!existing) return c.json({ message: "User not found" }, 404);
840
805
  const valid = await verifyPassword(oldPassword, existing.password);
841
806
  if (!valid) {
842
807
  return c.json({ message: "Invalid current password" }, 400);
@@ -867,13 +832,11 @@ var CollectionController = class {
867
832
  async delete(c) {
868
833
  const config = c.get("config");
869
834
  const db = config.db;
870
- if (!db)
871
- return c.json({ message: "Database not configured" }, 500);
835
+ if (!db) return c.json({ message: "Database not configured" }, 500);
872
836
  const provider = this.getDelegatedProvider(c);
873
837
  if (provider && provider.members?.delete) {
874
838
  const id2 = c.req.param("id");
875
- if (!id2)
876
- return c.json({ message: "Missing ID" }, 400);
839
+ if (!id2) return c.json({ message: "Missing ID" }, 400);
877
840
  const localDoc = await db.findOne({ collection: this.collection.slug, id: id2 });
878
841
  const externalSubject = localDoc?.externalSubject || id2;
879
842
  await provider.members.delete({ externalSubject, req: c.req });
@@ -881,12 +844,10 @@ var CollectionController = class {
881
844
  }
882
845
  const readonlyDb = createReadonlyDb(db);
883
846
  const id = c.req.param("id");
884
- if (!id)
885
- return c.json({ message: "Missing ID" }, 400);
847
+ if (!id) return c.json({ message: "Missing ID" }, 400);
886
848
  const user = c.get("user");
887
849
  const doc = await db.findOne({ collection: this.collection.slug, id });
888
- if (!doc)
889
- return c.json({ message: "Not Found" }, 404);
850
+ if (!doc) return c.json({ message: "Not Found" }, 404);
890
851
  let before = null;
891
852
  if (this.collection.audit) {
892
853
  before = doc;
@@ -921,8 +882,7 @@ var CollectionController = class {
921
882
  async deleteMany(c) {
922
883
  const config = c.get("config");
923
884
  const db = config.db;
924
- if (!db)
925
- return c.json({ message: "Database not configured" }, 500);
885
+ if (!db) return c.json({ message: "Database not configured" }, 500);
926
886
  const readonlyDb = createReadonlyDb(db);
927
887
  const user = c.get("user");
928
888
  let ids = [];
@@ -937,8 +897,7 @@ var CollectionController = class {
937
897
  const raw = c.req.queries("ids") ?? c.req.queries("ids[]") ?? [];
938
898
  ids = raw.filter(Boolean);
939
899
  }
940
- if (!ids.length)
941
- return c.json({ message: "No IDs provided" }, 400);
900
+ if (!ids.length) return c.json({ message: "No IDs provided" }, 400);
942
901
  const deleted = [];
943
902
  const failed = [];
944
903
  for (const id of ids) {
@@ -991,8 +950,7 @@ var CollectionController = class {
991
950
  async seed(c) {
992
951
  const config = c.get("config");
993
952
  const db = config.db;
994
- if (!db)
995
- return c.json({ message: "Database not configured" }, 500);
953
+ if (!db) return c.json({ message: "Database not configured" }, 500);
996
954
  const body = await c.req.json();
997
955
  const initialData = body.data;
998
956
  if (!initialData || !Array.isArray(initialData)) {
@@ -1012,7 +970,7 @@ var CollectionController = class {
1012
970
  }
1013
971
  };
1014
972
 
1015
- // src/controllers/global.controller.js
973
+ // src/controllers/global.controller.ts
1016
974
  var GlobalController = class {
1017
975
  global;
1018
976
  constructor(global) {
@@ -1021,8 +979,7 @@ var GlobalController = class {
1021
979
  async get(c) {
1022
980
  const config = c.get("config");
1023
981
  const db = config.db;
1024
- if (!db)
1025
- return c.json({ message: "Database not configured" }, 500);
982
+ if (!db) return c.json({ message: "Database not configured" }, 500);
1026
983
  const readonlyDb = createReadonlyDb(db);
1027
984
  const depth = c.req.query("depth") !== void 0 ? Number(c.req.query("depth")) : 10;
1028
985
  const user = c.get("user");
@@ -1066,8 +1023,7 @@ var GlobalController = class {
1066
1023
  async update(c) {
1067
1024
  const config = c.get("config");
1068
1025
  const db = config.db;
1069
- if (!db)
1070
- return c.json({ message: "Database not configured" }, 500);
1026
+ if (!db) return c.json({ message: "Database not configured" }, 500);
1071
1027
  const readonlyDb = createReadonlyDb(db);
1072
1028
  const body = await c.req.json();
1073
1029
  const user = c.get("user");
@@ -1102,8 +1058,7 @@ var GlobalController = class {
1102
1058
  async seed(c) {
1103
1059
  const config = c.get("config");
1104
1060
  const db = config.db;
1105
- if (!db)
1106
- return c.json({ message: "Database not configured" }, 500);
1061
+ if (!db) return c.json({ message: "Database not configured" }, 500);
1107
1062
  const body = await c.req.json();
1108
1063
  const initialData = body.data;
1109
1064
  if (!initialData) {
@@ -1119,23 +1074,20 @@ var GlobalController = class {
1119
1074
  }
1120
1075
  };
1121
1076
  function isFunctionallyEmpty(obj) {
1122
- if (obj === null || obj === void 0 || obj === "")
1123
- return true;
1077
+ if (obj === null || obj === void 0 || obj === "") return true;
1124
1078
  if (Array.isArray(obj)) {
1125
- if (obj.length === 0)
1126
- return true;
1079
+ if (obj.length === 0) return true;
1127
1080
  return obj.every(isFunctionallyEmpty);
1128
1081
  }
1129
1082
  if (typeof obj === "object") {
1130
1083
  const keys = Object.keys(obj);
1131
- if (keys.length === 0)
1132
- return true;
1084
+ if (keys.length === 0) return true;
1133
1085
  return keys.every((key) => isFunctionallyEmpty(obj[key]));
1134
1086
  }
1135
1087
  return false;
1136
1088
  }
1137
1089
 
1138
- // src/controllers/media.controller.js
1090
+ // src/controllers/media.controller.ts
1139
1091
  var MediaController = class {
1140
1092
  collection;
1141
1093
  constructor(collection = "media") {
@@ -1215,8 +1167,7 @@ var MediaController = class {
1215
1167
  }
1216
1168
  }
1217
1169
  const db = config.db;
1218
- if (!db)
1219
- return c.json({ message: "Database not configured" }, 500);
1170
+ if (!db) return c.json({ message: "Database not configured" }, 500);
1220
1171
  const doc = await db.create({
1221
1172
  collection: this.collection,
1222
1173
  data: finalFileData
@@ -1225,8 +1176,7 @@ var MediaController = class {
1225
1176
  }
1226
1177
  async find(c) {
1227
1178
  const db = c.get("config").db;
1228
- if (!db)
1229
- return c.json({ message: "Database not configured" }, 500);
1179
+ if (!db) return c.json({ message: "Database not configured" }, 500);
1230
1180
  const limit = Number(c.req.query("limit")) || 10;
1231
1181
  const page = Number(c.req.query("page")) || 1;
1232
1182
  const result = await db.find({
@@ -1240,14 +1190,11 @@ var MediaController = class {
1240
1190
  const config = c.get("config");
1241
1191
  const storage = config.storage;
1242
1192
  const db = config.db;
1243
- if (!db)
1244
- return c.json({ message: "Database not configured" }, 500);
1193
+ if (!db) return c.json({ message: "Database not configured" }, 500);
1245
1194
  const id = c.req.param("id");
1246
- if (!id)
1247
- return c.json({ message: "Missing ID" }, 400);
1195
+ if (!id) return c.json({ message: "Missing ID" }, 400);
1248
1196
  const doc = await db.findOne({ collection: this.collection, id });
1249
- if (!doc)
1250
- return c.json({ message: "Not Found" }, 404);
1197
+ if (!doc) return c.json({ message: "Not Found" }, 404);
1251
1198
  if (storage) {
1252
1199
  await storage.delete({ filename: doc.filename });
1253
1200
  if (doc.sizes) {
@@ -1268,26 +1215,26 @@ var MediaController = class {
1268
1215
  return c.json({ message: "Storage not configured for serving" }, 404);
1269
1216
  }
1270
1217
  const filename = c.req.param("filename");
1271
- if (!filename)
1272
- return c.json({ message: "Missing filename" }, 400);
1218
+ if (!filename) return c.json({ message: "Missing filename" }, 400);
1273
1219
  let res = await storage.resolve({ filename });
1274
1220
  if (!res && !filename.includes("/")) {
1275
1221
  res = await storage.resolve({ filename: `default/${filename}` });
1276
1222
  }
1277
- if (!res)
1278
- return c.json({ message: "Not Found" }, 404);
1223
+ if (!res) return c.json({ message: "Not Found" }, 404);
1279
1224
  c.header("Content-Type", res.mimeType);
1280
1225
  return c.body(res.buffer);
1281
1226
  }
1282
1227
  };
1283
1228
 
1284
- // src/auth/token.js
1229
+ // src/auth/token.ts
1285
1230
  import { SignJWT, jwtVerify, decodeJwt } from "jose";
1286
1231
  import { TextEncoder } from "util";
1287
1232
  function getSecret() {
1288
1233
  const secret = process.env.DYRECTED_JWT_SECRET || process.env.JWT_SECRET;
1289
1234
  if (!secret) {
1290
- throw new Error("[dyrected/core] DYRECTED_JWT_SECRET is not set. Add it to your environment variables to enable auth collections.");
1235
+ throw new Error(
1236
+ "[dyrected/core] DYRECTED_JWT_SECRET is not set. Add it to your environment variables to enable auth collections."
1237
+ );
1291
1238
  }
1292
1239
  return new TextEncoder().encode(secret);
1293
1240
  }
@@ -1300,7 +1247,7 @@ async function verifyCollectionToken(token) {
1300
1247
  return payload;
1301
1248
  }
1302
1249
 
1303
- // src/services/email-template.js
1250
+ // src/services/email-template.ts
1304
1251
  var emailTokens = {
1305
1252
  colors: {
1306
1253
  canvas: "#f6f7f2",
@@ -1364,9 +1311,11 @@ function detailBox(content, monospace = false) {
1364
1311
  }
1365
1312
  function ctaButton(label, href) {
1366
1313
  const safeHref = safeHttpUrl(href);
1367
- if (!safeHref)
1368
- return "";
1369
- return table(row(`<a href="${safeHref}" style="display:inline-block;padding:13px 22px;border-radius:${emailTokens.radius.control};background:${emailTokens.colors.accent};font-family:${emailTokens.font};font-size:14px;line-height:1.2;font-weight:700;color:${emailTokens.colors.text};text-decoration:none">${escapeHtml(label)}</a>`, "padding:8px 0 24px"), "width:auto");
1314
+ if (!safeHref) return "";
1315
+ return table(row(
1316
+ `<a href="${safeHref}" style="display:inline-block;padding:13px 22px;border-radius:${emailTokens.radius.control};background:${emailTokens.colors.accent};font-family:${emailTokens.font};font-size:14px;line-height:1.2;font-weight:700;color:${emailTokens.colors.text};text-decoration:none">${escapeHtml(label)}</a>`,
1317
+ "padding:8px 0 24px"
1318
+ ), "width:auto");
1370
1319
  }
1371
1320
  function alertBox(content) {
1372
1321
  return table(row(escapeHtml(content), `padding:13px 16px;font-family:${emailTokens.font};font-size:13px;line-height:1.5;color:${emailTokens.colors.dangerText}`), `width:100%;background:${emailTokens.colors.dangerSurface};border:1px solid ${emailTokens.colors.dangerBorder};border-radius:${emailTokens.radius.control}`);
@@ -1377,19 +1326,23 @@ function layout({ preheader, title, content, footer }) {
1377
1326
  <head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"></head>
1378
1327
  <body style="margin:0;padding:0;background:${emailTokens.colors.canvas}">
1379
1328
  <div style="display:none;max-height:0;overflow:hidden;opacity:0;color:transparent">${escapeHtml(preheader)}</div>
1380
- ${table(row(table(row("&nbsp;", `height:5px;background:${emailTokens.colors.accent};font-size:0;line-height:0`) + row(`${sectionLabel("Dyrected")}${heading(title)}`, "padding:30px 32px 24px") + row(content, "padding:0 32px 32px") + row(`${divider()}${paragraph(footer, "20px 0 6px")}${paragraph("Privacy: this message contains account-related information; please avoid forwarding it.", "0")}`, "padding:0 32px 28px"), `width:100%;max-width:${emailTokens.width};background:${emailTokens.colors.surface};border:1px solid ${emailTokens.colors.border};border-radius:${emailTokens.radius.card};overflow:hidden`), "padding:32px 12px"), `width:100%;background:${emailTokens.colors.canvas}`)}
1329
+ ${table(row(
1330
+ table(
1331
+ row("&nbsp;", `height:5px;background:${emailTokens.colors.accent};font-size:0;line-height:0`) + row(`${sectionLabel("Dyrected")}${heading(title)}`, "padding:30px 32px 24px") + row(content, "padding:0 32px 32px") + row(`${divider()}${paragraph(footer, "20px 0 6px")}${paragraph("Privacy: this message contains account-related information; please avoid forwarding it.", "0")}`, "padding:0 32px 28px"),
1332
+ `width:100%;max-width:${emailTokens.width};background:${emailTokens.colors.surface};border:1px solid ${emailTokens.colors.border};border-radius:${emailTokens.radius.card};overflow:hidden`
1333
+ ),
1334
+ "padding:32px 12px"
1335
+ ), `width:100%;background:${emailTokens.colors.canvas}`)}
1381
1336
  </body>
1382
1337
  </html>`;
1383
1338
  }
1384
1339
 
1385
- // src/services/email.service.js
1340
+ // src/services/email.service.ts
1386
1341
  var _devSend = null;
1387
1342
  var _devSendPromise = null;
1388
1343
  async function getDevSend() {
1389
- if (_devSend)
1390
- return _devSend;
1391
- if (_devSendPromise)
1392
- return _devSendPromise;
1344
+ if (_devSend) return _devSend;
1345
+ if (_devSendPromise) return _devSendPromise;
1393
1346
  _devSendPromise = (async () => {
1394
1347
  try {
1395
1348
  const nodemailer = await import("nodemailer");
@@ -1473,7 +1426,7 @@ function buildPasswordChangedEmail(config, args) {
1473
1426
  };
1474
1427
  }
1475
1428
 
1476
- // src/controllers/auth.controller.js
1429
+ // src/controllers/auth.controller.ts
1477
1430
  var AuthController = class {
1478
1431
  collection;
1479
1432
  constructor(collection) {
@@ -1485,8 +1438,7 @@ var AuthController = class {
1485
1438
  // ---------------------------------------------------------------------------
1486
1439
  async init(c) {
1487
1440
  const db = c.get("config").db;
1488
- if (!db)
1489
- return c.json({ message: "Database not configured" }, 500);
1441
+ if (!db) return c.json({ message: "Database not configured" }, 500);
1490
1442
  const result = await db.find({
1491
1443
  collection: this.collection.slug,
1492
1444
  limit: 1
@@ -1502,8 +1454,7 @@ var AuthController = class {
1502
1454
  async registerFirstUser(c) {
1503
1455
  const config = c.get("config");
1504
1456
  const db = config.db;
1505
- if (!db)
1506
- return c.json({ message: "Database not configured" }, 500);
1457
+ if (!db) return c.json({ message: "Database not configured" }, 500);
1507
1458
  const check = await db.find({
1508
1459
  collection: this.collection.slug,
1509
1460
  limit: 1
@@ -1531,7 +1482,9 @@ var AuthController = class {
1531
1482
  collection: this.collection.slug
1532
1483
  });
1533
1484
  const { subject, html } = buildWelcomeEmail(config, { email: body.email });
1534
- sendEmail(config, { to: body.email, subject, html }).catch((err) => console.error("[dyrected/core] Failed to send welcome email:", err));
1485
+ sendEmail(config, { to: body.email, subject, html }).catch(
1486
+ (err) => console.error("[dyrected/core] Failed to send welcome email:", err)
1487
+ );
1535
1488
  const { password: _, ...safeUser } = user;
1536
1489
  return c.json({ token, user: safeUser });
1537
1490
  }
@@ -1540,8 +1493,7 @@ var AuthController = class {
1540
1493
  // ---------------------------------------------------------------------------
1541
1494
  async login(c) {
1542
1495
  const db = c.get("config").db;
1543
- if (!db)
1544
- return c.json({ message: "Database not configured" }, 500);
1496
+ if (!db) return c.json({ message: "Database not configured" }, 500);
1545
1497
  const body = await c.req.json().catch(() => null);
1546
1498
  if (!body?.email || !body?.password) {
1547
1499
  return c.json({ error: true, message: "email and password are required." }, 400);
@@ -1580,8 +1532,7 @@ var AuthController = class {
1580
1532
  // ---------------------------------------------------------------------------
1581
1533
  async me(c) {
1582
1534
  const db = c.get("config").db;
1583
- if (!db)
1584
- return c.json({ message: "Database not configured" }, 500);
1535
+ if (!db) return c.json({ message: "Database not configured" }, 500);
1585
1536
  const requestUser = c.get("user");
1586
1537
  if (!requestUser) {
1587
1538
  return c.json({ error: true, message: "Authentication required." }, 401);
@@ -1616,8 +1567,7 @@ var AuthController = class {
1616
1567
  async forgotPassword(c) {
1617
1568
  const config = c.get("config");
1618
1569
  const db = config.db;
1619
- if (!db)
1620
- return c.json({ message: "Database not configured" }, 500);
1570
+ if (!db) return c.json({ message: "Database not configured" }, 500);
1621
1571
  const body = await c.req.json().catch(() => null);
1622
1572
  if (!body?.email) {
1623
1573
  return c.json({ error: true, message: "email is required." }, 400);
@@ -1629,7 +1579,10 @@ var AuthController = class {
1629
1579
  });
1630
1580
  const user = result.docs[0];
1631
1581
  if (user) {
1632
- const resetToken = await signCollectionToken({ sub: user.id, email: user.email, collection: this.collection.slug, purpose: "reset" }, "1h");
1582
+ const resetToken = await signCollectionToken(
1583
+ { sub: user.id, email: user.email, collection: this.collection.slug, purpose: "reset" },
1584
+ "1h"
1585
+ );
1633
1586
  const resetUrl = body?.resetUrl;
1634
1587
  const url = resetUrl ? `${resetUrl}${resetUrl.includes("?") ? "&" : "?"}token=${encodeURIComponent(resetToken)}` : void 0;
1635
1588
  try {
@@ -1652,8 +1605,7 @@ var AuthController = class {
1652
1605
  async resetPassword(c) {
1653
1606
  const config = c.get("config");
1654
1607
  const db = config.db;
1655
- if (!db)
1656
- return c.json({ message: "Database not configured" }, 500);
1608
+ if (!db) return c.json({ message: "Database not configured" }, 500);
1657
1609
  const body = await c.req.json().catch(() => null);
1658
1610
  if (!body?.token || !body?.password) {
1659
1611
  return c.json({ error: true, message: "token and password are required." }, 400);
@@ -1674,7 +1626,9 @@ var AuthController = class {
1674
1626
  data: { password: hashedPassword }
1675
1627
  });
1676
1628
  const { subject, html } = buildPasswordChangedEmail(config, { email: payload.email });
1677
- sendEmail(config, { to: payload.email, subject, html }).catch((err) => console.error("[dyrected/core] Failed to send password-changed email:", err));
1629
+ sendEmail(config, { to: payload.email, subject, html }).catch(
1630
+ (err) => console.error("[dyrected/core] Failed to send password-changed email:", err)
1631
+ );
1678
1632
  return c.json({ success: true, message: "Password has been reset. You can now log in." });
1679
1633
  }
1680
1634
  // ---------------------------------------------------------------------------
@@ -1684,8 +1638,7 @@ var AuthController = class {
1684
1638
  async invite(c) {
1685
1639
  const config = c.get("config");
1686
1640
  const db = config.db;
1687
- if (!db)
1688
- return c.json({ message: "Database not configured" }, 500);
1641
+ if (!db) return c.json({ message: "Database not configured" }, 500);
1689
1642
  const requestUser = c.get("user");
1690
1643
  if (!requestUser) {
1691
1644
  return c.json({ error: true, message: "Authentication required." }, 401);
@@ -1702,7 +1655,10 @@ var AuthController = class {
1702
1655
  if (existing.total > 0) {
1703
1656
  return c.json({ error: true, message: "An account with that email already exists." }, 409);
1704
1657
  }
1705
- const inviteToken = await signCollectionToken({ sub: body.email, email: body.email, collection: this.collection.slug, purpose: "invite" }, "7d");
1658
+ const inviteToken = await signCollectionToken(
1659
+ { sub: body.email, email: body.email, collection: this.collection.slug, purpose: "invite" },
1660
+ "7d"
1661
+ );
1706
1662
  try {
1707
1663
  const { subject, html } = buildInviteEmail(config, {
1708
1664
  token: inviteToken,
@@ -1722,8 +1678,7 @@ var AuthController = class {
1722
1678
  async acceptInvite(c) {
1723
1679
  const config = c.get("config");
1724
1680
  const db = config.db;
1725
- if (!db)
1726
- return c.json({ message: "Database not configured" }, 500);
1681
+ if (!db) return c.json({ message: "Database not configured" }, 500);
1727
1682
  const body = await c.req.json().catch(() => null);
1728
1683
  if (!body?.token || !body?.password) {
1729
1684
  return c.json({ error: true, message: "token and password are required." }, 400);
@@ -1758,21 +1713,28 @@ var AuthController = class {
1758
1713
  collection: this.collection.slug
1759
1714
  });
1760
1715
  const { subject, html } = buildWelcomeEmail(config, { email: inviteeEmail });
1761
- sendEmail(config, { to: inviteeEmail, subject, html }).catch((err) => console.error("[dyrected/core] Failed to send welcome email:", err));
1716
+ sendEmail(config, { to: inviteeEmail, subject, html }).catch(
1717
+ (err) => console.error("[dyrected/core] Failed to send welcome email:", err)
1718
+ );
1762
1719
  const { password: _, ...safeUser } = user;
1763
1720
  return c.json({ token: sessionToken, user: safeUser }, 201);
1764
1721
  }
1765
1722
  };
1766
1723
 
1767
- // src/controllers/admin-auth.controller.js
1724
+ // src/controllers/admin-auth.controller.ts
1768
1725
  import { randomBytes as randomBytes2 } from "crypto";
1769
1726
  import { TextEncoder as TextEncoder2 } from "util";
1770
- import { SignJWT as SignJWT2, createRemoteJWKSet, jwtVerify as jwtVerify2, decodeJwt as decodeJwt2 } from "jose";
1727
+ import {
1728
+ SignJWT as SignJWT2,
1729
+ createRemoteJWKSet,
1730
+ jwtVerify as jwtVerify2,
1731
+ decodeJwt as decodeJwt2
1732
+ } from "jose";
1771
1733
  var AdminAuthController = class {
1772
- config;
1773
1734
  constructor(config) {
1774
1735
  this.config = config;
1775
1736
  }
1737
+ config;
1776
1738
  providers(c) {
1777
1739
  return c.json(getPublicAdminAuthConfig(this.config.adminAuth));
1778
1740
  }
@@ -1785,7 +1747,12 @@ var AdminAuthController = class {
1785
1747
  const siteId = this.getSiteId(c);
1786
1748
  const returnTo = this.normalizeReturnTo(c.req.query("returnTo"), c);
1787
1749
  if (provider.type === "oidc") {
1788
- const redirectUrl = await this.buildOidcStartUrl(provider, returnTo, siteId, new URL(c.req.url).origin);
1750
+ const redirectUrl = await this.buildOidcStartUrl(
1751
+ provider,
1752
+ returnTo,
1753
+ siteId,
1754
+ new URL(c.req.url).origin
1755
+ );
1789
1756
  return c.redirect(redirectUrl, 302);
1790
1757
  }
1791
1758
  if (!provider.startUrl) {
@@ -1793,14 +1760,16 @@ var AdminAuthController = class {
1793
1760
  }
1794
1761
  const url = this.buildCustomProviderStartUrl(provider.startUrl, new URL(c.req.url).origin);
1795
1762
  if (!url) {
1796
- return c.json({
1797
- error: true,
1798
- message: `Admin auth provider "${provider.id}" has an invalid start URL.`
1799
- }, 500);
1763
+ return c.json(
1764
+ {
1765
+ error: true,
1766
+ message: `Admin auth provider "${provider.id}" has an invalid start URL.`
1767
+ },
1768
+ 500
1769
+ );
1800
1770
  }
1801
1771
  url.searchParams.set("returnTo", returnTo);
1802
- if (siteId)
1803
- url.searchParams.set("siteId", siteId);
1772
+ if (siteId) url.searchParams.set("siteId", siteId);
1804
1773
  url.searchParams.set("provider", provider.id);
1805
1774
  return c.redirect(url.toString(), 302);
1806
1775
  }
@@ -1847,8 +1816,7 @@ var AdminAuthController = class {
1847
1816
  return c.json({ success: true, message: "Logged out. Discard your token." });
1848
1817
  }
1849
1818
  getProvider(config, id) {
1850
- if (config.adminAuth?.mode !== "external")
1851
- return void 0;
1819
+ if (config.adminAuth?.mode !== "external") return void 0;
1852
1820
  return config.adminAuth.providers.find((provider) => provider.id === id);
1853
1821
  }
1854
1822
  async completeProviderAuth(requestConfig, provider, c) {
@@ -1860,8 +1828,7 @@ var AdminAuthController = class {
1860
1828
  throw new Error("Admin auth collection is not configured.");
1861
1829
  }
1862
1830
  const db = c.get("config").db;
1863
- if (!db)
1864
- throw new Error("Database not configured.");
1831
+ if (!db) throw new Error("Database not configured.");
1865
1832
  let user = await this.findUserByExternalIdentity(db, adminCollection.slug, provider.id, identity.sub) ?? (identity.email ? (await db.find({
1866
1833
  collection: adminCollection.slug,
1867
1834
  where: { email: identity.email },
@@ -1921,8 +1888,7 @@ var AdminAuthController = class {
1921
1888
  },
1922
1889
  user
1923
1890
  });
1924
- if (resolved)
1925
- return resolved;
1891
+ if (resolved) return resolved;
1926
1892
  return { allowed: true, roles: identity.roles, data: {} };
1927
1893
  }
1928
1894
  async buildUserData(identity, providerId, roles, extraData) {
@@ -1953,8 +1919,7 @@ var AdminAuthController = class {
1953
1919
  }
1954
1920
  async getRequestConfig(c) {
1955
1921
  const siteId = this.getSiteId(c);
1956
- if (!siteId || !this.config.onSchemaFetch)
1957
- return this.config;
1922
+ if (!siteId || !this.config.onSchemaFetch) return this.config;
1958
1923
  const dynamic = await this.config.onSchemaFetch(siteId);
1959
1924
  return {
1960
1925
  ...this.config,
@@ -1985,8 +1950,7 @@ var AdminAuthController = class {
1985
1950
  async resolveOidcIdentity(provider, c) {
1986
1951
  const code = c.req.query("code");
1987
1952
  const state = c.req.query("state");
1988
- if (!code || !state)
1989
- throw new Error("Missing OIDC callback parameters.");
1953
+ if (!code || !state) throw new Error("Missing OIDC callback parameters.");
1990
1954
  const parsedState = await this.verifyState(state, provider.id);
1991
1955
  const discovery = await this.getOidcDiscovery(provider);
1992
1956
  const redirectUri = provider.redirectUri || this.defaultCallbackPath(provider.id, new URL(c.req.url).origin);
@@ -2021,8 +1985,7 @@ var AdminAuthController = class {
2021
1985
  const userInfo = await fetch(provider.userInfoEndpoint || discovery.userinfo_endpoint, {
2022
1986
  headers: { Authorization: `Bearer ${tokenBody.access_token}` }
2023
1987
  });
2024
- if (!userInfo.ok)
2025
- throw new Error("OIDC userinfo request failed.");
1988
+ if (!userInfo.ok) throw new Error("OIDC userinfo request failed.");
2026
1989
  claims = await userInfo.json();
2027
1990
  } else {
2028
1991
  throw new Error("OIDC provider did not return usable identity claims.");
@@ -2062,13 +2025,15 @@ var AdminAuthController = class {
2062
2025
  if (provider.audience) {
2063
2026
  const aud = claims.aud;
2064
2027
  const matches = Array.isArray(aud) ? aud.includes(provider.audience) : aud === provider.audience;
2065
- if (!matches)
2066
- throw new Error("External auth audience mismatch.");
2028
+ if (!matches) throw new Error("External auth audience mismatch.");
2067
2029
  }
2068
2030
  }
2069
2031
  return {
2070
2032
  identity: this.mapClaims(claims, provider.claimMapping),
2071
- returnTo: this.normalizeReturnTo(body?.returnTo || c.req.query("returnTo"), c)
2033
+ returnTo: this.normalizeReturnTo(
2034
+ body?.returnTo || c.req.query("returnTo"),
2035
+ c
2036
+ )
2072
2037
  };
2073
2038
  }
2074
2039
  mapClaims(claims, mapping) {
@@ -2098,20 +2063,19 @@ var AdminAuthController = class {
2098
2063
  return typeof value === "string" ? value : void 0;
2099
2064
  }
2100
2065
  readStringArrayClaim(value) {
2101
- if (!value)
2102
- return void 0;
2066
+ if (!value) return void 0;
2103
2067
  if (Array.isArray(value)) {
2104
2068
  return value.filter((entry) => typeof entry === "string");
2105
2069
  }
2106
- if (typeof value === "string")
2107
- return [value];
2070
+ if (typeof value === "string") return [value];
2108
2071
  return void 0;
2109
2072
  }
2110
2073
  async getOidcDiscovery(provider) {
2111
- const discoveryUrl = new URL(provider.issuer.replace(/\/$/, "") + "/.well-known/openid-configuration");
2074
+ const discoveryUrl = new URL(
2075
+ provider.issuer.replace(/\/$/, "") + "/.well-known/openid-configuration"
2076
+ );
2112
2077
  const response = await fetch(discoveryUrl.toString());
2113
- if (!response.ok)
2114
- throw new Error("Failed to load OIDC discovery document.");
2078
+ if (!response.ok) throw new Error("Failed to load OIDC discovery document.");
2115
2079
  return response.json();
2116
2080
  }
2117
2081
  defaultCallbackPath(providerId, origin = "") {
@@ -2119,12 +2083,10 @@ var AdminAuthController = class {
2119
2083
  }
2120
2084
  buildCustomProviderStartUrl(startUrl, origin) {
2121
2085
  const value = startUrl.trim();
2122
- if (!value || /^(undefined|null)(\/|$)/i.test(value))
2123
- return null;
2086
+ if (!value || /^(undefined|null)(\/|$)/i.test(value)) return null;
2124
2087
  try {
2125
2088
  const url = new URL(value, origin);
2126
- if (url.protocol !== "http:" && url.protocol !== "https:")
2127
- return null;
2089
+ if (url.protocol !== "http:" && url.protocol !== "https:") return null;
2128
2090
  return url;
2129
2091
  } catch {
2130
2092
  return null;
@@ -2149,14 +2111,13 @@ var AdminAuthController = class {
2149
2111
  return new TextEncoder2().encode(secret);
2150
2112
  }
2151
2113
  normalizeReturnTo(returnTo, c) {
2152
- if (returnTo)
2153
- return returnTo;
2114
+ if (returnTo) return returnTo;
2154
2115
  const url = new URL(c.req.url);
2155
2116
  return `${url.origin}/admin`;
2156
2117
  }
2157
2118
  };
2158
2119
 
2159
- // src/controllers/preview.controller.js
2120
+ // src/controllers/preview.controller.ts
2160
2121
  import { SignJWT as SignJWT3, jwtVerify as jwtVerify3 } from "jose";
2161
2122
  import { TextEncoder as TextEncoder3 } from "util";
2162
2123
  var PreviewController = class {
@@ -2199,7 +2160,7 @@ var PreviewController = class {
2199
2160
  }
2200
2161
  };
2201
2162
 
2202
- // src/middleware/auth.js
2163
+ // src/middleware/auth.ts
2203
2164
  function requireAuth() {
2204
2165
  return async (c, next) => {
2205
2166
  const authHeader = c.req.header("Authorization");
@@ -2231,7 +2192,7 @@ function optionalAuth() {
2231
2192
  };
2232
2193
  }
2233
2194
 
2234
- // src/utils/swagger.js
2195
+ // src/utils/swagger.ts
2235
2196
  function getSwaggerHtml(specUrl = "/api/openapi.json") {
2236
2197
  return `
2237
2198
  <!DOCTYPE html>
@@ -2280,7 +2241,7 @@ function getSwaggerHtml(specUrl = "/api/openapi.json") {
2280
2241
  `;
2281
2242
  }
2282
2243
 
2283
- // src/router.js
2244
+ // src/router.ts
2284
2245
  function accessGate(target, action) {
2285
2246
  return async (c, next) => {
2286
2247
  const user = c.get("user");
@@ -2297,8 +2258,7 @@ function accessGate(target, action) {
2297
2258
  };
2298
2259
  }
2299
2260
  async function checkAccess(access, accessArgs) {
2300
- if (access === void 0 || access === null)
2301
- return true;
2261
+ if (access === void 0 || access === null) return true;
2302
2262
  if (typeof access === "function") {
2303
2263
  try {
2304
2264
  const result = await access(accessArgs);
@@ -2314,8 +2274,7 @@ async function checkAccess(access, accessArgs) {
2314
2274
  return true;
2315
2275
  }
2316
2276
  function serializeFieldForApi(f) {
2317
- if (!f)
2318
- return f;
2277
+ if (!f) return f;
2319
2278
  const serialized = { ...f };
2320
2279
  if (serialized.admin?.hooks) {
2321
2280
  const hooks = { ...serialized.admin.hooks };
@@ -2348,10 +2307,8 @@ function registerRoutes(app, config) {
2348
2307
  let globals = [...config.globals];
2349
2308
  if (siteId && config.onSchemaFetch) {
2350
2309
  const dynamic = await config.onSchemaFetch(siteId);
2351
- if (dynamic.collections)
2352
- collections = [...collections, ...dynamic.collections];
2353
- if (dynamic.globals)
2354
- globals = [...globals, ...dynamic.globals];
2310
+ if (dynamic.collections) collections = [...collections, ...dynamic.collections];
2311
+ if (dynamic.globals) globals = [...globals, ...dynamic.globals];
2355
2312
  if (dynamic.admin) {
2356
2313
  config.admin = { ...config.admin, ...dynamic.admin };
2357
2314
  }
@@ -2362,10 +2319,8 @@ function registerRoutes(app, config) {
2362
2319
  const user = c.get("user");
2363
2320
  const accessArgs = { user, req: c.req, doc: null };
2364
2321
  const serializeAccess = async (access) => {
2365
- if (typeof access === "string")
2366
- return access;
2367
- if (typeof access === "boolean")
2368
- return access;
2322
+ if (typeof access === "string") return access;
2323
+ if (typeof access === "boolean") return access;
2369
2324
  return checkAccess(access, accessArgs);
2370
2325
  };
2371
2326
  const filteredCollections = await Promise.all(collections.filter((col) => !siteId || col.shared || !col.siteId || col.siteId === siteId).map(async (col) => ({
@@ -2458,8 +2413,7 @@ function registerRoutes(app, config) {
2458
2413
  let collections = [...config.collections];
2459
2414
  if (siteId && config.onSchemaFetch) {
2460
2415
  const dynamic = await config.onSchemaFetch(siteId);
2461
- if (dynamic.collections)
2462
- collections = [...collections, ...dynamic.collections];
2416
+ if (dynamic.collections) collections = [...collections, ...dynamic.collections];
2463
2417
  }
2464
2418
  const user = c.get("user");
2465
2419
  let collection = collections.find((col) => col.slug === colSlug);
@@ -2478,8 +2432,7 @@ function registerRoutes(app, config) {
2478
2432
  let globals = [...config.globals];
2479
2433
  if (siteId && config.onSchemaFetch) {
2480
2434
  const dynamic = await config.onSchemaFetch(siteId);
2481
- if (dynamic.globals)
2482
- globals = [...globals, ...dynamic.globals];
2435
+ if (dynamic.globals) globals = [...globals, ...dynamic.globals];
2483
2436
  }
2484
2437
  const glb = globals.find((g) => g.slug === colSlug);
2485
2438
  if (!glb) {
@@ -2537,12 +2490,9 @@ function registerRoutes(app, config) {
2537
2490
  const user = c.get("user");
2538
2491
  const key = c.req.param("key");
2539
2492
  const scope = c.req.query("scope");
2540
- if (!db)
2541
- return c.json({ message: "Database not configured" }, 500);
2542
- if (!user?.collection || !user.sub)
2543
- return c.json({ error: true, message: "Authentication required." }, 401);
2544
- if (!key)
2545
- return c.json({ error: true, message: "Preference key is required." }, 400);
2493
+ if (!db) return c.json({ message: "Database not configured" }, 500);
2494
+ if (!user?.collection || !user.sub) return c.json({ error: true, message: "Authentication required." }, 401);
2495
+ if (!key) return c.json({ error: true, message: "Preference key is required." }, 400);
2546
2496
  const getGlobalPreference = async () => {
2547
2497
  const globalDoc = await db.findOne({ collection: "__global_preferences", id: key });
2548
2498
  return globalDoc ? globalDoc.value : null;
@@ -2552,8 +2502,7 @@ function registerRoutes(app, config) {
2552
2502
  return c.json({ key, value: globalValue2 });
2553
2503
  }
2554
2504
  const doc = await db.findOne({ collection: user.collection, id: user.sub });
2555
- if (!doc)
2556
- return c.json({ error: true, message: "User not found." }, 404);
2505
+ if (!doc) return c.json({ error: true, message: "User not found." }, 404);
2557
2506
  const preferences = typeof doc.__preferences === "object" && doc.__preferences !== null ? doc.__preferences : {};
2558
2507
  if (key in preferences) {
2559
2508
  return c.json({ key, value: preferences[key] ?? null });
@@ -2566,12 +2515,9 @@ function registerRoutes(app, config) {
2566
2515
  const user = c.get("user");
2567
2516
  const key = c.req.param("key");
2568
2517
  const scope = c.req.query("scope");
2569
- if (!db)
2570
- return c.json({ message: "Database not configured" }, 500);
2571
- if (!user?.collection || !user.sub)
2572
- return c.json({ error: true, message: "Authentication required." }, 401);
2573
- if (!key)
2574
- return c.json({ error: true, message: "Preference key is required." }, 400);
2518
+ if (!db) return c.json({ message: "Database not configured" }, 500);
2519
+ if (!user?.collection || !user.sub) return c.json({ error: true, message: "Authentication required." }, 401);
2520
+ if (!key) return c.json({ error: true, message: "Preference key is required." }, 400);
2575
2521
  const body = await c.req.json().catch(() => ({}));
2576
2522
  if (scope === "global") {
2577
2523
  const isAdminUser = Array.isArray(user?.roles) && user.roles.includes("admin");
@@ -2594,8 +2540,7 @@ function registerRoutes(app, config) {
2594
2540
  return c.json({ key, value: body.value });
2595
2541
  }
2596
2542
  const doc = await db.findOne({ collection: user.collection, id: user.sub });
2597
- if (!doc)
2598
- return c.json({ error: true, message: "User not found." }, 404);
2543
+ if (!doc) return c.json({ error: true, message: "User not found." }, 404);
2599
2544
  const preferences = typeof doc.__preferences === "object" && doc.__preferences !== null ? doc.__preferences : {};
2600
2545
  const nextPreferences = { ...preferences, [key]: body.value };
2601
2546
  await db.update({
@@ -2610,12 +2555,9 @@ function registerRoutes(app, config) {
2610
2555
  const user = c.get("user");
2611
2556
  const key = c.req.param("key");
2612
2557
  const scope = c.req.query("scope");
2613
- if (!db)
2614
- return c.json({ message: "Database not configured" }, 500);
2615
- if (!user?.collection || !user.sub)
2616
- return c.json({ error: true, message: "Authentication required." }, 401);
2617
- if (!key)
2618
- return c.json({ error: true, message: "Preference key is required." }, 400);
2558
+ if (!db) return c.json({ message: "Database not configured" }, 500);
2559
+ if (!user?.collection || !user.sub) return c.json({ error: true, message: "Authentication required." }, 401);
2560
+ if (!key) return c.json({ error: true, message: "Preference key is required." }, 400);
2619
2561
  if (scope === "global") {
2620
2562
  const isAdminUser = Array.isArray(user?.roles) && user.roles.includes("admin");
2621
2563
  if (!isAdminUser) {
@@ -2625,8 +2567,7 @@ function registerRoutes(app, config) {
2625
2567
  return c.json({ success: true });
2626
2568
  }
2627
2569
  const doc = await db.findOne({ collection: user.collection, id: user.sub });
2628
- if (!doc)
2629
- return c.json({ error: true, message: "User not found." }, 404);
2570
+ if (!doc) return c.json({ error: true, message: "User not found." }, 404);
2630
2571
  const preferences = typeof doc.__preferences === "object" && doc.__preferences !== null ? { ...doc.__preferences } : {};
2631
2572
  delete preferences[key];
2632
2573
  await db.update({
@@ -2662,8 +2603,7 @@ function registerRoutes(app, config) {
2662
2603
  app.post("/api/admin/auth/:provider/exchange", (c) => adminAuthController.exchange(c));
2663
2604
  app.post("/api/admin/logout", (c) => adminAuthController.logout(c));
2664
2605
  for (const collection of config.collections) {
2665
- if (!collection.auth)
2666
- continue;
2606
+ if (!collection.auth) continue;
2667
2607
  const path = `/api/collections/${collection.slug}`;
2668
2608
  const authController = new AuthController(collection);
2669
2609
  app.post(`${path}/login`, (c) => authController.login(c));
@@ -2765,39 +2705,25 @@ function registerRoutes(app, config) {
2765
2705
  if (collection.auth && id) {
2766
2706
  const authController = new AuthController(collection);
2767
2707
  const method2 = c.req.method;
2768
- if (method2 === "POST" && id === "login")
2769
- return authController.login(c);
2770
- if (method2 === "POST" && id === "logout")
2771
- return authController.logout(c);
2772
- if (method2 === "GET" && id === "me")
2773
- return authController.me(c);
2774
- if (method2 === "POST" && id === "refresh-token")
2775
- return authController.refreshToken(c);
2776
- if (method2 === "POST" && id === "forgot-password")
2777
- return authController.forgotPassword(c);
2778
- if (method2 === "POST" && id === "reset-password")
2779
- return authController.resetPassword(c);
2708
+ if (method2 === "POST" && id === "login") return authController.login(c);
2709
+ if (method2 === "POST" && id === "logout") return authController.logout(c);
2710
+ if (method2 === "GET" && id === "me") return authController.me(c);
2711
+ if (method2 === "POST" && id === "refresh-token") return authController.refreshToken(c);
2712
+ if (method2 === "POST" && id === "forgot-password") return authController.forgotPassword(c);
2713
+ if (method2 === "POST" && id === "reset-password") return authController.resetPassword(c);
2780
2714
  }
2781
2715
  const controller = new CollectionController(collection);
2782
2716
  const method = c.req.method;
2783
2717
  if (id) {
2784
- if (method === "GET")
2785
- return controller.findOne(c);
2786
- if (method === "PATCH")
2787
- return controller.update(c);
2788
- if (method === "DELETE" && id === "delete-many")
2789
- return controller.deleteMany(c);
2790
- if (method === "DELETE")
2791
- return controller.delete(c);
2792
- if (method === "POST" && id === "media")
2793
- return controller.create(c);
2794
- if (method === "POST" && id === "seed")
2795
- return controller.seed(c);
2718
+ if (method === "GET") return controller.findOne(c);
2719
+ if (method === "PATCH") return controller.update(c);
2720
+ if (method === "DELETE" && id === "delete-many") return controller.deleteMany(c);
2721
+ if (method === "DELETE") return controller.delete(c);
2722
+ if (method === "POST" && id === "media") return controller.create(c);
2723
+ if (method === "POST" && id === "seed") return controller.seed(c);
2796
2724
  } else {
2797
- if (method === "GET")
2798
- return controller.find(c);
2799
- if (method === "POST")
2800
- return controller.create(c);
2725
+ if (method === "GET") return controller.find(c);
2726
+ if (method === "POST") return controller.create(c);
2801
2727
  }
2802
2728
  }
2803
2729
  }
@@ -2818,13 +2744,10 @@ function registerRoutes(app, config) {
2818
2744
  const controller = new GlobalController(global);
2819
2745
  const method = c.req.method;
2820
2746
  if (id) {
2821
- if (method === "POST" && id === "seed")
2822
- return controller.seed(c);
2747
+ if (method === "POST" && id === "seed") return controller.seed(c);
2823
2748
  } else {
2824
- if (method === "GET")
2825
- return controller.get(c);
2826
- if (method === "PATCH")
2827
- return controller.update(c);
2749
+ if (method === "GET") return controller.get(c);
2750
+ if (method === "PATCH") return controller.update(c);
2828
2751
  }
2829
2752
  }
2830
2753
  }
@@ -2832,7 +2755,7 @@ function registerRoutes(app, config) {
2832
2755
  });
2833
2756
  }
2834
2757
 
2835
- // src/app.js
2758
+ // src/app.ts
2836
2759
  async function createDyrectedApp(rawConfig) {
2837
2760
  const config = normalizeConfig(rawConfig);
2838
2761
  const app = new Hono();