@effect-auth/core 0.1.0-alpha.16 → 0.1.0-alpha.19
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 +21 -0
- package/README.md +307 -133
- package/dist/AbuseProtection.d.ts +100 -0
- package/dist/AbuseProtection.d.ts.map +1 -0
- package/dist/AbuseProtection.js +71 -0
- package/dist/AbuseProtection.js.map +1 -0
- package/dist/AccessGrant.d.ts +344 -0
- package/dist/AccessGrant.d.ts.map +1 -0
- package/dist/AccessGrant.js +687 -0
- package/dist/AccessGrant.js.map +1 -0
- package/dist/ApiKey.d.ts +0 -12
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +36 -27
- package/dist/ApiKey.js.map +1 -1
- package/dist/Assurance.d.ts +415 -0
- package/dist/Assurance.d.ts.map +1 -0
- package/dist/Assurance.js +764 -0
- package/dist/Assurance.js.map +1 -0
- package/dist/AtomicPlanExecutor.d.ts +28 -0
- package/dist/AtomicPlanExecutor.d.ts.map +1 -0
- package/dist/AtomicPlanExecutor.js +5 -0
- package/dist/AtomicPlanExecutor.js.map +1 -0
- package/dist/AuditLog.d.ts +2314 -52
- package/dist/AuditLog.d.ts.map +1 -1
- package/dist/AuditLog.js +511 -33
- package/dist/AuditLog.js.map +1 -1
- package/dist/AuthFlow.d.ts +128 -38
- package/dist/AuthFlow.d.ts.map +1 -1
- package/dist/AuthFlow.js +611 -263
- package/dist/AuthFlow.js.map +1 -1
- package/dist/AuthRateLimit.d.ts +96 -0
- package/dist/AuthRateLimit.d.ts.map +1 -0
- package/dist/AuthRateLimit.js +212 -0
- package/dist/AuthRateLimit.js.map +1 -0
- package/dist/Challenge.d.ts +0 -3
- package/dist/Challenge.d.ts.map +1 -1
- package/dist/Challenge.js +1 -4
- package/dist/Challenge.js.map +1 -1
- package/dist/Client.d.ts +205 -10
- package/dist/Client.d.ts.map +1 -1
- package/dist/Client.js +397 -16
- package/dist/Client.js.map +1 -1
- package/dist/CloudflareTurnstile.d.ts +28 -0
- package/dist/CloudflareTurnstile.d.ts.map +1 -0
- package/dist/CloudflareTurnstile.js +205 -0
- package/dist/CloudflareTurnstile.js.map +1 -0
- package/dist/Crypto.d.ts +0 -3
- package/dist/Crypto.d.ts.map +1 -1
- package/dist/Crypto.js +1 -4
- package/dist/Crypto.js.map +1 -1
- package/dist/DelegatedAccessStorageMigrations.d.ts +7 -0
- package/dist/DelegatedAccessStorageMigrations.d.ts.map +1 -0
- package/dist/DelegatedAccessStorageMigrations.js +159 -0
- package/dist/DelegatedAccessStorageMigrations.js.map +1 -0
- package/dist/DevEmail.d.ts +44 -0
- package/dist/DevEmail.d.ts.map +1 -0
- package/dist/DevEmail.js +115 -0
- package/dist/DevEmail.js.map +1 -0
- package/dist/DevelopmentSeed.d.ts +47 -0
- package/dist/DevelopmentSeed.d.ts.map +1 -0
- package/dist/DevelopmentSeed.js +337 -0
- package/dist/DevelopmentSeed.js.map +1 -0
- package/dist/DisposableEmailDomains.d.ts +19 -0
- package/dist/DisposableEmailDomains.d.ts.map +1 -0
- package/dist/DisposableEmailDomains.js +85 -0
- package/dist/DisposableEmailDomains.js.map +1 -0
- package/dist/DomainVerification.d.ts +0 -9
- package/dist/DomainVerification.d.ts.map +1 -1
- package/dist/DomainVerification.js +36 -22
- package/dist/DomainVerification.js.map +1 -1
- package/dist/DrizzleBunSqliteStorage.d.ts +18 -0
- package/dist/DrizzleBunSqliteStorage.d.ts.map +1 -0
- package/dist/DrizzleBunSqliteStorage.js +11 -0
- package/dist/DrizzleBunSqliteStorage.js.map +1 -0
- package/dist/DrizzleD1SqliteStorage.d.ts +4 -4
- package/dist/DrizzleD1SqliteStorage.d.ts.map +1 -1
- package/dist/DrizzleD1SqliteStorage.js +5 -5
- package/dist/DrizzleD1SqliteStorage.js.map +1 -1
- package/dist/DrizzleEffectSqliteStorage.d.ts +13 -4
- package/dist/DrizzleEffectSqliteStorage.d.ts.map +1 -1
- package/dist/DrizzleEffectSqliteStorage.js +71 -4
- package/dist/DrizzleEffectSqliteStorage.js.map +1 -1
- package/dist/DrizzleNodeSqliteStorage.d.ts +18 -0
- package/dist/DrizzleNodeSqliteStorage.d.ts.map +1 -0
- package/dist/DrizzleNodeSqliteStorage.js +11 -0
- package/dist/DrizzleNodeSqliteStorage.js.map +1 -0
- package/dist/DrizzlePostgresStorage.d.ts +26 -0
- package/dist/DrizzlePostgresStorage.d.ts.map +1 -0
- package/dist/DrizzlePostgresStorage.js +14 -0
- package/dist/DrizzlePostgresStorage.js.map +1 -0
- package/dist/EffectQbPostgresDelegatedAccessStorage.d.ts +34 -0
- package/dist/EffectQbPostgresDelegatedAccessStorage.d.ts.map +1 -0
- package/dist/EffectQbPostgresDelegatedAccessStorage.js +499 -0
- package/dist/EffectQbPostgresDelegatedAccessStorage.js.map +1 -0
- package/dist/EffectQbPostgresStorage.d.ts +178 -0
- package/dist/EffectQbPostgresStorage.d.ts.map +1 -0
- package/dist/EffectQbPostgresStorage.js +4637 -0
- package/dist/EffectQbPostgresStorage.js.map +1 -0
- package/dist/EffectQbSqliteDelegatedAccessStorage.d.ts +112 -0
- package/dist/EffectQbSqliteDelegatedAccessStorage.d.ts.map +1 -0
- package/dist/EffectQbSqliteDelegatedAccessStorage.js +602 -0
- package/dist/EffectQbSqliteDelegatedAccessStorage.js.map +1 -0
- package/dist/EffectQbSqliteStorage.d.ts +221 -23
- package/dist/EffectQbSqliteStorage.d.ts.map +1 -1
- package/dist/EffectQbSqliteStorage.js +2064 -135
- package/dist/EffectQbSqliteStorage.js.map +1 -1
- package/dist/EmailAuth.d.ts +65 -0
- package/dist/EmailAuth.d.ts.map +1 -0
- package/dist/EmailAuth.js +171 -0
- package/dist/EmailAuth.js.map +1 -0
- package/dist/EmailIdentityAuth.d.ts +30 -0
- package/dist/EmailIdentityAuth.d.ts.map +1 -0
- package/dist/EmailIdentityAuth.js +142 -0
- package/dist/EmailIdentityAuth.js.map +1 -0
- package/dist/EmailOtp.d.ts +10 -11
- package/dist/EmailOtp.d.ts.map +1 -1
- package/dist/EmailOtp.js +44 -81
- package/dist/EmailOtp.js.map +1 -1
- package/dist/EmailRisk.d.ts +48 -0
- package/dist/EmailRisk.d.ts.map +1 -0
- package/dist/EmailRisk.js +33 -0
- package/dist/EmailRisk.js.map +1 -0
- package/dist/EmailVerification.d.ts +10 -16
- package/dist/EmailVerification.d.ts.map +1 -1
- package/dist/EmailVerification.js +85 -42
- package/dist/EmailVerification.js.map +1 -1
- package/dist/Guard.d.ts +11 -0
- package/dist/Guard.d.ts.map +1 -0
- package/dist/Guard.js +11 -0
- package/dist/Guard.js.map +1 -0
- package/dist/HibpPwnedPasswords.d.ts +56 -0
- package/dist/HibpPwnedPasswords.d.ts.map +1 -0
- package/dist/HibpPwnedPasswords.js +232 -0
- package/dist/HibpPwnedPasswords.js.map +1 -0
- package/dist/HttpApi/AdminPermissionDefinition.d.ts +4 -0
- package/dist/HttpApi/AdminPermissionDefinition.d.ts.map +1 -0
- package/dist/HttpApi/AdminPermissionDefinition.js +4 -0
- package/dist/HttpApi/AdminPermissionDefinition.js.map +1 -0
- package/dist/HttpApi/AdminSecurityTimeline.d.ts +4 -0
- package/dist/HttpApi/AdminSecurityTimeline.d.ts.map +1 -0
- package/dist/HttpApi/AdminSecurityTimeline.js +4 -0
- package/dist/HttpApi/AdminSecurityTimeline.js.map +1 -0
- package/dist/HttpApi/AdminSession.d.ts +4 -0
- package/dist/HttpApi/AdminSession.d.ts.map +1 -0
- package/dist/HttpApi/AdminSession.js +4 -0
- package/dist/HttpApi/AdminSession.js.map +1 -0
- package/dist/HttpApi/AdminTrustedDevice.d.ts +4 -0
- package/dist/HttpApi/AdminTrustedDevice.d.ts.map +1 -0
- package/dist/HttpApi/AdminTrustedDevice.js +4 -0
- package/dist/HttpApi/AdminTrustedDevice.js.map +1 -0
- package/dist/HttpApi/Api.d.ts +939 -884
- package/dist/HttpApi/Api.d.ts.map +1 -1
- package/dist/HttpApi/Api.js +2254 -940
- package/dist/HttpApi/Api.js.map +1 -1
- package/dist/HttpApi/ApiKey.d.ts +4 -0
- package/dist/HttpApi/ApiKey.d.ts.map +1 -0
- package/dist/HttpApi/ApiKey.js +4 -0
- package/dist/HttpApi/ApiKey.js.map +1 -0
- package/dist/HttpApi/Audit.d.ts +6 -0
- package/dist/HttpApi/Audit.d.ts.map +1 -0
- package/dist/HttpApi/Audit.js +10 -0
- package/dist/HttpApi/Audit.js.map +1 -0
- package/dist/HttpApi/ClientApi.d.ts +917 -0
- package/dist/HttpApi/ClientApi.d.ts.map +1 -0
- package/dist/HttpApi/ClientApi.js +101 -0
- package/dist/HttpApi/ClientApi.js.map +1 -0
- package/dist/HttpApi/EmailAuth.d.ts +6 -0
- package/dist/HttpApi/EmailAuth.d.ts.map +1 -0
- package/dist/HttpApi/EmailAuth.js +6 -0
- package/dist/HttpApi/EmailAuth.js.map +1 -0
- package/dist/HttpApi/EmailGuards.d.ts +115 -0
- package/dist/HttpApi/EmailGuards.d.ts.map +1 -0
- package/dist/HttpApi/EmailGuards.js +191 -0
- package/dist/HttpApi/EmailGuards.js.map +1 -0
- package/dist/HttpApi/EmailOtp.d.ts +6 -0
- package/dist/HttpApi/EmailOtp.d.ts.map +1 -0
- package/dist/HttpApi/EmailOtp.js +6 -0
- package/dist/HttpApi/EmailOtp.js.map +1 -0
- package/dist/HttpApi/EmailVerification.d.ts +6 -0
- package/dist/HttpApi/EmailVerification.d.ts.map +1 -0
- package/dist/HttpApi/EmailVerification.js +6 -0
- package/dist/HttpApi/EmailVerification.js.map +1 -0
- package/dist/HttpApi/Endpoints.d.ts +661 -301
- package/dist/HttpApi/Endpoints.d.ts.map +1 -1
- package/dist/HttpApi/Endpoints.js +207 -120
- package/dist/HttpApi/Endpoints.js.map +1 -1
- package/dist/HttpApi/Errors.d.ts +37 -10
- package/dist/HttpApi/Errors.d.ts.map +1 -1
- package/dist/HttpApi/Errors.js +42 -4
- package/dist/HttpApi/Errors.js.map +1 -1
- package/dist/HttpApi/Identity.d.ts +6 -0
- package/dist/HttpApi/Identity.d.ts.map +1 -0
- package/dist/HttpApi/Identity.js +6 -0
- package/dist/HttpApi/Identity.js.map +1 -0
- package/dist/HttpApi/IdentityGuards.d.ts +31 -0
- package/dist/HttpApi/IdentityGuards.d.ts.map +1 -0
- package/dist/HttpApi/IdentityGuards.js +33 -0
- package/dist/HttpApi/IdentityGuards.js.map +1 -0
- package/dist/HttpApi/Jwt.d.ts +4 -0
- package/dist/HttpApi/Jwt.d.ts.map +1 -0
- package/dist/HttpApi/Jwt.js +4 -0
- package/dist/HttpApi/Jwt.js.map +1 -0
- package/dist/HttpApi/JwtDiscovery.d.ts +4 -0
- package/dist/HttpApi/JwtDiscovery.d.ts.map +1 -0
- package/dist/HttpApi/JwtDiscovery.js +4 -0
- package/dist/HttpApi/JwtDiscovery.js.map +1 -0
- package/dist/HttpApi/LoginApproval.d.ts +5 -0
- package/dist/HttpApi/LoginApproval.d.ts.map +1 -0
- package/dist/HttpApi/LoginApproval.js +5 -0
- package/dist/HttpApi/LoginApproval.js.map +1 -0
- package/dist/HttpApi/LoginNotification.d.ts +5 -0
- package/dist/HttpApi/LoginNotification.d.ts.map +1 -0
- package/dist/HttpApi/LoginNotification.js +5 -0
- package/dist/HttpApi/LoginNotification.js.map +1 -0
- package/dist/HttpApi/MagicLink.d.ts +6 -0
- package/dist/HttpApi/MagicLink.d.ts.map +1 -0
- package/dist/HttpApi/MagicLink.js +6 -0
- package/dist/HttpApi/MagicLink.js.map +1 -0
- package/dist/HttpApi/Mfa.d.ts +5 -0
- package/dist/HttpApi/Mfa.d.ts.map +1 -0
- package/dist/HttpApi/Mfa.js +5 -0
- package/dist/HttpApi/Mfa.js.map +1 -0
- package/dist/HttpApi/Middleware.d.ts +26 -0
- package/dist/HttpApi/Middleware.d.ts.map +1 -0
- package/dist/HttpApi/Middleware.js +13 -0
- package/dist/HttpApi/Middleware.js.map +1 -0
- package/dist/HttpApi/OAuth.d.ts +4 -0
- package/dist/HttpApi/OAuth.d.ts.map +1 -0
- package/dist/HttpApi/OAuth.js +4 -0
- package/dist/HttpApi/OAuth.js.map +1 -0
- package/dist/HttpApi/OAuthDeviceAuthorization.d.ts +106 -0
- package/dist/HttpApi/OAuthDeviceAuthorization.d.ts.map +1 -0
- package/dist/HttpApi/OAuthDeviceAuthorization.js +415 -0
- package/dist/HttpApi/OAuthDeviceAuthorization.js.map +1 -0
- package/dist/HttpApi/OAuthProviderAuthorization.d.ts +4 -0
- package/dist/HttpApi/OAuthProviderAuthorization.d.ts.map +1 -0
- package/dist/HttpApi/OAuthProviderAuthorization.js +4 -0
- package/dist/HttpApi/OAuthProviderAuthorization.js.map +1 -0
- package/dist/HttpApi/OAuthToken.d.ts +4 -0
- package/dist/HttpApi/OAuthToken.d.ts.map +1 -0
- package/dist/HttpApi/OAuthToken.js +4 -0
- package/dist/HttpApi/OAuthToken.js.map +1 -0
- package/dist/HttpApi/OidcDiscovery.d.ts +4 -0
- package/dist/HttpApi/OidcDiscovery.d.ts.map +1 -0
- package/dist/HttpApi/OidcDiscovery.js +4 -0
- package/dist/HttpApi/OidcDiscovery.js.map +1 -0
- package/dist/HttpApi/Operations/AdminPermissionDefinition.d.ts +28 -0
- package/dist/HttpApi/Operations/AdminPermissionDefinition.d.ts.map +1 -0
- package/dist/HttpApi/Operations/AdminPermissionDefinition.js +5 -0
- package/dist/HttpApi/Operations/AdminPermissionDefinition.js.map +1 -0
- package/dist/HttpApi/Operations/AdminSession.d.ts +16 -0
- package/dist/HttpApi/Operations/AdminSession.d.ts.map +1 -0
- package/dist/HttpApi/Operations/AdminSession.js +5 -0
- package/dist/HttpApi/Operations/AdminSession.js.map +1 -0
- package/dist/HttpApi/Operations/ApiKey.d.ts +16 -0
- package/dist/HttpApi/Operations/ApiKey.d.ts.map +1 -0
- package/dist/HttpApi/Operations/ApiKey.js +5 -0
- package/dist/HttpApi/Operations/ApiKey.js.map +1 -0
- package/dist/HttpApi/Operations/Discovery.d.ts +19 -0
- package/dist/HttpApi/Operations/Discovery.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Discovery.js +7 -0
- package/dist/HttpApi/Operations/Discovery.js.map +1 -0
- package/dist/HttpApi/Operations/EmailAuth.d.ts +12 -0
- package/dist/HttpApi/Operations/EmailAuth.d.ts.map +1 -0
- package/dist/HttpApi/Operations/EmailAuth.js +5 -0
- package/dist/HttpApi/Operations/EmailAuth.js.map +1 -0
- package/dist/HttpApi/Operations/EmailOtp.d.ts +14 -0
- package/dist/HttpApi/Operations/EmailOtp.d.ts.map +1 -0
- package/dist/HttpApi/Operations/EmailOtp.js +5 -0
- package/dist/HttpApi/Operations/EmailOtp.js.map +1 -0
- package/dist/HttpApi/Operations/EmailVerification.d.ts +14 -0
- package/dist/HttpApi/Operations/EmailVerification.d.ts.map +1 -0
- package/dist/HttpApi/Operations/EmailVerification.js +5 -0
- package/dist/HttpApi/Operations/EmailVerification.js.map +1 -0
- package/dist/HttpApi/Operations/HttpOperation.d.ts +4 -0
- package/dist/HttpApi/Operations/HttpOperation.d.ts.map +1 -0
- package/dist/HttpApi/Operations/HttpOperation.js +2 -0
- package/dist/HttpApi/Operations/HttpOperation.js.map +1 -0
- package/dist/HttpApi/Operations/Identity.d.ts +22 -0
- package/dist/HttpApi/Operations/Identity.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Identity.js +5 -0
- package/dist/HttpApi/Operations/Identity.js.map +1 -0
- package/dist/HttpApi/Operations/Jwt.d.ts +14 -0
- package/dist/HttpApi/Operations/Jwt.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Jwt.js +5 -0
- package/dist/HttpApi/Operations/Jwt.js.map +1 -0
- package/dist/HttpApi/Operations/LoginApproval.d.ts +16 -0
- package/dist/HttpApi/Operations/LoginApproval.d.ts.map +1 -0
- package/dist/HttpApi/Operations/LoginApproval.js +5 -0
- package/dist/HttpApi/Operations/LoginApproval.js.map +1 -0
- package/dist/HttpApi/Operations/MagicLink.d.ts +14 -0
- package/dist/HttpApi/Operations/MagicLink.d.ts.map +1 -0
- package/dist/HttpApi/Operations/MagicLink.js +5 -0
- package/dist/HttpApi/Operations/MagicLink.js.map +1 -0
- package/dist/HttpApi/Operations/Mfa.d.ts +24 -0
- package/dist/HttpApi/Operations/Mfa.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Mfa.js +5 -0
- package/dist/HttpApi/Operations/Mfa.js.map +1 -0
- package/dist/HttpApi/Operations/OAuth.d.ts +20 -0
- package/dist/HttpApi/Operations/OAuth.d.ts.map +1 -0
- package/dist/HttpApi/Operations/OAuth.js +5 -0
- package/dist/HttpApi/Operations/OAuth.js.map +1 -0
- package/dist/HttpApi/Operations/OAuthDeviceAuthorization.d.ts +23 -0
- package/dist/HttpApi/Operations/OAuthDeviceAuthorization.d.ts.map +1 -0
- package/dist/HttpApi/Operations/OAuthDeviceAuthorization.js +7 -0
- package/dist/HttpApi/Operations/OAuthDeviceAuthorization.js.map +1 -0
- package/dist/HttpApi/Operations/OAuthProviderAuthorization.d.ts +12 -0
- package/dist/HttpApi/Operations/OAuthProviderAuthorization.d.ts.map +1 -0
- package/dist/HttpApi/Operations/OAuthProviderAuthorization.js +5 -0
- package/dist/HttpApi/Operations/OAuthProviderAuthorization.js.map +1 -0
- package/dist/HttpApi/Operations/OAuthToken.d.ts +26 -0
- package/dist/HttpApi/Operations/OAuthToken.d.ts.map +1 -0
- package/dist/HttpApi/Operations/OAuthToken.js +9 -0
- package/dist/HttpApi/Operations/OAuthToken.js.map +1 -0
- package/dist/HttpApi/Operations/Passkey.d.ts +22 -0
- package/dist/HttpApi/Operations/Passkey.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Passkey.js +5 -0
- package/dist/HttpApi/Operations/Passkey.js.map +1 -0
- package/dist/HttpApi/Operations/Password.d.ts +22 -0
- package/dist/HttpApi/Operations/Password.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Password.js +5 -0
- package/dist/HttpApi/Operations/Password.js.map +1 -0
- package/dist/HttpApi/Operations/RecoveryCodes.d.ts +20 -0
- package/dist/HttpApi/Operations/RecoveryCodes.d.ts.map +1 -0
- package/dist/HttpApi/Operations/RecoveryCodes.js +5 -0
- package/dist/HttpApi/Operations/RecoveryCodes.js.map +1 -0
- package/dist/HttpApi/Operations/RefreshToken.d.ts +12 -0
- package/dist/HttpApi/Operations/RefreshToken.d.ts.map +1 -0
- package/dist/HttpApi/Operations/RefreshToken.js +5 -0
- package/dist/HttpApi/Operations/RefreshToken.js.map +1 -0
- package/dist/HttpApi/Operations/Security.d.ts +12 -0
- package/dist/HttpApi/Operations/Security.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Security.js +5 -0
- package/dist/HttpApi/Operations/Security.js.map +1 -0
- package/dist/HttpApi/Operations/SecurityTimeline.d.ts +19 -0
- package/dist/HttpApi/Operations/SecurityTimeline.d.ts.map +1 -0
- package/dist/HttpApi/Operations/SecurityTimeline.js +7 -0
- package/dist/HttpApi/Operations/SecurityTimeline.js.map +1 -0
- package/dist/HttpApi/Operations/Session.d.ts +22 -0
- package/dist/HttpApi/Operations/Session.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Session.js +5 -0
- package/dist/HttpApi/Operations/Session.js.map +1 -0
- package/dist/HttpApi/Operations/StepUp.d.ts +22 -0
- package/dist/HttpApi/Operations/StepUp.d.ts.map +1 -0
- package/dist/HttpApi/Operations/StepUp.js +5 -0
- package/dist/HttpApi/Operations/StepUp.js.map +1 -0
- package/dist/HttpApi/Operations/Totp.d.ts +20 -0
- package/dist/HttpApi/Operations/Totp.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Totp.js +5 -0
- package/dist/HttpApi/Operations/Totp.js.map +1 -0
- package/dist/HttpApi/Operations/TrustedDevice.d.ts +23 -0
- package/dist/HttpApi/Operations/TrustedDevice.d.ts.map +1 -0
- package/dist/HttpApi/Operations/TrustedDevice.js +7 -0
- package/dist/HttpApi/Operations/TrustedDevice.js.map +1 -0
- package/dist/HttpApi/Operations/index.d.ts +28 -0
- package/dist/HttpApi/Operations/index.d.ts.map +1 -0
- package/dist/HttpApi/Operations/index.js +28 -0
- package/dist/HttpApi/Operations/index.js.map +1 -0
- package/dist/HttpApi/Passkey.d.ts +5 -0
- package/dist/HttpApi/Passkey.d.ts.map +1 -0
- package/dist/HttpApi/Passkey.js +5 -0
- package/dist/HttpApi/Passkey.js.map +1 -0
- package/dist/HttpApi/Password.d.ts +220 -0
- package/dist/HttpApi/Password.d.ts.map +1 -0
- package/dist/HttpApi/Password.js +237 -0
- package/dist/HttpApi/Password.js.map +1 -0
- package/dist/HttpApi/PasswordContract.d.ts +307 -0
- package/dist/HttpApi/PasswordContract.d.ts.map +1 -0
- package/dist/HttpApi/PasswordContract.js +63 -0
- package/dist/HttpApi/PasswordContract.js.map +1 -0
- package/dist/HttpApi/PasswordGuards.d.ts +82 -0
- package/dist/HttpApi/PasswordGuards.d.ts.map +1 -0
- package/dist/HttpApi/PasswordGuards.js +179 -0
- package/dist/HttpApi/PasswordGuards.js.map +1 -0
- package/dist/HttpApi/RecoveryCodes.d.ts +5 -0
- package/dist/HttpApi/RecoveryCodes.d.ts.map +1 -0
- package/dist/HttpApi/RecoveryCodes.js +5 -0
- package/dist/HttpApi/RecoveryCodes.js.map +1 -0
- package/dist/HttpApi/RefreshToken.d.ts +4 -0
- package/dist/HttpApi/RefreshToken.d.ts.map +1 -0
- package/dist/HttpApi/RefreshToken.js +4 -0
- package/dist/HttpApi/RefreshToken.js.map +1 -0
- package/dist/HttpApi/RequestGuards.d.ts +42 -0
- package/dist/HttpApi/RequestGuards.d.ts.map +1 -0
- package/dist/HttpApi/RequestGuards.js +194 -0
- package/dist/HttpApi/RequestGuards.js.map +1 -0
- package/dist/HttpApi/Schemas.d.ts +399 -84
- package/dist/HttpApi/Schemas.d.ts.map +1 -1
- package/dist/HttpApi/Schemas.js +225 -27
- package/dist/HttpApi/Schemas.js.map +1 -1
- package/dist/HttpApi/Security.d.ts +12 -93
- package/dist/HttpApi/Security.d.ts.map +1 -1
- package/dist/HttpApi/Security.js +65 -356
- package/dist/HttpApi/Security.js.map +1 -1
- package/dist/HttpApi/SecurityTimeline.d.ts +4 -0
- package/dist/HttpApi/SecurityTimeline.d.ts.map +1 -0
- package/dist/HttpApi/SecurityTimeline.js +4 -0
- package/dist/HttpApi/SecurityTimeline.js.map +1 -0
- package/dist/HttpApi/Session.d.ts +5 -0
- package/dist/HttpApi/Session.d.ts.map +1 -0
- package/dist/HttpApi/Session.js +5 -0
- package/dist/HttpApi/Session.js.map +1 -0
- package/dist/HttpApi/SessionGuards.d.ts +15 -0
- package/dist/HttpApi/SessionGuards.d.ts.map +1 -0
- package/dist/HttpApi/SessionGuards.js +37 -0
- package/dist/HttpApi/SessionGuards.js.map +1 -0
- package/dist/HttpApi/StepUp.d.ts +5 -0
- package/dist/HttpApi/StepUp.d.ts.map +1 -0
- package/dist/HttpApi/StepUp.js +5 -0
- package/dist/HttpApi/StepUp.js.map +1 -0
- package/dist/HttpApi/Totp.d.ts +5 -0
- package/dist/HttpApi/Totp.d.ts.map +1 -0
- package/dist/HttpApi/Totp.js +5 -0
- package/dist/HttpApi/Totp.js.map +1 -0
- package/dist/HttpApi/Transport.d.ts +4 -6
- package/dist/HttpApi/Transport.d.ts.map +1 -1
- package/dist/HttpApi/Transport.js +62 -36
- package/dist/HttpApi/Transport.js.map +1 -1
- package/dist/HttpApi/TrustedDevice.d.ts +4 -0
- package/dist/HttpApi/TrustedDevice.d.ts.map +1 -0
- package/dist/HttpApi/TrustedDevice.js +4 -0
- package/dist/HttpApi/TrustedDevice.js.map +1 -0
- package/dist/HttpApi/index.d.ts +11 -3
- package/dist/HttpApi/index.d.ts.map +1 -1
- package/dist/HttpApi/index.js +10 -2
- package/dist/HttpApi/index.js.map +1 -1
- package/dist/Identity.d.ts +138 -0
- package/dist/Identity.d.ts.map +1 -0
- package/dist/Identity.js +105 -0
- package/dist/Identity.js.map +1 -0
- package/dist/IdentityManagement.d.ts +189 -0
- package/dist/IdentityManagement.d.ts.map +1 -0
- package/dist/IdentityManagement.js +317 -0
- package/dist/IdentityManagement.js.map +1 -0
- package/dist/IncidentAction.d.ts +1 -4
- package/dist/IncidentAction.d.ts.map +1 -1
- package/dist/IncidentAction.js +15 -9
- package/dist/IncidentAction.js.map +1 -1
- package/dist/Internal.d.ts +2 -0
- package/dist/Internal.d.ts.map +1 -1
- package/dist/Internal.js +30 -0
- package/dist/Internal.js.map +1 -1
- package/dist/Invitation.d.ts +362 -0
- package/dist/Invitation.d.ts.map +1 -0
- package/dist/Invitation.js +633 -0
- package/dist/Invitation.js.map +1 -0
- package/dist/IpQualityScore.d.ts +38 -0
- package/dist/IpQualityScore.d.ts.map +1 -0
- package/dist/IpQualityScore.js +215 -0
- package/dist/IpQualityScore.js.map +1 -0
- package/dist/Jwt.d.ts +8 -29
- package/dist/Jwt.d.ts.map +1 -1
- package/dist/Jwt.js +67 -56
- package/dist/Jwt.js.map +1 -1
- package/dist/LoginApproval.d.ts +15 -30
- package/dist/LoginApproval.d.ts.map +1 -1
- package/dist/LoginApproval.js +47 -41
- package/dist/LoginApproval.js.map +1 -1
- package/dist/LoginNotification.d.ts +7 -11
- package/dist/LoginNotification.d.ts.map +1 -1
- package/dist/LoginNotification.js +30 -17
- package/dist/LoginNotification.js.map +1 -1
- package/dist/LoginRisk.d.ts +11 -13
- package/dist/LoginRisk.d.ts.map +1 -1
- package/dist/LoginRisk.js +66 -26
- package/dist/LoginRisk.js.map +1 -1
- package/dist/LoginRiskEnrichment.d.ts +145 -0
- package/dist/LoginRiskEnrichment.d.ts.map +1 -0
- package/dist/LoginRiskEnrichment.js +220 -0
- package/dist/LoginRiskEnrichment.js.map +1 -0
- package/dist/MagicLink.d.ts +9 -8
- package/dist/MagicLink.d.ts.map +1 -1
- package/dist/MagicLink.js +40 -73
- package/dist/MagicLink.js.map +1 -1
- package/dist/Mailer.d.ts +19 -12
- package/dist/Mailer.d.ts.map +1 -1
- package/dist/Mailer.js +10 -12
- package/dist/Mailer.js.map +1 -1
- package/dist/OAuth.d.ts +138 -96
- package/dist/OAuth.d.ts.map +1 -1
- package/dist/OAuth.js +522 -221
- package/dist/OAuth.js.map +1 -1
- package/dist/OAuthDeviceAuthorization.d.ts +378 -0
- package/dist/OAuthDeviceAuthorization.d.ts.map +1 -0
- package/dist/OAuthDeviceAuthorization.js +860 -0
- package/dist/OAuthDeviceAuthorization.js.map +1 -0
- package/dist/OAuthDeviceClient.d.ts +76 -0
- package/dist/OAuthDeviceClient.d.ts.map +1 -0
- package/dist/OAuthDeviceClient.js +362 -0
- package/dist/OAuthDeviceClient.js.map +1 -0
- package/dist/Passkey.d.ts +15 -17
- package/dist/Passkey.d.ts.map +1 -1
- package/dist/Passkey.js +86 -39
- package/dist/Passkey.js.map +1 -1
- package/dist/PasskeyBrowser.d.ts +39 -0
- package/dist/PasskeyBrowser.d.ts.map +1 -0
- package/dist/PasskeyBrowser.js +206 -0
- package/dist/PasskeyBrowser.js.map +1 -0
- package/dist/PasskeySimpleWebAuthn.d.ts.map +1 -1
- package/dist/PasskeySimpleWebAuthn.js +19 -7
- package/dist/PasskeySimpleWebAuthn.js.map +1 -1
- package/dist/Password.d.ts +71 -37
- package/dist/Password.d.ts.map +1 -1
- package/dist/Password.js +295 -81
- package/dist/Password.js.map +1 -1
- package/dist/PasswordRisk.d.ts +63 -0
- package/dist/PasswordRisk.d.ts.map +1 -0
- package/dist/PasswordRisk.js +37 -0
- package/dist/PasswordRisk.js.map +1 -0
- package/dist/Permission.d.ts +308 -0
- package/dist/Permission.d.ts.map +1 -0
- package/dist/Permission.js +827 -0
- package/dist/Permission.js.map +1 -0
- package/dist/Policy.d.ts +31 -18
- package/dist/Policy.d.ts.map +1 -1
- package/dist/Policy.js +58 -14
- package/dist/Policy.js.map +1 -1
- package/dist/PostgresDelegatedAccessStorageMigrations.d.ts +7 -0
- package/dist/PostgresDelegatedAccessStorageMigrations.d.ts.map +1 -0
- package/dist/PostgresDelegatedAccessStorageMigrations.js +119 -0
- package/dist/PostgresDelegatedAccessStorageMigrations.js.map +1 -0
- package/dist/PostgresStorageMigrations.d.ts +16 -0
- package/dist/PostgresStorageMigrations.d.ts.map +1 -0
- package/dist/PostgresStorageMigrations.js +674 -0
- package/dist/PostgresStorageMigrations.js.map +1 -0
- package/dist/Privacy.d.ts +0 -3
- package/dist/Privacy.d.ts.map +1 -1
- package/dist/Privacy.js +2 -5
- package/dist/Privacy.js.map +1 -1
- package/dist/RateLimiter.d.ts +0 -3
- package/dist/RateLimiter.d.ts.map +1 -1
- package/dist/RateLimiter.js +1 -4
- package/dist/RateLimiter.js.map +1 -1
- package/dist/RecoveryCode.d.ts +83 -11
- package/dist/RecoveryCode.d.ts.map +1 -1
- package/dist/RecoveryCode.js +273 -75
- package/dist/RecoveryCode.js.map +1 -1
- package/dist/RecoveryPolicy.d.ts +81 -0
- package/dist/RecoveryPolicy.d.ts.map +1 -0
- package/dist/RecoveryPolicy.js +119 -0
- package/dist/RecoveryPolicy.js.map +1 -0
- package/dist/RefreshToken.d.ts +0 -9
- package/dist/RefreshToken.d.ts.map +1 -1
- package/dist/RefreshToken.js +31 -22
- package/dist/RefreshToken.js.map +1 -1
- package/dist/Retention.d.ts +6 -1
- package/dist/Retention.d.ts.map +1 -1
- package/dist/Retention.js +49 -12
- package/dist/Retention.js.map +1 -1
- package/dist/SecurityTimeline.d.ts +1 -4
- package/dist/SecurityTimeline.d.ts.map +1 -1
- package/dist/SecurityTimeline.js +110 -17
- package/dist/SecurityTimeline.js.map +1 -1
- package/dist/Sessions.d.ts +124 -29
- package/dist/Sessions.d.ts.map +1 -1
- package/dist/Sessions.js +626 -94
- package/dist/Sessions.js.map +1 -1
- package/dist/SqliteStorageSchemaData.d.ts +2 -0
- package/dist/SqliteStorageSchemaData.d.ts.map +1 -0
- package/dist/SqliteStorageSchemaData.js +508 -0
- package/dist/SqliteStorageSchemaData.js.map +1 -0
- package/dist/StepUp.d.ts +132 -11
- package/dist/StepUp.d.ts.map +1 -1
- package/dist/StepUp.js +387 -19
- package/dist/StepUp.js.map +1 -1
- package/dist/Storage.d.ts +89 -23
- package/dist/Storage.d.ts.map +1 -1
- package/dist/Storage.js +10 -12
- package/dist/Storage.js.map +1 -1
- package/dist/StorageMigrations.d.ts +7 -1
- package/dist/StorageMigrations.d.ts.map +1 -1
- package/dist/StorageMigrations.js +256 -0
- package/dist/StorageMigrations.js.map +1 -1
- package/dist/StorageSchemaGenerator.d.ts +544 -0
- package/dist/StorageSchemaGenerator.d.ts.map +1 -0
- package/dist/StorageSchemaGenerator.js +1418 -0
- package/dist/StorageSchemaGenerator.js.map +1 -0
- package/dist/StrongFactor.d.ts +64 -0
- package/dist/StrongFactor.d.ts.map +1 -0
- package/dist/StrongFactor.js +100 -0
- package/dist/StrongFactor.js.map +1 -0
- package/dist/Testing.js +2 -2
- package/dist/Testing.js.map +1 -1
- package/dist/Totp.d.ts +88 -13
- package/dist/Totp.d.ts.map +1 -1
- package/dist/Totp.js +192 -34
- package/dist/Totp.js.map +1 -1
- package/dist/TrustedDevice.d.ts +0 -9
- package/dist/TrustedDevice.d.ts.map +1 -1
- package/dist/TrustedDevice.js +15 -17
- package/dist/TrustedDevice.js.map +1 -1
- package/dist/WaitUntil.d.ts +0 -3
- package/dist/WaitUntil.d.ts.map +1 -1
- package/dist/WaitUntil.js +1 -4
- package/dist/WaitUntil.js.map +1 -1
- package/dist/Webhook.d.ts +42 -12
- package/dist/Webhook.d.ts.map +1 -1
- package/dist/Webhook.js +165 -26
- package/dist/Webhook.js.map +1 -1
- package/dist/alchemy/cloudflare/Email.d.ts.map +1 -1
- package/dist/alchemy/cloudflare/Email.js +9 -4
- package/dist/alchemy/cloudflare/Email.js.map +1 -1
- package/dist/cloudflare/Email.js +1 -1
- package/dist/cloudflare/Email.js.map +1 -1
- package/dist/cloudflare/RequestMetadata.d.ts +49 -0
- package/dist/cloudflare/RequestMetadata.d.ts.map +1 -0
- package/dist/cloudflare/RequestMetadata.js +71 -0
- package/dist/cloudflare/RequestMetadata.js.map +1 -0
- package/dist/index.d.ts +0 -35
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -35
- package/dist/index.js.map +1 -1
- package/dist/internal/AuthFlowFinalizer.d.ts +31 -0
- package/dist/internal/AuthFlowFinalizer.d.ts.map +1 -0
- package/dist/internal/AuthFlowFinalizer.js +182 -0
- package/dist/internal/AuthFlowFinalizer.js.map +1 -0
- package/migrations/0001_auth_storage.sql +1 -0
- package/migrations/0006_auth_totp_factor.sql +1 -0
- package/migrations/0024_auth_permission.sql +39 -0
- package/migrations/0025_auth_permission_definition.sql +19 -0
- package/migrations/0026_auth_user_identity.sql +59 -0
- package/migrations/0027_auth_audit_log_storage_order.sql +46 -0
- package/migrations/0028_auth_oauth_client_secret_key.sql +39 -0
- package/migrations/0029_auth_oauth_device_authorization.sql +28 -0
- package/migrations/delegated-access/0001_auth_delegated_access.sql +152 -0
- package/migrations/postgres/0001_auth_core.sql +77 -0
- package/migrations/postgres/0002_auth_security_oauth.sql +65 -0
- package/migrations/postgres/0003_auth_credentials_tokens.sql +43 -0
- package/migrations/postgres/0004_auth_security_history.sql +103 -0
- package/migrations/postgres/0005_auth_webhooks.sql +29 -0
- package/migrations/postgres/0006_auth_domain_timeline.sql +50 -0
- package/migrations/postgres/0007_auth_oauth_clients.sql +85 -0
- package/migrations/postgres/0008_auth_oauth_tokens.sql +63 -0
- package/migrations/postgres/0009_auth_permissions.sql +66 -0
- package/migrations/postgres/0010_auth_oauth_device_authorization.sql +50 -0
- package/migrations/postgres/delegated-access/0001_auth_delegated_access.sql +112 -0
- package/package.json +309 -2
|
@@ -0,0 +1,1418 @@
|
|
|
1
|
+
import { postgresAuthStorageMigrations } from "./PostgresStorageMigrations.js";
|
|
2
|
+
import { sqliteAuthStorageSchema } from "./SqliteStorageSchemaData.js";
|
|
3
|
+
export const storageSchemaGeneratorApiVersion = "effect-auth.storage-schema-generator/v1";
|
|
4
|
+
export const storageSchemaGeneratorVersion = "1.5.0";
|
|
5
|
+
export const storageSchemaVersion = "0010_auth_oauth_device_authorization";
|
|
6
|
+
export const storageSchemaVersions = {
|
|
7
|
+
postgres: storageSchemaVersion,
|
|
8
|
+
sqlite: "0029_auth_oauth_device_authorization",
|
|
9
|
+
};
|
|
10
|
+
export const supportedStorageDatabases = ["postgres", "sqlite"];
|
|
11
|
+
export const supportedStorageAdapters = ["effect-qb", "drizzle"];
|
|
12
|
+
export const supportedStorageGeneratorModes = ["fresh"];
|
|
13
|
+
export const supportedDevelopmentSeedTargets = [
|
|
14
|
+
"alchemy-d1",
|
|
15
|
+
"bun-sqlite",
|
|
16
|
+
"node-sqlite",
|
|
17
|
+
"postgres",
|
|
18
|
+
];
|
|
19
|
+
export const supportedDevelopmentSeedComplexities = ["medium", "low"];
|
|
20
|
+
export const storageDatabaseAdapters = {
|
|
21
|
+
postgres: supportedStorageAdapters,
|
|
22
|
+
sqlite: supportedStorageAdapters,
|
|
23
|
+
};
|
|
24
|
+
export const developmentSeedTargetsByDatabase = {
|
|
25
|
+
postgres: ["postgres"],
|
|
26
|
+
sqlite: ["alchemy-d1", "bun-sqlite", "node-sqlite"],
|
|
27
|
+
};
|
|
28
|
+
export const developmentSeedTargetsByDatabaseAdapter = {
|
|
29
|
+
postgres: {
|
|
30
|
+
"effect-qb": ["postgres"],
|
|
31
|
+
drizzle: ["postgres"],
|
|
32
|
+
},
|
|
33
|
+
sqlite: {
|
|
34
|
+
"effect-qb": ["alchemy-d1"],
|
|
35
|
+
drizzle: ["alchemy-d1", "bun-sqlite", "node-sqlite"],
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
export const storageModuleCatalog = [
|
|
39
|
+
{
|
|
40
|
+
id: "core",
|
|
41
|
+
description: "Users and login identities.",
|
|
42
|
+
dependencies: [],
|
|
43
|
+
tables: ["auth_user", "auth_user_identity"],
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: "credentials",
|
|
47
|
+
description: "Password and other typed credentials.",
|
|
48
|
+
dependencies: ["core"],
|
|
49
|
+
tables: ["auth_credential"],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: "sessions",
|
|
53
|
+
description: "Authenticated sessions.",
|
|
54
|
+
dependencies: ["core"],
|
|
55
|
+
tables: ["auth_session"],
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: "verification",
|
|
59
|
+
description: "Short-lived verification challenges.",
|
|
60
|
+
dependencies: ["core"],
|
|
61
|
+
tables: ["auth_verification"],
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: "totp",
|
|
65
|
+
description: "TOTP factors.",
|
|
66
|
+
dependencies: ["core"],
|
|
67
|
+
tables: ["auth_totp_factor"],
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: "recovery-codes",
|
|
71
|
+
description: "MFA recovery codes.",
|
|
72
|
+
dependencies: ["core"],
|
|
73
|
+
tables: ["auth_recovery_code"],
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: "refresh-tokens",
|
|
77
|
+
description: "Rotating refresh-token families.",
|
|
78
|
+
dependencies: ["core"],
|
|
79
|
+
tables: ["auth_refresh_token"],
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
id: "oauth-accounts",
|
|
83
|
+
description: "External OAuth account links.",
|
|
84
|
+
dependencies: ["core"],
|
|
85
|
+
tables: ["auth_oauth_account"],
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
id: "passkeys",
|
|
89
|
+
description: "WebAuthn passkey credentials.",
|
|
90
|
+
dependencies: ["core"],
|
|
91
|
+
tables: ["auth_passkey_credential"],
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: "api-keys",
|
|
95
|
+
description: "User API keys.",
|
|
96
|
+
dependencies: ["core"],
|
|
97
|
+
tables: ["auth_api_key"],
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: "jwt",
|
|
101
|
+
description: "JWT revocations.",
|
|
102
|
+
dependencies: [],
|
|
103
|
+
tables: ["auth_jwt_revocation"],
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
id: "audit-log",
|
|
107
|
+
description: "Append-only authentication audit events.",
|
|
108
|
+
dependencies: ["core"],
|
|
109
|
+
tables: ["auth_audit_log"],
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
id: "login-approval",
|
|
113
|
+
description: "Out-of-band login approval reviews.",
|
|
114
|
+
dependencies: ["core", "verification"],
|
|
115
|
+
tables: ["auth_login_approval_review"],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
id: "login-risk",
|
|
119
|
+
description: "Login risk history.",
|
|
120
|
+
dependencies: ["core"],
|
|
121
|
+
tables: ["auth_login_risk_history"],
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
id: "trusted-devices",
|
|
125
|
+
description: "Trusted-device tokens.",
|
|
126
|
+
dependencies: ["core"],
|
|
127
|
+
tables: ["auth_trusted_device"],
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
id: "webhooks",
|
|
131
|
+
description: "Webhook delivery and replay state.",
|
|
132
|
+
dependencies: [],
|
|
133
|
+
tables: ["auth_webhook_outbox", "auth_webhook_replay"],
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
id: "domain-verification",
|
|
137
|
+
description: "Domain ownership proofs.",
|
|
138
|
+
dependencies: [],
|
|
139
|
+
tables: ["auth_domain_verification"],
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
id: "security-timeline",
|
|
143
|
+
description: "User security timeline entries.",
|
|
144
|
+
dependencies: ["core"],
|
|
145
|
+
tables: ["auth_security_timeline"],
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
id: "oauth-provider",
|
|
149
|
+
description: "OAuth authorization-server clients, grants, and tokens.",
|
|
150
|
+
dependencies: ["core", "verification"],
|
|
151
|
+
tables: [
|
|
152
|
+
"auth_oauth_client",
|
|
153
|
+
"auth_oauth_consent",
|
|
154
|
+
"auth_oauth_authorization_code",
|
|
155
|
+
"auth_oauth_device_authorization",
|
|
156
|
+
"auth_oauth_client_secret",
|
|
157
|
+
"auth_oauth_provider_mode_token",
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
id: "oauth-token-vault",
|
|
162
|
+
description: "Encrypted upstream OAuth provider tokens.",
|
|
163
|
+
dependencies: ["oauth-accounts"],
|
|
164
|
+
tables: ["auth_oauth_provider_token_vault"],
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
id: "permissions",
|
|
168
|
+
description: "Permission, role, and grant definitions.",
|
|
169
|
+
dependencies: [],
|
|
170
|
+
tables: [
|
|
171
|
+
"auth_permission_definition",
|
|
172
|
+
"auth_role_definition",
|
|
173
|
+
"auth_permission_grant",
|
|
174
|
+
"auth_role_grant",
|
|
175
|
+
"auth_role_permission",
|
|
176
|
+
],
|
|
177
|
+
},
|
|
178
|
+
];
|
|
179
|
+
export const storageFeatureCatalog = [
|
|
180
|
+
{
|
|
181
|
+
id: "password",
|
|
182
|
+
description: "Password authentication.",
|
|
183
|
+
modules: ["credentials", "sessions", "verification"],
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
id: "email-verification",
|
|
187
|
+
description: "Email ownership verification.",
|
|
188
|
+
modules: ["verification"],
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
id: "email-otp",
|
|
192
|
+
description: "Email one-time passwords.",
|
|
193
|
+
modules: ["sessions", "verification"],
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
id: "magic-link",
|
|
197
|
+
description: "Email magic links.",
|
|
198
|
+
modules: ["sessions", "verification"],
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
id: "sessions",
|
|
202
|
+
description: "Cookie or token-backed sessions.",
|
|
203
|
+
modules: ["sessions"],
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
id: "login-approval",
|
|
207
|
+
description: "Out-of-band login approvals.",
|
|
208
|
+
modules: ["sessions", "login-approval"],
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
id: "trusted-devices",
|
|
212
|
+
description: "Trusted-device recognition.",
|
|
213
|
+
modules: ["trusted-devices"],
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
id: "passkeys",
|
|
217
|
+
description: "Passkey authentication.",
|
|
218
|
+
modules: ["sessions", "verification", "passkeys"],
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
id: "totp",
|
|
222
|
+
description: "TOTP multi-factor authentication.",
|
|
223
|
+
modules: ["sessions", "verification", "totp"],
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
id: "recovery-codes",
|
|
227
|
+
description: "MFA recovery codes.",
|
|
228
|
+
modules: ["sessions", "verification", "recovery-codes"],
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
id: "api-keys",
|
|
232
|
+
description: "User API keys.",
|
|
233
|
+
modules: ["api-keys"],
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
id: "refresh-tokens",
|
|
237
|
+
description: "Refresh-token rotation.",
|
|
238
|
+
modules: ["refresh-tokens"],
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
id: "jwt",
|
|
242
|
+
description: "JWT revocation.",
|
|
243
|
+
modules: ["jwt"],
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
id: "oauth",
|
|
247
|
+
description: "OAuth client login and account linking.",
|
|
248
|
+
modules: ["sessions", "verification", "oauth-accounts"],
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
id: "oauth-provider",
|
|
252
|
+
description: "OAuth authorization-server mode.",
|
|
253
|
+
modules: ["sessions", "oauth-provider"],
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
id: "oauth-token-vault",
|
|
257
|
+
description: "Encrypted upstream provider-token storage.",
|
|
258
|
+
modules: ["oauth-token-vault"],
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
id: "audit-log",
|
|
262
|
+
description: "Authentication audit logging.",
|
|
263
|
+
modules: ["audit-log"],
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
id: "login-risk",
|
|
267
|
+
description: "Login risk history.",
|
|
268
|
+
modules: ["login-risk"],
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
id: "security-timeline",
|
|
272
|
+
description: "User security timelines.",
|
|
273
|
+
modules: ["security-timeline"],
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
id: "webhooks",
|
|
277
|
+
description: "Reliable webhook delivery.",
|
|
278
|
+
modules: ["webhooks"],
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
id: "domain-verification",
|
|
282
|
+
description: "Domain ownership verification.",
|
|
283
|
+
modules: ["domain-verification"],
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
id: "permissions",
|
|
287
|
+
description: "Roles and permissions.",
|
|
288
|
+
modules: ["permissions"],
|
|
289
|
+
},
|
|
290
|
+
];
|
|
291
|
+
export const storageSchemaGeneratorCatalog = {
|
|
292
|
+
apiVersion: storageSchemaGeneratorApiVersion,
|
|
293
|
+
generatorVersion: storageSchemaGeneratorVersion,
|
|
294
|
+
schemaVersion: storageSchemaVersion,
|
|
295
|
+
schemaVersions: storageSchemaVersions,
|
|
296
|
+
databases: supportedStorageDatabases,
|
|
297
|
+
adapters: supportedStorageAdapters,
|
|
298
|
+
databaseAdapters: storageDatabaseAdapters,
|
|
299
|
+
adapterOutputs: {
|
|
300
|
+
"effect-qb": ["migration-sql", "development-seed"],
|
|
301
|
+
drizzle: ["migration-sql", "drizzle-schema", "development-seed"],
|
|
302
|
+
},
|
|
303
|
+
modes: supportedStorageGeneratorModes,
|
|
304
|
+
outputKinds: ["migration-sql", "drizzle-schema", "development-seed"],
|
|
305
|
+
sqlLayouts: ["single", "module"],
|
|
306
|
+
drizzleLayouts: ["single", "module", "table"],
|
|
307
|
+
developmentSeedTargets: supportedDevelopmentSeedTargets,
|
|
308
|
+
developmentSeedTargetsByDatabase,
|
|
309
|
+
developmentSeedTargetsByDatabaseAdapter,
|
|
310
|
+
developmentSeedComplexities: supportedDevelopmentSeedComplexities,
|
|
311
|
+
features: storageFeatureCatalog,
|
|
312
|
+
modules: storageModuleCatalog,
|
|
313
|
+
};
|
|
314
|
+
export class StorageSchemaGeneratorError extends Error {
|
|
315
|
+
name = "StorageSchemaGeneratorError";
|
|
316
|
+
code;
|
|
317
|
+
path;
|
|
318
|
+
suggestions;
|
|
319
|
+
constructor(code, path, message, suggestions = []) {
|
|
320
|
+
super(message);
|
|
321
|
+
this.code = code;
|
|
322
|
+
this.path = path;
|
|
323
|
+
this.suggestions = suggestions;
|
|
324
|
+
}
|
|
325
|
+
toJSON() {
|
|
326
|
+
return {
|
|
327
|
+
name: this.name,
|
|
328
|
+
code: this.code,
|
|
329
|
+
path: this.path,
|
|
330
|
+
message: this.message,
|
|
331
|
+
suggestions: this.suggestions,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
const moduleById = new Map(storageModuleCatalog.map((entry) => [entry.id, entry]));
|
|
336
|
+
const featureById = new Map(storageFeatureCatalog.map((feature) => [feature.id, feature]));
|
|
337
|
+
const moduleOrder = new Map(storageModuleCatalog.map((entry, index) => [entry.id, index]));
|
|
338
|
+
const featureOrder = new Map(storageFeatureCatalog.map((feature, index) => [feature.id, index]));
|
|
339
|
+
const tableModule = new Map();
|
|
340
|
+
for (const entry of storageModuleCatalog) {
|
|
341
|
+
for (const table of entry.tables) {
|
|
342
|
+
tableModule.set(table, entry.id);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
const splitSqlStatements = (sql) => {
|
|
346
|
+
const statements = [];
|
|
347
|
+
let start = 0;
|
|
348
|
+
let singleQuoted = false;
|
|
349
|
+
let doubleQuoted = false;
|
|
350
|
+
for (let index = 0; index < sql.length; index += 1) {
|
|
351
|
+
const character = sql[index];
|
|
352
|
+
const next = sql[index + 1];
|
|
353
|
+
if (character === "'" && !doubleQuoted) {
|
|
354
|
+
if (singleQuoted && next === "'") {
|
|
355
|
+
index += 1;
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
singleQuoted = !singleQuoted;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
else if (character === '"' && !singleQuoted) {
|
|
362
|
+
if (doubleQuoted && next === '"') {
|
|
363
|
+
index += 1;
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
doubleQuoted = !doubleQuoted;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
else if (character === ";" && !singleQuoted && !doubleQuoted) {
|
|
370
|
+
const statement = sql.slice(start, index).trim();
|
|
371
|
+
if (statement.length > 0) {
|
|
372
|
+
statements.push(`${statement};`);
|
|
373
|
+
}
|
|
374
|
+
start = index + 1;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
const remainder = sql.slice(start).trim();
|
|
378
|
+
if (remainder.length > 0) {
|
|
379
|
+
statements.push(remainder.endsWith(";") ? remainder : `${remainder};`);
|
|
380
|
+
}
|
|
381
|
+
return statements;
|
|
382
|
+
};
|
|
383
|
+
const buildCanonicalTables = (database, sqlSources) => {
|
|
384
|
+
const creates = new Map();
|
|
385
|
+
const indexes = new Map();
|
|
386
|
+
let order = 0;
|
|
387
|
+
for (const sql of sqlSources) {
|
|
388
|
+
for (const statement of splitSqlStatements(sql)) {
|
|
389
|
+
const createMatch = /^create table (?:if not exists )?([a-z0-9_]+)\s*\(/i.exec(statement);
|
|
390
|
+
if (createMatch?.[1] !== undefined) {
|
|
391
|
+
creates.set(createMatch[1], { sql: statement, order });
|
|
392
|
+
indexes.set(createMatch[1], []);
|
|
393
|
+
order += 1;
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
const indexMatch = /^create (?:unique )?index (?:if not exists )?[a-z0-9_]+\s+on ([a-z0-9_]+)\s*\(/i.exec(statement);
|
|
397
|
+
if (indexMatch?.[1] !== undefined) {
|
|
398
|
+
const tableIndexes = indexes.get(indexMatch[1]);
|
|
399
|
+
if (tableIndexes === undefined) {
|
|
400
|
+
throw new Error(`Index references unknown canonical table ${indexMatch[1]}`);
|
|
401
|
+
}
|
|
402
|
+
tableIndexes.push(statement);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
const oauthClient = creates.get("auth_oauth_client");
|
|
407
|
+
if (database === "postgres" && oauthClient !== undefined) {
|
|
408
|
+
const previous = '@ != "client_credentials"))\'))';
|
|
409
|
+
const replacement = '@ != "client_credentials" && @ != "urn:ietf:params:oauth:grant-type:device_code"))\'))';
|
|
410
|
+
const sql = oauthClient.sql.replace(previous, replacement);
|
|
411
|
+
if (sql === oauthClient.sql) {
|
|
412
|
+
throw new Error("Unable to apply the OAuth device-code grant constraint");
|
|
413
|
+
}
|
|
414
|
+
creates.set("auth_oauth_client", { ...oauthClient, sql });
|
|
415
|
+
}
|
|
416
|
+
const result = [];
|
|
417
|
+
for (const [name, create] of creates) {
|
|
418
|
+
const moduleId = tableModule.get(name);
|
|
419
|
+
if (moduleId === undefined) {
|
|
420
|
+
throw new Error(`Canonical table ${name} is missing from the module catalog`);
|
|
421
|
+
}
|
|
422
|
+
result.push({
|
|
423
|
+
name: name,
|
|
424
|
+
module: moduleId,
|
|
425
|
+
order: create.order,
|
|
426
|
+
createTable: create.sql,
|
|
427
|
+
indexes: indexes.get(name) ?? [],
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
for (const table of tableModule.keys()) {
|
|
431
|
+
if (!creates.has(table)) {
|
|
432
|
+
throw new Error(`Catalog table ${table} is missing from canonical migrations`);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
// oxlint-disable-next-line unicorn/no-array-sort -- ES2023 toSorted is outside the supported target.
|
|
436
|
+
return result.sort((left, right) => left.order - right.order);
|
|
437
|
+
};
|
|
438
|
+
const canonicalTablesByDatabase = {
|
|
439
|
+
postgres: buildCanonicalTables("postgres", postgresAuthStorageMigrations.map((migration) => migration.sql)),
|
|
440
|
+
sqlite: buildCanonicalTables("sqlite", [sqliteAuthStorageSchema]),
|
|
441
|
+
};
|
|
442
|
+
const canonicalTables = canonicalTablesByDatabase.postgres;
|
|
443
|
+
const splitTopLevel = (value) => {
|
|
444
|
+
const parts = [];
|
|
445
|
+
let depth = 0;
|
|
446
|
+
let start = 0;
|
|
447
|
+
let singleQuoted = false;
|
|
448
|
+
let doubleQuoted = false;
|
|
449
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
450
|
+
const character = value[index];
|
|
451
|
+
const next = value[index + 1];
|
|
452
|
+
if (character === "'" && !doubleQuoted) {
|
|
453
|
+
if (singleQuoted && next === "'") {
|
|
454
|
+
index += 1;
|
|
455
|
+
}
|
|
456
|
+
else {
|
|
457
|
+
singleQuoted = !singleQuoted;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
else if (character === '"' && !singleQuoted) {
|
|
461
|
+
if (doubleQuoted && next === '"') {
|
|
462
|
+
index += 1;
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
doubleQuoted = !doubleQuoted;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
else if (!singleQuoted && !doubleQuoted) {
|
|
469
|
+
if (character === "(") {
|
|
470
|
+
depth += 1;
|
|
471
|
+
}
|
|
472
|
+
else if (character === ")") {
|
|
473
|
+
depth -= 1;
|
|
474
|
+
}
|
|
475
|
+
else if (character === "," && depth === 0) {
|
|
476
|
+
parts.push(value.slice(start, index).trim());
|
|
477
|
+
start = index + 1;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
parts.push(value.slice(start).trim());
|
|
482
|
+
return parts.filter((part) => part.length > 0);
|
|
483
|
+
};
|
|
484
|
+
// oxlint-disable-next-line eslint/complexity -- one pass handles both dialects' column and constraint syntax
|
|
485
|
+
const parseCanonicalTable = (canonical) => {
|
|
486
|
+
const tableMatch = /^create table (?:if not exists )?[a-z0-9_]+\s*\(([\s\S]*)\);$/i.exec(canonical.createTable);
|
|
487
|
+
if (tableMatch?.[1] === undefined) {
|
|
488
|
+
throw new Error(`Unable to parse canonical table ${canonical.name}`);
|
|
489
|
+
}
|
|
490
|
+
const columns = [];
|
|
491
|
+
const constraints = [];
|
|
492
|
+
for (const definition of splitTopLevel(tableMatch[1])) {
|
|
493
|
+
const constraintMatch = /^constraint ([a-z0-9_]+)\s+(primary key|unique|check)\s*\(([\s\S]*)\)$/i.exec(definition);
|
|
494
|
+
if (constraintMatch !== null) {
|
|
495
|
+
const [, name, rawKind, value] = constraintMatch;
|
|
496
|
+
if (name === undefined || rawKind === undefined || value === undefined) {
|
|
497
|
+
throw new Error(`Unable to parse constraint in ${canonical.name}`);
|
|
498
|
+
}
|
|
499
|
+
const kind = rawKind.toLowerCase();
|
|
500
|
+
constraints.push(kind === "check"
|
|
501
|
+
? { name, kind: "check", expression: value.trim() }
|
|
502
|
+
: {
|
|
503
|
+
name,
|
|
504
|
+
kind: kind === "unique" ? "unique" : "primary-key",
|
|
505
|
+
columns: splitTopLevel(value).map((column) => column.trim().split(/\s+/u)[0].toLowerCase()),
|
|
506
|
+
});
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
509
|
+
const primaryKeyMatch = /^primary key\s*\(([\s\S]*)\)$/i.exec(definition);
|
|
510
|
+
if (primaryKeyMatch?.[1] !== undefined) {
|
|
511
|
+
constraints.push({
|
|
512
|
+
name: `${canonical.name}_pkey`,
|
|
513
|
+
kind: "primary-key",
|
|
514
|
+
columns: splitTopLevel(primaryKeyMatch[1]).map((column) => column.trim().split(/\s+/u)[0].toLowerCase()),
|
|
515
|
+
});
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
const tableCheckMatch = /^check\s*\(([\s\S]*)\)$/i.exec(definition);
|
|
519
|
+
if (tableCheckMatch?.[1] !== undefined) {
|
|
520
|
+
constraints.push({
|
|
521
|
+
name: `${canonical.name}_state_check`,
|
|
522
|
+
kind: "check",
|
|
523
|
+
expression: tableCheckMatch[1].trim(),
|
|
524
|
+
});
|
|
525
|
+
continue;
|
|
526
|
+
}
|
|
527
|
+
const columnMatch = /^([a-z0-9_]+)\s+(text|bigint|integer|boolean|jsonb)\b([\s\S]*)$/i.exec(definition);
|
|
528
|
+
if (columnMatch === null) {
|
|
529
|
+
throw new Error(`Unable to parse column definition in ${canonical.name}: ${definition}`);
|
|
530
|
+
}
|
|
531
|
+
const [, name, rawType, modifiers = ""] = columnMatch;
|
|
532
|
+
if (name === undefined || rawType === undefined) {
|
|
533
|
+
throw new Error(`Unable to parse column in ${canonical.name}`);
|
|
534
|
+
}
|
|
535
|
+
const inlinePrimaryKey = /\bprimary key\b/i.test(modifiers);
|
|
536
|
+
const namedPrimaryKey = /constraint ([a-z0-9_]+) primary key/i.exec(modifiers)?.[1];
|
|
537
|
+
if (inlinePrimaryKey) {
|
|
538
|
+
constraints.push({
|
|
539
|
+
name: namedPrimaryKey ?? `${canonical.name}_pkey`,
|
|
540
|
+
kind: "primary-key",
|
|
541
|
+
columns: [name],
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
if (/\bunique\b/i.test(modifiers)) {
|
|
545
|
+
constraints.push({
|
|
546
|
+
name: `${canonical.name}_${name}_key`,
|
|
547
|
+
kind: "unique",
|
|
548
|
+
columns: [name],
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
const inlineCheck = /\bcheck\s*\(([\s\S]*)\)\s*$/i.exec(modifiers);
|
|
552
|
+
if (inlineCheck?.[1] !== undefined) {
|
|
553
|
+
constraints.push({
|
|
554
|
+
name: `${canonical.name}_${name}_check`,
|
|
555
|
+
kind: "check",
|
|
556
|
+
expression: inlineCheck[1].trim(),
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
const defaultMatch = /\bdefault\s+(false|true|-?\d+|'(?:''|[^'])*')/i.exec(modifiers);
|
|
560
|
+
const defaultValue = defaultMatch?.[1];
|
|
561
|
+
columns.push({
|
|
562
|
+
name,
|
|
563
|
+
type: rawType.toLowerCase(),
|
|
564
|
+
notNull: /\bnot null\b/i.test(modifiers) || inlinePrimaryKey,
|
|
565
|
+
defaultValue: defaultValue === undefined
|
|
566
|
+
? undefined
|
|
567
|
+
: /^(?:false|true)$/iu.test(defaultValue)
|
|
568
|
+
? defaultValue.toLowerCase()
|
|
569
|
+
: defaultValue,
|
|
570
|
+
identity: /\bgenerated always as identity\b/i.test(modifiers),
|
|
571
|
+
autoincrement: /\bautoincrement\b/i.test(modifiers),
|
|
572
|
+
collateC: /\bcollate "C"/i.test(modifiers),
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
return { canonical, columns, constraints };
|
|
576
|
+
};
|
|
577
|
+
const parsedTableByDatabase = {
|
|
578
|
+
postgres: new Map(canonicalTablesByDatabase.postgres.map((table) => [
|
|
579
|
+
table.name,
|
|
580
|
+
parseCanonicalTable(table),
|
|
581
|
+
])),
|
|
582
|
+
sqlite: new Map(canonicalTablesByDatabase.sqlite.map((table) => [
|
|
583
|
+
table.name,
|
|
584
|
+
parseCanonicalTable(table),
|
|
585
|
+
])),
|
|
586
|
+
};
|
|
587
|
+
const compareByOrder = (order) => (left, right) => (order.get(left) ?? Number.MAX_SAFE_INTEGER) -
|
|
588
|
+
(order.get(right) ?? Number.MAX_SAFE_INTEGER);
|
|
589
|
+
const resolveModules = (directModules) => {
|
|
590
|
+
const resolved = new Set();
|
|
591
|
+
const include = (moduleId) => {
|
|
592
|
+
if (resolved.has(moduleId)) {
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
const moduleEntry = moduleById.get(moduleId);
|
|
596
|
+
if (moduleEntry === undefined) {
|
|
597
|
+
throw new Error(`Unknown catalog module ${moduleId}`);
|
|
598
|
+
}
|
|
599
|
+
for (const dependency of moduleEntry.dependencies) {
|
|
600
|
+
include(dependency);
|
|
601
|
+
}
|
|
602
|
+
resolved.add(moduleId);
|
|
603
|
+
};
|
|
604
|
+
for (const moduleId of directModules) {
|
|
605
|
+
include(moduleId);
|
|
606
|
+
}
|
|
607
|
+
// oxlint-disable-next-line unicorn/no-array-sort -- ES2023 toSorted is outside the supported target.
|
|
608
|
+
return [...resolved].sort(compareByOrder(moduleOrder));
|
|
609
|
+
};
|
|
610
|
+
export const resolveStorageFeatures = (features) => {
|
|
611
|
+
// oxlint-disable-next-line unicorn/no-array-sort -- ES2023 toSorted is outside the supported target.
|
|
612
|
+
const normalizedFeatures = [...new Set(features)].sort(compareByOrder(featureOrder));
|
|
613
|
+
const directModules = new Set();
|
|
614
|
+
for (const featureId of normalizedFeatures) {
|
|
615
|
+
const feature = featureById.get(featureId);
|
|
616
|
+
if (feature === undefined) {
|
|
617
|
+
throw new StorageSchemaGeneratorError("UNKNOWN_FEATURE", "features", `Unsupported storage feature ${JSON.stringify(featureId)}.`, storageFeatureCatalog.map((entry) => entry.id));
|
|
618
|
+
}
|
|
619
|
+
for (const moduleId of feature.modules) {
|
|
620
|
+
directModules.add(moduleId);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
const modules = resolveModules(directModules);
|
|
624
|
+
const selectedModules = new Set(modules);
|
|
625
|
+
const tables = canonicalTables
|
|
626
|
+
.filter((table) => selectedModules.has(table.module))
|
|
627
|
+
.map((table) => table.name);
|
|
628
|
+
return {
|
|
629
|
+
features: normalizedFeatures,
|
|
630
|
+
modules,
|
|
631
|
+
tables,
|
|
632
|
+
impliedModules: modules.filter((moduleId) => !directModules.has(moduleId)),
|
|
633
|
+
};
|
|
634
|
+
};
|
|
635
|
+
const includeDevelopmentSeedRequirements = (selection) => {
|
|
636
|
+
if (selection.modules.includes("core")) {
|
|
637
|
+
return selection;
|
|
638
|
+
}
|
|
639
|
+
const modules = resolveModules(new Set([...selection.modules, "core"]));
|
|
640
|
+
const selectedModules = new Set(modules);
|
|
641
|
+
return {
|
|
642
|
+
...selection,
|
|
643
|
+
modules,
|
|
644
|
+
tables: canonicalTables
|
|
645
|
+
.filter((table) => selectedModules.has(table.module))
|
|
646
|
+
.map((table) => table.name),
|
|
647
|
+
impliedModules: [...selection.impliedModules, "core"],
|
|
648
|
+
};
|
|
649
|
+
};
|
|
650
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
651
|
+
const assertKnownKeys = (value, keys, path, code) => {
|
|
652
|
+
const allowed = new Set(keys);
|
|
653
|
+
for (const key of Object.keys(value)) {
|
|
654
|
+
if (!allowed.has(key)) {
|
|
655
|
+
throw new StorageSchemaGeneratorError(code, path === "$" ? key : `${path}.${key}`, `Unknown property ${JSON.stringify(key)}.`, keys);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
// oxlint-disable-next-line eslint/complexity -- validation keeps precise error paths in one pass
|
|
660
|
+
const normalizeRequest = (input) => {
|
|
661
|
+
if (!isRecord(input)) {
|
|
662
|
+
throw new StorageSchemaGeneratorError("INVALID_REQUEST", "$", "The generator request must be an object.");
|
|
663
|
+
}
|
|
664
|
+
const request = input;
|
|
665
|
+
assertKnownKeys(request, ["database", "adapter", "mode", "features", "outputs"], "$", "INVALID_REQUEST");
|
|
666
|
+
if (request.database !== "postgres" && request.database !== "sqlite") {
|
|
667
|
+
throw new StorageSchemaGeneratorError("UNSUPPORTED_DATABASE", "database", `Unsupported database ${JSON.stringify(request.database)}.`, supportedStorageDatabases);
|
|
668
|
+
}
|
|
669
|
+
const { database } = request;
|
|
670
|
+
if (request.adapter !== "effect-qb" && request.adapter !== "drizzle") {
|
|
671
|
+
throw new StorageSchemaGeneratorError("UNSUPPORTED_ADAPTER", "adapter", `Unsupported adapter ${JSON.stringify(request.adapter)}.`, supportedStorageAdapters);
|
|
672
|
+
}
|
|
673
|
+
const { adapter } = request;
|
|
674
|
+
if (request.mode !== undefined && request.mode !== "fresh") {
|
|
675
|
+
throw new StorageSchemaGeneratorError("UNSUPPORTED_MODE", "mode", `Unsupported generation mode ${JSON.stringify(request.mode)}.`, ["fresh"]);
|
|
676
|
+
}
|
|
677
|
+
if (!Array.isArray(request.features) || request.features.length === 0) {
|
|
678
|
+
throw new StorageSchemaGeneratorError("INVALID_REQUEST", "features", "At least one storage feature is required.", storageFeatureCatalog.map((feature) => feature.id));
|
|
679
|
+
}
|
|
680
|
+
const features = [];
|
|
681
|
+
for (const [index, feature] of request.features.entries()) {
|
|
682
|
+
if (typeof feature !== "string" ||
|
|
683
|
+
!featureById.has(feature)) {
|
|
684
|
+
throw new StorageSchemaGeneratorError("UNKNOWN_FEATURE", `features[${index}]`, `Unsupported storage feature ${JSON.stringify(feature)}.`, storageFeatureCatalog.map((entry) => entry.id));
|
|
685
|
+
}
|
|
686
|
+
features.push(feature);
|
|
687
|
+
}
|
|
688
|
+
if (!Array.isArray(request.outputs) || request.outputs.length === 0) {
|
|
689
|
+
throw new StorageSchemaGeneratorError("INVALID_REQUEST", "outputs", "At least one output is required.", ["migration-sql", "drizzle-schema", "development-seed"]);
|
|
690
|
+
}
|
|
691
|
+
const outputs = [];
|
|
692
|
+
const outputKinds = new Set();
|
|
693
|
+
for (const [index, output] of request.outputs.entries()) {
|
|
694
|
+
const path = `outputs[${index}]`;
|
|
695
|
+
if (!isRecord(output)) {
|
|
696
|
+
throw new StorageSchemaGeneratorError("INVALID_OUTPUT", path, "Each output must be an object.");
|
|
697
|
+
}
|
|
698
|
+
if (output.kind === "migration-sql") {
|
|
699
|
+
assertKnownKeys(output, ["kind", "layout"], path, "INVALID_OUTPUT");
|
|
700
|
+
if (output.layout !== "single" && output.layout !== "module") {
|
|
701
|
+
throw new StorageSchemaGeneratorError("INVALID_OUTPUT", `${path}.layout`, `Invalid migration SQL layout ${JSON.stringify(output.layout)}.`, ["single", "module"]);
|
|
702
|
+
}
|
|
703
|
+
outputs.push({ kind: "migration-sql", layout: output.layout });
|
|
704
|
+
}
|
|
705
|
+
else if (output.kind === "drizzle-schema") {
|
|
706
|
+
assertKnownKeys(output, ["kind", "layout", "includeRelations"], path, "INVALID_OUTPUT");
|
|
707
|
+
if (output.layout !== "single" &&
|
|
708
|
+
output.layout !== "module" &&
|
|
709
|
+
output.layout !== "table") {
|
|
710
|
+
throw new StorageSchemaGeneratorError("INVALID_OUTPUT", `${path}.layout`, `Invalid Drizzle schema layout ${JSON.stringify(output.layout)}.`, ["single", "module", "table"]);
|
|
711
|
+
}
|
|
712
|
+
if (output.includeRelations !== undefined &&
|
|
713
|
+
typeof output.includeRelations !== "boolean") {
|
|
714
|
+
throw new StorageSchemaGeneratorError("INVALID_OUTPUT", `${path}.includeRelations`, "includeRelations must be a boolean.");
|
|
715
|
+
}
|
|
716
|
+
outputs.push({
|
|
717
|
+
kind: "drizzle-schema",
|
|
718
|
+
layout: output.layout,
|
|
719
|
+
includeRelations: output.includeRelations === true,
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
else if (output.kind === "development-seed") {
|
|
723
|
+
assertKnownKeys(output, ["kind", "target", "complexity"], path, "INVALID_OUTPUT");
|
|
724
|
+
if (typeof output.target !== "string" ||
|
|
725
|
+
!supportedDevelopmentSeedTargets.includes(output.target)) {
|
|
726
|
+
throw new StorageSchemaGeneratorError("INVALID_OUTPUT", `${path}.target`, `Invalid development seed target ${JSON.stringify(output.target)}.`, supportedDevelopmentSeedTargets);
|
|
727
|
+
}
|
|
728
|
+
if (!developmentSeedTargetsByDatabaseAdapter[database][adapter].includes(output.target)) {
|
|
729
|
+
throw new StorageSchemaGeneratorError("INVALID_OUTPUT", `${path}.target`, `Development seed target ${JSON.stringify(output.target)} is not available for ${database}.`, developmentSeedTargetsByDatabaseAdapter[database][adapter]);
|
|
730
|
+
}
|
|
731
|
+
if (output.complexity !== undefined &&
|
|
732
|
+
output.complexity !== "medium" &&
|
|
733
|
+
output.complexity !== "low") {
|
|
734
|
+
throw new StorageSchemaGeneratorError("INVALID_OUTPUT", `${path}.complexity`, `Invalid development seed complexity ${JSON.stringify(output.complexity)}.`, supportedDevelopmentSeedComplexities);
|
|
735
|
+
}
|
|
736
|
+
outputs.push({
|
|
737
|
+
kind: "development-seed",
|
|
738
|
+
target: output.target,
|
|
739
|
+
complexity: output.complexity ??
|
|
740
|
+
"medium",
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
else {
|
|
744
|
+
throw new StorageSchemaGeneratorError("INVALID_OUTPUT", `${path}.kind`, `Unsupported output kind ${JSON.stringify(output.kind)}.`, ["migration-sql", "drizzle-schema", "development-seed"]);
|
|
745
|
+
}
|
|
746
|
+
if (outputKinds.has(output.kind)) {
|
|
747
|
+
throw new StorageSchemaGeneratorError("DUPLICATE_OUTPUT", `${path}.kind`, `Only one ${String(output.kind)} output may be requested.`, ["Combine the requested files by choosing one layout."]);
|
|
748
|
+
}
|
|
749
|
+
outputKinds.add(output.kind);
|
|
750
|
+
}
|
|
751
|
+
if (adapter === "effect-qb") {
|
|
752
|
+
const unsupportedOutputIndex = outputs.findIndex((output) => output.kind === "drizzle-schema");
|
|
753
|
+
if (unsupportedOutputIndex !== -1) {
|
|
754
|
+
throw new StorageSchemaGeneratorError("UNSUPPORTED_OUTPUT_FOR_ADAPTER", `outputs[${unsupportedOutputIndex}].kind`, "The effect-qb adapter owns its table declarations and does not generate a Drizzle schema.", ["migration-sql", "development-seed"]);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
// oxlint-disable-next-line unicorn/no-array-sort -- ES2023 toSorted is outside the supported target.
|
|
758
|
+
outputs.sort((left, right) => {
|
|
759
|
+
if (left.kind !== right.kind) {
|
|
760
|
+
const order = new Map([
|
|
761
|
+
["migration-sql", 0],
|
|
762
|
+
["drizzle-schema", 1],
|
|
763
|
+
["development-seed", 2],
|
|
764
|
+
]);
|
|
765
|
+
return (order.get(left.kind) ?? 3) - (order.get(right.kind) ?? 3);
|
|
766
|
+
}
|
|
767
|
+
if (left.kind === "development-seed") {
|
|
768
|
+
return left.target.localeCompare(right.target);
|
|
769
|
+
}
|
|
770
|
+
return left.layout.localeCompare(right.layout);
|
|
771
|
+
});
|
|
772
|
+
return {
|
|
773
|
+
database,
|
|
774
|
+
adapter,
|
|
775
|
+
mode: "fresh",
|
|
776
|
+
// oxlint-disable-next-line unicorn/no-array-sort -- ES2023 toSorted is outside the supported target.
|
|
777
|
+
features: [...new Set(features)].sort(compareByOrder(featureOrder)),
|
|
778
|
+
outputs,
|
|
779
|
+
};
|
|
780
|
+
};
|
|
781
|
+
const renderCanonicalSql = (tables) => `${tables
|
|
782
|
+
.flatMap((table) => [table.createTable, ...table.indexes])
|
|
783
|
+
.join("\n\n")}
|
|
784
|
+
`;
|
|
785
|
+
const sqlFiles = (database, layout, selection) => {
|
|
786
|
+
const selectedTables = new Set(selection.tables);
|
|
787
|
+
const tables = canonicalTablesByDatabase[database].filter((table) => selectedTables.has(table.name));
|
|
788
|
+
if (layout === "single") {
|
|
789
|
+
return [
|
|
790
|
+
{
|
|
791
|
+
path: "effect-auth.sql",
|
|
792
|
+
mediaType: "application/sql",
|
|
793
|
+
content: renderCanonicalSql(tables),
|
|
794
|
+
},
|
|
795
|
+
];
|
|
796
|
+
}
|
|
797
|
+
return selection.modules.map((moduleId, index) => ({
|
|
798
|
+
path: `${String(index + 1).padStart(4, "0")}_effect_auth_${moduleId.replaceAll("-", "_")}.sql`,
|
|
799
|
+
mediaType: "application/sql",
|
|
800
|
+
content: renderCanonicalSql(tables.filter((table) => table.module === moduleId)),
|
|
801
|
+
}));
|
|
802
|
+
};
|
|
803
|
+
const camelCase = (value) => value.replaceAll(/_([a-z0-9])/g, (_, character) => character.toUpperCase());
|
|
804
|
+
const kebabCase = (value) => value.replaceAll("_", "-");
|
|
805
|
+
const escapeTemplate = (value) => value.replaceAll("`", "\\`").replaceAll("${", "\\${");
|
|
806
|
+
const renderColumn = (column, database) => {
|
|
807
|
+
let expression;
|
|
808
|
+
if (database === "sqlite") {
|
|
809
|
+
expression = `${column.type === "integer" ? "integer" : "text"}(${JSON.stringify(column.name)})`;
|
|
810
|
+
}
|
|
811
|
+
else {
|
|
812
|
+
switch (column.type) {
|
|
813
|
+
case "bigint": {
|
|
814
|
+
expression = `bigint(${JSON.stringify(column.name)}, { mode: "number" })`;
|
|
815
|
+
break;
|
|
816
|
+
}
|
|
817
|
+
case "boolean": {
|
|
818
|
+
expression = `boolean(${JSON.stringify(column.name)})`;
|
|
819
|
+
break;
|
|
820
|
+
}
|
|
821
|
+
case "integer": {
|
|
822
|
+
expression = `integer(${JSON.stringify(column.name)})`;
|
|
823
|
+
break;
|
|
824
|
+
}
|
|
825
|
+
case "jsonb": {
|
|
826
|
+
expression = `jsonb(${JSON.stringify(column.name)})`;
|
|
827
|
+
break;
|
|
828
|
+
}
|
|
829
|
+
case "text": {
|
|
830
|
+
expression = `${column.collateC ? "textC" : "text"}(${JSON.stringify(column.name)})`;
|
|
831
|
+
break;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
if (column.autoincrement) {
|
|
836
|
+
expression += ".primaryKey({ autoIncrement: true })";
|
|
837
|
+
}
|
|
838
|
+
else if (column.identity) {
|
|
839
|
+
expression += ".generatedAlwaysAsIdentity()";
|
|
840
|
+
}
|
|
841
|
+
if (column.notNull && !column.identity && !column.autoincrement) {
|
|
842
|
+
expression += ".notNull()";
|
|
843
|
+
}
|
|
844
|
+
if (column.defaultValue !== undefined) {
|
|
845
|
+
const defaultValue = column.defaultValue.startsWith("'")
|
|
846
|
+
? JSON.stringify(column.defaultValue.slice(1, -1).replaceAll("''", "'"))
|
|
847
|
+
: column.defaultValue;
|
|
848
|
+
expression += `.default(${defaultValue})`;
|
|
849
|
+
}
|
|
850
|
+
return ` ${camelCase(column.name)}: ${expression},`;
|
|
851
|
+
};
|
|
852
|
+
const renderSqlTemplate = (value) => `sql\`${escapeTemplate(value)}\``;
|
|
853
|
+
const renderIndexColumn = (value) => {
|
|
854
|
+
const match = /^([a-z0-9_]+)(?:\s+collate\s+"C")?$/i.exec(value.trim());
|
|
855
|
+
if (match?.[1] === undefined) {
|
|
856
|
+
return renderSqlTemplate(value.trim());
|
|
857
|
+
}
|
|
858
|
+
const column = camelCase(match[1]);
|
|
859
|
+
return /\bcollate\s+"C"/i.test(value)
|
|
860
|
+
? `sql\`\${t.${column}} collate "C"\``
|
|
861
|
+
: `t.${column}`;
|
|
862
|
+
};
|
|
863
|
+
const renderIndex = (statement) => {
|
|
864
|
+
const match = /^create (unique )?index (?:if not exists )?([a-z0-9_]+)\s+on [a-z0-9_]+\s*\(([\s\S]*?)\)(?:\s+where\s+([\s\S]+?))?;$/i.exec(statement);
|
|
865
|
+
if (match === null || match[2] === undefined || match[3] === undefined) {
|
|
866
|
+
throw new Error(`Unable to render canonical index: ${statement}`);
|
|
867
|
+
}
|
|
868
|
+
const [, uniqueMarker, name, columns, where] = match;
|
|
869
|
+
let expression = `${uniqueMarker === undefined ? "index" : "uniqueIndex"}(${JSON.stringify(name)}).on(${splitTopLevel(columns).map(renderIndexColumn).join(", ")})`;
|
|
870
|
+
if (where !== undefined) {
|
|
871
|
+
expression += `.where(${renderSqlTemplate(where.trim())})`;
|
|
872
|
+
}
|
|
873
|
+
return ` ${expression},`;
|
|
874
|
+
};
|
|
875
|
+
const renderConstraint = (constraint) => {
|
|
876
|
+
switch (constraint.kind) {
|
|
877
|
+
case "check": {
|
|
878
|
+
return ` check(${JSON.stringify(constraint.name)}, ${renderSqlTemplate(constraint.expression ?? "")}),`;
|
|
879
|
+
}
|
|
880
|
+
case "primary-key": {
|
|
881
|
+
return ` primaryKey({ name: ${JSON.stringify(constraint.name)}, columns: [${(constraint.columns ?? [])
|
|
882
|
+
.map((column) => `t.${camelCase(column)}`)
|
|
883
|
+
.join(", ")}] }),`;
|
|
884
|
+
}
|
|
885
|
+
case "unique": {
|
|
886
|
+
return ` unique(${JSON.stringify(constraint.name)}).on(${(constraint.columns ?? [])
|
|
887
|
+
.map((column) => `t.${camelCase(column)}`)
|
|
888
|
+
.join(", ")}),`;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
};
|
|
892
|
+
const isAutoincrementPrimaryKey = (table, constraint) => constraint.kind === "primary-key" &&
|
|
893
|
+
constraint.columns?.some((columnName) => table.columns.some((column) => column.name === columnName && column.autoincrement)) === true;
|
|
894
|
+
const drizzleImports = (database, tables) => {
|
|
895
|
+
const imports = new Set([
|
|
896
|
+
database === "postgres" ? "pgTable" : "sqliteTable",
|
|
897
|
+
]);
|
|
898
|
+
for (const table of tables) {
|
|
899
|
+
for (const column of table.columns) {
|
|
900
|
+
imports.add(database === "sqlite"
|
|
901
|
+
? column.type === "integer"
|
|
902
|
+
? "integer"
|
|
903
|
+
: "text"
|
|
904
|
+
: column.type);
|
|
905
|
+
if (database === "postgres" && column.collateC) {
|
|
906
|
+
imports.add("customType");
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
for (const constraint of table.constraints) {
|
|
910
|
+
if (isAutoincrementPrimaryKey(table, constraint)) {
|
|
911
|
+
continue;
|
|
912
|
+
}
|
|
913
|
+
imports.add(constraint.kind === "primary-key"
|
|
914
|
+
? "primaryKey"
|
|
915
|
+
: constraint.kind === "unique"
|
|
916
|
+
? "unique"
|
|
917
|
+
: "check");
|
|
918
|
+
if (constraint.kind === "check") {
|
|
919
|
+
imports.add("sql");
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
for (const statement of table.canonical.indexes) {
|
|
923
|
+
imports.add(/^create unique index/i.test(statement) ? "uniqueIndex" : "index");
|
|
924
|
+
if (/\bwhere\b|\bcollate\b/i.test(statement)) {
|
|
925
|
+
imports.add("sql");
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
// oxlint-disable-next-line unicorn/no-array-sort -- ES2023 toSorted is outside the supported target.
|
|
930
|
+
return [...imports].sort();
|
|
931
|
+
};
|
|
932
|
+
const renderTable = (database, table) => {
|
|
933
|
+
const variable = camelCase(table.canonical.name);
|
|
934
|
+
const extras = [
|
|
935
|
+
...table.constraints
|
|
936
|
+
.filter((constraint) => !isAutoincrementPrimaryKey(table, constraint))
|
|
937
|
+
.map(renderConstraint),
|
|
938
|
+
...table.canonical.indexes.map(renderIndex),
|
|
939
|
+
];
|
|
940
|
+
return `export const ${variable} = ${database === "postgres" ? "pgTable" : "sqliteTable"}(
|
|
941
|
+
${JSON.stringify(table.canonical.name)},
|
|
942
|
+
{
|
|
943
|
+
${table.columns.map((column) => renderColumn(column, database)).join("\n")}
|
|
944
|
+
},
|
|
945
|
+
(t) => [
|
|
946
|
+
${extras.join("\n")}
|
|
947
|
+
]
|
|
948
|
+
);`;
|
|
949
|
+
};
|
|
950
|
+
const renderDrizzleTables = (database, tables) => {
|
|
951
|
+
const imports = drizzleImports(database, tables);
|
|
952
|
+
const usesSql = imports.includes("sql");
|
|
953
|
+
const databaseImports = imports.filter((name) => name !== "sql");
|
|
954
|
+
const importLines = [
|
|
955
|
+
...(usesSql ? ['import { sql } from "drizzle-orm";'] : []),
|
|
956
|
+
`import { ${databaseImports.join(", ")} } from "drizzle-orm/${database === "postgres" ? "pg-core" : "sqlite-core"}";`,
|
|
957
|
+
];
|
|
958
|
+
const collatedText = database === "postgres" &&
|
|
959
|
+
tables.some((table) => table.columns.some((column) => column.collateC))
|
|
960
|
+
? `
|
|
961
|
+
const textC = customType<{ data: string }>({
|
|
962
|
+
dataType: () => 'text collate "C"',
|
|
963
|
+
});`
|
|
964
|
+
: "";
|
|
965
|
+
return `${importLines.join("\n")}${collatedText}
|
|
966
|
+
|
|
967
|
+
${tables.map((table) => renderTable(database, table)).join("\n\n")}
|
|
968
|
+
`;
|
|
969
|
+
};
|
|
970
|
+
// oxlint-disable-next-line eslint/complexity -- each branch describes one canonical relation family
|
|
971
|
+
const logicalRelations = (tables) => {
|
|
972
|
+
const byName = new Map(tables.map((table) => [table.canonical.name, table]));
|
|
973
|
+
const relations = [];
|
|
974
|
+
const addRelation = (sourceTable, sourceColumnName, targetTable, targetColumnName, name) => {
|
|
975
|
+
const source = byName.get(sourceTable);
|
|
976
|
+
const target = byName.get(targetTable);
|
|
977
|
+
const sourceColumn = source?.columns.find((column) => column.name === sourceColumnName);
|
|
978
|
+
const targetColumn = target?.columns.find((column) => column.name === targetColumnName);
|
|
979
|
+
if (source !== undefined &&
|
|
980
|
+
target !== undefined &&
|
|
981
|
+
sourceColumn !== undefined &&
|
|
982
|
+
targetColumn !== undefined) {
|
|
983
|
+
relations.push({ source, sourceColumn, target, targetColumn, name });
|
|
984
|
+
}
|
|
985
|
+
};
|
|
986
|
+
const user = byName.get("auth_user");
|
|
987
|
+
const userId = user?.columns.find((column) => column.name === "id");
|
|
988
|
+
if (user !== undefined && userId !== undefined) {
|
|
989
|
+
for (const table of tables) {
|
|
990
|
+
for (const column of table.columns) {
|
|
991
|
+
if (table !== user && column.name.endsWith("user_id")) {
|
|
992
|
+
const prefix = column.name
|
|
993
|
+
.slice(0, -"user_id".length)
|
|
994
|
+
.replace(/_$/, "");
|
|
995
|
+
relations.push({
|
|
996
|
+
source: table,
|
|
997
|
+
sourceColumn: column,
|
|
998
|
+
target: user,
|
|
999
|
+
targetColumn: userId,
|
|
1000
|
+
name: prefix.length === 0 ? "user" : `${camelCase(prefix)}User`,
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
const oauthClient = byName.get("auth_oauth_client");
|
|
1007
|
+
const oauthClientId = oauthClient?.columns.find((column) => column.name === "id");
|
|
1008
|
+
if (oauthClient !== undefined && oauthClientId !== undefined) {
|
|
1009
|
+
for (const tableName of [
|
|
1010
|
+
"auth_oauth_consent",
|
|
1011
|
+
"auth_oauth_authorization_code",
|
|
1012
|
+
"auth_oauth_device_authorization",
|
|
1013
|
+
"auth_oauth_client_secret",
|
|
1014
|
+
"auth_oauth_provider_mode_token",
|
|
1015
|
+
]) {
|
|
1016
|
+
const source = byName.get(tableName);
|
|
1017
|
+
const sourceColumn = source?.columns.find((column) => column.name === "client_id");
|
|
1018
|
+
if (source !== undefined && sourceColumn !== undefined) {
|
|
1019
|
+
relations.push({
|
|
1020
|
+
source,
|
|
1021
|
+
sourceColumn,
|
|
1022
|
+
target: oauthClient,
|
|
1023
|
+
targetColumn: oauthClientId,
|
|
1024
|
+
name: "client",
|
|
1025
|
+
});
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
const oauthAccount = byName.get("auth_oauth_account");
|
|
1030
|
+
const oauthAccountId = oauthAccount?.columns.find((column) => column.name === "id");
|
|
1031
|
+
const vault = byName.get("auth_oauth_provider_token_vault");
|
|
1032
|
+
const vaultAccountId = vault?.columns.find((column) => column.name === "account_id");
|
|
1033
|
+
if (oauthAccount !== undefined &&
|
|
1034
|
+
oauthAccountId !== undefined &&
|
|
1035
|
+
vault !== undefined &&
|
|
1036
|
+
vaultAccountId !== undefined) {
|
|
1037
|
+
relations.push({
|
|
1038
|
+
source: vault,
|
|
1039
|
+
sourceColumn: vaultAccountId,
|
|
1040
|
+
target: oauthAccount,
|
|
1041
|
+
targetColumn: oauthAccountId,
|
|
1042
|
+
name: "account",
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
addRelation("auth_user_identity", "replaced_by_id", "auth_user_identity", "id", "replacedBy");
|
|
1046
|
+
addRelation("auth_refresh_token", "replaced_by_id", "auth_refresh_token", "id", "replacedBy");
|
|
1047
|
+
addRelation("auth_login_approval_review", "approval_challenge_id", "auth_verification", "id", "challenge");
|
|
1048
|
+
addRelation("auth_oauth_provider_mode_token", "replaced_by_token_hash", "auth_oauth_provider_mode_token", "token_hash", "replacedBy");
|
|
1049
|
+
addRelation("auth_permission_grant", "permission_id", "auth_permission_definition", "id", "permission");
|
|
1050
|
+
addRelation("auth_role_grant", "role_id", "auth_role_definition", "id", "role");
|
|
1051
|
+
addRelation("auth_role_permission", "role_id", "auth_role_definition", "id", "role");
|
|
1052
|
+
addRelation("auth_role_permission", "permission_id", "auth_permission_definition", "id", "permission");
|
|
1053
|
+
return relations;
|
|
1054
|
+
};
|
|
1055
|
+
const renderRelations = (database, tables, schemaExpression, importPath) => {
|
|
1056
|
+
const relations = logicalRelations(tables);
|
|
1057
|
+
const grouped = new Map();
|
|
1058
|
+
for (const relation of relations) {
|
|
1059
|
+
const existing = grouped.get(relation.source) ?? [];
|
|
1060
|
+
existing.push(relation);
|
|
1061
|
+
grouped.set(relation.source, existing);
|
|
1062
|
+
}
|
|
1063
|
+
const entries = [...grouped.entries()].map(([table, tableRelations]) => {
|
|
1064
|
+
const sourceName = camelCase(table.canonical.name);
|
|
1065
|
+
return ` ${sourceName}: {
|
|
1066
|
+
${tableRelations
|
|
1067
|
+
.map((relation) => {
|
|
1068
|
+
const targetName = camelCase(relation.target.canonical.name);
|
|
1069
|
+
return ` ${relation.name}: r.one.${targetName}({
|
|
1070
|
+
from: r.${sourceName}.${camelCase(relation.sourceColumn.name)},
|
|
1071
|
+
to: r.${targetName}.${camelCase(relation.targetColumn.name)},
|
|
1072
|
+
}),`;
|
|
1073
|
+
})
|
|
1074
|
+
.join("\n")}
|
|
1075
|
+
},`;
|
|
1076
|
+
});
|
|
1077
|
+
const imports = [
|
|
1078
|
+
'import { defineRelations } from "drizzle-orm";',
|
|
1079
|
+
...(importPath === undefined
|
|
1080
|
+
? []
|
|
1081
|
+
: [`import * as schema from ${JSON.stringify(importPath)};`]),
|
|
1082
|
+
];
|
|
1083
|
+
return `${imports.join("\n")}
|
|
1084
|
+
|
|
1085
|
+
// Drizzle relations are application-level only and do not create ${database === "postgres" ? "PostgreSQL" : "SQLite"} foreign keys.
|
|
1086
|
+
export const relations = defineRelations(${schemaExpression}, (r) => ({
|
|
1087
|
+
${entries.join("\n")}
|
|
1088
|
+
}));
|
|
1089
|
+
`;
|
|
1090
|
+
};
|
|
1091
|
+
const exportFile = (paths) => `${paths.map((path) => `export * from ${JSON.stringify(path)};`).join("\n")}
|
|
1092
|
+
`;
|
|
1093
|
+
const drizzleFiles = (database, layout, includeRelations, selection) => {
|
|
1094
|
+
const selected = new Set(selection.tables);
|
|
1095
|
+
const tables = canonicalTablesByDatabase[database]
|
|
1096
|
+
.filter((table) => selected.has(table.name))
|
|
1097
|
+
.map((table) => parsedTableByDatabase[database].get(table.name));
|
|
1098
|
+
if (layout === "single") {
|
|
1099
|
+
let content = renderDrizzleTables(database, tables);
|
|
1100
|
+
if (includeRelations) {
|
|
1101
|
+
const schema = `{ ${tables
|
|
1102
|
+
.map((table) => camelCase(table.canonical.name))
|
|
1103
|
+
.join(", ")} }`;
|
|
1104
|
+
content += `\n${renderRelations(database, tables, schema)}`;
|
|
1105
|
+
}
|
|
1106
|
+
return [{ path: "schema.ts", mediaType: "text/typescript", content }];
|
|
1107
|
+
}
|
|
1108
|
+
const directory = layout === "module" ? "modules" : "tables";
|
|
1109
|
+
const groups = layout === "module"
|
|
1110
|
+
? selection.modules.map((moduleId) => ({
|
|
1111
|
+
name: moduleId,
|
|
1112
|
+
tables: tables.filter((table) => table.canonical.module === moduleId),
|
|
1113
|
+
}))
|
|
1114
|
+
: tables.map((table) => ({
|
|
1115
|
+
name: kebabCase(table.canonical.name),
|
|
1116
|
+
tables: [table],
|
|
1117
|
+
}));
|
|
1118
|
+
const files = groups.map((group) => ({
|
|
1119
|
+
path: `${directory}/${group.name}.ts`,
|
|
1120
|
+
mediaType: "text/typescript",
|
|
1121
|
+
content: renderDrizzleTables(database, group.tables),
|
|
1122
|
+
}));
|
|
1123
|
+
files.push({
|
|
1124
|
+
path: `${directory}/index.ts`,
|
|
1125
|
+
mediaType: "text/typescript",
|
|
1126
|
+
content: exportFile(groups.map((group) => `./${group.name}.js`)),
|
|
1127
|
+
});
|
|
1128
|
+
if (includeRelations) {
|
|
1129
|
+
files.push({
|
|
1130
|
+
path: "relations.ts",
|
|
1131
|
+
mediaType: "text/typescript",
|
|
1132
|
+
content: renderRelations(database, tables, "schema", `./${directory}/index.js`),
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
files.push({
|
|
1136
|
+
path: "index.ts",
|
|
1137
|
+
mediaType: "text/typescript",
|
|
1138
|
+
content: exportFile([
|
|
1139
|
+
`./${directory}/index.js`,
|
|
1140
|
+
...(includeRelations ? ["./relations.js"] : []),
|
|
1141
|
+
]),
|
|
1142
|
+
});
|
|
1143
|
+
return files;
|
|
1144
|
+
};
|
|
1145
|
+
const developmentSeedCoreImports = (includePassword) => `import {
|
|
1146
|
+
DevelopmentSeed,
|
|
1147
|
+
DevelopmentSeedLive,
|
|
1148
|
+
} from "@effect-auth/core/DevelopmentSeed";
|
|
1149
|
+
import { IdentityKindRegistryDefaultLive } from "@effect-auth/core/Identity";
|
|
1150
|
+
${includePassword
|
|
1151
|
+
? `import { WebCryptoLive } from "@effect-auth/core/Crypto";
|
|
1152
|
+
import { Pbkdf2PasswordHasherLive } from "@effect-auth/core/Password";
|
|
1153
|
+
`
|
|
1154
|
+
: ""}`;
|
|
1155
|
+
const developmentSeedDependenciesSource = (includePassword) => includePassword
|
|
1156
|
+
? `const DevelopmentSeedSupportLive = Layer.mergeAll(
|
|
1157
|
+
IdentityKindRegistryDefaultLive,
|
|
1158
|
+
Pbkdf2PasswordHasherLive().pipe(Layer.provide(WebCryptoLive())),
|
|
1159
|
+
);
|
|
1160
|
+
`
|
|
1161
|
+
: `const DevelopmentSeedSupportLive = IdentityKindRegistryDefaultLive;
|
|
1162
|
+
`;
|
|
1163
|
+
const developmentSeedProgramSource = (includePassword) => `const developmentSeedProgram = Effect.gen(function* () {
|
|
1164
|
+
const seed = yield* DevelopmentSeed;
|
|
1165
|
+
const result = yield* seed.${includePassword ? "seedPasswordUsers" : "seedUsers"};
|
|
1166
|
+
yield* Effect.logInfo(
|
|
1167
|
+
\`Development auth seed complete: \${result.created} created, \${result.existing} existing.\`,
|
|
1168
|
+
);
|
|
1169
|
+
return result;
|
|
1170
|
+
});
|
|
1171
|
+
`;
|
|
1172
|
+
const developmentSeedConfigurationErrorSource = `export class DevelopmentSeedConfigurationError extends Data.TaggedError(
|
|
1173
|
+
"DevelopmentSeedConfigurationError",
|
|
1174
|
+
)<{ readonly message: string }> {}
|
|
1175
|
+
`;
|
|
1176
|
+
const alchemyD1SeedSource = (adapter, includePassword, complexity) => {
|
|
1177
|
+
const drizzle = adapter === "drizzle";
|
|
1178
|
+
const storageModule = drizzle
|
|
1179
|
+
? "DrizzleD1SqliteStorage"
|
|
1180
|
+
: "EffectQbSqliteStorage";
|
|
1181
|
+
const storageType = drizzle
|
|
1182
|
+
? "DrizzleD1DatabaseLike"
|
|
1183
|
+
: "D1EffectQbDatabaseLike";
|
|
1184
|
+
const storageLayer = drizzle
|
|
1185
|
+
? "DrizzleD1SqliteAuthStorageLive"
|
|
1186
|
+
: "D1EffectQbSqliteAuthStorageLive";
|
|
1187
|
+
const medium = complexity === "medium";
|
|
1188
|
+
return `import type { ${storageType} } from "@effect-auth/core/${storageModule}";
|
|
1189
|
+
import { ${storageLayer} } from "@effect-auth/core/${storageModule}";
|
|
1190
|
+
${developmentSeedCoreImports(includePassword)}import { Data, Effect, Layer } from "effect";
|
|
1191
|
+
|
|
1192
|
+
${developmentSeedConfigurationErrorSource}
|
|
1193
|
+
${developmentSeedDependenciesSource(includePassword)}
|
|
1194
|
+
${developmentSeedProgramSource(includePassword)}
|
|
1195
|
+
${medium ? "export " : ""}const AppDevelopmentSeedLive = (database: ${storageType}) =>
|
|
1196
|
+
DevelopmentSeedLive.pipe(
|
|
1197
|
+
Layer.provideMerge(
|
|
1198
|
+
Layer.mergeAll(
|
|
1199
|
+
${storageLayer}(database),
|
|
1200
|
+
DevelopmentSeedSupportLive,
|
|
1201
|
+
),
|
|
1202
|
+
),
|
|
1203
|
+
);
|
|
1204
|
+
|
|
1205
|
+
${medium ? "export const runDevelopmentSeed" : "export const seedDevelopmentAuth"} = (
|
|
1206
|
+
database: ${storageType},
|
|
1207
|
+
isDevelopment: boolean,
|
|
1208
|
+
) =>
|
|
1209
|
+
Effect.gen(function* () {
|
|
1210
|
+
if (!isDevelopment) {
|
|
1211
|
+
return yield* new DevelopmentSeedConfigurationError({
|
|
1212
|
+
message: "Refusing to seed Effect Auth outside Alchemy development mode.",
|
|
1213
|
+
});
|
|
1214
|
+
}
|
|
1215
|
+
return yield* developmentSeedProgram.pipe(
|
|
1216
|
+
Effect.provide(AppDevelopmentSeedLive(database)),
|
|
1217
|
+
);
|
|
1218
|
+
});
|
|
1219
|
+
${medium
|
|
1220
|
+
? ""
|
|
1221
|
+
: `
|
|
1222
|
+
// In alchemy.run.ts, after migrations:
|
|
1223
|
+
// const alchemy = yield* Alchemy.AlchemyContext;
|
|
1224
|
+
// yield* Database;
|
|
1225
|
+
// const client = yield* Cloudflare.D1.QueryDatabase(Database);
|
|
1226
|
+
// yield* seedDevelopmentAuth(yield* client.raw, alchemy.dev);
|
|
1227
|
+
`}`;
|
|
1228
|
+
};
|
|
1229
|
+
const standaloneConfigurationSource = (value) => {
|
|
1230
|
+
const readValue = value === "sqlite"
|
|
1231
|
+
? 'const filename = process.env.EFFECT_AUTH_SQLITE_FILE ?? "./data/auth.sqlite";'
|
|
1232
|
+
: `const databaseUrl = process.env.DATABASE_URL;
|
|
1233
|
+
if (databaseUrl === undefined || databaseUrl.length === 0) {
|
|
1234
|
+
return yield* new DevelopmentSeedConfigurationError({
|
|
1235
|
+
message: "DATABASE_URL is required.",
|
|
1236
|
+
});
|
|
1237
|
+
}`;
|
|
1238
|
+
const returned = value === "sqlite" ? "filename" : "databaseUrl";
|
|
1239
|
+
return `const developmentSeedConfiguration = Effect.gen(function* () {
|
|
1240
|
+
if (
|
|
1241
|
+
process.env.NODE_ENV === "production" ||
|
|
1242
|
+
process.env.EFFECT_AUTH_DEVELOPMENT_SEED !== "true"
|
|
1243
|
+
) {
|
|
1244
|
+
return yield* new DevelopmentSeedConfigurationError({
|
|
1245
|
+
message: "Set EFFECT_AUTH_DEVELOPMENT_SEED=true to run the development seed.",
|
|
1246
|
+
});
|
|
1247
|
+
}
|
|
1248
|
+
${readValue}
|
|
1249
|
+
return ${returned};
|
|
1250
|
+
});
|
|
1251
|
+
`;
|
|
1252
|
+
};
|
|
1253
|
+
const sqliteSeedSource = (runtime, includePassword, complexity) => {
|
|
1254
|
+
const storageModule = runtime === "bun" ? "DrizzleBunSqliteStorage" : "DrizzleNodeSqliteStorage";
|
|
1255
|
+
const storageLayer = runtime === "bun"
|
|
1256
|
+
? "DrizzleBunSqliteAuthStorageLive"
|
|
1257
|
+
: "DrizzleNodeSqliteAuthStorageLive";
|
|
1258
|
+
const medium = complexity === "medium";
|
|
1259
|
+
return `import { ${storageLayer} } from "@effect-auth/core/${storageModule}";
|
|
1260
|
+
${developmentSeedCoreImports(includePassword)}import { Data, Effect, Layer } from "effect";
|
|
1261
|
+
|
|
1262
|
+
${developmentSeedConfigurationErrorSource}
|
|
1263
|
+
${developmentSeedDependenciesSource(includePassword)}
|
|
1264
|
+
${developmentSeedProgramSource(includePassword)}
|
|
1265
|
+
${standaloneConfigurationSource("sqlite")}
|
|
1266
|
+
${medium ? "export " : ""}const AppDevelopmentSeedLive = (filename: string) =>
|
|
1267
|
+
DevelopmentSeedLive.pipe(
|
|
1268
|
+
Layer.provideMerge(
|
|
1269
|
+
Layer.mergeAll(
|
|
1270
|
+
${storageLayer}({ filename }),
|
|
1271
|
+
DevelopmentSeedSupportLive,
|
|
1272
|
+
),
|
|
1273
|
+
),
|
|
1274
|
+
);
|
|
1275
|
+
|
|
1276
|
+
${medium ? "export " : ""}const runDevelopmentSeed = Effect.gen(function* () {
|
|
1277
|
+
const filename = yield* developmentSeedConfiguration;
|
|
1278
|
+
return yield* developmentSeedProgram.pipe(
|
|
1279
|
+
Effect.provide(AppDevelopmentSeedLive(filename)),
|
|
1280
|
+
Effect.scoped,
|
|
1281
|
+
);
|
|
1282
|
+
});
|
|
1283
|
+
${medium ? "" : "\nawait Effect.runPromise(runDevelopmentSeed);\n"}`;
|
|
1284
|
+
};
|
|
1285
|
+
const postgresSeedSource = (adapter, includePassword, complexity) => {
|
|
1286
|
+
const drizzle = adapter === "drizzle";
|
|
1287
|
+
const medium = complexity === "medium";
|
|
1288
|
+
const storageImports = drizzle
|
|
1289
|
+
? 'import { DrizzlePostgresAuthStorageLive } from "@effect-auth/core/DrizzlePostgresStorage";\n'
|
|
1290
|
+
: `import * as PgClient from "@effect/sql-pg/PgClient";
|
|
1291
|
+
import { EffectQbPostgresCoreStoresLive } from "@effect-auth/core/EffectQbPostgresStorage";
|
|
1292
|
+
`;
|
|
1293
|
+
const layerSource = drizzle
|
|
1294
|
+
? `${medium ? "export " : ""}const AppDevelopmentSeedLive = (databaseUrl: string) =>
|
|
1295
|
+
DevelopmentSeedLive.pipe(
|
|
1296
|
+
Layer.provideMerge(
|
|
1297
|
+
Layer.mergeAll(
|
|
1298
|
+
DrizzlePostgresAuthStorageLive({ url: Redacted.make(databaseUrl) }),
|
|
1299
|
+
DevelopmentSeedSupportLive,
|
|
1300
|
+
),
|
|
1301
|
+
),
|
|
1302
|
+
);`
|
|
1303
|
+
: `${medium ? "export " : ""}const AppDevelopmentSeedLive = (sql: PgClient.PgClient) =>
|
|
1304
|
+
DevelopmentSeedLive.pipe(
|
|
1305
|
+
Layer.provideMerge(
|
|
1306
|
+
Layer.mergeAll(
|
|
1307
|
+
EffectQbPostgresCoreStoresLive(sql),
|
|
1308
|
+
DevelopmentSeedSupportLive,
|
|
1309
|
+
),
|
|
1310
|
+
),
|
|
1311
|
+
);`;
|
|
1312
|
+
const runSource = drizzle
|
|
1313
|
+
? `const databaseUrl = yield* developmentSeedConfiguration;
|
|
1314
|
+
return yield* developmentSeedProgram.pipe(
|
|
1315
|
+
Effect.provide(AppDevelopmentSeedLive(databaseUrl)),
|
|
1316
|
+
Effect.scoped,
|
|
1317
|
+
);`
|
|
1318
|
+
: `const databaseUrl = yield* developmentSeedConfiguration;
|
|
1319
|
+
const PostgresClientLive = PgClient.layer({
|
|
1320
|
+
url: Redacted.make(databaseUrl),
|
|
1321
|
+
});
|
|
1322
|
+
return yield* Effect.gen(function* () {
|
|
1323
|
+
const sql = yield* PgClient.PgClient;
|
|
1324
|
+
return yield* developmentSeedProgram.pipe(
|
|
1325
|
+
Effect.provide(AppDevelopmentSeedLive(sql)),
|
|
1326
|
+
);
|
|
1327
|
+
}).pipe(Effect.provide(PostgresClientLive), Effect.scoped);`;
|
|
1328
|
+
return `${storageImports}${developmentSeedCoreImports(includePassword)}import { Data, Effect, Layer, Redacted } from "effect";
|
|
1329
|
+
|
|
1330
|
+
${developmentSeedConfigurationErrorSource}
|
|
1331
|
+
${developmentSeedDependenciesSource(includePassword)}
|
|
1332
|
+
${developmentSeedProgramSource(includePassword)}
|
|
1333
|
+
${standaloneConfigurationSource("postgres")}
|
|
1334
|
+
${layerSource}
|
|
1335
|
+
|
|
1336
|
+
${medium ? "export " : ""}const runDevelopmentSeed = Effect.gen(function* () {
|
|
1337
|
+
${runSource}
|
|
1338
|
+
});
|
|
1339
|
+
${medium ? "" : "\nawait Effect.runPromise(runDevelopmentSeed);\n"}`;
|
|
1340
|
+
};
|
|
1341
|
+
const developmentSeedFiles = (adapter, target, includePassword, complexity) => {
|
|
1342
|
+
let content;
|
|
1343
|
+
switch (target) {
|
|
1344
|
+
case "alchemy-d1": {
|
|
1345
|
+
content = alchemyD1SeedSource(adapter, includePassword, complexity);
|
|
1346
|
+
break;
|
|
1347
|
+
}
|
|
1348
|
+
case "bun-sqlite": {
|
|
1349
|
+
content = sqliteSeedSource("bun", includePassword, complexity);
|
|
1350
|
+
break;
|
|
1351
|
+
}
|
|
1352
|
+
case "node-sqlite": {
|
|
1353
|
+
content = sqliteSeedSource("node", includePassword, complexity);
|
|
1354
|
+
break;
|
|
1355
|
+
}
|
|
1356
|
+
case "postgres": {
|
|
1357
|
+
content = postgresSeedSource(adapter, includePassword, complexity);
|
|
1358
|
+
break;
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
return [{ path: "seed-auth.ts", mediaType: "text/typescript", content }];
|
|
1362
|
+
};
|
|
1363
|
+
const fingerprint = (value) => {
|
|
1364
|
+
let hash = 2_166_136_261;
|
|
1365
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
1366
|
+
hash ^= value.codePointAt(index) ?? 0;
|
|
1367
|
+
hash = Math.imul(hash, 16_777_619);
|
|
1368
|
+
}
|
|
1369
|
+
const unsignedHash = hash < 0 ? hash + 4_294_967_296 : hash;
|
|
1370
|
+
return `fnv1a32:${unsignedHash.toString(16).padStart(8, "0")}`;
|
|
1371
|
+
};
|
|
1372
|
+
export const parseStorageSchemaGeneratorRequest = (request) => normalizeRequest(request);
|
|
1373
|
+
export const generateStorageArtifacts = (request) => {
|
|
1374
|
+
const normalized = normalizeRequest(request);
|
|
1375
|
+
const featureSelection = resolveStorageFeatures(normalized.features);
|
|
1376
|
+
const resolved = normalized.outputs.some(({ kind }) => kind === "development-seed")
|
|
1377
|
+
? includeDevelopmentSeedRequirements(featureSelection)
|
|
1378
|
+
: featureSelection;
|
|
1379
|
+
const schemaVersion = storageSchemaVersions[normalized.database];
|
|
1380
|
+
const files = [];
|
|
1381
|
+
const warnings = [];
|
|
1382
|
+
for (const output of normalized.outputs) {
|
|
1383
|
+
if (output.kind === "migration-sql") {
|
|
1384
|
+
files.push(...sqlFiles(normalized.database, output.layout, resolved));
|
|
1385
|
+
}
|
|
1386
|
+
else if (output.kind === "drizzle-schema") {
|
|
1387
|
+
files.push(...drizzleFiles(normalized.database, output.layout, output.includeRelations, resolved));
|
|
1388
|
+
if (output.includeRelations) {
|
|
1389
|
+
warnings.push(`Drizzle relations are application-level only and do not create ${normalized.database === "postgres" ? "PostgreSQL" : "SQLite"} foreign keys.`);
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
else {
|
|
1393
|
+
files.push(...developmentSeedFiles(normalized.adapter, output.target, normalized.features.includes("password"), output.complexity));
|
|
1394
|
+
warnings.push("The generated development seed creates public demo credentials and must never run against production data.");
|
|
1395
|
+
if (!normalized.features.includes("password")) {
|
|
1396
|
+
warnings.push("The selected features do not include password authentication, so the development seed does not create password credentials.");
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
const fingerprintInput = JSON.stringify({
|
|
1401
|
+
schemaVersion,
|
|
1402
|
+
request: normalized,
|
|
1403
|
+
resolved,
|
|
1404
|
+
files,
|
|
1405
|
+
warnings,
|
|
1406
|
+
});
|
|
1407
|
+
return {
|
|
1408
|
+
apiVersion: storageSchemaGeneratorApiVersion,
|
|
1409
|
+
generatorVersion: storageSchemaGeneratorVersion,
|
|
1410
|
+
schemaVersion,
|
|
1411
|
+
fingerprint: fingerprint(fingerprintInput),
|
|
1412
|
+
request: normalized,
|
|
1413
|
+
resolved,
|
|
1414
|
+
files,
|
|
1415
|
+
warnings,
|
|
1416
|
+
};
|
|
1417
|
+
};
|
|
1418
|
+
//# sourceMappingURL=StorageSchemaGenerator.js.map
|