@kyro-cms/core 0.9.1 → 0.9.2

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.
Files changed (180) hide show
  1. package/README.md +0 -6
  2. package/dist/{WebhookService-Yg2UEOB4.d.cts → WebhookService-BKszZlG0.d.cts} +1 -1
  3. package/dist/{WebhookService-CUTb9XOy.d.ts → WebhookService-Ccf1j-IN.d.ts} +1 -1
  4. package/dist/api-handler-graphql.cjs +17 -17
  5. package/dist/api-handler-graphql.js +13 -13
  6. package/dist/api-handler-trpc.cjs +15 -15
  7. package/dist/api-handler-trpc.js +13 -13
  8. package/dist/api-handler.cjs +16 -16
  9. package/dist/api-handler.js +13 -13
  10. package/dist/{base-DaqY2GhA.d.ts → base-CIuXkrH4.d.cts} +3 -5
  11. package/dist/{base-B71y_EAF.d.cts → base-fFo4lqER.d.ts} +3 -5
  12. package/dist/bootstrap-3PV3GJ3S.js +7 -0
  13. package/dist/{bootstrap-T5BK77LD.js.map → bootstrap-3PV3GJ3S.js.map} +1 -1
  14. package/dist/bootstrap-4CELFLJO.cjs +32 -0
  15. package/dist/{bootstrap-5NLASFOG.cjs.map → bootstrap-4CELFLJO.cjs.map} +1 -1
  16. package/dist/{chunk-Z6ZWNWWR.js → chunk-4CV4JOE5.js} +3 -9
  17. package/dist/{chunk-Z6ZWNWWR.js.map → chunk-4CV4JOE5.js.map} +1 -1
  18. package/dist/{chunk-5EPFQUQD.js → chunk-53NYVYVX.js} +6 -6
  19. package/dist/chunk-53NYVYVX.js.map +1 -0
  20. package/dist/{chunk-22M4O4ZJ.js → chunk-5H3MWQJS.js} +129 -143
  21. package/dist/chunk-5H3MWQJS.js.map +1 -0
  22. package/dist/{chunk-RAMGUDJN.cjs → chunk-5PMQQFRE.cjs} +5 -5
  23. package/dist/{chunk-RAMGUDJN.cjs.map → chunk-5PMQQFRE.cjs.map} +1 -1
  24. package/dist/{chunk-TXSZFA4G.js → chunk-6UNONDW7.js} +93 -9
  25. package/dist/chunk-6UNONDW7.js.map +1 -0
  26. package/dist/{chunk-C36TMDTY.cjs → chunk-7OS7TX2Q.cjs} +49 -48
  27. package/dist/chunk-7OS7TX2Q.cjs.map +1 -0
  28. package/dist/{chunk-3TPQ2BU6.js → chunk-BYBMTIMT.js} +2 -6
  29. package/dist/chunk-BYBMTIMT.js.map +1 -0
  30. package/dist/{chunk-FOPGUM27.js → chunk-CJX74IYK.js} +5 -4
  31. package/dist/chunk-CJX74IYK.js.map +1 -0
  32. package/dist/{chunk-RSF3UU7H.cjs → chunk-CNKT4PME.cjs} +196 -200
  33. package/dist/chunk-CNKT4PME.cjs.map +1 -0
  34. package/dist/{chunk-G7VZBCD6.cjs → chunk-CZLDE2OZ.cjs} +2 -9
  35. package/dist/{chunk-G7VZBCD6.cjs.map → chunk-CZLDE2OZ.cjs.map} +1 -1
  36. package/dist/{chunk-JOPVMWTM.cjs → chunk-DPA3KWPY.cjs} +3 -3
  37. package/dist/chunk-DPA3KWPY.cjs.map +1 -0
  38. package/dist/{chunk-ROJHKAQ4.cjs → chunk-E2763JUP.cjs} +143 -157
  39. package/dist/chunk-E2763JUP.cjs.map +1 -0
  40. package/dist/{chunk-FAXU7BMP.js → chunk-E5UJBLQ7.js} +2 -2
  41. package/dist/chunk-E5UJBLQ7.js.map +1 -0
  42. package/dist/{chunk-DVD5P72E.cjs → chunk-EEJUFDMF.cjs} +2 -6
  43. package/dist/chunk-EEJUFDMF.cjs.map +1 -0
  44. package/dist/{chunk-2HZRBATX.cjs → chunk-FSKONGCX.cjs} +2 -2
  45. package/dist/chunk-FSKONGCX.cjs.map +1 -0
  46. package/dist/{chunk-P2HKJ7P5.js → chunk-GAAHG2Z4.js} +3 -3
  47. package/dist/{chunk-P2HKJ7P5.js.map → chunk-GAAHG2Z4.js.map} +1 -1
  48. package/dist/{chunk-PI73NNOK.cjs → chunk-GUUB5EAG.cjs} +2 -2
  49. package/dist/chunk-GUUB5EAG.cjs.map +1 -0
  50. package/dist/{chunk-PU2Z5VWF.js → chunk-IPTZM3VE.js} +183 -187
  51. package/dist/chunk-IPTZM3VE.js.map +1 -0
  52. package/dist/{chunk-UERVXYVK.cjs → chunk-NWUEVLQT.cjs} +13 -13
  53. package/dist/{chunk-UERVXYVK.cjs.map → chunk-NWUEVLQT.cjs.map} +1 -1
  54. package/dist/{chunk-KPA4AN4R.js → chunk-OHC6UHFY.js} +86 -12
  55. package/dist/chunk-OHC6UHFY.js.map +1 -0
  56. package/dist/{chunk-DEVFAKCQ.cjs → chunk-PHJRNPHY.cjs} +6 -6
  57. package/dist/chunk-PHJRNPHY.cjs.map +1 -0
  58. package/dist/{chunk-VO35MNPH.js → chunk-PQ72Z6WC.js} +67 -105
  59. package/dist/chunk-PQ72Z6WC.js.map +1 -0
  60. package/dist/{chunk-KNRSROWB.cjs → chunk-PV2I2KMI.cjs} +86 -12
  61. package/dist/chunk-PV2I2KMI.cjs.map +1 -0
  62. package/dist/{chunk-V2TVSCV5.cjs → chunk-Q23GAMLE.cjs} +71 -109
  63. package/dist/chunk-Q23GAMLE.cjs.map +1 -0
  64. package/dist/{chunk-COIASRDK.cjs → chunk-RFFSZSCL.cjs} +107 -171
  65. package/dist/chunk-RFFSZSCL.cjs.map +1 -0
  66. package/dist/{chunk-AL5KX63J.js → chunk-UUDTPZX6.js} +3 -3
  67. package/dist/chunk-UUDTPZX6.js.map +1 -0
  68. package/dist/{chunk-EJN2PAOE.js → chunk-V7KZQIZ6.js} +102 -166
  69. package/dist/chunk-V7KZQIZ6.js.map +1 -0
  70. package/dist/{chunk-DYTZ6FQ7.js → chunk-WXVB364T.js} +2 -2
  71. package/dist/chunk-WXVB364T.js.map +1 -0
  72. package/dist/{chunk-WNCYAKF3.cjs → chunk-Y7AQK4R4.cjs} +93 -9
  73. package/dist/chunk-Y7AQK4R4.cjs.map +1 -0
  74. package/dist/{chunk-SPBTLUN6.js → chunk-YFAVQQTU.js} +7 -7
  75. package/dist/{chunk-SPBTLUN6.js.map → chunk-YFAVQQTU.js.map} +1 -1
  76. package/dist/cli/index.cjs +5 -5
  77. package/dist/cli/index.js +5 -5
  78. package/dist/client.cjs +4 -4
  79. package/dist/client.d.cts +2 -2
  80. package/dist/client.d.ts +2 -2
  81. package/dist/client.js +2 -2
  82. package/dist/drizzle/index.cjs +14 -14
  83. package/dist/drizzle/index.d.cts +4 -10
  84. package/dist/drizzle/index.d.ts +4 -10
  85. package/dist/drizzle/index.js +5 -5
  86. package/dist/fields/index.cjs +22 -22
  87. package/dist/fields/index.d.cts +1 -1
  88. package/dist/fields/index.d.ts +1 -1
  89. package/dist/fields/index.js +2 -2
  90. package/dist/graphql/index.cjs +1 -1
  91. package/dist/graphql/index.d.cts +3 -3
  92. package/dist/graphql/index.d.ts +3 -3
  93. package/dist/graphql/index.js +1 -1
  94. package/dist/{index-CaTNnLGd.d.cts → index-BKta3cBH.d.cts} +3 -2
  95. package/dist/{index-CJXPB_ot.d.ts → index-ClOqnkTO.d.ts} +3 -2
  96. package/dist/index.cjs +117 -117
  97. package/dist/index.d.cts +10 -15
  98. package/dist/index.d.ts +10 -15
  99. package/dist/index.js +18 -18
  100. package/dist/integration.cjs +1 -1
  101. package/dist/integration.js +1 -1
  102. package/dist/media-7WDX4BDJ.js +4 -0
  103. package/dist/{media-GPPTZ43E.js.map → media-7WDX4BDJ.js.map} +1 -1
  104. package/dist/{media-XNTUFJZR.cjs → media-TUSLVRQ6.cjs} +3 -3
  105. package/dist/{media-XNTUFJZR.cjs.map → media-TUSLVRQ6.cjs.map} +1 -1
  106. package/dist/{mongo-auth-adapter-ISOM7FSS.cjs → mongo-auth-adapter-GT4S7SCU.cjs} +3 -3
  107. package/dist/{mongo-auth-adapter-ISOM7FSS.cjs.map → mongo-auth-adapter-GT4S7SCU.cjs.map} +1 -1
  108. package/dist/mongo-auth-adapter-M7VV4LNB.js +4 -0
  109. package/dist/{mongo-auth-adapter-MO6STCV3.js.map → mongo-auth-adapter-M7VV4LNB.js.map} +1 -1
  110. package/dist/mongodb/index.cjs +5 -5
  111. package/dist/mongodb/index.d.cts +4 -9
  112. package/dist/mongodb/index.d.ts +4 -9
  113. package/dist/mongodb/index.js +3 -3
  114. package/dist/postgres-auth-adapter-AFAPISH7.js +5 -0
  115. package/dist/{postgres-auth-adapter-DWDR7P5G.js.map → postgres-auth-adapter-AFAPISH7.js.map} +1 -1
  116. package/dist/postgres-auth-adapter-SFDTLONT.cjs +14 -0
  117. package/dist/{postgres-auth-adapter-WRWSJD4E.cjs.map → postgres-auth-adapter-SFDTLONT.cjs.map} +1 -1
  118. package/dist/{redis-adapter-KJ3YOOT6.cjs → redis-adapter-UQX4EE3B.cjs} +3 -3
  119. package/dist/{redis-adapter-KJ3YOOT6.cjs.map → redis-adapter-UQX4EE3B.cjs.map} +1 -1
  120. package/dist/redis-adapter-XALOGWY3.js +4 -0
  121. package/dist/{redis-adapter-HGTPWIGV.js.map → redis-adapter-XALOGWY3.js.map} +1 -1
  122. package/dist/rest/index.cjs +10 -10
  123. package/dist/rest/index.d.cts +4 -4
  124. package/dist/rest/index.d.ts +4 -4
  125. package/dist/rest/index.js +8 -8
  126. package/dist/{schema-TTFE4467.cjs → schema-6QL3USNB.cjs} +15 -15
  127. package/dist/{schema-TTFE4467.cjs.map → schema-6QL3USNB.cjs.map} +1 -1
  128. package/dist/{schema-6I5OFR4Z.js → schema-FNNWEAAW.js} +4 -4
  129. package/dist/{schema-6I5OFR4Z.js.map → schema-FNNWEAAW.js.map} +1 -1
  130. package/dist/{sqlite-adapter-CSIZE5SX.cjs → sqlite-adapter-AQB5TCGV.cjs} +3 -3
  131. package/dist/{sqlite-adapter-CSIZE5SX.cjs.map → sqlite-adapter-AQB5TCGV.cjs.map} +1 -1
  132. package/dist/sqlite-adapter-N5H6IM2X.js +4 -0
  133. package/dist/{sqlite-adapter-6GEUSVXQ.js.map → sqlite-adapter-N5H6IM2X.js.map} +1 -1
  134. package/dist/templates/index.cjs +49 -49
  135. package/dist/templates/index.d.cts +2 -2
  136. package/dist/templates/index.d.ts +2 -2
  137. package/dist/templates/index.js +2 -2
  138. package/dist/trpc/index.cjs +11 -11
  139. package/dist/trpc/index.d.cts +3 -3
  140. package/dist/trpc/index.d.ts +3 -3
  141. package/dist/trpc/index.js +2 -2
  142. package/dist/{types-Z6FBiqa2.d.cts → types-DeSApf9T.d.cts} +1 -0
  143. package/dist/{types-Z6FBiqa2.d.ts → types-DeSApf9T.d.ts} +1 -0
  144. package/dist/{types-CyCQ6SAI.d.ts → types-Dgzlftb7.d.ts} +6 -28
  145. package/dist/{types-DJxD9394.d.cts → types-Ds0tCA3L.d.cts} +6 -28
  146. package/dist/ws/index.cjs +6 -6
  147. package/dist/ws/index.js +2 -2
  148. package/package.json +1 -1
  149. package/dist/bootstrap-5NLASFOG.cjs +0 -32
  150. package/dist/bootstrap-T5BK77LD.js +0 -7
  151. package/dist/chunk-22M4O4ZJ.js.map +0 -1
  152. package/dist/chunk-2HZRBATX.cjs.map +0 -1
  153. package/dist/chunk-3TPQ2BU6.js.map +0 -1
  154. package/dist/chunk-5EPFQUQD.js.map +0 -1
  155. package/dist/chunk-AL5KX63J.js.map +0 -1
  156. package/dist/chunk-C36TMDTY.cjs.map +0 -1
  157. package/dist/chunk-COIASRDK.cjs.map +0 -1
  158. package/dist/chunk-DEVFAKCQ.cjs.map +0 -1
  159. package/dist/chunk-DVD5P72E.cjs.map +0 -1
  160. package/dist/chunk-DYTZ6FQ7.js.map +0 -1
  161. package/dist/chunk-EJN2PAOE.js.map +0 -1
  162. package/dist/chunk-FAXU7BMP.js.map +0 -1
  163. package/dist/chunk-FOPGUM27.js.map +0 -1
  164. package/dist/chunk-JOPVMWTM.cjs.map +0 -1
  165. package/dist/chunk-KNRSROWB.cjs.map +0 -1
  166. package/dist/chunk-KPA4AN4R.js.map +0 -1
  167. package/dist/chunk-PI73NNOK.cjs.map +0 -1
  168. package/dist/chunk-PU2Z5VWF.js.map +0 -1
  169. package/dist/chunk-ROJHKAQ4.cjs.map +0 -1
  170. package/dist/chunk-RSF3UU7H.cjs.map +0 -1
  171. package/dist/chunk-TXSZFA4G.js.map +0 -1
  172. package/dist/chunk-V2TVSCV5.cjs.map +0 -1
  173. package/dist/chunk-VO35MNPH.js.map +0 -1
  174. package/dist/chunk-WNCYAKF3.cjs.map +0 -1
  175. package/dist/media-GPPTZ43E.js +0 -4
  176. package/dist/mongo-auth-adapter-MO6STCV3.js +0 -4
  177. package/dist/postgres-auth-adapter-DWDR7P5G.js +0 -5
  178. package/dist/postgres-auth-adapter-WRWSJD4E.cjs +0 -14
  179. package/dist/redis-adapter-HGTPWIGV.js +0 -4
  180. package/dist/sqlite-adapter-6GEUSVXQ.js +0 -4
