@trokky/trokky 2.0.3

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 (639) hide show
  1. package/dist/adapters/filesystem/filesystem-adapter.d.ts +80 -0
  2. package/dist/adapters/filesystem/filesystem-adapter.d.ts.map +1 -0
  3. package/dist/adapters/filesystem/filesystem-adapter.js +1370 -0
  4. package/dist/adapters/filesystem/filesystem-adapter.js.map +1 -0
  5. package/dist/adapters/filesystem/index.d.ts +29 -0
  6. package/dist/adapters/filesystem/index.d.ts.map +1 -0
  7. package/dist/adapters/filesystem/index.js +31 -0
  8. package/dist/adapters/filesystem/index.js.map +1 -0
  9. package/dist/adapters/filesystem/types.d.ts +111 -0
  10. package/dist/adapters/filesystem/types.d.ts.map +1 -0
  11. package/dist/adapters/filesystem/types.js +2 -0
  12. package/dist/adapters/filesystem/types.js.map +1 -0
  13. package/dist/adapters/filesystem-data/filesystem-data-adapter.d.ts +111 -0
  14. package/dist/adapters/filesystem-data/filesystem-data-adapter.d.ts.map +1 -0
  15. package/dist/adapters/filesystem-data/filesystem-data-adapter.js +1363 -0
  16. package/dist/adapters/filesystem-data/filesystem-data-adapter.js.map +1 -0
  17. package/dist/adapters/filesystem-data/index.d.ts +3 -0
  18. package/dist/adapters/filesystem-data/index.d.ts.map +1 -0
  19. package/dist/adapters/filesystem-data/index.js +13 -0
  20. package/dist/adapters/filesystem-data/index.js.map +1 -0
  21. package/dist/adapters/filesystem-data/types.d.ts +147 -0
  22. package/dist/adapters/filesystem-data/types.d.ts.map +1 -0
  23. package/dist/adapters/filesystem-data/types.js +2 -0
  24. package/dist/adapters/filesystem-data/types.js.map +1 -0
  25. package/dist/adapters/filesystem-media/filesystem-media-adapter.d.ts +32 -0
  26. package/dist/adapters/filesystem-media/filesystem-media-adapter.d.ts.map +1 -0
  27. package/dist/adapters/filesystem-media/filesystem-media-adapter.js +639 -0
  28. package/dist/adapters/filesystem-media/filesystem-media-adapter.js.map +1 -0
  29. package/dist/adapters/filesystem-media/index.d.ts +3 -0
  30. package/dist/adapters/filesystem-media/index.d.ts.map +1 -0
  31. package/dist/adapters/filesystem-media/index.js +13 -0
  32. package/dist/adapters/filesystem-media/index.js.map +1 -0
  33. package/dist/adapters/filesystem-media/types.d.ts +76 -0
  34. package/dist/adapters/filesystem-media/types.d.ts.map +1 -0
  35. package/dist/adapters/filesystem-media/types.js +2 -0
  36. package/dist/adapters/filesystem-media/types.js.map +1 -0
  37. package/dist/adapters/postgres-data/index.d.ts +3 -0
  38. package/dist/adapters/postgres-data/index.d.ts.map +1 -0
  39. package/dist/adapters/postgres-data/index.js +13 -0
  40. package/dist/adapters/postgres-data/index.js.map +1 -0
  41. package/dist/adapters/postgres-data/postgres-data-adapter.d.ts +154 -0
  42. package/dist/adapters/postgres-data/postgres-data-adapter.d.ts.map +1 -0
  43. package/dist/adapters/postgres-data/postgres-data-adapter.js +1432 -0
  44. package/dist/adapters/postgres-data/postgres-data-adapter.js.map +1 -0
  45. package/dist/adapters/postgres-data/types.d.ts +139 -0
  46. package/dist/adapters/postgres-data/types.d.ts.map +1 -0
  47. package/dist/adapters/postgres-data/types.js +2 -0
  48. package/dist/adapters/postgres-data/types.js.map +1 -0
  49. package/dist/core/adapters/registry.d.ts +79 -0
  50. package/dist/core/adapters/registry.d.ts.map +1 -0
  51. package/dist/core/adapters/registry.js +149 -0
  52. package/dist/core/adapters/registry.js.map +1 -0
  53. package/dist/core/core/engine.d.ts +551 -0
  54. package/dist/core/core/engine.d.ts.map +1 -0
  55. package/dist/core/core/engine.js +1074 -0
  56. package/dist/core/core/engine.js.map +1 -0
  57. package/dist/core/crypto/adapter.d.ts +63 -0
  58. package/dist/core/crypto/adapter.d.ts.map +1 -0
  59. package/dist/core/crypto/adapter.js +63 -0
  60. package/dist/core/crypto/adapter.js.map +1 -0
  61. package/dist/core/crypto/fallback-adapter.d.ts +23 -0
  62. package/dist/core/crypto/fallback-adapter.d.ts.map +1 -0
  63. package/dist/core/crypto/fallback-adapter.js +195 -0
  64. package/dist/core/crypto/fallback-adapter.js.map +1 -0
  65. package/dist/core/crypto/node-adapter.d.ts +20 -0
  66. package/dist/core/crypto/node-adapter.d.ts.map +1 -0
  67. package/dist/core/crypto/node-adapter.js +85 -0
  68. package/dist/core/crypto/node-adapter.js.map +1 -0
  69. package/dist/core/crypto/password-hash.d.ts +73 -0
  70. package/dist/core/crypto/password-hash.d.ts.map +1 -0
  71. package/dist/core/crypto/password-hash.js +244 -0
  72. package/dist/core/crypto/password-hash.js.map +1 -0
  73. package/dist/core/crypto/webcrypto-adapter.d.ts +24 -0
  74. package/dist/core/crypto/webcrypto-adapter.d.ts.map +1 -0
  75. package/dist/core/crypto/webcrypto-adapter.js +158 -0
  76. package/dist/core/crypto/webcrypto-adapter.js.map +1 -0
  77. package/dist/core/errors/index.d.ts +30 -0
  78. package/dist/core/errors/index.d.ts.map +1 -0
  79. package/dist/core/errors/index.js +61 -0
  80. package/dist/core/errors/index.js.map +1 -0
  81. package/dist/core/events/event-bus.d.ts +121 -0
  82. package/dist/core/events/event-bus.d.ts.map +1 -0
  83. package/dist/core/events/event-bus.js +631 -0
  84. package/dist/core/events/event-bus.js.map +1 -0
  85. package/dist/core/events/index.d.ts +17 -0
  86. package/dist/core/events/index.d.ts.map +1 -0
  87. package/dist/core/events/index.js +22 -0
  88. package/dist/core/events/index.js.map +1 -0
  89. package/dist/core/events/memory-storage.d.ts +57 -0
  90. package/dist/core/events/memory-storage.d.ts.map +1 -0
  91. package/dist/core/events/memory-storage.js +175 -0
  92. package/dist/core/events/memory-storage.js.map +1 -0
  93. package/dist/core/events/types.d.ts +434 -0
  94. package/dist/core/events/types.d.ts.map +1 -0
  95. package/dist/core/events/types.js +9 -0
  96. package/dist/core/events/types.js.map +1 -0
  97. package/dist/core/events/utils.d.ts +134 -0
  98. package/dist/core/events/utils.d.ts.map +1 -0
  99. package/dist/core/events/utils.js +333 -0
  100. package/dist/core/events/utils.js.map +1 -0
  101. package/dist/core/fields/conditional.d.ts +115 -0
  102. package/dist/core/fields/conditional.d.ts.map +1 -0
  103. package/dist/core/fields/conditional.js +296 -0
  104. package/dist/core/fields/conditional.js.map +1 -0
  105. package/dist/core/fields/field-type.d.ts +218 -0
  106. package/dist/core/fields/field-type.d.ts.map +1 -0
  107. package/dist/core/fields/field-type.js +17 -0
  108. package/dist/core/fields/field-type.js.map +1 -0
  109. package/dist/core/fields/helpers.d.ts +86 -0
  110. package/dist/core/fields/helpers.d.ts.map +1 -0
  111. package/dist/core/fields/helpers.js +260 -0
  112. package/dist/core/fields/helpers.js.map +1 -0
  113. package/dist/core/fields/index.d.ts +5 -0
  114. package/dist/core/fields/index.d.ts.map +1 -0
  115. package/dist/core/fields/index.js +6 -0
  116. package/dist/core/fields/index.js.map +1 -0
  117. package/dist/core/fields/registry.d.ts +78 -0
  118. package/dist/core/fields/registry.d.ts.map +1 -0
  119. package/dist/core/fields/registry.js +185 -0
  120. package/dist/core/fields/registry.js.map +1 -0
  121. package/dist/core/index.d.ts +39 -0
  122. package/dist/core/index.d.ts.map +1 -0
  123. package/dist/core/index.js +57 -0
  124. package/dist/core/index.js.map +1 -0
  125. package/dist/core/media/image-processor.d.ts +24 -0
  126. package/dist/core/media/image-processor.d.ts.map +1 -0
  127. package/dist/core/media/image-processor.js +69 -0
  128. package/dist/core/media/image-processor.js.map +1 -0
  129. package/dist/core/media/processors/cloudflare-images.d.ts +83 -0
  130. package/dist/core/media/processors/cloudflare-images.d.ts.map +1 -0
  131. package/dist/core/media/processors/cloudflare-images.js +241 -0
  132. package/dist/core/media/processors/cloudflare-images.js.map +1 -0
  133. package/dist/core/media/processors/cloudflare-transform-store.d.ts +127 -0
  134. package/dist/core/media/processors/cloudflare-transform-store.d.ts.map +1 -0
  135. package/dist/core/media/processors/cloudflare-transform-store.js +237 -0
  136. package/dist/core/media/processors/cloudflare-transform-store.js.map +1 -0
  137. package/dist/core/media/processors/cloudflare-transformations.d.ts +81 -0
  138. package/dist/core/media/processors/cloudflare-transformations.d.ts.map +1 -0
  139. package/dist/core/media/processors/cloudflare-transformations.js +144 -0
  140. package/dist/core/media/processors/cloudflare-transformations.js.map +1 -0
  141. package/dist/core/media/processors/index.d.ts +9 -0
  142. package/dist/core/media/processors/index.d.ts.map +1 -0
  143. package/dist/core/media/processors/index.js +13 -0
  144. package/dist/core/media/processors/index.js.map +1 -0
  145. package/dist/core/media/processors/noop.d.ts +22 -0
  146. package/dist/core/media/processors/noop.d.ts.map +1 -0
  147. package/dist/core/media/processors/noop.js +38 -0
  148. package/dist/core/media/processors/noop.js.map +1 -0
  149. package/dist/core/media/processors/sharp.d.ts +30 -0
  150. package/dist/core/media/processors/sharp.d.ts.map +1 -0
  151. package/dist/core/media/processors/sharp.js +126 -0
  152. package/dist/core/media/processors/sharp.js.map +1 -0
  153. package/dist/core/media/processors/types.d.ts +67 -0
  154. package/dist/core/media/processors/types.d.ts.map +1 -0
  155. package/dist/core/media/processors/types.js +42 -0
  156. package/dist/core/media/processors/types.js.map +1 -0
  157. package/dist/core/media/processors/workers-images.d.ts +112 -0
  158. package/dist/core/media/processors/workers-images.d.ts.map +1 -0
  159. package/dist/core/media/processors/workers-images.js +257 -0
  160. package/dist/core/media/processors/workers-images.js.map +1 -0
  161. package/dist/core/schema/registry.d.ts +41 -0
  162. package/dist/core/schema/registry.d.ts.map +1 -0
  163. package/dist/core/schema/registry.js +248 -0
  164. package/dist/core/schema/registry.js.map +1 -0
  165. package/dist/core/schema/singleton.d.ts +107 -0
  166. package/dist/core/schema/singleton.d.ts.map +1 -0
  167. package/dist/core/schema/singleton.js +180 -0
  168. package/dist/core/schema/singleton.js.map +1 -0
  169. package/dist/core/security/auth.d.ts +120 -0
  170. package/dist/core/security/auth.d.ts.map +1 -0
  171. package/dist/core/security/auth.js +274 -0
  172. package/dist/core/security/auth.js.map +1 -0
  173. package/dist/core/security/captcha/index.d.ts +21 -0
  174. package/dist/core/security/captcha/index.d.ts.map +1 -0
  175. package/dist/core/security/captcha/index.js +34 -0
  176. package/dist/core/security/captcha/index.js.map +1 -0
  177. package/dist/core/security/captcha/recaptcha.d.ts +41 -0
  178. package/dist/core/security/captcha/recaptcha.d.ts.map +1 -0
  179. package/dist/core/security/captcha/recaptcha.js +89 -0
  180. package/dist/core/security/captcha/recaptcha.js.map +1 -0
  181. package/dist/core/security/captcha/turnstile.d.ts +41 -0
  182. package/dist/core/security/captcha/turnstile.d.ts.map +1 -0
  183. package/dist/core/security/captcha/turnstile.js +90 -0
  184. package/dist/core/security/captcha/turnstile.js.map +1 -0
  185. package/dist/core/security/captcha/types.d.ts +66 -0
  186. package/dist/core/security/captcha/types.d.ts.map +1 -0
  187. package/dist/core/security/captcha/types.js +7 -0
  188. package/dist/core/security/captcha/types.js.map +1 -0
  189. package/dist/core/security/mfa/email-otp.d.ts +91 -0
  190. package/dist/core/security/mfa/email-otp.d.ts.map +1 -0
  191. package/dist/core/security/mfa/email-otp.js +264 -0
  192. package/dist/core/security/mfa/email-otp.js.map +1 -0
  193. package/dist/core/security/mfa/index.d.ts +8 -0
  194. package/dist/core/security/mfa/index.d.ts.map +1 -0
  195. package/dist/core/security/mfa/index.js +8 -0
  196. package/dist/core/security/mfa/index.js.map +1 -0
  197. package/dist/core/security/mfa/totp.d.ts +87 -0
  198. package/dist/core/security/mfa/totp.d.ts.map +1 -0
  199. package/dist/core/security/mfa/totp.js +293 -0
  200. package/dist/core/security/mfa/totp.js.map +1 -0
  201. package/dist/core/security/middleware.d.ts +102 -0
  202. package/dist/core/security/middleware.d.ts.map +1 -0
  203. package/dist/core/security/middleware.js +261 -0
  204. package/dist/core/security/middleware.js.map +1 -0
  205. package/dist/core/security/oauth/google.d.ts +76 -0
  206. package/dist/core/security/oauth/google.d.ts.map +1 -0
  207. package/dist/core/security/oauth/google.js +154 -0
  208. package/dist/core/security/oauth/google.js.map +1 -0
  209. package/dist/core/security/oauth/index.d.ts +8 -0
  210. package/dist/core/security/oauth/index.d.ts.map +1 -0
  211. package/dist/core/security/oauth/index.js +7 -0
  212. package/dist/core/security/oauth/index.js.map +1 -0
  213. package/dist/core/security/oauth2/authorization-server.d.ts +195 -0
  214. package/dist/core/security/oauth2/authorization-server.d.ts.map +1 -0
  215. package/dist/core/security/oauth2/authorization-server.js +569 -0
  216. package/dist/core/security/oauth2/authorization-server.js.map +1 -0
  217. package/dist/core/security/oauth2/index.d.ts +9 -0
  218. package/dist/core/security/oauth2/index.d.ts.map +1 -0
  219. package/dist/core/security/oauth2/index.js +9 -0
  220. package/dist/core/security/oauth2/index.js.map +1 -0
  221. package/dist/core/security/rate-limiter.d.ts +15 -0
  222. package/dist/core/security/rate-limiter.d.ts.map +1 -0
  223. package/dist/core/security/rate-limiter.js +48 -0
  224. package/dist/core/security/rate-limiter.js.map +1 -0
  225. package/dist/core/security/validation.d.ts +20 -0
  226. package/dist/core/security/validation.d.ts.map +1 -0
  227. package/dist/core/security/validation.js +273 -0
  228. package/dist/core/security/validation.js.map +1 -0
  229. package/dist/core/services/auth-service.d.ts +128 -0
  230. package/dist/core/services/auth-service.d.ts.map +1 -0
  231. package/dist/core/services/auth-service.js +530 -0
  232. package/dist/core/services/auth-service.js.map +1 -0
  233. package/dist/core/services/captcha-service.d.ts +44 -0
  234. package/dist/core/services/captcha-service.d.ts.map +1 -0
  235. package/dist/core/services/captcha-service.js +82 -0
  236. package/dist/core/services/captcha-service.js.map +1 -0
  237. package/dist/core/services/document-service.d.ts +59 -0
  238. package/dist/core/services/document-service.d.ts.map +1 -0
  239. package/dist/core/services/document-service.js +269 -0
  240. package/dist/core/services/document-service.js.map +1 -0
  241. package/dist/core/services/media-service.d.ts +40 -0
  242. package/dist/core/services/media-service.d.ts.map +1 -0
  243. package/dist/core/services/media-service.js +396 -0
  244. package/dist/core/services/media-service.js.map +1 -0
  245. package/dist/core/services/mfa-service.d.ts +123 -0
  246. package/dist/core/services/mfa-service.d.ts.map +1 -0
  247. package/dist/core/services/mfa-service.js +606 -0
  248. package/dist/core/services/mfa-service.js.map +1 -0
  249. package/dist/core/services/oauth-service.d.ts +58 -0
  250. package/dist/core/services/oauth-service.d.ts.map +1 -0
  251. package/dist/core/services/oauth-service.js +253 -0
  252. package/dist/core/services/oauth-service.js.map +1 -0
  253. package/dist/core/services/oauth2-server-service.d.ts +61 -0
  254. package/dist/core/services/oauth2-server-service.d.ts.map +1 -0
  255. package/dist/core/services/oauth2-server-service.js +259 -0
  256. package/dist/core/services/oauth2-server-service.js.map +1 -0
  257. package/dist/core/services/passkey-service.d.ts +59 -0
  258. package/dist/core/services/passkey-service.d.ts.map +1 -0
  259. package/dist/core/services/passkey-service.js +238 -0
  260. package/dist/core/services/passkey-service.js.map +1 -0
  261. package/dist/core/services/token-service.d.ts +31 -0
  262. package/dist/core/services/token-service.d.ts.map +1 -0
  263. package/dist/core/services/token-service.js +132 -0
  264. package/dist/core/services/token-service.js.map +1 -0
  265. package/dist/core/services/trusted-device-service.d.ts +39 -0
  266. package/dist/core/services/trusted-device-service.d.ts.map +1 -0
  267. package/dist/core/services/trusted-device-service.js +123 -0
  268. package/dist/core/services/trusted-device-service.js.map +1 -0
  269. package/dist/core/services/user-service.d.ts +38 -0
  270. package/dist/core/services/user-service.d.ts.map +1 -0
  271. package/dist/core/services/user-service.js +265 -0
  272. package/dist/core/services/user-service.js.map +1 -0
  273. package/dist/core/studio/integration.d.ts +54 -0
  274. package/dist/core/studio/integration.d.ts.map +1 -0
  275. package/dist/core/studio/integration.js +326 -0
  276. package/dist/core/studio/integration.js.map +1 -0
  277. package/dist/core/types/index.d.ts +282 -0
  278. package/dist/core/types/index.d.ts.map +1 -0
  279. package/dist/core/types/index.js +83 -0
  280. package/dist/core/types/index.js.map +1 -0
  281. package/dist/core/types/mail.d.ts +90 -0
  282. package/dist/core/types/mail.d.ts.map +1 -0
  283. package/dist/core/types/mail.js +7 -0
  284. package/dist/core/types/mail.js.map +1 -0
  285. package/dist/core/types/oauth2.d.ts +9 -0
  286. package/dist/core/types/oauth2.d.ts.map +1 -0
  287. package/dist/core/types/oauth2.js +7 -0
  288. package/dist/core/types/oauth2.js.map +1 -0
  289. package/dist/core/types/storage-adapters.d.ts +611 -0
  290. package/dist/core/types/storage-adapters.d.ts.map +1 -0
  291. package/dist/core/types/storage-adapters.js +14 -0
  292. package/dist/core/types/storage-adapters.js.map +1 -0
  293. package/dist/core/types/user.d.ts +10 -0
  294. package/dist/core/types/user.d.ts.map +1 -0
  295. package/dist/core/types/user.js +45 -0
  296. package/dist/core/types/user.js.map +1 -0
  297. package/dist/core/utils/id-generator.d.ts +16 -0
  298. package/dist/core/utils/id-generator.d.ts.map +1 -0
  299. package/dist/core/utils/id-generator.js +61 -0
  300. package/dist/core/utils/id-generator.js.map +1 -0
  301. package/dist/core/utils/logger.d.ts +100 -0
  302. package/dist/core/utils/logger.d.ts.map +1 -0
  303. package/dist/core/utils/logger.js +212 -0
  304. package/dist/core/utils/logger.js.map +1 -0
  305. package/dist/core/utils/reference-expander.d.ts +57 -0
  306. package/dist/core/utils/reference-expander.d.ts.map +1 -0
  307. package/dist/core/utils/reference-expander.js +192 -0
  308. package/dist/core/utils/reference-expander.js.map +1 -0
  309. package/dist/core/utils/universal-crypto.d.ts +46 -0
  310. package/dist/core/utils/universal-crypto.d.ts.map +1 -0
  311. package/dist/core/utils/universal-crypto.js +171 -0
  312. package/dist/core/utils/universal-crypto.js.map +1 -0
  313. package/dist/core/validation/validator.d.ts +11 -0
  314. package/dist/core/validation/validator.d.ts.map +1 -0
  315. package/dist/core/validation/validator.js +164 -0
  316. package/dist/core/validation/validator.js.map +1 -0
  317. package/dist/i18n/config.d.ts +4077 -0
  318. package/dist/i18n/config.d.ts.map +1 -0
  319. package/dist/i18n/config.js +116 -0
  320. package/dist/i18n/config.js.map +1 -0
  321. package/dist/i18n/hooks.d.ts +86 -0
  322. package/dist/i18n/hooks.d.ts.map +1 -0
  323. package/dist/i18n/hooks.js +122 -0
  324. package/dist/i18n/hooks.js.map +1 -0
  325. package/dist/i18n/index.d.ts +39 -0
  326. package/dist/i18n/index.d.ts.map +1 -0
  327. package/dist/i18n/index.js +40 -0
  328. package/dist/i18n/index.js.map +1 -0
  329. package/dist/i18n/locales/en/auth.json +108 -0
  330. package/dist/i18n/locales/en/common.json +100 -0
  331. package/dist/i18n/locales/en/errors.json +55 -0
  332. package/dist/i18n/locales/en/fields.json +456 -0
  333. package/dist/i18n/locales/en/studio.json +1329 -0
  334. package/dist/i18n/locales/fr/auth.json +108 -0
  335. package/dist/i18n/locales/fr/common.json +100 -0
  336. package/dist/i18n/locales/fr/errors.json +55 -0
  337. package/dist/i18n/locales/fr/fields.json +456 -0
  338. package/dist/i18n/locales/fr/studio.json +1274 -0
  339. package/dist/i18n/provider.d.ts +45 -0
  340. package/dist/i18n/provider.d.ts.map +1 -0
  341. package/dist/i18n/provider.js +49 -0
  342. package/dist/i18n/provider.js.map +1 -0
  343. package/dist/i18n/types.d.ts +8 -0
  344. package/dist/i18n/types.d.ts.map +1 -0
  345. package/dist/i18n/types.js +7 -0
  346. package/dist/i18n/types.js.map +1 -0
  347. package/dist/index.d.ts +15 -0
  348. package/dist/index.d.ts.map +1 -0
  349. package/dist/index.js +16 -0
  350. package/dist/index.js.map +1 -0
  351. package/dist/integrations/express/adapter.d.ts +33 -0
  352. package/dist/integrations/express/adapter.d.ts.map +1 -0
  353. package/dist/integrations/express/adapter.js +203 -0
  354. package/dist/integrations/express/adapter.js.map +1 -0
  355. package/dist/integrations/express/config.d.ts +599 -0
  356. package/dist/integrations/express/config.d.ts.map +1 -0
  357. package/dist/integrations/express/config.js +166 -0
  358. package/dist/integrations/express/config.js.map +1 -0
  359. package/dist/integrations/express/index.d.ts +10 -0
  360. package/dist/integrations/express/index.d.ts.map +1 -0
  361. package/dist/integrations/express/index.js +9 -0
  362. package/dist/integrations/express/index.js.map +1 -0
  363. package/dist/integrations/express/integration.d.ts +111 -0
  364. package/dist/integrations/express/integration.d.ts.map +1 -0
  365. package/dist/integrations/express/integration.js +730 -0
  366. package/dist/integrations/express/integration.js.map +1 -0
  367. package/dist/integrations/express/media-rewrite-middleware.d.ts +78 -0
  368. package/dist/integrations/express/media-rewrite-middleware.d.ts.map +1 -0
  369. package/dist/integrations/express/media-rewrite-middleware.js +211 -0
  370. package/dist/integrations/express/media-rewrite-middleware.js.map +1 -0
  371. package/dist/integrations/express/media-url-generator.d.ts +52 -0
  372. package/dist/integrations/express/media-url-generator.d.ts.map +1 -0
  373. package/dist/integrations/express/media-url-generator.js +107 -0
  374. package/dist/integrations/express/media-url-generator.js.map +1 -0
  375. package/dist/integrations/express/middleware.d.ts +25 -0
  376. package/dist/integrations/express/middleware.d.ts.map +1 -0
  377. package/dist/integrations/express/middleware.js +130 -0
  378. package/dist/integrations/express/middleware.js.map +1 -0
  379. package/dist/integrations/express/server.d.ts +99 -0
  380. package/dist/integrations/express/server.d.ts.map +1 -0
  381. package/dist/integrations/express/server.js +597 -0
  382. package/dist/integrations/express/server.js.map +1 -0
  383. package/dist/integrations/express/types.d.ts +106 -0
  384. package/dist/integrations/express/types.d.ts.map +1 -0
  385. package/dist/integrations/express/types.js +2 -0
  386. package/dist/integrations/express/types.js.map +1 -0
  387. package/dist/mail/adapters/console.d.ts +30 -0
  388. package/dist/mail/adapters/console.d.ts.map +1 -0
  389. package/dist/mail/adapters/console.js +169 -0
  390. package/dist/mail/adapters/console.js.map +1 -0
  391. package/dist/mail/adapters/resend.d.ts +18 -0
  392. package/dist/mail/adapters/resend.d.ts.map +1 -0
  393. package/dist/mail/adapters/resend.js +148 -0
  394. package/dist/mail/adapters/resend.js.map +1 -0
  395. package/dist/mail/adapters/smtp.d.ts +22 -0
  396. package/dist/mail/adapters/smtp.d.ts.map +1 -0
  397. package/dist/mail/adapters/smtp.js +180 -0
  398. package/dist/mail/adapters/smtp.js.map +1 -0
  399. package/dist/mail/index.d.ts +15 -0
  400. package/dist/mail/index.d.ts.map +1 -0
  401. package/dist/mail/index.js +13 -0
  402. package/dist/mail/index.js.map +1 -0
  403. package/dist/mail/mail-service.d.ts +180 -0
  404. package/dist/mail/mail-service.d.ts.map +1 -0
  405. package/dist/mail/mail-service.js +370 -0
  406. package/dist/mail/mail-service.js.map +1 -0
  407. package/dist/mail/notification-service.d.ts +82 -0
  408. package/dist/mail/notification-service.d.ts.map +1 -0
  409. package/dist/mail/notification-service.js +262 -0
  410. package/dist/mail/notification-service.js.map +1 -0
  411. package/dist/mail/templates/built-in-templates.d.ts +47 -0
  412. package/dist/mail/templates/built-in-templates.d.ts.map +1 -0
  413. package/dist/mail/templates/built-in-templates.js +416 -0
  414. package/dist/mail/templates/built-in-templates.js.map +1 -0
  415. package/dist/mail/templates/custom-template-renderer.d.ts +115 -0
  416. package/dist/mail/templates/custom-template-renderer.d.ts.map +1 -0
  417. package/dist/mail/templates/custom-template-renderer.js +225 -0
  418. package/dist/mail/templates/custom-template-renderer.js.map +1 -0
  419. package/dist/mail/types.d.ts +7 -0
  420. package/dist/mail/types.d.ts.map +1 -0
  421. package/dist/mail/types.js +7 -0
  422. package/dist/mail/types.js.map +1 -0
  423. package/dist/routes/auth/captcha.d.ts +33 -0
  424. package/dist/routes/auth/captcha.d.ts.map +1 -0
  425. package/dist/routes/auth/captcha.js +102 -0
  426. package/dist/routes/auth/captcha.js.map +1 -0
  427. package/dist/routes/auth/change-password.d.ts +17 -0
  428. package/dist/routes/auth/change-password.d.ts.map +1 -0
  429. package/dist/routes/auth/change-password.js +121 -0
  430. package/dist/routes/auth/change-password.js.map +1 -0
  431. package/dist/routes/auth/index.d.ts +13 -0
  432. package/dist/routes/auth/index.d.ts.map +1 -0
  433. package/dist/routes/auth/index.js +35 -0
  434. package/dist/routes/auth/index.js.map +1 -0
  435. package/dist/routes/auth/mfa.d.ts +121 -0
  436. package/dist/routes/auth/mfa.d.ts.map +1 -0
  437. package/dist/routes/auth/mfa.js +1143 -0
  438. package/dist/routes/auth/mfa.js.map +1 -0
  439. package/dist/routes/auth/oauth.d.ts +37 -0
  440. package/dist/routes/auth/oauth.d.ts.map +1 -0
  441. package/dist/routes/auth/oauth.js +420 -0
  442. package/dist/routes/auth/oauth.js.map +1 -0
  443. package/dist/routes/auth/oauth2-server.d.ts +70 -0
  444. package/dist/routes/auth/oauth2-server.d.ts.map +1 -0
  445. package/dist/routes/auth/oauth2-server.js +775 -0
  446. package/dist/routes/auth/oauth2-server.js.map +1 -0
  447. package/dist/routes/auth/passkey.d.ts +65 -0
  448. package/dist/routes/auth/passkey.d.ts.map +1 -0
  449. package/dist/routes/auth/passkey.js +910 -0
  450. package/dist/routes/auth/passkey.js.map +1 -0
  451. package/dist/routes/auth/password-reset.d.ts +23 -0
  452. package/dist/routes/auth/password-reset.d.ts.map +1 -0
  453. package/dist/routes/auth/password-reset.js +336 -0
  454. package/dist/routes/auth/password-reset.js.map +1 -0
  455. package/dist/routes/handlers/audit.d.ts +21 -0
  456. package/dist/routes/handlers/audit.d.ts.map +1 -0
  457. package/dist/routes/handlers/audit.js +124 -0
  458. package/dist/routes/handlers/audit.js.map +1 -0
  459. package/dist/routes/handlers/auth.d.ts +150 -0
  460. package/dist/routes/handlers/auth.d.ts.map +1 -0
  461. package/dist/routes/handlers/auth.js +512 -0
  462. package/dist/routes/handlers/auth.js.map +1 -0
  463. package/dist/routes/handlers/base.d.ts +34 -0
  464. package/dist/routes/handlers/base.d.ts.map +1 -0
  465. package/dist/routes/handlers/base.js +366 -0
  466. package/dist/routes/handlers/base.js.map +1 -0
  467. package/dist/routes/handlers/config.d.ts +31 -0
  468. package/dist/routes/handlers/config.d.ts.map +1 -0
  469. package/dist/routes/handlers/config.js +483 -0
  470. package/dist/routes/handlers/config.js.map +1 -0
  471. package/dist/routes/handlers/documents.d.ts +50 -0
  472. package/dist/routes/handlers/documents.d.ts.map +1 -0
  473. package/dist/routes/handlers/documents.js +708 -0
  474. package/dist/routes/handlers/documents.js.map +1 -0
  475. package/dist/routes/handlers/index.d.ts +12 -0
  476. package/dist/routes/handlers/index.d.ts.map +1 -0
  477. package/dist/routes/handlers/index.js +11 -0
  478. package/dist/routes/handlers/index.js.map +1 -0
  479. package/dist/routes/handlers/media.d.ts +24 -0
  480. package/dist/routes/handlers/media.d.ts.map +1 -0
  481. package/dist/routes/handlers/media.js +432 -0
  482. package/dist/routes/handlers/media.js.map +1 -0
  483. package/dist/routes/handlers/search.d.ts +10 -0
  484. package/dist/routes/handlers/search.d.ts.map +1 -0
  485. package/dist/routes/handlers/search.js +153 -0
  486. package/dist/routes/handlers/search.js.map +1 -0
  487. package/dist/routes/handlers/tokens.d.ts +14 -0
  488. package/dist/routes/handlers/tokens.d.ts.map +1 -0
  489. package/dist/routes/handlers/tokens.js +109 -0
  490. package/dist/routes/handlers/tokens.js.map +1 -0
  491. package/dist/routes/handlers/types.d.ts +13 -0
  492. package/dist/routes/handlers/types.d.ts.map +1 -0
  493. package/dist/routes/handlers/types.js +5 -0
  494. package/dist/routes/handlers/types.js.map +1 -0
  495. package/dist/routes/handlers/users.d.ts +16 -0
  496. package/dist/routes/handlers/users.d.ts.map +1 -0
  497. package/dist/routes/handlers/users.js +198 -0
  498. package/dist/routes/handlers/users.js.map +1 -0
  499. package/dist/routes/handlers/webhooks.d.ts +37 -0
  500. package/dist/routes/handlers/webhooks.d.ts.map +1 -0
  501. package/dist/routes/handlers/webhooks.js +343 -0
  502. package/dist/routes/handlers/webhooks.js.map +1 -0
  503. package/dist/routes/index.d.ts +5 -0
  504. package/dist/routes/index.d.ts.map +1 -0
  505. package/dist/routes/index.js +5 -0
  506. package/dist/routes/index.js.map +1 -0
  507. package/dist/routes/routes.d.ts +29 -0
  508. package/dist/routes/routes.d.ts.map +1 -0
  509. package/dist/routes/routes.js +531 -0
  510. package/dist/routes/routes.js.map +1 -0
  511. package/dist/routes/slug-processor.d.ts +32 -0
  512. package/dist/routes/slug-processor.d.ts.map +1 -0
  513. package/dist/routes/slug-processor.js +328 -0
  514. package/dist/routes/slug-processor.js.map +1 -0
  515. package/dist/routes/types.d.ts +31 -0
  516. package/dist/routes/types.d.ts.map +1 -0
  517. package/dist/routes/types.js +7 -0
  518. package/dist/routes/types.js.map +1 -0
  519. package/dist/routes/users/index.d.ts +7 -0
  520. package/dist/routes/users/index.d.ts.map +1 -0
  521. package/dist/routes/users/index.js +7 -0
  522. package/dist/routes/users/index.js.map +1 -0
  523. package/dist/structure/builder/StructureBuilder.d.ts +209 -0
  524. package/dist/structure/builder/StructureBuilder.d.ts.map +1 -0
  525. package/dist/structure/builder/StructureBuilder.js +425 -0
  526. package/dist/structure/builder/StructureBuilder.js.map +1 -0
  527. package/dist/structure/builder/index.d.ts +8 -0
  528. package/dist/structure/builder/index.d.ts.map +1 -0
  529. package/dist/structure/builder/index.js +6 -0
  530. package/dist/structure/builder/index.js.map +1 -0
  531. package/dist/structure/builder/navigation-tree-builder.d.ts +33 -0
  532. package/dist/structure/builder/navigation-tree-builder.d.ts.map +1 -0
  533. package/dist/structure/builder/navigation-tree-builder.js +284 -0
  534. package/dist/structure/builder/navigation-tree-builder.js.map +1 -0
  535. package/dist/structure/errors/index.d.ts +72 -0
  536. package/dist/structure/errors/index.d.ts.map +1 -0
  537. package/dist/structure/errors/index.js +136 -0
  538. package/dist/structure/errors/index.js.map +1 -0
  539. package/dist/structure/index.d.ts +14 -0
  540. package/dist/structure/index.d.ts.map +1 -0
  541. package/dist/structure/index.js +16 -0
  542. package/dist/structure/index.js.map +1 -0
  543. package/dist/structure/types/filters.d.ts +167 -0
  544. package/dist/structure/types/filters.d.ts.map +1 -0
  545. package/dist/structure/types/filters.js +38 -0
  546. package/dist/structure/types/filters.js.map +1 -0
  547. package/dist/structure/types/index.d.ts +11 -0
  548. package/dist/structure/types/index.d.ts.map +1 -0
  549. package/dist/structure/types/index.js +7 -0
  550. package/dist/structure/types/index.js.map +1 -0
  551. package/dist/structure/types/permissions.d.ts +159 -0
  552. package/dist/structure/types/permissions.d.ts.map +1 -0
  553. package/dist/structure/types/permissions.js +49 -0
  554. package/dist/structure/types/permissions.js.map +1 -0
  555. package/dist/structure/types/structure.d.ts +342 -0
  556. package/dist/structure/types/structure.d.ts.map +1 -0
  557. package/dist/structure/types/structure.js +6 -0
  558. package/dist/structure/types/structure.js.map +1 -0
  559. package/dist/structure/types/views.d.ts +278 -0
  560. package/dist/structure/types/views.d.ts.map +1 -0
  561. package/dist/structure/types/views.js +6 -0
  562. package/dist/structure/types/views.js.map +1 -0
  563. package/dist/structure/utils/hash.d.ts +61 -0
  564. package/dist/structure/utils/hash.d.ts.map +1 -0
  565. package/dist/structure/utils/hash.js +118 -0
  566. package/dist/structure/utils/hash.js.map +1 -0
  567. package/dist/structure/utils/index.d.ts +10 -0
  568. package/dist/structure/utils/index.d.ts.map +1 -0
  569. package/dist/structure/utils/index.js +7 -0
  570. package/dist/structure/utils/index.js.map +1 -0
  571. package/dist/structure/utils/permission-checker.d.ts +57 -0
  572. package/dist/structure/utils/permission-checker.d.ts.map +1 -0
  573. package/dist/structure/utils/permission-checker.js +286 -0
  574. package/dist/structure/utils/permission-checker.js.map +1 -0
  575. package/dist/structure/utils/query-builder.d.ts +82 -0
  576. package/dist/structure/utils/query-builder.d.ts.map +1 -0
  577. package/dist/structure/utils/query-builder.js +489 -0
  578. package/dist/structure/utils/query-builder.js.map +1 -0
  579. package/dist/structure/utils/structure-merger.d.ts +91 -0
  580. package/dist/structure/utils/structure-merger.d.ts.map +1 -0
  581. package/dist/structure/utils/structure-merger.js +445 -0
  582. package/dist/structure/utils/structure-merger.js.map +1 -0
  583. package/dist/structure/validation/schemas.d.ts +3107 -0
  584. package/dist/structure/validation/schemas.d.ts.map +1 -0
  585. package/dist/structure/validation/schemas.js +436 -0
  586. package/dist/structure/validation/schemas.js.map +1 -0
  587. package/dist/types/api-requests.d.ts +334 -0
  588. package/dist/types/api-requests.d.ts.map +1 -0
  589. package/dist/types/api-requests.js +8 -0
  590. package/dist/types/api-requests.js.map +1 -0
  591. package/dist/types/auth.d.ts +394 -0
  592. package/dist/types/auth.d.ts.map +1 -0
  593. package/dist/types/auth.js +8 -0
  594. package/dist/types/auth.js.map +1 -0
  595. package/dist/types/document.d.ts +49 -0
  596. package/dist/types/document.d.ts.map +1 -0
  597. package/dist/types/document.js +6 -0
  598. package/dist/types/document.js.map +1 -0
  599. package/dist/types/field-system.d.ts +197 -0
  600. package/dist/types/field-system.d.ts.map +1 -0
  601. package/dist/types/field-system.js +8 -0
  602. package/dist/types/field-system.js.map +1 -0
  603. package/dist/types/fields.d.ts +17 -0
  604. package/dist/types/fields.d.ts.map +1 -0
  605. package/dist/types/fields.js +21 -0
  606. package/dist/types/fields.js.map +1 -0
  607. package/dist/types/http.d.ts +162 -0
  608. package/dist/types/http.d.ts.map +1 -0
  609. package/dist/types/http.js +8 -0
  610. package/dist/types/http.js.map +1 -0
  611. package/dist/types/i18n.d.ts +56 -0
  612. package/dist/types/i18n.d.ts.map +1 -0
  613. package/dist/types/i18n.js +25 -0
  614. package/dist/types/i18n.js.map +1 -0
  615. package/dist/types/index.d.ts +22 -0
  616. package/dist/types/index.d.ts.map +1 -0
  617. package/dist/types/index.js +10 -0
  618. package/dist/types/index.js.map +1 -0
  619. package/dist/types/mail.d.ts +224 -0
  620. package/dist/types/mail.d.ts.map +1 -0
  621. package/dist/types/mail.js +8 -0
  622. package/dist/types/mail.js.map +1 -0
  623. package/dist/types/media.d.ts +56 -0
  624. package/dist/types/media.d.ts.map +1 -0
  625. package/dist/types/media.js +6 -0
  626. package/dist/types/media.js.map +1 -0
  627. package/dist/types/oauth2.d.ts +287 -0
  628. package/dist/types/oauth2.d.ts.map +1 -0
  629. package/dist/types/oauth2.js +43 -0
  630. package/dist/types/oauth2.js.map +1 -0
  631. package/dist/types/passkey.d.ts +217 -0
  632. package/dist/types/passkey.d.ts.map +1 -0
  633. package/dist/types/passkey.js +8 -0
  634. package/dist/types/passkey.js.map +1 -0
  635. package/dist/types/slug.d.ts +99 -0
  636. package/dist/types/slug.d.ts.map +1 -0
  637. package/dist/types/slug.js +8 -0
  638. package/dist/types/slug.js.map +1 -0
  639. package/package.json +183 -0
