nextly 0.0.1 → 0.0.2-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +122 -0
- package/dist/_dts-chunks/collections-handler.d-DjgO74Wt.d.ts +20540 -0
- package/dist/_dts-chunks/config.d-DNwsDnjs.d.ts +2589 -0
- package/dist/_dts-chunks/define-component.d-BUgTHmt3.d.ts +1149 -0
- package/dist/_dts-chunks/image-processor.d-OO1PmMrv.d.ts +335 -0
- package/dist/_dts-chunks/index.d-axCAzZ7m.d.ts +17842 -0
- package/dist/_dts-chunks/media.d-DjDOZo4B.d.ts +117 -0
- package/dist/_dts-chunks/on-error.d-CHIKWNxd.d.ts +38 -0
- package/dist/_dts-chunks/storage.d-BUhQ2we_.d.ts +404 -0
- package/dist/actions/index.d.ts +239 -0
- package/dist/actions/index.mjs +281 -0
- package/dist/api/auth-state.d.ts +5 -0
- package/dist/api/auth-state.mjs +131 -0
- package/dist/api/collections-schema-detail.d.ts +56 -0
- package/dist/api/collections-schema-detail.mjs +244 -0
- package/dist/api/collections-schema-export.d.ts +56 -0
- package/dist/api/collections-schema-export.mjs +129 -0
- package/dist/api/collections-schema.d.ts +59 -0
- package/dist/api/collections-schema.mjs +207 -0
- package/dist/api/components-detail.d.ts +50 -0
- package/dist/api/components-detail.mjs +132 -0
- package/dist/api/components.d.ts +69 -0
- package/dist/api/components.mjs +144 -0
- package/dist/api/email-providers-default.d.ts +40 -0
- package/dist/api/email-providers-default.mjs +75 -0
- package/dist/api/email-providers-detail.d.ts +81 -0
- package/dist/api/email-providers-detail.mjs +109 -0
- package/dist/api/email-providers-test.d.ts +43 -0
- package/dist/api/email-providers-test.mjs +114 -0
- package/dist/api/email-providers.d.ts +69 -0
- package/dist/api/email-providers.mjs +110 -0
- package/dist/api/email-send-template.d.ts +41 -0
- package/dist/api/email-send-template.mjs +58 -0
- package/dist/api/email-send.d.ts +42 -0
- package/dist/api/email-send.mjs +58 -0
- package/dist/api/email-templates-detail.d.ts +74 -0
- package/dist/api/email-templates-detail.mjs +112 -0
- package/dist/api/email-templates-layout.d.ts +55 -0
- package/dist/api/email-templates-layout.mjs +92 -0
- package/dist/api/email-templates-preview.d.ts +48 -0
- package/dist/api/email-templates-preview.mjs +93 -0
- package/dist/api/email-templates.d.ts +61 -0
- package/dist/api/email-templates.mjs +118 -0
- package/dist/api/health.d.ts +68 -0
- package/dist/api/health.mjs +67 -0
- package/dist/api/index.d.ts +54 -0
- package/dist/api/index.mjs +16 -0
- package/dist/api/media-bulk.d.ts +74 -0
- package/dist/api/media-bulk.mjs +196 -0
- package/dist/api/media-folders.d.ts +112 -0
- package/dist/api/media-folders.mjs +187 -0
- package/dist/api/media-handlers.d.ts +102 -0
- package/dist/api/media-handlers.mjs +437 -0
- package/dist/api/media.d.ts +117 -0
- package/dist/api/media.mjs +242 -0
- package/dist/api/singles-detail.d.ts +87 -0
- package/dist/api/singles-detail.mjs +170 -0
- package/dist/api/singles-schema-detail.d.ts +54 -0
- package/dist/api/singles-schema-detail.mjs +182 -0
- package/dist/api/singles.d.ts +34 -0
- package/dist/api/singles.mjs +94 -0
- package/dist/api/storage-upload-url.d.ts +48 -0
- package/dist/api/storage-upload-url.mjs +202 -0
- package/dist/api/uploads.d.ts +109 -0
- package/dist/api/uploads.mjs +359 -0
- package/dist/auth/index.d.ts +425 -0
- package/dist/auth/index.mjs +199 -0
- package/dist/boot-apply-PQSYLDIN.mjs +7 -0
- package/dist/chunk-2OALJTK6.mjs +489 -0
- package/dist/chunk-2Q2SX2CS.mjs +365 -0
- package/dist/chunk-2TFX4ND3.mjs +13 -0
- package/dist/chunk-2TWPDSYD.mjs +87 -0
- package/dist/chunk-2W3DVD7S.mjs +647 -0
- package/dist/chunk-2ZFKXPQM.mjs +88 -0
- package/dist/chunk-3FA7FKAV.mjs +832 -0
- package/dist/chunk-3NZ2KMBL.mjs +58 -0
- package/dist/chunk-4MJLT6PZ.mjs +0 -0
- package/dist/chunk-56WO4WX7.mjs +0 -0
- package/dist/chunk-5APFUGAD.mjs +89 -0
- package/dist/chunk-5HMZ644B.mjs +108 -0
- package/dist/chunk-67GXH6PR.mjs +32 -0
- package/dist/chunk-6JNEPWRW.mjs +14368 -0
- package/dist/chunk-6NFHQIJD.mjs +45 -0
- package/dist/chunk-7P6ASYW6.mjs +9 -0
- package/dist/chunk-A3WPLSDT.mjs +1364 -0
- package/dist/chunk-AGJ6F2T3.mjs +144 -0
- package/dist/chunk-AK6Z23OX.mjs +1464 -0
- package/dist/chunk-APKKRD2G.mjs +102 -0
- package/dist/chunk-B2GV2BWH.mjs +73 -0
- package/dist/chunk-D5HQBNUB.mjs +74 -0
- package/dist/chunk-DNNG377Z.mjs +204 -0
- package/dist/chunk-DP3G27G5.mjs +135 -0
- package/dist/chunk-DV6WVX2Q.mjs +0 -0
- package/dist/chunk-DXGGXIUZ.mjs +57 -0
- package/dist/chunk-EGXBZCGC.mjs +943 -0
- package/dist/chunk-ERCNLX3V.mjs +176 -0
- package/dist/chunk-FQULBZ53.mjs +850 -0
- package/dist/chunk-G2AA4QLC.mjs +262 -0
- package/dist/chunk-GDBJ5JCU.mjs +488 -0
- package/dist/chunk-GJNSJU4S.mjs +19 -0
- package/dist/chunk-GZ6DCQKC.mjs +69 -0
- package/dist/chunk-H26B4FYG.mjs +167 -0
- package/dist/chunk-I4JMR3UR.mjs +21 -0
- package/dist/chunk-INV7QKLG.mjs +508 -0
- package/dist/chunk-IUDOC7N7.mjs +46 -0
- package/dist/chunk-IZWPRDC3.mjs +206 -0
- package/dist/chunk-KIMNCZGV.mjs +15 -0
- package/dist/chunk-L6HW2DA7.mjs +15 -0
- package/dist/chunk-LAZXX4HR.mjs +100 -0
- package/dist/chunk-LDKCUMHK.mjs +95 -0
- package/dist/chunk-LRXMECUA.mjs +0 -0
- package/dist/chunk-M52VMPGA.mjs +119 -0
- package/dist/chunk-MGUWEEI6.mjs +160 -0
- package/dist/chunk-NRUWQ5Z7.mjs +419 -0
- package/dist/chunk-NSEFNNU4.mjs +25360 -0
- package/dist/chunk-NTHVDFGO.mjs +138 -0
- package/dist/chunk-O3QHXMOX.mjs +3166 -0
- package/dist/chunk-P7NH2OSC.mjs +2605 -0
- package/dist/chunk-PKMABBB5.mjs +184 -0
- package/dist/chunk-PWS6XGJK.mjs +76 -0
- package/dist/chunk-R6JJQHFC.mjs +20 -0
- package/dist/chunk-RJLLGGPG.mjs +0 -0
- package/dist/chunk-SBACDPNX.mjs +689 -0
- package/dist/chunk-TO5AFLVQ.mjs +124 -0
- package/dist/chunk-TS7GHTG2.mjs +5436 -0
- package/dist/chunk-UJ2IMJ4W.mjs +133 -0
- package/dist/chunk-UOP63Q54.mjs +102 -0
- package/dist/chunk-UUOFWCM6.mjs +78 -0
- package/dist/chunk-V4EQTOA4.mjs +893 -0
- package/dist/chunk-VJ66NCL4.mjs +193 -0
- package/dist/chunk-VQJQHVEV.mjs +29 -0
- package/dist/chunk-VTJADRO3.mjs +141 -0
- package/dist/chunk-VWF3JO32.mjs +0 -0
- package/dist/chunk-W4MGXIRR.mjs +27 -0
- package/dist/chunk-W5KKPZT5.mjs +1204 -0
- package/dist/chunk-WD34YQ6T.mjs +381 -0
- package/dist/chunk-WZBYMYVW.mjs +14 -0
- package/dist/chunk-X23WKS3Z.mjs +50 -0
- package/dist/chunk-X7TXCYYN.mjs +6496 -0
- package/dist/chunk-XGI4EMS3.mjs +140 -0
- package/dist/chunk-XZKLBMN6.mjs +1153 -0
- package/dist/chunk-YB7INWPY.mjs +0 -0
- package/dist/chunk-YV4Y7SDL.mjs +83 -0
- package/dist/chunk-YZNBLFIW.mjs +1688 -0
- package/dist/chunk-YZZCTONM.mjs +263 -0
- package/dist/chunk-ZE6A3FYH.mjs +289 -0
- package/dist/cli/nextly.mjs +68 -0
- package/dist/cli/utils/index.d.ts +449 -0
- package/dist/cli/utils/index.mjs +49 -0
- package/dist/component-schema-service-5577KVW6.mjs +11 -0
- package/dist/config-loader-23YEMC3Z.mjs +23 -0
- package/dist/config.d.ts +44 -0
- package/dist/config.mjs +109 -0
- package/dist/container-ORGFGYSZ.mjs +9 -0
- package/dist/database/index.d.ts +12 -0
- package/dist/database/index.mjs +40 -0
- package/dist/database/seeders/index.d.ts +93 -0
- package/dist/database/seeders/index.mjs +47 -0
- package/dist/db-sync-demote-LJGKLB3S.mjs +117 -0
- package/dist/db-sync-promote-B26VSYQF.mjs +113 -0
- package/dist/dev-reload-broadcaster-B73IQ53V.mjs +25 -0
- package/dist/dist-M2NOU37V.mjs +19 -0
- package/dist/drizzle-kit-lazy-D2M2PXR2.mjs +13 -0
- package/dist/dynamic-collection-schema-service-IEXTPIZ7.mjs +8 -0
- package/dist/errors/index.d.ts +159 -0
- package/dist/errors/index.mjs +10 -0
- package/dist/factory-IWMBKUJM.mjs +15 -0
- package/dist/first-run-QIVKWJIF.mjs +63 -0
- package/dist/fresh-push-NR67DC3R.mjs +8 -0
- package/dist/index.d.ts +4175 -0
- package/dist/index.mjs +1336 -0
- package/dist/local-plugin-PTET4NAT.mjs +7 -0
- package/dist/logger-NU46DXNY.mjs +15 -0
- package/dist/logger-YE4TC7ZN.mjs +9 -0
- package/dist/migration-journal-EP532Y4L.mjs +139 -0
- package/dist/migrations/mysql/0000_eager_sentry.sql +174 -0
- package/dist/migrations/mysql/0001_soft_giant_girl.sql +27 -0
- package/dist/migrations/mysql/0002_media_table.sql +24 -0
- package/dist/migrations/mysql/0003_dynamic_singles.sql +37 -0
- package/dist/migrations/mysql/0004_dynamic_components.sql +35 -0
- package/dist/migrations/mysql/0005_user_management_tables.sql +92 -0
- package/dist/migrations/mysql/0006_api_keys.sql +36 -0
- package/dist/migrations/mysql/0007_general_settings.sql +20 -0
- package/dist/migrations/mysql/0008_site_settings_logo_url.sql +9 -0
- package/dist/migrations/mysql/0009_activity_log.sql +30 -0
- package/dist/migrations/mysql/0010_site_settings_sidebar.sql +13 -0
- package/dist/migrations/mysql/0011_missing_tables_and_columns.sql +54 -0
- package/dist/migrations/mysql/0012_image_sizes_and_focal_point.sql +30 -0
- package/dist/migrations/mysql/0012_media_folders.sql +43 -0
- package/dist/migrations/mysql/0013_user_brute_force_protection.sql +31 -0
- package/dist/migrations/mysql/0014_email_template_attachments.sql +12 -0
- package/dist/migrations/mysql/0015_media_uploaded_by_nullable.sql +15 -0
- package/dist/migrations/mysql/20260429_000000_000_initial_journal.sql +22 -0
- package/dist/migrations/mysql/20260501_000000_journal_batch.sql +17 -0
- package/dist/migrations/mysql/20260501_000001_audit_log.sql +24 -0
- package/dist/migrations/mysql/20260504_000000_nextly_meta.sql +21 -0
- package/dist/migrations/mysql/meta/0000_snapshot.json +1005 -0
- package/dist/migrations/mysql/meta/0001_snapshot.json +1099 -0
- package/dist/migrations/mysql/meta/_journal.json +41 -0
- package/dist/migrations/postgresql/0000_misty_king_bedlam.sql +169 -0
- package/dist/migrations/postgresql/0001_perpetual_captain_marvel.sql +8 -0
- package/dist/migrations/postgresql/0002_sad_spectrum.sql +16 -0
- package/dist/migrations/postgresql/0003_hesitant_ultron.sql +17 -0
- package/dist/migrations/postgresql/0004_media_table.sql +24 -0
- package/dist/migrations/postgresql/0005_media_folders.sql +36 -0
- package/dist/migrations/postgresql/0006_dynamic_collections_update.sql +50 -0
- package/dist/migrations/postgresql/0007_dynamic_singles.sql +38 -0
- package/dist/migrations/postgresql/0008_dynamic_components.sql +37 -0
- package/dist/migrations/postgresql/0009_user_management_tables.sql +95 -0
- package/dist/migrations/postgresql/0010_api_keys.sql +34 -0
- package/dist/migrations/postgresql/0011_general_settings.sql +20 -0
- package/dist/migrations/postgresql/0012_site_settings_logo_url.sql +9 -0
- package/dist/migrations/postgresql/0013_activity_log.sql +29 -0
- package/dist/migrations/postgresql/0014_image_sizes_and_focal_point.sql +33 -0
- package/dist/migrations/postgresql/0014_site_settings_sidebar.sql +13 -0
- package/dist/migrations/postgresql/0015_user_brute_force_protection.sql +29 -0
- package/dist/migrations/postgresql/0016_email_template_attachments.sql +12 -0
- package/dist/migrations/postgresql/0017_media_uploaded_by_nullable.sql +15 -0
- package/dist/migrations/postgresql/20260429_000000_000_initial_journal.sql +24 -0
- package/dist/migrations/postgresql/20260501_000000_journal_batch.sql +17 -0
- package/dist/migrations/postgresql/20260501_000001_audit_log.sql +24 -0
- package/dist/migrations/postgresql/20260504_000000_nextly_meta.sql +22 -0
- package/dist/migrations/postgresql/meta/0000_snapshot.json +1286 -0
- package/dist/migrations/postgresql/meta/0001_snapshot.json +1407 -0
- package/dist/migrations/postgresql/meta/0002_snapshot.json +1552 -0
- package/dist/migrations/postgresql/meta/0003_snapshot.json +1695 -0
- package/dist/migrations/postgresql/meta/0010_snapshot.json +2345 -0
- package/dist/migrations/postgresql/meta/_journal.json +90 -0
- package/dist/migrations/sqlite/0000_api_keys.sql +34 -0
- package/dist/migrations/sqlite/0001_general_settings.sql +20 -0
- package/dist/migrations/sqlite/0002_site_settings_logo_url.sql +9 -0
- package/dist/migrations/sqlite/0003_activity_log.sql +29 -0
- package/dist/migrations/sqlite/0004_image_sizes_and_focal_point.sql +29 -0
- package/dist/migrations/sqlite/0004_site_settings_sidebar.sql +11 -0
- package/dist/migrations/sqlite/0005_user_brute_force_protection.sql +29 -0
- package/dist/migrations/sqlite/0006_email_template_attachments.sql +12 -0
- package/dist/migrations/sqlite/0007_media_uploaded_by_nullable.sql +111 -0
- package/dist/migrations/sqlite/20260429_000000_000_initial_journal.sql +24 -0
- package/dist/migrations/sqlite/20260501_000000_journal_batch.sql +19 -0
- package/dist/migrations/sqlite/20260501_000001_audit_log.sql +24 -0
- package/dist/migrations/sqlite/20260504_000000_nextly_meta.sql +21 -0
- package/dist/migrations/sqlite/20260505_000000_user_management_tables.sql +77 -0
- package/dist/next.d.ts +57 -0
- package/dist/next.mjs +55 -0
- package/dist/observability/index.d.ts +87 -0
- package/dist/observability/index.mjs +57 -0
- package/dist/permissions-3DZZQZMI.mjs +39 -0
- package/dist/pipeline-YOML7SWF.mjs +29 -0
- package/dist/preview-ZZTR3QGS.mjs +9 -0
- package/dist/program-PW6UB2ZC.mjs +5934 -0
- package/dist/reconcile-single-tables-7ENVXJGB.mjs +7 -0
- package/dist/register-SF6E6FVU.mjs +49 -0
- package/dist/reload-config-HWQ4G5MM.mjs +23 -0
- package/dist/resolve-single-table-name-JSOMUB3R.mjs +7 -0
- package/dist/routeHandler-UNMMJIBM.mjs +77 -0
- package/dist/runtime-schema-generator-NRA6A6Z6.mjs +8 -0
- package/dist/runtime.d.ts +120 -0
- package/dist/runtime.mjs +73 -0
- package/dist/schema-hash-FMMG6VPJ.mjs +13 -0
- package/dist/schema-registry-EQ36FZDP.mjs +7 -0
- package/dist/scripts/load-env.mjs +42 -0
- package/dist/storage/index.d.ts +566 -0
- package/dist/storage/index.mjs +45 -0
- package/dist/super-admin-G5ZK5F4T.mjs +39 -0
- package/dist/system-table-service-WGSRVEGT.mjs +17 -0
- package/dist/users-7KELGRYJ.mjs +38 -0
- package/package.json +308 -9
package/dist/index.d.ts
ADDED
|
@@ -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 };
|