nextly 0.0.1 → 0.0.2-alpha.0

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 (268) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +122 -0
  3. package/dist/_dts-chunks/collections-handler.d-DjgO74Wt.d.ts +20540 -0
  4. package/dist/_dts-chunks/config.d-DNwsDnjs.d.ts +2589 -0
  5. package/dist/_dts-chunks/define-component.d-BUgTHmt3.d.ts +1149 -0
  6. package/dist/_dts-chunks/image-processor.d-OO1PmMrv.d.ts +335 -0
  7. package/dist/_dts-chunks/index.d-axCAzZ7m.d.ts +17842 -0
  8. package/dist/_dts-chunks/media.d-DjDOZo4B.d.ts +117 -0
  9. package/dist/_dts-chunks/on-error.d-CHIKWNxd.d.ts +38 -0
  10. package/dist/_dts-chunks/storage.d-BUhQ2we_.d.ts +404 -0
  11. package/dist/actions/index.d.ts +239 -0
  12. package/dist/actions/index.mjs +281 -0
  13. package/dist/api/auth-state.d.ts +5 -0
  14. package/dist/api/auth-state.mjs +131 -0
  15. package/dist/api/collections-schema-detail.d.ts +56 -0
  16. package/dist/api/collections-schema-detail.mjs +244 -0
  17. package/dist/api/collections-schema-export.d.ts +56 -0
  18. package/dist/api/collections-schema-export.mjs +129 -0
  19. package/dist/api/collections-schema.d.ts +59 -0
  20. package/dist/api/collections-schema.mjs +207 -0
  21. package/dist/api/components-detail.d.ts +50 -0
  22. package/dist/api/components-detail.mjs +132 -0
  23. package/dist/api/components.d.ts +69 -0
  24. package/dist/api/components.mjs +144 -0
  25. package/dist/api/email-providers-default.d.ts +40 -0
  26. package/dist/api/email-providers-default.mjs +75 -0
  27. package/dist/api/email-providers-detail.d.ts +81 -0
  28. package/dist/api/email-providers-detail.mjs +109 -0
  29. package/dist/api/email-providers-test.d.ts +43 -0
  30. package/dist/api/email-providers-test.mjs +114 -0
  31. package/dist/api/email-providers.d.ts +69 -0
  32. package/dist/api/email-providers.mjs +110 -0
  33. package/dist/api/email-send-template.d.ts +41 -0
  34. package/dist/api/email-send-template.mjs +58 -0
  35. package/dist/api/email-send.d.ts +42 -0
  36. package/dist/api/email-send.mjs +58 -0
  37. package/dist/api/email-templates-detail.d.ts +74 -0
  38. package/dist/api/email-templates-detail.mjs +112 -0
  39. package/dist/api/email-templates-layout.d.ts +55 -0
  40. package/dist/api/email-templates-layout.mjs +92 -0
  41. package/dist/api/email-templates-preview.d.ts +48 -0
  42. package/dist/api/email-templates-preview.mjs +93 -0
  43. package/dist/api/email-templates.d.ts +61 -0
  44. package/dist/api/email-templates.mjs +118 -0
  45. package/dist/api/health.d.ts +68 -0
  46. package/dist/api/health.mjs +67 -0
  47. package/dist/api/index.d.ts +54 -0
  48. package/dist/api/index.mjs +16 -0
  49. package/dist/api/media-bulk.d.ts +74 -0
  50. package/dist/api/media-bulk.mjs +196 -0
  51. package/dist/api/media-folders.d.ts +112 -0
  52. package/dist/api/media-folders.mjs +187 -0
  53. package/dist/api/media-handlers.d.ts +102 -0
  54. package/dist/api/media-handlers.mjs +437 -0
  55. package/dist/api/media.d.ts +117 -0
  56. package/dist/api/media.mjs +242 -0
  57. package/dist/api/singles-detail.d.ts +87 -0
  58. package/dist/api/singles-detail.mjs +170 -0
  59. package/dist/api/singles-schema-detail.d.ts +54 -0
  60. package/dist/api/singles-schema-detail.mjs +182 -0
  61. package/dist/api/singles.d.ts +34 -0
  62. package/dist/api/singles.mjs +94 -0
  63. package/dist/api/storage-upload-url.d.ts +48 -0
  64. package/dist/api/storage-upload-url.mjs +202 -0
  65. package/dist/api/uploads.d.ts +109 -0
  66. package/dist/api/uploads.mjs +359 -0
  67. package/dist/auth/index.d.ts +425 -0
  68. package/dist/auth/index.mjs +199 -0
  69. package/dist/boot-apply-PQSYLDIN.mjs +7 -0
  70. package/dist/chunk-2OALJTK6.mjs +489 -0
  71. package/dist/chunk-2Q2SX2CS.mjs +365 -0
  72. package/dist/chunk-2TFX4ND3.mjs +13 -0
  73. package/dist/chunk-2TWPDSYD.mjs +87 -0
  74. package/dist/chunk-2W3DVD7S.mjs +647 -0
  75. package/dist/chunk-2ZFKXPQM.mjs +88 -0
  76. package/dist/chunk-3FA7FKAV.mjs +832 -0
  77. package/dist/chunk-3NZ2KMBL.mjs +58 -0
  78. package/dist/chunk-4MJLT6PZ.mjs +0 -0
  79. package/dist/chunk-56WO4WX7.mjs +0 -0
  80. package/dist/chunk-5APFUGAD.mjs +89 -0
  81. package/dist/chunk-5HMZ644B.mjs +108 -0
  82. package/dist/chunk-67GXH6PR.mjs +32 -0
  83. package/dist/chunk-6JNEPWRW.mjs +14368 -0
  84. package/dist/chunk-6NFHQIJD.mjs +45 -0
  85. package/dist/chunk-7P6ASYW6.mjs +9 -0
  86. package/dist/chunk-A3WPLSDT.mjs +1364 -0
  87. package/dist/chunk-AGJ6F2T3.mjs +144 -0
  88. package/dist/chunk-AK6Z23OX.mjs +1464 -0
  89. package/dist/chunk-APKKRD2G.mjs +102 -0
  90. package/dist/chunk-B2GV2BWH.mjs +73 -0
  91. package/dist/chunk-D5HQBNUB.mjs +74 -0
  92. package/dist/chunk-DNNG377Z.mjs +204 -0
  93. package/dist/chunk-DP3G27G5.mjs +135 -0
  94. package/dist/chunk-DV6WVX2Q.mjs +0 -0
  95. package/dist/chunk-DXGGXIUZ.mjs +57 -0
  96. package/dist/chunk-EGXBZCGC.mjs +943 -0
  97. package/dist/chunk-ERCNLX3V.mjs +176 -0
  98. package/dist/chunk-FQULBZ53.mjs +850 -0
  99. package/dist/chunk-G2AA4QLC.mjs +262 -0
  100. package/dist/chunk-GDBJ5JCU.mjs +488 -0
  101. package/dist/chunk-GJNSJU4S.mjs +19 -0
  102. package/dist/chunk-GZ6DCQKC.mjs +69 -0
  103. package/dist/chunk-H26B4FYG.mjs +167 -0
  104. package/dist/chunk-I4JMR3UR.mjs +21 -0
  105. package/dist/chunk-INV7QKLG.mjs +508 -0
  106. package/dist/chunk-IUDOC7N7.mjs +46 -0
  107. package/dist/chunk-IZWPRDC3.mjs +206 -0
  108. package/dist/chunk-KIMNCZGV.mjs +15 -0
  109. package/dist/chunk-L6HW2DA7.mjs +15 -0
  110. package/dist/chunk-LAZXX4HR.mjs +100 -0
  111. package/dist/chunk-LDKCUMHK.mjs +95 -0
  112. package/dist/chunk-LRXMECUA.mjs +0 -0
  113. package/dist/chunk-M52VMPGA.mjs +119 -0
  114. package/dist/chunk-MGUWEEI6.mjs +160 -0
  115. package/dist/chunk-NRUWQ5Z7.mjs +419 -0
  116. package/dist/chunk-NSEFNNU4.mjs +25360 -0
  117. package/dist/chunk-NTHVDFGO.mjs +138 -0
  118. package/dist/chunk-O3QHXMOX.mjs +3166 -0
  119. package/dist/chunk-P7NH2OSC.mjs +2605 -0
  120. package/dist/chunk-PKMABBB5.mjs +184 -0
  121. package/dist/chunk-PWS6XGJK.mjs +76 -0
  122. package/dist/chunk-R6JJQHFC.mjs +20 -0
  123. package/dist/chunk-RJLLGGPG.mjs +0 -0
  124. package/dist/chunk-SBACDPNX.mjs +689 -0
  125. package/dist/chunk-TO5AFLVQ.mjs +124 -0
  126. package/dist/chunk-TS7GHTG2.mjs +5436 -0
  127. package/dist/chunk-UJ2IMJ4W.mjs +133 -0
  128. package/dist/chunk-UOP63Q54.mjs +102 -0
  129. package/dist/chunk-UUOFWCM6.mjs +78 -0
  130. package/dist/chunk-V4EQTOA4.mjs +893 -0
  131. package/dist/chunk-VJ66NCL4.mjs +193 -0
  132. package/dist/chunk-VQJQHVEV.mjs +29 -0
  133. package/dist/chunk-VTJADRO3.mjs +141 -0
  134. package/dist/chunk-VWF3JO32.mjs +0 -0
  135. package/dist/chunk-W4MGXIRR.mjs +27 -0
  136. package/dist/chunk-W5KKPZT5.mjs +1204 -0
  137. package/dist/chunk-WD34YQ6T.mjs +381 -0
  138. package/dist/chunk-WZBYMYVW.mjs +14 -0
  139. package/dist/chunk-X23WKS3Z.mjs +50 -0
  140. package/dist/chunk-X7TXCYYN.mjs +6496 -0
  141. package/dist/chunk-XGI4EMS3.mjs +140 -0
  142. package/dist/chunk-XZKLBMN6.mjs +1153 -0
  143. package/dist/chunk-YB7INWPY.mjs +0 -0
  144. package/dist/chunk-YV4Y7SDL.mjs +83 -0
  145. package/dist/chunk-YZNBLFIW.mjs +1688 -0
  146. package/dist/chunk-YZZCTONM.mjs +263 -0
  147. package/dist/chunk-ZE6A3FYH.mjs +289 -0
  148. package/dist/cli/nextly.mjs +68 -0
  149. package/dist/cli/utils/index.d.ts +449 -0
  150. package/dist/cli/utils/index.mjs +49 -0
  151. package/dist/component-schema-service-5577KVW6.mjs +11 -0
  152. package/dist/config-loader-23YEMC3Z.mjs +23 -0
  153. package/dist/config.d.ts +44 -0
  154. package/dist/config.mjs +109 -0
  155. package/dist/container-ORGFGYSZ.mjs +9 -0
  156. package/dist/database/index.d.ts +12 -0
  157. package/dist/database/index.mjs +40 -0
  158. package/dist/database/seeders/index.d.ts +93 -0
  159. package/dist/database/seeders/index.mjs +47 -0
  160. package/dist/db-sync-demote-LJGKLB3S.mjs +117 -0
  161. package/dist/db-sync-promote-B26VSYQF.mjs +113 -0
  162. package/dist/dev-reload-broadcaster-B73IQ53V.mjs +25 -0
  163. package/dist/dist-M2NOU37V.mjs +19 -0
  164. package/dist/drizzle-kit-lazy-D2M2PXR2.mjs +13 -0
  165. package/dist/dynamic-collection-schema-service-IEXTPIZ7.mjs +8 -0
  166. package/dist/errors/index.d.ts +159 -0
  167. package/dist/errors/index.mjs +10 -0
  168. package/dist/factory-IWMBKUJM.mjs +15 -0
  169. package/dist/first-run-QIVKWJIF.mjs +63 -0
  170. package/dist/fresh-push-NR67DC3R.mjs +8 -0
  171. package/dist/index.d.ts +4175 -0
  172. package/dist/index.mjs +1336 -0
  173. package/dist/local-plugin-PTET4NAT.mjs +7 -0
  174. package/dist/logger-NU46DXNY.mjs +15 -0
  175. package/dist/logger-YE4TC7ZN.mjs +9 -0
  176. package/dist/migration-journal-EP532Y4L.mjs +139 -0
  177. package/dist/migrations/mysql/0000_eager_sentry.sql +174 -0
  178. package/dist/migrations/mysql/0001_soft_giant_girl.sql +27 -0
  179. package/dist/migrations/mysql/0002_media_table.sql +24 -0
  180. package/dist/migrations/mysql/0003_dynamic_singles.sql +37 -0
  181. package/dist/migrations/mysql/0004_dynamic_components.sql +35 -0
  182. package/dist/migrations/mysql/0005_user_management_tables.sql +92 -0
  183. package/dist/migrations/mysql/0006_api_keys.sql +36 -0
  184. package/dist/migrations/mysql/0007_general_settings.sql +20 -0
  185. package/dist/migrations/mysql/0008_site_settings_logo_url.sql +9 -0
  186. package/dist/migrations/mysql/0009_activity_log.sql +30 -0
  187. package/dist/migrations/mysql/0010_site_settings_sidebar.sql +13 -0
  188. package/dist/migrations/mysql/0011_missing_tables_and_columns.sql +54 -0
  189. package/dist/migrations/mysql/0012_image_sizes_and_focal_point.sql +30 -0
  190. package/dist/migrations/mysql/0012_media_folders.sql +43 -0
  191. package/dist/migrations/mysql/0013_user_brute_force_protection.sql +31 -0
  192. package/dist/migrations/mysql/0014_email_template_attachments.sql +12 -0
  193. package/dist/migrations/mysql/0015_media_uploaded_by_nullable.sql +15 -0
  194. package/dist/migrations/mysql/20260429_000000_000_initial_journal.sql +22 -0
  195. package/dist/migrations/mysql/20260501_000000_journal_batch.sql +17 -0
  196. package/dist/migrations/mysql/20260501_000001_audit_log.sql +24 -0
  197. package/dist/migrations/mysql/20260504_000000_nextly_meta.sql +21 -0
  198. package/dist/migrations/mysql/meta/0000_snapshot.json +1005 -0
  199. package/dist/migrations/mysql/meta/0001_snapshot.json +1099 -0
  200. package/dist/migrations/mysql/meta/_journal.json +41 -0
  201. package/dist/migrations/postgresql/0000_misty_king_bedlam.sql +169 -0
  202. package/dist/migrations/postgresql/0001_perpetual_captain_marvel.sql +8 -0
  203. package/dist/migrations/postgresql/0002_sad_spectrum.sql +16 -0
  204. package/dist/migrations/postgresql/0003_hesitant_ultron.sql +17 -0
  205. package/dist/migrations/postgresql/0004_media_table.sql +24 -0
  206. package/dist/migrations/postgresql/0005_media_folders.sql +36 -0
  207. package/dist/migrations/postgresql/0006_dynamic_collections_update.sql +50 -0
  208. package/dist/migrations/postgresql/0007_dynamic_singles.sql +38 -0
  209. package/dist/migrations/postgresql/0008_dynamic_components.sql +37 -0
  210. package/dist/migrations/postgresql/0009_user_management_tables.sql +95 -0
  211. package/dist/migrations/postgresql/0010_api_keys.sql +34 -0
  212. package/dist/migrations/postgresql/0011_general_settings.sql +20 -0
  213. package/dist/migrations/postgresql/0012_site_settings_logo_url.sql +9 -0
  214. package/dist/migrations/postgresql/0013_activity_log.sql +29 -0
  215. package/dist/migrations/postgresql/0014_image_sizes_and_focal_point.sql +33 -0
  216. package/dist/migrations/postgresql/0014_site_settings_sidebar.sql +13 -0
  217. package/dist/migrations/postgresql/0015_user_brute_force_protection.sql +29 -0
  218. package/dist/migrations/postgresql/0016_email_template_attachments.sql +12 -0
  219. package/dist/migrations/postgresql/0017_media_uploaded_by_nullable.sql +15 -0
  220. package/dist/migrations/postgresql/20260429_000000_000_initial_journal.sql +24 -0
  221. package/dist/migrations/postgresql/20260501_000000_journal_batch.sql +17 -0
  222. package/dist/migrations/postgresql/20260501_000001_audit_log.sql +24 -0
  223. package/dist/migrations/postgresql/20260504_000000_nextly_meta.sql +22 -0
  224. package/dist/migrations/postgresql/meta/0000_snapshot.json +1286 -0
  225. package/dist/migrations/postgresql/meta/0001_snapshot.json +1407 -0
  226. package/dist/migrations/postgresql/meta/0002_snapshot.json +1552 -0
  227. package/dist/migrations/postgresql/meta/0003_snapshot.json +1695 -0
  228. package/dist/migrations/postgresql/meta/0010_snapshot.json +2345 -0
  229. package/dist/migrations/postgresql/meta/_journal.json +90 -0
  230. package/dist/migrations/sqlite/0000_api_keys.sql +34 -0
  231. package/dist/migrations/sqlite/0001_general_settings.sql +20 -0
  232. package/dist/migrations/sqlite/0002_site_settings_logo_url.sql +9 -0
  233. package/dist/migrations/sqlite/0003_activity_log.sql +29 -0
  234. package/dist/migrations/sqlite/0004_image_sizes_and_focal_point.sql +29 -0
  235. package/dist/migrations/sqlite/0004_site_settings_sidebar.sql +11 -0
  236. package/dist/migrations/sqlite/0005_user_brute_force_protection.sql +29 -0
  237. package/dist/migrations/sqlite/0006_email_template_attachments.sql +12 -0
  238. package/dist/migrations/sqlite/0007_media_uploaded_by_nullable.sql +111 -0
  239. package/dist/migrations/sqlite/20260429_000000_000_initial_journal.sql +24 -0
  240. package/dist/migrations/sqlite/20260501_000000_journal_batch.sql +19 -0
  241. package/dist/migrations/sqlite/20260501_000001_audit_log.sql +24 -0
  242. package/dist/migrations/sqlite/20260504_000000_nextly_meta.sql +21 -0
  243. package/dist/migrations/sqlite/20260505_000000_user_management_tables.sql +77 -0
  244. package/dist/next.d.ts +57 -0
  245. package/dist/next.mjs +55 -0
  246. package/dist/observability/index.d.ts +87 -0
  247. package/dist/observability/index.mjs +57 -0
  248. package/dist/permissions-3DZZQZMI.mjs +39 -0
  249. package/dist/pipeline-YOML7SWF.mjs +29 -0
  250. package/dist/preview-ZZTR3QGS.mjs +9 -0
  251. package/dist/program-PW6UB2ZC.mjs +5934 -0
  252. package/dist/reconcile-single-tables-7ENVXJGB.mjs +7 -0
  253. package/dist/register-SF6E6FVU.mjs +49 -0
  254. package/dist/reload-config-HWQ4G5MM.mjs +23 -0
  255. package/dist/resolve-single-table-name-JSOMUB3R.mjs +7 -0
  256. package/dist/routeHandler-UNMMJIBM.mjs +77 -0
  257. package/dist/runtime-schema-generator-NRA6A6Z6.mjs +8 -0
  258. package/dist/runtime.d.ts +120 -0
  259. package/dist/runtime.mjs +73 -0
  260. package/dist/schema-hash-FMMG6VPJ.mjs +13 -0
  261. package/dist/schema-registry-EQ36FZDP.mjs +7 -0
  262. package/dist/scripts/load-env.mjs +42 -0
  263. package/dist/storage/index.d.ts +566 -0
  264. package/dist/storage/index.mjs +45 -0
  265. package/dist/super-admin-G5ZK5F4T.mjs +39 -0
  266. package/dist/system-table-service-WGSRVEGT.mjs +17 -0
  267. package/dist/users-7KELGRYJ.mjs +38 -0
  268. package/package.json +308 -9
