@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,4 +1,4 @@
1
- import { AbstractBaseAdapter, applyRLS, DEFAULT_RLS_CONFIG, canAccessDocument } from './chunk-DYTZ6FQ7.js';
1
+ import { AbstractBaseAdapter, applyRLS, DEFAULT_RLS_CONFIG, canAccessDocument } from './chunk-WXVB364T.js';
2
2
  import { randomBytes } from 'crypto';
3
3
 
4
4
  var MongoDBAdapter = class extends AbstractBaseAdapter {
@@ -6,7 +6,7 @@ var MongoDBAdapter = class extends AbstractBaseAdapter {
6
6
  db;
7
7
  database;
8
8
  connectionString;
9
- draftsCollectionName = "kyro_drafts";
9
+ // NOTE: draftsCollectionName removed — autosave now uses versions table with autosave flag
10
10
  constructor(options) {
11
11
  super();
12
12
  if (options.connectionString) {
@@ -56,7 +56,7 @@ var MongoDBAdapter = class extends AbstractBaseAdapter {
56
56
  }
57
57
  const filter = this.buildFilter(effectiveWhere, tenantID);
58
58
  if (!draft) {
59
- filter.publishStatus = "published";
59
+ filter.status = "published";
60
60
  }
61
61
  const sortOption = this.parseSort(sort);
62
62
  const sortObj = {
@@ -73,16 +73,14 @@ var MongoDBAdapter = class extends AbstractBaseAdapter {
73
73
  }
74
74
  if (draft) {
75
75
  processedDocs = await Promise.all(processedDocs.map(async (doc) => {
76
- if (doc.hasDraft) {
77
- const versions = await this.findVersions({
78
- collection: slug,
79
- documentId: doc.id,
80
- limit: 1,
81
- sort: "-createdAt"
82
- });
83
- if (versions.docs.length > 0 && versions.docs[0].status === "draft") {
84
- return { ...doc, ...versions.docs[0].data, hasDraft: true, publishStatus: doc.publishStatus };
85
- }
76
+ const versionCollection = this.getMongoCollection(`${slug}_versions`);
77
+ const version = await versionCollection.findOne(
78
+ { document_id: doc.id },
79
+ { sort: { createdAt: -1 } }
80
+ );
81
+ if (version) {
82
+ const versionData = version.data || {};
83
+ return { ...doc, ...versionData, status: doc.status };
86
84
  }
87
85
  return doc;
88
86
  }));
@@ -107,20 +105,20 @@ var MongoDBAdapter = class extends AbstractBaseAdapter {
107
105
  filter.tenantId = tenantID;
108
106
  }
109
107
  if (!draft) {
110
- filter.publishStatus = "published";
108
+ filter.status = "published";
111
109
  }
112
110
  const doc = await col.findOne(filter);
113
111
  if (!doc) return null;
114
112
  let processedDoc = this.processResult(doc, config);
115
- if (draft && processedDoc.hasDraft) {
116
- const versions = await this.findVersions({
117
- collection: slug,
118
- documentId: processedDoc.id,
119
- limit: 1,
120
- sort: "-createdAt"
121
- });
122
- if (versions.docs.length > 0 && versions.docs[0].status === "draft") {
123
- processedDoc = { ...processedDoc, ...versions.docs[0].data, hasDraft: true, publishStatus: processedDoc.publishStatus };
113
+ if (draft) {
114
+ const versionCollection = this.getMongoCollection(`${slug}_versions`);
115
+ const version = await versionCollection.findOne(
116
+ { document_id: processedDoc.id },
117
+ { sort: { createdAt: -1 } }
118
+ );
119
+ if (version) {
120
+ const versionData = version.data || {};
121
+ processedDoc = { ...processedDoc, ...versionData, status: processedDoc.status };
124
122
  }
125
123
  }
126
124
  return processedDoc;
@@ -184,20 +182,20 @@ var MongoDBAdapter = class extends AbstractBaseAdapter {
184
182
  const col = this.getMongoCollection(slug);
185
183
  const filter = this.buildFilter(where, tenantID);
186
184
  if (!draft) {
187
- filter.publishStatus = "published";
185
+ filter.status = "published";
188
186
  }
189
187
  const doc = await col.findOne(filter);
190
188
  if (!doc) return null;
191
189
  let processedDoc = this.processResult(doc, config);
192
- if (draft && processedDoc.hasDraft) {
193
- const versions = await this.findVersions({
194
- collection: slug,
195
- documentId: processedDoc.id,
196
- limit: 1,
197
- sort: "-createdAt"
198
- });
199
- if (versions.docs.length > 0 && versions.docs[0].status === "draft") {
200
- processedDoc = { ...processedDoc, ...versions.docs[0].data, hasDraft: true, publishStatus: processedDoc.publishStatus };
190
+ if (draft) {
191
+ const versionCollection = this.getMongoCollection(`${slug}_versions`);
192
+ const version = await versionCollection.findOne(
193
+ { document_id: processedDoc.id },
194
+ { sort: { createdAt: -1 } }
195
+ );
196
+ if (version) {
197
+ const versionData = version.data || {};
198
+ processedDoc = { ...processedDoc, ...versionData, status: processedDoc.status };
201
199
  }
202
200
  }
203
201
  return processedDoc;
@@ -205,7 +203,7 @@ var MongoDBAdapter = class extends AbstractBaseAdapter {
205
203
  async findVersions(args) {
206
204
  const { collection: slug, documentId, sort, limit = 10, page = 1, tenantID } = args;
207
205
  const versionCollection = this.getMongoCollection(`${slug}_versions`);
208
- const filter = { document_id: documentId };
206
+ const filter = { document_id: documentId, autosave: { $ne: true } };
209
207
  if (tenantID) filter.tenant_id = tenantID;
210
208
  const skip = (page - 1) * limit;
211
209
  const sortOption = this.parseSort(sort);
@@ -230,8 +228,22 @@ var MongoDBAdapter = class extends AbstractBaseAdapter {
230
228
  return doc ? this.processResult(doc, {}) : null;
231
229
  }
232
230
  async createVersion(args) {
233
- const { collection: slug, documentId, data, status, createdBy, changeDescription, tenantID } = args;
231
+ const { collection: slug, documentId, data, status, createdBy, changeDescription, tenantID, autosave } = args;
234
232
  const versionCollection = this.getMongoCollection(`${slug}_versions`);
233
+ if (autosave) {
234
+ const filter = { document_id: documentId, collection_slug: slug, autosave: true };
235
+ if (tenantID) filter.tenant_id = tenantID;
236
+ const existing = await versionCollection.findOne(filter);
237
+ if (existing) {
238
+ const now2 = (/* @__PURE__ */ new Date()).toISOString();
239
+ await versionCollection.updateOne(
240
+ { _id: existing._id },
241
+ { $set: { data, status, updatedAt: now2 } }
242
+ );
243
+ return this.processResult({ ...existing, data, status, updatedAt: now2 }, {});
244
+ }
245
+ }
246
+ const now = (/* @__PURE__ */ new Date()).toISOString();
235
247
  const versionDoc = {
236
248
  _id: this.generateId(),
237
249
  document_id: documentId,
@@ -239,34 +251,41 @@ var MongoDBAdapter = class extends AbstractBaseAdapter {
239
251
  tenant_id: tenantID,
240
252
  data,
241
253
  status,
254
+ autosave: autosave === true,
242
255
  created_by: createdBy,
243
256
  change_description: changeDescription,
244
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
245
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
257
+ createdAt: now,
258
+ updatedAt: now
246
259
  };
247
260
  await versionCollection.insertOne(versionDoc);
248
- const config = this.getCollectionConfig(slug);
249
- if (config.versions?.maxPerDoc) {
250
- await this.deleteVersions({
251
- collection: slug,
252
- documentId,
253
- keepLatest: config.versions.maxPerDoc,
254
- tenantID
255
- });
261
+ if (!autosave) {
262
+ const config = this.getCollectionConfig(slug);
263
+ if (config.versions?.maxPerDoc) {
264
+ await this.deleteVersions({
265
+ collection: slug,
266
+ documentId,
267
+ keepLatest: config.versions.maxPerDoc,
268
+ tenantID
269
+ });
270
+ }
256
271
  }
257
272
  return this.processResult(versionDoc, {});
258
273
  }
274
+ async updateLatestVersion(args) {
275
+ return this.createVersion({ ...args, autosave: true });
276
+ }
259
277
  async deleteVersions(args) {
260
278
  const { collection: slug, documentId, keepLatest, tenantID } = args;
261
279
  const versionCollection = this.getMongoCollection(`${slug}_versions`);
262
280
  if (keepLatest) {
263
- const filter = { document_id: documentId };
281
+ const filter = { document_id: documentId, autosave: { $ne: true } };
264
282
  if (tenantID) filter.tenant_id = tenantID;
265
283
  const toKeep = await versionCollection.find(filter).sort({ createdAt: -1 }).limit(keepLatest).project({ _id: 1 }).toArray();
266
284
  const keepIds = toKeep.map((doc) => doc._id);
267
285
  if (keepIds.length > 0) {
268
286
  await versionCollection.deleteMany({
269
287
  document_id: documentId,
288
+ autosave: { $ne: true },
270
289
  _id: { $nin: keepIds },
271
290
  ...tenantID ? { tenant_id: tenantID } : {}
272
291
  });
@@ -277,46 +296,6 @@ var MongoDBAdapter = class extends AbstractBaseAdapter {
277
296
  await versionCollection.deleteMany(filter);
278
297
  }
279
298
  }
280
- async findDraft(args) {
281
- const draft = await this.getMongoCollection(this.draftsCollectionName).findOne({
282
- _id: this.getDraftId(args.collection, args.documentId, args.tenantID)
283
- });
284
- return draft ? this.docToDraft(draft) : null;
285
- }
286
- async upsertDraft(args) {
287
- const now = (/* @__PURE__ */ new Date()).toISOString();
288
- const draftUpdatedAt = args.draftUpdatedAt || now;
289
- const _id = this.getDraftId(args.collection, args.documentId, args.tenantID);
290
- const existing = await this.getMongoCollection(this.draftsCollectionName).findOne({ _id });
291
- await this.getMongoCollection(this.draftsCollectionName).updateOne(
292
- { _id },
293
- {
294
- $set: {
295
- collectionSlug: args.collection,
296
- documentId: args.documentId,
297
- tenantId: args.tenantID,
298
- data: args.data,
299
- baseUpdatedAt: args.baseUpdatedAt ?? null,
300
- draftUpdatedAt,
301
- updatedAt: now
302
- },
303
- $setOnInsert: {
304
- createdAt: existing?.createdAt || now
305
- }
306
- },
307
- { upsert: true }
308
- );
309
- const saved = await this.getMongoCollection(this.draftsCollectionName).findOne({ _id });
310
- if (!saved) {
311
- throw new Error("Failed to persist draft snapshot");
312
- }
313
- return this.docToDraft(saved);
314
- }
315
- async deleteDraft(args) {
316
- await this.getMongoCollection(this.draftsCollectionName).deleteOne({
317
- _id: this.getDraftId(args.collection, args.documentId, args.tenantID)
318
- });
319
- }
320
299
  async migrate() {
321
300
  for (const config of this.collections.values()) {
322
301
  const col = this.getMongoCollection(config.slug);
@@ -336,7 +315,6 @@ var MongoDBAdapter = class extends AbstractBaseAdapter {
336
315
  }
337
316
  }
338
317
  }
339
- await this.getMongoCollection(this.draftsCollectionName).createIndex({ updatedAt: -1 });
340
318
  console.log(`[MongoDBAdapter] Migration completed`);
341
319
  }
342
320
  // ========================================================================
@@ -408,22 +386,6 @@ var MongoDBAdapter = class extends AbstractBaseAdapter {
408
386
  }
409
387
  return filter;
410
388
  }
411
- getDraftId(collection, documentId, tenantID) {
412
- return `${collection}::${documentId}::${tenantID || "global"}`;
413
- }
414
- docToDraft(doc) {
415
- return {
416
- id: String(doc._id),
417
- collection: doc.collectionSlug,
418
- documentId: doc.documentId,
419
- tenantID: doc.tenantId ?? void 0,
420
- data: doc.data || {},
421
- baseUpdatedAt: doc.baseUpdatedAt ?? null,
422
- draftUpdatedAt: doc.draftUpdatedAt,
423
- createdAt: doc.createdAt,
424
- updatedAt: doc.updatedAt
425
- };
426
- }
427
389
  buildProjection(select) {
428
390
  if (!select || select.length === 0) return void 0;
429
391
  const projection = { _id: 1 };
@@ -459,5 +421,5 @@ function createMongoDBAdapter(options) {
459
421
  }
460
422
 
461
423
  export { MongoDBAdapter, createMongoDBAdapter };
462
- //# sourceMappingURL=chunk-VO35MNPH.js.map
463
- //# sourceMappingURL=chunk-VO35MNPH.js.map
424
+ //# sourceMappingURL=chunk-PQ72Z6WC.js.map
425
+ //# sourceMappingURL=chunk-PQ72Z6WC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/database/mongodb/adapter.ts"],"names":["now"],"mappings":"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","file":"chunk-PQ72Z6WC.js","sourcesContent":["import { randomBytes } from 'crypto';\nimport { AbstractBaseAdapter } from '../base.js';\nimport type {\n CollectionConfig,\n GlobalConfig,\n FindArgs,\n FindByIDArgs,\n CreateArgs,\n UpdateArgs,\n DeleteArgs,\n FindResult,\n VersionRecord,\n CreateVersionArgs,\n FindVersionsArgs,\n} from '../../registry/types.js';\nimport type { TenantContext } from '../../auth/rls/tenant.js';\nimport { applyRLS, DEFAULT_RLS_CONFIG, canAccessDocument } from '../../auth/rls/tenant.js';\n\nexport class MongoDBAdapter extends AbstractBaseAdapter {\n public client: any;\n public db: any;\n private database: string;\n private connectionString?: string;\n // NOTE: draftsCollectionName removed — autosave now uses versions table with autosave flag\n \n constructor(options: {\n client?: any;\n database?: string;\n connectionString?: string;\n }) {\n super();\n if (options.connectionString) {\n this.connectionString = options.connectionString;\n try {\n const url = new URL(options.connectionString);\n this.database = url.pathname.replace(/^\\//, '') || 'kyro_cms';\n } catch {\n this.database = 'kyro_cms';\n }\n } else {\n this.client = options.client;\n this.database = options.database!;\n }\n }\n\n async connect(): Promise<void> {\n if (this.connectionString && !this.client) {\n const { MongoClient } = await import('mongodb');\n this.client = new MongoClient(this.connectionString);\n await this.client.connect();\n }\n this.db = this.client.db(this.database);\n this.connected = true;\n console.log(`[MongoDBAdapter] Connected to database: ${this.database}`);\n }\n\n async disconnect(): Promise<void> {\n if (this.client) {\n await this.client.close();\n this.connected = false;\n console.log(`[MongoDBAdapter] Disconnected`);\n }\n }\n\n private getMongoCollection(slug: string): any {\n if (!this.db) {\n throw new Error('MongoDB not connected');\n }\n return this.db.collection(slug);\n }\n\n async find<T>(args: FindArgs): Promise<FindResult<T>> {\n const { collection: slug, where = {}, sort, limit = 10, page = 1, tenantID, select, draft } = args;\n const config = this.getCollectionConfig(slug);\n const col = this.getMongoCollection(slug);\n\n let effectiveWhere = { ...where };\n if (this.tenantContext && config.tenantScoped) {\n const rlsQuery = applyRLS({ where: effectiveWhere }, slug, this.tenantContext, DEFAULT_RLS_CONFIG);\n effectiveWhere = rlsQuery.where || {};\n }\n\n // Build filter\n const filter = this.buildFilter(effectiveWhere, tenantID);\n \n // Default filter for non-draft requests: only show published\n if (!draft) {\n filter.status = 'published';\n }\n\n // Build sort\n const sortOption = this.parseSort(sort);\n const sortObj: Record<string, 1 | -1> = {\n [sortOption.field]: sortOption.direction === 'asc' ? 1 : -1,\n };\n\n // Execute query\n const skip = (page - 1) * limit;\n \n const [docs, totalDocs] = await Promise.all([\n col\n .find(filter)\n .sort(sortObj)\n .skip(skip)\n .limit(limit)\n .project(this.buildProjection(select))\n .toArray(),\n col.countDocuments(filter),\n ]);\n\n // Process results\n let processedDocs = docs.map((doc: any) => this.processResult(doc, config));\n\n if (this.tenantContext && !this.tenantContext.isSuperAdmin) {\n processedDocs = processedDocs.filter((doc: any) => canAccessDocument(doc, slug, this.tenantContext!, DEFAULT_RLS_CONFIG));\n }\n\n // If draft: true, merge the latest version (autosave or manual) into the response\n if (draft) {\n processedDocs = await Promise.all(processedDocs.map(async (doc: any) => {\n const versionCollection = this.getMongoCollection(`${slug}_versions`);\n const version = await versionCollection.findOne(\n { document_id: doc.id },\n { sort: { createdAt: -1 } },\n );\n if (version) {\n const versionData = version.data || {};\n return { ...doc, ...versionData, status: doc.status };\n }\n return doc;\n }));\n }\n\n return {\n docs: processedDocs as T[],\n ...this.calculatePagination(page, limit, totalDocs),\n };\n }\n\n async findByID<T>(args: FindByIDArgs): Promise<T | null> {\n const { collection: slug, id, tenantID, draft } = args;\n const config = this.getCollectionConfig(slug);\n const col = this.getMongoCollection(slug);\n\n if (this.tenantContext && config.tenantScoped) {\n const tempDoc = { _id: id, tenantId: this.tenantContext.tenantId };\n if (!canAccessDocument(tempDoc, slug, this.tenantContext, DEFAULT_RLS_CONFIG)) {\n return null;\n }\n }\n\n const filter: any = { _id: id };\n if (tenantID) {\n filter.tenantId = tenantID;\n }\n \n if (!draft) {\n filter.status = 'published';\n }\n\n const doc = await col.findOne(filter);\n if (!doc) return null;\n\n let processedDoc = this.processResult(doc, config);\n\n // If draft: true, merge the latest version (autosave or manual) into the response\n if (draft) {\n const versionCollection = this.getMongoCollection(`${slug}_versions`);\n const version = await versionCollection.findOne(\n { document_id: processedDoc.id },\n { sort: { createdAt: -1 } },\n );\n if (version) {\n const versionData = version.data || {};\n processedDoc = { ...processedDoc, ...versionData, status: processedDoc.status };\n }\n }\n\n return processedDoc as T;\n }\n\n async create<T>(args: CreateArgs): Promise<T> {\n const { collection: slug, data, tenantID } = args;\n const config = this.getCollectionConfig(slug);\n const col = this.getMongoCollection(slug);\n\n const doc: any = {\n ...this.prepareData(data, config),\n _id: this.generateId(),\n };\n\n if (tenantID) {\n doc.tenantId = tenantID;\n }\n\n await col.insertOne(doc);\n\n return this.processResult(doc, config) as T;\n }\n\n async update<T>(args: UpdateArgs): Promise<T> {\n const { collection: slug, id, data, tenantID } = args;\n const config = this.getCollectionConfig(slug);\n const col = this.getMongoCollection(slug);\n\n const filter: any = { _id: id };\n if (tenantID) {\n filter.tenantId = tenantID;\n }\n\n const updateData = this.prepareData(data, config);\n\n const result = await col.findOneAndUpdate(\n filter,\n { $set: updateData },\n { returnDocument: 'after' }\n );\n\n if (!result) {\n throw new Error(`Document not found: ${slug}/${id}`);\n }\n\n return this.processResult(result, config) as T;\n }\n\n async delete<T>(args: DeleteArgs): Promise<T> {\n const { collection: slug, id, tenantID } = args;\n const config = this.getCollectionConfig(slug);\n const col = this.getMongoCollection(slug);\n\n const filter: any = { _id: id };\n if (tenantID) {\n filter.tenantId = tenantID;\n }\n\n const doc = await col.findOneAndDelete(filter);\n if (!doc) {\n throw new Error(`Document not found: ${slug}/${id}`);\n }\n\n return this.processResult(doc, config) as T;\n }\n\n async count(args: { collection: string; where?: Record<string, any>; tenantID?: string }): Promise<number> {\n const { collection: slug, where = {}, tenantID } = args;\n const col = this.getMongoCollection(slug);\n const filter = this.buildFilter(where, tenantID);\n return col.countDocuments(filter);\n }\n\n async findOne(args: { collection: string; where: Record<string, any>; tenantID?: string; draft?: boolean }): Promise<any> {\n const { collection: slug, where = {}, tenantID, draft } = args;\n const config = this.getCollectionConfig(slug);\n const col = this.getMongoCollection(slug);\n const filter = this.buildFilter(where, tenantID);\n\n if (!draft) {\n filter.status = 'published';\n }\n\n const doc = await col.findOne(filter);\n if (!doc) return null;\n\n let processedDoc = this.processResult(doc, config);\n\n // If draft: true, merge the latest version (autosave or manual) into the response\n if (draft) {\n const versionCollection = this.getMongoCollection(`${slug}_versions`);\n const version = await versionCollection.findOne(\n { document_id: processedDoc.id },\n { sort: { createdAt: -1 } },\n );\n if (version) {\n const versionData = version.data || {};\n processedDoc = { ...processedDoc, ...versionData, status: processedDoc.status };\n }\n }\n\n return processedDoc;\n }\n\n async findVersions(args: FindVersionsArgs): Promise<FindResult<VersionRecord>> {\n const { collection: slug, documentId, sort, limit = 10, page = 1, tenantID } = args;\n \n // Versions stored in a separate collection; exclude ephemeral autosave versions\n const versionCollection = this.getMongoCollection(`${slug}_versions`);\n const filter: any = { document_id: documentId, autosave: { $ne: true } };\n if (tenantID) filter.tenant_id = tenantID;\n\n const skip = (page - 1) * limit;\n const sortOption = this.parseSort(sort);\n const sortObj: Record<string, 1 | -1> = {\n [sortOption.field]: sortOption.direction === 'asc' ? 1 : -1,\n };\n\n const [docs, totalDocs] = await Promise.all([\n versionCollection.find(filter).sort(sortObj).skip(skip).limit(limit).toArray(),\n versionCollection.countDocuments(filter),\n ]);\n\n return {\n docs: docs.map((doc: any) => this.processResult(doc, {} as CollectionConfig) as VersionRecord),\n ...this.calculatePagination(page, limit, totalDocs),\n };\n }\n\n async findVersionByID(args: { collection: string; versionId: string; tenantID?: string }): Promise<VersionRecord | null> {\n const { collection: slug, versionId, tenantID } = args;\n const versionCollection = this.getMongoCollection(`${slug}_versions`);\n const filter: any = { _id: versionId };\n if (tenantID) filter.tenant_id = tenantID;\n \n const doc = await versionCollection.findOne(filter);\n return doc ? this.processResult(doc, {} as CollectionConfig) as VersionRecord : null;\n }\n\n async createVersion<T = Record<string, any>>(args: CreateVersionArgs<T>): Promise<VersionRecord<T>> {\n const { collection: slug, documentId, data, status, createdBy, changeDescription, tenantID, autosave } = args;\n const versionCollection = this.getMongoCollection(`${slug}_versions`);\n\n // Autosave: reuse existing autosave slot instead of creating a new row\n if (autosave) {\n const filter: any = { document_id: documentId, collection_slug: slug, autosave: true };\n if (tenantID) filter.tenant_id = tenantID;\n const existing = await versionCollection.findOne(filter);\n if (existing) {\n const now = new Date().toISOString();\n await versionCollection.updateOne(\n { _id: existing._id },\n { $set: { data, status, updatedAt: now } },\n );\n return this.processResult({ ...existing, data, status, updatedAt: now }, {} as CollectionConfig) as VersionRecord<T>;\n }\n }\n\n const now = new Date().toISOString();\n const versionDoc: any = {\n _id: this.generateId(),\n document_id: documentId,\n collection_slug: slug,\n tenant_id: tenantID,\n data,\n status,\n autosave: autosave === true,\n created_by: createdBy,\n change_description: changeDescription,\n createdAt: now,\n updatedAt: now,\n };\n\n await versionCollection.insertOne(versionDoc);\n \n // Pruning logic — skip for autosave versions\n if (!autosave) {\n const config = this.getCollectionConfig(slug);\n if (config.versions?.maxPerDoc) {\n await this.deleteVersions({\n collection: slug,\n documentId: documentId,\n keepLatest: config.versions.maxPerDoc,\n tenantID: tenantID,\n });\n }\n }\n\n return this.processResult(versionDoc, {} as CollectionConfig) as VersionRecord<T>;\n }\n\n async updateLatestVersion<T = Record<string, any>>(args: CreateVersionArgs<T>): Promise<VersionRecord<T>> {\n return this.createVersion({ ...args, autosave: true });\n }\n\n async deleteVersions(args: { collection: string; documentId: string; keepLatest?: number; tenantID?: string }): Promise<void> {\n const { collection: slug, documentId, keepLatest, tenantID } = args;\n const versionCollection = this.getMongoCollection(`${slug}_versions`);\n \n if (keepLatest) {\n const filter: any = { document_id: documentId, autosave: { $ne: true } };\n if (tenantID) filter.tenant_id = tenantID;\n\n const toKeep = await versionCollection\n .find(filter)\n .sort({ createdAt: -1 })\n .limit(keepLatest)\n .project({ _id: 1 })\n .toArray();\n\n const keepIds = toKeep.map((doc: any) => doc._id);\n if (keepIds.length > 0) {\n await versionCollection.deleteMany({\n document_id: documentId,\n autosave: { $ne: true },\n _id: { $nin: keepIds },\n ...(tenantID ? { tenant_id: tenantID } : {}),\n });\n }\n } else {\n const filter: any = { document_id: documentId };\n if (tenantID) filter.tenant_id = tenantID;\n await versionCollection.deleteMany(filter);\n }\n }\n\n\n\n async migrate?(): Promise<void> {\n // Create indexes for all collections\n for (const config of this.collections.values()) {\n const col = this.getMongoCollection(config.slug);\n\n // Create default indexes\n await col.createIndex({ _id: 1 });\n \n if (config.tenantScoped) {\n await col.createIndex({ tenantId: 1 });\n }\n\n if (config.timestamps) {\n await col.createIndex({ createdAt: -1 });\n }\n\n // Create unique indexes\n for (const field of config.fields) {\n if (field.unique && field.name) {\n await col.createIndex({ [field.name]: 1 }, { unique: true });\n }\n if (field.indexed && field.name) {\n await col.createIndex({ [field.name]: 1 });\n }\n }\n }\n\n console.log(`[MongoDBAdapter] Migration completed`);\n }\n\n // ========================================================================\n // Helper Methods\n // ========================================================================\n\n private getCollectionConfig(slug: string): CollectionConfig {\n const config = this.collections.get(slug);\n if (!config) {\n throw new Error(`Collection \"${slug}\" not found`);\n }\n return config;\n }\n\n private buildFilter(where: Record<string, any> = {}, tenantID?: string): Record<string, any> {\n const filter: Record<string, any> = {};\n\n // Apply tenant filter\n if (tenantID) {\n filter.tenantId = tenantID;\n }\n\n // Convert operators to MongoDB format\n for (const [key, value] of Object.entries(where)) {\n if (key === 'AND' && Array.isArray(value)) {\n const andConditions = value.map((v: any) => this.buildFilter(v));\n Object.assign(filter, ...andConditions);\n } else if (key === 'OR' && Array.isArray(value)) {\n filter.$or = value.map((v: any) => this.buildFilter(v));\n } else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n // Operator-based conditions\n const mongoOperators: Record<string, any> = {};\n \n if (value.equals !== undefined) {\n filter[key === 'id' ? '_id' : key] = value.equals;\n continue;\n }\n if (value.not_equals !== undefined) {\n mongoOperators.$ne = value.not_equals;\n }\n if (value.in !== undefined) {\n mongoOperators.$in = value.in;\n }\n if (value.not_in !== undefined) {\n mongoOperators.$nin = value.not_in;\n }\n if (value.greater_than !== undefined) {\n mongoOperators.$gt = value.greater_than;\n }\n if (value.greater_than_equal !== undefined) {\n mongoOperators.$gte = value.greater_than_equal;\n }\n if (value.less_than !== undefined) {\n mongoOperators.$lt = value.less_than;\n }\n if (value.less_than_equal !== undefined) {\n mongoOperators.$lte = value.less_than_equal;\n }\n if (value.like !== undefined) {\n mongoOperators.$regex = new RegExp(value.like.replace(/%/g, '.*'), 'i');\n }\n if (value.not_like !== undefined) {\n mongoOperators.$not = new RegExp(value.not_like.replace(/%/g, '.*'), 'i');\n }\n if (value.contains !== undefined) {\n mongoOperators.$regex = new RegExp(`.*${value.contains}.*`, 'i');\n }\n if (value.exists !== undefined) {\n mongoOperators.$exists = value.exists;\n }\n\n if (Object.keys(mongoOperators).length > 0) {\n filter[key === 'id' ? '_id' : key] = mongoOperators;\n }\n } else {\n // Direct equality\n filter[key === 'id' ? '_id' : key] = value;\n }\n }\n\n return filter;\n } private buildProjection(select?: string[]): Record<string, 1> | undefined {\n if (!select || select.length === 0) return undefined;\n \n const projection: Record<string, 1> = { _id: 1 };\n for (const field of select) {\n projection[field] = 1;\n }\n return projection;\n }\n\n private processResult(data: any, config: CollectionConfig): any {\n if (!data) return null;\n\n const result = { ...data };\n\n // Convert _id to id\n if (data._id) {\n result.id = data._id;\n delete result._id;\n }\n\n // Remove MongoDB internals\n delete result.__v;\n\n // Convert dates to ISO strings\n if (result.createdAt) {\n result.createdAt = new Date(result.createdAt).toISOString();\n }\n if (result.updatedAt) {\n result.updatedAt = new Date(result.updatedAt).toISOString();\n }\n\n return result;\n }\n\n private generateId(): string {\n const timestamp = Date.now().toString(16).padStart(12, '0');\n const random = randomBytes(6).toString('hex');\n return timestamp + random;\n }\n}\n\n// ============================================================================\n// Factory Function\n// ============================================================================\n\nexport function createMongoDBAdapter(options: {\n client?: any;\n database?: string;\n connectionString?: string;\n}): MongoDBAdapter {\n return new MongoDBAdapter(options);\n}\n"]}
@@ -18,7 +18,14 @@ async function createContext(options) {
18
18
  };
19
19
  const apiKeyRaw = chunk4M7X5HAB_cjs.extractApiKeyFromRequest(options.req);
20
20
  if (apiKeyRaw) {
21
- const result = await chunk4M7X5HAB_cjs.validateApiKey(apiKeyRaw, options.db);
21
+ const result = await chunk4M7X5HAB_cjs.validateApiKey(apiKeyRaw, options.db, async (userId) => {
22
+ try {
23
+ const user = await options.db.findByID({ collection: "users", id: userId });
24
+ return user || null;
25
+ } catch {
26
+ return null;
27
+ }
28
+ });
22
29
  if (result.valid) {
23
30
  baseContext.user = result.user || options.user;
24
31
  baseContext.tenantID = result.tenantId || options.tenantID;
@@ -56,6 +63,38 @@ async function triggerWebhook(ctx, event, payload) {
56
63
  console.error(`[Webhook] Failed to trigger ${event}:`, err);
57
64
  }
58
65
  }
66
+ function normalizeEmptyStrings(data, fields) {
67
+ if (!data || typeof data !== "object") return;
68
+ for (const field of fields) {
69
+ if (!field.name || !(field.name in data)) continue;
70
+ const val = data[field.name];
71
+ if (val === "") {
72
+ const isTextual = field.type === "text" || field.type === "textarea" || field.type === "code" || field.type === "markdown" || field.type === "email" || field.type === "password" || field.type === "color";
73
+ if (!isTextual) data[field.name] = null;
74
+ }
75
+ if (field.type === "tabs" && field.name && Array.isArray(field.tabs) && data[field.name] && typeof data[field.name] === "object") {
76
+ for (const tab of field.tabs) {
77
+ if (Array.isArray(tab.fields)) normalizeEmptyStrings(data[field.name], tab.fields);
78
+ }
79
+ } else if ((field.type === "group" || field.type === "collapsible") && field.name && Array.isArray(field.fields) && data[field.name] && typeof data[field.name] === "object") {
80
+ normalizeEmptyStrings(data[field.name], field.fields);
81
+ } else if (field.type === "array" && field.name && Array.isArray(field.fields) && Array.isArray(data[field.name])) {
82
+ for (const item of data[field.name]) {
83
+ if (item && typeof item === "object") normalizeEmptyStrings(item, field.fields);
84
+ }
85
+ } else if (field.type === "blocks" && field.name && Array.isArray(field.blocks) && Array.isArray(data[field.name])) {
86
+ for (const item of data[field.name]) {
87
+ if (!item || typeof item !== "object") continue;
88
+ const blockTypeStr = item.type || item.blockType;
89
+ if (!blockTypeStr) continue;
90
+ const blockDef = field.blocks.find((b) => b.slug === blockTypeStr);
91
+ if (!blockDef || !Array.isArray(blockDef.fields)) continue;
92
+ const target = item.data && typeof item.data === "object" ? item.data : item;
93
+ normalizeEmptyStrings(target, blockDef.fields);
94
+ }
95
+ }
96
+ }
97
+ }
59
98
  async function checkTRPCAccess(config, operation, ctx) {
60
99
  const accessRule = config.access?.[operation];
61
100
  const apiKey = ctx.apiKey;
@@ -67,7 +106,7 @@ async function checkTRPCAccess(config, operation, ctx) {
67
106
  throw new Error(`Access denied: missing API key permission ${permission}`);
68
107
  }
69
108
  }
70
- if (ctx.user) {
109
+ if (ctx.user && !(apiKey && apiKey.permissions && apiKey.permissions.length > 0)) {
71
110
  const resource = config.slug;
72
111
  const action = operation === "read" ? "read" : operation === "create" ? "create" : operation === "update" ? "update" : "delete";
73
112
  const permission = `${resource}:${action}`;
@@ -255,6 +294,7 @@ function createUpdateProcedure(ctx) {
255
294
  if (baseUpdatedAt && originalDoc.updatedAt && baseUpdatedAt !== originalDoc.updatedAt) {
256
295
  throw new Error(`Revision conflict: document has changed since ${baseUpdatedAt}. Current updatedAt: ${originalDoc.updatedAt}`);
257
296
  }
297
+ normalizeEmptyStrings(data, config.fields);
258
298
  const schema = ctx.registry.getUpdateZodSchema(collection);
259
299
  const validated = schema.parse(data);
260
300
  if (config.tenantScoped && ctx.tenantID) {
@@ -290,14 +330,48 @@ function createUpdateProcedure(ctx) {
290
330
  if (hookResult) Object.assign(validated, hookResult);
291
331
  }
292
332
  }
293
- const doc = await ctx.db.update({
294
- collection,
295
- id,
296
- data: validated,
297
- depth: depth || 0,
298
- tenantID: ctx.tenantID,
299
- select
300
- });
333
+ const isDraft = ctx.req && typeof ctx.req.headers?.get === "function" && ctx.req.headers.get("x-draft") === "true" || input.draft === true;
334
+ const isDraftEnabled = config.versions?.drafts === true;
335
+ const isAutosave = ctx.req?.query?.autosave === "true" || ctx.req?.url?.includes("autosave=true") || input.autosave === true;
336
+ let doc;
337
+ if (isDraftEnabled && isDraft) {
338
+ await ctx.db.createVersion({
339
+ collection,
340
+ documentId: id,
341
+ data: validated,
342
+ status: "draft",
343
+ autosave: isAutosave,
344
+ createdBy: ctx.user?.id,
345
+ tenantID: ctx.tenantID
346
+ });
347
+ doc = await ctx.db.findByID({ collection, id, tenantID: ctx.tenantID, draft: true });
348
+ } else if (isDraftEnabled) {
349
+ doc = await ctx.db.update({
350
+ collection,
351
+ id,
352
+ data: { ...validated, status: "published" },
353
+ depth: depth || 0,
354
+ tenantID: ctx.tenantID,
355
+ select
356
+ });
357
+ await ctx.db.createVersion({
358
+ collection,
359
+ documentId: id,
360
+ data: validated,
361
+ status: "published",
362
+ createdBy: ctx.user?.id,
363
+ tenantID: ctx.tenantID
364
+ });
365
+ } else {
366
+ doc = await ctx.db.update({
367
+ collection,
368
+ id,
369
+ data: validated,
370
+ depth: depth || 0,
371
+ tenantID: ctx.tenantID,
372
+ select
373
+ });
374
+ }
301
375
  if (config.hooks?.afterChange) {
302
376
  for (const hook of config.hooks.afterChange) {
303
377
  await hook({
@@ -502,5 +576,5 @@ exports.createFindByIDProcedure = createFindByIDProcedure;
502
576
  exports.createFindProcedure = createFindProcedure;
503
577
  exports.createKyroServer = createKyroServer;
504
578
  exports.createUpdateProcedure = createUpdateProcedure;
505
- //# sourceMappingURL=chunk-KNRSROWB.cjs.map
506
- //# sourceMappingURL=chunk-KNRSROWB.cjs.map
579
+ //# sourceMappingURL=chunk-PV2I2KMI.cjs.map
580
+ //# sourceMappingURL=chunk-PV2I2KMI.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/api/trpc/context.ts","../src/api/trpc/procedures.ts","../src/api/trpc/router.ts"],"names":["createWebhookService","extractApiKeyFromRequest","validateApiKey","createApiKeyContext","WEBHOOK_EVENTS","hasApiKeyPermission","hasPermission","evaluateAccess"],"mappings":"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","file":"chunk-PV2I2KMI.cjs","sourcesContent":["import type { BaseAdapter } from \"../../registry/types.js\";\nimport type { User, Request } from \"../../hooks/types.js\";\nimport {\n validateApiKey,\n extractApiKeyFromRequest,\n createApiKeyContext,\n} from \"../../auth/api-key.js\";\nimport { createWebhookService } from \"../../webhooks/index.js\";\n\n// ============================================================================\n// Context Types\n// ============================================================================\n\nexport interface ApiKeyContext {\n userId: string;\n user: Partial<User>;\n permissions: string[];\n apiKeyId: string;\n tenantId?: string;\n role?: string;\n}\n\nexport interface KyroContext {\n db: BaseAdapter;\n registry: any;\n user?: User;\n tenantID?: string;\n req: Request;\n apiKey?: ApiKeyContext;\n webhookService?: ReturnType<typeof createWebhookService>;\n settings?: Record<string, any>;\n [key: string]: any;\n}\n\n// ============================================================================\n// Context Factory\n// ============================================================================\n\nexport async function createContext(options: {\n db: BaseAdapter;\n registry: any;\n req: Request;\n user?: User;\n tenantID?: string;\n settings?: Record<string, any>;\n}): Promise<KyroContext> {\n const webhookService = createWebhookService(options.db);\n\n const baseContext: KyroContext = {\n db: options.db,\n registry: options.registry,\n req: options.req,\n user: options.user,\n tenantID: options.tenantID,\n webhookService,\n settings: options.settings,\n };\n\n const apiKeyRaw = extractApiKeyFromRequest(options.req as any);\n if (apiKeyRaw) {\n const result = await validateApiKey(apiKeyRaw, options.db, async (userId) => {\n try {\n const user = await options.db.findByID({ collection: 'users', id: userId });\n return user || null;\n } catch {\n return null;\n }\n });\n if (result.valid) {\n baseContext.user = (result.user as User) || options.user;\n baseContext.tenantID = result.tenantId || options.tenantID;\n baseContext.apiKey = createApiKeyContext(result) as ApiKeyContext;\n }\n }\n\n return baseContext;\n}\n","import type {\n FindArgs,\n CreateArgs,\n UpdateArgs,\n DeleteArgs,\n} from \"../../registry/types.js\";\nimport { runHooks } from \"../../hooks/types.js\";\nimport { evaluateAccess } from \"../../access/types.js\";\nexport type { KyroContext, ApiKeyContext } from \"./context.js\";\nexport { createContext } from \"./context.js\";\nimport type { KyroContext, ApiKeyContext } from \"./context.js\";\nimport type { Field } from \"../../fields/types.js\";\nimport { WEBHOOK_EVENTS, type WebhookEvent } from \"../../webhooks/types.js\";\nimport { hasApiKeyPermission } from \"../../auth/api-key.js\";\nimport { hasPermission } from \"../../auth/rbac/checker.js\";\n\nconst COLLECTION_EVENT_MAP: Record<\n string,\n { create: WebhookEvent; update: WebhookEvent; delete: WebhookEvent }\n> = {\n _media: {\n create: WEBHOOK_EVENTS.MEDIA_UPLOAD,\n update: WEBHOOK_EVENTS.MEDIA_UPLOAD,\n delete: WEBHOOK_EVENTS.MEDIA_DELETE,\n },\n};\n\nfunction getWebhookEvent(\n collection: string,\n operation: \"create\" | \"update\" | \"delete\",\n): WebhookEvent {\n const mapped = COLLECTION_EVENT_MAP[collection];\n if (mapped) return mapped[operation];\n return `collection.${operation}` as WebhookEvent;\n}\n\nasync function triggerWebhook(\n ctx: KyroContext,\n event: WebhookEvent,\n payload: {\n collection: string;\n data: unknown;\n previousData?: unknown;\n operation: \"create\" | \"update\" | \"delete\";\n },\n) {\n if (!ctx.webhookService) return;\n try {\n await ctx.webhookService.trigger(event, {\n collection: payload.collection,\n operation: payload.operation,\n data: payload.data,\n previousData: payload.previousData,\n user: ctx.user\n ? { id: ctx.user.id, email: ctx.user.email, role: ctx.user.role }\n : undefined,\n tenantId: ctx.tenantID,\n });\n } catch (err) {\n console.error(`[Webhook] Failed to trigger ${event}:`, err);\n }\n}\n\n// ============================================================================\n// Data normalization helpers\n// ============================================================================\n\nfunction normalizeEmptyStrings(data: any, fields: Field[]): void {\n if (!data || typeof data !== 'object') return;\n for (const field of fields) {\n if (!field.name || !(field.name in data)) continue;\n const val = data[field.name];\n if (val === \"\") {\n const isTextual = field.type === 'text' || field.type === 'textarea' || field.type === 'code' || field.type === 'markdown' || field.type === 'email' || field.type === 'password' || field.type === 'color';\n if (!isTextual) data[field.name] = null;\n }\n if (field.type === 'tabs' && field.name && Array.isArray((field as any).tabs) && data[field.name] && typeof data[field.name] === 'object') {\n for (const tab of (field as any).tabs) {\n if (Array.isArray(tab.fields)) normalizeEmptyStrings(data[field.name], tab.fields as Field[]);\n }\n } else if ((field.type === 'group' || field.type === 'collapsible') && field.name && Array.isArray((field as any).fields) && data[field.name] && typeof data[field.name] === 'object') {\n normalizeEmptyStrings(data[field.name], (field as any).fields as Field[]);\n } else if (field.type === 'array' && field.name && Array.isArray((field as any).fields) && Array.isArray(data[field.name])) {\n for (const item of data[field.name]) {\n if (item && typeof item === 'object') normalizeEmptyStrings(item, (field as any).fields as Field[]);\n }\n } else if (field.type === 'blocks' && field.name && Array.isArray((field as any).blocks) && Array.isArray(data[field.name])) {\n for (const item of data[field.name]) {\n if (!item || typeof item !== 'object') continue;\n const blockTypeStr = item.type || item.blockType;\n if (!blockTypeStr) continue;\n const blockDef = (field as any).blocks.find((b: any) => b.slug === blockTypeStr);\n if (!blockDef || !Array.isArray(blockDef.fields)) continue;\n const target = item.data && typeof item.data === 'object' ? item.data : item;\n normalizeEmptyStrings(target, blockDef.fields as Field[]);\n }\n }\n }\n}\n\n// ============================================================================\n// Access Check Helper\n// ============================================================================\n\nasync function checkTRPCAccess(\n config: { access?: any; slug: string },\n operation: \"read\" | \"create\" | \"update\" | \"delete\",\n ctx: KyroContext,\n): Promise<void> {\n const accessRule = config.access?.[operation];\n\n // API key permission check\n const apiKey = ctx.apiKey;\n if (apiKey && apiKey.permissions && apiKey.permissions.length > 0) {\n const resource = config.slug;\n const action = operation === \"read\" ? \"read\" : operation === \"create\" ? \"create\" : \"update\";\n const permission = `${resource}:${action}`;\n if (\n !hasApiKeyPermission(apiKey.permissions, permission) &&\n !hasApiKeyPermission(apiKey.permissions, `${resource}:admin`)\n ) {\n throw new Error(`Access denied: missing API key permission ${permission}`);\n }\n }\n\n // RBAC check for authenticated users (skip when API key permissions are authoritative)\n if (ctx.user && !(apiKey && apiKey.permissions && apiKey.permissions.length > 0)) {\n const resource = config.slug;\n const action = operation === \"read\" ? \"read\" : operation === \"create\" ? \"create\" : operation === \"update\" ? \"update\" : \"delete\";\n const permission = `${resource}:${action}`;\n const userHasPermission = hasPermission(\n { id: ctx.user.id, email: ctx.user.email, role: ctx.user.role } as any,\n permission,\n );\n if (!userHasPermission && !hasPermission(\n { id: ctx.user.id, email: ctx.user.email, role: ctx.user.role } as any,\n `${resource}:admin`,\n )) {\n if (!accessRule) {\n throw new Error(`Access denied: missing RBAC permission ${permission}`);\n }\n }\n }\n\n if (accessRule) {\n const allowed = await evaluateAccess(accessRule, {\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n });\n if (allowed === false) throw new Error(\"Access denied\");\n } else if (!ctx.user && !ctx.apiKey) {\n throw new Error(\"Access denied: authentication required\");\n }\n\n // Set tenant context\n if (ctx.tenantID) {\n ctx.db.setTenantContext({ tenantId: ctx.tenantID, userId: ctx.user?.id ?? '', role: ctx.user?.role, isSuperAdmin: ctx.user?.role === 'super_admin' });\n }\n}\n\n// ============================================================================\n// CRUD Procedure Builders\n// ============================================================================\n\nexport function createFindProcedure(ctx: KyroContext) {\n return async (input: {\n collection: string;\n where?: Record<string, any>;\n sort?: string;\n limit?: number;\n page?: number;\n depth?: number;\n select?: string[];\n draft?: boolean;\n }) => {\n const { collection, where, sort, limit, page, depth, select, draft } = input;\n const config = ctx.registry.getCollection(collection);\n\n await checkTRPCAccess(config, \"read\", ctx);\n\n // Run beforeRead hooks\n if (config.hooks?.beforeRead) {\n for (const hook of config.hooks.beforeRead) {\n await hook({\n collection,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"read\",\n where,\n });\n }\n }\n\n const isDraft = draft ?? !!ctx.user;\n\n // Execute query\n const result = await ctx.db.find({\n collection,\n where: where || {},\n sort,\n limit: limit || 10,\n page: page || 1,\n depth: depth || 0,\n tenantID: ctx.tenantID,\n select,\n draft: isDraft,\n });\n\n // Run afterRead hooks\n if (config.hooks?.afterRead) {\n for (const doc of result.docs) {\n for (const hook of config.hooks.afterRead) {\n await hook({\n collection,\n doc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"read\",\n });\n }\n }\n }\n\n return result;\n };\n}\n\nexport function createFindByIDProcedure(ctx: KyroContext) {\n return async (input: {\n collection: string;\n id: string;\n depth?: number;\n select?: string[];\n draft?: boolean;\n }) => {\n const { collection, id, depth, select, draft } = input;\n const config = ctx.registry.getCollection(collection);\n\n await checkTRPCAccess(config, \"read\", ctx);\n\n const isDraft = draft ?? !!ctx.user;\n\n const doc = await ctx.db.findByID({\n collection,\n id,\n depth: depth || 0,\n tenantID: ctx.tenantID,\n select,\n draft: isDraft,\n });\n\n if (!doc) throw new Error(`Document not found: ${collection}/${id}`);\n\n // Run afterRead hooks\n if (config.hooks?.afterRead) {\n for (const hook of config.hooks.afterRead) {\n await hook({\n collection,\n doc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"read\",\n id,\n });\n }\n }\n\n return doc;\n };\n}\n\nexport function createCreateProcedure(ctx: KyroContext) {\n return async (input: {\n collection: string;\n data: Record<string, any>;\n depth?: number;\n select?: string[];\n }) => {\n const { collection, data, depth, select } = input;\n const config = ctx.registry.getCollection(collection);\n\n await checkTRPCAccess(config, \"create\", ctx);\n\n // Validate with Zod\n const schema = ctx.registry.getCreateZodSchema(collection);\n const validated = schema.parse(data);\n\n // Add tenantID if scoped\n if (config.tenantScoped && ctx.tenantID) {\n validated.tenantID = ctx.tenantID;\n }\n\n // Run beforeValidate hooks\n if (config.hooks?.beforeValidate) {\n for (const hook of config.hooks.beforeValidate) {\n const hookResult = await hook({\n collection,\n data: validated,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"create\",\n });\n if (hookResult) Object.assign(validated, hookResult);\n }\n }\n\n // Run beforeChange hooks\n if (config.hooks?.beforeChange) {\n for (const hook of config.hooks.beforeChange) {\n const hookResult = await hook({\n collection,\n data: validated,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"create\",\n });\n if (hookResult) Object.assign(validated, hookResult);\n }\n }\n\n // Execute create\n const doc = await ctx.db.create({\n collection,\n data: validated,\n depth: depth || 0,\n tenantID: ctx.tenantID,\n select,\n });\n\n // Run afterChange hooks\n if (config.hooks?.afterChange) {\n for (const hook of config.hooks.afterChange) {\n await hook({\n collection,\n doc,\n data: validated,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"create\",\n });\n }\n }\n\n await triggerWebhook(ctx, getWebhookEvent(collection, \"create\"), {\n collection,\n data: doc,\n operation: \"create\",\n });\n\n return { doc };\n };\n}\n\nexport function createUpdateProcedure(ctx: KyroContext) {\n return async (input: {\n collection: string;\n id: string;\n data: Record<string, any>;\n depth?: number;\n select?: string[];\n baseUpdatedAt?: string;\n }) => {\n const { collection, id, data, depth, select, baseUpdatedAt } = input;\n const config = ctx.registry.getCollection(collection);\n\n await checkTRPCAccess(config, \"update\", ctx);\n\n // Get original doc for hooks + conflict detection\n const originalDoc = await ctx.db.findByID({\n collection,\n id,\n tenantID: ctx.tenantID,\n draft: true,\n });\n\n if (!originalDoc)\n throw new Error(`Document not found: ${collection}/${id}`);\n\n // Revision conflict detection\n if (baseUpdatedAt && (originalDoc as Record<string, any>).updatedAt && baseUpdatedAt !== (originalDoc as Record<string, any>).updatedAt) {\n throw new Error(`Revision conflict: document has changed since ${baseUpdatedAt}. Current updatedAt: ${(originalDoc as Record<string, any>).updatedAt}`);\n }\n\n // Normalize empty strings for non-textual field types\n normalizeEmptyStrings(data as any, config.fields as any);\n\n // Validate with Zod\n const schema = ctx.registry.getUpdateZodSchema(collection);\n const validated = schema.parse(data);\n\n // Add tenantID if scoped\n if (config.tenantScoped && ctx.tenantID) {\n validated.tenantID = ctx.tenantID;\n }\n\n // Run beforeValidate hooks\n if (config.hooks?.beforeValidate) {\n for (const hook of config.hooks.beforeValidate) {\n const hookResult = await hook({\n collection,\n data: validated,\n originalDoc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"update\",\n id,\n });\n if (hookResult) Object.assign(validated, hookResult);\n }\n }\n\n // Run beforeChange hooks\n if (config.hooks?.beforeChange) {\n for (const hook of config.hooks.beforeChange) {\n const hookResult = await hook({\n collection,\n data: validated,\n originalDoc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"update\",\n id,\n });\n if (hookResult) Object.assign(validated, hookResult);\n }\n }\n\n // Determine if this is a draft save vs publish\n const isDraft = (ctx.req && typeof (ctx.req as any).headers?.get === \"function\" && (ctx.req as any).headers.get(\"x-draft\") === \"true\") || (input as any).draft === true;\n const isDraftEnabled = config.versions?.drafts === true;\n const isAutosave = ((ctx.req as any)?.query?.autosave === \"true\") || ((ctx.req as any)?.url?.includes(\"autosave=true\")) || (input as any).autosave === true;\n\n let doc;\n if (isDraftEnabled && isDraft) {\n // Draft save: versions table only\n // Autosave reuses a single version slot; manual draft creates a new version\n await ctx.db.createVersion({\n collection,\n documentId: id,\n data: validated,\n status: 'draft',\n autosave: isAutosave,\n createdBy: ctx.user?.id,\n tenantID: ctx.tenantID,\n });\n // Refetch merged doc\n doc = await ctx.db.findByID({ collection, id, tenantID: ctx.tenantID, draft: true });\n } else if (isDraftEnabled) {\n // Publish: main doc + versions table\n doc = await ctx.db.update({\n collection,\n id,\n data: { ...validated, status: 'published' },\n depth: depth || 0,\n tenantID: ctx.tenantID,\n select,\n });\n await ctx.db.createVersion({\n collection,\n documentId: id,\n data: validated,\n status: 'published',\n createdBy: ctx.user?.id,\n tenantID: ctx.tenantID,\n });\n } else {\n // No versions: direct update\n doc = await ctx.db.update({\n collection,\n id,\n data: validated,\n depth: depth || 0,\n tenantID: ctx.tenantID,\n select,\n });\n }\n\n // Run afterChange hooks\n if (config.hooks?.afterChange) {\n for (const hook of config.hooks.afterChange) {\n await hook({\n collection,\n doc,\n data: validated,\n originalDoc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"update\",\n id,\n });\n }\n }\n\n await triggerWebhook(ctx, getWebhookEvent(collection, \"update\"), {\n collection,\n data: doc,\n previousData: originalDoc,\n operation: \"update\",\n });\n\n return { doc };\n };\n}\n\nexport function createDeleteProcedure(ctx: KyroContext) {\n return async (input: { collection: string; id: string }) => {\n const { collection, id } = input;\n const config = ctx.registry.getCollection(collection);\n\n await checkTRPCAccess(config, \"delete\", ctx);\n\n // Get original doc for hooks\n const originalDoc = await ctx.db.findByID({\n collection,\n id,\n tenantID: ctx.tenantID,\n draft: true,\n });\n\n if (!originalDoc)\n throw new Error(`Document not found: ${collection}/${id}`);\n\n // Run beforeDelete hooks\n if (config.hooks?.beforeDelete) {\n for (const hook of config.hooks.beforeDelete) {\n await hook({\n collection,\n doc: originalDoc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"delete\",\n id,\n });\n }\n }\n\n // Execute delete\n const doc = await ctx.db.delete({\n collection,\n id,\n tenantID: ctx.tenantID,\n });\n\n // Run afterDelete hooks\n if (config.hooks?.afterDelete) {\n for (const hook of config.hooks.afterDelete) {\n await hook({\n collection,\n doc,\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n operation: \"delete\",\n id,\n });\n }\n }\n\n await triggerWebhook(ctx, getWebhookEvent(collection, \"delete\"), {\n collection,\n data: doc,\n previousData: originalDoc,\n operation: \"delete\",\n });\n\n return { doc, message: \"Deleted successfully\" };\n };\n}\n\nexport function createCountProcedure(ctx: KyroContext) {\n return async (input: { collection: string; where?: Record<string, any> }) => {\n const { collection, where } = input;\n const config = ctx.registry.getCollection(collection);\n\n await checkTRPCAccess(config, \"read\", ctx);\n\n const totalDocs = await ctx.db.count({\n collection,\n where: where || {},\n tenantID: ctx.tenantID,\n });\n\n return { totalDocs };\n };\n}\n","import type { KyroContext } from \"./context.js\";\nimport {\n createFindProcedure,\n createFindByIDProcedure,\n createCreateProcedure,\n createUpdateProcedure,\n createDeleteProcedure,\n createCountProcedure,\n} from \"./procedures.js\";\nimport { evaluateAccess } from \"../../access/types.js\";\nimport { hasPermission } from \"../../auth/rbac/checker.js\";\nimport { hasApiKeyPermission } from \"../../auth/api-key.js\";\n\n// ============================================================================\n// Global Access Check Helper\n// ============================================================================\n\nasync function checkGlobalAccessTRPC(\n global: { access?: any; slug: string },\n operation: \"read\" | \"update\",\n ctx: KyroContext,\n): Promise<void> {\n const accessRule = global.access?.[operation];\n\n const apiKey = ctx.apiKey;\n if (apiKey && apiKey.permissions && apiKey.permissions.length > 0) {\n const permission = `globals:${operation}`;\n if (\n !hasApiKeyPermission(apiKey.permissions, permission) &&\n !hasApiKeyPermission(apiKey.permissions, \"globals:admin\")\n ) {\n throw new Error(`Access denied: missing API key permission ${permission}`);\n }\n }\n\n if (ctx.user) {\n const permission = `globals:${operation}`;\n const userHasPermission = hasPermission(\n { id: ctx.user.id, email: ctx.user.email, role: ctx.user.role } as any,\n permission,\n );\n if (!userHasPermission && !hasPermission(\n { id: ctx.user.id, email: ctx.user.email, role: ctx.user.role } as any,\n \"globals:admin\",\n )) {\n if (!accessRule) {\n throw new Error(`Access denied: missing RBAC permission ${permission}`);\n }\n }\n }\n\n if (accessRule) {\n const allowed = await evaluateAccess(accessRule, {\n req: ctx.req,\n user: ctx.user,\n tenantID: ctx.tenantID,\n });\n if (allowed === false) throw new Error(\"Access denied\");\n } else if (!ctx.user && !ctx.apiKey) {\n throw new Error(\"Access denied: authentication required\");\n }\n\n if (ctx.tenantID) {\n ctx.db.setTenantContext({ tenantId: ctx.tenantID, userId: ctx.user?.id ?? '', role: ctx.user?.role, isSuperAdmin: ctx.user?.role === 'super_admin' });\n }\n}\n\n// ============================================================================\n// Dynamic Router Generator\n// ============================================================================\n\nexport function createDynamicRouter(ctx: KyroContext) {\n const router: Record<string, any> = {};\n const collections = ctx.registry.getCollections();\n\n for (const collection of collections) {\n const slug = collection.slug;\n\n router[slug] = {\n find: createFindProcedure(ctx),\n findByID: createFindByIDProcedure(ctx),\n create: createCreateProcedure(ctx),\n update: createUpdateProcedure(ctx),\n delete: createDeleteProcedure(ctx),\n count: createCountProcedure(ctx),\n };\n }\n\n // Add globals\n const globals = ctx.registry.getGlobals();\n for (const global of globals) {\n const slug = global.slug;\n\n router[`_globals_${slug}`] = {\n get: async () => {\n await checkGlobalAccessTRPC(global, \"read\", ctx);\n\n const doc = await ctx.db.findOne({\n collection: `_globals_${slug}`,\n where: {},\n tenantID: ctx.tenantID,\n });\n return doc;\n },\n update: async (input: { data: Record<string, any> }) => {\n await checkGlobalAccessTRPC(global, \"update\", ctx);\n\n const schema = ctx.registry.getZodSchema(slug);\n const validated = schema.parse(input.data);\n\n const existing = await ctx.db.findOne({\n collection: `_globals_${slug}`,\n where: {},\n tenantID: ctx.tenantID,\n });\n\n let doc;\n if (existing) {\n doc = await ctx.db.update({\n collection: `_globals_${slug}`,\n id: existing.id,\n data: validated,\n tenantID: ctx.tenantID,\n });\n } else {\n doc = await ctx.db.create({\n collection: `_globals_${slug}`,\n data: { ...validated, id: slug },\n tenantID: ctx.tenantID,\n });\n }\n\n return doc;\n },\n };\n }\n\n return router;\n}\n\n// ============================================================================\n// Typed Router Interface\n// ============================================================================\n\nexport interface KyroRouter {\n [collectionSlug: string]: {\n find: (input: {\n where?: Record<string, any>;\n sort?: string;\n limit?: number;\n page?: number;\n depth?: number;\n select?: string[];\n draft?: boolean;\n }) => Promise<{\n docs: any[];\n totalDocs: number;\n limit: number;\n totalPages: number;\n page: number;\n pagingCounter: number;\n hasPrevPage: boolean;\n hasNextPage: boolean;\n prevPage: number | null;\n nextPage: number | null;\n }>;\n findByID: (input: {\n id: string;\n depth?: number;\n select?: string[];\n draft?: boolean;\n }) => Promise<any>;\n create: (input: {\n data: Record<string, any>;\n depth?: number;\n select?: string[];\n }) => Promise<{ doc: any }>;\n update: (input: {\n id: string;\n data: Record<string, any>;\n depth?: number;\n select?: string[];\n baseUpdatedAt?: string;\n }) => Promise<{ doc: any }>;\n delete: (input: { id: string }) => Promise<{ doc: any; message: string }>;\n count: (input: {\n where?: Record<string, any>;\n }) => Promise<{ totalDocs: number }>;\n };\n}\n\n// ============================================================================\n// Server Entry\n// ============================================================================\n\nexport function createKyroServer(ctx: KyroContext): KyroRouter {\n // Check if tRPC is disabled in settings\n const apiAccess = ctx.settings?.access?.apiAccess;\n if (apiAccess?.trpcEnabled === false) {\n throw new Error(\"tRPC API is disabled\");\n }\n\n return createDynamicRouter(ctx) as KyroRouter;\n}\n"]}