@kyro-cms/core 0.8.0 → 0.9.1

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 (248) hide show
  1. package/README.md +57 -589
  2. package/dist/{WebhookService-118ZTFis.d.ts → WebhookService-CUTb9XOy.d.ts} +1 -1
  3. package/dist/{WebhookService-AefJfqX0.d.cts → WebhookService-Yg2UEOB4.d.cts} +1 -1
  4. package/dist/api-handler-graphql.cjs +44 -0
  5. package/dist/api-handler-graphql.cjs.map +1 -0
  6. package/dist/api-handler-graphql.d.cts +6 -0
  7. package/dist/api-handler-graphql.d.ts +6 -0
  8. package/dist/api-handler-graphql.js +41 -0
  9. package/dist/api-handler-graphql.js.map +1 -0
  10. package/dist/api-handler-trpc.cjs +38 -0
  11. package/dist/api-handler-trpc.cjs.map +1 -0
  12. package/dist/api-handler-trpc.d.cts +5 -0
  13. package/dist/api-handler-trpc.d.ts +5 -0
  14. package/dist/api-handler-trpc.js +36 -0
  15. package/dist/api-handler-trpc.js.map +1 -0
  16. package/dist/api-handler.cjs +31 -97
  17. package/dist/api-handler.cjs.map +1 -1
  18. package/dist/api-handler.d.cts +2 -1
  19. package/dist/api-handler.d.ts +2 -1
  20. package/dist/api-handler.js +19 -95
  21. package/dist/api-handler.js.map +1 -1
  22. package/dist/{tenant-B1YB0Jy8.d.ts → base-B71y_EAF.d.cts} +6 -12
  23. package/dist/{tenant-Cpeveji6.d.cts → base-DaqY2GhA.d.ts} +6 -12
  24. package/dist/bootstrap-5NLASFOG.cjs +32 -0
  25. package/dist/{bootstrap-AKAUP6F6.cjs.map → bootstrap-5NLASFOG.cjs.map} +1 -1
  26. package/dist/bootstrap-T5BK77LD.js +7 -0
  27. package/dist/{bootstrap-JCML6NFO.js.map → bootstrap-T5BK77LD.js.map} +1 -1
  28. package/dist/{chunk-35U3FROB.js → chunk-22M4O4ZJ.js} +607 -63
  29. package/dist/chunk-22M4O4ZJ.js.map +1 -0
  30. package/dist/chunk-2HZRBATX.cjs +253 -0
  31. package/dist/chunk-2HZRBATX.cjs.map +1 -0
  32. package/dist/{chunk-VJT6P4N6.cjs → chunk-3HR772HI.cjs} +199 -32
  33. package/dist/chunk-3HR772HI.cjs.map +1 -0
  34. package/dist/chunk-3KTWGODI.cjs +178 -0
  35. package/dist/chunk-3KTWGODI.cjs.map +1 -0
  36. package/dist/{chunk-QXIQWPAP.js → chunk-3UK5XBVJ.js} +4 -134
  37. package/dist/chunk-3UK5XBVJ.js.map +1 -0
  38. package/dist/{chunk-FXYP2HA6.js → chunk-4AO3A3JM.js} +48 -4
  39. package/dist/chunk-4AO3A3JM.js.map +1 -0
  40. package/dist/chunk-4M7X5HAB.cjs +173 -0
  41. package/dist/chunk-4M7X5HAB.cjs.map +1 -0
  42. package/dist/chunk-5EPFQUQD.js +3243 -0
  43. package/dist/chunk-5EPFQUQD.js.map +1 -0
  44. package/dist/{chunk-Y3N7UUDO.js → chunk-7OGPN7MP.js} +5 -2
  45. package/dist/chunk-7OGPN7MP.js.map +1 -0
  46. package/dist/{chunk-WOWUL7ZY.js → chunk-AL5KX63J.js} +4 -3
  47. package/dist/chunk-AL5KX63J.js.map +1 -0
  48. package/dist/{chunk-2OL4O2TH.cjs → chunk-C36TMDTY.cjs} +66 -61
  49. package/dist/chunk-C36TMDTY.cjs.map +1 -0
  50. package/dist/{chunk-ES5HNFFT.js → chunk-CF7OL6HR.js} +4 -2
  51. package/dist/chunk-CF7OL6HR.js.map +1 -0
  52. package/dist/chunk-CJONKRHJ.js +162 -0
  53. package/dist/chunk-CJONKRHJ.js.map +1 -0
  54. package/dist/{chunk-2KVHZE6O.cjs → chunk-COIASRDK.cjs} +202 -46
  55. package/dist/chunk-COIASRDK.cjs.map +1 -0
  56. package/dist/chunk-DEVFAKCQ.cjs +3291 -0
  57. package/dist/chunk-DEVFAKCQ.cjs.map +1 -0
  58. package/dist/{chunk-3ZFYL34R.js → chunk-DYTZ6FQ7.js} +12 -185
  59. package/dist/chunk-DYTZ6FQ7.js.map +1 -0
  60. package/dist/{chunk-QPPDLRNR.js → chunk-EJN2PAOE.js} +197 -41
  61. package/dist/chunk-EJN2PAOE.js.map +1 -0
  62. package/dist/chunk-FAXU7BMP.js +220 -0
  63. package/dist/chunk-FAXU7BMP.js.map +1 -0
  64. package/dist/{chunk-OHVB4AJ7.js → chunk-FOPGUM27.js} +22 -17
  65. package/dist/chunk-FOPGUM27.js.map +1 -0
  66. package/dist/chunk-GAOXD3XT.js +175 -0
  67. package/dist/chunk-GAOXD3XT.js.map +1 -0
  68. package/dist/{chunk-4DA7QPLA.cjs → chunk-GXFOGU7N.cjs} +5 -2
  69. package/dist/chunk-GXFOGU7N.cjs.map +1 -0
  70. package/dist/{chunk-I7HHI6QV.cjs → chunk-IDVRRRAK.cjs} +17 -9
  71. package/dist/chunk-IDVRRRAK.cjs.map +1 -0
  72. package/dist/{chunk-WQBRWOQT.cjs → chunk-JOPVMWTM.cjs} +3 -2
  73. package/dist/chunk-JOPVMWTM.cjs.map +1 -0
  74. package/dist/chunk-KC2GDBLS.cjs +84 -0
  75. package/dist/chunk-KC2GDBLS.cjs.map +1 -0
  76. package/dist/{chunk-K7JPTH3G.cjs → chunk-KNRSROWB.cjs} +132 -74
  77. package/dist/chunk-KNRSROWB.cjs.map +1 -0
  78. package/dist/{chunk-3AJE4SEG.js → chunk-KPA4AN4R.js} +125 -67
  79. package/dist/chunk-KPA4AN4R.js.map +1 -0
  80. package/dist/{chunk-QUW2RZTM.cjs → chunk-L46ROHUS.cjs} +51 -7
  81. package/dist/chunk-L46ROHUS.cjs.map +1 -0
  82. package/dist/chunk-L4EZKIEX.js +185 -0
  83. package/dist/chunk-L4EZKIEX.js.map +1 -0
  84. package/dist/{chunk-REK7AYOC.js → chunk-L5UKKZQN.js} +199 -32
  85. package/dist/chunk-L5UKKZQN.js.map +1 -0
  86. package/dist/chunk-NKPKR5BW.cjs +188 -0
  87. package/dist/chunk-NKPKR5BW.cjs.map +1 -0
  88. package/dist/{chunk-Y3QQN7PN.js → chunk-P2HKJ7P5.js} +13 -4
  89. package/dist/chunk-P2HKJ7P5.js.map +1 -0
  90. package/dist/{chunk-SA7NSSIQ.cjs → chunk-PI73NNOK.cjs} +13 -187
  91. package/dist/chunk-PI73NNOK.cjs.map +1 -0
  92. package/dist/{chunk-HXRD4B37.js → chunk-PU2Z5VWF.js} +1279 -556
  93. package/dist/chunk-PU2Z5VWF.js.map +1 -0
  94. package/dist/{chunk-H727JIG7.js → chunk-Q72BOAPK.js} +16 -8
  95. package/dist/chunk-Q72BOAPK.js.map +1 -0
  96. package/dist/{chunk-IBG6V56E.cjs → chunk-QFLB4EIJ.cjs} +2 -139
  97. package/dist/chunk-QFLB4EIJ.cjs.map +1 -0
  98. package/dist/{chunk-YVUJBEXE.cjs → chunk-RAMGUDJN.cjs} +16 -7
  99. package/dist/chunk-RAMGUDJN.cjs.map +1 -0
  100. package/dist/{chunk-LINKCEG4.cjs → chunk-ROJHKAQ4.cjs} +617 -73
  101. package/dist/chunk-ROJHKAQ4.cjs.map +1 -0
  102. package/dist/{chunk-5KVM3WEY.cjs → chunk-RSF3UU7H.cjs} +1330 -602
  103. package/dist/chunk-RSF3UU7H.cjs.map +1 -0
  104. package/dist/{chunk-V3LKPM3O.cjs → chunk-SHTTJMLT.cjs} +4 -2
  105. package/dist/chunk-SHTTJMLT.cjs.map +1 -0
  106. package/dist/chunk-SPBTLUN6.js +92 -0
  107. package/dist/chunk-SPBTLUN6.js.map +1 -0
  108. package/dist/{chunk-57P6MJKC.js → chunk-TXSZFA4G.js} +3 -3
  109. package/dist/chunk-TXSZFA4G.js.map +1 -0
  110. package/dist/chunk-UERVXYVK.cjs +99 -0
  111. package/dist/chunk-UERVXYVK.cjs.map +1 -0
  112. package/dist/{chunk-PDYFVNUX.cjs → chunk-V2TVSCV5.cjs} +16 -23
  113. package/dist/chunk-V2TVSCV5.cjs.map +1 -0
  114. package/dist/{chunk-DXHRBMGB.js → chunk-VO35MNPH.js} +12 -19
  115. package/dist/chunk-VO35MNPH.js.map +1 -0
  116. package/dist/{chunk-IA6AU5PI.cjs → chunk-WNCYAKF3.cjs} +3 -3
  117. package/dist/chunk-WNCYAKF3.cjs.map +1 -0
  118. package/dist/chunk-XEB7PH2E.js +81 -0
  119. package/dist/chunk-XEB7PH2E.js.map +1 -0
  120. package/dist/cli/index.cjs +5 -5
  121. package/dist/cli/index.cjs.map +1 -1
  122. package/dist/cli/index.js +5 -5
  123. package/dist/cli/index.js.map +1 -1
  124. package/dist/client.cjs +3 -3
  125. package/dist/client.d.cts +3 -3
  126. package/dist/client.d.ts +3 -3
  127. package/dist/client.js +1 -1
  128. package/dist/drizzle/index.cjs +14 -13
  129. package/dist/drizzle/index.d.cts +9 -7
  130. package/dist/drizzle/index.d.ts +9 -7
  131. package/dist/drizzle/index.js +5 -4
  132. package/dist/fields/index.cjs +21 -37
  133. package/dist/fields/index.d.cts +2 -22
  134. package/dist/fields/index.d.ts +2 -22
  135. package/dist/fields/index.js +1 -1
  136. package/dist/graphql/index.cjs +5 -4
  137. package/dist/graphql/index.d.cts +5 -3
  138. package/dist/graphql/index.d.ts +5 -3
  139. package/dist/graphql/index.js +3 -2
  140. package/dist/index-CJXPB_ot.d.ts +276 -0
  141. package/dist/index-CaTNnLGd.d.cts +276 -0
  142. package/dist/index.cjs +304 -162
  143. package/dist/index.cjs.map +1 -1
  144. package/dist/index.d.cts +129 -205
  145. package/dist/index.d.ts +129 -205
  146. package/dist/index.js +172 -33
  147. package/dist/index.js.map +1 -1
  148. package/dist/integration.cjs +2 -2
  149. package/dist/integration.js +1 -1
  150. package/dist/mongo-auth-adapter-ISOM7FSS.cjs +17 -0
  151. package/dist/{mongo-auth-adapter-NHHUJHVH.cjs.map → mongo-auth-adapter-ISOM7FSS.cjs.map} +1 -1
  152. package/dist/mongo-auth-adapter-MO6STCV3.js +4 -0
  153. package/dist/{mongo-auth-adapter-NJQUUCTP.js.map → mongo-auth-adapter-MO6STCV3.js.map} +1 -1
  154. package/dist/mongodb/index.cjs +8 -7
  155. package/dist/mongodb/index.d.cts +5 -7
  156. package/dist/mongodb/index.d.ts +5 -7
  157. package/dist/mongodb/index.js +4 -3
  158. package/dist/postgres-auth-adapter-DWDR7P5G.js +5 -0
  159. package/dist/{postgres-auth-adapter-3T2NKTSE.js.map → postgres-auth-adapter-DWDR7P5G.js.map} +1 -1
  160. package/dist/postgres-auth-adapter-WRWSJD4E.cjs +14 -0
  161. package/dist/{postgres-auth-adapter-7IEENCKQ.cjs.map → postgres-auth-adapter-WRWSJD4E.cjs.map} +1 -1
  162. package/dist/redis-adapter-HGTPWIGV.js +4 -0
  163. package/dist/{redis-adapter-VQXD7ESY.js.map → redis-adapter-HGTPWIGV.js.map} +1 -1
  164. package/dist/redis-adapter-KJ3YOOT6.cjs +13 -0
  165. package/dist/{redis-adapter-D2E2S3GB.cjs.map → redis-adapter-KJ3YOOT6.cjs.map} +1 -1
  166. package/dist/rest/index.cjs +15 -14
  167. package/dist/rest/index.d.cts +4 -4
  168. package/dist/rest/index.d.ts +4 -4
  169. package/dist/rest/index.js +13 -12
  170. package/dist/{schema-5PHL5IVB.js → schema-6I5OFR4Z.js} +3 -3
  171. package/dist/{schema-5PHL5IVB.js.map → schema-6I5OFR4Z.js.map} +1 -1
  172. package/dist/{schema-37SE2F4B.cjs → schema-TTFE4467.cjs} +14 -14
  173. package/dist/{schema-37SE2F4B.cjs.map → schema-TTFE4467.cjs.map} +1 -1
  174. package/dist/sqlite-adapter-6GEUSVXQ.js +4 -0
  175. package/dist/{sqlite-adapter-TR3U3W6Q.js.map → sqlite-adapter-6GEUSVXQ.js.map} +1 -1
  176. package/dist/sqlite-adapter-CSIZE5SX.cjs +13 -0
  177. package/dist/{sqlite-adapter-LVK5PS4T.cjs.map → sqlite-adapter-CSIZE5SX.cjs.map} +1 -1
  178. package/dist/templates/index.cjs +133 -31
  179. package/dist/templates/index.d.cts +52 -9
  180. package/dist/templates/index.d.ts +52 -9
  181. package/dist/templates/index.js +3 -1
  182. package/dist/trpc/index.cjs +13 -12
  183. package/dist/trpc/index.d.cts +55 -49
  184. package/dist/trpc/index.d.ts +55 -49
  185. package/dist/trpc/index.js +4 -3
  186. package/dist/{types-D6ZLRGbH.d.cts → types-CpjuXbe7.d.cts} +2 -0
  187. package/dist/{types-D6ZLRGbH.d.ts → types-CpjuXbe7.d.ts} +2 -0
  188. package/dist/{types-Bs1up4yP.d.ts → types-CyCQ6SAI.d.ts} +28 -2
  189. package/dist/{types-J3R9nVsZ.d.cts → types-DJxD9394.d.cts} +28 -2
  190. package/dist/{types-VtjUxIMp.d.cts → types-Z6FBiqa2.d.cts} +35 -14
  191. package/dist/{types-VtjUxIMp.d.ts → types-Z6FBiqa2.d.ts} +35 -14
  192. package/package.json +22 -4
  193. package/dist/bootstrap-AKAUP6F6.cjs +0 -32
  194. package/dist/bootstrap-JCML6NFO.js +0 -7
  195. package/dist/chunk-2KVHZE6O.cjs.map +0 -1
  196. package/dist/chunk-2OL4O2TH.cjs.map +0 -1
  197. package/dist/chunk-35U3FROB.js.map +0 -1
  198. package/dist/chunk-3AJE4SEG.js.map +0 -1
  199. package/dist/chunk-3J4MFTI3.js +0 -3872
  200. package/dist/chunk-3J4MFTI3.js.map +0 -1
  201. package/dist/chunk-3ZFYL34R.js.map +0 -1
  202. package/dist/chunk-4DA7QPLA.cjs.map +0 -1
  203. package/dist/chunk-57P6MJKC.js.map +0 -1
  204. package/dist/chunk-5KVM3WEY.cjs.map +0 -1
  205. package/dist/chunk-6IMPH6WV.cjs +0 -3897
  206. package/dist/chunk-6IMPH6WV.cjs.map +0 -1
  207. package/dist/chunk-ATBOUGQP.cjs +0 -513
  208. package/dist/chunk-ATBOUGQP.cjs.map +0 -1
  209. package/dist/chunk-DXHRBMGB.js.map +0 -1
  210. package/dist/chunk-ES5HNFFT.js.map +0 -1
  211. package/dist/chunk-FXYP2HA6.js.map +0 -1
  212. package/dist/chunk-H727JIG7.js.map +0 -1
  213. package/dist/chunk-HXRD4B37.js.map +0 -1
  214. package/dist/chunk-I7HHI6QV.cjs.map +0 -1
  215. package/dist/chunk-IA6AU5PI.cjs.map +0 -1
  216. package/dist/chunk-IBG6V56E.cjs.map +0 -1
  217. package/dist/chunk-K7JPTH3G.cjs.map +0 -1
  218. package/dist/chunk-LINKCEG4.cjs.map +0 -1
  219. package/dist/chunk-OHVB4AJ7.js.map +0 -1
  220. package/dist/chunk-PDYFVNUX.cjs.map +0 -1
  221. package/dist/chunk-Q23JB3KL.js +0 -488
  222. package/dist/chunk-Q23JB3KL.js.map +0 -1
  223. package/dist/chunk-QPPDLRNR.js.map +0 -1
  224. package/dist/chunk-QUW2RZTM.cjs.map +0 -1
  225. package/dist/chunk-QXIQWPAP.js.map +0 -1
  226. package/dist/chunk-R3XIBBAW.cjs +0 -34
  227. package/dist/chunk-R3XIBBAW.cjs.map +0 -1
  228. package/dist/chunk-REK7AYOC.js.map +0 -1
  229. package/dist/chunk-SA7NSSIQ.cjs.map +0 -1
  230. package/dist/chunk-SDMNUYVU.js +0 -30
  231. package/dist/chunk-SDMNUYVU.js.map +0 -1
  232. package/dist/chunk-V3LKPM3O.cjs.map +0 -1
  233. package/dist/chunk-VJT6P4N6.cjs.map +0 -1
  234. package/dist/chunk-WOWUL7ZY.js.map +0 -1
  235. package/dist/chunk-WQBRWOQT.cjs.map +0 -1
  236. package/dist/chunk-Y3N7UUDO.js.map +0 -1
  237. package/dist/chunk-Y3QQN7PN.js.map +0 -1
  238. package/dist/chunk-YVUJBEXE.cjs.map +0 -1
  239. package/dist/index-CLp-DRKA.d.ts +0 -64
  240. package/dist/index-DfO7G4kN.d.cts +0 -64
  241. package/dist/mongo-auth-adapter-NHHUJHVH.cjs +0 -17
  242. package/dist/mongo-auth-adapter-NJQUUCTP.js +0 -4
  243. package/dist/postgres-auth-adapter-3T2NKTSE.js +0 -5
  244. package/dist/postgres-auth-adapter-7IEENCKQ.cjs +0 -14
  245. package/dist/redis-adapter-D2E2S3GB.cjs +0 -13
  246. package/dist/redis-adapter-VQXD7ESY.js +0 -4
  247. package/dist/sqlite-adapter-LVK5PS4T.cjs +0 -13
  248. package/dist/sqlite-adapter-TR3U3W6Q.js +0 -4