@@ -0,0 +1,4175 @@
1
+ import { DrizzleAdapter } from '@nextlyhq/adapter-drizzle';
2
+ export { DrizzleAdapter } from '@nextlyhq/adapter-drizzle';
3
+ import { bc as BaseService, bd as Logger, k as CodeFieldValue, o as CollectionConfig, bt as UserConfig, bC as UserExtSchemaService, bF as EmailService, bW as ListUsersResponse, bX as GetUserResponse, bY as MinimalUser, bZ as UserMutationResponse, b_ as GetAccountsResponse, b$ as UnlinkAccountResult, bJ as AuthService, bb as CollectionsHandler, c0 as RoleService, c1 as PermissionService, c2 as RolePermissionService, c3 as MediaService, c4 as MediaFolderService, c5 as MigrationRecordStatus, bL as HookType, $ as HookHandler, bs as HookRegistry, c6 as CollectionSlug, c7 as FindArgs, c8 as ListResult, c9 as DataFromCollectionSlug, ca as FindByIDArgs, cb as CreateArgs, cc as MutationResult, cd as UpdateArgs, ce as DeleteArgs, cf as DeleteResult, cg as CountArgs, ch as CountResult, ci as BulkDeleteArgs, cj as BulkOperationResult, ck as DuplicateArgs, cl as SingleSlug, cm as FindSingleArgs, cn as DataFromSingleSlug, co as UpdateSingleArgs, cp as FindSinglesArgs, cq as SingleListResult, cr as LoginArgs, cs as UserContext, ct as AuthResult, cu as RegisterArgs, cv as ChangePasswordArgs, cw as ForgotPasswordArgs, cx as ResetPasswordArgs, cy as VerifyEmailArgs, cz as FindUsersArgs, cA as User, cB as FindUserByIDArgs, cC as CreateUserArgs, cD as UpdateUserArgs, cE as DeleteUserArgs, cF as UploadMediaArgs, cG as MediaFile, cH as FindMediaArgs, cI as FindMediaByIDArgs, cJ as UpdateMediaArgs, cK as DeleteMediaArgs, cL as BulkDeleteMediaArgs, cM as ListFoldersArgs, cN as MediaFolder, cO as CreateFolderArgs, cP as FindFormsArgs, cQ as FindFormBySlugArgs, cR as SubmitFormArgs, cS as SubmitFormResult, cT as FormSubmissionsArgs, cU as FindEmailProvidersArgs, cV as EmailProviderRecord, cW as FindEmailProviderByIDArgs, cX as CreateEmailProviderArgs, cY as UpdateEmailProviderArgs, cZ as DeleteEmailProviderArgs, c_ as SetDefaultProviderArgs, c$ as TestEmailProviderArgs, d0 as FindEmailTemplatesArgs, d1 as EmailTemplateRecord, d2 as FindEmailTemplateByIDArgs, d3 as FindEmailTemplateBySlugArgs, d4 as CreateEmailTemplateArgs, d5 as UpdateEmailTemplateArgs, d6 as DeleteEmailTemplateArgs, d7 as PreviewEmailTemplateArgs, d8 as GetEmailLayoutArgs, d9 as UpdateEmailLayoutArgs, da as FindUserFieldsArgs, db as UserFieldDefinitionRecord, dc as FindUserFieldByIDArgs, dd as CreateUserFieldArgs, de as UpdateUserFieldArgs, df as DeleteUserFieldArgs, dg as ReorderUserFieldsArgs, dh as SendEmailArgs, di as SendEmailResult, dj as SendTemplateEmailArgs, dk as FindRolesArgs, dl as Role, dm as FindRoleByIDArgs, dn as CreateRoleArgs, dp as UpdateRoleArgs, dq as DeleteRoleArgs, dr as GetRolePermissionsArgs, ds as Permission, dt as SetRolePermissionsArgs, du as FindPermissionsArgs, dv as FindPermissionByIDArgs, dw as CreatePermissionArgs, dx as DeletePermissionArgs, dy as CheckAccessArgs, P as FieldConfig, dz as IndexConfig, aQ as SingleConfig, t as ComponentConfig } from './_dts-chunks/collections-handler.d-DjgO74Wt.d.ts';
4
+ export { A as ALL_FIELD_TYPES, dA as AccessControlContext, dB as AccessControlFunction, a as AccessFunction, dC as ApiKeyMeta, dD as ApiKeyResult, dE as ApiKeyTokenType, B as BaseFieldConfig, dF as BuildPaginatedResponseOptions, dG as BulkOperationResult, dH as COMPONENT_MIGRATION_STATUSES, dI as COMPONENT_SOURCE_TYPES, C as CellComponentProps, dJ as CheckApiKeyArgs, dK as CheckApiKeyResult, b as CheckboxFieldAdminOptions, c as CheckboxFieldConfig, d as CheckboxFieldValue, e as ChipsFieldAdminOptions, f as ChipsFieldConfig, g as ChipsFieldValue, h as CodeEditorOptions, i as CodeFieldAdminOptions, j as CodeFieldConfig, l as CodeLanguage, m as CollectionAccessControl, n as CollectionAdminOptions, dL as CollectionArtifacts, dM as CollectionFileManager, p as CollectionHooks, q as CollectionLabels, r as CollectionPagination, dN as CollectionSchemaDefinition, s as ComponentAdminOptions, u as ComponentFieldConfig, v as ComponentLabel, bN as ComponentMigrationStatus, bM as ComponentSource, dO as CreateApiKeyArgs, dP as CreateFolderInput, dQ as CreateUserServiceInput, w as CustomEndpoint, D as DATA_FIELD_TYPES, x as DataFieldConfig, y as DataFieldType, z as DateFieldAdminOptions, E as DateFieldConfig, F as DateFieldValue, G as DatePickerAppearance, H as DatePickerOptions, dR as DirectAPIConfig, dS as DirectAPIRequestContext, dT as DrizzleDB, dU as DynamicCollection, dV as DynamicCollectionService, dW as DynamicComponentInsert, dX as DynamicComponentRecord, dY as DynamicFieldType, bu as EmailConfig, I as EmailFieldAdminOptions, J as EmailFieldConfig, K as EmailFieldValue, dZ as EmailProviderAdapter, d_ as EmailTemplateFn, d$ as ExpiresIn, L as FieldAccess, M as FieldAdminOptions, N as FieldComponentProps, e0 as FieldCondition, bm as FieldDefinition, Q as FieldHooks, R as FieldType, S as FieldValidation, T as FilterComponentProps, U as FilterOptionsArgs, V as FilterOptionsFunction, e1 as FindApiKeyByIDArgs, e2 as FolderContents, e3 as FormsConfig, e4 as GeneratedTypes, W as GroupFieldAdminOptions, X as GroupFieldConfig, Y as GroupFieldConfig_FieldConfig, Z as GroupFieldValue, _ as HookContext, a0 as HttpMethod, a1 as JSONEditorOptions, a2 as JSONFieldAdminOptions, a3 as JSONFieldConfig, a4 as JSONFieldValue, a5 as JSONSchemaDefinition, a6 as JSONSchemaProperty, a7 as JSONSchemaType, a8 as JoinFieldAdminOptions, a9 as JoinFieldConfig, aa as JoinFieldWhere, e5 as ListApiKeysArgs, e6 as ListMediaOptions, e7 as ListUsersQueryOptions, e8 as LoginResult, bw as MediaService, e9 as MediaType, ea as MigrationRecord, eb as MigrationRecordInsert, ec as MinimalUser, ed as NewDynamicCollection, ab as NumberFieldAdminOptions, ac as NumberFieldConfig, ad as NumberFieldValue, ae as NumberFilterOperator, ee as PAGINATION_DEFAULTS, ef as PaginatedResponse, bq as PaginatedResult, eg as PaginationMeta, eh as PaginationOptions, af as PasswordFieldAdminOptions, ag as PasswordFieldConfig, ah as PasswordFieldValue, ei as PasswordHasher, ej as PopulateOptions, ek as QueryOperator, br as QueryOptions, ai as RadioFieldAdminOptions, aj as RadioFieldConfig, ak as RadioFieldValue, al as RadioLayout, am as RelationshipAppearance, an as RelationshipFieldAdminOptions, ao as RelationshipFieldConfig, ap as RelationshipFieldValue, aq as RelationshipFilterOptions, ar as RelationshipFilterOptionsArgs, as as RelationshipFilterOptionsFunction, at as RelationshipFilterQuery, au as RelationshipPolymorphicValue, av as RelationshipSingleValue, aw as RelationshipSortOptions, ax as RepeaterFieldAdminOptions, ay as RepeaterFieldConfig, az as RepeaterFieldLabels, aA as RepeaterFieldValue, aB as RepeaterRowLabelProps, aC as RepeaterRowValue, bp as RequestContext, el as ResendConfig, em as RevokeApiKeyArgs, aE as RichTextFeature, aF as RichTextFieldAdminOptions, aG as RichTextFieldConfig, aH as RichTextFieldValue, aI as RichTextNode, aJ as RichTextValue, en as SYSTEM_CONTEXT, aK as SelectFieldAdminOptions, aL as SelectFieldConfig, aM as SelectFieldValue, aN as SelectOption, eo as SendLayerConfig, ep as ServiceDeps, aO as SingleAccessControl, aP as SingleAdminOptions, aR as SingleHooks, aS as SingleLabel, eq as SmtpConfig, er as SortOptions, aT as StringFilterOperator, aU as TextFieldAdminOptions, aV as TextFieldConfig, aW as TextFieldValue, aX as TextareaFieldAdminOptions, aY as TextareaFieldConfig, aZ as TextareaFieldValue, es as UpdateApiKeyArgs, et as UpdateFolderInput, eu as UpdateMediaInput, ev as UpdateUserServiceInput, a_ as UploadFieldAdminOptions, a$ as UploadFieldConfig, b0 as UploadFieldValue, ew as UploadFileData, b1 as UploadFilterOptions, b2 as UploadFilterOptionsArgs, b3 as UploadFilterOptionsFunction, b4 as UploadFilterQuery, ex as UploadMediaInput, b5 as UploadPolymorphicValue, b6 as UploadSingleValue, ey as UserAdminOptions, ez as UserFieldConfig, bR as UserFieldType, bv as UserService, b7 as VIRTUAL_FIELD_TYPES, b8 as VirtualFieldConfig, b9 as VirtualFieldType, eA as WhereFilter, eB as buildPaginatedResponse, eC as calculateOffset, eD as clampLimit, eE as consoleLogger, ba as defineCollection, eF as dynamicCollections, eG as getHookRegistry, eH as nextly, eI as resetHookRegistry } from './_dts-chunks/collections-handler.d-DjgO74Wt.d.ts';
5
+ import { NextlyError } from './errors/index.d.ts';
6
+ import { z } from 'zod';
7
+ export { A as AdapterConfig, a as AdapterType, D as DbError, b as DbErrorKind, c as DynamicComponentInsertMysql, d as DynamicComponentInsertPg, e as DynamicComponentInsertSqlite, f as DynamicComponentMysql, g as DynamicComponentPg, h as DynamicComponentSqlite, H as HealthCheckResult, i as checkAdapterHealth, j as createAdapter, k as createAdapterFromEnv, l as dynamicComponentsMysql, m as dynamicComponentsPg, n as dynamicComponentsSqlite, o as env, p as getDialectTables, q as healthCheck, r as isDbError, s as schema, t as toDbError, v as validateDatabaseEnv, w as withDbErrors } from './_dts-chunks/index.d-axCAzZ7m.d.ts';
8
+ import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
9
+ import * as drizzle_orm_mysql_core from 'drizzle-orm/mysql-core';
10
+ import * as drizzle_orm_sqlite_core from 'drizzle-orm/sqlite-core';
11
+ import { d as NextlyServiceConfig, S as SanitizedNextlyConfig, e as ServiceMap } from './_dts-chunks/config.d-DNwsDnjs.d.ts';
12
+ export { A as AdminBrandingColors, f as AdminBrandingConfig, g as AdminConfig, h as AdminPlacement, i as AuthRateLimitConfigInput, j as AuthRateLimitConfigSchema, C as Collection, k as CollectionDocument, l as CollectionService, m as CorsConfig, n as CorsConfigInput, o as CorsConfigSchema, p as CreateCollectionInput, D as DatabaseConfig, I as InMemoryRateLimitStore, L as ListCollectionsOptions, N as NextlyUserConfig, P as PluginAdminAppearance, q as PluginAdminConfig, r as PluginContext, t as PluginDefinition, u as PluginHookRegistry, v as PluginOverride, w as RateLimitConfig, R as RateLimitRecord, x as RateLimitResult, a as RateLimitStore, b as RateLimitingConfig, y as SanitizationConfigInput, z as SanitizationConfigSchema, c as SanitizedRateLimitingConfig, B as SecurityConfig, E as SecurityConfigInput, F as SecurityConfigSchema, G as SecurityHeadersConfig, H as SecurityHeadersConfigInput, J as SecurityHeadersConfigSchema, K as SecurityLimitsConfigInput, M as SecurityLimitsConfigSchema, T as TypeScriptConfig, U as UpdateCollectionInput, O as UploadSecurityConfigInput, Q as UploadSecurityConfigSchema, V as clearServices, W as createPluginContext, X as createRateLimitHeaders, Y as createRateLimiter, Z as definePlugin, _ as getService, $ as isServicesRegistered, a0 as registerServices, a1 as shutdownServices } from './_dts-chunks/config.d-DNwsDnjs.d.ts';
13
+ export { DatabaseCapabilities, SelectOptions, TransactionContext, WhereClause } from '@nextlyhq/adapter-drizzle/types';
14
+ export { I as StorageProvider } from './_dts-chunks/image-processor.d-OO1PmMrv.d.ts';
15
+ export { a as array, c as checkbox, b as chips, d as code, e as component, f as date, g as defineComponent, h as defineConfig, i as defineSingle, j as email, k as group, l as hasNestedFields, m as isCheckboxField, n as isChipsField, o as isCodeField, p as isComponentField, q as isDataField, r as isDateField, s as isEmailField, t as isGroupField, u as isJSONField, v as isNumberField, w as isPasswordField, x as isRadioField, y as isRelationalField, z as isRelationshipField, A as isRepeaterField, B as isRichTextField, C as isSelectField, D as isTextField, E as isTextareaField, F as isUploadField, G as json, H as number, I as option, J as password, K as radio, L as relationship, M as repeater, N as richText, O as select, P as text, Q as textarea, R as upload } from './_dts-chunks/define-component.d-BUgTHmt3.d.ts';
16
+ import 'react';
17
+ import './_dts-chunks/media.d-DjDOZo4B.d.ts';
18
+ import 'drizzle-orm';
19
+ import './_dts-chunks/storage.d-BUhQ2we_.d.ts';
20
+
21
+ /**
22
+ * PermissionCheckerService handles authorization checking logic.
23
+ *
24
+ * Responsibilities:
25
+ * - Get all permissions for a role (direct + inherited)
26
+ * - Check if a user has specific permissions (future)
27
+ * - Batch permission checking (future)
28
+ *
29
+ * This service depends on RoleInheritanceService for traversing role hierarchies.
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * const service = new PermissionCheckerService(adapter, logger);
34
+ * const permissions = await service.getAllPermissionsForRole(roleId);
35
+ * ```
36
+ */
37
+ declare class PermissionCheckerService extends BaseService {
38
+ private roleInheritanceService;
39
+ constructor(adapter: DrizzleAdapter, logger: Logger);
40
+ /**
41
+ * Get all permissions for a given role (direct + inherited).
42
+ *
43
+ * @param roleId - Role ID to get permissions for
44
+ * @returns Array of permission IDs (deduplicated)
45
+ */
46
+ getAllPermissionsForRole(roleId: string): Promise<string[]>;
47
+ }
48
+
49
+ /**
50
+ * RoleInheritanceService handles role hierarchy management.
51
+ *
52
+ * Responsibilities:
53
+ * - Add parent-child role relationships
54
+ * - Remove role inheritance relationships
55
+ * - List ancestor roles (parents, grandparents, etc.)
56
+ * - List descendant roles (children, grandchildren, etc.)
57
+ * - Prevent circular inheritance (cycle detection)
58
+ *
59
+ * Role hierarchy enables permission inheritance:
60
+ * - Child roles inherit permissions from parent roles
61
+ * - Multi-level inheritance is supported (child → parent → grandparent)
62
+ * - Cycles are forbidden to maintain consistency
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * const service = new RoleInheritanceService(adapter, logger);
67
+ * await service.addRoleInheritance(childRoleId, parentRoleId);
68
+ * const ancestors = await service.listAncestorRoles(roleId);
69
+ * ```
70
+ */
71
+ declare class RoleInheritanceService extends BaseService {
72
+ constructor(adapter: DrizzleAdapter, logger: Logger);
73
+ /**
74
+ * Add a parent-child role inheritance relationship.
75
+ *
76
+ * The child role will inherit all permissions from the parent role.
77
+ * Multi-level inheritance is supported.
78
+ *
79
+ * @param childRoleId - Child role ID (inherits from parent)
80
+ * @param parentRoleId - Parent role ID (provides permissions)
81
+ * @throws Error if self-inheritance or cycle would be created
82
+ */
83
+ addRoleInheritance(childRoleId: string, parentRoleId: string): Promise<void>;
84
+ /**
85
+ * Remove a parent-child role inheritance relationship.
86
+ *
87
+ * @param childRoleId - Child role ID
88
+ * @param parentRoleId - Parent role ID
89
+ */
90
+ removeRoleInheritance(childRoleId: string, parentRoleId: string): Promise<void>;
91
+ /**
92
+ * List all ancestor roles (parents, grandparents, etc.) for a given role.
93
+ *
94
+ * Uses breadth-first traversal to find all roles in the hierarchy above this role.
95
+ * Note: The starting roleId is NOT included in the results - only its ancestors.
96
+ *
97
+ * Safety limit: Stops after visiting MAX_ROLE_HIERARCHY_DEPTH roles to prevent infinite loops.
98
+ *
99
+ * @param roleId - Role ID to find ancestors for
100
+ * @returns Array of ancestor role IDs (excluding the starting roleId)
101
+ */
102
+ listAncestorRoles(roleId: string): Promise<string[]>;
103
+ /**
104
+ * List all descendant roles (children, grandchildren, etc.) for a given role.
105
+ *
106
+ * Uses breadth-first traversal to find all roles in the hierarchy below this role.
107
+ * Note: The starting roleId is NOT included in the results - only its descendants.
108
+ *
109
+ * Safety limit: Stops after visiting MAX_ROLE_HIERARCHY_DEPTH roles to prevent infinite loops.
110
+ *
111
+ * @param roleId - Role ID to find descendants for
112
+ * @returns Array of descendant role IDs (excluding the starting roleId)
113
+ */
114
+ listDescendantRoles(roleId: string): Promise<string[]>;
115
+ private willCreateCycle;
116
+ }
117
+
118
+ declare class UserRoleService extends BaseService {
119
+ constructor(adapter: DrizzleAdapter, logger: Logger);
120
+ /**
121
+ * Assign a role to a user.
122
+ *
123
+ * @param userId - User ID to assign role to
124
+ * @param roleId - Role ID to assign
125
+ * @param opts - Optional expiration date
126
+ * @returns Success/failure status
127
+ */
128
+ assignRoleToUser(userId: string, roleId: string, opts?: {
129
+ expiresAt?: Date | string;
130
+ }): Promise<{
131
+ success: boolean;
132
+ statusCode: number;
133
+ message: string;
134
+ }>;
135
+ /**
136
+ * Remove a role assignment from a user.
137
+ *
138
+ * @param userId - User ID to remove role from
139
+ * @param roleId - Role ID to remove
140
+ * @returns Success/failure status
141
+ */
142
+ unassignRoleFromUser(userId: string, roleId: string): Promise<{
143
+ success: boolean;
144
+ statusCode: number;
145
+ message: string;
146
+ }>;
147
+ /**
148
+ * List all role IDs assigned to a user.
149
+ *
150
+ * @param userId - User ID to list roles for
151
+ * @returns Array of role IDs
152
+ */
153
+ listUserRoles(userId: string): Promise<string[]>;
154
+ /**
155
+ * List all role names assigned to a user.
156
+ *
157
+ * @param userId - User ID to list role names for
158
+ * @returns Array of role names
159
+ */
160
+ listUserRoleNames(userId: string): Promise<string[]>;
161
+ /**
162
+ * Invalidate API key permission caches for all active read-only and full-access
163
+ * keys owned by a user.
164
+ *
165
+ * Called after `assignRoleToUser()` and `unassignRoleFromUser()` because those
166
+ * token types resolve permissions from the creator's current role set. When the
167
+ * role set changes, the cached permission slugs must be evicted so the next
168
+ * request re-resolves them from the updated roles.
169
+ *
170
+ * Role-based keys are NOT invalidated here — their cache is keyed to the assigned
171
+ * role, not to the creator, and is invalidated via RolePermissionService instead.
172
+ *
173
+ * @param userId - The user whose read-only and full-access API key caches to evict
174
+ */
175
+ private invalidateApiKeyCachesForUser;
176
+ }
177
+
178
+ /**
179
+ * Code Field Validators
180
+ *
181
+ * Reusable validation functions for code fields with language-specific syntax checking.
182
+ * These validators can be used in field configurations to ensure code content is valid.
183
+ *
184
+ * @module collections/fields/validators/code-validators
185
+ * @since 1.0.0
186
+ */
187
+
188
+ /**
189
+ * Validation result type for code validators.
190
+ * Returns `true` if valid, or an error message string if invalid.
191
+ */
192
+ type CodeValidationResult = string | true;
193
+ /**
194
+ * Validator function signature.
195
+ */
196
+ type CodeValidator = (value: CodeFieldValue) => CodeValidationResult;
197
+ /**
198
+ * Validates JSON syntax.
199
+ *
200
+ * Ensures the code field contains valid, parseable JSON.
201
+ * Provides detailed error messages including line/column information.
202
+ *
203
+ * @example
204
+ * ```typescript
205
+ * const configField: CodeFieldConfig = {
206
+ * name: 'config',
207
+ * type: 'code',
208
+ * admin: { language: 'json' },
209
+ * validate: validateJSON,
210
+ * };
211
+ * ```
212
+ *
213
+ * @param value - The JSON string to validate
214
+ * @returns `true` if valid, error message if invalid
215
+ */
216
+ declare function validateJSON(value: CodeFieldValue): CodeValidationResult;
217
+ /**
218
+ * Validates basic XML/HTML syntax.
219
+ *
220
+ * Performs basic validation checking for:
221
+ * - Properly closed tags
222
+ * - Balanced brackets
223
+ * - Valid tag names
224
+ *
225
+ * Note: This is a basic validator. For comprehensive validation,
226
+ * consider using a proper XML parser library.
227
+ *
228
+ * @example
229
+ * ```typescript
230
+ * const xmlField: CodeFieldConfig = {
231
+ * name: 'xmlContent',
232
+ * type: 'code',
233
+ * admin: { language: 'xml' },
234
+ * validate: validateXML,
235
+ * };
236
+ * ```
237
+ *
238
+ * @param value - The XML/HTML string to validate
239
+ * @returns `true` if valid, error message if invalid
240
+ */
241
+ declare function validateXML(value: CodeFieldValue): CodeValidationResult;
242
+ /**
243
+ * Validates JavaScript/TypeScript syntax.
244
+ *
245
+ * Uses the Function constructor for basic syntax validation.
246
+ * Note: This only checks if the code is parseable JavaScript,
247
+ * not if it's valid TypeScript or follows best practices.
248
+ *
249
+ * @example
250
+ * ```typescript
251
+ * const scriptField: CodeFieldConfig = {
252
+ * name: 'customScript',
253
+ * type: 'code',
254
+ * admin: { language: 'javascript' },
255
+ * validate: validateJavaScript,
256
+ * };
257
+ * ```
258
+ *
259
+ * @param value - The JavaScript code to validate
260
+ * @returns `true` if valid, error message if invalid
261
+ */
262
+ declare function validateJavaScript(value: CodeFieldValue): CodeValidationResult;
263
+ /**
264
+ * Options for SQL validation.
265
+ */
266
+ interface SQLValidatorOptions {
267
+ /**
268
+ * Forbidden SQL commands (case-insensitive).
269
+ * Common dangerous commands to block.
270
+ *
271
+ * @default ['DROP TABLE', 'DROP DATABASE', 'TRUNCATE', 'DELETE FROM', 'ALTER TABLE']
272
+ */
273
+ forbiddenCommands?: string[];
274
+ /**
275
+ * Allow empty values.
276
+ * @default true
277
+ */
278
+ allowEmpty?: boolean;
279
+ }
280
+ /**
281
+ * Creates a basic SQL validator with configurable forbidden commands.
282
+ *
283
+ * This is a safety validator, not a comprehensive syntax checker.
284
+ * It blocks potentially dangerous SQL commands.
285
+ *
286
+ * @example
287
+ * ```typescript
288
+ * const queryField: CodeFieldConfig = {
289
+ * name: 'customQuery',
290
+ * type: 'code',
291
+ * admin: { language: 'sql' },
292
+ * validate: createSQLValidator({
293
+ * forbiddenCommands: ['DROP', 'DELETE', 'TRUNCATE', 'ALTER'],
294
+ * }),
295
+ * };
296
+ * ```
297
+ *
298
+ * @param options - Validation options
299
+ * @returns Validator function
300
+ */
301
+ declare function createSQLValidator(options?: SQLValidatorOptions): CodeValidator;
302
+ /**
303
+ * Validates basic CSS syntax.
304
+ *
305
+ * Performs simple validation checking for:
306
+ * - Balanced braces
307
+ * - Basic selector syntax
308
+ * - Property-value pairs
309
+ *
310
+ * @example
311
+ * ```typescript
312
+ * const stylesField: CodeFieldConfig = {
313
+ * name: 'customStyles',
314
+ * type: 'code',
315
+ * admin: { language: 'css' },
316
+ * validate: validateCSS,
317
+ * };
318
+ * ```
319
+ *
320
+ * @param value - The CSS code to validate
321
+ * @returns `true` if valid, error message if invalid
322
+ */
323
+ declare function validateCSS(value: CodeFieldValue): CodeValidationResult;
324
+ /**
325
+ * Collection of all available code validators.
326
+ */
327
+ declare const codeValidators: {
328
+ readonly json: typeof validateJSON;
329
+ readonly xml: typeof validateXML;
330
+ readonly html: typeof validateXML;
331
+ readonly javascript: typeof validateJavaScript;
332
+ readonly typescript: typeof validateJavaScript;
333
+ readonly css: typeof validateCSS;
334
+ readonly sql: typeof createSQLValidator;
335
+ };
336
+
337
+ /**
338
+ * Shared SQL Reserved Keyword & Slug Constants
339
+ *
340
+ * Pure-data module — no imports — so it can be the cycle-breaker between
341
+ * collections/config/validate-config.ts and shared/base-validator.ts.
342
+ *
343
+ * Originally these constants lived in validate-config.ts and base-validator.ts
344
+ * imported them back, creating a circular dependency. tsup's bundling masked
345
+ * the issue (its evaluation order happened to initialise the constants before
346
+ * base-validator's top-level Set construction). Turbopack's strict ESM
347
+ * evaluation surfaced it as a TDZ ReferenceError when source-mode dev started
348
+ * walking the source files directly.
349
+ *
350
+ * Solution: extract the constants here. Both validate-config and base-validator
351
+ * import from this leaf module, which has no further imports → no cycle.
352
+ *
353
+ * @module shared/sql-reserved
354
+ */
355
+ /**
356
+ * Reserved collection slugs that cannot be used.
357
+ * These are used by the system or have special meaning.
358
+ */
359
+ declare const RESERVED_SLUGS: readonly ["api", "graphql", "rest", "admin", "dashboard", "auth", "login", "logout", "register", "signup", "signin", "signout", "forgot-password", "reset-password", "verify", "verify-email", "static", "public", "assets", "_next", "health", "status", "metrics", "users", "roles", "permissions", "sessions", "tokens", "media", "uploads", "files"];
360
+ /**
361
+ * SQL reserved keywords that should not be used as identifiers.
362
+ *
363
+ * Curated list of the most problematic keywords across PostgreSQL, MySQL,
364
+ * and SQLite. Using these as table or column names can cause issues even
365
+ * with quoting.
366
+ *
367
+ * @see https://sqlite.org/lang_keywords.html
368
+ * @see https://www.postgresql.org/docs/current/sql-keywords-appendix.html
369
+ * @see https://dev.mysql.com/doc/refman/8.0/en/keywords.html
370
+ */
371
+ declare const SQL_RESERVED_KEYWORDS: readonly ["select", "insert", "update", "delete", "from", "where", "set", "values", "create", "drop", "alter", "table", "index", "view", "trigger", "database", "join", "inner", "outer", "left", "right", "cross", "full", "on", "using", "order", "group", "by", "having", "limit", "offset", "distinct", "as", "case", "when", "then", "else", "end", "and", "or", "not", "in", "is", "null", "like", "between", "exists", "primary", "foreign", "key", "references", "unique", "check", "constraint", "default", "begin", "commit", "rollback", "transaction", "count", "sum", "avg", "min", "max", "all", "any", "union", "except", "intersect", "column", "row", "rows", "for", "to", "into", "with", "user", "password", "role", "session", "grant", "revoke", "match", "natural"];
372
+
373
+ /**
374
+ * Collection Configuration Validator
375
+ *
376
+ * Validates a {@link CollectionConfig} using shared base-validator helpers
377
+ * for slug/field-name/relationship/select/component rules, plus the
378
+ * collection-specific access control (create/read/update/delete) and
379
+ * index validation that Singles/Components don't have.
380
+ *
381
+ * Duplicated validation logic was moved to `src/shared/base-validator.ts`
382
+ * This file now orchestrates those helpers and keeps
383
+ * only Collection-specific rules.
384
+ *
385
+ * @module collections/config/validate-config
386
+ * @since 1.0.0
387
+ *
388
+ * @example
389
+ * ```typescript
390
+ * import { validateCollectionConfig } from '@nextly/core';
391
+ *
392
+ * const result = validateCollectionConfig(config, ['users', 'posts']);
393
+ * if (!result.valid) {
394
+ * console.error('Validation errors:', result.errors);
395
+ * }
396
+ * ```
397
+ */
398
+
399
+ /**
400
+ * Error codes for validation failures.
401
+ * Used for programmatic error handling.
402
+ */
403
+ type ValidationErrorCode$1 = "SLUG_REQUIRED" | "SLUG_INVALID_TYPE" | "SLUG_TOO_SHORT" | "SLUG_TOO_LONG" | "SLUG_INVALID_FORMAT" | "SLUG_RESERVED" | "SLUG_SQL_KEYWORD" | "FIELDS_REQUIRED" | "FIELDS_INVALID_TYPE" | "FIELDS_EMPTY" | "FIELD_NAME_REQUIRED" | "FIELD_NAME_INVALID_FORMAT" | "FIELD_NAME_SQL_KEYWORD" | "FIELD_NAME_DUPLICATE" | "FIELD_TYPE_REQUIRED" | "FIELD_TYPE_INVALID" | "SELECT_OPTIONS_REQUIRED" | "SELECT_OPTIONS_EMPTY" | "RADIO_OPTIONS_REQUIRED" | "RADIO_OPTIONS_EMPTY" | "RELATIONSHIP_TARGET_REQUIRED" | "RELATIONSHIP_TARGET_INVALID" | "RELATIONSHIP_TARGET_UNKNOWN" | "ARRAY_FIELDS_REQUIRED" | "GROUP_FIELDS_REQUIRED" | "BLOCKS_REQUIRED" | "BLOCKS_EMPTY" | "BLOCK_SLUG_REQUIRED" | "BLOCK_FIELDS_REQUIRED" | "COMPONENT_REF_REQUIRED" | "COMPONENT_REF_CONFLICT" | "COMPONENT_REF_INVALID" | "COMPONENT_REF_EMPTY" | "ACCESS_INVALID_TYPE" | "ACCESS_FUNCTION_INVALID" | "INDEX_INVALID_TYPE" | "INDEX_FIELDS_REQUIRED" | "INDEX_FIELDS_EMPTY" | "INDEX_FIELD_UNKNOWN" | "INDEX_NAME_INVALID";
404
+ /**
405
+ * A single validation error with path and context.
406
+ */
407
+ interface ValidationError$1 {
408
+ /**
409
+ * Dot-notation path to the invalid property.
410
+ * @example 'slug', 'fields.0.name', 'fields.metadata.items.title'
411
+ */
412
+ path: string;
413
+ /** Human-readable error message. */
414
+ message: string;
415
+ /** Machine-readable error code for programmatic handling. */
416
+ code: ValidationErrorCode$1;
417
+ }
418
+ /**
419
+ * Result of collection config validation.
420
+ */
421
+ interface ValidationResult$1 {
422
+ /** Whether the configuration is valid. */
423
+ valid: boolean;
424
+ /** Array of validation errors (empty if valid). */
425
+ errors: ValidationError$1[];
426
+ }
427
+ /**
428
+ * Validates a complete collection configuration.
429
+ *
430
+ * Performs comprehensive validation including slug format/reserved names,
431
+ * SQL keyword blocking, recursive field validation, select options,
432
+ * relationship targets (optionally cross-checked against known collection
433
+ * slugs), duplicate detection, access function types, and index
434
+ * configuration validation.
435
+ *
436
+ * @param config - The collection configuration to validate
437
+ * @param allCollectionSlugs - Optional array of all collection slugs for relationship validation
438
+ * @returns Validation result with any errors found
439
+ *
440
+ * @example
441
+ * ```typescript
442
+ * import { validateCollectionConfig } from '@nextly/core';
443
+ *
444
+ * const result = validateCollectionConfig(config, ['users', 'posts', 'categories']);
445
+ *
446
+ * if (!result.valid) {
447
+ * result.errors.forEach(err => {
448
+ * console.error(`[${err.code}] ${err.path}: ${err.message}`);
449
+ * });
450
+ * }
451
+ * ```
452
+ */
453
+ declare function validateCollectionConfig(config: CollectionConfig, allCollectionSlugs?: string[]): ValidationResult$1;
454
+ /**
455
+ * Throws an error if the configuration is invalid.
456
+ *
457
+ * Convenience wrapper around {@link validateCollectionConfig}.
458
+ */
459
+ declare function assertValidCollectionConfig(config: CollectionConfig, allCollectionSlugs?: string[]): void;
460
+
461
+ /**
462
+ * TypeScript Type Generator Service
463
+ *
464
+ * Generates TypeScript interfaces from collection and single definitions. Provides strong typing for
465
+ * collections, singles, entries, and input types.
466
+ *
467
+ * Generates:
468
+ * - Collection interfaces with all fields typed
469
+ * - Single interfaces with all fields typed
470
+ * - Config interface mapping slugs to types (collections and singles)
471
+ * - Create/Update input types for collections
472
+ * - Update input types for singles
473
+ * - Module augmentation for type-safe collection and single access
474
+ *
475
+ * @module services/schema/type-generator
476
+ * @since 1.0.0
477
+ */
478
+
479
+ /**
480
+ * Result of generating TypeScript types for a single collection.
481
+ */
482
+ interface GeneratedTypeInterface {
483
+ /** Collection slug */
484
+ collectionSlug: string;
485
+ /** Generated TypeScript interface code */
486
+ code: string;
487
+ /** Interface name (e.g., "Post", "User") */
488
+ interfaceName: string;
489
+ }
490
+ /**
491
+ * Result of generating TypeScript types for a single Single.
492
+ */
493
+ interface GeneratedSingleTypeInterface {
494
+ /** Single slug */
495
+ singleSlug: string;
496
+ /** Generated TypeScript interface code */
497
+ code: string;
498
+ /** Interface name (e.g., "SiteSettings", "Header") */
499
+ interfaceName: string;
500
+ }
501
+ /**
502
+ * Result of generating the complete payload-types.ts file.
503
+ */
504
+ interface GeneratedTypesFile {
505
+ /** Generated TypeScript code for the types file */
506
+ code: string;
507
+ /** Suggested filename (default: "payload-types.ts") */
508
+ filename: string;
509
+ }
510
+ /**
511
+ * Options for TypeScript type generation.
512
+ */
513
+ interface TypeGeneratorOptions {
514
+ /**
515
+ * Whether to include JSDoc comments in generated code.
516
+ * @default true
517
+ */
518
+ includeComments?: boolean;
519
+ /**
520
+ * Whether to generate Create and Update input types.
521
+ * @default true
522
+ */
523
+ generateInputTypes?: boolean;
524
+ /**
525
+ * Whether to generate Config interface mapping.
526
+ * @default true
527
+ */
528
+ generateConfig?: boolean;
529
+ /**
530
+ * Whether to generate module augmentation.
531
+ * @default true
532
+ */
533
+ generateModuleAugmentation?: boolean;
534
+ /**
535
+ * Custom filename for generated types.
536
+ * @default "payload-types.ts"
537
+ */
538
+ filename?: string;
539
+ /**
540
+ * Module to augment for GeneratedTypes.
541
+ * @default "nextly"
542
+ */
543
+ moduleToAugment?: string;
544
+ }
545
+
546
+ /**
547
+ * UsersService - Facade for user operations
548
+ *
549
+ * This service acts as a facade, delegating to specialized services:
550
+ * - UserQueryService: List, get, find operations
551
+ * - UserMutationService: Create, update, delete operations
552
+ * - UserAccountService: Profile, password, OAuth account operations
553
+ *
554
+ * For new code, consider using the specialized services directly for better
555
+ * separation of concerns.
556
+ *
557
+ * PR 4 (unified-error-system): facade methods now mirror the underlying
558
+ * services — they return the value directly and throw NextlyError on
559
+ * failure rather than returning `{ success, statusCode, message, data }`
560
+ * envelopes. Callers should use try/catch with NextlyError.is*() guards.
561
+ *
562
+ * @example
563
+ * ```typescript
564
+ * const usersService = new UsersService(adapter, logger);
565
+ * const users = await usersService.listUsers();
566
+ *
567
+ * // Using specialized services directly (recommended for new code)
568
+ * import { UserQueryService, UserMutationService } from './users/index';
569
+ * const queryService = new UserQueryService(adapter, logger);
570
+ * const users = await queryService.listUsers();
571
+ * ```
572
+ */
573
+
574
+ declare class UsersService extends BaseService {
575
+ private queryService;
576
+ private mutationService;
577
+ private accountService;
578
+ /**
579
+ * Creates a new UsersService instance.
580
+ *
581
+ * @param adapter - Database adapter for multi-database support
582
+ * @param logger - Logger instance
583
+ * @param userConfig - Optional user extension configuration (custom fields)
584
+ * @param userExtSchemaService - Optional schema service for runtime user_ext table
585
+ * @param emailService - Optional email service for welcome emails
586
+ */
587
+ constructor(adapter: DrizzleAdapter, logger: Logger, userConfig?: UserConfig, userExtSchemaService?: UserExtSchemaService, emailService?: EmailService);
588
+ /**
589
+ * List users with pagination, filtering, and sorting.
590
+ *
591
+ * PR 4: returns the data envelope directly (no `success` wrapper).
592
+ * Throws NextlyError on failure.
593
+ */
594
+ listUsers(options?: {
595
+ page?: number;
596
+ limit?: number;
597
+ search?: string;
598
+ emailVerified?: boolean;
599
+ hasPassword?: boolean;
600
+ createdAtFrom?: Date;
601
+ createdAtTo?: Date;
602
+ sortBy?: "createdAt" | "name" | "email" | (string & {});
603
+ sortOrder?: "asc" | "desc";
604
+ }): Promise<ListUsersResponse>;
605
+ /**
606
+ * Get a user by ID.
607
+ *
608
+ * PR 4: returns the user directly. Throws NextlyError(NOT_FOUND) if missing.
609
+ */
610
+ getUserById(userId: number | string): Promise<GetUserResponse>;
611
+ /**
612
+ * Find a user by email
613
+ */
614
+ findByEmail(email: string): Promise<MinimalUser | null>;
615
+ /**
616
+ * Create a new local user.
617
+ *
618
+ * PR 4: returns the created user directly. Throws NextlyError on failure
619
+ * (e.g. DUPLICATE on email collision).
620
+ */
621
+ createLocalUser(userData: {
622
+ email: string;
623
+ name: string;
624
+ image?: string | null;
625
+ password?: string | null;
626
+ roles?: string[];
627
+ isActive?: boolean;
628
+ sendWelcomeEmail?: boolean;
629
+ [key: string]: unknown;
630
+ }): Promise<UserMutationResponse>;
631
+ /**
632
+ * Update an existing user.
633
+ *
634
+ * PR 4: returns the updated user directly. Throws NextlyError(NOT_FOUND)
635
+ * or NextlyError(DUPLICATE) on failure.
636
+ */
637
+ updateUser(userId: number | string, changes: {
638
+ email?: string;
639
+ name?: string;
640
+ password?: string | null;
641
+ image?: string;
642
+ emailVerified?: Date | null;
643
+ roles?: string[];
644
+ isActive?: boolean;
645
+ sendWelcomeEmail?: boolean;
646
+ [key: string]: unknown;
647
+ }): Promise<UserMutationResponse>;
648
+ /**
649
+ * Delete a user.
650
+ *
651
+ * PR 4: returns void. Throws NextlyError(NOT_FOUND) when the user does
652
+ * not exist, or NextlyError on DB errors.
653
+ */
654
+ deleteUser(userId: number | string): Promise<void>;
655
+ /**
656
+ * Get current user profile.
657
+ *
658
+ * PR 4: returns the user directly. Throws NextlyError(NOT_FOUND) if missing.
659
+ */
660
+ getCurrentUser(userId: number | string): Promise<GetUserResponse>;
661
+ /**
662
+ * Update current user profile.
663
+ *
664
+ * PR 4: returns the updated user directly. Throws NextlyError on failure.
665
+ */
666
+ updateCurrentUser(userId: number | string, changes: {
667
+ name?: string;
668
+ image?: string;
669
+ }): Promise<GetUserResponse>;
670
+ /**
671
+ * Update a user's password hash.
672
+ *
673
+ * PR 4: returns void. Throws NextlyError(NOT_FOUND) when the user does
674
+ * not exist, or NextlyError on DB errors.
675
+ */
676
+ updatePasswordHash(userId: number | string, passwordHash: string): Promise<void>;
677
+ /**
678
+ * Check if a user has a password set
679
+ */
680
+ hasPassword(userId: number | string): Promise<boolean>;
681
+ /**
682
+ * Get a user's password hash by ID
683
+ */
684
+ getUserPasswordHashById(userId: number | string): Promise<string | null>;
685
+ /**
686
+ * Get all OAuth accounts linked to a user.
687
+ *
688
+ * PR 4: returns the array directly. Throws NextlyError on failure.
689
+ */
690
+ getAccounts(userId: number | string): Promise<GetAccountsResponse>;
691
+ /**
692
+ * Delete a specific OAuth account
693
+ */
694
+ deleteUserAccount(userId: number | string, provider: string, providerAccountId: string): Promise<number>;
695
+ /**
696
+ * Unlink an OAuth account from a user.
697
+ *
698
+ * Note: this method intentionally returns a discriminated union rather
699
+ * than throwing — callers branch on `.ok` (see UserAccountService for
700
+ * rationale). It does NOT follow the throw-based pattern.
701
+ */
702
+ unlinkAccountForUser(userId: number | string, provider: string, providerAccountId: string): Promise<UnlinkAccountResult>;
703
+ }
704
+
705
+ /**
706
+ * Service container providing dependency injection for Nextly services.
707
+ *
708
+ * Centralizes service instantiation with consistent db and tables injection.
709
+ * Services are lazily instantiated to avoid unnecessary overhead.
710
+ */
711
+ declare class ServiceContainer {
712
+ private readonly adapter;
713
+ private _users?;
714
+ private _auth?;
715
+ private _collections?;
716
+ private _roles?;
717
+ private _permissions?;
718
+ private _rolePermissions?;
719
+ private _userRoles?;
720
+ private _roleInheritance?;
721
+ private _permissionChecker?;
722
+ private _media?;
723
+ private _mediaFolders?;
724
+ private readonly tables;
725
+ private readonly db;
726
+ constructor(adapter: DrizzleAdapter);
727
+ private getLogger;
728
+ /**
729
+ * Check if adapter is configured
730
+ */
731
+ get hasAdapter(): boolean;
732
+ /**
733
+ * Get Users service instance (lazy-loaded)
734
+ * Injects UserExtSchemaService, UserConfig, and EmailService from DI container if available.
735
+ */
736
+ get users(): UsersService;
737
+ /**
738
+ * Get Auth service instance (lazy-loaded)
739
+ * Injects EmailService from DI container if available.
740
+ */
741
+ get auth(): AuthService;
742
+ /**
743
+ * Get Collections handler instance (lazy-loaded)
744
+ *
745
+ * IMPORTANT: This getter first checks the DI container for a registered
746
+ * CollectionsHandler. This ensures that dynamic schemas registered via
747
+ * getCollectionsHandler() are available to the ServiceDispatcher.
748
+ *
749
+ * @throws Error if adapter was not provided and DI container has no handler
750
+ */
751
+ get collections(): CollectionsHandler;
752
+ /**
753
+ * Get Role service instance (lazy-loaded)
754
+ * Handles role CRUD operations
755
+ */
756
+ get roles(): RoleService;
757
+ /**
758
+ * Get Permission service instance (lazy-loaded)
759
+ * Handles permission CRUD operations
760
+ */
761
+ get permissions(): PermissionService;
762
+ /**
763
+ * Get RolePermission service instance (lazy-loaded)
764
+ * Handles role-permission assignments
765
+ */
766
+ get rolePermissions(): RolePermissionService;
767
+ /**
768
+ * Get UserRole service instance (lazy-loaded)
769
+ * Handles user-role assignments
770
+ */
771
+ get userRoles(): UserRoleService;
772
+ /**
773
+ * Get RoleInheritance service instance (lazy-loaded)
774
+ * Handles role hierarchy management
775
+ */
776
+ get roleInheritance(): RoleInheritanceService;
777
+ /**
778
+ * Get PermissionChecker service instance (lazy-loaded)
779
+ * Handles authorization checking logic
780
+ */
781
+ get permissionChecker(): PermissionCheckerService;
782
+ /**
783
+ * Get Media service instance (lazy-loaded)
784
+ * Handles media file uploads, processing, and storage
785
+ */
786
+ get media(): MediaService;
787
+ /**
788
+ * Get MediaFolder service instance (lazy-loaded)
789
+ * Handles folder organization for media files
790
+ */
791
+ get mediaFolders(): MediaFolderService;
792
+ /**
793
+ * Get tables for current dialect (public accessor)
794
+ */
795
+ get dialectTables(): unknown;
796
+ /**
797
+ * Execute a function within a database transaction with fresh service instances.
798
+ * Creates new service instances with transaction context for use within the transaction.
799
+ *
800
+ * @param fn Function to execute within transaction, receives fresh service container with tx context
801
+ * @returns Promise resolving to the function's return value
802
+ */
803
+ withTransaction<T>(fn: (txServices: ServiceContainer) => Promise<T>): Promise<T>;
804
+ }
805
+
806
+ /**
807
+ * Public types for the service dispatcher.
808
+ *
809
+ * The dispatcher routes API requests to the appropriate service method,
810
+ * normalizes responses, and maps error messages to HTTP status codes.
811
+ * Consumers (route handlers) import `ServiceDispatcher` plus these
812
+ * types to build and interpret dispatch requests.
813
+ */
814
+
815
+ type ServiceType = "users" | "rbac" | "auth" | "posts" | "collections" | "singles" | "forms" | "components" | "userFields" | "emailProviders" | "emailTemplates" | "apiKeys" | "generalSettings" | "imageSizes" | "dashboard" | "email" | "schema";
816
+ type OperationType = "single" | "list" | "create" | "update" | "delete" | "count";
817
+ interface DispatchRequest {
818
+ service: ServiceType;
819
+ operation: OperationType;
820
+ method: string;
821
+ params?: Record<string, unknown>;
822
+ body?: unknown;
823
+ userId?: string;
824
+ /** Optional request object for accessing headers. */
825
+ request?: Request;
826
+ }
827
+ interface DispatchResult {
828
+ success: boolean;
829
+ data?: unknown;
830
+ /**
831
+ * Carries the original NextlyError (not a stringified message) so the
832
+ * route wrapper can rebuild the response with correct statusCode, code,
833
+ * publicData, and headers (Retry-After for rate limits, etc.). See spec
834
+ * §6.4.
835
+ */
836
+ error?: NextlyError;
837
+ status: number;
838
+ message?: string;
839
+ meta?: unknown;
840
+ }
841
+
842
+ /**
843
+ * Service dispatcher — thin router that delegates every incoming
844
+ * request to a domain-specific handler.
845
+ *
846
+ * The legacy monolithic dispatcher held ~3,000 lines of per-method
847
+ * logic. That logic now lives in `./handlers/*`. This class keeps only:
848
+ *
849
+ * - Lazy initialization of the underlying `ServiceContainer` (it resolves
850
+ * the adapter from DI or falls back to env-based adapter creation).
851
+ * - Request validation (service + operation + method presence/shape).
852
+ * - Service-name → handler dispatch (the `executeServiceMethod` switch).
853
+ * - Response normalization (`ServiceResult` → `DispatchResult`).
854
+ * - Error-status mapping (heuristic text match on error messages).
855
+ *
856
+ * Route handlers (e.g. `auth-handler.ts`, `route-parser.ts`) import
857
+ * `ServiceDispatcher` from `@nextly/services` / `src/services/dispatcher.ts`,
858
+ * which re-exports this class.
859
+ */
860
+
861
+ /**
862
+ * ServiceDispatcher routes API requests to the appropriate service
863
+ * method. It provides a unified dispatch interface for all service
864
+ * operations, handling parameter validation, type coercion, and error
865
+ * handling.
866
+ *
867
+ * @example
868
+ * ```typescript
869
+ * const dispatcher = new ServiceDispatcher();
870
+ * const result = await dispatcher.dispatch({
871
+ * service: 'users',
872
+ * operation: 'single',
873
+ * method: 'getUserById',
874
+ * params: { userId: '123' }
875
+ * });
876
+ * ```
877
+ */
878
+ declare class ServiceDispatcher {
879
+ private container;
880
+ private availableServices;
881
+ constructor();
882
+ /** Returns the underlying service container. */
883
+ getContainer(): ServiceContainer;
884
+ /** Checks if a service is available. */
885
+ isServiceAvailable(service: ServiceType): boolean;
886
+ /** Validates a dispatch request. */
887
+ validateRequest(request: DispatchRequest): {
888
+ valid: boolean;
889
+ error?: string;
890
+ };
891
+ /**
892
+ * Ensure the service container is fully initialized with an adapter.
893
+ * Resolves from DI first and falls back to environment-based adapter
894
+ * creation when DI hasn't been initialized (e.g. certain test paths).
895
+ */
896
+ private ensureInitialized;
897
+ /**
898
+ * Dispatches a request to the appropriate service method.
899
+ *
900
+ * @param request - Service, method, params, and body to execute.
901
+ * @returns Standardized dispatch result with success, data, and error.
902
+ */
903
+ dispatch(request: DispatchRequest): Promise<DispatchResult>;
904
+ private executeServiceMethod;
905
+ /** Registers a new service type. */
906
+ addService(service: ServiceType): void;
907
+ /** Unregisters a service type. */
908
+ removeService(service: ServiceType): void;
909
+ /** Returns list of available service types. */
910
+ getAvailableServices(): ServiceType[];
911
+ /** Executes a function within a database transaction. */
912
+ withTransaction<T>(fn: (dispatcher: ServiceDispatcher) => Promise<T>): Promise<T>;
913
+ }
914
+
915
+ declare const UserIdSchema: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
916
+ declare const MinimalUserSchema: z.ZodObject<{
917
+ id: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
918
+ email: z.ZodString;
919
+ emailVerified: z.ZodOptional<z.ZodUnion<readonly [z.ZodDate, z.ZodString, z.ZodNull]>>;
920
+ name: z.ZodNullable<z.ZodString>;
921
+ image: z.ZodNullable<z.ZodString>;
922
+ isActive: z.ZodOptional<z.ZodBoolean>;
923
+ createdAt: z.ZodOptional<z.ZodUnion<readonly [z.ZodDate, z.ZodString]>>;
924
+ updatedAt: z.ZodOptional<z.ZodUnion<readonly [z.ZodDate, z.ZodString]>>;
925
+ roles: z.ZodOptional<z.ZodArray<z.ZodObject<{
926
+ id: z.ZodString;
927
+ name: z.ZodString;
928
+ }, z.core.$strip>>>;
929
+ }, z.core.$loose>;
930
+ declare const UserAccountSchema: z.ZodObject<{
931
+ id: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
932
+ userId: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
933
+ provider: z.ZodString;
934
+ providerAccountId: z.ZodString;
935
+ type: z.ZodString;
936
+ }, z.core.$strip>;
937
+ declare const CreateLocalUserSchema: z.ZodObject<{
938
+ email: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
939
+ name: z.ZodString;
940
+ image: z.ZodOptional<z.ZodNullable<z.ZodString>>;
941
+ password: z.ZodOptional<z.ZodString>;
942
+ roles: z.ZodOptional<z.ZodArray<z.ZodString>>;
943
+ isActive: z.ZodOptional<z.ZodBoolean>;
944
+ sendWelcomeEmail: z.ZodOptional<z.ZodBoolean>;
945
+ }, z.core.$strip>;
946
+ declare const CreateUserWithPasswordSchema: z.ZodObject<{
947
+ email: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
948
+ name: z.ZodString;
949
+ password: z.ZodString;
950
+ }, z.core.$strip>;
951
+ declare const UpdateUserSchema: z.ZodObject<{
952
+ email: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
953
+ name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
954
+ password: z.ZodOptional<z.ZodString>;
955
+ image: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string | null, string>>>;
956
+ emailVerified: z.ZodOptional<z.ZodUnion<readonly [z.ZodDate, z.ZodString, z.ZodNull]>>;
957
+ roles: z.ZodOptional<z.ZodArray<z.ZodString>>;
958
+ isActive: z.ZodOptional<z.ZodBoolean>;
959
+ sendWelcomeEmail: z.ZodOptional<z.ZodBoolean>;
960
+ }, z.core.$strip>;
961
+ declare const UpdatePasswordSchema: z.ZodObject<{
962
+ userId: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
963
+ password: z.ZodString;
964
+ }, z.core.$strip>;
965
+ declare const GetUserByIdSchema: z.ZodObject<{
966
+ userId: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
967
+ }, z.core.$strip>;
968
+ declare const DeleteUserSchema: z.ZodObject<{
969
+ userId: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
970
+ }, z.core.$strip>;
971
+ declare const ListUsersSchema: z.ZodObject<{
972
+ page: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
973
+ limit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
974
+ search: z.ZodOptional<z.ZodString>;
975
+ emailVerified: z.ZodOptional<z.ZodBoolean>;
976
+ hasPassword: z.ZodOptional<z.ZodBoolean>;
977
+ createdAtFrom: z.ZodOptional<z.ZodDate>;
978
+ createdAtTo: z.ZodOptional<z.ZodDate>;
979
+ sortBy: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
980
+ email: "email";
981
+ name: "name";
982
+ createdAt: "createdAt";
983
+ }>>>;
984
+ sortOrder: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
985
+ asc: "asc";
986
+ desc: "desc";
987
+ }>>>;
988
+ }, z.core.$strip>;
989
+ declare const DeleteUserAccountSchema: z.ZodObject<{
990
+ userId: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
991
+ provider: z.ZodString;
992
+ providerAccountId: z.ZodString;
993
+ }, z.core.$strip>;
994
+ declare const UnlinkAccountSchema: z.ZodObject<{
995
+ userId: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
996
+ provider: z.ZodString;
997
+ providerAccountId: z.ZodString;
998
+ }, z.core.$strip>;
999
+ declare const UserListResponseSchema: z.ZodArray<z.ZodObject<{
1000
+ id: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
1001
+ email: z.ZodString;
1002
+ emailVerified: z.ZodOptional<z.ZodUnion<readonly [z.ZodDate, z.ZodString, z.ZodNull]>>;
1003
+ name: z.ZodNullable<z.ZodString>;
1004
+ image: z.ZodNullable<z.ZodString>;
1005
+ isActive: z.ZodOptional<z.ZodBoolean>;
1006
+ createdAt: z.ZodOptional<z.ZodUnion<readonly [z.ZodDate, z.ZodString]>>;
1007
+ updatedAt: z.ZodOptional<z.ZodUnion<readonly [z.ZodDate, z.ZodString]>>;
1008
+ roles: z.ZodOptional<z.ZodArray<z.ZodObject<{
1009
+ id: z.ZodString;
1010
+ name: z.ZodString;
1011
+ }, z.core.$strip>>>;
1012
+ }, z.core.$loose>>;
1013
+ declare const UserResponseSchema: z.ZodObject<{
1014
+ id: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
1015
+ email: z.ZodString;
1016
+ emailVerified: z.ZodOptional<z.ZodUnion<readonly [z.ZodDate, z.ZodString, z.ZodNull]>>;
1017
+ name: z.ZodNullable<z.ZodString>;
1018
+ image: z.ZodNullable<z.ZodString>;
1019
+ isActive: z.ZodOptional<z.ZodBoolean>;
1020
+ createdAt: z.ZodOptional<z.ZodUnion<readonly [z.ZodDate, z.ZodString]>>;
1021
+ updatedAt: z.ZodOptional<z.ZodUnion<readonly [z.ZodDate, z.ZodString]>>;
1022
+ roles: z.ZodOptional<z.ZodArray<z.ZodObject<{
1023
+ id: z.ZodString;
1024
+ name: z.ZodString;
1025
+ }, z.core.$strip>>>;
1026
+ }, z.core.$loose>;
1027
+ declare const DeleteUserResponseSchema: z.ZodObject<{
1028
+ deleted: z.ZodBoolean;
1029
+ }, z.core.$strip>;
1030
+ declare const UnlinkAccountResponseSchema: z.ZodUnion<readonly [z.ZodObject<{
1031
+ ok: z.ZodLiteral<true>;
1032
+ }, z.core.$strip>, z.ZodObject<{
1033
+ ok: z.ZodLiteral<false>;
1034
+ status: z.ZodNumber;
1035
+ error: z.ZodString;
1036
+ }, z.core.$strip>]>;
1037
+ type UserAccount = z.infer<typeof UserAccountSchema>;
1038
+ type CreateLocalUser = z.infer<typeof CreateLocalUserSchema>;
1039
+ type CreateUserWithPassword = z.infer<typeof CreateUserWithPasswordSchema>;
1040
+ type UpdateUser = z.infer<typeof UpdateUserSchema>;
1041
+ type UpdatePassword = z.infer<typeof UpdatePasswordSchema>;
1042
+ type GetUserById = z.infer<typeof GetUserByIdSchema>;
1043
+ type DeleteUser = z.infer<typeof DeleteUserSchema>;
1044
+ type ListUsers = z.infer<typeof ListUsersSchema>;
1045
+ type DeleteUserAccount = z.infer<typeof DeleteUserAccountSchema>;
1046
+ type UnlinkAccount = z.infer<typeof UnlinkAccountSchema>;
1047
+ type UserListResponse = z.infer<typeof UserListResponseSchema>;
1048
+ type UserResponse = z.infer<typeof UserResponseSchema>;
1049
+ type DeleteUserResponse = z.infer<typeof DeleteUserResponseSchema>;
1050
+ type UnlinkAccountResponse = z.infer<typeof UnlinkAccountResponseSchema>;
1051
+
1052
+ declare const IdSchema: z.ZodString;
1053
+ /**
1054
+ * System resources that are always available regardless of dynamic collections.
1055
+ * These represent core Nextly entities that exist in every installation.
1056
+ */
1057
+ declare const SYSTEM_RESOURCES: readonly ["users", "roles", "permissions", "media", "settings", "email-providers", "email-templates", "api-keys"];
1058
+ type SystemResource = (typeof SYSTEM_RESOURCES)[number];
1059
+ /**
1060
+ * Check if a resource is a built-in system resource.
1061
+ */
1062
+ declare function isSystemResource(resource: string): resource is SystemResource;
1063
+ /**
1064
+ * Check if a resource is valid (either a system resource or a known collection slug).
1065
+ * The caller provides known collection slugs from the database.
1066
+ */
1067
+ declare function isValidResource(resource: string, knownCollectionSlugs: string[]): boolean;
1068
+ declare const RoleSchema: z.ZodObject<{
1069
+ id: z.ZodString;
1070
+ name: z.ZodString;
1071
+ slug: z.ZodString;
1072
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1073
+ level: z.ZodDefault<z.ZodNumber>;
1074
+ isSystem: z.ZodDefault<z.ZodBoolean>;
1075
+ createdAt: z.ZodOptional<z.ZodDate>;
1076
+ updatedAt: z.ZodOptional<z.ZodDate>;
1077
+ }, z.core.$strip>;
1078
+ declare const CreateRoleSchema: z.ZodObject<{
1079
+ name: z.ZodString;
1080
+ slug: z.ZodString;
1081
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1082
+ level: z.ZodDefault<z.ZodNumber>;
1083
+ isSystem: z.ZodDefault<z.ZodBoolean>;
1084
+ child: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
1085
+ }, z.core.$strip>;
1086
+ declare const UpdateRoleSchema: z.ZodObject<{
1087
+ name: z.ZodOptional<z.ZodString>;
1088
+ slug: z.ZodOptional<z.ZodString>;
1089
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1090
+ level: z.ZodOptional<z.ZodNumber>;
1091
+ isSystem: z.ZodOptional<z.ZodBoolean>;
1092
+ child: z.ZodOptional<z.ZodArray<z.ZodString>>;
1093
+ }, z.core.$strip>;
1094
+ declare const GetRoleByIdSchema: z.ZodObject<{
1095
+ roleId: z.ZodString;
1096
+ }, z.core.$strip>;
1097
+ declare const DeleteRoleSchema: z.ZodObject<{
1098
+ roleId: z.ZodString;
1099
+ }, z.core.$strip>;
1100
+ declare const PermissionActionSchema: z.ZodEnum<{
1101
+ update: "update";
1102
+ delete: "delete";
1103
+ create: "create";
1104
+ read: "read";
1105
+ manage: "manage";
1106
+ }>;
1107
+ declare const PermissionResourceSchema: z.ZodString;
1108
+ declare const PermissionSchema: z.ZodObject<{
1109
+ id: z.ZodString;
1110
+ name: z.ZodString;
1111
+ slug: z.ZodString;
1112
+ action: z.ZodEnum<{
1113
+ update: "update";
1114
+ delete: "delete";
1115
+ create: "create";
1116
+ read: "read";
1117
+ manage: "manage";
1118
+ }>;
1119
+ resource: z.ZodString;
1120
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1121
+ createdAt: z.ZodOptional<z.ZodDate>;
1122
+ updatedAt: z.ZodOptional<z.ZodDate>;
1123
+ }, z.core.$strip>;
1124
+ declare const CreatePermissionSchema: z.ZodObject<{
1125
+ name: z.ZodString;
1126
+ slug: z.ZodString;
1127
+ action: z.ZodEnum<{
1128
+ update: "update";
1129
+ delete: "delete";
1130
+ create: "create";
1131
+ read: "read";
1132
+ manage: "manage";
1133
+ }>;
1134
+ resource: z.ZodString;
1135
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1136
+ }, z.core.$strip>;
1137
+ declare const UpdatePermissionSchema: z.ZodObject<{
1138
+ name: z.ZodOptional<z.ZodString>;
1139
+ slug: z.ZodOptional<z.ZodString>;
1140
+ action: z.ZodOptional<z.ZodEnum<{
1141
+ update: "update";
1142
+ delete: "delete";
1143
+ create: "create";
1144
+ read: "read";
1145
+ manage: "manage";
1146
+ }>>;
1147
+ resource: z.ZodOptional<z.ZodString>;
1148
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1149
+ }, z.core.$strip>;
1150
+ declare const GetPermissionByIdSchema: z.ZodObject<{
1151
+ permissionId: z.ZodString;
1152
+ }, z.core.$strip>;
1153
+ declare const DeletePermissionSchema: z.ZodObject<{
1154
+ permissionId: z.ZodString;
1155
+ }, z.core.$strip>;
1156
+ declare const RolePermissionSchema: z.ZodObject<{
1157
+ id: z.ZodString;
1158
+ roleId: z.ZodString;
1159
+ permissionId: z.ZodString;
1160
+ createdAt: z.ZodOptional<z.ZodDate>;
1161
+ }, z.core.$strip>;
1162
+ declare const AssignPermissionToRoleSchema: z.ZodObject<{
1163
+ roleId: z.ZodString;
1164
+ permissionId: z.ZodString;
1165
+ }, z.core.$strip>;
1166
+ declare const RemovePermissionFromRoleSchema: z.ZodObject<{
1167
+ roleId: z.ZodString;
1168
+ permissionId: z.ZodString;
1169
+ }, z.core.$strip>;
1170
+ declare const UserRoleSchema: z.ZodObject<{
1171
+ id: z.ZodString;
1172
+ userId: z.ZodString;
1173
+ roleId: z.ZodString;
1174
+ createdAt: z.ZodOptional<z.ZodDate>;
1175
+ expiresAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
1176
+ }, z.core.$strip>;
1177
+ declare const AssignRoleToUserSchema: z.ZodObject<{
1178
+ userId: z.ZodString;
1179
+ roleId: z.ZodString;
1180
+ expiresAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
1181
+ }, z.core.$strip>;
1182
+ declare const RemoveRoleFromUserSchema: z.ZodObject<{
1183
+ userId: z.ZodString;
1184
+ roleId: z.ZodString;
1185
+ }, z.core.$strip>;
1186
+ declare const RoleInheritanceSchema: z.ZodObject<{
1187
+ id: z.ZodString;
1188
+ parentRoleId: z.ZodString;
1189
+ childRoleId: z.ZodString;
1190
+ }, z.core.$strip>;
1191
+ declare const CreateRoleInheritanceSchema: z.ZodObject<{
1192
+ parentRoleId: z.ZodString;
1193
+ childRoleId: z.ZodString;
1194
+ }, z.core.$strip>;
1195
+ declare const DeleteRoleInheritanceSchema: z.ZodObject<{
1196
+ parentRoleId: z.ZodString;
1197
+ childRoleId: z.ZodString;
1198
+ }, z.core.$strip>;
1199
+ declare const GetUserRolesSchema: z.ZodObject<{
1200
+ userId: z.ZodString;
1201
+ }, z.core.$strip>;
1202
+ declare const GetRolePermissionsSchema: z.ZodObject<{
1203
+ roleId: z.ZodString;
1204
+ }, z.core.$strip>;
1205
+ declare const GetUserPermissionsSchema: z.ZodObject<{
1206
+ userId: z.ZodString;
1207
+ }, z.core.$strip>;
1208
+ declare const CheckUserPermissionSchema: z.ZodObject<{
1209
+ userId: z.ZodString;
1210
+ action: z.ZodEnum<{
1211
+ update: "update";
1212
+ delete: "delete";
1213
+ create: "create";
1214
+ read: "read";
1215
+ manage: "manage";
1216
+ }>;
1217
+ resource: z.ZodString;
1218
+ }, z.core.$strip>;
1219
+ declare const RoleListResponseSchema: z.ZodArray<z.ZodObject<{
1220
+ id: z.ZodString;
1221
+ name: z.ZodString;
1222
+ slug: z.ZodString;
1223
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1224
+ level: z.ZodDefault<z.ZodNumber>;
1225
+ isSystem: z.ZodDefault<z.ZodBoolean>;
1226
+ createdAt: z.ZodOptional<z.ZodDate>;
1227
+ updatedAt: z.ZodOptional<z.ZodDate>;
1228
+ }, z.core.$strip>>;
1229
+ declare const PermissionListResponseSchema: z.ZodArray<z.ZodObject<{
1230
+ id: z.ZodString;
1231
+ name: z.ZodString;
1232
+ slug: z.ZodString;
1233
+ action: z.ZodEnum<{
1234
+ update: "update";
1235
+ delete: "delete";
1236
+ create: "create";
1237
+ read: "read";
1238
+ manage: "manage";
1239
+ }>;
1240
+ resource: z.ZodString;
1241
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1242
+ createdAt: z.ZodOptional<z.ZodDate>;
1243
+ updatedAt: z.ZodOptional<z.ZodDate>;
1244
+ }, z.core.$strip>>;
1245
+ declare const UserRoleListResponseSchema: z.ZodArray<z.ZodObject<{
1246
+ id: z.ZodString;
1247
+ userId: z.ZodString;
1248
+ roleId: z.ZodString;
1249
+ createdAt: z.ZodOptional<z.ZodDate>;
1250
+ expiresAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
1251
+ }, z.core.$strip>>;
1252
+ declare const RolePermissionListResponseSchema: z.ZodArray<z.ZodObject<{
1253
+ id: z.ZodString;
1254
+ roleId: z.ZodString;
1255
+ permissionId: z.ZodString;
1256
+ createdAt: z.ZodOptional<z.ZodDate>;
1257
+ }, z.core.$strip>>;
1258
+ declare const PermissionCheckResponseSchema: z.ZodObject<{
1259
+ hasPermission: z.ZodBoolean;
1260
+ reason: z.ZodOptional<z.ZodString>;
1261
+ }, z.core.$strip>;
1262
+ type CreateRole = z.infer<typeof CreateRoleSchema>;
1263
+ type UpdateRole = z.infer<typeof UpdateRoleSchema>;
1264
+ type GetRoleById = z.infer<typeof GetRoleByIdSchema>;
1265
+ type DeleteRole = z.infer<typeof DeleteRoleSchema>;
1266
+ type PermissionAction = z.infer<typeof PermissionActionSchema>;
1267
+ type PermissionResource = z.infer<typeof PermissionResourceSchema>;
1268
+ type CreatePermission = z.infer<typeof CreatePermissionSchema>;
1269
+ type UpdatePermission = z.infer<typeof UpdatePermissionSchema>;
1270
+ type GetPermissionById = z.infer<typeof GetPermissionByIdSchema>;
1271
+ type DeletePermission = z.infer<typeof DeletePermissionSchema>;
1272
+ type RolePermission = z.infer<typeof RolePermissionSchema>;
1273
+ type AssignPermissionToRole = z.infer<typeof AssignPermissionToRoleSchema>;
1274
+ type RemovePermissionFromRole = z.infer<typeof RemovePermissionFromRoleSchema>;
1275
+ type UserRole = z.infer<typeof UserRoleSchema>;
1276
+ type AssignRoleToUser = z.infer<typeof AssignRoleToUserSchema>;
1277
+ type RemoveRoleFromUser = z.infer<typeof RemoveRoleFromUserSchema>;
1278
+ type RoleInheritance = z.infer<typeof RoleInheritanceSchema>;
1279
+ type CreateRoleInheritance = z.infer<typeof CreateRoleInheritanceSchema>;
1280
+ type DeleteRoleInheritance = z.infer<typeof DeleteRoleInheritanceSchema>;
1281
+ type GetUserRoles = z.infer<typeof GetUserRolesSchema>;
1282
+ type GetRolePermissions = z.infer<typeof GetRolePermissionsSchema>;
1283
+ type GetUserPermissions = z.infer<typeof GetUserPermissionsSchema>;
1284
+ type CheckUserPermission = z.infer<typeof CheckUserPermissionSchema>;
1285
+ type RoleListResponse = z.infer<typeof RoleListResponseSchema>;
1286
+ type PermissionListResponse = z.infer<typeof PermissionListResponseSchema>;
1287
+ type UserRoleListResponse = z.infer<typeof UserRoleListResponseSchema>;
1288
+ type RolePermissionListResponse = z.infer<typeof RolePermissionListResponseSchema>;
1289
+ type PermissionCheckResponse = z.infer<typeof PermissionCheckResponseSchema>;
1290
+
1291
+ declare const PaginationSchema: z.ZodObject<{
1292
+ page: z.ZodDefault<z.ZodNumber>;
1293
+ limit: z.ZodDefault<z.ZodNumber>;
1294
+ offset: z.ZodOptional<z.ZodNumber>;
1295
+ }, z.core.$strip>;
1296
+ declare const PaginatedResponseSchema: <T extends z.ZodTypeAny>(dataSchema: T) => z.ZodObject<{
1297
+ data: z.ZodArray<T>;
1298
+ pagination: z.ZodObject<Record<string, z.ZodTypeAny>>;
1299
+ }>;
1300
+ declare const SortOrderSchema: z.ZodDefault<z.ZodEnum<{
1301
+ asc: "asc";
1302
+ desc: "desc";
1303
+ }>>;
1304
+ declare const SortSchema: z.ZodObject<{
1305
+ field: z.ZodString;
1306
+ order: z.ZodDefault<z.ZodEnum<{
1307
+ asc: "asc";
1308
+ desc: "desc";
1309
+ }>>;
1310
+ }, z.core.$strip>;
1311
+ declare const DateRangeSchema: z.ZodObject<{
1312
+ from: z.ZodOptional<z.ZodDate>;
1313
+ to: z.ZodOptional<z.ZodDate>;
1314
+ }, z.core.$strip>;
1315
+ declare const SearchSchema: z.ZodObject<{
1316
+ query: z.ZodString;
1317
+ fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
1318
+ }, z.core.$strip>;
1319
+ declare const SuccessResponseSchema: z.ZodObject<{
1320
+ success: z.ZodLiteral<true>;
1321
+ message: z.ZodOptional<z.ZodString>;
1322
+ data: z.ZodOptional<z.ZodAny>;
1323
+ }, z.core.$strip>;
1324
+ declare const ErrorResponseSchema: z.ZodObject<{
1325
+ success: z.ZodLiteral<false>;
1326
+ error: z.ZodString;
1327
+ code: z.ZodOptional<z.ZodString>;
1328
+ details: z.ZodOptional<z.ZodAny>;
1329
+ }, z.core.$strip>;
1330
+ /**
1331
+ * @deprecated Use `ValidationError` and `ValidationErrorResponse` from `nextly/validation` instead.
1332
+ * This schema will be removed in a future version.
1333
+ *
1334
+ * Migration:
1335
+ * ```typescript
1336
+ * // Old
1337
+ * import { ValidationErrorSchema } from 'nextly/schemas/validation';
1338
+ *
1339
+ * // New
1340
+ * import { ValidationError, ValidationErrorResponse } from 'nextly/validation';
1341
+ * ```
1342
+ */
1343
+ declare const ValidationErrorSchema: z.ZodObject<{
1344
+ success: z.ZodLiteral<false>;
1345
+ error: z.ZodLiteral<"Validation failed">;
1346
+ details: z.ZodArray<z.ZodObject<{
1347
+ field: z.ZodString;
1348
+ message: z.ZodString;
1349
+ code: z.ZodOptional<z.ZodString>;
1350
+ }, z.core.$strip>>;
1351
+ }, z.core.$strip>;
1352
+ declare const BulkOperationSchema: z.ZodObject<{
1353
+ ids: z.ZodArray<z.ZodString>;
1354
+ operation: z.ZodEnum<{
1355
+ update: "update";
1356
+ delete: "delete";
1357
+ activate: "activate";
1358
+ deactivate: "deactivate";
1359
+ }>;
1360
+ }, z.core.$strip>;
1361
+ declare const BulkOperationResponseSchema: z.ZodObject<{
1362
+ success: z.ZodBoolean;
1363
+ processed: z.ZodNumber;
1364
+ failed: z.ZodNumber;
1365
+ errors: z.ZodOptional<z.ZodArray<z.ZodObject<{
1366
+ id: z.ZodString;
1367
+ error: z.ZodString;
1368
+ }, z.core.$strip>>>;
1369
+ }, z.core.$strip>;
1370
+ declare const FileUploadSchema: z.ZodObject<{
1371
+ filename: z.ZodString;
1372
+ mimetype: z.ZodString;
1373
+ size: z.ZodNumber;
1374
+ buffer: z.ZodOptional<z.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>>;
1375
+ }, z.core.$strip>;
1376
+ declare const ImageUploadSchema: z.ZodObject<{
1377
+ filename: z.ZodString;
1378
+ buffer: z.ZodOptional<z.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>>;
1379
+ mimetype: z.ZodString;
1380
+ size: z.ZodNumber;
1381
+ }, z.core.$strip>;
1382
+ declare const EmailSchema: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
1383
+ declare const PasswordSchema: z.ZodString;
1384
+ declare const UrlSchema: z.ZodString;
1385
+ declare const PhoneSchema: z.ZodString;
1386
+ type Pagination = z.infer<typeof PaginationSchema>;
1387
+ type SortOrder = z.infer<typeof SortOrderSchema>;
1388
+ type Sort = z.infer<typeof SortSchema>;
1389
+ type DateRange = z.infer<typeof DateRangeSchema>;
1390
+ type Search = z.infer<typeof SearchSchema>;
1391
+ type SuccessResponse = z.infer<typeof SuccessResponseSchema>;
1392
+ type ErrorResponse = z.infer<typeof ErrorResponseSchema>;
1393
+ /**
1394
+ * @deprecated Use `ValidationError` from `nextly/validation` instead.
1395
+ * Renamed to `LegacyValidationError` to avoid conflicts.
1396
+ */
1397
+ type LegacyValidationError = z.infer<typeof ValidationErrorSchema>;
1398
+ type BulkOperation = z.infer<typeof BulkOperationSchema>;
1399
+ type BulkOperationResponse = z.infer<typeof BulkOperationResponseSchema>;
1400
+ type FileUpload = z.infer<typeof FileUploadSchema>;
1401
+ type ImageUpload = z.infer<typeof ImageUploadSchema>;
1402
+
1403
+ /**
1404
+ * PostgreSQL `nextly_migrations` table.
1405
+ *
1406
+ * Per the F11 spec (§7), columns capture everything an operator needs
1407
+ * to debug a production deploy: structured `errorJson`, `appliedBy`
1408
+ * actor, `durationMs` for ops visibility, and a reserved `rollbackSql`
1409
+ * column for the future v2 corrective-rollback feature.
1410
+ *
1411
+ * `status` is constrained to `'applied' | 'failed'` only — the spec
1412
+ * deliberately drops `'pending'` because rows are inserted ONLY after
1413
+ * the apply attempt completes (no transient pending state on disk).
1414
+ */
1415
+ declare const nextlyMigrationsPg: drizzle_orm_pg_core.PgTableWithColumns<{
1416
+ name: "nextly_migrations";
1417
+ schema: undefined;
1418
+ columns: {
1419
+ id: drizzle_orm_pg_core.PgColumn<{
1420
+ name: "id";
1421
+ tableName: "nextly_migrations";
1422
+ dataType: "string";
1423
+ columnType: "PgUUID";
1424
+ data: string;
1425
+ driverParam: string;
1426
+ notNull: true;
1427
+ hasDefault: true;
1428
+ isPrimaryKey: true;
1429
+ isAutoincrement: false;
1430
+ hasRuntimeDefault: false;
1431
+ enumValues: undefined;
1432
+ baseColumn: never;
1433
+ identity: undefined;
1434
+ generated: undefined;
1435
+ }, {}, {}>;
1436
+ filename: drizzle_orm_pg_core.PgColumn<{
1437
+ name: "filename";
1438
+ tableName: "nextly_migrations";
1439
+ dataType: "string";
1440
+ columnType: "PgText";
1441
+ data: string;
1442
+ driverParam: string;
1443
+ notNull: true;
1444
+ hasDefault: false;
1445
+ isPrimaryKey: false;
1446
+ isAutoincrement: false;
1447
+ hasRuntimeDefault: false;
1448
+ enumValues: [string, ...string[]];
1449
+ baseColumn: never;
1450
+ identity: undefined;
1451
+ generated: undefined;
1452
+ }, {}, {}>;
1453
+ sha256: drizzle_orm_pg_core.PgColumn<{
1454
+ name: "sha256";
1455
+ tableName: "nextly_migrations";
1456
+ dataType: "string";
1457
+ columnType: "PgChar";
1458
+ data: string;
1459
+ driverParam: string;
1460
+ notNull: true;
1461
+ hasDefault: false;
1462
+ isPrimaryKey: false;
1463
+ isAutoincrement: false;
1464
+ hasRuntimeDefault: false;
1465
+ enumValues: [string, ...string[]];
1466
+ baseColumn: never;
1467
+ identity: undefined;
1468
+ generated: undefined;
1469
+ }, {}, {
1470
+ length: 64;
1471
+ }>;
1472
+ appliedAt: drizzle_orm_pg_core.PgColumn<{
1473
+ name: "applied_at";
1474
+ tableName: "nextly_migrations";
1475
+ dataType: "date";
1476
+ columnType: "PgTimestamp";
1477
+ data: Date;
1478
+ driverParam: string;
1479
+ notNull: true;
1480
+ hasDefault: true;
1481
+ isPrimaryKey: false;
1482
+ isAutoincrement: false;
1483
+ hasRuntimeDefault: false;
1484
+ enumValues: undefined;
1485
+ baseColumn: never;
1486
+ identity: undefined;
1487
+ generated: undefined;
1488
+ }, {}, {}>;
1489
+ appliedBy: drizzle_orm_pg_core.PgColumn<{
1490
+ name: "applied_by";
1491
+ tableName: "nextly_migrations";
1492
+ dataType: "string";
1493
+ columnType: "PgText";
1494
+ data: string;
1495
+ driverParam: string;
1496
+ notNull: false;
1497
+ hasDefault: false;
1498
+ isPrimaryKey: false;
1499
+ isAutoincrement: false;
1500
+ hasRuntimeDefault: false;
1501
+ enumValues: [string, ...string[]];
1502
+ baseColumn: never;
1503
+ identity: undefined;
1504
+ generated: undefined;
1505
+ }, {}, {}>;
1506
+ durationMs: drizzle_orm_pg_core.PgColumn<{
1507
+ name: "duration_ms";
1508
+ tableName: "nextly_migrations";
1509
+ dataType: "number";
1510
+ columnType: "PgInteger";
1511
+ data: number;
1512
+ driverParam: string | number;
1513
+ notNull: false;
1514
+ hasDefault: false;
1515
+ isPrimaryKey: false;
1516
+ isAutoincrement: false;
1517
+ hasRuntimeDefault: false;
1518
+ enumValues: undefined;
1519
+ baseColumn: never;
1520
+ identity: undefined;
1521
+ generated: undefined;
1522
+ }, {}, {}>;
1523
+ status: drizzle_orm_pg_core.PgColumn<{
1524
+ name: "status";
1525
+ tableName: "nextly_migrations";
1526
+ dataType: "string";
1527
+ columnType: "PgText";
1528
+ data: MigrationRecordStatus;
1529
+ driverParam: string;
1530
+ notNull: true;
1531
+ hasDefault: false;
1532
+ isPrimaryKey: false;
1533
+ isAutoincrement: false;
1534
+ hasRuntimeDefault: false;
1535
+ enumValues: [string, ...string[]];
1536
+ baseColumn: never;
1537
+ identity: undefined;
1538
+ generated: undefined;
1539
+ }, {}, {
1540
+ $type: MigrationRecordStatus;
1541
+ }>;
1542
+ errorJson: drizzle_orm_pg_core.PgColumn<{
1543
+ name: "error_json";
1544
+ tableName: "nextly_migrations";
1545
+ dataType: "json";
1546
+ columnType: "PgJsonb";
1547
+ data: unknown;
1548
+ driverParam: unknown;
1549
+ notNull: false;
1550
+ hasDefault: false;
1551
+ isPrimaryKey: false;
1552
+ isAutoincrement: false;
1553
+ hasRuntimeDefault: false;
1554
+ enumValues: undefined;
1555
+ baseColumn: never;
1556
+ identity: undefined;
1557
+ generated: undefined;
1558
+ }, {}, {}>;
1559
+ rollbackSql: drizzle_orm_pg_core.PgColumn<{
1560
+ name: "rollback_sql";
1561
+ tableName: "nextly_migrations";
1562
+ dataType: "string";
1563
+ columnType: "PgText";
1564
+ data: string;
1565
+ driverParam: string;
1566
+ notNull: false;
1567
+ hasDefault: false;
1568
+ isPrimaryKey: false;
1569
+ isAutoincrement: false;
1570
+ hasRuntimeDefault: false;
1571
+ enumValues: [string, ...string[]];
1572
+ baseColumn: never;
1573
+ identity: undefined;
1574
+ generated: undefined;
1575
+ }, {}, {}>;
1576
+ };
1577
+ dialect: "pg";
1578
+ }>;
1579
+ /** Full row type for SELECT queries. */
1580
+ type NextlyMigrationPg = typeof nextlyMigrationsPg.$inferSelect;
1581
+ /** Insert shape for INSERT queries. `id` and `appliedAt` have defaults. */
1582
+ type NextlyMigrationInsertPg = typeof nextlyMigrationsPg.$inferInsert;
1583
+
1584
+ /**
1585
+ * MySQL `nextly_migrations` table.
1586
+ *
1587
+ * Mirrors the PG schema with dialect-appropriate types:
1588
+ * - `uuid` → `varchar(36)` with client-side `crypto.randomUUID()`.
1589
+ * - `timestamptz` → `datetime` (MySQL stores in DB session timezone;
1590
+ * the app layer is responsible for UTC normalization).
1591
+ * - `jsonb` → `json` (MySQL 5.7+ native JSON column).
1592
+ *
1593
+ * MySQL 8.0.16+ supports CHECK constraints (per F17 minimum 8.0+).
1594
+ */
1595
+ declare const nextlyMigrationsMysql: drizzle_orm_mysql_core.MySqlTableWithColumns<{
1596
+ name: "nextly_migrations";
1597
+ schema: undefined;
1598
+ columns: {
1599
+ id: drizzle_orm_mysql_core.MySqlColumn<{
1600
+ name: "id";
1601
+ tableName: "nextly_migrations";
1602
+ dataType: "string";
1603
+ columnType: "MySqlVarChar";
1604
+ data: string;
1605
+ driverParam: string | number;
1606
+ notNull: true;
1607
+ hasDefault: true;
1608
+ isPrimaryKey: true;
1609
+ isAutoincrement: false;
1610
+ hasRuntimeDefault: true;
1611
+ enumValues: [string, ...string[]];
1612
+ baseColumn: never;
1613
+ identity: undefined;
1614
+ generated: undefined;
1615
+ }, {}, {}>;
1616
+ filename: drizzle_orm_mysql_core.MySqlColumn<{
1617
+ name: "filename";
1618
+ tableName: "nextly_migrations";
1619
+ dataType: "string";
1620
+ columnType: "MySqlVarChar";
1621
+ data: string;
1622
+ driverParam: string | number;
1623
+ notNull: true;
1624
+ hasDefault: false;
1625
+ isPrimaryKey: false;
1626
+ isAutoincrement: false;
1627
+ hasRuntimeDefault: false;
1628
+ enumValues: [string, ...string[]];
1629
+ baseColumn: never;
1630
+ identity: undefined;
1631
+ generated: undefined;
1632
+ }, {}, {}>;
1633
+ sha256: drizzle_orm_mysql_core.MySqlColumn<{
1634
+ name: "sha256";
1635
+ tableName: "nextly_migrations";
1636
+ dataType: "string";
1637
+ columnType: "MySqlChar";
1638
+ data: string;
1639
+ driverParam: string | number;
1640
+ notNull: true;
1641
+ hasDefault: false;
1642
+ isPrimaryKey: false;
1643
+ isAutoincrement: false;
1644
+ hasRuntimeDefault: false;
1645
+ enumValues: [string, ...string[]];
1646
+ baseColumn: never;
1647
+ identity: undefined;
1648
+ generated: undefined;
1649
+ }, {}, {
1650
+ length: 64;
1651
+ }>;
1652
+ appliedAt: drizzle_orm_mysql_core.MySqlColumn<{
1653
+ name: "applied_at";
1654
+ tableName: "nextly_migrations";
1655
+ dataType: "date";
1656
+ columnType: "MySqlDateTime";
1657
+ data: Date;
1658
+ driverParam: string | number;
1659
+ notNull: true;
1660
+ hasDefault: true;
1661
+ isPrimaryKey: false;
1662
+ isAutoincrement: false;
1663
+ hasRuntimeDefault: true;
1664
+ enumValues: undefined;
1665
+ baseColumn: never;
1666
+ identity: undefined;
1667
+ generated: undefined;
1668
+ }, {}, {}>;
1669
+ appliedBy: drizzle_orm_mysql_core.MySqlColumn<{
1670
+ name: "applied_by";
1671
+ tableName: "nextly_migrations";
1672
+ dataType: "string";
1673
+ columnType: "MySqlVarChar";
1674
+ data: string;
1675
+ driverParam: string | number;
1676
+ notNull: false;
1677
+ hasDefault: false;
1678
+ isPrimaryKey: false;
1679
+ isAutoincrement: false;
1680
+ hasRuntimeDefault: false;
1681
+ enumValues: [string, ...string[]];
1682
+ baseColumn: never;
1683
+ identity: undefined;
1684
+ generated: undefined;
1685
+ }, {}, {}>;
1686
+ durationMs: drizzle_orm_mysql_core.MySqlColumn<{
1687
+ name: "duration_ms";
1688
+ tableName: "nextly_migrations";
1689
+ dataType: "number";
1690
+ columnType: "MySqlInt";
1691
+ data: number;
1692
+ driverParam: string | number;
1693
+ notNull: false;
1694
+ hasDefault: false;
1695
+ isPrimaryKey: false;
1696
+ isAutoincrement: false;
1697
+ hasRuntimeDefault: false;
1698
+ enumValues: undefined;
1699
+ baseColumn: never;
1700
+ identity: undefined;
1701
+ generated: undefined;
1702
+ }, {}, {}>;
1703
+ status: drizzle_orm_mysql_core.MySqlColumn<{
1704
+ name: "status";
1705
+ tableName: "nextly_migrations";
1706
+ dataType: "string";
1707
+ columnType: "MySqlVarChar";
1708
+ data: MigrationRecordStatus;
1709
+ driverParam: string | number;
1710
+ notNull: true;
1711
+ hasDefault: false;
1712
+ isPrimaryKey: false;
1713
+ isAutoincrement: false;
1714
+ hasRuntimeDefault: false;
1715
+ enumValues: [string, ...string[]];
1716
+ baseColumn: never;
1717
+ identity: undefined;
1718
+ generated: undefined;
1719
+ }, {}, {
1720
+ $type: MigrationRecordStatus;
1721
+ }>;
1722
+ errorJson: drizzle_orm_mysql_core.MySqlColumn<{
1723
+ name: "error_json";
1724
+ tableName: "nextly_migrations";
1725
+ dataType: "json";
1726
+ columnType: "MySqlJson";
1727
+ data: unknown;
1728
+ driverParam: string;
1729
+ notNull: false;
1730
+ hasDefault: false;
1731
+ isPrimaryKey: false;
1732
+ isAutoincrement: false;
1733
+ hasRuntimeDefault: false;
1734
+ enumValues: undefined;
1735
+ baseColumn: never;
1736
+ identity: undefined;
1737
+ generated: undefined;
1738
+ }, {}, {}>;
1739
+ rollbackSql: drizzle_orm_mysql_core.MySqlColumn<{
1740
+ name: "rollback_sql";
1741
+ tableName: "nextly_migrations";
1742
+ dataType: "string";
1743
+ columnType: "MySqlText";
1744
+ data: string;
1745
+ driverParam: string;
1746
+ notNull: false;
1747
+ hasDefault: false;
1748
+ isPrimaryKey: false;
1749
+ isAutoincrement: false;
1750
+ hasRuntimeDefault: false;
1751
+ enumValues: [string, ...string[]];
1752
+ baseColumn: never;
1753
+ identity: undefined;
1754
+ generated: undefined;
1755
+ }, {}, {}>;
1756
+ };
1757
+ dialect: "mysql";
1758
+ }>;
1759
+ type NextlyMigrationMysql = typeof nextlyMigrationsMysql.$inferSelect;
1760
+ type NextlyMigrationInsertMysql = typeof nextlyMigrationsMysql.$inferInsert;
1761
+
1762
+ /**
1763
+ * SQLite `nextly_migrations` table.
1764
+ *
1765
+ * Mirrors the PG schema with dialect-appropriate types:
1766
+ * - `uuid` → `text` with client-side `crypto.randomUUID()`.
1767
+ * - `timestamptz` → `integer` (Unix epoch ms; SQLite has no native
1768
+ * timestamp; we store ms-since-epoch for sub-second precision).
1769
+ * - `jsonb` → `text` (JSON-encoded; readers JSON.parse on access).
1770
+ *
1771
+ * SQLite supports CHECK constraints on every supported version
1772
+ * (3.38+ per F17), so the two-state lifecycle is enforced at the DB.
1773
+ */
1774
+ declare const nextlyMigrationsSqlite: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
1775
+ name: "nextly_migrations";
1776
+ schema: undefined;
1777
+ columns: {
1778
+ id: drizzle_orm_sqlite_core.SQLiteColumn<{
1779
+ name: "id";
1780
+ tableName: "nextly_migrations";
1781
+ dataType: "string";
1782
+ columnType: "SQLiteText";
1783
+ data: string;
1784
+ driverParam: string;
1785
+ notNull: true;
1786
+ hasDefault: true;
1787
+ isPrimaryKey: true;
1788
+ isAutoincrement: false;
1789
+ hasRuntimeDefault: true;
1790
+ enumValues: [string, ...string[]];
1791
+ baseColumn: never;
1792
+ identity: undefined;
1793
+ generated: undefined;
1794
+ }, {}, {
1795
+ length: number | undefined;
1796
+ }>;
1797
+ filename: drizzle_orm_sqlite_core.SQLiteColumn<{
1798
+ name: "filename";
1799
+ tableName: "nextly_migrations";
1800
+ dataType: "string";
1801
+ columnType: "SQLiteText";
1802
+ data: string;
1803
+ driverParam: string;
1804
+ notNull: true;
1805
+ hasDefault: false;
1806
+ isPrimaryKey: false;
1807
+ isAutoincrement: false;
1808
+ hasRuntimeDefault: false;
1809
+ enumValues: [string, ...string[]];
1810
+ baseColumn: never;
1811
+ identity: undefined;
1812
+ generated: undefined;
1813
+ }, {}, {
1814
+ length: number | undefined;
1815
+ }>;
1816
+ sha256: drizzle_orm_sqlite_core.SQLiteColumn<{
1817
+ name: "sha256";
1818
+ tableName: "nextly_migrations";
1819
+ dataType: "string";
1820
+ columnType: "SQLiteText";
1821
+ data: string;
1822
+ driverParam: string;
1823
+ notNull: true;
1824
+ hasDefault: false;
1825
+ isPrimaryKey: false;
1826
+ isAutoincrement: false;
1827
+ hasRuntimeDefault: false;
1828
+ enumValues: [string, ...string[]];
1829
+ baseColumn: never;
1830
+ identity: undefined;
1831
+ generated: undefined;
1832
+ }, {}, {
1833
+ length: number | undefined;
1834
+ }>;
1835
+ appliedAt: drizzle_orm_sqlite_core.SQLiteColumn<{
1836
+ name: "applied_at";
1837
+ tableName: "nextly_migrations";
1838
+ dataType: "date";
1839
+ columnType: "SQLiteTimestamp";
1840
+ data: Date;
1841
+ driverParam: number;
1842
+ notNull: true;
1843
+ hasDefault: true;
1844
+ isPrimaryKey: false;
1845
+ isAutoincrement: false;
1846
+ hasRuntimeDefault: true;
1847
+ enumValues: undefined;
1848
+ baseColumn: never;
1849
+ identity: undefined;
1850
+ generated: undefined;
1851
+ }, {}, {}>;
1852
+ appliedBy: drizzle_orm_sqlite_core.SQLiteColumn<{
1853
+ name: "applied_by";
1854
+ tableName: "nextly_migrations";
1855
+ dataType: "string";
1856
+ columnType: "SQLiteText";
1857
+ data: string;
1858
+ driverParam: string;
1859
+ notNull: false;
1860
+ hasDefault: false;
1861
+ isPrimaryKey: false;
1862
+ isAutoincrement: false;
1863
+ hasRuntimeDefault: false;
1864
+ enumValues: [string, ...string[]];
1865
+ baseColumn: never;
1866
+ identity: undefined;
1867
+ generated: undefined;
1868
+ }, {}, {
1869
+ length: number | undefined;
1870
+ }>;
1871
+ durationMs: drizzle_orm_sqlite_core.SQLiteColumn<{
1872
+ name: "duration_ms";
1873
+ tableName: "nextly_migrations";
1874
+ dataType: "number";
1875
+ columnType: "SQLiteInteger";
1876
+ data: number;
1877
+ driverParam: number;
1878
+ notNull: false;
1879
+ hasDefault: false;
1880
+ isPrimaryKey: false;
1881
+ isAutoincrement: false;
1882
+ hasRuntimeDefault: false;
1883
+ enumValues: undefined;
1884
+ baseColumn: never;
1885
+ identity: undefined;
1886
+ generated: undefined;
1887
+ }, {}, {}>;
1888
+ status: drizzle_orm_sqlite_core.SQLiteColumn<{
1889
+ name: "status";
1890
+ tableName: "nextly_migrations";
1891
+ dataType: "string";
1892
+ columnType: "SQLiteText";
1893
+ data: MigrationRecordStatus;
1894
+ driverParam: string;
1895
+ notNull: true;
1896
+ hasDefault: false;
1897
+ isPrimaryKey: false;
1898
+ isAutoincrement: false;
1899
+ hasRuntimeDefault: false;
1900
+ enumValues: [string, ...string[]];
1901
+ baseColumn: never;
1902
+ identity: undefined;
1903
+ generated: undefined;
1904
+ }, {}, {
1905
+ length: number | undefined;
1906
+ $type: MigrationRecordStatus;
1907
+ }>;
1908
+ errorJson: drizzle_orm_sqlite_core.SQLiteColumn<{
1909
+ name: "error_json";
1910
+ tableName: "nextly_migrations";
1911
+ dataType: "string";
1912
+ columnType: "SQLiteText";
1913
+ data: string;
1914
+ driverParam: string;
1915
+ notNull: false;
1916
+ hasDefault: false;
1917
+ isPrimaryKey: false;
1918
+ isAutoincrement: false;
1919
+ hasRuntimeDefault: false;
1920
+ enumValues: [string, ...string[]];
1921
+ baseColumn: never;
1922
+ identity: undefined;
1923
+ generated: undefined;
1924
+ }, {}, {
1925
+ length: number | undefined;
1926
+ }>;
1927
+ rollbackSql: drizzle_orm_sqlite_core.SQLiteColumn<{
1928
+ name: "rollback_sql";
1929
+ tableName: "nextly_migrations";
1930
+ dataType: "string";
1931
+ columnType: "SQLiteText";
1932
+ data: string;
1933
+ driverParam: string;
1934
+ notNull: false;
1935
+ hasDefault: false;
1936
+ isPrimaryKey: false;
1937
+ isAutoincrement: false;
1938
+ hasRuntimeDefault: false;
1939
+ enumValues: [string, ...string[]];
1940
+ baseColumn: never;
1941
+ identity: undefined;
1942
+ generated: undefined;
1943
+ }, {}, {
1944
+ length: number | undefined;
1945
+ }>;
1946
+ };
1947
+ dialect: "sqlite";
1948
+ }>;
1949
+ type NextlyMigrationSqlite = typeof nextlyMigrationsSqlite.$inferSelect;
1950
+ type NextlyMigrationInsertSqlite = typeof nextlyMigrationsSqlite.$inferInsert;
1951
+
1952
+ /**
1953
+ * The three token types that determine how permissions are resolved at request time.
1954
+ * - "read-only" — resolves to the creator's read-* permissions only
1955
+ * - "full-access" — resolves to the creator's full permission set
1956
+ * - "role-based" — resolves to the permissions of the selected role
1957
+ */
1958
+ declare const ApiKeyTokenTypeSchema: z.ZodEnum<{
1959
+ "role-based": "role-based";
1960
+ "read-only": "read-only";
1961
+ "full-access": "full-access";
1962
+ }>;
1963
+ /**
1964
+ * Token duration options. "unlimited" means the key never expires.
1965
+ */
1966
+ declare const ExpiresInSchema: z.ZodEnum<{
1967
+ "7d": "7d";
1968
+ "30d": "30d";
1969
+ "90d": "90d";
1970
+ unlimited: "unlimited";
1971
+ }>;
1972
+ /**
1973
+ * Validates the request body for POST /api/api-keys.
1974
+ *
1975
+ * Refinement rules:
1976
+ * - `roleId` is required when `tokenType === "role-based"`
1977
+ * - `roleId` must be absent (undefined) when `tokenType` is not "role-based"
1978
+ */
1979
+ declare const CreateApiKeySchema: z.ZodObject<{
1980
+ name: z.ZodString;
1981
+ description: z.ZodOptional<z.ZodString>;
1982
+ tokenType: z.ZodEnum<{
1983
+ "role-based": "role-based";
1984
+ "read-only": "read-only";
1985
+ "full-access": "full-access";
1986
+ }>;
1987
+ roleId: z.ZodOptional<z.ZodString>;
1988
+ expiresIn: z.ZodEnum<{
1989
+ "7d": "7d";
1990
+ "30d": "30d";
1991
+ "90d": "90d";
1992
+ unlimited: "unlimited";
1993
+ }>;
1994
+ }, z.core.$strip>;
1995
+ /**
1996
+ * Validates the request body for PATCH /api/api-keys/:id.
1997
+ *
1998
+ * Only name and description may be updated. Token type, role, and duration
1999
+ * are immutable — revoke and recreate to change them.
2000
+ */
2001
+ declare const UpdateApiKeySchema: z.ZodObject<{
2002
+ name: z.ZodOptional<z.ZodString>;
2003
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
2004
+ }, z.core.$strip>;
2005
+ type ApiKeyTokenTypeEnum = z.infer<typeof ApiKeyTokenTypeSchema>;
2006
+ type ExpiresInEnum = z.infer<typeof ExpiresInSchema>;
2007
+ type CreateApiKey = z.infer<typeof CreateApiKeySchema>;
2008
+ type UpdateApiKey = z.infer<typeof UpdateApiKeySchema>;
2009
+
2010
+ /**
2011
+ * Database Lifecycle Hooks - Public API for NPM Package Consumers
2012
+ *
2013
+ * This module provides a clean, user-friendly API for registering and
2014
+ * managing database lifecycle hooks in Next.js 16 applications.
2015
+ *
2016
+ * **Usage in Next.js App:**
2017
+ * ```typescript
2018
+ * // app/db/hooks.ts
2019
+ * import { registerHook } from 'nextly';
2020
+ * import bcrypt from 'bcryptjs';
2021
+ *
2022
+ * // Hash password before creating user
2023
+ * registerHook('beforeCreate', 'users', async (context) => {
2024
+ * if (context.data?.password) {
2025
+ * const hashed = await bcrypt.hash(context.data.password, 10);
2026
+ * return { ...context.data, password: hashed };
2027
+ * }
2028
+ * return context.data;
2029
+ * });
2030
+ *
2031
+ * // Send welcome email after user creation
2032
+ * registerHook('afterCreate', 'users', async (context) => {
2033
+ * await sendWelcomeEmail(context.data.email);
2034
+ * });
2035
+ * ```
2036
+ *
2037
+ * @module hooks
2038
+ * @since 1.0.0
2039
+ */
2040
+
2041
+ /**
2042
+ * Register a database lifecycle hook
2043
+ *
2044
+ * Hooks allow you to run custom logic before/after database operations.
2045
+ * They are executed in the order they are registered (FIFO).
2046
+ *
2047
+ * **Hook Types:**
2048
+ * - `beforeCreate` - Run before creating a record (can modify data)
2049
+ * - `afterCreate` - Run after creating a record (for side effects)
2050
+ * - `beforeUpdate` - Run before updating a record (can modify data)
2051
+ * - `afterUpdate` - Run after updating a record (for side effects)
2052
+ * - `beforeDelete` - Run before deleting a record (can prevent deletion)
2053
+ * - `afterDelete` - Run after deleting a record (for cleanup)
2054
+ * - `beforeRead` - Run before reading records (can modify query)
2055
+ * - `afterRead` - Run after reading records (can transform data)
2056
+ *
2057
+ * @param hookType - Type of hook (e.g., 'beforeCreate', 'afterUpdate')
2058
+ * @param collection - Collection name or '*' for global hooks
2059
+ * @param handler - Hook function to execute
2060
+ *
2061
+ * @example
2062
+ * ```typescript
2063
+ * // Auto-generate slug from title
2064
+ * registerHook('beforeCreate', 'posts', (context) => {
2065
+ * return {
2066
+ * ...context.data,
2067
+ * slug: slugify(context.data.title)
2068
+ * };
2069
+ * });
2070
+ *
2071
+ * // Send notification after post creation
2072
+ * registerHook('afterCreate', 'posts', async (context) => {
2073
+ * await notifySubscribers(context.data);
2074
+ * });
2075
+ *
2076
+ * // Global hook for all collections
2077
+ * registerHook('afterCreate', '*', async (context) => {
2078
+ * console.log(`Created ${context.collection}:`, context.data.id);
2079
+ * });
2080
+ * ```
2081
+ */
2082
+ declare function registerHook<T = any>(hookType: HookType, collection: string, handler: HookHandler<T>): void;
2083
+ /**
2084
+ * Unregister a specific database lifecycle hook
2085
+ *
2086
+ * Removes the exact handler function from the registry.
2087
+ * Useful for cleanup or dynamically enabling/disabling hooks.
2088
+ *
2089
+ * @param hookType - Type of hook
2090
+ * @param collection - Collection name or '*'
2091
+ * @param handler - The exact handler function to remove
2092
+ *
2093
+ * @example
2094
+ * ```typescript
2095
+ * const myHook = async (context) => {
2096
+ * // Hook logic
2097
+ * };
2098
+ *
2099
+ * registerHook('beforeCreate', 'posts', myHook);
2100
+ *
2101
+ * // Later, remove the hook
2102
+ * unregisterHook('beforeCreate', 'posts', myHook);
2103
+ * ```
2104
+ */
2105
+ declare function unregisterHook(hookType: HookType, collection: string, handler: HookHandler): void;
2106
+ /**
2107
+ * Clear all registered hooks
2108
+ *
2109
+ * Removes all hooks for all collections.
2110
+ * Primarily used for testing cleanup.
2111
+ *
2112
+ * @example
2113
+ * ```typescript
2114
+ * // In test cleanup
2115
+ * afterEach(() => {
2116
+ * clearAllHooks();
2117
+ * });
2118
+ * ```
2119
+ */
2120
+ declare function clearAllHooks(): void;
2121
+ /**
2122
+ * Check if hooks are registered for a collection/hook type
2123
+ *
2124
+ * Returns true if any hooks (global or collection-specific) are registered.
2125
+ * Useful for conditional logic or debugging.
2126
+ *
2127
+ * @param hookType - Type of hook to check
2128
+ * @param collection - Collection name
2129
+ * @returns True if hooks are registered
2130
+ *
2131
+ * @example
2132
+ * ```typescript
2133
+ * if (hasHooks('beforeCreate', 'users')) {
2134
+ * console.log('User creation hooks are active');
2135
+ * }
2136
+ * ```
2137
+ */
2138
+ declare function hasHooks(hookType: HookType, collection: string): boolean;
2139
+ /**
2140
+ * Get count of registered hooks
2141
+ *
2142
+ * Returns the number of hooks registered for a specific type/collection.
2143
+ * Useful for debugging and monitoring.
2144
+ *
2145
+ * @param hookType - Type of hook
2146
+ * @param collection - Collection name or '*'
2147
+ * @returns Number of registered hooks
2148
+ *
2149
+ * @example
2150
+ * ```typescript
2151
+ * const count = getHookCount('beforeCreate', 'posts');
2152
+ * console.log(`${count} beforeCreate hooks for posts`);
2153
+ * ```
2154
+ */
2155
+ declare function getHookCount(hookType: HookType, collection: string): number;
2156
+
2157
+ /**
2158
+ * Register Collection Hooks
2159
+ *
2160
+ * Utility to register hooks defined in code-first collection configurations
2161
+ * with the global HookRegistry. This bridges the gap between the declarative
2162
+ * hook definitions in `defineCollection()` and the runtime hook execution system.
2163
+ *
2164
+ * @module hooks/register-collection-hooks
2165
+ * @since 1.0.0
2166
+ *
2167
+ * @example
2168
+ * ```typescript
2169
+ * import { registerCollectionHooks } from 'nextly/hooks';
2170
+ * import { loadConfig } from 'nextly/cli/utils/config-loader';
2171
+ *
2172
+ * // During app initialization
2173
+ * const { config } = await loadConfig();
2174
+ * const result = registerCollectionHooks(config.collections);
2175
+ *
2176
+ * console.log(`Registered ${result.totalHooks} hooks for ${result.collections.length} collections`);
2177
+ * ```
2178
+ */
2179
+
2180
+ /**
2181
+ * Result of registering collection hooks
2182
+ */
2183
+ interface RegisterCollectionHooksResult {
2184
+ /**
2185
+ * Collection slugs that had hooks registered
2186
+ */
2187
+ collections: string[];
2188
+ /**
2189
+ * Total number of hooks registered
2190
+ */
2191
+ totalHooks: number;
2192
+ /**
2193
+ * Breakdown of hooks registered per collection
2194
+ */
2195
+ details: {
2196
+ collection: string;
2197
+ hooks: {
2198
+ type: string;
2199
+ count: number;
2200
+ }[];
2201
+ }[];
2202
+ }
2203
+ /**
2204
+ * Register hooks from collection configurations with the global HookRegistry.
2205
+ *
2206
+ * This function takes an array of collection configurations (from `defineCollection()`)
2207
+ * and registers all their hooks with the global hook registry. This enables the hooks
2208
+ * to be executed during CRUD operations.
2209
+ *
2210
+ * **When to call:**
2211
+ * Call this function during application initialization, after loading the config
2212
+ * but before handling any requests.
2213
+ *
2214
+ * **Hook Mapping:**
2215
+ * Collection hooks use semantic names that map to specific registry hooks:
2216
+ * - `beforeChange` → `beforeCreate` and `beforeUpdate`
2217
+ * - `afterChange` → `afterCreate` and `afterUpdate`
2218
+ * - `beforeValidate` → `beforeCreate` and `beforeUpdate` (runs first)
2219
+ * - Other hooks map directly (beforeRead, afterRead, beforeDelete, afterDelete)
2220
+ *
2221
+ * @param collections - Array of collection configurations from `defineCollection()`
2222
+ * @param registry - Optional HookRegistry instance (defaults to global registry)
2223
+ * @returns Result object with registration statistics
2224
+ *
2225
+ * @example
2226
+ * ```typescript
2227
+ * import { registerCollectionHooks } from 'nextly/hooks';
2228
+ * import postsCollection from './collections/posts';
2229
+ * import usersCollection from './collections/users';
2230
+ *
2231
+ * const result = registerCollectionHooks([postsCollection, usersCollection]);
2232
+ *
2233
+ * console.log(`Registered hooks for: ${result.collections.join(', ')}`);
2234
+ * // Output: "Registered hooks for: posts, users"
2235
+ * ```
2236
+ *
2237
+ * @example
2238
+ * ```typescript
2239
+ * // With loaded config
2240
+ * import { registerCollectionHooks } from 'nextly/hooks';
2241
+ * import { loadConfig } from 'nextly/cli/utils/config-loader';
2242
+ *
2243
+ * async function initializeApp() {
2244
+ * const { config } = await loadConfig();
2245
+ *
2246
+ * // Register hooks from all collections in config
2247
+ * const hookResult = registerCollectionHooks(config.collections);
2248
+ *
2249
+ * console.log(`Initialized ${hookResult.totalHooks} hooks`);
2250
+ * }
2251
+ * ```
2252
+ */
2253
+ declare function registerCollectionHooks(collections: CollectionConfig[], registry?: HookRegistry): RegisterCollectionHooksResult;
2254
+ /**
2255
+ * Clear all hooks for a specific collection.
2256
+ *
2257
+ * Useful when re-registering hooks after a config change (e.g., in watch mode).
2258
+ *
2259
+ * @param collectionSlug - The collection slug to clear hooks for
2260
+ * @param registry - Optional HookRegistry instance (defaults to global registry)
2261
+ */
2262
+ declare function clearCollectionHooks(collectionSlug: string, registry?: HookRegistry): void;
2263
+ /**
2264
+ * Re-register hooks for collections.
2265
+ *
2266
+ * Clears existing hooks for the given collections and registers new ones.
2267
+ * Useful for hot-reload scenarios in development mode.
2268
+ *
2269
+ * @param collections - Array of collection configurations
2270
+ * @param registry - Optional HookRegistry instance (defaults to global registry)
2271
+ * @returns Result object with registration statistics
2272
+ */
2273
+ declare function reregisterCollectionHooks(collections: CollectionConfig[], registry?: HookRegistry): RegisterCollectionHooksResult;
2274
+
2275
+ /**
2276
+ * Nextly Initialization — Service Config Builder
2277
+ *
2278
+ * Merges caller-provided configuration with the loaded `nextly.config.ts`
2279
+ * into a final `NextlyServiceConfig` passed to the DI container.
2280
+ *
2281
+ * Extracted from `init.ts` so initialization orchestration can stay
2282
+ * focused on cache/lifecycle concerns.
2283
+ *
2284
+ * @module init/build-service-config
2285
+ */
2286
+
2287
+ /**
2288
+ * Configuration options for getNextly().
2289
+ *
2290
+ * Extends NextlyServiceConfig with a REQUIRED `config` property carrying the
2291
+ * loaded `nextly.config.ts`. It mirrors Payload's `getPayload({ config })`
2292
+ * contract: passing config on every call eliminates a class of "I forgot the
2293
+ * wrapper" bugs where a stray import bypassed the project-local wrapper and silently
2294
+ * bootstrapped an empty collections registry.
2295
+ *
2296
+ * Internal handlers that just need the cached singleton (post-init) should
2297
+ * call `getCachedNextly()` instead.
2298
+ */
2299
+ interface GetNextlyOptions extends Partial<NextlyServiceConfig> {
2300
+ /**
2301
+ * Pre-loaded Nextly configuration from nextly.config.ts. Required.
2302
+ *
2303
+ * The recommended import is via the `@nextly-config` TypeScript path
2304
+ * alias auto-generated by `create-nextly-app`:
2305
+ *
2306
+ * @example
2307
+ * ```typescript
2308
+ * import { getNextly } from 'nextly';
2309
+ * import config from '@nextly-config';
2310
+ *
2311
+ * const nextly = await getNextly({ config });
2312
+ * ```
2313
+ */
2314
+ config: SanitizedNextlyConfig;
2315
+ }
2316
+
2317
+ /**
2318
+ * Nextly Instance Type Definition
2319
+ *
2320
+ * Defines the public `Nextly` interface exposed by `getNextly()`.
2321
+ * Extracted from `init.ts` to keep the initialization orchestration file
2322
+ * focused on lifecycle/cache concerns.
2323
+ *
2324
+ * The interface is re-exported from `../init.ts` so all existing imports
2325
+ * like `import type { Nextly } from "nextly"` continue to work.
2326
+ *
2327
+ * @module init/nextly-instance
2328
+ */
2329
+
2330
+ /**
2331
+ * Nextly instance - provides access to all services and APIs.
2332
+ *
2333
+ * This is the main interface for interacting with Nextly. It provides
2334
+ * direct access to all core services and the database adapter.
2335
+ *
2336
+ * The instance is cached as a singleton, so multiple calls to `getNextly()`
2337
+ * will return the same instance.
2338
+ *
2339
+ * **Direct API Methods:**
2340
+ * - `find()`, `findByID()`, `create()`, `update()`, `delete()`
2341
+ * - `count()`, `bulkDelete()`, `duplicate()`
2342
+ * - `findSingle()`, `updateSingle()`
2343
+ *
2344
+ * **Service Accessors:**
2345
+ * - `collections`, `users`, `media`, `storage`, `adapter`
2346
+ */
2347
+ interface Nextly {
2348
+ /**
2349
+ * Find multiple documents in a collection.
2350
+ *
2351
+ * @example
2352
+ * ```typescript
2353
+ * const posts = await nextly.find({
2354
+ * collection: 'posts',
2355
+ * where: { status: { equals: 'published' } },
2356
+ * limit: 10,
2357
+ * sort: '-createdAt',
2358
+ * });
2359
+ * ```
2360
+ */
2361
+ find: <TSlug extends CollectionSlug>(args: FindArgs<TSlug>) => Promise<ListResult<DataFromCollectionSlug<TSlug>>>;
2362
+ /**
2363
+ * Find a single document by ID.
2364
+ *
2365
+ * @example
2366
+ * ```typescript
2367
+ * const post = await nextly.findByID({
2368
+ * collection: 'posts',
2369
+ * id: 'post-123',
2370
+ * });
2371
+ * ```
2372
+ */
2373
+ findByID: <TSlug extends CollectionSlug>(args: FindByIDArgs<TSlug>) => Promise<DataFromCollectionSlug<TSlug> | null>;
2374
+ /**
2375
+ * Create a new document.
2376
+ *
2377
+ * @example
2378
+ * ```typescript
2379
+ * const post = await nextly.create({
2380
+ * collection: 'posts',
2381
+ * data: { title: 'Hello', content: 'World' },
2382
+ * });
2383
+ * ```
2384
+ */
2385
+ create: <TSlug extends CollectionSlug>(args: CreateArgs<TSlug>) => Promise<MutationResult<DataFromCollectionSlug<TSlug>>>;
2386
+ /**
2387
+ * Update a document by ID.
2388
+ *
2389
+ * @example
2390
+ * ```typescript
2391
+ * const updated = await nextly.update({
2392
+ * collection: 'posts',
2393
+ * id: 'post-123',
2394
+ * data: { status: 'published' },
2395
+ * });
2396
+ * ```
2397
+ */
2398
+ update: <TSlug extends CollectionSlug>(args: UpdateArgs<TSlug>) => Promise<MutationResult<DataFromCollectionSlug<TSlug>>>;
2399
+ /**
2400
+ * Delete a document by ID or by where clause.
2401
+ *
2402
+ * the by-id path returns `{ message, item: { id } }`;
2403
+ * the by-where path keeps the legacy `DeleteResult` because it can
2404
+ * affect multiple rows.
2405
+ *
2406
+ * @example
2407
+ * ```typescript
2408
+ * const result = await nextly.delete({
2409
+ * collection: 'posts',
2410
+ * id: 'post-123',
2411
+ * });
2412
+ * ```
2413
+ */
2414
+ delete: <TSlug extends CollectionSlug = CollectionSlug>(args: DeleteArgs<TSlug>) => Promise<MutationResult<{
2415
+ id: string;
2416
+ }> | DeleteResult>;
2417
+ /**
2418
+ * Count documents matching a query.
2419
+ *
2420
+ * @example
2421
+ * ```typescript
2422
+ * //returns { total } (was { totalDocs }).
2423
+ * const { total } = await nextly.count({
2424
+ * collection: 'posts',
2425
+ * where: { status: { equals: 'published' } },
2426
+ * });
2427
+ * ```
2428
+ */
2429
+ count: (args: CountArgs) => Promise<CountResult>;
2430
+ /**
2431
+ * Bulk delete multiple documents by IDs.
2432
+ *
2433
+ * @example
2434
+ * ```typescript
2435
+ * const result = await nextly.bulkDelete({
2436
+ * collection: 'posts',
2437
+ * ids: ['post-1', 'post-2'],
2438
+ * });
2439
+ * ```
2440
+ */
2441
+ bulkDelete: (args: BulkDeleteArgs) => Promise<BulkOperationResult>;
2442
+ /**
2443
+ * Duplicate a document.
2444
+ *
2445
+ * @example
2446
+ * ```typescript
2447
+ * const copy = await nextly.duplicate({
2448
+ * collection: 'posts',
2449
+ * id: 'post-123',
2450
+ * });
2451
+ * ```
2452
+ */
2453
+ duplicate: <TSlug extends CollectionSlug>(args: DuplicateArgs<TSlug>) => Promise<MutationResult<DataFromCollectionSlug<TSlug>>>;
2454
+ /**
2455
+ * Get a Single document.
2456
+ *
2457
+ * @example
2458
+ * ```typescript
2459
+ * const settings = await nextly.findSingle({
2460
+ * slug: 'site-settings',
2461
+ * });
2462
+ * ```
2463
+ */
2464
+ findSingle: <TSlug extends SingleSlug>(args: FindSingleArgs<TSlug>) => Promise<DataFromSingleSlug<TSlug>>;
2465
+ /**
2466
+ * Update a Single document.
2467
+ *
2468
+ * @example
2469
+ * ```typescript
2470
+ * const updated = await nextly.updateSingle({
2471
+ * slug: 'site-settings',
2472
+ * data: { siteName: 'My Site' },
2473
+ * });
2474
+ * ```
2475
+ */
2476
+ updateSingle: <TSlug extends SingleSlug>(args: UpdateSingleArgs<TSlug>) => Promise<DataFromSingleSlug<TSlug>>;
2477
+ /**
2478
+ * List all registered Single type definitions.
2479
+ */
2480
+ findSingles: (args?: FindSinglesArgs) => Promise<SingleListResult>;
2481
+ /**
2482
+ * Verify user credentials and return user info.
2483
+ *
2484
+ * Since Direct API operates server-side without sessions, this simply
2485
+ * verifies credentials and returns the user object (no JWT token).
2486
+ *
2487
+ * @example
2488
+ * ```typescript
2489
+ * const result = await nextly.login({
2490
+ * email: 'user@example.com',
2491
+ * password: 'password123',
2492
+ * });
2493
+ * console.log('Logged in as:', result.user.email);
2494
+ * ```
2495
+ */
2496
+ login: (args: LoginArgs) => Promise<{
2497
+ user: Record<string, unknown>;
2498
+ }>;
2499
+ /**
2500
+ * Logout operation (no-op for Direct API).
2501
+ *
2502
+ * Since Direct API operates server-side without sessions,
2503
+ * logout is a no-op. Session management should be handled
2504
+ * at the application level.
2505
+ */
2506
+ logout: () => Promise<void>;
2507
+ /**
2508
+ * Get the current user's profile.
2509
+ *
2510
+ * Requires `user.id` to be provided since Direct API
2511
+ * doesn't have implicit session state.
2512
+ *
2513
+ * @example
2514
+ * ```typescript
2515
+ * const profile = await nextly.me({
2516
+ * user: { id: session.user.id },
2517
+ * });
2518
+ * ```
2519
+ */
2520
+ me: (args: {
2521
+ user: UserContext;
2522
+ }) => Promise<AuthResult>;
2523
+ /**
2524
+ * Update the current user's profile (name and image only).
2525
+ *
2526
+ * @example
2527
+ * ```typescript
2528
+ * const updated = await nextly.updateMe({
2529
+ * user: { id: session.user.id },
2530
+ * data: { name: 'New Name' },
2531
+ * });
2532
+ * ```
2533
+ */
2534
+ updateMe: (args: {
2535
+ user: UserContext;
2536
+ data: {
2537
+ name?: string;
2538
+ image?: string;
2539
+ };
2540
+ }) => Promise<AuthResult>;
2541
+ /**
2542
+ * Register a new user.
2543
+ *
2544
+ * @example
2545
+ * ```typescript
2546
+ * const result = await nextly.register({
2547
+ * email: 'newuser@example.com',
2548
+ * password: 'securePassword123!',
2549
+ * name: 'New User',
2550
+ * });
2551
+ * ```
2552
+ */
2553
+ register: (args: RegisterArgs) => Promise<{
2554
+ user: Record<string, unknown>;
2555
+ }>;
2556
+ /**
2557
+ * Change the current user's password.
2558
+ *
2559
+ * Requires `user.id` and current password for verification.
2560
+ *
2561
+ * @example
2562
+ * ```typescript
2563
+ * await nextly.changePassword({
2564
+ * user: { id: session.user.id },
2565
+ * currentPassword: 'oldPassword123',
2566
+ * newPassword: 'newSecurePassword456!',
2567
+ * });
2568
+ * ```
2569
+ */
2570
+ changePassword: (args: ChangePasswordArgs & {
2571
+ user: UserContext;
2572
+ }) => Promise<{
2573
+ success: true;
2574
+ }>;
2575
+ /**
2576
+ * Initiate password reset by generating a reset token.
2577
+ *
2578
+ * Returns the raw token which should be sent to the user via email.
2579
+ *
2580
+ * @example
2581
+ * ```typescript
2582
+ * const result = await nextly.forgotPassword({
2583
+ * email: 'user@example.com',
2584
+ * });
2585
+ * if (result.token) {
2586
+ * await sendResetEmail(args.email, result.token);
2587
+ * }
2588
+ * ```
2589
+ */
2590
+ forgotPassword: (args: ForgotPasswordArgs) => Promise<{
2591
+ success: true;
2592
+ token?: string;
2593
+ }>;
2594
+ /**
2595
+ * Reset password using a reset token.
2596
+ *
2597
+ * @example
2598
+ * ```typescript
2599
+ * const result = await nextly.resetPassword({
2600
+ * token: 'reset-token-from-email',
2601
+ * password: 'newSecurePassword456!',
2602
+ * });
2603
+ * ```
2604
+ */
2605
+ resetPassword: (args: ResetPasswordArgs) => Promise<{
2606
+ success: true;
2607
+ email?: string;
2608
+ }>;
2609
+ /**
2610
+ * Verify user email using a verification token.
2611
+ *
2612
+ * @example
2613
+ * ```typescript
2614
+ * const result = await nextly.verifyEmail({
2615
+ * token: 'verification-token-from-email',
2616
+ * });
2617
+ * ```
2618
+ */
2619
+ verifyEmail: (args: VerifyEmailArgs) => Promise<{
2620
+ success: true;
2621
+ email?: string;
2622
+ }>;
2623
+ /**
2624
+ * Collection service - manage collections and their entries.
2625
+ *
2626
+ * @example
2627
+ * ```typescript
2628
+ * const nextly = await getNextly(config);
2629
+ *
2630
+ * // Find documents
2631
+ * const posts = await nextly.collections.find('posts', {
2632
+ * where: { status: 'published' }
2633
+ * }, context);
2634
+ *
2635
+ * // Create document
2636
+ * const newPost = await nextly.collections.create('posts', {
2637
+ * data: { title: 'Hello World' }
2638
+ * }, context);
2639
+ * ```
2640
+ */
2641
+ collections: ServiceMap["collectionService"];
2642
+ /**
2643
+ * Users API namespace - CRUD operations for users.
2644
+ *
2645
+ * Provides direct database operations for user management without HTTP overhead.
2646
+ *
2647
+ * @example
2648
+ * ```typescript
2649
+ * const nextly = await getNextly(config);
2650
+ *
2651
+ * // Find users
2652
+ * const users = await nextly.users.find({
2653
+ * where: { role: { equals: 'admin' } },
2654
+ * limit: 10,
2655
+ * });
2656
+ *
2657
+ * // Get user by ID
2658
+ * const user = await nextly.users.findByID({ id: 'user-123' });
2659
+ *
2660
+ * // Create user
2661
+ * const newUser = await nextly.users.create({
2662
+ * email: 'user@example.com',
2663
+ * password: 'secure123',
2664
+ * data: { name: 'John Doe' },
2665
+ * });
2666
+ *
2667
+ * // Update user
2668
+ * await nextly.users.update({
2669
+ * id: 'user-123',
2670
+ * data: { name: 'Jane Doe' },
2671
+ * });
2672
+ *
2673
+ * // Delete user
2674
+ * await nextly.users.delete({ id: 'user-123' });
2675
+ * ```
2676
+ */
2677
+ users: {
2678
+ find: (args?: FindUsersArgs) => Promise<ListResult<User>>;
2679
+ findByID: (args: FindUserByIDArgs) => Promise<User | null>;
2680
+ create: (args: CreateUserArgs) => Promise<MutationResult<User>>;
2681
+ update: (args: UpdateUserArgs) => Promise<MutationResult<User>>;
2682
+ delete: (args: DeleteUserArgs) => Promise<MutationResult<{
2683
+ id: string;
2684
+ }>>;
2685
+ };
2686
+ /**
2687
+ * User service - direct access to UserService for advanced operations.
2688
+ *
2689
+ * For most use cases, prefer the `users` namespace above which provides
2690
+ * a simplified CRUD API. Use this for advanced operations like
2691
+ * authentication, password management, etc.
2692
+ *
2693
+ * @example
2694
+ * ```typescript
2695
+ * const nextly = await getNextly(config);
2696
+ *
2697
+ * // Authenticate user
2698
+ * const user = await nextly.userService.authenticate('user@example.com', 'password');
2699
+ *
2700
+ * // Change password
2701
+ * await nextly.userService.changePassword(userId, oldPass, newPass);
2702
+ * ```
2703
+ */
2704
+ userService: ServiceMap["userService"];
2705
+ /**
2706
+ * Runtime key/value flags accessor.
2707
+ *
2708
+ * Backed by the `nextly_meta` table — a small KV store for runtime
2709
+ * state that doesn't belong in collection schemas. First consumers
2710
+ * are the dashboard `SeedDemoContentCard` flags
2711
+ * (`seed.completedAt`, `seed.skippedAt`).
2712
+ *
2713
+ * Values are JSON round-tripped: callers pass and receive JS values;
2714
+ * the service handles serialisation per-dialect.
2715
+ *
2716
+ * @example
2717
+ * ```typescript
2718
+ * const nextly = await getNextly({ config });
2719
+ *
2720
+ * await nextly.meta.set("seed.completedAt", new Date().toISOString());
2721
+ * const ts = await nextly.meta.get<string>("seed.completedAt");
2722
+ * await nextly.meta.delete("seed.skippedAt");
2723
+ * const all = await nextly.meta.getAll();
2724
+ * ```
2725
+ */
2726
+ meta: ServiceMap["metaService"];
2727
+ /**
2728
+ * Media API namespace - operations for media files and folders.
2729
+ *
2730
+ * Provides direct database operations for media management without HTTP overhead.
2731
+ *
2732
+ * @example
2733
+ * ```typescript
2734
+ * const nextly = await getNextly(config);
2735
+ *
2736
+ * // Upload media
2737
+ * const media = await nextly.media.upload({
2738
+ * file: { data: buffer, name: 'image.jpg', mimetype: 'image/jpeg', size: buffer.length },
2739
+ * altText: 'My image',
2740
+ * });
2741
+ *
2742
+ * // List media
2743
+ * const files = await nextly.media.find({ folder: 'uploads', limit: 20 });
2744
+ *
2745
+ * // Get by ID
2746
+ * const file = await nextly.media.findByID({ id: 'media-123' });
2747
+ *
2748
+ * // Update metadata
2749
+ * await nextly.media.update({ id: 'media-123', data: { altText: 'Updated' } });
2750
+ *
2751
+ * // Delete
2752
+ * await nextly.media.delete({ id: 'media-123' });
2753
+ *
2754
+ * // Folders
2755
+ * const folder = await nextly.media.folders.create({ name: 'Photos' });
2756
+ * const folders = await nextly.media.folders.list();
2757
+ * ```
2758
+ */
2759
+ media: {
2760
+ upload: (args: UploadMediaArgs) => Promise<MediaFile>;
2761
+ find: (args?: FindMediaArgs) => Promise<ListResult<MediaFile>>;
2762
+ findByID: (args: FindMediaByIDArgs) => Promise<MediaFile | null>;
2763
+ update: (args: UpdateMediaArgs) => Promise<MutationResult<MediaFile>>;
2764
+ delete: (args: DeleteMediaArgs) => Promise<MutationResult<{
2765
+ id: string;
2766
+ }>>;
2767
+ bulkDelete: (args: BulkDeleteMediaArgs) => Promise<BulkOperationResult>;
2768
+ folders: {
2769
+ list: (args?: ListFoldersArgs) => Promise<MediaFolder[]>;
2770
+ create: (args: CreateFolderArgs) => Promise<MediaFolder>;
2771
+ };
2772
+ };
2773
+ /**
2774
+ * Forms API namespace - operations for forms and form submissions.
2775
+ *
2776
+ * Provides direct database operations for form management without HTTP overhead.
2777
+ * Requires the `@nextlyhq/plugin-form-builder` plugin to be installed.
2778
+ *
2779
+ * @example
2780
+ * ```typescript
2781
+ * const nextly = await getNextly(config);
2782
+ *
2783
+ * // List published forms
2784
+ * const forms = await nextly.forms.find({ status: 'published' });
2785
+ *
2786
+ * // Get form by slug
2787
+ * const form = await nextly.forms.findBySlug({ slug: 'contact-form' });
2788
+ *
2789
+ * // Submit form data
2790
+ * const result = await nextly.forms.submit({
2791
+ * form: 'contact-form',
2792
+ * data: { name: 'John', email: 'john@example.com', message: 'Hello!' },
2793
+ * });
2794
+ *
2795
+ * // Get submissions
2796
+ * const submissions = await nextly.forms.submissions({
2797
+ * form: 'contact-form',
2798
+ * limit: 20,
2799
+ * });
2800
+ * ```
2801
+ */
2802
+ forms: {
2803
+ find: (args?: FindFormsArgs) => Promise<ListResult<Record<string, unknown>>>;
2804
+ findBySlug: (args: FindFormBySlugArgs) => Promise<Record<string, unknown> | null>;
2805
+ submit: (args: SubmitFormArgs) => Promise<SubmitFormResult>;
2806
+ submissions: (args: FormSubmissionsArgs) => Promise<ListResult<Record<string, unknown>>>;
2807
+ };
2808
+ /**
2809
+ * Media service - direct access to MediaService for advanced operations.
2810
+ *
2811
+ * For most use cases, prefer the `media` namespace above which provides
2812
+ * a simplified CRUD API. Use this for advanced operations like
2813
+ * image processing, storage checks, etc.
2814
+ *
2815
+ * @example
2816
+ * ```typescript
2817
+ * const nextly = await getNextly(config);
2818
+ *
2819
+ * // Check storage type
2820
+ * const storageType = nextly.mediaService.getStorageType();
2821
+ *
2822
+ * // Move media to folder
2823
+ * await nextly.mediaService.moveToFolder('media-id', 'folder-id', context);
2824
+ * ```
2825
+ */
2826
+ mediaService: ServiceMap["mediaService"];
2827
+ /**
2828
+ * Storage manager - manage file storage with collection-specific routing.
2829
+ *
2830
+ * Provides access to storage operations with support for:
2831
+ * - Collection-specific storage backends (S3, Vercel Blob, local)
2832
+ * - Client-side upload URL generation
2833
+ * - Signed download URLs for private files
2834
+ *
2835
+ * @example
2836
+ * ```typescript
2837
+ * const nextly = await getNextly(config);
2838
+ *
2839
+ * // Upload with collection routing
2840
+ * const result = await nextly.storage.upload(buffer, {
2841
+ * filename: 'photo.jpg',
2842
+ * mimeType: 'image/jpeg',
2843
+ * collection: 'media'
2844
+ * });
2845
+ *
2846
+ * // Get client upload URL (bypasses server for large files)
2847
+ * const uploadData = await nextly.storage.getClientUploadUrl(
2848
+ * 'video.mp4',
2849
+ * 'video/mp4',
2850
+ * 'media'
2851
+ * );
2852
+ *
2853
+ * // Get signed URL for private file access
2854
+ * const signedUrl = await nextly.storage.getSignedDownloadUrl(
2855
+ * 'private/doc.pdf',
2856
+ * 'private-docs',
2857
+ * 3600 // expires in 1 hour
2858
+ * );
2859
+ * ```
2860
+ */
2861
+ storage: ServiceMap["mediaStorage"];
2862
+ /**
2863
+ * Database adapter - direct access to the database layer.
2864
+ *
2865
+ * Provides low-level database operations for advanced use cases.
2866
+ * Most applications should use the service APIs instead.
2867
+ *
2868
+ * @example
2869
+ * ```typescript
2870
+ * const nextly = await getNextly(config);
2871
+ *
2872
+ * // Check capabilities
2873
+ * const caps = nextly.adapter.getCapabilities();
2874
+ * console.log('JSONB support:', caps.supportsJsonb);
2875
+ *
2876
+ * // Run raw query (advanced)
2877
+ * const results = await nextly.adapter.select('custom_table', {
2878
+ * where: { status: 'active' }
2879
+ * });
2880
+ * ```
2881
+ */
2882
+ adapter: DrizzleAdapter;
2883
+ emailProviders: {
2884
+ find: (args?: FindEmailProvidersArgs) => Promise<ListResult<EmailProviderRecord>>;
2885
+ findByID: (args: FindEmailProviderByIDArgs) => Promise<EmailProviderRecord | null>;
2886
+ create: (args: CreateEmailProviderArgs) => Promise<MutationResult<EmailProviderRecord>>;
2887
+ update: (args: UpdateEmailProviderArgs) => Promise<MutationResult<EmailProviderRecord>>;
2888
+ delete: (args: DeleteEmailProviderArgs) => Promise<MutationResult<{
2889
+ id: string;
2890
+ }>>;
2891
+ setDefault: (args: SetDefaultProviderArgs) => Promise<EmailProviderRecord>;
2892
+ test: (args: TestEmailProviderArgs) => Promise<{
2893
+ success: boolean;
2894
+ error?: string;
2895
+ }>;
2896
+ };
2897
+ emailTemplates: {
2898
+ find: (args?: FindEmailTemplatesArgs) => Promise<ListResult<EmailTemplateRecord>>;
2899
+ findByID: (args: FindEmailTemplateByIDArgs) => Promise<EmailTemplateRecord | null>;
2900
+ findBySlug: (args: FindEmailTemplateBySlugArgs) => Promise<EmailTemplateRecord | null>;
2901
+ create: (args: CreateEmailTemplateArgs) => Promise<MutationResult<EmailTemplateRecord>>;
2902
+ update: (args: UpdateEmailTemplateArgs) => Promise<MutationResult<EmailTemplateRecord>>;
2903
+ delete: (args: DeleteEmailTemplateArgs) => Promise<MutationResult<{
2904
+ id: string;
2905
+ }>>;
2906
+ preview: (args: PreviewEmailTemplateArgs) => Promise<{
2907
+ subject: string;
2908
+ html: string;
2909
+ }>;
2910
+ getLayout: (args?: GetEmailLayoutArgs) => Promise<{
2911
+ header: string;
2912
+ footer: string;
2913
+ }>;
2914
+ updateLayout: (args: UpdateEmailLayoutArgs) => Promise<void>;
2915
+ };
2916
+ userFields: {
2917
+ find: (args?: FindUserFieldsArgs) => Promise<ListResult<UserFieldDefinitionRecord>>;
2918
+ findByID: (args: FindUserFieldByIDArgs) => Promise<UserFieldDefinitionRecord | null>;
2919
+ create: (args: CreateUserFieldArgs) => Promise<MutationResult<UserFieldDefinitionRecord>>;
2920
+ update: (args: UpdateUserFieldArgs) => Promise<MutationResult<UserFieldDefinitionRecord>>;
2921
+ delete: (args: DeleteUserFieldArgs) => Promise<MutationResult<{
2922
+ id: string;
2923
+ }>>;
2924
+ reorder: (args: ReorderUserFieldsArgs) => Promise<UserFieldDefinitionRecord[]>;
2925
+ };
2926
+ email: {
2927
+ send: (args: SendEmailArgs) => Promise<SendEmailResult>;
2928
+ sendWithTemplate: (args: SendTemplateEmailArgs) => Promise<SendEmailResult>;
2929
+ };
2930
+ /**
2931
+ * Roles API namespace - CRUD operations for RBAC roles.
2932
+ *
2933
+ * @example
2934
+ * ```typescript
2935
+ * const nextly = await getNextly(config);
2936
+ *
2937
+ * // List roles
2938
+ * const roles = await nextly.roles.find({ limit: 20 });
2939
+ *
2940
+ * // Get role by ID
2941
+ * const role = await nextly.roles.findByID({ id: 'role-123' });
2942
+ *
2943
+ * // Create a role
2944
+ * const editor = await nextly.roles.create({
2945
+ * data: { name: 'Editor', slug: 'editor', level: 10 },
2946
+ * });
2947
+ *
2948
+ * // Assign permissions to a role
2949
+ * await nextly.roles.setPermissions({
2950
+ * id: editor.id,
2951
+ * permissionIds: ['perm-1', 'perm-2'],
2952
+ * });
2953
+ * ```
2954
+ */
2955
+ roles: {
2956
+ find: (args?: FindRolesArgs) => Promise<ListResult<Role>>;
2957
+ findByID: (args: FindRoleByIDArgs) => Promise<Role>;
2958
+ create: (args: CreateRoleArgs) => Promise<MutationResult<Role>>;
2959
+ update: (args: UpdateRoleArgs) => Promise<MutationResult<Role>>;
2960
+ delete: (args: DeleteRoleArgs) => Promise<MutationResult<{
2961
+ id: string;
2962
+ }>>;
2963
+ getPermissions: (args: GetRolePermissionsArgs) => Promise<Permission[]>;
2964
+ setPermissions: (args: SetRolePermissionsArgs) => Promise<Permission[]>;
2965
+ };
2966
+ /**
2967
+ * Permissions API namespace - CRUD operations for RBAC permissions.
2968
+ *
2969
+ * @example
2970
+ * ```typescript
2971
+ * const nextly = await getNextly(config);
2972
+ *
2973
+ * // List all permissions
2974
+ * const perms = await nextly.permissions.find({ resource: 'posts' });
2975
+ *
2976
+ * // Create a permission
2977
+ * const perm = await nextly.permissions.create({
2978
+ * data: { name: 'Publish Posts', slug: 'publish-posts', action: 'update', resource: 'posts' },
2979
+ * });
2980
+ * ```
2981
+ */
2982
+ permissions: {
2983
+ find: (args?: FindPermissionsArgs) => Promise<ListResult<Permission>>;
2984
+ findByID: (args: FindPermissionByIDArgs) => Promise<Permission | null>;
2985
+ create: (args: CreatePermissionArgs) => Promise<MutationResult<Permission>>;
2986
+ delete: (args: DeletePermissionArgs) => Promise<MutationResult<{
2987
+ id: string;
2988
+ }>>;
2989
+ };
2990
+ /**
2991
+ * Access namespace - programmatic access control evaluation.
2992
+ *
2993
+ * @example
2994
+ * ```typescript
2995
+ * const nextly = await getNextly(config);
2996
+ *
2997
+ * // Check if a user can read posts
2998
+ * const canRead = await nextly.access.check({
2999
+ * userId: 'user-123',
3000
+ * resource: 'posts',
3001
+ * operation: 'read',
3002
+ * });
3003
+ * ```
3004
+ */
3005
+ access: {
3006
+ check: (args: CheckAccessArgs) => Promise<boolean>;
3007
+ };
3008
+ /**
3009
+ * Shutdown the Nextly instance and clean up resources.
3010
+ *
3011
+ * This will:
3012
+ * - Disconnect the database adapter
3013
+ * - Clear the service container
3014
+ * - Reset the cached instance
3015
+ *
3016
+ * After calling this, the next call to `getNextly()` will create
3017
+ * a new instance.
3018
+ *
3019
+ * @example
3020
+ * ```typescript
3021
+ * const nextly = await getNextly(config);
3022
+ *
3023
+ * // When shutting down
3024
+ * await nextly.shutdown();
3025
+ * ```
3026
+ */
3027
+ shutdown: () => Promise<void>;
3028
+ }
3029
+
3030
+ /**
3031
+ * Nextly Initialization
3032
+ *
3033
+ * This module provides the main entry point for initializing and accessing
3034
+ * Nextly services. `getNextly()` is the primary API, providing a cached
3035
+ * singleton instance.
3036
+ *
3037
+ * The bulky pieces that used to live here have been extracted:
3038
+ *
3039
+ * - The public `Nextly` interface is defined in `./init/nextly-instance.ts`
3040
+ * - `runPostInitTasks()` lives in `./init/post-init-tasks.ts`
3041
+ * - `buildServiceConfig()` and `GetNextlyOptions` live in
3042
+ * `./init/build-service-config.ts`
3043
+ *
3044
+ * All of those names are re-exported from this module so existing
3045
+ * imports (`import { Nextly } from "nextly"`, etc.) keep working.
3046
+ *
3047
+ * @example
3048
+ * ```typescript
3049
+ * import { getNextly } from 'nextly';
3050
+ *
3051
+ * // In your API route or server component
3052
+ * export async function GET() {
3053
+ * const nextly = await getNextly({
3054
+ * storage: myStorageAdapter,
3055
+ * imageProcessor: myImageProcessor,
3056
+ * });
3057
+ *
3058
+ * // Returns ListResult<T> = { items, meta } (Phase 4 canonical shape).
3059
+ * const posts = await nextly.find({ collection: 'posts' });
3060
+ * return Response.json(posts);
3061
+ * }
3062
+ * ```
3063
+ */
3064
+
3065
+ /**
3066
+ * Get or initialize the Nextly instance.
3067
+ *
3068
+ * Cached: subsequent calls return the same instance. The cache survives
3069
+ * Next.js HMR via `globalThis`.
3070
+ *
3071
+ * happens after validation, so even cached lookups must pass config —
3072
+ * this matches Payload's `getPayload({ config })` contract and keeps
3073
+ * the call site self-documenting. Internal handlers that just need the
3074
+ * cached singleton (post-init) should use `getCachedNextly()` instead.
3075
+ *
3076
+ * @example
3077
+ * ```typescript
3078
+ * // Recommended: use the @nextly-config path alias.
3079
+ * import { getNextly } from 'nextly';
3080
+ * import config from '@nextly-config';
3081
+ *
3082
+ * export async function GET() {
3083
+ * const nextly = await getNextly({ config });
3084
+ * // Returns ListResult<T> = { items, meta } (Phase 4 canonical shape).
3085
+ * const posts = await nextly.find({ collection: 'posts' });
3086
+ * return Response.json(posts);
3087
+ * }
3088
+ * ```
3089
+ */
3090
+ declare function getNextly(options: GetNextlyOptions): Promise<Nextly>;
3091
+ /**
3092
+ * Return the already-initialised Nextly instance from the singleton cache.
3093
+ *
3094
+ * Use this inside Nextly's own internal API handlers (anywhere under
3095
+ * `packages/nextly/src/api/*`) where the user-provided config is not in
3096
+ * scope. Throws a clear error if the singleton has not been initialised
3097
+ * yet — the typical fix is to ensure the project ships an
3098
+ * `instrumentation.ts` that calls `createRegister(config)` so init runs
3099
+ * once per worker before the first request.
3100
+ *
3101
+ * Do NOT use this in user code. User code should always call
3102
+ * `getNextly({ config })` directly.
3103
+ */
3104
+ declare function getCachedNextly(): Promise<Nextly>;
3105
+ /**
3106
+ * Create a Next.js instrumentation `register` function for Nextly.
3107
+ *
3108
+ * This is the recommended way to initialize Nextly via Next.js's
3109
+ * `instrumentation.ts` hook, which runs **once** in each server worker
3110
+ * process before the first request is handled. Calling `getNextly()`
3111
+ * here warms up the database connection and registers storage/plugins so
3112
+ * that the first page request never pays the cold-start penalty.
3113
+ *
3114
+ * @param config - Pre-loaded Nextly configuration from `nextly.config.ts`.
3115
+ * Pass the default export of your config file so storage
3116
+ * plugins and collections are registered on startup.
3117
+ * @returns An async `register()` function that satisfies the Next.js
3118
+ * instrumentation contract.
3119
+ *
3120
+ * @example
3121
+ * ```typescript
3122
+ * // instrumentation.ts (project root)
3123
+ * import { createRegister } from 'nextly';
3124
+ * import nextlyConfig from './nextly.config';
3125
+ *
3126
+ * export const register = createRegister(nextlyConfig);
3127
+ * ```
3128
+ */
3129
+ declare function createRegister(config: SanitizedNextlyConfig): () => Promise<void>;
3130
+ /**
3131
+ * Shutdown the Nextly instance and clean up resources.
3132
+ *
3133
+ * This will:
3134
+ * - Disconnect the database adapter
3135
+ * - Clear all service registrations
3136
+ * - Reset the cached Nextly instance
3137
+ *
3138
+ * After calling this, the next call to `getNextly()` will create
3139
+ * a new instance with fresh connections.
3140
+ *
3141
+ * **Use Cases:**
3142
+ * - Application shutdown (SIGTERM/SIGINT handlers)
3143
+ * - Testing (reset between tests)
3144
+ * - Hot reload scenarios
3145
+ *
3146
+ * @example
3147
+ * ```typescript
3148
+ * // Graceful shutdown on process signals
3149
+ * process.on('SIGTERM', async () => {
3150
+ * await shutdownNextly();
3151
+ * process.exit(0);
3152
+ * });
3153
+ *
3154
+ * process.on('SIGINT', async () => {
3155
+ * await shutdownNextly();
3156
+ * process.exit(0);
3157
+ * });
3158
+ * ```
3159
+ *
3160
+ * @example
3161
+ * ```typescript
3162
+ * // In tests
3163
+ * afterEach(async () => {
3164
+ * await shutdownNextly(); // Clean up between tests
3165
+ * });
3166
+ *
3167
+ * test('creates a post', async () => {
3168
+ * const nextly = await getNextly(testConfig);
3169
+ * const post = await nextly.collections.create('posts', data, context);
3170
+ * expect(post).toBeDefined();
3171
+ * });
3172
+ * ```
3173
+ *
3174
+ * @example
3175
+ * ```typescript
3176
+ * // Using the instance method
3177
+ * const nextly = await getNextly(config);
3178
+ *
3179
+ * // Later...
3180
+ * await nextly.shutdown(); // Or use shutdownNextly()
3181
+ * ```
3182
+ */
3183
+ declare function shutdownNextly(): Promise<void>;
3184
+
3185
+ type SchemaApplyErrorCode = "SCHEMA_VERSION_CONFLICT" | "PUSHSCHEMA_FAILED" | "DDL_EXECUTION_FAILED" | "CONFIRMATION_DECLINED" | "CONFIRMATION_REQUIRED_NO_TTY" | "CONNECTION_FAILED" | "UNSUPPORTED_DIALECT_VERSION" | "INTERNAL_ERROR";
3186
+
3187
+ interface DesiredSchema {
3188
+ collections: Record<string, DesiredCollection>;
3189
+ singles: Record<string, DesiredSingle>;
3190
+ components: Record<string, DesiredComponent>;
3191
+ }
3192
+ interface DesiredCollection {
3193
+ slug: string;
3194
+ tableName: string;
3195
+ fields: FieldConfig[];
3196
+ indexes?: IndexConfig[];
3197
+ /**
3198
+ * Whether the collection has Draft/Published status enabled.
3199
+ * When true, the diff input includes a `status` system column so the
3200
+ * pipeline knows to add it on first enable and drop it on disable.
3201
+ */
3202
+ status?: boolean;
3203
+ }
3204
+ interface DesiredSingle {
3205
+ slug: string;
3206
+ tableName: string;
3207
+ fields: FieldConfig[];
3208
+ indexes?: IndexConfig[];
3209
+ /** Same semantics as DesiredCollection.status. */
3210
+ status?: boolean;
3211
+ }
3212
+ interface DesiredComponent {
3213
+ slug: string;
3214
+ tableName: string;
3215
+ fields: FieldConfig[];
3216
+ indexes?: IndexConfig[];
3217
+ }
3218
+
3219
+ interface ApplySummary {
3220
+ added: number;
3221
+ removed: number;
3222
+ renamed: number;
3223
+ changed: number;
3224
+ }
3225
+ type ApplyResult = {
3226
+ success: true;
3227
+ newSchemaVersions: Record<string, number>;
3228
+ statementsExecuted: number;
3229
+ renamesApplied: number;
3230
+ durationMs: number;
3231
+ summary?: ApplySummary;
3232
+ } | {
3233
+ success: false;
3234
+ error: {
3235
+ message: string;
3236
+ code: SchemaApplyErrorCode;
3237
+ details?: unknown;
3238
+ };
3239
+ partiallyApplied?: boolean;
3240
+ durationMs: number;
3241
+ };
3242
+ type ApplyDesiredSchemaFn = (desired: DesiredSchema, source: "ui" | "code", ctx: {
3243
+ schemaVersions?: Record<string, number>;
3244
+ promptChannel: "browser" | "terminal" | "auto";
3245
+ }) => Promise<ApplyResult>;
3246
+
3247
+ interface RegistryRecord {
3248
+ slug: string;
3249
+ tableName: string;
3250
+ fields: unknown[];
3251
+ /** Optional — only collections and singles carry this; components ignore it. */
3252
+ status?: boolean;
3253
+ }
3254
+ interface RegistryReader {
3255
+ getAllCollectionsRecords(): RegistryRecord[] | Promise<RegistryRecord[]>;
3256
+ getAllSinglesRecords(): RegistryRecord[] | Promise<RegistryRecord[]>;
3257
+ getAllComponentsRecords(): RegistryRecord[] | Promise<RegistryRecord[]>;
3258
+ }
3259
+ interface DesiredSchemaOverrides {
3260
+ collections?: Record<string, DesiredCollection>;
3261
+ singles?: Record<string, DesiredSingle>;
3262
+ components?: Record<string, DesiredComponent>;
3263
+ }
3264
+ declare function buildDesiredSchemaFromRegistry(registry: RegistryReader, overrides?: DesiredSchemaOverrides): DesiredSchema;
3265
+ declare function buildDesiredSchemaFromRegistryAsync(registry: RegistryReader, overrides?: DesiredSchemaOverrides): Promise<DesiredSchema>;
3266
+
3267
+ declare const applyDesiredSchema: ApplyDesiredSchemaFn;
3268
+
3269
+ /**
3270
+ * Lightweight Dependency Injection Container
3271
+ *
3272
+ * ~50 lines, SWC-compatible (no decorators), zero external dependencies.
3273
+ *
3274
+ * Usage:
3275
+ * ```typescript
3276
+ * import { container } from 'nextly';
3277
+ *
3278
+ * // Register singleton
3279
+ * container.registerSingleton('db', () => createDatabase(config));
3280
+ *
3281
+ * // Register factory (new instance per get)
3282
+ * container.register('requestService', () => new RequestService());
3283
+ *
3284
+ * // Get service
3285
+ * const db = container.get<Database>('db');
3286
+ * ```
3287
+ */
3288
+ type Factory<T> = () => T;
3289
+ declare class Container {
3290
+ private singletons;
3291
+ private factories;
3292
+ private parent?;
3293
+ constructor(parent?: Container);
3294
+ /**
3295
+ * Register a factory that creates a new instance each time get() is called.
3296
+ */
3297
+ register<T>(name: string, factory: Factory<T>): this;
3298
+ /**
3299
+ * Register a factory that creates a singleton instance (lazily initialized).
3300
+ */
3301
+ registerSingleton<T>(name: string, factory: Factory<T>): this;
3302
+ /**
3303
+ * Get a service by name. Throws if not registered.
3304
+ */
3305
+ get<T>(name: string): T;
3306
+ /**
3307
+ * Check if a service is registered.
3308
+ */
3309
+ has(name: string): boolean;
3310
+ /**
3311
+ * Create a child scope container for request-scoped services.
3312
+ */
3313
+ createScope(): Container;
3314
+ /**
3315
+ * Clear all registrations and singletons (useful for testing).
3316
+ */
3317
+ clear(): void;
3318
+ }
3319
+ declare const container: Container;
3320
+
3321
+ /**
3322
+ * Validation Error Types
3323
+ *
3324
+ * Standardized validation error types for consistent error handling
3325
+ * across the Nextly system. Compatible with Zod error transformation.
3326
+ *
3327
+ * @module validation/types
3328
+ */
3329
+ /**
3330
+ * Standard validation error codes.
3331
+ *
3332
+ * These codes provide programmatic error identification and
3333
+ * enable type-safe error handling.
3334
+ *
3335
+ * @example
3336
+ * ```typescript
3337
+ * if (error.code === 'required') {
3338
+ * // Handle required field error
3339
+ * }
3340
+ * ```
3341
+ */
3342
+ type ValidationErrorCode = "required" | "type_error" | "invalid_type" | "min_length" | "max_length" | "too_short" | "too_long" | "pattern" | "min_value" | "max_value" | "too_small" | "too_big" | "not_integer" | "not_finite" | "invalid_email" | "invalid_url" | "invalid_uuid" | "invalid_date" | "invalid_format" | "invalid_option" | "invalid_reference" | "invalid_enum" | "unique" | "duplicate" | "min_items" | "max_items" | "invalid_array" | "invalid_object" | "unknown_key" | "invalid_file_type" | "file_too_large" | "custom";
3343
+ /**
3344
+ * All validation error codes as a const array.
3345
+ * Useful for runtime validation and iteration.
3346
+ */
3347
+ declare const VALIDATION_ERROR_CODES: readonly ["required", "type_error", "invalid_type", "min_length", "max_length", "too_short", "too_long", "pattern", "min_value", "max_value", "too_small", "too_big", "not_integer", "not_finite", "invalid_email", "invalid_url", "invalid_uuid", "invalid_date", "invalid_format", "invalid_option", "invalid_reference", "invalid_enum", "unique", "duplicate", "min_items", "max_items", "invalid_array", "invalid_object", "unknown_key", "invalid_file_type", "file_too_large", "custom"];
3348
+ /**
3349
+ * Individual validation error.
3350
+ *
3351
+ * Represents a single validation failure with its location,
3352
+ * error code, human-readable message, and optionally the
3353
+ * invalid value.
3354
+ *
3355
+ * @example
3356
+ * ```typescript
3357
+ * const error: ValidationError = {
3358
+ * path: 'user.email',
3359
+ * code: 'invalid_email',
3360
+ * message: 'Invalid email format',
3361
+ * value: 'not-an-email',
3362
+ * };
3363
+ * ```
3364
+ */
3365
+ interface ValidationError {
3366
+ /**
3367
+ * Dot-notation path to the invalid field.
3368
+ * For nested fields: "fields.0.options.1.label"
3369
+ * For root fields: "email"
3370
+ */
3371
+ path: string;
3372
+ /**
3373
+ * Human-readable error message.
3374
+ * Should be suitable for display to end users.
3375
+ */
3376
+ message: string;
3377
+ /**
3378
+ * Typed error code for programmatic handling.
3379
+ */
3380
+ code: ValidationErrorCode;
3381
+ /**
3382
+ * The invalid value that caused the error.
3383
+ * Optional - may be omitted for security reasons.
3384
+ */
3385
+ value?: unknown;
3386
+ }
3387
+ /**
3388
+ * Result of a validation operation.
3389
+ *
3390
+ * @example
3391
+ * ```typescript
3392
+ * function validateUser(data: unknown): ValidationResult {
3393
+ * const errors: ValidationError[] = [];
3394
+ *
3395
+ * if (!data.email) {
3396
+ * errors.push({
3397
+ * path: 'email',
3398
+ * code: 'required',
3399
+ * message: 'Email is required',
3400
+ * });
3401
+ * }
3402
+ *
3403
+ * return {
3404
+ * valid: errors.length === 0,
3405
+ * errors,
3406
+ * };
3407
+ * }
3408
+ * ```
3409
+ */
3410
+ interface ValidationResult {
3411
+ /**
3412
+ * Whether the validation passed (no errors).
3413
+ */
3414
+ valid: boolean;
3415
+ /**
3416
+ * Array of validation errors.
3417
+ * Empty array when valid is true.
3418
+ */
3419
+ errors: ValidationError[];
3420
+ }
3421
+ /**
3422
+ * Standard API response format for validation errors.
3423
+ *
3424
+ * Used for HTTP 400 responses when input validation fails.
3425
+ *
3426
+ * @example
3427
+ * ```typescript
3428
+ * // API Response
3429
+ * {
3430
+ * "error": {
3431
+ * "code": "VALIDATION_ERROR",
3432
+ * "message": "Validation failed",
3433
+ * "details": [
3434
+ * {
3435
+ * "path": "email",
3436
+ * "code": "invalid_email",
3437
+ * "message": "Invalid email format"
3438
+ * }
3439
+ * ]
3440
+ * }
3441
+ * }
3442
+ * ```
3443
+ */
3444
+ interface ValidationErrorResponse {
3445
+ error: {
3446
+ /**
3447
+ * Always "VALIDATION_ERROR" for validation errors.
3448
+ */
3449
+ code: "VALIDATION_ERROR";
3450
+ /**
3451
+ * Summary message describing the error.
3452
+ */
3453
+ message: string;
3454
+ /**
3455
+ * Array of individual field validation errors.
3456
+ */
3457
+ details: ValidationError[];
3458
+ };
3459
+ }
3460
+ /**
3461
+ * Check if a string is a valid ValidationErrorCode.
3462
+ *
3463
+ * @param code - The string to check
3464
+ * @returns True if the code is a valid ValidationErrorCode
3465
+ *
3466
+ * @example
3467
+ * ```typescript
3468
+ * if (isValidationErrorCode('required')) {
3469
+ * // TypeScript knows this is ValidationErrorCode
3470
+ * }
3471
+ * ```
3472
+ */
3473
+ declare function isValidationErrorCode(code: string): code is ValidationErrorCode;
3474
+ /**
3475
+ * Check if an object is a ValidationError.
3476
+ *
3477
+ * @param obj - The object to check
3478
+ * @returns True if the object is a ValidationError
3479
+ *
3480
+ * @example
3481
+ * ```typescript
3482
+ * if (isValidationError(err)) {
3483
+ * console.log(err.path, err.message);
3484
+ * }
3485
+ * ```
3486
+ */
3487
+ declare function isValidationError(obj: unknown): obj is ValidationError;
3488
+ /**
3489
+ * Check if an object is a ValidationResult.
3490
+ *
3491
+ * @param obj - The object to check
3492
+ * @returns True if the object is a ValidationResult
3493
+ */
3494
+ declare function isValidationResult(obj: unknown): obj is ValidationResult;
3495
+ /**
3496
+ * Create a validation error.
3497
+ *
3498
+ * @param path - Dot-notation path to the field
3499
+ * @param code - Error code
3500
+ * @param message - Human-readable message
3501
+ * @param value - Optional invalid value
3502
+ * @returns ValidationError object
3503
+ *
3504
+ * @example
3505
+ * ```typescript
3506
+ * const error = createValidationError(
3507
+ * 'user.email',
3508
+ * 'invalid_email',
3509
+ * 'Please enter a valid email address'
3510
+ * );
3511
+ * ```
3512
+ */
3513
+ declare function createValidationError(path: string, code: ValidationErrorCode, message: string, value?: unknown): ValidationError;
3514
+ /**
3515
+ * Create a successful validation result.
3516
+ *
3517
+ * @returns ValidationResult with valid=true and empty errors
3518
+ */
3519
+ declare function validResult(): ValidationResult;
3520
+ /**
3521
+ * Create a failed validation result.
3522
+ *
3523
+ * @param errors - Array of validation errors
3524
+ * @returns ValidationResult with valid=false and the errors
3525
+ */
3526
+ declare function invalidResult(errors: ValidationError[]): ValidationResult;
3527
+ /**
3528
+ * Create a validation error response for API.
3529
+ *
3530
+ * @param errors - Array of validation errors
3531
+ * @param message - Optional summary message
3532
+ * @returns ValidationErrorResponse object
3533
+ *
3534
+ * @example
3535
+ * ```typescript
3536
+ * const response = createValidationErrorResponse(errors);
3537
+ * return NextResponse.json(response, { status: 400 });
3538
+ * ```
3539
+ */
3540
+ declare function createValidationErrorResponse(errors: ValidationError[], message?: string): ValidationErrorResponse;
3541
+
3542
+ /**
3543
+ * Error Formatter Utilities
3544
+ *
3545
+ * Provides utilities for converting Zod validation errors to our
3546
+ * standardized validation error format and merging validation results.
3547
+ *
3548
+ * @module validation/error-formatter
3549
+ *
3550
+ * @example
3551
+ * ```typescript
3552
+ * import { z } from "zod";
3553
+ * import { formatZodError, mergeValidationResults, toApiResponse } from "nextly/validation";
3554
+ *
3555
+ * const schema = z.object({
3556
+ * email: z.string().email(),
3557
+ * age: z.number().min(18),
3558
+ * });
3559
+ *
3560
+ * const result = schema.safeParse({ email: "invalid", age: 15 });
3561
+ * if (!result.success) {
3562
+ * const validationResult = formatZodError(result.error);
3563
+ * const apiResponse = toApiResponse(validationResult);
3564
+ * return NextResponse.json(apiResponse, { status: 400 });
3565
+ * }
3566
+ * ```
3567
+ */
3568
+
3569
+ /**
3570
+ * Convert a Zod error to our standardized ValidationResult format.
3571
+ *
3572
+ * This function transforms Zod's native error format into our
3573
+ * consistent validation error structure, enabling unified error
3574
+ * handling across the application.
3575
+ *
3576
+ * @param error - The ZodError to convert
3577
+ * @returns ValidationResult with valid=false and mapped errors
3578
+ *
3579
+ * @example
3580
+ * ```typescript
3581
+ * import { z } from "zod";
3582
+ * import { formatZodError } from "nextly/validation";
3583
+ *
3584
+ * const schema = z.object({
3585
+ * email: z.string().email(),
3586
+ * age: z.number().min(18),
3587
+ * });
3588
+ *
3589
+ * const result = schema.safeParse({ email: "bad", age: 10 });
3590
+ * if (!result.success) {
3591
+ * const validationResult = formatZodError(result.error);
3592
+ * // {
3593
+ * // valid: false,
3594
+ * // errors: [
3595
+ * // { path: "email", code: "invalid_email", message: "Invalid email" },
3596
+ * // { path: "age", code: "min_value", message: "Number must be >= 18" }
3597
+ * // ]
3598
+ * // }
3599
+ * }
3600
+ * ```
3601
+ */
3602
+ declare function formatZodError(error: z.ZodError): ValidationResult;
3603
+ /**
3604
+ * Merge multiple validation results into a single result.
3605
+ *
3606
+ * This is useful when you need to combine validation from
3607
+ * multiple sources (e.g., Zod schema + custom business rules).
3608
+ *
3609
+ * @param results - The validation results to merge
3610
+ * @returns A single ValidationResult containing all errors
3611
+ *
3612
+ * @example
3613
+ * ```typescript
3614
+ * import { formatZodError, mergeValidationResults, invalidResult } from "nextly/validation";
3615
+ *
3616
+ * // Schema validation
3617
+ * const schemaResult = formatZodError(zodError);
3618
+ *
3619
+ * // Custom business rule validation
3620
+ * const businessResult = invalidResult([
3621
+ * { path: "email", code: "unique", message: "Email already exists" }
3622
+ * ]);
3623
+ *
3624
+ * // Combine all errors
3625
+ * const finalResult = mergeValidationResults(schemaResult, businessResult);
3626
+ * ```
3627
+ */
3628
+ declare function mergeValidationResults(...results: ValidationResult[]): ValidationResult;
3629
+ /**
3630
+ * Format a validation result for API response.
3631
+ *
3632
+ * Converts a ValidationResult into the standard API error response
3633
+ * format with a fixed message including the error count.
3634
+ *
3635
+ * @param result - The validation result to format
3636
+ * @returns ValidationErrorResponse suitable for API response
3637
+ *
3638
+ * @example
3639
+ * ```typescript
3640
+ * import { formatZodError, toApiResponse } from "nextly/validation";
3641
+ * import { NextResponse } from "next/server";
3642
+ *
3643
+ * const result = schema.safeParse(data);
3644
+ * if (!result.success) {
3645
+ * const validationResult = formatZodError(result.error);
3646
+ * const apiResponse = toApiResponse(validationResult);
3647
+ * return NextResponse.json(apiResponse, { status: 400 });
3648
+ * }
3649
+ *
3650
+ * // Response:
3651
+ * // {
3652
+ * // "error": {
3653
+ * // "code": "VALIDATION_ERROR",
3654
+ * // "message": "Validation failed with 2 error(s)",
3655
+ * // "details": [...]
3656
+ * // }
3657
+ * // }
3658
+ * ```
3659
+ */
3660
+ declare function toApiResponse(result: ValidationResult): ValidationErrorResponse;
3661
+
3662
+ /**
3663
+ * Single Configuration Validator
3664
+ *
3665
+ * Validates a {@link SingleConfig} using the shared base-validator helpers
3666
+ * for slug/field-name/relationship/component rules, plus Single-specific
3667
+ * access control validation (read/update only, no create/delete).
3668
+ *
3669
+ * Duplicated validation logic was moved to `src/shared/base-validator.ts`
3670
+ *
3671
+ * @module singles/config/validate-single
3672
+ * @since 1.0.0
3673
+ *
3674
+ * @example
3675
+ * ```typescript
3676
+ * import { validateSingleConfig } from 'nextly';
3677
+ *
3678
+ * const result = validateSingleConfig(config);
3679
+ * if (!result.valid) {
3680
+ * console.error('Validation errors:', result.errors);
3681
+ * }
3682
+ * ```
3683
+ */
3684
+
3685
+ /**
3686
+ * Error codes for Single validation failures.
3687
+ * Shares most codes with Collection/Component validators.
3688
+ */
3689
+ type SingleValidationErrorCode = "SLUG_REQUIRED" | "SLUG_INVALID_TYPE" | "SLUG_TOO_SHORT" | "SLUG_TOO_LONG" | "SLUG_INVALID_FORMAT" | "SLUG_RESERVED" | "SLUG_SQL_KEYWORD" | "FIELDS_REQUIRED" | "FIELDS_INVALID_TYPE" | "FIELDS_EMPTY" | "FIELD_NAME_REQUIRED" | "FIELD_NAME_INVALID_FORMAT" | "FIELD_NAME_SQL_KEYWORD" | "FIELD_NAME_DUPLICATE" | "FIELD_TYPE_REQUIRED" | "FIELD_TYPE_INVALID" | "SELECT_OPTIONS_REQUIRED" | "SELECT_OPTIONS_EMPTY" | "RADIO_OPTIONS_REQUIRED" | "RADIO_OPTIONS_EMPTY" | "RELATIONSHIP_TARGET_REQUIRED" | "RELATIONSHIP_TARGET_INVALID" | "ARRAY_FIELDS_REQUIRED" | "GROUP_FIELDS_REQUIRED" | "BLOCKS_REQUIRED" | "BLOCKS_EMPTY" | "BLOCK_SLUG_REQUIRED" | "BLOCK_FIELDS_REQUIRED" | "COMPONENT_REF_REQUIRED" | "COMPONENT_REF_CONFLICT" | "COMPONENT_REF_INVALID" | "COMPONENT_REF_EMPTY" | "ACCESS_INVALID_TYPE" | "ACCESS_FUNCTION_INVALID";
3690
+ /**
3691
+ * A single validation error with path and context.
3692
+ */
3693
+ interface SingleValidationError {
3694
+ /**
3695
+ * Dot-notation path to the invalid property.
3696
+ * @example 'slug', 'fields.0.name', 'fields.seo.items.title'
3697
+ */
3698
+ path: string;
3699
+ /** Human-readable error message. */
3700
+ message: string;
3701
+ /** Machine-readable error code for programmatic handling. */
3702
+ code: SingleValidationErrorCode;
3703
+ }
3704
+ /**
3705
+ * Result of Single config validation.
3706
+ */
3707
+ interface SingleValidationResult {
3708
+ /** Whether the configuration is valid. */
3709
+ valid: boolean;
3710
+ /** Array of validation errors (empty if valid). */
3711
+ errors: SingleValidationError[];
3712
+ }
3713
+ /**
3714
+ * Reserved Single slugs that cannot be used.
3715
+ *
3716
+ * Extends the base RESERVED_SLUGS with Single-specific reserved names.
3717
+ */
3718
+ declare const RESERVED_SINGLE_SLUGS: readonly ["api", "graphql", "rest", "admin", "dashboard", "auth", "login", "logout", "register", "signup", "signin", "signout", "forgot-password", "reset-password", "verify", "verify-email", "static", "public", "assets", "_next", "health", "status", "metrics", "users", "roles", "permissions", "sessions", "tokens", "media", "uploads", "files"];
3719
+ /**
3720
+ * Validates a complete Single configuration.
3721
+ *
3722
+ * Performs comprehensive validation including slug format/reserved names,
3723
+ * SQL keyword blocking, recursive field validation, select options,
3724
+ * relationship targets, component references, duplicate detection, and
3725
+ * Single-specific access control (read/update only).
3726
+ *
3727
+ * @example
3728
+ * ```typescript
3729
+ * import { validateSingleConfig } from 'nextly';
3730
+ *
3731
+ * const result = validateSingleConfig(config);
3732
+ * if (!result.valid) {
3733
+ * result.errors.forEach(err => {
3734
+ * console.error(`[${err.code}] ${err.path}: ${err.message}`);
3735
+ * });
3736
+ * }
3737
+ * ```
3738
+ */
3739
+ declare function validateSingleConfig(config: SingleConfig): SingleValidationResult;
3740
+ /**
3741
+ * Throws an error if the Single configuration is invalid.
3742
+ *
3743
+ * Convenience wrapper around {@link validateSingleConfig}.
3744
+ */
3745
+ declare function assertValidSingleConfig(config: SingleConfig): void;
3746
+
3747
+ /**
3748
+ * Component Configuration Validator
3749
+ *
3750
+ * Validates a {@link ComponentConfig} using shared base-validator helpers
3751
+ * for slug/field-name/relationship/component rules. Components do not have
3752
+ * domain-specific access rules or index validation; cross-component
3753
+ * checks (circular references, nesting depth) run at `defineConfig()` time
3754
+ * when all component definitions are available.
3755
+ *
3756
+ * Duplicated validation logic was moved to `src/shared/base-validator.ts`
3757
+ * This file now orchestrates those helpers and keeps
3758
+ * only Component-specific error types and reserved slug constants.
3759
+ *
3760
+ * @module components/config/validate-component
3761
+ * @since 1.0.0
3762
+ *
3763
+ * @example
3764
+ * ```typescript
3765
+ * import { validateComponentConfig } from 'nextly';
3766
+ *
3767
+ * const result = validateComponentConfig(config);
3768
+ * if (!result.valid) {
3769
+ * console.error('Validation errors:', result.errors);
3770
+ * }
3771
+ * ```
3772
+ */
3773
+
3774
+ /**
3775
+ * Maximum nesting depth for component-within-component references.
3776
+ *
3777
+ * A depth of 3 means:
3778
+ * - Level 1: Component A used in a Collection/Single
3779
+ * - Level 2: Component B nested inside Component A
3780
+ * - Level 3: Component C nested inside Component B
3781
+ *
3782
+ * Enforced at `defineConfig()` time when all component definitions are available.
3783
+ */
3784
+ declare const MAX_COMPONENT_NESTING_DEPTH = 3;
3785
+ /**
3786
+ * Error codes for Component validation failures.
3787
+ */
3788
+ type ComponentValidationErrorCode = "SLUG_REQUIRED" | "SLUG_INVALID_TYPE" | "SLUG_TOO_SHORT" | "SLUG_TOO_LONG" | "SLUG_INVALID_FORMAT" | "SLUG_RESERVED" | "SLUG_SQL_KEYWORD" | "FIELDS_REQUIRED" | "FIELDS_INVALID_TYPE" | "FIELDS_EMPTY" | "FIELD_NAME_REQUIRED" | "FIELD_NAME_INVALID_FORMAT" | "FIELD_NAME_SQL_KEYWORD" | "FIELD_NAME_DUPLICATE" | "FIELD_TYPE_REQUIRED" | "FIELD_TYPE_INVALID" | "SELECT_OPTIONS_REQUIRED" | "SELECT_OPTIONS_EMPTY" | "RADIO_OPTIONS_REQUIRED" | "RADIO_OPTIONS_EMPTY" | "RELATIONSHIP_TARGET_REQUIRED" | "RELATIONSHIP_TARGET_INVALID" | "ARRAY_FIELDS_REQUIRED" | "GROUP_FIELDS_REQUIRED" | "COMPONENT_REF_REQUIRED" | "COMPONENT_REF_CONFLICT" | "COMPONENT_REF_INVALID" | "COMPONENT_REF_EMPTY";
3789
+ /**
3790
+ * A single validation error with path and context.
3791
+ */
3792
+ interface ComponentValidationError {
3793
+ /**
3794
+ * Dot-notation path to the invalid property.
3795
+ * @example 'slug', 'fields.0.name', 'fields.seo.component'
3796
+ */
3797
+ path: string;
3798
+ /** Human-readable error message. */
3799
+ message: string;
3800
+ /** Machine-readable error code for programmatic handling. */
3801
+ code: ComponentValidationErrorCode;
3802
+ }
3803
+ /**
3804
+ * Result of Component config validation.
3805
+ */
3806
+ interface ComponentValidationResult {
3807
+ /** Whether the configuration is valid. */
3808
+ valid: boolean;
3809
+ /** Array of validation errors (empty if valid). */
3810
+ errors: ComponentValidationError[];
3811
+ }
3812
+ /**
3813
+ * Reserved Component slugs that cannot be used.
3814
+ *
3815
+ * Extends the base RESERVED_SLUGS with Component-specific reserved names.
3816
+ */
3817
+ declare const RESERVED_COMPONENT_SLUGS: readonly ["api", "graphql", "rest", "admin", "dashboard", "auth", "login", "logout", "register", "signup", "signin", "signout", "forgot-password", "reset-password", "verify", "verify-email", "static", "public", "assets", "_next", "health", "status", "metrics", "users", "roles", "permissions", "sessions", "tokens", "media", "uploads", "files", "components", "component"];
3818
+ /**
3819
+ * Validates a complete Component configuration.
3820
+ *
3821
+ * Performs comprehensive validation including slug format/reserved names,
3822
+ * SQL keyword blocking, recursive field validation, select options,
3823
+ * relationship targets, and component references.
3824
+ *
3825
+ * **Note:** Cross-component validation (circular references, nesting
3826
+ * depth, slug conflicts with Collections/Singles) is performed in
3827
+ * `defineConfig()`.
3828
+ *
3829
+ * @example
3830
+ * ```typescript
3831
+ * import { validateComponentConfig } from 'nextly';
3832
+ *
3833
+ * const result = validateComponentConfig(config);
3834
+ * if (!result.valid) {
3835
+ * result.errors.forEach(err => {
3836
+ * console.error(`[${err.code}] ${err.path}: ${err.message}`);
3837
+ * });
3838
+ * }
3839
+ * ```
3840
+ */
3841
+ declare function validateComponentConfig(config: ComponentConfig): ComponentValidationResult;
3842
+ /**
3843
+ * Throws an error if the Component configuration is invalid.
3844
+ *
3845
+ * Convenience wrapper around {@link validateComponentConfig}.
3846
+ */
3847
+ declare function assertValidComponentConfig(config: ComponentConfig): void;
3848
+
3849
+ /**
3850
+ * User Configuration Validator
3851
+ *
3852
+ * Validates UserConfig objects including:
3853
+ * - Field type restrictions (only scalar types allowed)
3854
+ * - Field name format and uniqueness
3855
+ * - Reserved field name checking (built-in user columns)
3856
+ * - SQL keyword blocking
3857
+ * - Select/radio option validation
3858
+ * - Admin option validation (listFields references)
3859
+ *
3860
+ * @module users/config/validate-user-config
3861
+ * @since 1.0.0
3862
+ *
3863
+ * @example
3864
+ * ```typescript
3865
+ * import { validateUserConfig } from '@nextly/core';
3866
+ *
3867
+ * const result = validateUserConfig({
3868
+ * fields: [
3869
+ * { type: 'text', name: 'company', label: 'Company' },
3870
+ * ],
3871
+ * });
3872
+ *
3873
+ * if (!result.valid) {
3874
+ * console.error('Validation errors:', result.errors);
3875
+ * }
3876
+ * ```
3877
+ */
3878
+
3879
+ /**
3880
+ * Error codes for user config validation failures.
3881
+ */
3882
+ type UserValidationErrorCode = "USER_FIELD_TYPE_NOT_ALLOWED" | "USER_FIELD_TYPE_REQUIRED" | "USER_FIELD_NAME_REQUIRED" | "USER_FIELD_NAME_INVALID_FORMAT" | "USER_FIELD_NAME_SQL_KEYWORD" | "USER_FIELD_NAME_DUPLICATE" | "USER_FIELD_NAME_RESERVED" | "USER_SELECT_OPTIONS_REQUIRED" | "USER_SELECT_OPTIONS_EMPTY" | "USER_RADIO_OPTIONS_REQUIRED" | "USER_RADIO_OPTIONS_EMPTY" | "USER_FIELDS_INVALID_TYPE" | "USER_ADMIN_INVALID_TYPE" | "USER_ADMIN_LIST_FIELD_UNKNOWN" | "USER_ADMIN_GROUP_INVALID_TYPE";
3883
+ /**
3884
+ * A single user config validation error with path and context.
3885
+ */
3886
+ interface UserValidationError {
3887
+ /** Dot-notation path to the invalid property. */
3888
+ path: string;
3889
+ /** Human-readable error message. */
3890
+ message: string;
3891
+ /** Machine-readable error code for programmatic handling. */
3892
+ code: UserValidationErrorCode;
3893
+ }
3894
+ /**
3895
+ * Result of user config validation.
3896
+ */
3897
+ interface UserValidationResult {
3898
+ /** Whether the configuration is valid. */
3899
+ valid: boolean;
3900
+ /** Array of validation errors (empty if valid). */
3901
+ errors: UserValidationError[];
3902
+ }
3903
+ /**
3904
+ * Built-in user field names that cannot be used as custom field names.
3905
+ * These correspond to columns in the core `users` table.
3906
+ */
3907
+ declare const RESERVED_USER_FIELD_NAMES: readonly ["id", "name", "email", "emailVerified", "passwordHash", "passwordUpdatedAt", "image", "isActive", "createdAt", "updatedAt", "roles", "accounts", "password"];
3908
+ /**
3909
+ * Allowed field types for user custom fields.
3910
+ * Limited to scalar types — complex types (relationship, array, group, etc.)
3911
+ * are not supported in user extension fields.
3912
+ */
3913
+ declare const ALLOWED_USER_FIELD_TYPES: readonly ["text", "textarea", "number", "email", "select", "radio", "checkbox", "date"];
3914
+ /**
3915
+ * Validates a complete user configuration.
3916
+ *
3917
+ * Performs comprehensive validation including:
3918
+ * - Field type restrictions (only scalar types allowed)
3919
+ * - Field name format, uniqueness, and reserved name checking
3920
+ * - SQL keyword blocking for field names
3921
+ * - Select/radio option validation
3922
+ * - Admin listFields reference validation
3923
+ *
3924
+ * @param config - The user configuration to validate
3925
+ * @returns Validation result with any errors found
3926
+ *
3927
+ * @example
3928
+ * ```typescript
3929
+ * import { validateUserConfig } from '@nextly/core';
3930
+ *
3931
+ * const result = validateUserConfig({
3932
+ * fields: [
3933
+ * { type: 'text', name: 'company', label: 'Company' },
3934
+ * { type: 'select', name: 'department', label: 'Department', options: [...] },
3935
+ * ],
3936
+ * admin: {
3937
+ * listFields: ['company', 'department'],
3938
+ * },
3939
+ * });
3940
+ *
3941
+ * if (!result.valid) {
3942
+ * result.errors.forEach(err => {
3943
+ * console.error(`[${err.code}] ${err.path}: ${err.message}`);
3944
+ * });
3945
+ * }
3946
+ * ```
3947
+ */
3948
+ declare function validateUserConfig(config: UserConfig): UserValidationResult;
3949
+ /**
3950
+ * Throws an error if the user configuration is invalid.
3951
+ *
3952
+ * Convenience wrapper around `validateUserConfig` that throws a
3953
+ * descriptive error instead of returning a result object.
3954
+ *
3955
+ * @param config - The user configuration to validate
3956
+ * @throws Error if validation fails with all error messages
3957
+ *
3958
+ * @example
3959
+ * ```typescript
3960
+ * import { assertValidUserConfig } from '@nextly/core';
3961
+ *
3962
+ * // Throws if invalid
3963
+ * assertValidUserConfig({
3964
+ * fields: [
3965
+ * { type: 'relationship', name: 'manager' }, // throws — type not allowed
3966
+ * ],
3967
+ * });
3968
+ * ```
3969
+ */
3970
+ declare function assertValidUserConfig(config: UserConfig): void;
3971
+
3972
+ /**
3973
+ * Trusted client-IP resolution for Web `Request` objects.
3974
+ *
3975
+ * The previous `getClientIp` helpers parsed
3976
+ * `X-Forwarded-For` unconditionally and returned the *leftmost* hop —
3977
+ * which a direct attacker can forge to defeat per-IP rate limits,
3978
+ * brute-force lockouts, and refresh-token IP binding.
3979
+ *
3980
+ * This helper applies the standard "rightmost-untrusted-hop" algorithm:
3981
+ *
3982
+ * - When `trustProxy` is `false` (default), proxy headers are
3983
+ * ignored entirely. Returns `null` because Web `Request` does not
3984
+ * expose the immediate-peer IP.
3985
+ *
3986
+ * - When `trustProxy` is `true`, walk `X-Forwarded-For` from the
3987
+ * rightmost hop, skipping any value that matches `trustedProxyIps`
3988
+ * (CIDR list). Return the first hop that is not in the trust list
3989
+ * — that is the closest *untrusted* IP in the chain, i.e. the real
3990
+ * client (or the closest claim of one).
3991
+ *
3992
+ * If no `X-Forwarded-For` is present, fall back to `cf-connecting-ip`
3993
+ * (Cloudflare) and `x-real-ip` (Nginx convention).
3994
+ *
3995
+ * If every hop in the chain is in the trust list, return `null`
3996
+ * rather than picking a trusted proxy as "the client".
3997
+ *
3998
+ * Implementation note: this module deliberately avoids `node:net` so
3999
+ * downstream packages that bundle for the browser (e.g. `@nextlyhq/admin`)
4000
+ * don't fail at build time. IP-family classification is done with
4001
+ * regex.
4002
+ *
4003
+ * @module utils/get-trusted-client-ip
4004
+ */
4005
+ interface TrustedClientIpOptions {
4006
+ /**
4007
+ * When false (default), proxy headers are ignored. When true,
4008
+ * `X-Forwarded-For` / `cf-connecting-ip` / `x-real-ip` are honored
4009
+ * subject to `trustedProxyIps`.
4010
+ */
4011
+ trustProxy: boolean;
4012
+ /**
4013
+ * CIDR list of proxy IPs that the application sits behind. Hops in
4014
+ * the `X-Forwarded-For` chain matching one of these CIDRs are
4015
+ * stripped during resolution; the first non-matching hop (walking
4016
+ * right-to-left) is returned as the client IP.
4017
+ *
4018
+ * IPv4 CIDR (`10.0.0.0/8`) and bare IPv4 addresses (`127.0.0.1`,
4019
+ * treated as `/32`) are fully supported. IPv6 entries are matched
4020
+ * exactly (no prefix masking) — sufficient for the common case
4021
+ * where proxy fleets advertise a small known IPv6 set.
4022
+ */
4023
+ trustedProxyIps?: readonly string[];
4024
+ }
4025
+ /**
4026
+ * Resolve the client IP for a Web `Request`, applying the trust-proxy
4027
+ * gate described above. Returns `null` when no trusted IP can be
4028
+ * identified — callers should treat that as "unknown" rather than
4029
+ * picking a fallback like `127.0.0.1` (which would collapse all
4030
+ * unknown clients into one rate-limit bucket).
4031
+ */
4032
+ declare function getTrustedClientIp(request: Request, options: TrustedClientIpOptions): string | null;
4033
+ /**
4034
+ * Parse `TRUSTED_PROXY_IPS` env-var format: comma-separated CIDR list
4035
+ * with optional whitespace. Empty / unset → empty array.
4036
+ */
4037
+ declare function parseTrustedProxyIpsEnv(raw: string | undefined): string[];
4038
+
4039
+ /**
4040
+ * SSRF-safe external URL validation + fetch.
4041
+ *
4042
+ * Closes the SSRF gap left by the previous webhook URL validator
4043
+ * (protocol-only) and the email-attachment fetcher (no validation).
4044
+ * Either let an attacker who controls a `url` field probe internal
4045
+ * services or exfiltrate cloud-metadata IAM credentials
4046
+ * (`http://169.254.169.254/...`).
4047
+ *
4048
+ * `validateExternalUrl(url, opts)`:
4049
+ * 1. Parse URL; reject non-allowed protocols.
4050
+ * 2. Reject hard-coded cloud-metadata hostnames before DNS.
4051
+ * 3. DNS-resolve the hostname (`all: true`). Reject if ANY returned
4052
+ * IP is private/loopback/link-local/CGNAT/multicast/cloud-metadata.
4053
+ * A single bad IP poisons the lookup — attacker-controlled DNS
4054
+ * could rotate which IP is returned per call.
4055
+ * 4. Return the validated URL + first resolved IP (the caller can use
4056
+ * it as a hint; full DNS-rebinding defense via dispatcher pinning
4057
+ * is documented as a follow-up).
4058
+ *
4059
+ * `safeFetch(url, init?, opts?)`:
4060
+ * Validate → fetch. Convenience wrapper for the common case.
4061
+ *
4062
+ * Implementation note: this module avoids module-level Node imports
4063
+ * so downstream packages that bundle for the browser
4064
+ * (e.g. `@nextlyhq/admin`) don't fail at build time. `node:dns/promises`
4065
+ * is loaded lazily inside the validation function.
4066
+ *
4067
+ * Known gap: full DNS-rebinding defense requires pinning the resolved
4068
+ * IP on the actual fetch dispatcher (undici Agent + custom connect).
4069
+ * Not implemented in v1 — the validation itself closes the primary
4070
+ * attack surface (URL pointing directly at private IP). Tracked for
4071
+ * follow-up.
4072
+ *
4073
+ * @module utils/validate-external-url
4074
+ */
4075
+ interface ValidateExternalUrlOptions {
4076
+ /**
4077
+ * When true, allow `localhost` / `127.0.0.1` / `::1` and HTTP
4078
+ * protocol (for tests, dev playgrounds). Default false.
4079
+ */
4080
+ allowLocalhost?: boolean;
4081
+ /**
4082
+ * Allowed URL protocols. Defaults to `["https:"]` — webhooks, email
4083
+ * attachments, and similar should never speak plain HTTP.
4084
+ */
4085
+ allowedProtocols?: readonly string[];
4086
+ }
4087
+ interface ValidatedUrl {
4088
+ /** The parsed URL (validated). */
4089
+ url: URL;
4090
+ /** The first IP returned by DNS — usable as an IP-pin hint. */
4091
+ pinnedIp: string;
4092
+ /** IP family of `pinnedIp`: 4 or 6. */
4093
+ family: 4 | 6;
4094
+ }
4095
+ declare class ExternalUrlError extends Error {
4096
+ readonly url: string;
4097
+ constructor(message: string, url: string);
4098
+ }
4099
+ /** Validate a URL for outbound fetch. Throws `ExternalUrlError` on rejection. */
4100
+ declare function validateExternalUrl(rawUrl: string, options?: ValidateExternalUrlOptions): Promise<ValidatedUrl>;
4101
+ interface SafeFetchOptions extends ValidateExternalUrlOptions, Omit<RequestInit, never> {
4102
+ }
4103
+ /**
4104
+ * Validate `rawUrl` then `fetch()` it. Convenience wrapper for the
4105
+ * common case (webhook delivery, email attachment fetch).
4106
+ *
4107
+ * NOTE: this does NOT pin the resolved IP on the actual connection.
4108
+ * If full DNS-rebinding defense is required, the caller should
4109
+ * implement a dispatcher with a custom `connect` that forces the
4110
+ * `pinnedIp` returned by `validateExternalUrl()`.
4111
+ */
4112
+ declare function safeFetch(rawUrl: string, options?: SafeFetchOptions): Promise<Response>;
4113
+
4114
+ /**
4115
+ * Media variant helpers
4116
+ *
4117
+ * Public-facing utility for picking a sized image variant URL from a Media
4118
+ * record. Consumers (admin UI, public Next.js apps reading the API) call
4119
+ * `getMediaVariant(media, "card")` instead of cracking open the
4120
+ * `media.sizes` JSON themselves.
4121
+ *
4122
+ * Selection rules (in order):
4123
+ * 1. If `media.sizes[name]` exists, return its URL.
4124
+ * 2. If `media.sizes[fallbackName]` exists, return its URL (when caller
4125
+ * passes one).
4126
+ * 3. If the asset isn't an image OR no sizes are present, fall back to
4127
+ * `media.url` (the original).
4128
+ *
4129
+ * The shape of `media` here is intentionally narrow so the helper works
4130
+ * for both the full Media row and any subset that callers pass through
4131
+ * the API.
4132
+ */
4133
+ interface MediaLike {
4134
+ url: string;
4135
+ thumbnailUrl?: string | null;
4136
+ mimeType?: string | null;
4137
+ sizes?: Record<string, {
4138
+ url: string;
4139
+ width?: number;
4140
+ height?: number;
4141
+ filesize?: number;
4142
+ }> | null;
4143
+ }
4144
+ interface GetMediaVariantOptions {
4145
+ /**
4146
+ * If the requested `name` isn't present, try this name next. Useful for
4147
+ * progressive fallback: `getMediaVariant(m, "card", { fallback: "thumbnail" })`.
4148
+ */
4149
+ fallback?: string;
4150
+ /**
4151
+ * If true (default), fall through to `media.thumbnailUrl` when neither the
4152
+ * requested variant nor the fallback variant exists. Set false to skip
4153
+ * straight to `media.url`.
4154
+ */
4155
+ preferThumbnail?: boolean;
4156
+ }
4157
+ /**
4158
+ * Return the URL for a named image-size variant, or fall back to the
4159
+ * thumbnail / original URL.
4160
+ *
4161
+ * Returns `undefined` only when `media` is null/undefined. Otherwise always
4162
+ * returns a string URL.
4163
+ */
4164
+ declare function getMediaVariant(media: MediaLike | null | undefined, name: string, options?: GetMediaVariantOptions): string | undefined;
4165
+ /**
4166
+ * Convenience: pick the smallest available variant URL. Useful for grid
4167
+ * thumbnails where bandwidth matters more than which exact name is used.
4168
+ *
4169
+ * Walks the variants by `width * height` and returns the smallest. Falls
4170
+ * back to `thumbnailUrl` then `url`.
4171
+ */
4172
+ declare function getSmallestMediaVariant(media: MediaLike | null | undefined): string | undefined;
4173
+
4174
+ export { ALLOWED_USER_FIELD_TYPES, ApiKeyTokenTypeSchema, AssignPermissionToRoleSchema, AssignRoleToUserSchema, AuthResult, BulkDeleteArgs, BulkDeleteMediaArgs, BulkOperationResponseSchema, BulkOperationSchema, ChangePasswordArgs, CheckAccessArgs, CheckUserPermissionSchema, CodeFieldValue, CollectionConfig, CollectionSlug, CollectionsHandler, ComponentConfig, Container, CountArgs, CountResult, CreateApiKeySchema, CreateArgs, CreateEmailProviderArgs, CreateEmailTemplateArgs, CreateFolderArgs, CreateLocalUserSchema, CreatePermissionArgs, CreatePermissionSchema, CreateRoleArgs, CreateRoleInheritanceSchema, CreateRoleSchema, CreateUserArgs, CreateUserFieldArgs, CreateUserWithPasswordSchema, DataFromCollectionSlug, DataFromSingleSlug, DateRangeSchema, DeleteArgs, DeleteEmailProviderArgs, DeleteEmailTemplateArgs, DeleteMediaArgs, DeletePermissionArgs, DeletePermissionSchema, DeleteResult, DeleteRoleArgs, DeleteRoleInheritanceSchema, DeleteRoleSchema, DeleteUserAccountSchema, DeleteUserArgs, DeleteUserFieldArgs, DeleteUserResponseSchema, DeleteUserSchema, BulkOperationResult as DirectAPIBulkOperationResult, DuplicateArgs, EmailProviderRecord, EmailSchema, EmailTemplateRecord, ErrorResponseSchema, ExpiresInSchema, ExternalUrlError, FieldConfig, FileUploadSchema, FindArgs, FindByIDArgs, FindEmailProviderByIDArgs, FindEmailProvidersArgs, FindEmailTemplateByIDArgs, FindEmailTemplateBySlugArgs, FindEmailTemplatesArgs, FindFormBySlugArgs, FindFormsArgs, FindMediaArgs, FindMediaByIDArgs, FindPermissionByIDArgs, FindPermissionsArgs, FindRoleByIDArgs, FindRolesArgs, FindSingleArgs, FindUserByIDArgs, FindUserFieldByIDArgs, FindUserFieldsArgs, FindUsersArgs, ForgotPasswordArgs, FormSubmissionsArgs, GetEmailLayoutArgs, GetPermissionByIdSchema, GetRoleByIdSchema, GetRolePermissionsArgs, GetRolePermissionsSchema, GetUserByIdSchema, GetUserPermissionsSchema, GetUserRolesSchema, HookHandler, HookRegistry, HookType, IdSchema, ImageUploadSchema, ListFoldersArgs, ListResult, ListUsersSchema, Logger, LoginArgs, MAX_COMPONENT_NESTING_DEPTH, MediaFile, MediaFolder, MigrationRecordStatus, MinimalUserSchema, MutationResult, NextlyServiceConfig as NextlyConfig, NextlyError, NextlyServiceConfig, PaginatedResponseSchema, PaginationSchema, PasswordSchema, Permission, PermissionActionSchema, PermissionCheckResponseSchema, PermissionListResponseSchema, PermissionResourceSchema, PermissionSchema, PhoneSchema, PreviewEmailTemplateArgs, RESERVED_COMPONENT_SLUGS, RESERVED_SINGLE_SLUGS, RESERVED_SLUGS, RESERVED_USER_FIELD_NAMES, RegisterArgs, RemovePermissionFromRoleSchema, RemoveRoleFromUserSchema, ReorderUserFieldsArgs, ResetPasswordArgs, Role, RoleInheritanceSchema, RoleListResponseSchema, RolePermissionListResponseSchema, RolePermissionSchema, RoleSchema, SQL_RESERVED_KEYWORDS, SYSTEM_RESOURCES, SanitizedNextlyConfig, SearchSchema, SendEmailArgs, SendEmailResult, SendTemplateEmailArgs, ServiceContainer, ServiceDispatcher, ServiceMap, SetDefaultProviderArgs, SetRolePermissionsArgs, SingleConfig, SingleSlug, SortOrderSchema, SortSchema, SubmitFormArgs, SubmitFormResult, SuccessResponseSchema, TestEmailProviderArgs, UnlinkAccountResponseSchema, UnlinkAccountSchema, UpdateApiKeySchema, UpdateArgs, UpdateEmailLayoutArgs, UpdateEmailProviderArgs, UpdateEmailTemplateArgs, UpdateMediaArgs, UpdatePasswordSchema, UpdatePermissionSchema, UpdateRoleArgs, UpdateRoleSchema, UpdateSingleArgs, UpdateUserArgs, UpdateUserFieldArgs, UpdateUserSchema, UploadMediaArgs, UrlSchema, User, UserAccountSchema, UserConfig, UserContext, UserFieldDefinitionRecord, UserIdSchema, UserListResponseSchema, UserResponseSchema, UserRoleListResponseSchema, UserRoleSchema, VALIDATION_ERROR_CODES, ValidationErrorSchema, VerifyEmailArgs, applyDesiredSchema, assertValidCollectionConfig, assertValidComponentConfig, assertValidSingleConfig, assertValidUserConfig, buildDesiredSchemaFromRegistry, buildDesiredSchemaFromRegistryAsync, clearAllHooks, clearCollectionHooks, codeValidators, container, createRegister, createSQLValidator, createValidationError, createValidationErrorResponse, formatZodError, getCachedNextly, getHookCount, getMediaVariant, getNextly, getSmallestMediaVariant, getTrustedClientIp, hasHooks, invalidResult, isSystemResource, isValidResource, isValidationError, isValidationErrorCode, isValidationResult, mergeValidationResults, nextlyMigrationsMysql, nextlyMigrationsPg, nextlyMigrationsSqlite, parseTrustedProxyIpsEnv, registerCollectionHooks, registerHook, reregisterCollectionHooks, safeFetch, shutdownNextly, toApiResponse, unregisterHook, validResult, validateCSS, validateCollectionConfig, validateComponentConfig, validateExternalUrl, validateJSON, validateJavaScript, validateSingleConfig, validateUserConfig, validateXML };
4175
+ export type { ApiKeyTokenTypeEnum, ApplyResult, AssignPermissionToRole, AssignRoleToUser, BulkOperation, BulkOperationResponse, CheckUserPermission, CodeValidationResult, CodeValidator, ValidationError$1 as CollectionValidationError, ValidationErrorCode$1 as CollectionValidationErrorCode, ValidationResult$1 as CollectionValidationResult, ComponentValidationError, ComponentValidationErrorCode, ComponentValidationResult, CreateApiKey, CreateLocalUser, CreatePermission, CreateRole, CreateRoleInheritance, CreateUserWithPassword, DateRange, DeletePermission, DeleteRole, DeleteRoleInheritance, DeleteUser, DeleteUserAccount, DeleteUserResponse, DesiredCollection, DesiredComponent, DesiredSchema, DesiredSchemaOverrides, DesiredSingle, DispatchRequest, DispatchResult, ErrorResponse, ExpiresInEnum, Factory, FileUpload, GeneratedSingleTypeInterface, GeneratedTypeInterface, GeneratedTypesFile, GetMediaVariantOptions, GetNextlyOptions, GetPermissionById, GetRoleById, GetRolePermissions, GetUserById, GetUserPermissions, GetUserRoles, ImageUpload, LegacyValidationError, ListUsers, MediaLike, Nextly, NextlyMigrationInsertMysql, NextlyMigrationInsertPg, NextlyMigrationInsertSqlite, NextlyMigrationMysql, NextlyMigrationPg, NextlyMigrationSqlite, OperationType, Pagination, PermissionAction, PermissionCheckResponse, PermissionListResponse, PermissionResource, RegisterCollectionHooksResult, RemovePermissionFromRole, RemoveRoleFromUser, RoleInheritance, RoleListResponse, RolePermission, RolePermissionListResponse, SQLValidatorOptions, SafeFetchOptions, SchemaApplyErrorCode, Search, ServiceType, SingleValidationError, SingleValidationErrorCode, SingleValidationResult, Sort, SortOrder, SuccessResponse, SystemResource, TrustedClientIpOptions, TypeGeneratorOptions, UnlinkAccount, UnlinkAccountResponse, UpdateApiKey, UpdatePassword, UpdatePermission, UpdateRole, UpdateUser, UserAccount, UserListResponse, UserResponse, UserRole, UserRoleListResponse, ValidateExternalUrlOptions, ValidatedUrl, ValidationError, ValidationErrorCode, ValidationErrorResponse, ValidationResult };