@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,41 @@
1
+ import { ContentSchema, TrokkyConfig } from '../types/index.js';
2
+ export declare class SchemaRegistry {
3
+ private schemas;
4
+ private config;
5
+ constructor(schemas: ContentSchema[] | string, config?: TrokkyConfig['features']);
6
+ private loadSchemas;
7
+ private validateAndRegisterSchema;
8
+ /**
9
+ * Automatically injects a slug field for document schemas if:
10
+ * 1. It's a document type (not singleton necessarily, but typically)
11
+ * 2. No slug field is already defined
12
+ * 3. There's a 'title' field to generate from (or fallback to the first string field)
13
+ */
14
+ private injectAutoSlugField;
15
+ /**
16
+ * Automatically injects a thumbnail field for document schemas if:
17
+ * 1. Feature is enabled in configuration (default: true)
18
+ * 2. It's a document type (or singleton if configured to include them)
19
+ * 3. No thumbnail/featured image field is already defined
20
+ * 4. Schema is not in the skip list
21
+ */
22
+ private injectAutoThumbnailField;
23
+ /**
24
+ * Find the best field to use as slug source
25
+ * Priority: 'title' > 'name' > first string field
26
+ */
27
+ private findSlugSourceField;
28
+ getSchema(name: string): ContentSchema | null;
29
+ hasSchema(name: string): boolean;
30
+ getAllSchemas(): ContentSchema[];
31
+ getSchemaNames(): string[];
32
+ registerSchema(schema: ContentSchema): void;
33
+ unregisterSchema(name: string): boolean;
34
+ }
35
+ /**
36
+ * Accept the array form of `fields` ([{ name, type, ... }]) at the top level of
37
+ * a schema and convert it to the record form keyed by field name that the
38
+ * engine, validator and route handlers iterate over. Record form passes through.
39
+ */
40
+ export declare function normalizeSchemaFields(schema: ContentSchema): ContentSchema;
41
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/core/schema/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAuB,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGpF,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAwC;IACvD,OAAO,CAAC,MAAM,CAA0B;gBAE5B,OAAO,EAAE,aAAa,EAAE,GAAG,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,CAAC,UAAU,CAAC;IAWhF,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,yBAAyB;IAajC;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IA0C3B;;;;;;OAMG;IACH,OAAO,CAAC,wBAAwB;IAmHhC;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAuBpB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAI7C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIhC,aAAa,IAAI,aAAa,EAAE;IAIhC,cAAc,IAAI,MAAM,EAAE;IAI1B,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAI3C,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAG/C;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa,CAiB1E"}
@@ -0,0 +1,248 @@
1
+ import { ContentSchemaSchema } from '../types/index.js';
2
+ import { isSingletonSchema } from './singleton.js';
3
+ export class SchemaRegistry {
4
+ schemas = new Map();
5
+ config;
6
+ constructor(schemas, config) {
7
+ this.config = config || {};
8
+ if (Array.isArray(schemas)) {
9
+ this.loadSchemas(schemas);
10
+ }
11
+ else {
12
+ // TODO: Implement dynamic schema loading from file pattern
13
+ throw new Error('File-based schema loading not yet implemented');
14
+ }
15
+ }
16
+ loadSchemas(schemas) {
17
+ for (const schema of schemas) {
18
+ this.validateAndRegisterSchema(schema);
19
+ }
20
+ }
21
+ validateAndRegisterSchema(schema) {
22
+ try {
23
+ // Automatically inject auto-fields for document schemas based on configuration
24
+ let processedSchema = this.injectAutoSlugField(normalizeSchemaFields(schema));
25
+ processedSchema = this.injectAutoThumbnailField(processedSchema);
26
+ const validatedSchema = ContentSchemaSchema.parse(processedSchema);
27
+ this.schemas.set(validatedSchema.name, validatedSchema);
28
+ }
29
+ catch (error) {
30
+ throw new Error(`Invalid schema "${schema.name}": ${error}`);
31
+ }
32
+ }
33
+ /**
34
+ * Automatically injects a slug field for document schemas if:
35
+ * 1. It's a document type (not singleton necessarily, but typically)
36
+ * 2. No slug field is already defined
37
+ * 3. There's a 'title' field to generate from (or fallback to the first string field)
38
+ */
39
+ injectAutoSlugField(schema) {
40
+ // Skip if slug field already exists
41
+ if (schema.fields.slug) {
42
+ return schema;
43
+ }
44
+ // Find a suitable source field for slug generation
45
+ const sourceField = this.findSlugSourceField(schema);
46
+ // Only inject if we have a source field
47
+ if (!sourceField) {
48
+ return schema;
49
+ }
50
+ // Create a copy of the schema with the injected slug field
51
+ // Insert slug field right after the source field for better UX
52
+ const newFields = {};
53
+ for (const [fieldName, fieldDef] of Object.entries(schema.fields)) {
54
+ newFields[fieldName] = fieldDef;
55
+ // Insert slug field right after the source field
56
+ if (fieldName === sourceField) {
57
+ newFields.slug = {
58
+ type: 'slug',
59
+ // Use i18n: prefix to indicate this should be translated on the frontend
60
+ title: 'i18n:autoFields.slug.title',
61
+ description: 'i18n:autoFields.slug.description',
62
+ source: sourceField,
63
+ autoGenerate: true,
64
+ unique: true,
65
+ required: false // Auto-generated, so not strictly required from user
66
+ };
67
+ }
68
+ }
69
+ return {
70
+ ...schema,
71
+ fields: newFields
72
+ };
73
+ }
74
+ /**
75
+ * Automatically injects a thumbnail field for document schemas if:
76
+ * 1. Feature is enabled in configuration (default: true)
77
+ * 2. It's a document type (or singleton if configured to include them)
78
+ * 3. No thumbnail/featured image field is already defined
79
+ * 4. Schema is not in the skip list
80
+ */
81
+ injectAutoThumbnailField(schema) {
82
+ const autoThumbnailConfig = this.config?.autoThumbnail || {};
83
+ // Check if feature is enabled (default: true)
84
+ if (autoThumbnailConfig.enabled === false) {
85
+ return schema;
86
+ }
87
+ // Check if schema is in skip list
88
+ if (autoThumbnailConfig.skipSchemas?.includes(schema.name)) {
89
+ return schema;
90
+ }
91
+ // Skip singletons if configured to do so (default: true)
92
+ const skipSingletons = autoThumbnailConfig.skipSingletons !== false;
93
+ if (skipSingletons && isSingletonSchema(schema)) {
94
+ return schema;
95
+ }
96
+ // Get field name from config (default: '_thumbnail')
97
+ const fieldName = autoThumbnailConfig.fieldName || '_thumbnail';
98
+ // Skip if thumbnail field already exists (check configured name and common variations)
99
+ if (schema.fields[fieldName] ||
100
+ schema.fields._thumbnail ||
101
+ schema.fields.thumbnail ||
102
+ schema.fields.featuredImage ||
103
+ schema.fields.featured_image ||
104
+ schema.fields.image) {
105
+ return schema;
106
+ }
107
+ // Get configuration values with defaults
108
+ const maxFileSize = autoThumbnailConfig.maxFileSize || 10 * 1024 * 1024; // 10MB
109
+ const allowedTypes = autoThumbnailConfig.allowedTypes || [
110
+ 'image/jpeg', 'image/png', 'image/webp', 'image/gif'
111
+ ];
112
+ // Create a copy of the schema with the injected thumbnail field
113
+ // Insert thumbnail field at the beginning for better UX (after title/name if present)
114
+ const newFields = {};
115
+ let thumbnailInserted = false;
116
+ for (const [fieldKey, fieldDef] of Object.entries(schema.fields)) {
117
+ newFields[fieldKey] = fieldDef;
118
+ // Insert thumbnail field after title, name, or slug field for better UX
119
+ if (!thumbnailInserted && (fieldKey === 'title' || fieldKey === 'name' || fieldKey === 'slug')) {
120
+ newFields[fieldName] = {
121
+ type: 'media',
122
+ // Use i18n: prefix to indicate this should be translated on the frontend
123
+ title: 'i18n:autoFields._thumbnail.title',
124
+ description: 'i18n:autoFields._thumbnail.description',
125
+ required: false,
126
+ options: {
127
+ // Enable upload/browse functionality
128
+ enableUpload: true,
129
+ enableBrowse: true,
130
+ enableDragDrop: true,
131
+ // Media type and validation
132
+ showVariantSelector: true,
133
+ showMetadata: true,
134
+ showPreview: true,
135
+ requireAlt: true
136
+ },
137
+ validation: {
138
+ allowedTypes,
139
+ maxFileSize,
140
+ restrictToMediaType: 'image'
141
+ }
142
+ };
143
+ thumbnailInserted = true;
144
+ }
145
+ }
146
+ // If we haven't inserted it yet, add it at the beginning
147
+ if (!thumbnailInserted) {
148
+ const fieldsWithThumbnail = {
149
+ [fieldName]: {
150
+ type: 'media',
151
+ // Use i18n: prefix to indicate this should be translated on the frontend
152
+ title: 'i18n:autoFields._thumbnail.title',
153
+ description: 'i18n:autoFields._thumbnail.description',
154
+ required: false,
155
+ options: {
156
+ // Enable upload/browse functionality
157
+ enableUpload: true,
158
+ enableBrowse: true,
159
+ enableDragDrop: true,
160
+ // Media type and validation
161
+ showVariantSelector: true,
162
+ showMetadata: true,
163
+ showPreview: true,
164
+ requireAlt: true
165
+ },
166
+ validation: {
167
+ allowedTypes,
168
+ maxFileSize,
169
+ restrictToMediaType: 'image'
170
+ }
171
+ },
172
+ ...newFields
173
+ };
174
+ return {
175
+ ...schema,
176
+ fields: fieldsWithThumbnail
177
+ };
178
+ }
179
+ return {
180
+ ...schema,
181
+ fields: newFields
182
+ };
183
+ }
184
+ /**
185
+ * Find the best field to use as slug source
186
+ * Priority: 'title' > 'name' > first string field
187
+ */
188
+ findSlugSourceField(schema) {
189
+ const fields = schema.fields;
190
+ // Priority 1: 'title' field
191
+ if (fields.title && fields.title.type === 'string') {
192
+ return 'title';
193
+ }
194
+ // Priority 2: 'name' field
195
+ if (fields.name && fields.name.type === 'string') {
196
+ return 'name';
197
+ }
198
+ // Priority 3: First string field
199
+ for (const [fieldName, fieldDef] of Object.entries(fields)) {
200
+ if (fieldDef.type === 'string') {
201
+ return fieldName;
202
+ }
203
+ }
204
+ return null;
205
+ }
206
+ getSchema(name) {
207
+ return this.schemas.get(name) || null;
208
+ }
209
+ hasSchema(name) {
210
+ return this.schemas.has(name);
211
+ }
212
+ getAllSchemas() {
213
+ return Array.from(this.schemas.values());
214
+ }
215
+ getSchemaNames() {
216
+ return Array.from(this.schemas.keys());
217
+ }
218
+ registerSchema(schema) {
219
+ this.validateAndRegisterSchema(schema);
220
+ }
221
+ unregisterSchema(name) {
222
+ return this.schemas.delete(name);
223
+ }
224
+ }
225
+ /**
226
+ * Accept the array form of `fields` ([{ name, type, ... }]) at the top level of
227
+ * a schema and convert it to the record form keyed by field name that the
228
+ * engine, validator and route handlers iterate over. Record form passes through.
229
+ */
230
+ export function normalizeSchemaFields(schema) {
231
+ const fields = schema.fields;
232
+ if (!Array.isArray(fields)) {
233
+ return schema;
234
+ }
235
+ const record = {};
236
+ for (const entry of fields) {
237
+ const { name, ...rest } = entry;
238
+ if (typeof name !== 'string' || name.length === 0) {
239
+ throw new Error(`Schema "${schema.name}": every field in array form needs a non-empty "name"`);
240
+ }
241
+ if (name in record) {
242
+ throw new Error(`Schema "${schema.name}": duplicate field "${name}"`);
243
+ }
244
+ record[name] = rest;
245
+ }
246
+ return { ...schema, fields: record };
247
+ }
248
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/core/schema/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Singleton resolution — the one place that answers "does this collection hold
3
+ * exactly one document?".
4
+ *
5
+ * The schema is the source of truth. "Exactly one document" is a content-model
6
+ * invariant: it governs the create guard, the PUT upsert, and how the CLI restores
7
+ * a backup. A `type: 'singleton'` entry in a project's structure answers a different
8
+ * question — which document the navigation opens and auto-creates — and must never
9
+ * be used to decide the invariant, because a project can have no custom structure,
10
+ * a static one, or one that varies by user role.
11
+ *
12
+ * Declaring the structure entry without the schema flag used to be silent: every
13
+ * request still behaved correctly and the divergence only surfaced later, when a
14
+ * restore regenerated document ids and dropped documents. `assertSingletonConsistency`
15
+ * turns that into a boot failure instead.
16
+ */
17
+ import type { ContentSchema } from '../types/index.js';
18
+ /** A structure entry that presents a collection as a singleton. */
19
+ export interface StructureSingleton {
20
+ collection: string;
21
+ documentId: string;
22
+ /** `options.autoCreate`, defaulting to true when the entry does not set it. */
23
+ autoCreate: boolean;
24
+ }
25
+ export interface SingletonConsistencyIssue {
26
+ collection: string;
27
+ documentId: string;
28
+ reason: 'schema-not-singleton' | 'schema-missing';
29
+ }
30
+ /** A singleton whose one stored document is filed under an id the structure does not name. */
31
+ export interface SingletonStoredIdIssue {
32
+ collection: string;
33
+ /** The id the structure addresses the singleton by. */
34
+ expectedId: string;
35
+ /** The id the document is actually stored under. */
36
+ actualId: string;
37
+ }
38
+ /**
39
+ * The slice of the core the stored-id check needs.
40
+ *
41
+ * Narrowed to one method so the check can be unit-tested without standing up an engine, and so
42
+ * it cannot reach for anything that writes: a boot-time advisory only ever reads.
43
+ */
44
+ export interface SingletonDocumentReader {
45
+ listDocuments(collection: string, options?: {
46
+ limit?: number;
47
+ }): Promise<Array<{
48
+ id?: string;
49
+ } | null | undefined>>;
50
+ }
51
+ /**
52
+ * Whether a schema declares itself a singleton.
53
+ *
54
+ * Both spellings are accepted: `singleton: true` and `type: 'singleton'`. Either alone means
55
+ * singleton, so a schema that sets `type: 'singleton'` alongside `singleton: false` is still
56
+ * one. Schemas are validated as `z.ZodSchema<any>`, so neither spelling is checked by the
57
+ * compiler and a near miss such as `isSingleton: true` is silently ignored — which is exactly
58
+ * why the consistency check below exists.
59
+ */
60
+ export declare function isSingletonSchema(schema: ContentSchema | null | undefined): boolean;
61
+ /**
62
+ * Collect every `type: 'singleton'` entry in a resolved structure, walking nested items.
63
+ *
64
+ * `documentId` falls back to the collection name, matching how the Studio addresses a
65
+ * singleton view that does not name one explicitly.
66
+ */
67
+ export declare function collectStructureSingletons(structure: any): StructureSingleton[];
68
+ /**
69
+ * Find structure singletons whose schema does not declare the invariant.
70
+ *
71
+ * Only this direction is a defect. A schema may be a singleton without appearing in the
72
+ * structure at all — it simply gets no navigation entry.
73
+ */
74
+ export declare function findSingletonConsistencyIssues(structure: any, schemas: ContentSchema[]): SingletonConsistencyIssue[];
75
+ /**
76
+ * Throw if the structure and the schemas disagree about which collections are singletons.
77
+ *
78
+ * Called at startup so the mismatch is reported against the project's source, long before
79
+ * it can cost documents during a restore.
80
+ *
81
+ * Only a schema that contradicts the structure is fatal. A structure entry naming a schema
82
+ * that is not registered at all is reported through `onWarning` instead: it costs a broken
83
+ * navigation link rather than documents, and a project may legitimately leave a nav entry in
84
+ * place while registering its schema conditionally.
85
+ */
86
+ export declare function assertSingletonConsistency(structure: any, schemas: ContentSchema[], onWarning?: (message: string) => void): void;
87
+ /**
88
+ * Warn when a singleton's stored document is filed under a different id than the structure names.
89
+ *
90
+ * The structure addresses a singleton by a fixed id, so a structure that says 'home' while storage
91
+ * holds 'homepage' silently 404s the singleton view — the document is there, nothing errors, and
92
+ * the only symptom is an editor screen that offers to create a document that already exists.
93
+ * Restores compound it, because they write back the id they find rather than the id the structure
94
+ * expects.
95
+ *
96
+ * This warns and never throws, unlike `assertSingletonConsistency` above. That check reads the
97
+ * project's own source, where a disagreement is always a defect the developer can fix on the spot.
98
+ * This one reads data, where the same divergence is routinely a legitimate intermediate state — a
99
+ * rename mid-migration, a restore from an older backup, a fixture — and refusing to boot on it
100
+ * would take a running site down over a condition the next deploy resolves.
101
+ *
102
+ * Only entries whose schema already agrees they are singletons are inspected; the rest belong to
103
+ * `findSingletonConsistencyIssues`, and reporting them twice would bury the actionable message.
104
+ * Returns the issues it found so callers (and tests) can act on them beyond the warning.
105
+ */
106
+ export declare function checkSingletonStoredIds(structure: any, schemas: ContentSchema[], reader: SingletonDocumentReader | null | undefined, onWarning?: (message: string) => void): Promise<SingletonStoredIdIssue[]>;
107
+ //# sourceMappingURL=singleton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"singleton.d.ts","sourceRoot":"","sources":["../../../src/core/schema/singleton.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEtD,mEAAmE;AACnE,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,+EAA+E;IAC/E,UAAU,EAAE,OAAO,CAAA;CACpB;AAED,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,sBAAsB,GAAG,gBAAgB,CAAA;CAClD;AAED,8FAA8F;AAC9F,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAA;IAClB,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAA;IAClB,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACtC,aAAa,CACX,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3B,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC,CAAA;CACtD;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAGnF;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,GAAG,GAAG,kBAAkB,EAAE,CA0B/E;AAED;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,GAAG,EACd,OAAO,EAAE,aAAa,EAAE,GACvB,yBAAyB,EAAE,CAiB7B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,GAAG,EACd,OAAO,EAAE,aAAa,EAAE,EACxB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GACpC,IAAI,CAyBN;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,uBAAuB,CAC3C,SAAS,EAAE,GAAG,EACd,OAAO,EAAE,aAAa,EAAE,EACxB,MAAM,EAAE,uBAAuB,GAAG,IAAI,GAAG,SAAS,EAClD,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GACpC,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAoDnC"}
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Singleton resolution — the one place that answers "does this collection hold
3
+ * exactly one document?".
4
+ *
5
+ * The schema is the source of truth. "Exactly one document" is a content-model
6
+ * invariant: it governs the create guard, the PUT upsert, and how the CLI restores
7
+ * a backup. A `type: 'singleton'` entry in a project's structure answers a different
8
+ * question — which document the navigation opens and auto-creates — and must never
9
+ * be used to decide the invariant, because a project can have no custom structure,
10
+ * a static one, or one that varies by user role.
11
+ *
12
+ * Declaring the structure entry without the schema flag used to be silent: every
13
+ * request still behaved correctly and the divergence only surfaced later, when a
14
+ * restore regenerated document ids and dropped documents. `assertSingletonConsistency`
15
+ * turns that into a boot failure instead.
16
+ */
17
+ /**
18
+ * Whether a schema declares itself a singleton.
19
+ *
20
+ * Both spellings are accepted: `singleton: true` and `type: 'singleton'`. Either alone means
21
+ * singleton, so a schema that sets `type: 'singleton'` alongside `singleton: false` is still
22
+ * one. Schemas are validated as `z.ZodSchema<any>`, so neither spelling is checked by the
23
+ * compiler and a near miss such as `isSingleton: true` is silently ignored — which is exactly
24
+ * why the consistency check below exists.
25
+ */
26
+ export function isSingletonSchema(schema) {
27
+ if (!schema)
28
+ return false;
29
+ return schema.singleton === true || schema.type === 'singleton';
30
+ }
31
+ /**
32
+ * Collect every `type: 'singleton'` entry in a resolved structure, walking nested items.
33
+ *
34
+ * `documentId` falls back to the collection name, matching how the Studio addresses a
35
+ * singleton view that does not name one explicitly.
36
+ */
37
+ export function collectStructureSingletons(structure) {
38
+ const found = [];
39
+ const seen = new Set();
40
+ const walk = (items) => {
41
+ for (const item of items) {
42
+ if (!item || typeof item !== 'object')
43
+ continue;
44
+ // Structures are user-supplied and may be self-referential.
45
+ if (seen.has(item))
46
+ continue;
47
+ seen.add(item);
48
+ if (item.type === 'singleton' && typeof item.schemaType === 'string') {
49
+ found.push({
50
+ collection: item.schemaType,
51
+ documentId: item.documentId || item.schemaType,
52
+ autoCreate: item.options?.autoCreate !== false,
53
+ });
54
+ }
55
+ if (Array.isArray(item.items))
56
+ walk(item.items);
57
+ }
58
+ };
59
+ walk(Array.isArray(structure?.items) ? structure.items : []);
60
+ return found;
61
+ }
62
+ /**
63
+ * Find structure singletons whose schema does not declare the invariant.
64
+ *
65
+ * Only this direction is a defect. A schema may be a singleton without appearing in the
66
+ * structure at all — it simply gets no navigation entry.
67
+ */
68
+ export function findSingletonConsistencyIssues(structure, schemas) {
69
+ const byName = new Map();
70
+ for (const schema of schemas) {
71
+ if (schema?.name)
72
+ byName.set(schema.name, schema);
73
+ }
74
+ const issues = [];
75
+ for (const entry of collectStructureSingletons(structure)) {
76
+ const { collection, documentId } = entry;
77
+ const schema = byName.get(collection);
78
+ if (!schema) {
79
+ issues.push({ collection, documentId, reason: 'schema-missing' });
80
+ }
81
+ else if (!isSingletonSchema(schema)) {
82
+ issues.push({ collection, documentId, reason: 'schema-not-singleton' });
83
+ }
84
+ }
85
+ return issues;
86
+ }
87
+ /**
88
+ * Throw if the structure and the schemas disagree about which collections are singletons.
89
+ *
90
+ * Called at startup so the mismatch is reported against the project's source, long before
91
+ * it can cost documents during a restore.
92
+ *
93
+ * Only a schema that contradicts the structure is fatal. A structure entry naming a schema
94
+ * that is not registered at all is reported through `onWarning` instead: it costs a broken
95
+ * navigation link rather than documents, and a project may legitimately leave a nav entry in
96
+ * place while registering its schema conditionally.
97
+ */
98
+ export function assertSingletonConsistency(structure, schemas, onWarning) {
99
+ const issues = findSingletonConsistencyIssues(structure, schemas);
100
+ if (issues.length === 0)
101
+ return;
102
+ for (const issue of issues.filter(i => i.reason === 'schema-missing')) {
103
+ onWarning?.(`Structure presents '${issue.collection}' as a singleton but no schema by that name is registered`);
104
+ }
105
+ const fatal = issues.filter(issue => issue.reason === 'schema-not-singleton');
106
+ if (fatal.length === 0)
107
+ return;
108
+ const lines = fatal.map(issue => ` - '${issue.collection}' is presented as a singleton but its schema does not set 'singleton: true'`);
109
+ throw new Error(`Structure and schemas disagree about singletons:\n${lines.join('\n')}\n\n` +
110
+ `The schema decides whether a collection holds exactly one document. Without the flag, ` +
111
+ `creating and restoring documents in these collections behaves as if they were ordinary ` +
112
+ `list collections: a restore regenerates their document ids, so the structure ends up ` +
113
+ `pointing at documents that no longer exist.`);
114
+ }
115
+ /**
116
+ * Warn when a singleton's stored document is filed under a different id than the structure names.
117
+ *
118
+ * The structure addresses a singleton by a fixed id, so a structure that says 'home' while storage
119
+ * holds 'homepage' silently 404s the singleton view — the document is there, nothing errors, and
120
+ * the only symptom is an editor screen that offers to create a document that already exists.
121
+ * Restores compound it, because they write back the id they find rather than the id the structure
122
+ * expects.
123
+ *
124
+ * This warns and never throws, unlike `assertSingletonConsistency` above. That check reads the
125
+ * project's own source, where a disagreement is always a defect the developer can fix on the spot.
126
+ * This one reads data, where the same divergence is routinely a legitimate intermediate state — a
127
+ * rename mid-migration, a restore from an older backup, a fixture — and refusing to boot on it
128
+ * would take a running site down over a condition the next deploy resolves.
129
+ *
130
+ * Only entries whose schema already agrees they are singletons are inspected; the rest belong to
131
+ * `findSingletonConsistencyIssues`, and reporting them twice would bury the actionable message.
132
+ * Returns the issues it found so callers (and tests) can act on them beyond the warning.
133
+ */
134
+ export async function checkSingletonStoredIds(structure, schemas, reader, onWarning) {
135
+ if (!reader || typeof reader.listDocuments !== 'function')
136
+ return [];
137
+ const byName = new Map();
138
+ for (const schema of schemas) {
139
+ if (schema?.name)
140
+ byName.set(schema.name, schema);
141
+ }
142
+ const issues = [];
143
+ for (const entry of collectStructureSingletons(structure)) {
144
+ if (!isSingletonSchema(byName.get(entry.collection)))
145
+ continue;
146
+ let documents;
147
+ try {
148
+ // One document is enough: the collection is declared to hold exactly one, and a boot check
149
+ // has no business paging through a collection that turned out to hold more.
150
+ documents = (await reader.listDocuments(entry.collection, { limit: 1 })) ?? [];
151
+ }
152
+ catch (error) {
153
+ // An adapter that is not up yet, a collection that does not exist, a role that cannot read
154
+ // it — all recoverable, and none of them worth failing a boot over.
155
+ onWarning?.(`Could not read '${entry.collection}' to check its singleton document id: ` +
156
+ `${error instanceof Error ? error.message : String(error)}`);
157
+ continue;
158
+ }
159
+ // Adapters disagree about which field carries the identity: filesystem-data returns `id`,
160
+ // postgres-data returns `_id`. Reading only one of them makes this check silently inert on
161
+ // the other backend — which would have meant it never ran on a Postgres-backed site.
162
+ const first = Array.isArray(documents) ? documents[0] : undefined;
163
+ const actualId = first?.id ?? first?._id;
164
+ // An empty collection has not diverged from anything; auto-create will file the first
165
+ // document under the id the structure names.
166
+ if (!actualId || actualId === entry.documentId)
167
+ continue;
168
+ issues.push({
169
+ collection: entry.collection,
170
+ expectedId: entry.documentId,
171
+ actualId,
172
+ });
173
+ onWarning?.(`Singleton '${entry.collection}' is stored under id '${actualId}' but the structure ` +
174
+ `addresses it as '${entry.documentId}'. The Studio will not find the existing document ` +
175
+ `and will offer to create a second one; rename the document or set the structure entry's ` +
176
+ `documentId to '${actualId}'.`);
177
+ }
178
+ return issues;
179
+ }
180
+ //# sourceMappingURL=singleton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"singleton.js","sourceRoot":"","sources":["../../../src/core/schema/singleton.ts"],"names":[],"mappings":"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"}