@@ -1,15 +1,15 @@
1
- import { PasswordPolicy, ConfigService, EmailTransport } from './chunk-TXSZFA4G.js';
1
+ import { PasswordPolicy, ConfigService, EmailTransport } from './chunk-6UNONDW7.js';
2
2
  import { usersCollection } from './chunk-XEB7PH2E.js';
3
3
  import { SQLiteAuthAdapter } from './chunk-Q72BOAPK.js';
4
4
  import { createAuditContext } from './chunk-P2YW545G.js';
5
5
  import { WEBHOOK_EVENTS } from './chunk-3UK5XBVJ.js';
6
6
  import { API_KEY_COLLECTION, generateApiKey, generateApiKeyPrefix, evaluateAccess, hasApiKeyPermission, extractApiKeyFromRequest, validateApiKey, createApiKeyContext } from './chunk-CJONKRHJ.js';
7
- import { genId, DrizzleAdapter } from './chunk-EJN2PAOE.js';
8
- import { PostgresAuthAdapter } from './chunk-FOPGUM27.js';
9
- import { MongoDBAdapter } from './chunk-VO35MNPH.js';
7
+ import { genId, DrizzleAdapter } from './chunk-V7KZQIZ6.js';
8
+ import { PostgresAuthAdapter } from './chunk-CJX74IYK.js';
9
+ import { MongoDBAdapter } from './chunk-PQ72Z6WC.js';
10
10
  import { MongoDBAuthAdapter } from './chunk-7OGPN7MP.js';