@@ -1,8 +1,17 @@
1
+ import { hasAnyRole } from './chunk-L4EZKIEX.js';
2
+
1
3
  // src/database/base.ts
2
4
  var AbstractBaseAdapter = class {
3
5
  collections = /* @__PURE__ */ new Map();
4
6
  globals = /* @__PURE__ */ new Map();
5
7
  connected = false;
8
+ tenantContext;
9
+ setTenantContext(context) {
10
+ this.tenantContext = context;
11
+ }
12
+ getTenantContext() {
13
+ return this.tenantContext;
14
+ }
6
15
  async init(collections, globals = []) {
7
16
  for (const config of collections) {
8
17
  this.collections.set(config.slug, config);
@@ -110,188 +119,6 @@ var AbstractBaseAdapter = class {
110
119
  }
111
120
  };
112
121
 
113
- // src/auth/rbac/roles.ts
114
- var DEFAULT_ROLES = [
115
- {
116
- name: "super_admin",
117
- level: 100,
118
- inherits: [],
119
- description: "Full system access across all tenants"
120
- },
121
- {
122
- name: "admin",
123
- level: 90,
124
- inherits: ["editor"],
125
- description: "Full tenant access with all content permissions"
126
- },
127
- {
128
- name: "editor",
129
- level: 70,
130
- inherits: ["author"],
131
- description: "Edit and publish all content"
132
- },
133
- {
134
- name: "author",
135
- level: 50,
136
- inherits: ["customer"],
137
- description: "Create and edit own content"
138
- },
139
- {
140
- name: "customer",
141
- level: 30,
142
- inherits: [],
143
- description: "Access own data and make purchases"
144
- },
145
- {
146
- name: "guest",
147
- level: 10,
148
- inherits: [],
149
- description: "Public read-only access"
150
- }
151
- ];
152
- var ROLE_PERMISSIONS = {
153
- super_admin: ["*"],
154
- admin: [
155
- "users:admin",
156
- "users:read",
157
- "users:update",
158
- "audit_logs:read",
159
- "posts:admin",
160
- "posts:read",
161
- "posts:create",
162
- "posts:update",
163
- "posts:delete",
164
- "pages:admin",
165
- "pages:read",
166
- "pages:create",
167
- "pages:update",
168
- "pages:delete",
169
- "media:admin",
170
- "media:read",
171
- "media:create",
172
- "media:update",
173
- "media:delete",
174
- "categories:admin",
175
- "categories:read",
176
- "categories:create",
177
- "categories:update",
178
- "categories:delete",
179
- "products:admin",
180
- "products:read",
181
- "products:create",
182
- "products:update",
183
- "products:delete",
184
- "orders:admin",
185
- "orders:read",
186
- "orders:update",
187
- "customers:admin",
188
- "customers:read",
189
- "customers:update",
190
- "coupons:admin",
191
- "coupons:read",
192
- "coupons:create",
193
- "coupons:update",
194
- "coupons:delete",
195
- "navigation:admin",
196
- "navigation:read",
197
- "navigation:create",
198
- "navigation:update",
199
- "navigation:delete",
200
- "settings:admin",
201
- "settings:read",
202
- "settings:update",
203
- "profile:admin",
204
- "profile:read",
205
- "profile:update"
206
- ],
207
- editor: [
208
- "posts:admin",
209
- "posts:read",
210
- "posts:create",
211
- "posts:update",
212
- "posts:delete",
213
- "pages:admin",
214
- "pages:read",
215
- "pages:create",
216
- "pages:update",
217
- "pages:delete",
218
- "media:read",
219
- "media:create",
220
- "media:update",
221
- "categories:read",
222
- "categories:create",
223
- "categories:update",
224
- "products:read",
225
- "orders:read",
226
- "orders:update",
227
- "navigation:read",
228
- "navigation:create",
229
- "navigation:update",
230
- "profile:read",
231
- "profile:update"
232
- ],
233
- author: [
234
- "posts:read",
235
- "posts:create",
236
- "posts:update",
237
- "media:read",
238
- "media:create",
239
- "categories:read",
240
- "profile:read",
241
- "profile:update"
242
- ],
243
- customer: ["profile:read", "profile:update", "orders:read", "orders:create"],
244
- guest: ["posts:read", "pages:read", "products:read"]
245
- };
246
- function getRoleHierarchy(role, roles = DEFAULT_ROLES) {
247
- const hierarchy = [role];
248
- const roleMap = new Map(roles.map((r) => [r.name, r]));
249
- const addInherited = (r) => {
250
- const roleData = roleMap.get(r);
251
- if (roleData && roleData.inherits) {
252
- for (const inherited of roleData.inherits) {
253
- if (!hierarchy.includes(inherited)) {
254
- hierarchy.push(inherited);
255
- addInherited(inherited);
256
- }
257
- }
258
- }
259
- };
260
- addInherited(role);
261
- return hierarchy;
262
- }
263
-
264
- // src/auth/rbac/checker.ts
265
- function hasPermission(user, permission, rolePermissions = ROLE_PERMISSIONS) {
266
- if (!user || !user.role) return false;
267
- const userPermissions = getUserPermissions(user, rolePermissions);
268
- if (userPermissions.includes("*")) return true;
269
- if (userPermissions.includes(permission)) return true;
270
- const [resource, action] = permission.split(":");
271
- if (userPermissions.includes(`${resource}:*`)) return true;
272
- if (userPermissions.includes(`${resource}:admin`)) return true;
273
- return false;
274
- }
275
- function hasAnyRole(user, checkRoles) {
276
- if (!user || !user.role) return false;
277
- const hierarchy = getRoleHierarchy(user.role);
278
- return checkRoles.some((role) => hierarchy.includes(role));
279
- }
280
- function getUserPermissions(user, rolePermissions = ROLE_PERMISSIONS) {
281
- if (!user || !user.role) return [];
282
- const hierarchy = getRoleHierarchy(user.role);
283
- const permissions = /* @__PURE__ */ new Set();
284
- for (const role of hierarchy) {
285
- const rolePerms = rolePermissions[role];
286
- if (rolePerms) {
287
- for (const perm of rolePerms) {
288
- permissions.add(perm);
289
- }
290
- }
291
- }
292
- return Array.from(permissions);
293
- }
294
-
295
122
  // src/auth/rls/tenant.ts
296
123
  var DEFAULT_RLS_CONFIG = {
297
124
  tenantEnabled: true,
@@ -386,6 +213,6 @@ function canAccessDocument(doc, collection, context, config = DEFAULT_RLS_CONFIG
386
213
  return true;
387
214
  }
388
215
 
389
- export { AbstractBaseAdapter, DEFAULT_RLS_CONFIG, applyRLS, canAccessDocument, hasPermission };
390
- //# sourceMappingURL=chunk-3ZFYL34R.js.map
391
- //# sourceMappingURL=chunk-3ZFYL34R.js.map
216
+ export { AbstractBaseAdapter, DEFAULT_RLS_CONFIG, applyRLS, canAccessDocument };
217
+ //# sourceMappingURL=chunk-DYTZ6FQ7.js.map
218
+ //# sourceMappingURL=chunk-DYTZ6FQ7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/database/base.ts","../src/auth/rls/tenant.ts"],"names":[],"mappings":"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","file":"chunk-DYTZ6FQ7.js","sourcesContent":["import type {\n BaseAdapter,\n CollectionConfig,\n GlobalConfig,\n FindArgs,\n FindByIDArgs,\n CreateArgs,\n UpdateArgs,\n DeleteArgs,\n FindResult,\n DraftFindArgs,\n DraftUpsertArgs,\n DraftDeleteArgs,\n DraftSnapshot,\n VersionRecord,\n CreateVersionArgs,\n FindVersionsArgs,\n} from '../registry/types.js';\nimport type { Field, RelationshipField, UploadField } from '../fields/types.js';\nimport type { TenantContext } from '../auth/rls/tenant.js';\n\n// ============================================================================\n// Abstract Base Adapter\n// ============================================================================\n\nexport abstract class AbstractBaseAdapter implements BaseAdapter {\n protected collections: Map<string, CollectionConfig> = new Map();\n protected globals: Map<string, GlobalConfig> = new Map();\n protected connected = false;\n protected tenantContext?: TenantContext;\n\n abstract connect(): Promise<void>;\n abstract disconnect(): Promise<void>;\n\n setTenantContext(context: TenantContext | undefined): void {\n this.tenantContext = context;\n }\n\n getTenantContext(): TenantContext | undefined {\n return this.tenantContext;\n }\n\n async init(collections: CollectionConfig[], globals: GlobalConfig[] = []): Promise<void> {\n for (const config of collections) {\n this.collections.set(config.slug, config);\n }\n for (const config of globals) {\n this.globals.set(config.slug, config);\n }\n await this.connect();\n }\n\n abstract find<T>(args: FindArgs): Promise<FindResult<T>>;\n abstract findByID<T>(args: FindByIDArgs): Promise<T | null>;\n abstract create<T>(args: CreateArgs): Promise<T>;\n abstract update<T>(args: UpdateArgs): Promise<T>;\n abstract delete<T>(args: DeleteArgs): Promise<T>;\n abstract count(args: { collection: string; where?: Record<string, any>; tenantID?: string }): Promise<number>;\n\n abstract findOne(args: { collection: string; where: Record<string, any>; tenantID?: string; draft?: boolean }): Promise<any>;\n\n abstract findVersions(args: FindVersionsArgs): Promise<FindResult<VersionRecord>>;\n abstract findVersionByID(args: { collection: string; versionId: string; tenantID?: string }): Promise<VersionRecord | null>;\n abstract createVersion<T = Record<string, any>>(args: CreateVersionArgs<T>): Promise<VersionRecord<T>>;\n abstract deleteVersions(args: { collection: string; documentId: string; keepLatest?: number; tenantID?: string }): Promise<void>;\n abstract findDraft<T>(args: DraftFindArgs): Promise<DraftSnapshot<T> | null>;\n abstract upsertDraft<T>(args: DraftUpsertArgs<T>): Promise<DraftSnapshot<T>>;\n abstract deleteDraft(args: DraftDeleteArgs): Promise<void>;\n\n async migrate?(): Promise<void>;\n async rollback?(): Promise<void>;\n async transaction?<T>(fn: (tx: any) => Promise<T>): Promise<T>;\n\n // ========================================================================\n // Utility Methods\n // ========================================================================\n\n protected getCollection(slug: string): CollectionConfig {\n const collection = this.collections.get(slug);\n if (!collection) {\n throw new Error(`Collection \"${slug}\" not found in adapter`);\n }\n return collection;\n }\n\n protected applyTenantFilter(where: Record<string, any> = {}, tenantID?: string): Record<string, any> {\n if (tenantID) {\n return {\n ...where,\n tenantID: { equals: tenantID },\n };\n }\n return where;\n }\n\n protected getTableName(slug: string): string {\n return slug.replace(/-/g, '_');\n }\n\n protected prepareData(data: Record<string, any>, collection: CollectionConfig): Record<string, any> {\n const prepared: Record<string, any> = { ...data };\n \n if (collection.timestamps) {\n prepared.updatedAt = new Date().toISOString();\n if (!prepared.createdAt) {\n prepared.createdAt = new Date().toISOString();\n }\n }\n\n // Handle password hashing\n if (collection.auth && prepared.password) {\n // Password should be hashed before this point via hooks\n }\n\n return prepared;\n }\n\n protected processRelationships(\n data: Record<string, any>,\n fields: Field[],\n depth: number\n ): Record<string, any> {\n // This is a base implementation - specific adapters override\n return data;\n }\n\n protected parseSort(sort?: string): { field: string; direction: 'asc' | 'desc' } {\n if (!sort) return { field: 'createdAt', direction: 'desc' };\n if (sort.startsWith('-')) {\n return { field: sort.slice(1), direction: 'desc' };\n }\n return { field: sort, direction: 'asc' };\n }\n\n protected calculatePagination(page: number, limit: number, totalDocs: number) {\n const totalPages = Math.ceil(totalDocs / limit);\n return {\n totalDocs,\n limit,\n totalPages,\n page,\n pagingCounter: (page - 1) * limit + 1,\n hasPrevPage: page > 1,\n hasNextPage: page < totalPages,\n prevPage: page > 1 ? page - 1 : null,\n nextPage: page < totalPages ? page + 1 : null,\n };\n }\n\n protected selectFields(data: Record<string, any>, select?: string[]): Record<string, any> {\n if (!select || select.length === 0) return data;\n const result: Record<string, any> = {};\n for (const field of select) {\n if (field in data) {\n result[field] = data[field];\n }\n }\n result['id'] = data.id;\n return result;\n }\n\n protected isRelationshipField(field: Field): field is RelationshipField {\n return field.type === 'relationship';\n }\n\n protected isUploadField(field: Field): field is UploadField {\n return field.type === 'upload';\n }\n\n protected getRelationshipFields(fields: Field[]): RelationshipField[] {\n const result: RelationshipField[] = [];\n for (const field of fields) {\n if (field.type === 'relationship') {\n result.push(field);\n } else if ('fields' in field && field.fields) {\n result.push(...this.getRelationshipFields(field.fields));\n }\n }\n return result;\n }\n\n protected getUploadFields(fields: Field[]): UploadField[] {\n const result: UploadField[] = [];\n for (const field of fields) {\n if (field.type === 'upload') {\n result.push(field);\n } else if ('fields' in field && field.fields) {\n result.push(...this.getUploadFields(field.fields));\n }\n }\n return result;\n }\n}\n","import type { AuthUser } from \"../types.js\";\nimport { hasAnyRole } from \"../rbac/checker.js\";\n\nexport interface TenantContext {\n tenantId: string;\n userId: string;\n role?: string;\n roles?: string[];\n permissions?: string[];\n isSuperAdmin?: boolean;\n}\n\nexport interface OwnershipRule {\n ownerField: string;\n bypassRoles?: string[];\n}\n\nexport interface RLSConfig {\n tenantEnabled: boolean;\n tenantField: string;\n ownershipRules: Record<string, OwnershipRule>;\n}\n\nexport const DEFAULT_RLS_CONFIG: RLSConfig = {\n tenantEnabled: true,\n tenantField: \"tenantId\",\n ownershipRules: {\n posts: {\n ownerField: \"authorId\",\n bypassRoles: [\"super_admin\", \"admin\", \"editor\"],\n },\n pages: {\n ownerField: \"authorId\",\n bypassRoles: [\"super_admin\", \"admin\", \"editor\"],\n },\n media: {\n ownerField: \"uploadedBy\",\n bypassRoles: [\"super_admin\", \"admin\", \"editor\"],\n },\n orders: {\n ownerField: \"customerId\",\n bypassRoles: [\"super_admin\", \"admin\", \"editor\"],\n },\n customers: { ownerField: \"id\", bypassRoles: [\"super_admin\", \"admin\"] },\n navigation: { ownerField: \"id\", bypassRoles: [\"super_admin\", \"admin\"] },\n },\n};\n\nexport function createTenantContext(user: AuthUser | undefined): TenantContext {\n if (!user) {\n return {\n tenantId: \"public\",\n userId: \"anonymous\",\n role: \"guest\",\n roles: [\"guest\"],\n permissions: [],\n isSuperAdmin: false,\n };\n }\n\n const isSuperAdmin = user.role === \"super_admin\";\n\n return {\n tenantId: user.tenantId || \"default\",\n userId: user.id,\n role: user.role,\n roles: [user.role],\n permissions: [],\n isSuperAdmin,\n };\n}\n\nexport function addTenantFilter<T extends Record<string, any>>(\n query: T,\n context: TenantContext,\n config: RLSConfig = DEFAULT_RLS_CONFIG,\n): T {\n if (!config.tenantEnabled || context.isSuperAdmin) {\n return query;\n }\n\n return {\n ...query,\n where: {\n ...query.where,\n [config.tenantField]: context.tenantId,\n },\n };\n}\n\nexport function applyOwnershipRule(\n query: Record<string, any>,\n collection: string,\n context: TenantContext,\n config: RLSConfig = DEFAULT_RLS_CONFIG,\n): Record<string, any> {\n const rule = config.ownershipRules[collection];\n\n if (!rule) {\n return query;\n }\n\n if (\n rule.bypassRoles &&\n hasAnyRole({ role: context.role } as AuthUser, rule.bypassRoles)\n ) {\n return query;\n }\n\n if (rule.ownerField === \"id\" && context.userId) {\n return {\n ...query,\n where: {\n ...query.where,\n id: context.userId,\n },\n };\n }\n\n if (rule.ownerField && context.userId) {\n return {\n ...query,\n where: {\n ...query.where,\n [rule.ownerField]: context.userId,\n },\n };\n }\n\n return query;\n}\n\nexport function applyRLS<T extends Record<string, any>>(\n query: T,\n collection: string,\n context: TenantContext,\n config: RLSConfig = DEFAULT_RLS_CONFIG,\n): T {\n let result = query;\n\n result = addTenantFilter(result, context, config) as T;\n\n result = applyOwnershipRule(result, collection, context, config) as T;\n\n return result;\n}\n\nexport function canAccessDocument(\n doc: Record<string, any>,\n collection: string,\n context: TenantContext,\n config: RLSConfig = DEFAULT_RLS_CONFIG,\n): boolean {\n if (context.isSuperAdmin) {\n return true;\n }\n\n if (config.tenantEnabled && doc[config.tenantField] !== context.tenantId) {\n return false;\n }\n\n const rule = config.ownershipRules[collection];\n\n if (!rule) {\n return true;\n }\n\n if (\n rule.bypassRoles &&\n hasAnyRole({ role: context.role } as AuthUser, rule.bypassRoles)\n ) {\n return true;\n }\n\n if (rule.ownerField === \"id\") {\n return doc.id === context.userId;\n }\n\n if (rule.ownerField) {\n return doc[rule.ownerField] === context.userId;\n }\n\n return true;\n}\n\nexport function filterDocumentsByRLS(\n docs: Record<string, any>[],\n collection: string,\n context: TenantContext,\n config: RLSConfig = DEFAULT_RLS_CONFIG,\n): Record<string, any>[] {\n if (context.isSuperAdmin) {\n return docs;\n }\n\n return docs.filter((doc) =>\n canAccessDocument(doc, collection, context, config),\n );\n}\n\nexport function sanitizeDocumentByRLS(\n doc: Record<string, any>,\n collection: string,\n context: TenantContext,\n config: RLSConfig = DEFAULT_RLS_CONFIG,\n): Record<string, any> | null {\n if (!canAccessDocument(doc, collection, context, config)) {\n return null;\n }\n\n if (config.tenantEnabled && !context.isSuperAdmin) {\n const { [config.tenantField]: _, ...rest } = doc;\n return rest;\n }\n\n return doc;\n}\n\nexport class RLSPolicy {\n private config: RLSConfig;\n\n constructor(config: RLSConfig = DEFAULT_RLS_CONFIG) {\n this.config = config;\n }\n\n setConfig(config: RLSConfig): void {\n this.config = config;\n }\n\n getConfig(): RLSConfig {\n return this.config;\n }\n\n addOwnershipRule(collection: string, rule: OwnershipRule): void {\n this.config.ownershipRules[collection] = rule;\n }\n\n removeOwnershipRule(collection: string): void {\n delete this.config.ownershipRules[collection];\n }\n\n createContext(user: AuthUser | undefined): TenantContext {\n return createTenantContext(user);\n }\n\n apply<T extends Record<string, any>>(\n query: T,\n collection: string,\n context: TenantContext,\n ): T {\n return applyRLS(query, collection, context, this.config);\n }\n\n canAccess(\n doc: Record<string, any>,\n collection: string,\n context: TenantContext,\n ): boolean {\n return canAccessDocument(doc, collection, context, this.config);\n }\n\n filter(\n docs: Record<string, any>[],\n collection: string,\n context: TenantContext,\n ): Record<string, any>[] {\n return filterDocumentsByRLS(docs, collection, context, this.config);\n }\n\n sanitize(\n doc: Record<string, any>,\n collection: string,\n context: TenantContext,\n ): Record<string, any> | null {\n return sanitizeDocumentByRLS(doc, collection, context, this.config);\n }\n}\n"]}