@@ -0,0 +1,708 @@
1
+ /**
2
+ * DocumentRoutes - Collection and document route handlers
3
+ */
4
+ import { SecurityValidator, InvalidInputError, expandDocumentReferences, parseExpandParam } from '../../core/index.js';
5
+ import { processSlugFields } from '../slug-processor.js';
6
+ import { isSingletonSchema, collectStructureSingletons } from '../../core/schema/singleton.js';
7
+ import { BaseRoutes } from './base.js';
8
+ /** System fields that clients may send back but must never overwrite storage-managed values */
9
+ const PRESERVED_SYSTEM_FIELDS = new Set(['_status', '_type']);
10
+ /**
11
+ * Remove client-sent system fields (keys starting with "_") from document data.
12
+ * _status and _type are content-level fields and are preserved.
13
+ */
14
+ function stripSystemFields(data) {
15
+ const result = {};
16
+ for (const [key, value] of Object.entries(data)) {
17
+ if (key.startsWith('_') && !PRESERVED_SYSTEM_FIELDS.has(key)) {
18
+ continue;
19
+ }
20
+ result[key] = value;
21
+ }
22
+ return result;
23
+ }
24
+ export class DocumentRoutes extends BaseRoutes {
25
+ getRoutes() {
26
+ const basePath = this.config.basePath || '';
27
+ return this.defineRoutes([
28
+ ['GET', `${basePath}/collections`, this.listCollections.bind(this)],
29
+ ['GET', `${basePath}/collections/:collection`, this.listDocuments.bind(this)],
30
+ ['POST', `${basePath}/collections/:collection`, this.createDocument.bind(this)],
31
+ ['GET', `${basePath}/collections/:collection/:id`, this.getDocument.bind(this)],
32
+ ['PUT', `${basePath}/collections/:collection/:id`, this.updateDocument.bind(this)],
33
+ ['DELETE', `${basePath}/collections/:collection/:id`, this.deleteDocument.bind(this)],
34
+ ['GET', `${basePath}/stats/:collection`, this.getCollectionStats.bind(this)],
35
+ ['GET', `${basePath}/slugs/check-unique`, this.checkSlugUniqueness.bind(this)]
36
+ ]);
37
+ }
38
+ // Route handlers
39
+ async listCollections(request) {
40
+ try {
41
+ // SECURITY: Validate authentication before processing
42
+ await this.validateAuthentication(request);
43
+ // Get all schemas from the core engine
44
+ const schemas = this.core.getAllSchemas();
45
+ this.logger.debug('Collections listed', {
46
+ count: schemas.length,
47
+ collections: schemas.map(s => s.name)
48
+ });
49
+ return {
50
+ status: 200,
51
+ headers: {
52
+ 'Content-Type': 'application/json',
53
+ ...this.buildCorsHeaders()
54
+ },
55
+ body: JSON.stringify({
56
+ success: true,
57
+ data: {
58
+ collections: schemas
59
+ }
60
+ })
61
+ };
62
+ }
63
+ catch (error) {
64
+ this.logger.error('Failed to list collections', { error: error instanceof Error ? error.message : String(error) });
65
+ // Delegate to errorResponse so authentication failures map to 401
66
+ // rather than being flattened into 400 here.
67
+ if (error instanceof InvalidInputError) {
68
+ return this.errorResponse(error);
69
+ }
70
+ return {
71
+ status: 500,
72
+ headers: { 'Content-Type': 'application/json' },
73
+ body: JSON.stringify({
74
+ success: false,
75
+ error: {
76
+ code: 'INTERNAL_ERROR',
77
+ message: 'Failed to list collections'
78
+ }
79
+ })
80
+ };
81
+ }
82
+ }
83
+ async listDocuments(request) {
84
+ try {
85
+ // SECURITY: Validate authentication and schema read permissions
86
+ await this.validateAuthentication(request);
87
+ const { collection } = request.params;
88
+ await this.validateSchemaAccess(request, collection, 'read');
89
+ const { limit, offset, filter, sort, page, search } = request.query;
90
+ // Validate collection name
91
+ SecurityValidator.validateCollectionName(collection);
92
+ // Build list options - handle both offset and page-based pagination
93
+ const options = {};
94
+ // Handle pagination (page-based or offset-based)
95
+ if (page && limit) {
96
+ const pageNum = parseInt(String(page), 10);
97
+ const limitNum = parseInt(String(limit), 10);
98
+ options.limit = limitNum;
99
+ options.offset = (pageNum - 1) * limitNum;
100
+ }
101
+ else {
102
+ if (limit)
103
+ options.limit = parseInt(String(limit), 10);
104
+ if (offset)
105
+ options.offset = parseInt(String(offset), 10);
106
+ }
107
+ // Handle filters - parse bracket notation from query params
108
+ // Studio sends filter[field]=value which Express parses as nested object
109
+ if (filter) {
110
+ try {
111
+ if (typeof filter === 'string') {
112
+ // Try parsing as JSON string
113
+ options.filter = JSON.parse(filter);
114
+ }
115
+ else if (typeof filter === 'object' && filter !== null) {
116
+ // Already parsed by Express query parser
117
+ options.filter = filter;
118
+ }
119
+ }
120
+ catch {
121
+ throw new InvalidInputError('Invalid filter format', 'filter');
122
+ }
123
+ }
124
+ // Handle sorting - convert prefix notation to field.direction
125
+ // Studio sends "-field" for desc, "field" for asc
126
+ if (sort) {
127
+ if (typeof sort === 'string' && sort.startsWith('-')) {
128
+ options.sort = `${sort.substring(1)}.desc`;
129
+ }
130
+ else if (typeof sort === 'string' && !sort.includes('.') && !sort.includes(':')) {
131
+ options.sort = `${sort}.asc`;
132
+ }
133
+ else {
134
+ options.sort = sort;
135
+ }
136
+ }
137
+ let documents = await this.core.listDocuments(collection, options);
138
+ // Get total count BEFORE search filtering (but after listDocuments)
139
+ // Call dataStorage directly since countDocuments is optional and not on core
140
+ const dataStorage = this.core.dataStorage;
141
+ let totalCount;
142
+ if (dataStorage && dataStorage.countDocuments) {
143
+ // Use adapter's count method with the same filter
144
+ totalCount = await dataStorage.countDocuments(collection, options.filter || {});
145
+ }
146
+ else {
147
+ // Fallback to document length if countDocuments not available
148
+ totalCount = documents.length;
149
+ }
150
+ // Handle search filtering - simple client-side text search
151
+ if (search && typeof search === 'string' && search.trim()) {
152
+ const searchLower = search.trim().toLowerCase();
153
+ documents = documents.filter(doc => {
154
+ // Search across common text fields
155
+ const searchableText = [
156
+ doc.name,
157
+ doc.title,
158
+ doc.description,
159
+ doc.excerpt,
160
+ doc.bio,
161
+ doc.slug,
162
+ doc._id
163
+ ].filter(Boolean).join(' ').toLowerCase();
164
+ return searchableText.includes(searchLower);
165
+ });
166
+ }
167
+ // Handle reference expansion if requested
168
+ const { expand } = request.query;
169
+ if (expand && documents.length > 0) {
170
+ const schema = this.core.getSchema(collection);
171
+ const expandFields = parseExpandParam(expand, schema || undefined);
172
+ if (expandFields.length > 0) {
173
+ // Create a document fetcher that uses the core
174
+ const fetchDocument = async (refCollection, refId) => {
175
+ return this.core.getDocument(refCollection, refId);
176
+ };
177
+ // Expand references in all documents
178
+ documents = await Promise.all(documents.map(doc => expandDocumentReferences(doc, { fields: expandFields }, fetchDocument)));
179
+ }
180
+ }
181
+ // Use actual database count, not filtered result length
182
+ const total = totalCount;
183
+ // Calculate pagination metadata
184
+ const currentPage = page ? parseInt(String(page), 10) : 1;
185
+ const pageSize = options.limit || 25;
186
+ const totalPages = Math.ceil(total / pageSize);
187
+ return this.successResponse({
188
+ documents,
189
+ pagination: {
190
+ page: currentPage,
191
+ limit: pageSize,
192
+ total,
193
+ pages: totalPages
194
+ },
195
+ // Legacy meta for backward compatibility
196
+ meta: {
197
+ total,
198
+ limit: options.limit,
199
+ offset: options.offset
200
+ }
201
+ });
202
+ }
203
+ catch (error) {
204
+ return this.errorResponse(error);
205
+ }
206
+ }
207
+ async createDocument(request) {
208
+ try {
209
+ // SECURITY: Validate authentication and schema write permissions
210
+ await this.validateAuthentication(request);
211
+ const { collection } = request.params;
212
+ await this.validateSchemaAccess(request, collection, 'write');
213
+ // Get current user for audit context
214
+ const currentUser = await this.getCurrentUser(request);
215
+ const auditContext = currentUser ? {
216
+ userId: currentUser.id,
217
+ userType: 'USER',
218
+ username: currentUser.username,
219
+ ipAddress: request.headers['x-forwarded-for'] || request.headers['x-real-ip'],
220
+ userAgent: request.headers['user-agent']
221
+ } : undefined;
222
+ // SECURITY: Validate request body structure before type assertion
223
+ if (!request.body || typeof request.body !== 'object') {
224
+ throw new InvalidInputError('Request body is required', 'body');
225
+ }
226
+ const body = request.body;
227
+ if (!('data' in body) || !body.data || typeof body.data !== 'object') {
228
+ throw new InvalidInputError('Document data is required', 'data');
229
+ }
230
+ const { data, id } = body;
231
+ // Validate inputs
232
+ SecurityValidator.validateCollectionName(collection);
233
+ SecurityValidator.validateDocumentData(data);
234
+ this.logger.debug('Creating document', { collection, data, id });
235
+ // SINGLETON VALIDATION: Check if this collection is a singleton and prevent duplicate creation
236
+ await this.validateSingletonCreation(collection, id);
237
+ // Strip client-sent system fields so they cannot shadow storage-managed values
238
+ const cleanData = stripSystemFields(data);
239
+ // Process slug fields - auto-generate slugs from source fields if not provided
240
+ const processedData = await processSlugFields(this.core, collection, cleanData);
241
+ const document = await this.core.saveDocument(collection, { ...processedData, id }, auditContext);
242
+ return this.successResponse({ document }, 201);
243
+ }
244
+ catch (error) {
245
+ this.logger.error('Failed to create document', {
246
+ collection: request.params.collection,
247
+ error: error instanceof Error ? error.message : String(error),
248
+ stack: error instanceof Error ? error.stack : undefined,
249
+ requestBody: request.body
250
+ });
251
+ return this.errorResponse(error);
252
+ }
253
+ }
254
+ async getDocument(request) {
255
+ try {
256
+ // SECURITY: Validate authentication and schema read permissions
257
+ await this.validateAuthentication(request);
258
+ const { collection, id } = request.params;
259
+ await this.validateSchemaAccess(request, collection, 'read');
260
+ // Validate inputs
261
+ SecurityValidator.validateCollectionName(collection);
262
+ SecurityValidator.validateDocumentId(id);
263
+ let document = await this.core.getDocument(collection, id);
264
+ // If document not found, check if this is a singleton that should be auto-created
265
+ if (!document) {
266
+ const singletonDocument = await this.tryAutoCreateSingleton(collection, id);
267
+ if (singletonDocument) {
268
+ document = singletonDocument;
269
+ }
270
+ else {
271
+ return this.errorResponse(new Error(`Document ${collection}/${id} not found`), 404);
272
+ }
273
+ }
274
+ // Handle reference expansion if requested
275
+ const { expand } = request.query;
276
+ if (expand && document) {
277
+ const schema = this.core.getSchema(collection);
278
+ const expandFields = parseExpandParam(expand, schema || undefined);
279
+ if (expandFields.length > 0) {
280
+ // Create a document fetcher that uses the core
281
+ const fetchDocument = async (refCollection, refId) => {
282
+ return this.core.getDocument(refCollection, refId);
283
+ };
284
+ document = await expandDocumentReferences(document, { fields: expandFields }, fetchDocument);
285
+ }
286
+ }
287
+ return this.successResponse({ document });
288
+ }
289
+ catch (error) {
290
+ return this.errorResponse(error);
291
+ }
292
+ }
293
+ async updateDocument(request) {
294
+ try {
295
+ // SECURITY: Validate authentication and schema write permissions
296
+ await this.validateAuthentication(request);
297
+ const { collection, id } = request.params;
298
+ await this.validateSchemaAccess(request, collection, 'write');
299
+ // Get current user for audit context
300
+ const currentUser = await this.getCurrentUser(request);
301
+ const auditContext = currentUser ? {
302
+ userId: currentUser.id,
303
+ userType: 'USER',
304
+ username: currentUser.username,
305
+ ipAddress: request.headers['x-forwarded-for'] || request.headers['x-real-ip'],
306
+ userAgent: request.headers['user-agent']
307
+ } : undefined;
308
+ // SECURITY: Validate request body structure before type assertion
309
+ if (!request.body || typeof request.body !== 'object') {
310
+ throw new InvalidInputError('Request body is required', 'body');
311
+ }
312
+ const body = request.body;
313
+ if (!('data' in body) || !body.data || typeof body.data !== 'object') {
314
+ throw new InvalidInputError('Document data is required', 'data');
315
+ }
316
+ const { data } = body;
317
+ // Validate inputs
318
+ SecurityValidator.validateCollectionName(collection);
319
+ SecurityValidator.validateDocumentId(id);
320
+ SecurityValidator.validateDocumentData(data);
321
+ // Strip client-sent system fields so they cannot shadow storage-managed values
322
+ const cleanData = stripSystemFields(data);
323
+ // Get existing document to merge with updates
324
+ // For singletons, allow upsert (create if doesn't exist)
325
+ const schema = this.core.getSchema(collection);
326
+ const isSingleton = isSingletonSchema(schema);
327
+ const existingDoc = await this.core.getDocument(collection, id);
328
+ if (!existingDoc && !isSingleton) {
329
+ return this.errorResponse(new Error(`Document ${collection}/${id} not found`), 404);
330
+ }
331
+ // SECURITY: Check publish permission if status is being changed to/from 'published'
332
+ // This enforces the content:publish permission for publishing/unpublishing actions
333
+ const newStatus = cleanData._status;
334
+ const currentStatus = existingDoc?._status;
335
+ const isPublishing = newStatus === 'published' && currentStatus !== 'published';
336
+ const isUnpublishing = newStatus !== 'published' && currentStatus === 'published' && newStatus !== undefined;
337
+ if (isPublishing || isUnpublishing) {
338
+ await this.validateSchemaAccess(request, collection, 'publish');
339
+ }
340
+ // Merge data (excluding system fields including audit fields, but preserve _status)
341
+ let mergedData;
342
+ if (existingDoc) {
343
+ const { _id, _collection, _createdAt, _updatedAt, _revision, _createdBy, _updatedBy, _createdByType, _updatedByType, ...existingData } = existingDoc;
344
+ // Preserve _status from existing document if not explicitly provided in update data
345
+ if (!('_status' in cleanData) && existingDoc._status) {
346
+ mergedData = { ...existingData, ...cleanData, _status: existingDoc._status };
347
+ }
348
+ else {
349
+ mergedData = { ...existingData, ...cleanData };
350
+ }
351
+ }
352
+ else {
353
+ // Singleton doesn't exist yet - create with provided data
354
+ mergedData = cleanData;
355
+ }
356
+ // Process slug fields - auto-generate slugs from source fields if not provided
357
+ // Pass the document ID to exclude it from uniqueness checks during updates
358
+ const processedData = await processSlugFields(this.core, collection, mergedData, id);
359
+ const document = await this.core.saveDocument(collection, { ...processedData, id }, auditContext);
360
+ return this.successResponse({ document });
361
+ }
362
+ catch (error) {
363
+ return this.errorResponse(error);
364
+ }
365
+ }
366
+ async deleteDocument(request) {
367
+ try {
368
+ // SECURITY: Validate authentication
369
+ await this.validateAuthentication(request);
370
+ const { collection, id } = request.params;
371
+ // Validate inputs
372
+ SecurityValidator.validateCollectionName(collection);
373
+ SecurityValidator.validateDocumentId(id);
374
+ // Get current user for ownership check
375
+ const currentUser = await this.getCurrentUser(request);
376
+ // Check if user has general delete permission
377
+ let hasDeletePermission = false;
378
+ try {
379
+ await this.validateSchemaAccess(request, collection, 'delete');
380
+ hasDeletePermission = true;
381
+ }
382
+ catch {
383
+ // User doesn't have general delete permission, check ownership
384
+ hasDeletePermission = false;
385
+ }
386
+ // If no delete permission, check if user owns the document
387
+ if (!hasDeletePermission) {
388
+ if (!currentUser) {
389
+ throw new InvalidInputError('Insufficient permissions to delete this document', 'permissions');
390
+ }
391
+ // Fetch the document to check ownership
392
+ const document = await this.core.getDocument(collection, id);
393
+ if (!document) {
394
+ throw new InvalidInputError('Document not found', 'id');
395
+ }
396
+ // Check if user is the document creator
397
+ const isOwner = document._createdBy === currentUser.id ||
398
+ document._createdBy === currentUser.username;
399
+ if (!isOwner) {
400
+ throw new InvalidInputError('Insufficient permissions to delete this document. You can only delete documents you created.', 'permissions');
401
+ }
402
+ }
403
+ // Get audit context from current user
404
+ const auditContext = currentUser ? {
405
+ userId: currentUser.id,
406
+ userType: 'USER',
407
+ username: currentUser.username,
408
+ ipAddress: request.headers['x-forwarded-for'] || request.headers['x-real-ip'],
409
+ userAgent: request.headers['user-agent']
410
+ } : undefined;
411
+ await this.core.deleteDocument(collection, id, auditContext);
412
+ return this.successResponse({ message: 'Document deleted successfully' });
413
+ }
414
+ catch (error) {
415
+ return this.errorResponse(error);
416
+ }
417
+ }
418
+ async getCollectionStats(request) {
419
+ try {
420
+ // SECURITY: Validate authentication before processing
421
+ await this.validateAuthentication(request);
422
+ const { collection } = request.params;
423
+ // Validate collection name
424
+ SecurityValidator.validateCollectionName(collection);
425
+ // Use countDocuments to avoid loading all documents into memory
426
+ const [totalDocuments, publishedDocuments] = await Promise.all([
427
+ this.core.countDocuments(collection),
428
+ this.core.countDocuments(collection, { _status: 'published' })
429
+ ]);
430
+ const draftDocuments = totalDocuments - publishedDocuments;
431
+ const stats = {
432
+ collection,
433
+ totalDocuments,
434
+ publishedDocuments,
435
+ draftDocuments
436
+ };
437
+ this.logger.debug('Collection stats calculated', { collection, stats });
438
+ return this.successResponse({ stats });
439
+ }
440
+ catch (error) {
441
+ return this.errorResponse(error);
442
+ }
443
+ }
444
+ async checkSlugUniqueness(request) {
445
+ try {
446
+ // SECURITY: Validate authentication before processing
447
+ await this.validateAuthentication(request);
448
+ const { slug, collection, excludeId } = request.query;
449
+ if (!slug || typeof slug !== 'string') {
450
+ throw new InvalidInputError('Slug parameter is required', 'slug');
451
+ }
452
+ if (!collection || typeof collection !== 'string') {
453
+ throw new InvalidInputError('Collection parameter is required', 'collection');
454
+ }
455
+ // Validate collection name and slug format
456
+ SecurityValidator.validateCollectionName(collection);
457
+ // Removed overly restrictive slug format validation
458
+ // Slug format should be validated by the schema field definition, not here
459
+ // This allows slugs to respect schema-level options like allowSlashes, preserveCase, allowedChars
460
+ // Basic check: just ensure it's not empty
461
+ if (!slug || slug.trim() === '') {
462
+ return this.successResponse({
463
+ unique: false,
464
+ reason: 'Slug cannot be empty'
465
+ });
466
+ }
467
+ // Check if slug exists in the collection
468
+ const documents = await this.core.listDocuments(collection, {
469
+ filter: { slug: slug }
470
+ });
471
+ // If excludeId is provided, filter out that document (for updates)
472
+ const conflictingDocs = excludeId
473
+ ? documents.filter(doc => doc._id !== excludeId)
474
+ : documents;
475
+ const isUnique = conflictingDocs.length === 0;
476
+ const responseData = {
477
+ unique: isUnique,
478
+ slug: slug,
479
+ collection: collection,
480
+ ...(isUnique ? {} : { reason: 'Slug already exists in collection' })
481
+ };
482
+ return this.successResponse(responseData);
483
+ }
484
+ catch (error) {
485
+ this.logger.error('Error in checkSlugUniqueness', error);
486
+ return this.errorResponse(error);
487
+ }
488
+ }
489
+ /**
490
+ * Auto-create a singleton document the first time it is read.
491
+ *
492
+ * The schema decides whether the collection is a singleton. The structure only decides
493
+ * which document id that singleton lives under, and whether auto-creation is wanted at
494
+ * all; without a structure entry the id defaults to the collection name.
495
+ */
496
+ async tryAutoCreateSingleton(collection, documentId) {
497
+ try {
498
+ if (!isSingletonSchema(this.core.getSchema(collection))) {
499
+ return null;
500
+ }
501
+ // A structure may carry more than one entry for a collection; prefer the one that names
502
+ // the requested id so each entry's own document stays reachable.
503
+ const entries = (await this.resolveStructureSingletons()).filter(candidate => candidate.collection === collection);
504
+ const entry = entries.find(candidate => candidate.documentId === documentId) ?? entries[0];
505
+ // Only the singleton's own document is conjured up; any other id stays a 404.
506
+ const singletonId = entry?.documentId ?? collection;
507
+ if (documentId !== singletonId) {
508
+ return null;
509
+ }
510
+ if (entry && !entry.autoCreate) {
511
+ this.logger.debug('Singleton auto-creation disabled by structure', { collection, documentId });
512
+ return null;
513
+ }
514
+ // Never conjure up a second document. A singleton whose stored document sits under a
515
+ // different id than the structure asks for would otherwise gain an empty duplicate on
516
+ // the first read, which is the invariant the create guard exists to protect.
517
+ const existingDocuments = await this.core.listDocuments(collection, { limit: 1 });
518
+ if (existingDocuments && existingDocuments.length > 0) {
519
+ this.logger.warn('Not auto-creating singleton: the collection already holds a document', {
520
+ collection,
521
+ documentId,
522
+ existingDocument: existingDocuments[0].id
523
+ });
524
+ return null;
525
+ }
526
+ this.logger.info('Auto-creating singleton document', { collection, documentId });
527
+ // Create the singleton document with sensible defaults
528
+ const singletonData = {
529
+ id: documentId,
530
+ _type: collection,
531
+ title: this.formatSchemaTitle(collection),
532
+ slug: documentId, // Use documentId as slug for singletons
533
+ ...this.getDefaultSingletonData(collection, documentId)
534
+ };
535
+ // Auto-created singleton uses system context
536
+ const systemContext = {
537
+ userId: 'system',
538
+ userType: 'SYSTEM',
539
+ username: 'system'
540
+ };
541
+ const document = await this.core.saveDocument(collection, singletonData, systemContext);
542
+ this.logger.info('Singleton document auto-created', { collection, documentId });
543
+ return document;
544
+ }
545
+ catch (error) {
546
+ this.logger.error('Failed to auto-create singleton', { collection, documentId, error });
547
+ return null;
548
+ }
549
+ }
550
+ /**
551
+ * Resolve the project's structure and collect its singleton entries.
552
+ *
553
+ * The structure is only consulted for presentation details — which id a singleton lives
554
+ * under and whether to auto-create it — never to decide whether a collection is one.
555
+ * A structure that cannot be resolved yields no entries rather than an error, so reads
556
+ * keep working on the schema alone.
557
+ */
558
+ async resolveStructureSingletons() {
559
+ try {
560
+ const customStructure = this.getCustomStructureFunction();
561
+ if (!customStructure)
562
+ return [];
563
+ if (typeof customStructure === 'function') {
564
+ const context = {
565
+ user: null,
566
+ schemas: this.core.getAllSchemas(),
567
+ core: this.core,
568
+ config: this.config
569
+ };
570
+ return collectStructureSingletons(await Promise.resolve(customStructure(context)));
571
+ }
572
+ return collectStructureSingletons(customStructure);
573
+ }
574
+ catch (error) {
575
+ this.logger.warn('Failed to resolve structure for singleton lookup', {
576
+ error: error instanceof Error ? error.message : String(error)
577
+ });
578
+ return [];
579
+ }
580
+ }
581
+ /**
582
+ * Validate singleton creation to prevent duplicates
583
+ */
584
+ async validateSingletonCreation(collection, requestedId) {
585
+ try {
586
+ if (!isSingletonSchema(this.core.getSchema(collection))) {
587
+ return;
588
+ }
589
+ // Check if a singleton document already exists for this collection
590
+ const existingDocuments = await this.core.listDocuments(collection, { limit: 1 });
591
+ if (existingDocuments && existingDocuments.length > 0) {
592
+ this.logger.warn('Attempted to create duplicate singleton document', {
593
+ collection,
594
+ requestedId,
595
+ existingDocument: existingDocuments[0].id
596
+ });
597
+ throw new InvalidInputError(`Singleton document already exists for collection '${collection}'. Only one document is allowed.`, 'singleton_duplicate');
598
+ }
599
+ }
600
+ catch (error) {
601
+ // Re-throw InvalidInputError as-is, wrap other errors
602
+ if (error instanceof InvalidInputError) {
603
+ throw error;
604
+ }
605
+ this.logger.error('Failed to validate singleton creation', {
606
+ collection,
607
+ requestedId,
608
+ error: error instanceof Error ? error.message : String(error)
609
+ });
610
+ // Don't fail the creation if validation fails, just log the error
611
+ // This ensures backward compatibility
612
+ return;
613
+ }
614
+ }
615
+ /**
616
+ * Get default data for specific singleton types
617
+ */
618
+ getDefaultSingletonData(collection, documentId) {
619
+ // Get schema to generate proper defaults
620
+ const schema = this.core.getSchema(collection);
621
+ if (schema) {
622
+ return this.generateSchemaDefaults(schema);
623
+ }
624
+ // Fallback to hardcoded defaults
625
+ switch (collection) {
626
+ case 'homePage':
627
+ return {
628
+ title: 'Home Page',
629
+ description: 'Welcome to our website',
630
+ content: '<p>Welcome to our website! This is the homepage content.</p>',
631
+ slug: 'home'
632
+ };
633
+ case 'settings':
634
+ return {
635
+ title: 'Site Settings',
636
+ siteName: 'My Website',
637
+ description: 'A website built with Trokky'
638
+ };
639
+ default:
640
+ return {};
641
+ }
642
+ }
643
+ /**
644
+ * Generate default values based on schema definition
645
+ */
646
+ generateSchemaDefaults(schema) {
647
+ const defaults = {};
648
+ if (schema.fields) {
649
+ for (const [fieldName, fieldDef] of Object.entries(schema.fields)) {
650
+ const field = fieldDef;
651
+ // Skip fields that start with underscore (system fields)
652
+ if (fieldName.startsWith('_')) {
653
+ continue;
654
+ }
655
+ if (field.default !== undefined) {
656
+ defaults[fieldName] = field.default;
657
+ }
658
+ else {
659
+ const defaultValue = this.getFieldTypeDefault(field);
660
+ // Only include fields that have non-null/non-undefined defaults
661
+ // This prevents validation errors for optional fields like media, references, etc.
662
+ if (defaultValue !== null && defaultValue !== undefined) {
663
+ defaults[fieldName] = defaultValue;
664
+ }
665
+ }
666
+ }
667
+ }
668
+ return defaults;
669
+ }
670
+ /**
671
+ * Get default value for a field type
672
+ */
673
+ getFieldTypeDefault(field) {
674
+ switch (field.type) {
675
+ case 'string':
676
+ return '';
677
+ case 'slug':
678
+ // Slug fields are auto-generated from title, don't provide a default
679
+ return undefined;
680
+ case 'number':
681
+ return 0;
682
+ case 'boolean':
683
+ return false;
684
+ case 'date':
685
+ return new Date().toISOString();
686
+ case 'array':
687
+ // Create empty array - items will be added through UI with proper _type
688
+ return [];
689
+ case 'object':
690
+ // Set _type to the field's name — this identifies the object type
691
+ // in polymorphic contexts (e.g., array items of different types).
692
+ // Matches Studio's ArrayField behavior which uses itemDefinition.name.
693
+ const baseObject = {};
694
+ if (field.name) {
695
+ baseObject._type = field.name;
696
+ }
697
+ return baseObject;
698
+ case 'reference':
699
+ return undefined;
700
+ case 'media':
701
+ // Media fields are optional, don't provide a default
702
+ return undefined;
703
+ default:
704
+ return null;
705
+ }
706
+ }
707
+ }
708
+ //# sourceMappingURL=documents.js.map