11
11
  import { hasPermission } from './chunk-L4EZKIEX.js';
12
- import { __esm, __export, __toCommonJS, __require } from './chunk-Z6ZWNWWR.js';
12
+ import { __esm, __export, __toCommonJS } from './chunk-4CV4JOE5.js';
13
13
  import crypto, { randomBytes, createHash } from 'crypto';
14
14
  import { createStorage } from 'unstorage';
15
15
  import fsDriver from 'unstorage/drivers/fs';
@@ -20,6 +20,7 @@ import sharp from 'sharp';
20
20
  import { mkdir, readdir, stat, rename, unlink, writeFile } from 'fs/promises';
21
21
  import process2 from 'process';
22
22
  import { S3Client, ListObjectsV2Command, DeleteObjectsCommand, DeleteObjectCommand, PutObjectCommand, HeadObjectCommand, CopyObjectCommand } from '@aws-sdk/client-s3';
23
+ import { NodeHttpHandler } from '@smithy/node-http-handler';
23
24
  import { Readable } from 'stream';
24
25
  import { Client } from 'basic-ftp';
25
26
  import { zodToJsonSchema } from 'zod-to-json-schema';
@@ -31,8 +32,8 @@ async function loadSecrets() {
31
32
  if (dbAdapter) {
32
33
  try {
33
34
  const result = await dbAdapter.findOne({
34
- collection: "_globals",
35
- where: { slug: "system" }
35
+ collection: "_globals_system",
36
+ where: {}
36
37
  });
37
38
  if (result) {
38
39
  cachedSecrets = {
@@ -442,6 +443,9 @@ function createTenantContextFromUser(user) {
442
443
  };
443
444
  }
444
445
 
446
+ // src/api/rest/hono-app.ts
447
+ init_secret();
448
+
445
449
  // src/auth/security/in-memory-rate-limit.ts
446
450
  var InMemoryRateLimiter = class {
447
451
  storage = /* @__PURE__ */ new Map();
@@ -2223,7 +2227,7 @@ function createS3Storage(config) {
2223
2227
  tls: true,
2224
2228
  // R2 requires specific SSL configuration
2225
2229
  ...config.provider === "r2" && {
2226
- requestHandler: new (__require("@smithy/node-http-handler")).NodeHttpHandler({
2230
+ requestHandler: new NodeHttpHandler({
2227
2231
  connectionTimeout: 1e4,
2228
2232
  socketTimeout: 1e4
2229
2233
  })
@@ -2846,9 +2850,7 @@ var MediaService = class _MediaService {
2846
2850
  storage2 = await resolveProviderWithConfig(options.storageConfig);
2847
2851
  } else {
2848
2852
  const configService = new ConfigService(db);
2849
- if (typeof db?.select === "function") {
2850
- await configService.load();
2851
- }
2853
+ await configService.load();
2852
2854
  storage2 = await resolveProvider(configService);
2853
2855
  }
2854
2856
  const service = new _MediaService(db, storage2, options);
@@ -3050,7 +3052,7 @@ var MediaService = class _MediaService {
3050
3052
  ]
3051
3053
  );
3052
3054
  } else {
3053
- const { media: mediaSchema } = await import('./media-GPPTZ43E.js');
3055
+ const { media: mediaSchema } = await import('./media-7WDX4BDJ.js');
3054
3056
  const mime = storageResult.mimeType;
3055
3057
  const mediaType = mime.startsWith("image/") ? "image" : mime.startsWith("video/") ? "video" : mime.startsWith("audio/") ? "audio" : mime.startsWith("application/pdf") ? "document" : ["application/zip", "application/x-zip", "application/x-tar", "application/gzip", "application/x-7z"].includes(mime) ? "archive" : "other";
3056
3058
  await this.db.insert(mediaSchema).values({
@@ -3112,7 +3114,7 @@ var MediaService = class _MediaService {
3112
3114
  id
3113
3115
  ]);
3114
3116
  } else {
3115
- const { media: mediaSchema } = await import('./media-GPPTZ43E.js');
3117
+ const { media: mediaSchema } = await import('./media-7WDX4BDJ.js');
3116
3118
  const { eq } = await import('drizzle-orm');
3117
3119
  const [row] = await this.db.select().from(mediaSchema).where(eq(mediaSchema.id, id));
3118
3120
  if (row) item = this.rowToMedia(row);
@@ -3128,7 +3130,7 @@ var MediaService = class _MediaService {
3128
3130
  if (this.dialect === "sqlite") {
3129
3131
  await this.sqliteRun(`DELETE FROM ${this.mediaTable} WHERE id = ?`, [id]);
3130
3132
  } else {
3131
- const { media: mediaSchema } = await import('./media-GPPTZ43E.js');
3133
+ const { media: mediaSchema } = await import('./media-7WDX4BDJ.js');
3132
3134
  const { eq } = await import('drizzle-orm');
3133
3135
  await this.db.delete(mediaSchema).where(eq(mediaSchema.id, id));
3134
3136
  }
@@ -3143,7 +3145,7 @@ var MediaService = class _MediaService {
3143
3145
  id
3144
3146
  ]);
3145
3147
  } else {
3146
- const { media: mediaSchema } = await import('./media-GPPTZ43E.js');
3148
+ const { media: mediaSchema } = await import('./media-7WDX4BDJ.js');
3147
3149
  const { eq } = await import('drizzle-orm');
3148
3150
  const [row] = await this.db.select().from(mediaSchema).where(eq(mediaSchema.id, id));
3149
3151
  if (row) item = this.rowToMedia(row);
@@ -3178,7 +3180,7 @@ var MediaService = class _MediaService {
3178
3180
  [...vals, this.now(), id]
3179
3181
  );
3180
3182
  } else {
3181
- const { media: mediaSchema } = await import('./media-GPPTZ43E.js');
3183
+ const { media: mediaSchema } = await import('./media-7WDX4BDJ.js');
3182
3184
  const { eq } = await import('drizzle-orm');
3183
3185
  await this.db.update(mediaSchema).set({ ...updateData, updatedAt: this.now() }).where(eq(mediaSchema.id, id));
3184
3186
  }
@@ -3197,7 +3199,7 @@ var MediaService = class _MediaService {
3197
3199
  );
3198
3200
  return row2 ? this.rowToMedia(row2) : null;
3199
3201
  }
3200
- const { media: mediaSchema } = await import('./media-GPPTZ43E.js');
3202
+ const { media: mediaSchema } = await import('./media-7WDX4BDJ.js');
3201
3203
  const { eq } = await import('drizzle-orm');
3202
3204
  const [row] = await this.db.select().from(mediaSchema).where(eq(mediaSchema.id, id));
3203
3205
  return row ? this.rowToMedia(row) : null;
@@ -3245,7 +3247,7 @@ var MediaService = class _MediaService {
3245
3247
  totalPages: Math.ceil(totalDocs2 / limit)
3246
3248
  };
3247
3249
  }
3248
- const { media: mediaSchema } = await import('./media-GPPTZ43E.js');
3250
+ const { media: mediaSchema } = await import('./media-7WDX4BDJ.js');
3249
3251
  const { like, or, and, asc, desc, eq, sql } = await import('drizzle-orm');
3250
3252
  const conditions = [];
3251
3253
  if (search) {
@@ -3324,7 +3326,7 @@ var MediaService = class _MediaService {
3324
3326
  );
3325
3327
  return row ? this.rowToMedia(row) : null;
3326
3328
  }
3327
- const { media: mediaSchema } = await import('./media-GPPTZ43E.js');
3329
+ const { media: mediaSchema } = await import('./media-7WDX4BDJ.js');
3328
3330
  const { eq } = await import('drizzle-orm');
3329
3331
  const [updated] = await this.db.update(mediaSchema).set({ ...data, updatedAt: /* @__PURE__ */ new Date() }).where(eq(mediaSchema.id, id)).returning();
3330
3332
  return updated ? this.rowToMedia(updated) : null;
@@ -3346,7 +3348,7 @@ var MediaService = class _MediaService {
3346
3348
  );
3347
3349
  }
3348
3350
  } else {
3349
- const { media: mediaSchema } = await import('./media-GPPTZ43E.js');
3351
+ const { media: mediaSchema } = await import('./media-7WDX4BDJ.js');
3350
3352
  const { eq } = await import('drizzle-orm');
3351
3353
  for (const id of ids) {
3352
3354
  await this.db.update(mediaSchema).set({ ...data, updatedAt: /* @__PURE__ */ new Date() }).where(eq(mediaSchema.id, id));
@@ -3361,7 +3363,7 @@ var MediaService = class _MediaService {
3361
3363
  );
3362
3364
  return rows.map((r) => r.path).filter((f) => f && f !== "").sort();
3363
3365
  }
3364
- const { media: mediaSchema, mediaFolders: folderSchema } = await import('./media-GPPTZ43E.js');
3366
+ const { media: mediaSchema, mediaFolders: folderSchema } = await import('./media-7WDX4BDJ.js');
3365
3367
  const { eq, sql } = await import('drizzle-orm');
3366
3368
  const fromMedia = await this.db.select({ folder: mediaSchema.folder }).from(mediaSchema).groupBy(mediaSchema.folder);
3367
3369
  const fromFolders = await this.db.select({ path: folderSchema.path }).from(folderSchema);
@@ -3381,7 +3383,7 @@ var MediaService = class _MediaService {
3381
3383
  [fullPath, name, parentPath || null, now]
3382
3384
  );
3383
3385
  } else {
3384
- const { mediaFolders: folderSchema } = await import('./media-GPPTZ43E.js');
3386
+ const { mediaFolders: folderSchema } = await import('./media-7WDX4BDJ.js');
3385
3387
  await this.db.insert(folderSchema).values({
3386
3388
  path: fullPath,
3387
3389
  name,
@@ -3402,7 +3404,7 @@ var MediaService = class _MediaService {
3402
3404
  [folder, `${folder}/%`]
3403
3405
  );
3404
3406
  } else {
3405
- const { mediaFolders: folderSchema } = await import('./media-GPPTZ43E.js');
3407
+ const { mediaFolders: folderSchema } = await import('./media-7WDX4BDJ.js');
3406
3408
  const { like, or, eq } = await import('drizzle-orm');
3407
3409
  await this.db.delete(folderSchema).where(
3408
3410
  or(
@@ -3416,6 +3418,38 @@ var MediaService = class _MediaService {
3416
3418
  function formatZodErrors(errors) {
3417
3419
  return errors.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
3418
3420
  }
3421
+ function normalizeEmptyStrings(data, fields) {
3422
+ if (!data || typeof data !== "object") return;
3423
+ for (const field of fields) {
3424
+ if (!field.name || !(field.name in data)) continue;
3425
+ const val = data[field.name];
3426
+ if (val === "") {
3427
+ const isTextual = field.type === "text" || field.type === "textarea" || field.type === "code" || field.type === "markdown" || field.type === "email" || field.type === "password" || field.type === "color";
3428
+ if (!isTextual) data[field.name] = null;
3429
+ }
3430
+ if (field.type === "tabs" && field.name && Array.isArray(field.tabs) && data[field.name] && typeof data[field.name] === "object") {
3431
+ for (const tab of field.tabs) {
3432
+ if (Array.isArray(tab.fields)) normalizeEmptyStrings(data[field.name], tab.fields);
3433
+ }
3434
+ } else if ((field.type === "group" || field.type === "collapsible") && field.name && Array.isArray(field.fields) && data[field.name] && typeof data[field.name] === "object") {
3435
+ normalizeEmptyStrings(data[field.name], field.fields);
3436
+ } else if (field.type === "array" && field.name && Array.isArray(field.fields) && Array.isArray(data[field.name])) {
3437
+ for (const item of data[field.name]) {
3438
+ if (item && typeof item === "object") normalizeEmptyStrings(item, field.fields);
3439
+ }
3440
+ } else if (field.type === "blocks" && field.name && Array.isArray(field.blocks) && Array.isArray(data[field.name])) {
3441
+ for (const item of data[field.name]) {
3442
+ if (!item || typeof item !== "object") continue;
3443
+ const blockTypeStr = item.type || item.blockType;
3444
+ if (!blockTypeStr) continue;
3445
+ const blockDef = field.blocks.find((b) => b.slug === blockTypeStr);
3446
+ if (!blockDef || !Array.isArray(blockDef.fields)) continue;
3447
+ const target = item.data && typeof item.data === "object" ? item.data : item;
3448
+ normalizeEmptyStrings(target, blockDef.fields);
3449
+ }
3450
+ }
3451
+ }
3452
+ }
3419
3453
  function convertRichtextFields(fields, data) {
3420
3454
  if (!data || typeof data !== "object") return;
3421
3455
  for (const field of fields) {
@@ -3437,6 +3471,16 @@ function convertRichtextFields(fields, data) {
3437
3471
  for (const item of data[field.name]) {
3438
3472
  if (item && typeof item === "object") convertRichtextFields(field.fields, item);
3439
3473
  }
3474
+ } else if (field.type === "blocks" && field.name && Array.isArray(field.blocks) && Array.isArray(data[field.name])) {
3475
+ for (const item of data[field.name]) {
3476
+ if (!item || typeof item !== "object") continue;
3477
+ const blockTypeStr = item.type || item.blockType;
3478
+ if (!blockTypeStr) continue;
3479
+ const blockDef = field.blocks.find((b) => b.slug === blockTypeStr);
3480
+ if (!blockDef || !Array.isArray(blockDef.fields)) continue;
3481
+ const target = item.data && typeof item.data === "object" ? item.data : item;
3482
+ convertRichtextFields(blockDef.fields, target);
3483
+ }
3440
3484
  }
3441
3485
  }
3442
3486
  }
@@ -3533,7 +3577,7 @@ async function checkCollectionAccess(collection, operation, req, ctxUser, ctxTen
3533
3577
  };
3534
3578
  }
3535
3579
  }
3536
- if (ctxUser) {
3580
+ if (ctxUser && !(apiKeyContext?.permissions?.length > 0)) {
3537
3581
  const resource = collection.slug;
3538
3582
  const action = operation === "read" ? "read" : operation === "create" ? "create" : operation === "update" ? "update" : "delete";
3539
3583
  const permission = `${resource}:${action}`;
@@ -3729,6 +3773,13 @@ function createHonoApp(options) {
3729
3773
  baseUrl: process.env.KYRO_BASE_URL || "http://localhost:4321",
3730
3774
  rateLimiter
3731
3775
  });
3776
+ EmailTransport.fromConfig(db).then((transport) => {
3777
+ if (transport) {
3778
+ authRoutes.email = transport;
3779
+ }
3780
+ }).catch((err) => {
3781
+ console.error("[Email] Failed to initialize transport from config:", err);
3782
+ });
3732
3783
  app.post("/api/auth/login", async (c) => authRoutes.login(c.req.raw));
3733
3784
  app.post("/api/auth/register", async (c) => authRoutes.register(c.req.raw));
3734
3785
  app.post("/api/auth/logout", async (c) => authRoutes.logout(c.req.raw));
@@ -4804,15 +4855,13 @@ function createHonoApp(options) {
4804
4855
  });
4805
4856
  app.get("/api/keys", async (c) => {
4806
4857
  try {
4807
- const { user: ctxUser } = await resolveAuthContext(c.req.raw, authMw, user, tenantID);
4858
+ const { user: ctxUser, tenantID: ctxTenantID } = await resolveAuthContext(c.req.raw, authMw, user, tenantID);
4808
4859
  if (!ctxUser || !hasPermission(ctxUser, "users:read")) {
4809
4860
  return c.json({ error: "Forbidden" }, 403);
4810
4861
  }
4811
4862
  const page = parseInt(c.req.query("page") || "1");
4812
4863
  const limit = Math.min(parseInt(c.req.query("limit") || "50"), 100);
4813
- console.log("[ApiKeys] Querying", API_KEY_COLLECTION, { page, limit });
4814
- const result = await db.find({ collection: API_KEY_COLLECTION, where: {}, page, limit });
4815
- console.log("[ApiKeys] Result:", result);
4864
+ const result = await db.find({ collection: API_KEY_COLLECTION, where: {}, page, limit, tenantID: ctxTenantID });
4816
4865
  const docs = (result.docs || []).map((doc) => ({
4817
4866
  id: doc.id,
4818
4867
  name: doc.name,
@@ -5205,36 +5254,6 @@ function createHonoApp(options) {
5205
5254
  return c.json({ error: error.message }, 500);
5206
5255
  }
5207
5256
  });
5208
- app.get(`${basePath}/:id/draft`, async (c) => {
5209
- try {
5210
- const {
5211
- user: ctxUser,
5212
- tenantID: ctxTenantID,
5213
- apiKeyContext
5214
- } = await resolveAuthContext(c.req.raw, authMw, user, tenantID);
5215
- const access = await checkCollectionAccess(
5216
- collection,
5217
- "read",
5218
- c.req.raw,
5219
- ctxUser,
5220
- ctxTenantID,
5221
- apiKeyContext,
5222
- enablePublicAccess,
5223
- defaultCollectionAccess
5224
- );
5225
- if (!access.allowed) {
5226
- return c.json({ error: access.error }, access.status || 403);
5227
- }
5228
- const draft = await db.findDraft({
5229
- collection: slug,
5230
- documentId: c.req.param("id"),
5231
- tenantID: ctxTenantID
5232
- });
5233
- return c.json({ data: draft });
5234
- } catch (error) {
5235
- return c.json({ error: error.message }, 500);
5236
- }
5237
- });
5238
5257
  app.put(`${basePath}/:id/draft`, async (c) => {
5239
5258
  try {
5240
5259
  const {
@@ -5273,13 +5292,12 @@ function createHonoApp(options) {
5273
5292
  } else {
5274
5293
  finalData = body.data ?? omitRevisionFields(body);
5275
5294
  }
5276
- const draft = await db.upsertDraft({
5295
+ const version = await db.updateLatestVersion({
5277
5296
  collection: slug,
5278
5297
  documentId: id,
5279
- tenantID: ctxTenantID,
5280
5298
  data: finalData,
5281
- baseUpdatedAt,
5282
- draftUpdatedAt: body.draftUpdatedAt
5299
+ status: "draft",
5300
+ tenantID: ctxTenantID
5283
5301
  });
5284
5302
  if (ctxUser) {
5285
5303
  sessionAuthAdapter?.createAuditLog({
@@ -5291,7 +5309,7 @@ function createHonoApp(options) {
5291
5309
  metadata: { type: "draft_save" }
5292
5310
  });
5293
5311
  }
5294
- return c.json({ data: draft, message: "Draft saved successfully" });
5312
+ return c.json({ data: version, message: "Draft saved successfully" });
5295
5313
  } catch (error) {
5296
5314
  return c.json({ error: error.message }, 500);
5297
5315
  }
@@ -5316,11 +5334,6 @@ function createHonoApp(options) {
5316
5334
  if (!access.allowed) {
5317
5335
  return c.json({ error: access.error }, access.status || 403);
5318
5336
  }
5319
- await db.deleteDraft({
5320
- collection: slug,
5321
- documentId: c.req.param("id"),
5322
- tenantID: ctxTenantID
5323
- });
5324
5337
  if (ctxUser) {
5325
5338
  sessionAuthAdapter?.createAuditLog({
5326
5339
  action: "document_update",
@@ -5412,14 +5425,7 @@ function createHonoApp(options) {
5412
5425
  auditApiKeyUsage(sessionAuthAdapter, apiKeyContext, basePath, "POST", c.req.raw);
5413
5426
  const body = await c.req.json();
5414
5427
  let validated = body;
5415
- for (const field of collection.fields) {
5416
- if (field.name && validated[field.name] === "") {
5417
- const isTextual = field.type === "text" || field.type === "textarea" || field.type === "code" || field.type === "markdown" || field.type === "email" || field.type === "password" || field.type === "color";
5418
- if (!isTextual) {
5419
- validated[field.name] = null;
5420
- }
5421
- }
5422
- }
5428
+ normalizeEmptyStrings(validated, collection.fields);
5423
5429
  convertRichtextFields(collection.fields, validated);
5424
5430
  const hookReq = c.req.raw;
5425
5431
  if (collection.hooks?.beforeValidate) {
@@ -5445,10 +5451,7 @@ function createHonoApp(options) {
5445
5451
  validated.tenantID = ctxTenantID;
5446
5452
  }
5447
5453
  const isDraftEnabled = collection.versions?.drafts === true;
5448
- if (isDraftEnabled) {
5449
- validated.publishStatus = "draft";
5450
- validated.hasDraft = false;
5451
- }
5454
+ validated.status = isDraftEnabled ? "draft" : "published";
5452
5455
  if (collection.hooks?.beforeChange) {
5453
5456
  for (const hook of collection.hooks.beforeChange) {
5454
5457
  const hookResult = await hook({
@@ -5467,6 +5470,17 @@ function createHonoApp(options) {
5467
5470
  data: validated,
5468
5471
  tenantID: ctxTenantID
5469
5472
  });
5473
+ if (isDraftEnabled) {
5474
+ await db.createVersion({
5475
+ collection: slug,
5476
+ documentId: doc.id,
5477
+ data: validated,
5478
+ status: "draft",
5479
+ createdBy: ctxUser?.id,
5480
+ changeDescription: "Created",
5481
+ tenantID: ctxTenantID
5482
+ });
5483
+ }
5470
5484
  if (collection.hooks?.afterChange) {
5471
5485
  for (const hook of collection.hooks.afterChange) {
5472
5486
  await hook({
@@ -5532,11 +5546,6 @@ function createHonoApp(options) {
5532
5546
  const id = c.req.param("id");
5533
5547
  const body = await c.req.json();
5534
5548
  const baseUpdatedAt = readBaseUpdatedAt(body);
5535
- console.log(`[PATCH] ${slug}/${id}`, {
5536
- baseUpdatedAt,
5537
- bodyKeys: Object.keys(body),
5538
- tenantID: ctxTenantID
5539
- });
5540
5549
  const originalDoc = await db.findByID({
5541
5550
  collection: slug,
5542
5551
  id,
@@ -5554,14 +5563,7 @@ function createHonoApp(options) {
5554
5563
  ([_, v]) => v !== "null" && v !== void 0
5555
5564
  )
5556
5565
  );
5557
- for (const field of collection.fields) {
5558
- if (field.name && validated[field.name] === "") {
5559
- const isTextual = field.type === "text" || field.type === "textarea" || field.type === "code" || field.type === "markdown" || field.type === "email" || field.type === "password" || field.type === "color";
5560
- if (!isTextual) {
5561
- validated[field.name] = null;
5562
- }
5563
- }
5564
- }
5566
+ normalizeEmptyStrings(validated, collection.fields);
5565
5567
  convertRichtextFields(collection.fields, validated);
5566
5568
  const hookReq = c.req.raw;
5567
5569
  if (collection.hooks?.beforeValidate) {
@@ -5594,37 +5596,44 @@ function createHonoApp(options) {
5594
5596
  if (hookResult) Object.assign(validated, hookResult);
5595
5597
  }
5596
5598
  }
5597
- console.log(`[PATCH] Validated data:`, Object.keys(validated));
5599
+ const isDraft = c.req.header("X-Draft") === "true";
5598
5600
  const isDraftEnabled = collection.versions?.drafts === true;
5599
- const isAlreadyPublished = originalDoc.publishStatus === "published";
5601
+ const isAutosave = c.req.query("autosave") === "true";
5600
5602
  let doc;
5601
- if (isDraftEnabled && isAlreadyPublished) {
5603
+ if (isDraftEnabled && isDraft) {
5602
5604
  await db.createVersion({
5603
5605
  collection: slug,
5604
5606
  documentId: id,
5605
5607
  data: validated,
5606
5608
  status: "draft",
5609
+ autosave: isAutosave,
5607
5610
  createdBy: ctxUser?.id,
5608
- changeDescription: "Manual save (Draft)",
5611
+ changeDescription: isAutosave ? "Autosave" : "Draft saved",
5609
5612
  tenantID: ctxTenantID
5610
5613
  });
5614
+ } else if (isDraftEnabled) {
5611
5615
  await db.update({
5612
5616
  collection: slug,
5613
5617
  id,
5614
- data: { hasDraft: true },
5615
- // Keep old data, just set flag
5618
+ data: { ...validated, status: "published" },
5619
+ tenantID: ctxTenantID
5620
+ });
5621
+ await db.createVersion({
5622
+ collection: slug,
5623
+ documentId: id,
5624
+ data: validated,
5625
+ status: "published",
5626
+ createdBy: ctxUser?.id,
5627
+ changeDescription: "Published",
5616
5628
  tenantID: ctxTenantID
5617
5629
  });
5618
5630
  } else {
5619
- const saveData = isDraftEnabled ? { ...validated, publishStatus: "draft", hasDraft: false } : validated;
5620
- console.log(`[PATCH] About to call db.update for ${slug}/${id} with keys:`, Object.keys(saveData));
5621
5631
  await db.update({
5622
5632
  collection: slug,
5623
5633
  id,
5624
- data: saveData,
5634
+ data: validated,
5625
5635
  tenantID: ctxTenantID
5626
5636
  });
5627
- console.log(`[PATCH] db.update SUCCEEDED for ${slug}/${id}`);
5628
5637
  }
5629
5638
  doc = await db.findByID({
5630
5639
  collection: slug,
@@ -5632,25 +5641,6 @@ function createHonoApp(options) {
5632
5641
  tenantID: ctxTenantID,
5633
5642
  draft: true
5634
5643
  });
5635
- if (isDraftEnabled) {
5636
- if (!isAlreadyPublished) {
5637
- await db.createVersion({
5638
- collection: slug,
5639
- documentId: id,
5640
- data: validated,
5641
- status: "draft",
5642
- createdBy: ctxUser?.id,
5643
- changeDescription: "Manual save",
5644
- tenantID: ctxTenantID
5645
- });
5646
- }
5647
- } else {
5648
- await db.deleteDraft({
5649
- collection: slug,
5650
- documentId: id,
5651
- tenantID: ctxTenantID
5652
- });
5653
- }
5654
5644
  if (collection.hooks?.afterChange) {
5655
5645
  for (const hook of collection.hooks.afterChange) {
5656
5646
  await hook({
@@ -5722,7 +5712,6 @@ function createHonoApp(options) {
5722
5712
  db.setTenantContext({ tenantId: ctxTenantID, userId: ctxUser?.id ?? "", role: ctxUser?.role, isSuperAdmin: ctxUser?.role === "super_admin" });
5723
5713
  }
5724
5714
  const id = c.req.param("id");
5725
- console.log(`[DELETE] Deleting ${slug}/${id}`);
5726
5715
  const hookReq = c.req.raw;
5727
5716
  const originalDoc = await db.findByID({
5728
5717
  collection: slug,
@@ -5750,11 +5739,6 @@ function createHonoApp(options) {
5750
5739
  id,
5751
5740
  tenantID: ctxTenantID
5752
5741
  });
5753
- await db.deleteDraft({
5754
- collection: slug,
5755
- documentId: id,
5756
- tenantID: ctxTenantID
5757
- });
5758
5742
  if (collection.hooks?.afterDelete) {
5759
5743
  for (const hook of collection.hooks.afterDelete) {
5760
5744
  await hook({
@@ -5796,7 +5780,6 @@ function createHonoApp(options) {
5796
5780
  });
5797
5781
  app.post(`${basePath}/:id/duplicate`, async (c) => {
5798
5782
  try {
5799
- console.log(`[Duplicate] Request for ${slug}`);
5800
5783
  const {
5801
5784
  user: ctxUser,
5802
5785
  tenantID: ctxTenantID,
@@ -5813,11 +5796,9 @@ function createHonoApp(options) {
5813
5796
  defaultCollectionAccess
5814
5797
  );
5815
5798
  if (!access.allowed) {
5816
- console.log("[Duplicate] Access denied:", access.error);
5817
5799
  return c.json({ error: access.error }, access.status || 403);
5818
5800
  }
5819
5801
  const id = c.req.param("id");
5820
- console.log(`[Duplicate] ID: ${id}`);
5821
5802
  const originalDoc = await db.findByID({
5822
5803
  collection: slug,
5823
5804
  id,
@@ -5825,14 +5806,11 @@ function createHonoApp(options) {
5825
5806
  draft: true
5826
5807
  });
5827
5808
  if (!originalDoc) {
5828
- console.log("[Duplicate] Document not found");
5829
5809
  return c.json({ error: "Document not found" }, 404);
5830
5810
  }
5831
- console.log(`[Duplicate] Original doc:`, originalDoc);
5832
5811
  const { id: _oldId, createdAt: _oldCreated, updatedAt: _oldUpdated, ...docData } = originalDoc;
5833
5812
  const timestamp = Date.now().toString(36);
5834
5813
  const newSlug = `${originalDoc.slug || "document"}-copy-${timestamp}`;
5835
- console.log(`[Duplicate] New slug: ${newSlug}`);
5836
5814
  const newDoc = await db.create({
5837
5815
  collection: slug,
5838
5816
  data: {
@@ -5842,7 +5820,6 @@ function createHonoApp(options) {
5842
5820
  },
5843
5821
  tenantID: ctxTenantID
5844
5822
  });
5845
- console.log(`[Duplicate] Created successfully:`, newDoc.id);
5846
5823
  return c.json({ data: newDoc, message: "Document duplicated successfully" });
5847
5824
  } catch (error) {
5848
5825
  console.error("[Duplicate] Error:", error);
@@ -5882,7 +5859,7 @@ function createHonoApp(options) {
5882
5859
  const doc = await db.update({
5883
5860
  collection: slug,
5884
5861
  id,
5885
- data: { ...version.data, publishStatus: "draft", hasDraft: false },
5862
+ data: { ...version.data, status: "draft" },
5886
5863
  tenantID: ctxTenantID
5887
5864
  });
5888
5865
  return c.json({
@@ -5927,7 +5904,7 @@ function createHonoApp(options) {
5927
5904
  const doc = await db.update({
5928
5905
  collection: slug,
5929
5906
  id: c.req.param("id"),
5930
- data: { ...version.data, publishStatus: "draft", hasDraft: false },
5907
+ data: { ...version.data, status: "draft" },
5931
5908
  tenantID: ctxTenantID
5932
5909
  });
5933
5910
  return c.json({
@@ -5978,9 +5955,9 @@ function createHonoApp(options) {
5978
5955
  if (baseUpdatedAt && originalDoc.updatedAt && baseUpdatedAt !== originalDoc.updatedAt) {
5979
5956
  return c.json(buildConflictResponse(baseUpdatedAt, originalDoc), 409);
5980
5957
  }
5981
- let publishData = { publishStatus: "published", hasDraft: false };
5958
+ let publishData = { status: "published" };
5982
5959
  let finalContent = originalDoc;
5983
- if (originalDoc.hasDraft) {
5960
+ if (collection.versions?.drafts) {
5984
5961
  const versions = await db.findVersions({
5985
5962
  collection: slug,
5986
5963
  documentId: id,
@@ -5988,9 +5965,10 @@ function createHonoApp(options) {
5988
5965
  sort: "-createdAt",
5989
5966
  tenantID: ctxTenantID
5990
5967
  });
5991
- if (versions.docs.length > 0 && versions.docs[0].status === "draft") {
5992
- finalContent = { ...originalDoc, ...versions.docs[0].data };
5993
- publishData = { ...versions.docs[0].data, ...publishData };
5968
+ if (versions.docs.length > 0) {
5969
+ const latestVersion = versions.docs[0];
5970
+ finalContent = { ...originalDoc, ...latestVersion.data };
5971
+ publishData = { ...latestVersion.data, ...publishData };
5994
5972
  }
5995
5973
  }
5996
5974
  const doc = await db.update({
@@ -6003,18 +5981,13 @@ function createHonoApp(options) {
6003
5981
  await db.createVersion({
6004
5982
  collection: slug,
6005
5983
  documentId: id,
6006
- data: { ...finalContent, publishStatus: "published" },
5984
+ data: { ...finalContent, status: "published" },
6007
5985
  status: "published",
6008
5986
  createdBy: ctxUser?.id,
6009
5987
  changeDescription: "Published",
6010
5988
  tenantID: ctxTenantID
6011
5989
  });
6012
5990
  }
6013
- await db.deleteDraft({
6014
- collection: slug,
6015
- documentId: id,
6016
- tenantID: ctxTenantID
6017
- });
6018
5991
  if (webhookService) {
6019
5992
  webhookService.trigger(getWebhookEvent(slug, "update"), {
6020
5993
  collection: slug,
@@ -6062,7 +6035,7 @@ function createHonoApp(options) {
6062
6035
  const doc = await db.update({
6063
6036
  collection: slug,
6064
6037
  id,
6065
- data: { publishStatus: "draft" },
6038
+ data: { status: "draft" },
6066
6039
  tenantID: ctxTenantID
6067
6040
  });
6068
6041
  if (webhookService) {
@@ -6097,7 +6070,7 @@ function createHonoApp(options) {
6097
6070
  if (!access.allowed) {
6098
6071
  return c.json({ error: access.error }, access.status || 403);
6099
6072
  }
6100
- const isDraftRequest = c.req.query("draft") === "true" && !!ctxUser;
6073
+ const isDraftRequest = !!ctxUser;
6101
6074
  let doc = await db.findOne({
6102
6075
  collection: `_globals_${slug}`,
6103
6076
  where: {},
@@ -6145,23 +6118,16 @@ function createHonoApp(options) {
6145
6118
  const cleaned = Object.fromEntries(
6146
6119
  Object.entries(body).filter(([_, v]) => v !== null && v !== "null" && v !== void 0)
6147
6120
  );
6148
- for (const field of globalConfig.fields) {
6149
- if (field.name && cleaned[field.name] === "") {
6150
- const isTextual = field.type === "text" || field.type === "textarea" || field.type === "code" || field.type === "markdown" || field.type === "email" || field.type === "password" || field.type === "color";
6151
- if (!isTextual) {
6152
- cleaned[field.name] = null;
6153
- }
6154
- }
6155
- }
6121
+ normalizeEmptyStrings(cleaned, globalConfig.fields);
6156
6122
  convertRichtextFields(globalConfig.fields, cleaned);
6157
- const schema = registry.getZodSchema(slug);
6123
+ const schema = registry.getUpdateZodSchema(slug);
6158
6124
  let validated;
6159
6125
  try {
6160
6126
  validated = schema.parse(cleaned);
6161
6127
  } catch (zodErr) {
6162
6128
  return c.json({ error: `Validation failed: ${formatZodErrors(zodErr.errors)}`, details: zodErr.errors }, 400);
6163
6129
  }
6164
- const SYSTEM_FIELDS = /* @__PURE__ */ new Set(["id", "createdAt", "updatedAt", "publishStatus", "hasDraft", "baseUpdatedAt", "_baseUpdatedAt"]);
6130
+ const SYSTEM_FIELDS = /* @__PURE__ */ new Set(["id", "createdAt", "updatedAt", "status", "baseUpdatedAt", "_baseUpdatedAt"]);
6165
6131
  const userData = Object.fromEntries(
6166
6132
  Object.entries(validated).filter(([k]) => !SYSTEM_FIELDS.has(k))
6167
6133
  );
@@ -6172,49 +6138,68 @@ function createHonoApp(options) {
6172
6138
  tenantID: ctxTenantID,
6173
6139
  draft: true
6174
6140
  });
6141
+ const isDraft = c.req.header("X-Draft") === "true";
6175
6142
  const isDraftEnabled = globalConfig.versions?.drafts === true;
6176
- const isAlreadyPublished = originalDoc?.publishStatus === "published";
6143
+ const isAutosave = c.req.query("autosave") === "true";
6177
6144
  let doc;
6178
- if (isDraftEnabled && isAlreadyPublished) {
6145
+ if (isDraftEnabled && isDraft) {
6179
6146
  await db.createVersion({
6180
6147
  collection: collectionSlug,
6181
6148
  documentId: slug,
6182
6149
  data: userData,
6183
6150
  status: "draft",
6151
+ autosave: isAutosave,
6184
6152
  createdBy: ctxUser?.id,
6185
- changeDescription: "Manual save (Draft)",
6153
+ changeDescription: isAutosave ? "Autosave" : "Manual save",
6186
6154
  tenantID: ctxTenantID
6187
6155
  });
6188
- doc = await db.update({
6189
- collection: collectionSlug,
6190
- id: slug,
6191
- data: { hasDraft: true },
6192
- tenantID: ctxTenantID
6193
- });
6194
- } else {
6195
- const saveData = isDraftEnabled ? { ...userData, publishStatus: "draft", hasDraft: false } : { ...userData, publishStatus: "published", hasDraft: false };
6156
+ if (!originalDoc) {
6157
+ doc = await db.create({
6158
+ collection: collectionSlug,
6159
+ data: { ...userData, id: slug, status: "draft" },
6160
+ tenantID: ctxTenantID
6161
+ });
6162
+ } else {
6163
+ doc = originalDoc;
6164
+ }
6165
+ } else if (isDraftEnabled && !isDraft) {
6166
+ const publishStatus = "published";
6196
6167
  if (originalDoc) {
6197
6168
  doc = await db.update({
6198
6169
  collection: collectionSlug,
6199
6170
  id: slug,
6200
- data: saveData,
6171
+ data: { ...userData, status: publishStatus },
6201
6172
  tenantID: ctxTenantID
6202
6173
  });
6203
6174
  } else {
6204
6175
  doc = await db.create({
6205
6176
  collection: collectionSlug,
6206
- data: { ...saveData, id: slug },
6177
+ data: { ...userData, id: slug, status: publishStatus },
6207
6178
  tenantID: ctxTenantID
6208
6179
  });
6209
6180
  }
6210
- if (isDraftEnabled) {
6211
- await db.createVersion({
6181
+ await db.createVersion({
6182
+ collection: collectionSlug,
6183
+ documentId: slug,
6184
+ data: userData,
6185
+ status: publishStatus,
6186
+ autosave: false,
6187
+ createdBy: ctxUser?.id,
6188
+ changeDescription: "Published",
6189
+ tenantID: ctxTenantID
6190
+ });
6191
+ } else {
6192
+ if (originalDoc) {
6193
+ doc = await db.update({
6212
6194
  collection: collectionSlug,
6213
- documentId: slug,
6195
+ id: slug,
6214
6196
  data: userData,
6215
- status: "draft",
6216
- createdBy: ctxUser?.id,
6217
- changeDescription: "Manual save",
6197
+ tenantID: ctxTenantID
6198
+ });
6199
+ } else {
6200
+ doc = await db.create({
6201
+ collection: collectionSlug,
6202
+ data: { ...userData, id: slug },
6218
6203
  tenantID: ctxTenantID
6219
6204
  });
6220
6205
  }
@@ -6223,6 +6208,13 @@ function createHonoApp(options) {
6223
6208
  mediaService = null;
6224
6209
  mediaServiceInitError = null;
6225
6210
  }
6211
+ if (slug === "email-settings") {
6212
+ const newEmailTransport = await EmailTransport.fromConfig(db);
6213
+ authRoutes.email = newEmailTransport || void 0;
6214
+ }
6215
+ if (slug === "system") {
6216
+ await loadSecrets();
6217
+ }
6226
6218
  if (ctxUser) {
6227
6219
  sessionAuthAdapter?.createAuditLog({
6228
6220
  action: "settings_change",
@@ -6256,9 +6248,9 @@ function createHonoApp(options) {
6256
6248
  draft: true
6257
6249
  });
6258
6250
  if (!originalDoc) return c.json({ error: "Global not found" }, 404);
6259
- let publishData = { publishStatus: "published", hasDraft: false };
6251
+ let publishData = { status: "published" };
6260
6252
  let finalContent = originalDoc;
6261
- if (originalDoc.hasDraft) {
6253
+ if (globalConfig.versions?.drafts) {
6262
6254
  const versions = await db.findVersions({
6263
6255
  collection: collectionSlug,
6264
6256
  documentId: slug,
@@ -6266,7 +6258,7 @@ function createHonoApp(options) {
6266
6258
  sort: "-createdAt",
6267
6259
  tenantID: ctxTenantID
6268
6260
  });
6269
- if (versions.docs.length > 0 && versions.docs[0].status === "draft") {
6261
+ if (versions.docs.length > 0) {
6270
6262
  finalContent = { ...originalDoc, ...versions.docs[0].data };
6271
6263
  publishData = { ...versions.docs[0].data, ...publishData };
6272
6264
  }
@@ -6281,7 +6273,7 @@ function createHonoApp(options) {
6281
6273
  await db.createVersion({
6282
6274
  collection: collectionSlug,
6283
6275
  documentId: slug,
6284
- data: { ...finalContent, publishStatus: "published" },
6276
+ data: { ...finalContent, status: "published" },
6285
6277
  status: "published",
6286
6278
  createdBy: ctxUser?.id,
6287
6279
  changeDescription: "Published",
@@ -6301,7 +6293,7 @@ function createHonoApp(options) {
6301
6293
  const doc = await db.update({
6302
6294
  collection: `_globals_${slug}`,
6303
6295
  id: slug,
6304
- data: { publishStatus: "draft", hasDraft: false },
6296
+ data: { status: "draft" },
6305
6297
  tenantID: ctxTenantID
6306
6298
  });
6307
6299
  return c.json({ data: doc, message: "Unpublished successfully" });
@@ -6361,9 +6353,13 @@ function createHonoApp(options) {
6361
6353
  const doc = await db.update({
6362
6354
  collection: collectionSlug,
6363
6355
  id: slug,
6364
- data: { ...version.data, publishStatus: "draft", hasDraft: false },
6356
+ data: { ...version.data, status: "draft" },
6365
6357
  tenantID: ctxTenantID
6366
6358
  });
6359
+ return c.json({
6360
+ data: doc,
6361
+ message: "Version restored successfully"
6362
+ });
6367
6363
  return c.json({ data: doc, message: "Restored successfully" });
6368
6364
  } catch (error) {
6369
6365
  return c.json({ error: error.message }, 500);
@@ -6466,5 +6462,5 @@ function createRESTAPI(registry, db, options) {
6466
6462
  }
6467
6463
 
6468
6464
  export { AuditLogger, AuthRoutes, InMemoryAuditLogger, InMemoryRateLimiter, MediaService, createAuditContext2 as createAuditContext, createCloudinaryStorage, createFtpStorage, createHonoApp, createLocalStorage, createRESTAPI, createS3Storage, getAppSecret, getDefaultRegistry, getEncryptionKey, getSessionConfig, init_secret, loadSecrets, resolveProvider, setDbAdapter };
6469
- //# sourceMappingURL=chunk-PU2Z5VWF.js.map
6470
- //# sourceMappingURL=chunk-PU2Z5VWF.js.map
6465
+ //# sourceMappingURL=chunk-IPTZM3VE.js.map
6466
+ //# sourceMappingURL=chunk-IPTZM3VE.js.map