@db3.ai/app 0.1.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +31 -0
- package/README.md +241 -0
- package/agent-instructions.md +69 -0
- package/bin/db3-agents.mjs +140 -0
- package/bin/db3.mjs +11 -0
- package/dist/ai/AIErrors.d.ts +33 -0
- package/dist/ai/AIErrors.js +43 -0
- package/dist/ai/AIFailover.d.ts +25 -0
- package/dist/ai/AIFailover.js +96 -0
- package/dist/ai/AIProviders.d.ts +35 -0
- package/dist/ai/AIProviders.js +197 -0
- package/dist/ai/AIQuotaDeferredError.d.ts +19 -0
- package/dist/ai/AIQuotaDeferredError.js +25 -0
- package/dist/ai/AIRateLimiter.d.ts +103 -0
- package/dist/ai/AIRateLimiter.js +690 -0
- package/dist/ai/Agent.d.ts +633 -0
- package/dist/ai/Agent.js +2976 -0
- package/dist/ai/AgentHistory.d.ts +11 -0
- package/dist/ai/AgentHistory.js +495 -0
- package/dist/ai/AgentRunJob.d.ts +21 -0
- package/dist/ai/AgentRunJob.js +53 -0
- package/dist/ai/Ai.d.ts +375 -0
- package/dist/ai/Ai.js +1771 -0
- package/dist/ai/AiConversation.d.ts +17 -0
- package/dist/ai/AiConversation.js +38 -0
- package/dist/ai/AiExecutionContext.d.ts +7 -0
- package/dist/ai/AiExecutionContext.js +16 -0
- package/dist/ai/AiMessage.d.ts +43 -0
- package/dist/ai/AiMessage.js +105 -0
- package/dist/ai/AiRateLimitBucket.d.ts +69 -0
- package/dist/ai/AiRateLimitBucket.js +138 -0
- package/dist/ai/AiRateLimitReservation.d.ts +56 -0
- package/dist/ai/AiRateLimitReservation.js +101 -0
- package/dist/ai/AiRequest.d.ts +78 -0
- package/dist/ai/AiRequest.js +384 -0
- package/dist/ai/Estimates.d.ts +26 -0
- package/dist/ai/Estimates.js +34 -0
- package/dist/ai/Models.d.ts +88 -0
- package/dist/ai/Models.js +328 -0
- package/dist/ai/OpenAIProviderError.d.ts +30 -0
- package/dist/ai/OpenAIProviderError.js +77 -0
- package/dist/ai/OpenAIQuotaRetry.d.ts +27 -0
- package/dist/ai/OpenAIQuotaRetry.js +144 -0
- package/dist/ai/ProviderCosts.d.ts +55 -0
- package/dist/ai/ProviderCosts.js +108 -0
- package/dist/ai/ResponsesProviderCall.d.ts +13 -0
- package/dist/ai/ResponsesProviderCall.js +29 -0
- package/dist/ai/agentCitations.d.ts +27 -0
- package/dist/ai/agentCitations.js +153 -0
- package/dist/ai/contracts/AI.d.ts +347 -0
- package/dist/ai/contracts/AI.js +13 -0
- package/dist/ai/contracts/Agent.d.ts +476 -0
- package/dist/ai/contracts/Agent.js +1 -0
- package/dist/ai/contracts/AiRequestRunCostSummary.d.ts +31 -0
- package/dist/ai/contracts/AiRequestRunCostSummary.js +1 -0
- package/dist/ai/contracts/Pricing.d.ts +88 -0
- package/dist/ai/contracts/Pricing.js +1 -0
- package/dist/ai/contracts/Providers.d.ts +68 -0
- package/dist/ai/contracts/Providers.js +1 -0
- package/dist/ai/contracts/QuotaRetry.d.ts +38 -0
- package/dist/ai/contracts/QuotaRetry.js +1 -0
- package/dist/ai/contracts/RateLimits.d.ts +45 -0
- package/dist/ai/contracts/RateLimits.js +1 -0
- package/dist/ai/contracts/ResponsesProviderCall.d.ts +28 -0
- package/dist/ai/contracts/ResponsesProviderCall.js +1 -0
- package/dist/ai/contracts/index.d.ts +8 -0
- package/dist/ai/contracts/index.js +8 -0
- package/dist/ai/index.d.ts +27 -0
- package/dist/ai/index.js +27 -0
- package/dist/ai/registry.d.ts +28 -0
- package/dist/ai/registry.js +49 -0
- package/dist/ai/sdkNodeCompatibility.d.ts +76 -0
- package/dist/ai/toolCallRecovery.d.ts +16 -0
- package/dist/ai/toolCallRecovery.js +71 -0
- package/dist/ai/toolHelpers.d.ts +65 -0
- package/dist/ai/toolHelpers.js +106 -0
- package/dist/auth/Auth.d.ts +641 -0
- package/dist/auth/Auth.js +927 -0
- package/dist/auth/AuthProvider.d.ts +104 -0
- package/dist/auth/AuthProvider.js +185 -0
- package/dist/auth/AuthToken.d.ts +123 -0
- package/dist/auth/AuthToken.js +156 -0
- package/dist/auth/PasswordResetToken.d.ts +33 -0
- package/dist/auth/PasswordResetToken.js +64 -0
- package/dist/auth/UserIdentity.d.ts +46 -0
- package/dist/auth/UserIdentity.js +72 -0
- package/dist/auth/contracts/AuthProviderDriver.d.ts +94 -0
- package/dist/auth/contracts/AuthProviderDriver.js +1 -0
- package/dist/auth/contracts/index.d.ts +1 -0
- package/dist/auth/contracts/index.js +1 -0
- package/dist/auth/index.d.ts +8 -0
- package/dist/auth/index.js +8 -0
- package/dist/auth/passwordHash.d.ts +26 -0
- package/dist/auth/passwordHash.js +96 -0
- package/dist/auth/providers/GoogleAuthProvider.d.ts +135 -0
- package/dist/auth/providers/GoogleAuthProvider.js +305 -0
- package/dist/auth/providers/PasswordAuthProvider.d.ts +115 -0
- package/dist/auth/providers/PasswordAuthProvider.js +195 -0
- package/dist/auth/providers/index.d.ts +3 -0
- package/dist/auth/providers/index.js +3 -0
- package/dist/auth/providers/resolveAuthProviders.d.ts +29 -0
- package/dist/auth/providers/resolveAuthProviders.js +111 -0
- package/dist/cache/Cache.d.ts +67 -0
- package/dist/cache/Cache.js +115 -0
- package/dist/cache/contracts/CacheDriver.d.ts +10 -0
- package/dist/cache/contracts/CacheDriver.js +1 -0
- package/dist/cache/contracts/CacheOperations.d.ts +26 -0
- package/dist/cache/contracts/CacheOperations.js +1 -0
- package/dist/cache/contracts/CacheOptions.d.ts +51 -0
- package/dist/cache/contracts/CacheOptions.js +1 -0
- package/dist/cache/contracts/CacheRepository.d.ts +45 -0
- package/dist/cache/contracts/CacheRepository.js +1 -0
- package/dist/cache/contracts/index.d.ts +4 -0
- package/dist/cache/contracts/index.js +4 -0
- package/dist/cache/drivers/CacheManagerDriver.d.ts +55 -0
- package/dist/cache/drivers/CacheManagerDriver.js +68 -0
- package/dist/cache/drivers/createCacheDriver.d.ts +8 -0
- package/dist/cache/drivers/createCacheDriver.js +147 -0
- package/dist/cache/index.d.ts +2 -0
- package/dist/cache/index.js +2 -0
- package/dist/cli/Cli.d.ts +17 -0
- package/dist/cli/Cli.js +120 -0
- package/dist/cli/commands/repl.d.ts +9 -0
- package/dist/cli/commands/repl.js +27 -0
- package/dist/cli/contracts/CliCommand.d.ts +30 -0
- package/dist/cli/contracts/CliCommand.js +1 -0
- package/dist/cli/contracts/CliConfig.d.ts +9 -0
- package/dist/cli/contracts/CliConfig.js +1 -0
- package/dist/cli/contracts/CliOptions.d.ts +13 -0
- package/dist/cli/contracts/CliOptions.js +1 -0
- package/dist/cli/contracts/CommandDefinition.d.ts +18 -0
- package/dist/cli/contracts/CommandDefinition.js +1 -0
- package/dist/cli/contracts/ReplOptions.d.ts +11 -0
- package/dist/cli/contracts/ReplOptions.js +1 -0
- package/dist/cli/contracts/index.d.ts +5 -0
- package/dist/cli/contracts/index.js +1 -0
- package/dist/cli/defineCommand.d.ts +10 -0
- package/dist/cli/defineCommand.js +25 -0
- package/dist/cli/index.d.ts +5 -0
- package/dist/cli/index.js +5 -0
- package/dist/cli/runDb3.d.ts +11 -0
- package/dist/cli/runDb3.js +70 -0
- package/dist/cli/runRepl.d.ts +12 -0
- package/dist/cli/runRepl.js +54 -0
- package/dist/config/Config.d.ts +48 -0
- package/dist/config/Config.js +80 -0
- package/dist/config/env.d.ts +26 -0
- package/dist/config/env.js +117 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.js +2 -0
- package/dist/db/ActiveProjection.d.ts +90 -0
- package/dist/db/ActiveProjection.js +134 -0
- package/dist/db/ActiveQueryBuilder.d.ts +268 -0
- package/dist/db/ActiveQueryBuilder.js +621 -0
- package/dist/db/ActiveRecord.d.ts +483 -0
- package/dist/db/ActiveRecord.js +765 -0
- package/dist/db/Database.d.ts +277 -0
- package/dist/db/Database.js +827 -0
- package/dist/db/FieldType.d.ts +540 -0
- package/dist/db/FieldType.js +706 -0
- package/dist/db/SoftDeletes.d.ts +30 -0
- package/dist/db/SoftDeletes.js +93 -0
- package/dist/db/commands/check.d.ts +6 -0
- package/dist/db/commands/check.js +8 -0
- package/dist/db/commands/index.d.ts +6 -0
- package/dist/db/commands/index.js +17 -0
- package/dist/db/commands/makeMigration.d.ts +7 -0
- package/dist/db/commands/makeMigration.js +9 -0
- package/dist/db/commands/migrate.d.ts +6 -0
- package/dist/db/commands/migrate.js +8 -0
- package/dist/db/connection.d.ts +10 -0
- package/dist/db/connection.js +55 -0
- package/dist/db/contracts/ActiveRecordDefinition.d.ts +64 -0
- package/dist/db/contracts/ActiveRecordDefinition.js +1 -0
- package/dist/db/contracts/DatabaseBackup.d.ts +7 -0
- package/dist/db/contracts/DatabaseBackup.js +1 -0
- package/dist/db/contracts/DatabaseMigrationsConfig.d.ts +9 -0
- package/dist/db/contracts/DatabaseMigrationsConfig.js +1 -0
- package/dist/db/contracts/index.d.ts +3 -0
- package/dist/db/contracts/index.js +3 -0
- package/dist/db/dialects/columnTypes.d.ts +20 -0
- package/dist/db/dialects/columnTypes.js +67 -0
- package/dist/db/dialects/index.d.ts +6 -0
- package/dist/db/dialects/index.js +6 -0
- package/dist/db/dialects/mariadb.d.ts +7 -0
- package/dist/db/dialects/mariadb.js +35 -0
- package/dist/db/dialects/mysql.d.ts +14 -0
- package/dist/db/dialects/mysql.js +203 -0
- package/dist/db/dialects/postgres.d.ts +5 -0
- package/dist/db/dialects/postgres.js +106 -0
- package/dist/db/dialects/resolveDialect.d.ts +14 -0
- package/dist/db/dialects/resolveDialect.js +57 -0
- package/dist/db/dialects/types.d.ts +44 -0
- package/dist/db/dialects/types.js +1 -0
- package/dist/db/errors.d.ts +15 -0
- package/dist/db/errors.js +20 -0
- package/dist/db/fields/BooleanField.d.ts +29 -0
- package/dist/db/fields/BooleanField.js +89 -0
- package/dist/db/fields/CharUuidField.d.ts +29 -0
- package/dist/db/fields/CharUuidField.js +63 -0
- package/dist/db/fields/ChoiceStringField.d.ts +25 -0
- package/dist/db/fields/ChoiceStringField.js +58 -0
- package/dist/db/fields/DecimalField.d.ts +20 -0
- package/dist/db/fields/DecimalField.js +105 -0
- package/dist/db/fields/EmailField.d.ts +31 -0
- package/dist/db/fields/EmailField.js +52 -0
- package/dist/db/fields/EncryptedJsonField.d.ts +82 -0
- package/dist/db/fields/EncryptedJsonField.js +169 -0
- package/dist/db/fields/IntegerField.d.ts +35 -0
- package/dist/db/fields/IntegerField.js +139 -0
- package/dist/db/fields/JsonField.d.ts +40 -0
- package/dist/db/fields/JsonField.js +79 -0
- package/dist/db/fields/JsonStringField.d.ts +21 -0
- package/dist/db/fields/JsonStringField.js +41 -0
- package/dist/db/fields/LinkField.d.ts +180 -0
- package/dist/db/fields/LinkField.js +359 -0
- package/dist/db/fields/PasswordField.d.ts +93 -0
- package/dist/db/fields/PasswordField.js +180 -0
- package/dist/db/fields/StringField.d.ts +43 -0
- package/dist/db/fields/StringField.js +102 -0
- package/dist/db/fields/StringListField.d.ts +54 -0
- package/dist/db/fields/StringListField.js +124 -0
- package/dist/db/fields/TextField.d.ts +25 -0
- package/dist/db/fields/TextField.js +44 -0
- package/dist/db/fields/TimestampField.d.ts +47 -0
- package/dist/db/fields/TimestampField.js +97 -0
- package/dist/db/fields/UlidField.d.ts +69 -0
- package/dist/db/fields/UlidField.js +114 -0
- package/dist/db/fields/UrlField.d.ts +30 -0
- package/dist/db/fields/UrlField.js +61 -0
- package/dist/db/fields/VectorField.d.ts +64 -0
- package/dist/db/fields/VectorField.js +180 -0
- package/dist/db/fields/createField.d.ts +2 -0
- package/dist/db/fields/createField.js +13 -0
- package/dist/db/fields/field.d.ts +36 -0
- package/dist/db/fields/field.js +101 -0
- package/dist/db/fields/index.d.ts +18 -0
- package/dist/db/fields/index.js +18 -0
- package/dist/db/fields/resolveFields.d.ts +17 -0
- package/dist/db/fields/resolveFields.js +38 -0
- package/dist/db/index.d.ts +13 -0
- package/dist/db/index.js +13 -0
- package/dist/db/migrations/DatabaseMigrationManager.d.ts +57 -0
- package/dist/db/migrations/DatabaseMigrationManager.js +589 -0
- package/dist/db/migrations/DatabaseSchemaInspector.d.ts +19 -0
- package/dist/db/migrations/DatabaseSchemaInspector.js +384 -0
- package/dist/db/migrations/KnexMigrationRenderer.d.ts +11 -0
- package/dist/db/migrations/KnexMigrationRenderer.js +390 -0
- package/dist/db/migrations/ModelSchemaCollector.d.ts +29 -0
- package/dist/db/migrations/ModelSchemaCollector.js +183 -0
- package/dist/db/migrations/SchemaDiffer.d.ts +13 -0
- package/dist/db/migrations/SchemaDiffer.js +427 -0
- package/dist/db/migrations/SchemaNames.d.ts +27 -0
- package/dist/db/migrations/SchemaNames.js +46 -0
- package/dist/db/migrations/SchemaSnapshotSerializer.d.ts +30 -0
- package/dist/db/migrations/SchemaSnapshotSerializer.js +49 -0
- package/dist/db/migrations/contracts/DatabaseMigration.d.ts +118 -0
- package/dist/db/migrations/contracts/DatabaseMigration.js +1 -0
- package/dist/db/migrations/contracts/SchemaChange.d.ts +83 -0
- package/dist/db/migrations/contracts/SchemaChange.js +1 -0
- package/dist/db/migrations/contracts/SchemaSnapshot.d.ts +94 -0
- package/dist/db/migrations/contracts/SchemaSnapshot.js +1 -0
- package/dist/db/migrations/contracts/index.d.ts +3 -0
- package/dist/db/migrations/contracts/index.js +3 -0
- package/dist/db/migrations/errors.d.ts +35 -0
- package/dist/db/migrations/errors.js +45 -0
- package/dist/db/migrations/index.d.ts +10 -0
- package/dist/db/migrations/index.js +10 -0
- package/dist/db/migrations/promoteDestructiveSchemaChanges.d.ts +19 -0
- package/dist/db/migrations/promoteDestructiveSchemaChanges.js +102 -0
- package/dist/db/queryMonitor.d.ts +142 -0
- package/dist/db/queryMonitor.js +357 -0
- package/dist/db/sqlErrors.d.ts +11 -0
- package/dist/db/sqlErrors.js +17 -0
- package/dist/db/test/db.d.ts +11 -0
- package/dist/db/test/db.js +109 -0
- package/dist/devtools/HttpEventDispatcher.d.ts +19 -0
- package/dist/devtools/HttpEventDispatcher.js +180 -0
- package/dist/devtools/contracts/DevtoolsEventDispatcher.d.ts +53 -0
- package/dist/devtools/contracts/DevtoolsEventDispatcher.js +1 -0
- package/dist/devtools/contracts/index.d.ts +1 -0
- package/dist/devtools/contracts/index.js +1 -0
- package/dist/devtools/environment.d.ts +10 -0
- package/dist/devtools/environment.js +14 -0
- package/dist/devtools/index.d.ts +3 -0
- package/dist/devtools/index.js +3 -0
- package/dist/events/Events.d.ts +70 -0
- package/dist/events/Events.js +126 -0
- package/dist/events/contracts/EventConstructor.d.ts +12 -0
- package/dist/events/contracts/EventConstructor.js +1 -0
- package/dist/events/contracts/EventListener.d.ts +6 -0
- package/dist/events/contracts/EventListener.js +1 -0
- package/dist/events/contracts/EventUnsubscribe.d.ts +4 -0
- package/dist/events/contracts/EventUnsubscribe.js +1 -0
- package/dist/events/contracts/index.d.ts +3 -0
- package/dist/events/contracts/index.js +3 -0
- package/dist/events/index.d.ts +2 -0
- package/dist/events/index.js +2 -0
- package/dist/flows/FlowBlockRegistry.d.ts +39 -0
- package/dist/flows/FlowBlockRegistry.js +66 -0
- package/dist/flows/FlowCompiler.d.ts +26 -0
- package/dist/flows/FlowCompiler.js +488 -0
- package/dist/flows/FlowDefinitionError.d.ts +21 -0
- package/dist/flows/FlowDefinitionError.js +16 -0
- package/dist/flows/FlowStepJob.d.ts +28 -0
- package/dist/flows/FlowStepJob.js +31 -0
- package/dist/flows/FlowValueValidator.d.ts +32 -0
- package/dist/flows/FlowValueValidator.js +105 -0
- package/dist/flows/Flows.d.ts +102 -0
- package/dist/flows/Flows.js +871 -0
- package/dist/flows/blocks/FlowInput.d.ts +10 -0
- package/dist/flows/blocks/FlowInput.js +29 -0
- package/dist/flows/blocks/FlowOutput.d.ts +10 -0
- package/dist/flows/blocks/FlowOutput.js +29 -0
- package/dist/flows/blocks/Subflow.d.ts +10 -0
- package/dist/flows/blocks/Subflow.js +21 -0
- package/dist/flows/blocks/index.d.ts +6 -0
- package/dist/flows/blocks/index.js +8 -0
- package/dist/flows/constants.d.ts +55 -0
- package/dist/flows/constants.js +47 -0
- package/dist/flows/contracts/FlowBlock.d.ts +64 -0
- package/dist/flows/contracts/FlowBlock.js +1 -0
- package/dist/flows/contracts/FlowCompiler.d.ts +30 -0
- package/dist/flows/contracts/FlowCompiler.js +1 -0
- package/dist/flows/contracts/FlowDefinition.d.ts +118 -0
- package/dist/flows/contracts/FlowDefinition.js +1 -0
- package/dist/flows/contracts/FlowDefinitionStore.d.ts +47 -0
- package/dist/flows/contracts/FlowDefinitionStore.js +1 -0
- package/dist/flows/contracts/FlowRun.d.ts +40 -0
- package/dist/flows/contracts/FlowRun.js +1 -0
- package/dist/flows/contracts/FlowValue.d.ts +49 -0
- package/dist/flows/contracts/FlowValue.js +1 -0
- package/dist/flows/contracts/FlowsService.d.ts +37 -0
- package/dist/flows/contracts/FlowsService.js +1 -0
- package/dist/flows/contracts/index.d.ts +7 -0
- package/dist/flows/contracts/index.js +7 -0
- package/dist/flows/defineBlock.d.ts +18 -0
- package/dist/flows/defineBlock.js +19 -0
- package/dist/flows/drivers/FileFlowDefinitionStore.d.ts +53 -0
- package/dist/flows/drivers/FileFlowDefinitionStore.js +313 -0
- package/dist/flows/drivers/index.d.ts +1 -0
- package/dist/flows/drivers/index.js +1 -0
- package/dist/flows/errors.d.ts +8 -0
- package/dist/flows/errors.js +19 -0
- package/dist/flows/index.d.ts +13 -0
- package/dist/flows/index.js +13 -0
- package/dist/flows/models/FlowRun.d.ts +55 -0
- package/dist/flows/models/FlowRun.js +126 -0
- package/dist/flows/models/FlowRunEvent.d.ts +41 -0
- package/dist/flows/models/FlowRunEvent.js +85 -0
- package/dist/flows/models/FlowStepRun.d.ts +56 -0
- package/dist/flows/models/FlowStepRun.js +137 -0
- package/dist/flows/models/index.d.ts +10 -0
- package/dist/flows/models/index.js +14 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +16 -0
- package/dist/logging/Log.d.ts +66 -0
- package/dist/logging/Log.js +79 -0
- package/dist/logging/contracts/HttpExchange.d.ts +50 -0
- package/dist/logging/contracts/HttpExchange.js +1 -0
- package/dist/logging/contracts/Logger.d.ts +41 -0
- package/dist/logging/contracts/Logger.js +1 -0
- package/dist/logging/contracts/LoggerDriver.d.ts +16 -0
- package/dist/logging/contracts/LoggerDriver.js +1 -0
- package/dist/logging/contracts/LoggingOptions.d.ts +49 -0
- package/dist/logging/contracts/LoggingOptions.js +1 -0
- package/dist/logging/contracts/index.d.ts +4 -0
- package/dist/logging/contracts/index.js +4 -0
- package/dist/logging/drivers/PinoLoggerDriver.d.ts +24 -0
- package/dist/logging/drivers/PinoLoggerDriver.js +291 -0
- package/dist/logging/drivers/index.d.ts +1 -0
- package/dist/logging/drivers/index.js +1 -0
- package/dist/logging/index.d.ts +3 -0
- package/dist/logging/index.js +3 -0
- package/dist/logging/transports/DevtoolsLogTransport.d.ts +35 -0
- package/dist/logging/transports/DevtoolsLogTransport.js +96 -0
- package/dist/mail/Mail.d.ts +62 -0
- package/dist/mail/Mail.js +98 -0
- package/dist/mail/index.d.ts +4 -0
- package/dist/mail/index.js +4 -0
- package/dist/mail/transports/FileMailTransport.d.ts +12 -0
- package/dist/mail/transports/FileMailTransport.js +41 -0
- package/dist/mail/transports/MailgunTransport.d.ts +22 -0
- package/dist/mail/transports/MailgunTransport.js +57 -0
- package/dist/mail/transports/ResendTransport.d.ts +14 -0
- package/dist/mail/transports/ResendTransport.js +55 -0
- package/dist/media/MediaFile.d.ts +48 -0
- package/dist/media/MediaFile.js +104 -0
- package/dist/media/MediaItem.d.ts +47 -0
- package/dist/media/MediaItem.js +106 -0
- package/dist/media/MediaLibrary.d.ts +42 -0
- package/dist/media/MediaLibrary.js +94 -0
- package/dist/media/MediaManager.d.ts +159 -0
- package/dist/media/MediaManager.js +754 -0
- package/dist/media/constants.d.ts +27 -0
- package/dist/media/constants.js +19 -0
- package/dist/media/contracts/MediaOptions.d.ts +8 -0
- package/dist/media/contracts/MediaOptions.js +1 -0
- package/dist/media/contracts/index.d.ts +1 -0
- package/dist/media/contracts/index.js +1 -0
- package/dist/media/image/ImageReconstructionError.d.ts +15 -0
- package/dist/media/image/ImageReconstructionError.js +18 -0
- package/dist/media/image/ImageVariantRenderer.d.ts +44 -0
- package/dist/media/image/ImageVariantRenderer.js +337 -0
- package/dist/media/image/ImageVariantRequest.d.ts +28 -0
- package/dist/media/image/ImageVariantRequest.js +55 -0
- package/dist/media/image/contracts/ImageProcessor.d.ts +46 -0
- package/dist/media/image/contracts/ImageProcessor.js +1 -0
- package/dist/media/image/contracts/ImageVariant.d.ts +31 -0
- package/dist/media/image/contracts/ImageVariant.js +7 -0
- package/dist/media/image/contracts/ImageVariantCacheOptions.d.ts +20 -0
- package/dist/media/image/contracts/ImageVariantCacheOptions.js +1 -0
- package/dist/media/image/contracts/index.d.ts +3 -0
- package/dist/media/image/contracts/index.js +3 -0
- package/dist/media/image/index.d.ts +5 -0
- package/dist/media/image/index.js +5 -0
- package/dist/media/image/processors/SharpImageProcessor.d.ts +25 -0
- package/dist/media/image/processors/SharpImageProcessor.js +112 -0
- package/dist/media/image/processors/index.d.ts +1 -0
- package/dist/media/image/processors/index.js +1 -0
- package/dist/media/index.d.ts +8 -0
- package/dist/media/index.js +8 -0
- package/dist/media/types.d.ts +129 -0
- package/dist/media/types.js +1 -0
- package/dist/queue/FailedJob.d.ts +31 -0
- package/dist/queue/FailedJob.js +41 -0
- package/dist/queue/Queue.d.ts +208 -0
- package/dist/queue/Queue.js +685 -0
- package/dist/queue/QueueEvents.d.ts +31 -0
- package/dist/queue/QueueEvents.js +49 -0
- package/dist/queue/QueueRetryLaterError.d.ts +23 -0
- package/dist/queue/QueueRetryLaterError.js +34 -0
- package/dist/queue/QueueWorker.d.ts +72 -0
- package/dist/queue/QueueWorker.js +236 -0
- package/dist/queue/QueueableJob.d.ts +109 -0
- package/dist/queue/QueueableJob.js +137 -0
- package/dist/queue/QueuedJob.d.ts +31 -0
- package/dist/queue/QueuedJob.js +52 -0
- package/dist/queue/RetryPolicy.d.ts +51 -0
- package/dist/queue/RetryPolicy.js +84 -0
- package/dist/queue/commands/index.d.ts +4 -0
- package/dist/queue/commands/index.js +11 -0
- package/dist/queue/commands/makeJob.d.ts +7 -0
- package/dist/queue/commands/makeJob.js +9 -0
- package/dist/queue/console.d.ts +60 -0
- package/dist/queue/console.js +348 -0
- package/dist/queue/contracts/CreateJob.d.ts +12 -0
- package/dist/queue/contracts/CreateJob.js +1 -0
- package/dist/queue/contracts/QueueDriver.d.ts +122 -0
- package/dist/queue/contracts/QueueDriver.js +1 -0
- package/dist/queue/contracts/QueueEvents.d.ts +61 -0
- package/dist/queue/contracts/QueueEvents.js +1 -0
- package/dist/queue/contracts/QueuePayload.d.ts +136 -0
- package/dist/queue/contracts/QueuePayload.js +1 -0
- package/dist/queue/contracts/QueueRetry.d.ts +43 -0
- package/dist/queue/contracts/QueueRetry.js +1 -0
- package/dist/queue/contracts/QueueService.d.ts +199 -0
- package/dist/queue/contracts/QueueService.js +1 -0
- package/dist/queue/contracts/QueueWorkerLifecycle.d.ts +65 -0
- package/dist/queue/contracts/QueueWorkerLifecycle.js +1 -0
- package/dist/queue/contracts/QueueableJob.d.ts +50 -0
- package/dist/queue/contracts/QueueableJob.js +1 -0
- package/dist/queue/contracts/RedisQueueDriver.d.ts +37 -0
- package/dist/queue/contracts/RedisQueueDriver.js +1 -0
- package/dist/queue/contracts/index.d.ts +9 -0
- package/dist/queue/contracts/index.js +9 -0
- package/dist/queue/createJob.d.ts +18 -0
- package/dist/queue/createJob.js +52 -0
- package/dist/queue/drivers/DatabaseQueueDriver.d.ts +83 -0
- package/dist/queue/drivers/DatabaseQueueDriver.js +393 -0
- package/dist/queue/drivers/RedisQueueDriver.d.ts +102 -0
- package/dist/queue/drivers/RedisQueueDriver.js +641 -0
- package/dist/queue/index.d.ts +13 -0
- package/dist/queue/index.js +13 -0
- package/dist/queue/queueMonitor.d.ts +133 -0
- package/dist/queue/queueMonitor.js +238 -0
- package/dist/scheduler/ScheduledCall.d.ts +25 -0
- package/dist/scheduler/ScheduledCall.js +31 -0
- package/dist/scheduler/ScheduledEvent.d.ts +74 -0
- package/dist/scheduler/ScheduledEvent.js +115 -0
- package/dist/scheduler/ScheduledJob.d.ts +34 -0
- package/dist/scheduler/ScheduledJob.js +50 -0
- package/dist/scheduler/ScheduledOccurrence.d.ts +74 -0
- package/dist/scheduler/ScheduledOccurrence.js +194 -0
- package/dist/scheduler/ScheduledOccurrenceRecorder.d.ts +34 -0
- package/dist/scheduler/ScheduledOccurrenceRecorder.js +106 -0
- package/dist/scheduler/Scheduler.d.ts +76 -0
- package/dist/scheduler/Scheduler.js +186 -0
- package/dist/scheduler/SchedulerWorker.d.ts +37 -0
- package/dist/scheduler/SchedulerWorker.js +119 -0
- package/dist/scheduler/console.d.ts +18 -0
- package/dist/scheduler/console.js +288 -0
- package/dist/scheduler/constants.d.ts +13 -0
- package/dist/scheduler/constants.js +23 -0
- package/dist/scheduler/contracts/Scheduler.d.ts +104 -0
- package/dist/scheduler/contracts/Scheduler.js +1 -0
- package/dist/scheduler/contracts/SchedulerConsole.d.ts +37 -0
- package/dist/scheduler/contracts/SchedulerConsole.js +1 -0
- package/dist/scheduler/contracts/SchedulerWorker.d.ts +18 -0
- package/dist/scheduler/contracts/SchedulerWorker.js +1 -0
- package/dist/scheduler/contracts/index.d.ts +3 -0
- package/dist/scheduler/contracts/index.js +3 -0
- package/dist/scheduler/index.d.ts +9 -0
- package/dist/scheduler/index.js +9 -0
- package/dist/scheduler/scheduleTime.d.ts +30 -0
- package/dist/scheduler/scheduleTime.js +64 -0
- package/dist/security/Security.d.ts +60 -0
- package/dist/security/Security.js +252 -0
- package/dist/security/SecurityError.d.ts +13 -0
- package/dist/security/SecurityError.js +16 -0
- package/dist/security/contracts/SecurityOptions.d.ts +17 -0
- package/dist/security/contracts/SecurityOptions.js +1 -0
- package/dist/security/contracts/SecurityPayload.d.ts +13 -0
- package/dist/security/contracts/SecurityPayload.js +1 -0
- package/dist/security/contracts/index.d.ts +2 -0
- package/dist/security/contracts/index.js +2 -0
- package/dist/security/ensureAppKey.d.ts +16 -0
- package/dist/security/ensureAppKey.js +69 -0
- package/dist/security/index.d.ts +4 -0
- package/dist/security/index.js +4 -0
- package/dist/serialization/Serializable.d.ts +17 -0
- package/dist/serialization/Serializable.js +1 -0
- package/dist/serialization/SerializationError.d.ts +40 -0
- package/dist/serialization/SerializationError.js +42 -0
- package/dist/serialization/SerializationRegistry.d.ts +76 -0
- package/dist/serialization/SerializationRegistry.js +153 -0
- package/dist/serialization/SerializationRegistryError.d.ts +18 -0
- package/dist/serialization/SerializationRegistryError.js +18 -0
- package/dist/serialization/Serializer.d.ts +37 -0
- package/dist/serialization/Serializer.js +477 -0
- package/dist/serialization/contracts/SerializableClass.d.ts +20 -0
- package/dist/serialization/contracts/SerializableClass.js +1 -0
- package/dist/serialization/contracts/SerializedValue.d.ts +59 -0
- package/dist/serialization/contracts/SerializedValue.js +19 -0
- package/dist/serialization/contracts/SerializerOptions.d.ts +17 -0
- package/dist/serialization/contracts/SerializerOptions.js +1 -0
- package/dist/serialization/contracts/SerializerService.d.ts +26 -0
- package/dist/serialization/contracts/SerializerService.js +1 -0
- package/dist/serialization/contracts/index.d.ts +4 -0
- package/dist/serialization/contracts/index.js +4 -0
- package/dist/serialization/index.d.ts +6 -0
- package/dist/serialization/index.js +6 -0
- package/dist/server/App.d.ts +141 -0
- package/dist/server/App.js +225 -0
- package/dist/server/RequestContext.d.ts +42 -0
- package/dist/server/RequestContext.js +95 -0
- package/dist/server/appContext.d.ts +34 -0
- package/dist/server/appContext.js +42 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.js +3 -0
- package/dist/ssr/constants.d.ts +6 -0
- package/dist/ssr/constants.js +6 -0
- package/dist/ssr/contracts/DocumentHead.d.ts +32 -0
- package/dist/ssr/contracts/DocumentHead.js +1 -0
- package/dist/ssr/contracts/SsrRenderContext.d.ts +23 -0
- package/dist/ssr/contracts/SsrRenderContext.js +1 -0
- package/dist/ssr/contracts/SsrRenderResult.d.ts +21 -0
- package/dist/ssr/contracts/SsrRenderResult.js +1 -0
- package/dist/ssr/contracts/SsrRenderer.d.ts +9 -0
- package/dist/ssr/contracts/SsrRenderer.js +1 -0
- package/dist/ssr/contracts/SsrRequest.d.ts +16 -0
- package/dist/ssr/contracts/SsrRequest.js +1 -0
- package/dist/ssr/contracts/index.d.ts +5 -0
- package/dist/ssr/contracts/index.js +1 -0
- package/dist/ssr/createSsrRenderContext.d.ts +9 -0
- package/dist/ssr/createSsrRenderContext.js +20 -0
- package/dist/ssr/fastify/contracts/FastifySsrOptions.d.ts +21 -0
- package/dist/ssr/fastify/contracts/FastifySsrOptions.js +1 -0
- package/dist/ssr/fastify/contracts/index.d.ts +1 -0
- package/dist/ssr/fastify/contracts/index.js +1 -0
- package/dist/ssr/fastify/fastifySsr.d.ts +25 -0
- package/dist/ssr/fastify/fastifySsr.js +89 -0
- package/dist/ssr/fastify/index.d.ts +2 -0
- package/dist/ssr/fastify/index.js +1 -0
- package/dist/ssr/index.d.ts +6 -0
- package/dist/ssr/index.js +5 -0
- package/dist/ssr/renderDocumentHead.d.ts +8 -0
- package/dist/ssr/renderDocumentHead.js +62 -0
- package/dist/ssr/renderSsrDocument.d.ts +14 -0
- package/dist/ssr/renderSsrDocument.js +28 -0
- package/dist/ssr/serializeSsrState.d.ts +10 -0
- package/dist/ssr/serializeSsrState.js +18 -0
- package/dist/ssr/vite/contracts/ViteSsrOptions.d.ts +45 -0
- package/dist/ssr/vite/contracts/ViteSsrOptions.js +1 -0
- package/dist/ssr/vite/contracts/index.d.ts +1 -0
- package/dist/ssr/vite/contracts/index.js +1 -0
- package/dist/ssr/vite/fastifyViteSsr.d.ts +24 -0
- package/dist/ssr/vite/fastifyViteSsr.js +213 -0
- package/dist/ssr/vite/index.d.ts +4 -0
- package/dist/ssr/vite/index.js +2 -0
- package/dist/ssr/vite/viteSsrManifest.d.ts +16 -0
- package/dist/ssr/vite/viteSsrManifest.js +63 -0
- package/dist/storage/Storage.d.ts +244 -0
- package/dist/storage/Storage.js +348 -0
- package/dist/storage/contents.d.ts +8 -0
- package/dist/storage/contents.js +18 -0
- package/dist/storage/contracts/StorageListing.d.ts +50 -0
- package/dist/storage/contracts/StorageListing.js +1 -0
- package/dist/storage/contracts/index.d.ts +1 -0
- package/dist/storage/contracts/index.js +1 -0
- package/dist/storage/drivers/FlystorageDisk.d.ts +185 -0
- package/dist/storage/drivers/FlystorageDisk.js +250 -0
- package/dist/storage/drivers/FlystorageListing.d.ts +27 -0
- package/dist/storage/drivers/FlystorageListing.js +69 -0
- package/dist/storage/drivers/LocalStorageDisk.d.ts +25 -0
- package/dist/storage/drivers/LocalStorageDisk.js +38 -0
- package/dist/storage/drivers/S3StorageDisk.d.ts +17 -0
- package/dist/storage/drivers/S3StorageDisk.js +102 -0
- package/dist/storage/drivers/index.d.ts +3 -0
- package/dist/storage/drivers/index.js +3 -0
- package/dist/storage/index.d.ts +7 -0
- package/dist/storage/index.js +7 -0
- package/dist/storage/mime.d.ts +7 -0
- package/dist/storage/mime.js +28 -0
- package/dist/storage/path.d.ts +22 -0
- package/dist/storage/path.js +61 -0
- package/dist/storage/types.d.ts +218 -0
- package/dist/storage/types.js +1 -0
- package/dist/url/UrlGenerator.d.ts +32 -0
- package/dist/url/UrlGenerator.js +61 -0
- package/dist/url/contracts/UrlGeneratorOptions.d.ts +13 -0
- package/dist/url/contracts/UrlGeneratorOptions.js +1 -0
- package/dist/url/contracts/index.d.ts +1 -0
- package/dist/url/contracts/index.js +1 -0
- package/dist/url/index.d.ts +2 -0
- package/dist/url/index.js +2 -0
- package/dist/validation/index.d.ts +28 -0
- package/dist/validation/index.js +260 -0
- package/package.json +290 -0
- package/src/ai/AIErrors.ts +46 -0
- package/src/ai/AIFailover.ts +101 -0
- package/src/ai/AIProviders.ts +228 -0
- package/src/ai/AIQuotaDeferredError.ts +26 -0
- package/src/ai/AIRateLimiter.ts +880 -0
- package/src/ai/Agent.ts +3630 -0
- package/src/ai/AgentHistory.ts +576 -0
- package/src/ai/AgentRunJob.ts +65 -0
- package/src/ai/Ai.ts +2176 -0
- package/src/ai/AiConversation.ts +49 -0
- package/src/ai/AiExecutionContext.ts +19 -0
- package/src/ai/AiMessage.ts +131 -0
- package/src/ai/AiRateLimitBucket.ts +163 -0
- package/src/ai/AiRateLimitReservation.ts +117 -0
- package/src/ai/AiRequest.ts +466 -0
- package/src/ai/Estimates.ts +36 -0
- package/src/ai/Models.ts +373 -0
- package/src/ai/OpenAIProviderError.ts +98 -0
- package/src/ai/OpenAIQuotaRetry.ts +183 -0
- package/src/ai/ProviderCosts.ts +156 -0
- package/src/ai/README.md +187 -0
- package/src/ai/ResponsesProviderCall.ts +34 -0
- package/src/ai/agentCitations.ts +186 -0
- package/src/ai/contracts/AI.ts +380 -0
- package/src/ai/contracts/Agent.ts +539 -0
- package/src/ai/contracts/AiRequestRunCostSummary.ts +31 -0
- package/src/ai/contracts/Pricing.ts +95 -0
- package/src/ai/contracts/Providers.ts +73 -0
- package/src/ai/contracts/QuotaRetry.ts +39 -0
- package/src/ai/contracts/RateLimits.ts +49 -0
- package/src/ai/contracts/ResponsesProviderCall.ts +30 -0
- package/src/ai/contracts/index.ts +8 -0
- package/src/ai/examples/Conversation.ts +12 -0
- package/src/ai/examples/HelpAgent.ts +27 -0
- package/src/ai/examples/createHelpImage.ts +13 -0
- package/src/ai/index.ts +27 -0
- package/src/ai/registry.ts +70 -0
- package/src/ai/sdkNodeCompatibility.d.ts +76 -0
- package/src/ai/toolCallRecovery.ts +82 -0
- package/src/ai/toolHelpers.ts +145 -0
- package/src/auth/Auth.ts +1422 -0
- package/src/auth/AuthProvider.ts +251 -0
- package/src/auth/AuthToken.ts +239 -0
- package/src/auth/PasswordResetToken.ts +93 -0
- package/src/auth/README.md +396 -0
- package/src/auth/UserIdentity.ts +112 -0
- package/src/auth/contracts/AuthProviderDriver.ts +114 -0
- package/src/auth/contracts/index.ts +1 -0
- package/src/auth/examples/runPasswordAuth.ts +45 -0
- package/src/auth/index.ts +8 -0
- package/src/auth/passwordHash.ts +160 -0
- package/src/auth/providers/GoogleAuthProvider.ts +470 -0
- package/src/auth/providers/PasswordAuthProvider.ts +256 -0
- package/src/auth/providers/index.ts +3 -0
- package/src/auth/providers/resolveAuthProviders.ts +166 -0
- package/src/cache/Cache.ts +151 -0
- package/src/cache/README.md +137 -0
- package/src/cache/contracts/CacheDriver.ts +11 -0
- package/src/cache/contracts/CacheOperations.ts +28 -0
- package/src/cache/contracts/CacheOptions.ts +56 -0
- package/src/cache/contracts/CacheRepository.ts +62 -0
- package/src/cache/contracts/index.ts +4 -0
- package/src/cache/drivers/CacheManagerDriver.ts +84 -0
- package/src/cache/drivers/createCacheDriver.ts +191 -0
- package/src/cache/examples/runNoteCache.ts +37 -0
- package/src/cache/index.ts +2 -0
- package/src/cli/Cli.ts +110 -0
- package/src/cli/README.md +164 -0
- package/src/cli/commands/repl.ts +29 -0
- package/src/cli/contracts/CliCommand.ts +33 -0
- package/src/cli/contracts/CliConfig.ts +10 -0
- package/src/cli/contracts/CliOptions.ts +13 -0
- package/src/cli/contracts/CommandDefinition.ts +19 -0
- package/src/cli/contracts/ReplOptions.ts +11 -0
- package/src/cli/contracts/index.ts +5 -0
- package/src/cli/defineCommand.ts +25 -0
- package/src/cli/index.ts +5 -0
- package/src/cli/runDb3.ts +63 -0
- package/src/cli/runRepl.ts +55 -0
- package/src/config/Config.ts +110 -0
- package/src/config/README.md +142 -0
- package/src/config/env.ts +164 -0
- package/src/config/examples/loadNotesConfig.ts +29 -0
- package/src/config/examples/runConfig.ts +40 -0
- package/src/config/index.ts +2 -0
- package/src/db/ActiveProjection.ts +311 -0
- package/src/db/ActiveQueryBuilder.ts +831 -0
- package/src/db/ActiveRecord.ts +1317 -0
- package/src/db/Database.ts +1283 -0
- package/src/db/FieldType.ts +1243 -0
- package/src/db/README.md +508 -0
- package/src/db/SoftDeletes.ts +158 -0
- package/src/db/commands/check.ts +10 -0
- package/src/db/commands/index.ts +19 -0
- package/src/db/commands/makeMigration.ts +11 -0
- package/src/db/commands/migrate.ts +10 -0
- package/src/db/connection.ts +68 -0
- package/src/db/contracts/ActiveRecordDefinition.ts +69 -0
- package/src/db/contracts/DatabaseBackup.ts +7 -0
- package/src/db/contracts/DatabaseMigrationsConfig.ts +10 -0
- package/src/db/contracts/index.ts +3 -0
- package/src/db/dialects/columnTypes.ts +103 -0
- package/src/db/dialects/index.ts +6 -0
- package/src/db/dialects/mariadb.ts +51 -0
- package/src/db/dialects/mysql.ts +277 -0
- package/src/db/dialects/postgres.ts +143 -0
- package/src/db/dialects/resolveDialect.ts +88 -0
- package/src/db/dialects/types.ts +59 -0
- package/src/db/errors.ts +22 -0
- package/src/db/examples/DefinedUser.ts +20 -0
- package/src/db/examples/FieldNote.ts +27 -0
- package/src/db/examples/KnowledgeNote.ts +29 -0
- package/src/db/examples/NoteCodeField.ts +9 -0
- package/src/db/examples/createNotesTogether.ts +24 -0
- package/src/db/examples/outputs/workspace-notes.json +9 -0
- package/src/db/examples/runFieldNotes.ts +51 -0
- package/src/db/examples/runNoteMigrations.ts +64 -0
- package/src/db/examples/runWorkspaceNotes.ts +86 -0
- package/src/db/examples/workspaceNotes.ts +57 -0
- package/src/db/fields/BooleanField.ts +128 -0
- package/src/db/fields/CharUuidField.ts +91 -0
- package/src/db/fields/ChoiceStringField.ts +97 -0
- package/src/db/fields/DecimalField.ts +157 -0
- package/src/db/fields/EmailField.ts +79 -0
- package/src/db/fields/EncryptedJsonField.ts +211 -0
- package/src/db/fields/IntegerField.ts +200 -0
- package/src/db/fields/JsonField.ts +108 -0
- package/src/db/fields/JsonStringField.ts +63 -0
- package/src/db/fields/LinkField.ts +502 -0
- package/src/db/fields/PasswordField.ts +294 -0
- package/src/db/fields/StringField.ts +154 -0
- package/src/db/fields/StringListField.ts +179 -0
- package/src/db/fields/TextField.ts +71 -0
- package/src/db/fields/TimestampField.ts +164 -0
- package/src/db/fields/UlidField.ts +189 -0
- package/src/db/fields/UrlField.ts +97 -0
- package/src/db/fields/VectorField.ts +266 -0
- package/src/db/fields/createField.ts +22 -0
- package/src/db/fields/field.ts +209 -0
- package/src/db/fields/index.ts +76 -0
- package/src/db/fields/resolveFields.ts +69 -0
- package/src/db/index.ts +13 -0
- package/src/db/migrations/DatabaseMigrationManager.ts +756 -0
- package/src/db/migrations/DatabaseSchemaInspector.ts +541 -0
- package/src/db/migrations/KnexMigrationRenderer.ts +490 -0
- package/src/db/migrations/ModelSchemaCollector.ts +240 -0
- package/src/db/migrations/SchemaDiffer.ts +541 -0
- package/src/db/migrations/SchemaNames.ts +62 -0
- package/src/db/migrations/SchemaSnapshotSerializer.ts +59 -0
- package/src/db/migrations/contracts/DatabaseMigration.ts +143 -0
- package/src/db/migrations/contracts/SchemaChange.ts +113 -0
- package/src/db/migrations/contracts/SchemaSnapshot.ts +122 -0
- package/src/db/migrations/contracts/index.ts +3 -0
- package/src/db/migrations/errors.ts +45 -0
- package/src/db/migrations/index.ts +10 -0
- package/src/db/migrations/promoteDestructiveSchemaChanges.ts +120 -0
- package/src/db/queryMonitor.ts +549 -0
- package/src/db/sqlErrors.ts +36 -0
- package/src/db/test/db.ts +159 -0
- package/src/devtools/HttpEventDispatcher.ts +214 -0
- package/src/devtools/contracts/DevtoolsEventDispatcher.ts +57 -0
- package/src/devtools/contracts/index.ts +1 -0
- package/src/devtools/environment.ts +18 -0
- package/src/devtools/index.ts +3 -0
- package/src/events/Events.ts +165 -0
- package/src/events/README.md +106 -0
- package/src/events/contracts/EventConstructor.ts +12 -0
- package/src/events/contracts/EventListener.ts +8 -0
- package/src/events/contracts/EventUnsubscribe.ts +4 -0
- package/src/events/contracts/index.ts +3 -0
- package/src/events/examples/NoteSaved.ts +9 -0
- package/src/events/examples/runNoteEvents.ts +31 -0
- package/src/events/index.ts +2 -0
- package/src/flows/FlowBlockRegistry.ts +79 -0
- package/src/flows/FlowCompiler.ts +624 -0
- package/src/flows/FlowDefinitionError.ts +24 -0
- package/src/flows/FlowStepJob.ts +54 -0
- package/src/flows/FlowValueValidator.ts +120 -0
- package/src/flows/Flows.ts +1118 -0
- package/src/flows/README.md +144 -0
- package/src/flows/blocks/FlowInput.ts +32 -0
- package/src/flows/blocks/FlowOutput.ts +32 -0
- package/src/flows/blocks/Subflow.ts +24 -0
- package/src/flows/blocks/index.ts +11 -0
- package/src/flows/constants.ts +62 -0
- package/src/flows/contracts/FlowBlock.ts +73 -0
- package/src/flows/contracts/FlowCompiler.ts +32 -0
- package/src/flows/contracts/FlowDefinition.ts +126 -0
- package/src/flows/contracts/FlowDefinitionStore.ts +52 -0
- package/src/flows/contracts/FlowRun.ts +44 -0
- package/src/flows/contracts/FlowValue.ts +54 -0
- package/src/flows/contracts/FlowsService.ts +39 -0
- package/src/flows/contracts/index.ts +7 -0
- package/src/flows/defineBlock.ts +25 -0
- package/src/flows/drivers/FileFlowDefinitionStore.ts +372 -0
- package/src/flows/drivers/index.ts +1 -0
- package/src/flows/errors.ts +22 -0
- package/src/flows/examples/FlowExampleApp.ts +15 -0
- package/src/flows/examples/createTextFlow.ts +14 -0
- package/src/flows/examples/normalizeTextBlock.ts +15 -0
- package/src/flows/examples/runTextFlow.ts +46 -0
- package/src/flows/examples/uppercaseTextBlock.ts +11 -0
- package/src/flows/index.ts +13 -0
- package/src/flows/models/FlowRun.ts +164 -0
- package/src/flows/models/FlowRunEvent.ts +108 -0
- package/src/flows/models/FlowStepRun.ts +176 -0
- package/src/flows/models/index.ts +16 -0
- package/src/index.ts +40 -0
- package/src/logging/Log.ts +100 -0
- package/src/logging/README.md +139 -0
- package/src/logging/contracts/HttpExchange.ts +53 -0
- package/src/logging/contracts/Logger.ts +45 -0
- package/src/logging/contracts/LoggerDriver.ts +19 -0
- package/src/logging/contracts/LoggingOptions.ts +51 -0
- package/src/logging/contracts/index.ts +4 -0
- package/src/logging/drivers/PinoLoggerDriver.ts +376 -0
- package/src/logging/drivers/index.ts +1 -0
- package/src/logging/examples/runNoteLogs.ts +38 -0
- package/src/logging/index.ts +3 -0
- package/src/logging/transports/DevtoolsLogTransport.ts +142 -0
- package/src/mail/Mail.ts +188 -0
- package/src/mail/README.md +206 -0
- package/src/mail/examples/runMailPreview.ts +44 -0
- package/src/mail/examples/welcomeMessage.ts +26 -0
- package/src/mail/index.ts +4 -0
- package/src/mail/transports/FileMailTransport.ts +58 -0
- package/src/mail/transports/MailgunTransport.ts +85 -0
- package/src/mail/transports/ResendTransport.ts +80 -0
- package/src/media/MediaFile.ts +132 -0
- package/src/media/MediaItem.ts +132 -0
- package/src/media/MediaLibrary.ts +117 -0
- package/src/media/MediaManager.ts +874 -0
- package/src/media/README.md +358 -0
- package/src/media/constants.ts +31 -0
- package/src/media/contracts/MediaOptions.ts +9 -0
- package/src/media/contracts/index.ts +1 -0
- package/src/media/examples/createPrivateFileServer.ts +55 -0
- package/src/media/examples/runPrivateFiles.ts +45 -0
- package/src/media/examples/runProjectMedia.ts +46 -0
- package/src/media/image/ImageReconstructionError.ts +18 -0
- package/src/media/image/ImageVariantRenderer.ts +386 -0
- package/src/media/image/ImageVariantRequest.ts +65 -0
- package/src/media/image/contracts/ImageProcessor.ts +53 -0
- package/src/media/image/contracts/ImageVariant.ts +37 -0
- package/src/media/image/contracts/ImageVariantCacheOptions.ts +21 -0
- package/src/media/image/contracts/index.ts +3 -0
- package/src/media/image/index.ts +5 -0
- package/src/media/image/processors/SharpImageProcessor.ts +121 -0
- package/src/media/image/processors/index.ts +1 -0
- package/src/media/index.ts +8 -0
- package/src/media/types.ts +168 -0
- package/src/queue/FailedJob.ts +58 -0
- package/src/queue/Queue.ts +938 -0
- package/src/queue/QueueEvents.ts +57 -0
- package/src/queue/QueueRetryLaterError.ts +40 -0
- package/src/queue/QueueWorker.ts +296 -0
- package/src/queue/QueueableJob.ts +167 -0
- package/src/queue/QueuedJob.ts +69 -0
- package/src/queue/README.md +368 -0
- package/src/queue/RetryPolicy.ts +129 -0
- package/src/queue/commands/index.ts +13 -0
- package/src/queue/commands/makeJob.ts +11 -0
- package/src/queue/console.ts +518 -0
- package/src/queue/contracts/CreateJob.ts +13 -0
- package/src/queue/contracts/QueueDriver.ts +135 -0
- package/src/queue/contracts/QueueEvents.ts +77 -0
- package/src/queue/contracts/QueuePayload.ts +150 -0
- package/src/queue/contracts/QueueRetry.ts +47 -0
- package/src/queue/contracts/QueueService.ts +219 -0
- package/src/queue/contracts/QueueWorkerLifecycle.ts +71 -0
- package/src/queue/contracts/QueueableJob.ts +56 -0
- package/src/queue/contracts/RedisQueueDriver.ts +37 -0
- package/src/queue/contracts/index.ts +9 -0
- package/src/queue/createJob.ts +54 -0
- package/src/queue/drivers/DatabaseQueueDriver.ts +449 -0
- package/src/queue/drivers/RedisQueueDriver.ts +733 -0
- package/src/queue/examples/DeferredReportJob.ts +25 -0
- package/src/queue/examples/GenerateReportJob.ts +37 -0
- package/src/queue/examples/WriteReportJob.ts +37 -0
- package/src/queue/examples/createAndProcessReportJob.ts +29 -0
- package/src/queue/examples/dispatchReportWorkflows.ts +40 -0
- package/src/queue/examples/manageReportRetries.ts +47 -0
- package/src/queue/examples/outputs/create-and-process-report-job.json +6 -0
- package/src/queue/examples/outputs/dispatch-report-workflows.json +14 -0
- package/src/queue/examples/outputs/manage-report-retries.json +24 -0
- package/src/queue/examples/outputs/queue-reports.json +11 -0
- package/src/queue/examples/reportConsole.ts +47 -0
- package/src/queue/examples/runBackpressure.ts +27 -0
- package/src/queue/examples/runQueueReports.ts +80 -0
- package/src/queue/examples/runQueueWorkflows.ts +43 -0
- package/src/queue/index.ts +13 -0
- package/src/queue/queueMonitor.ts +368 -0
- package/src/scheduler/README.md +139 -0
- package/src/scheduler/ScheduledCall.ts +36 -0
- package/src/scheduler/ScheduledEvent.ts +149 -0
- package/src/scheduler/ScheduledJob.ts +58 -0
- package/src/scheduler/ScheduledOccurrence.ts +250 -0
- package/src/scheduler/ScheduledOccurrenceRecorder.ts +125 -0
- package/src/scheduler/Scheduler.ts +225 -0
- package/src/scheduler/SchedulerWorker.ts +151 -0
- package/src/scheduler/console.ts +368 -0
- package/src/scheduler/constants.ts +27 -0
- package/src/scheduler/contracts/Scheduler.ts +123 -0
- package/src/scheduler/contracts/SchedulerConsole.ts +40 -0
- package/src/scheduler/contracts/SchedulerWorker.ts +23 -0
- package/src/scheduler/contracts/index.ts +3 -0
- package/src/scheduler/examples/RecoverableSummaryJob.ts +18 -0
- package/src/scheduler/examples/WriteDailySummaryJob.ts +17 -0
- package/src/scheduler/examples/registerDailySummary.ts +13 -0
- package/src/scheduler/examples/runDailySummary.ts +46 -0
- package/src/scheduler/examples/runScheduledReplay.ts +60 -0
- package/src/scheduler/index.ts +9 -0
- package/src/scheduler/scheduleTime.ts +78 -0
- package/src/security/README.md +130 -0
- package/src/security/Security.ts +346 -0
- package/src/security/SecurityError.ts +16 -0
- package/src/security/contracts/SecurityOptions.ts +20 -0
- package/src/security/contracts/SecurityPayload.ts +14 -0
- package/src/security/contracts/index.ts +2 -0
- package/src/security/ensureAppKey.ts +82 -0
- package/src/security/examples/runSecretRoundTrip.ts +42 -0
- package/src/security/index.ts +4 -0
- package/src/serialization/README.md +169 -0
- package/src/serialization/Serializable.ts +17 -0
- package/src/serialization/SerializationError.ts +91 -0
- package/src/serialization/SerializationRegistry.ts +208 -0
- package/src/serialization/SerializationRegistryError.ts +24 -0
- package/src/serialization/Serializer.ts +793 -0
- package/src/serialization/contracts/SerializableClass.ts +26 -0
- package/src/serialization/contracts/SerializedValue.ts +71 -0
- package/src/serialization/contracts/SerializerOptions.ts +19 -0
- package/src/serialization/contracts/SerializerService.ts +29 -0
- package/src/serialization/contracts/index.ts +4 -0
- package/src/serialization/examples/ExportRequest.ts +25 -0
- package/src/serialization/examples/runExportSerialization.ts +24 -0
- package/src/serialization/index.ts +6 -0
- package/src/server/App.ts +326 -0
- package/src/server/README.md +219 -0
- package/src/server/RequestContext.ts +122 -0
- package/src/server/appContext.ts +59 -0
- package/src/server/examples/createFirstServer.ts +25 -0
- package/src/server/examples/startFirstServer.ts +19 -0
- package/src/server/index.ts +16 -0
- package/src/ssr/README.md +158 -0
- package/src/ssr/constants.ts +8 -0
- package/src/ssr/contracts/DocumentHead.ts +35 -0
- package/src/ssr/contracts/SsrRenderContext.ts +25 -0
- package/src/ssr/contracts/SsrRenderResult.ts +23 -0
- package/src/ssr/contracts/SsrRenderer.ts +12 -0
- package/src/ssr/contracts/SsrRequest.ts +17 -0
- package/src/ssr/contracts/index.ts +19 -0
- package/src/ssr/createSsrRenderContext.ts +25 -0
- package/src/ssr/examples/createPublicPageServer.ts +32 -0
- package/src/ssr/examples/runPublicPages.ts +25 -0
- package/src/ssr/fastify/contracts/FastifySsrOptions.ts +24 -0
- package/src/ssr/fastify/contracts/index.ts +5 -0
- package/src/ssr/fastify/fastifySsr.ts +110 -0
- package/src/ssr/fastify/index.ts +2 -0
- package/src/ssr/index.ts +10 -0
- package/src/ssr/renderDocumentHead.ts +72 -0
- package/src/ssr/renderSsrDocument.ts +35 -0
- package/src/ssr/serializeSsrState.ts +19 -0
- package/src/ssr/vite/contracts/ViteSsrOptions.ts +52 -0
- package/src/ssr/vite/contracts/index.ts +6 -0
- package/src/ssr/vite/fastifyViteSsr.ts +279 -0
- package/src/ssr/vite/index.ts +4 -0
- package/src/ssr/vite/viteSsrManifest.ts +92 -0
- package/src/storage/README.md +310 -0
- package/src/storage/Storage.ts +392 -0
- package/src/storage/contents.ts +23 -0
- package/src/storage/contracts/StorageListing.ts +55 -0
- package/src/storage/contracts/index.ts +1 -0
- package/src/storage/drivers/FlystorageDisk.ts +295 -0
- package/src/storage/drivers/FlystorageListing.ts +78 -0
- package/src/storage/drivers/LocalStorageDisk.ts +45 -0
- package/src/storage/drivers/S3StorageDisk.ts +114 -0
- package/src/storage/drivers/index.ts +3 -0
- package/src/storage/examples/runStorage.ts +37 -0
- package/src/storage/examples/runStreamExport.ts +41 -0
- package/src/storage/examples/writeCsvExport.ts +45 -0
- package/src/storage/index.ts +7 -0
- package/src/storage/mime.ts +30 -0
- package/src/storage/path.ts +76 -0
- package/src/storage/types.ts +251 -0
- package/src/url/README.md +41 -0
- package/src/url/UrlGenerator.ts +72 -0
- package/src/url/contracts/UrlGeneratorOptions.ts +14 -0
- package/src/url/contracts/index.ts +1 -0
- package/src/url/examples/runApplicationLinks.ts +33 -0
- package/src/url/index.ts +2 -0
- package/src/validation/README.md +433 -0
- package/src/validation/examples/runNoteValidation.ts +18 -0
- package/src/validation/examples/validateNoteInput.ts +31 -0
- package/src/validation/index.ts +398 -0
- package/templates/AGENTS.md +15 -0
|
@@ -0,0 +1,1283 @@
|
|
|
1
|
+
import type { Knex } from 'knex';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { normalizeDatabaseComment } from '@db3.ai/pure';
|
|
4
|
+
|
|
5
|
+
import type {
|
|
6
|
+
ActiveRecord,
|
|
7
|
+
ActiveRecordClass,
|
|
8
|
+
} from './ActiveRecord';
|
|
9
|
+
import { ActiveRecord as ActiveRecordBase } from './ActiveRecord';
|
|
10
|
+
import type * as database from './contracts';
|
|
11
|
+
import { DatabaseMigrationManager } from './migrations/DatabaseMigrationManager';
|
|
12
|
+
import {
|
|
13
|
+
databaseDialectForConnection,
|
|
14
|
+
type DatabaseDialect,
|
|
15
|
+
type TableIndexSpec,
|
|
16
|
+
} from './dialects';
|
|
17
|
+
import type {
|
|
18
|
+
DbColumnSpec,
|
|
19
|
+
DbForeignKeySpec,
|
|
20
|
+
DbIndexColumnSpec,
|
|
21
|
+
DbIndexSpec,
|
|
22
|
+
DbSchemaPart,
|
|
23
|
+
} from './FieldType';
|
|
24
|
+
import { writeDbColumn } from './FieldType';
|
|
25
|
+
import {
|
|
26
|
+
enableDefaultQueryMonitor,
|
|
27
|
+
type QueryMonitor,
|
|
28
|
+
type QueryMonitorOptions,
|
|
29
|
+
} from './queryMonitor';
|
|
30
|
+
|
|
31
|
+
/** App-owned model registry and policies for migrations, query monitoring and schema synchronization. */
|
|
32
|
+
export interface DatabaseOptions {
|
|
33
|
+
/** Model registry and policy for migrations under the app's server/database directory. */
|
|
34
|
+
migrations?: database.DatabaseMigrationsConfig;
|
|
35
|
+
/**
|
|
36
|
+
* Configures query telemetry for this database connection.
|
|
37
|
+
*/
|
|
38
|
+
queryMonitor?: false | QueryMonitorOptions;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Whether `install()` should add missing model columns and relax existing
|
|
42
|
+
* columns that are now nullable or safely wider.
|
|
43
|
+
*/
|
|
44
|
+
syncColumns?: boolean;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Whether `install()` should add missing model indexes to existing tables.
|
|
48
|
+
*/
|
|
49
|
+
syncIndexes?: boolean;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Reports schema differences left after `install()` runs safe sync steps.
|
|
53
|
+
* Defaults to `warn`; set false to silence or pass a custom reporter.
|
|
54
|
+
*/
|
|
55
|
+
reportSchemaDiff?: DatabaseSchemaDiffReporter;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface DatabaseInstallOptions {
|
|
59
|
+
/**
|
|
60
|
+
* Per-install override for adding missing model columns to existing tables.
|
|
61
|
+
*/
|
|
62
|
+
syncColumns?: boolean;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Per-install override for adding missing model indexes to existing tables.
|
|
66
|
+
*/
|
|
67
|
+
syncIndexes?: boolean;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Per-install override for reporting remaining schema differences.
|
|
71
|
+
*/
|
|
72
|
+
reportSchemaDiff?: DatabaseSchemaDiffReporter;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export type DatabaseSchemaDifferenceKind =
|
|
76
|
+
| 'missing_table'
|
|
77
|
+
| 'missing_column'
|
|
78
|
+
| 'missing_index'
|
|
79
|
+
| 'type_mismatch'
|
|
80
|
+
| 'nullable_mismatch';
|
|
81
|
+
|
|
82
|
+
export type DatabaseSchemaDiffReporter =
|
|
83
|
+
| false
|
|
84
|
+
| 'warn'
|
|
85
|
+
| ((
|
|
86
|
+
diffs: DatabaseSchemaDiff[],
|
|
87
|
+
database: Database,
|
|
88
|
+
) => void | Promise<void>);
|
|
89
|
+
|
|
90
|
+
export interface DatabaseSchemaDifference {
|
|
91
|
+
kind: DatabaseSchemaDifferenceKind;
|
|
92
|
+
table: string;
|
|
93
|
+
column?: string;
|
|
94
|
+
index?: string;
|
|
95
|
+
columns?: string[];
|
|
96
|
+
databaseValue?: unknown;
|
|
97
|
+
modelValue?: unknown;
|
|
98
|
+
rowsWithNull?: number;
|
|
99
|
+
blocked?: boolean;
|
|
100
|
+
message: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface DatabaseSchemaDiff {
|
|
104
|
+
model: string;
|
|
105
|
+
table: string;
|
|
106
|
+
differences: DatabaseSchemaDifference[];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
type InstallArgs =
|
|
110
|
+
| ActiveRecordClass[]
|
|
111
|
+
| [DatabaseInstallOptions, ...ActiveRecordClass[]];
|
|
112
|
+
|
|
113
|
+
interface InstallColumnOptions {
|
|
114
|
+
alter?: boolean;
|
|
115
|
+
alterNullable?: boolean;
|
|
116
|
+
alterType?: boolean;
|
|
117
|
+
applyDefault?: boolean;
|
|
118
|
+
applyComment?: boolean;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
interface NormalizedIndexColumn {
|
|
122
|
+
name: string;
|
|
123
|
+
order?: 'asc' | 'desc';
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
interface MissingIndex {
|
|
127
|
+
index: DbIndexSpec;
|
|
128
|
+
blocked: boolean;
|
|
129
|
+
message: string;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
interface InstalledTableSchema {
|
|
133
|
+
columnInfo: Record<string, unknown>;
|
|
134
|
+
indexes: TableIndexSpec[];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* App-facing database service.
|
|
139
|
+
*
|
|
140
|
+
* This gathers database operations that do not really belong on an individual
|
|
141
|
+
* record instance, while keeping the existing ActiveRecord model definitions.
|
|
142
|
+
*/
|
|
143
|
+
export class Database {
|
|
144
|
+
private readonly monitor: QueryMonitor | null;
|
|
145
|
+
#backupHandler?: database.DatabaseBackupHandler;
|
|
146
|
+
#migrations?: DatabaseMigrationManager;
|
|
147
|
+
readonly #directory: string;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Returns migrations from the application's conventional server/database paths.
|
|
151
|
+
* @returns Lazy migration manager shared by commands, tests and application operations.
|
|
152
|
+
* @throws When the app has not supplied dbOptions.migrations.
|
|
153
|
+
*/
|
|
154
|
+
get migrations(): DatabaseMigrationManager {
|
|
155
|
+
if (!this.options.migrations) throw new Error('Configure dbOptions.migrations with { models } for the app model registry.');
|
|
156
|
+
return this.#migrations ??= new DatabaseMigrationManager({
|
|
157
|
+
...this.options.migrations,
|
|
158
|
+
db: this.connection,
|
|
159
|
+
dialect: this.dialect(),
|
|
160
|
+
migrationsDirectory: resolve(this.#directory, 'server/database/migrations'),
|
|
161
|
+
snapshotFile: resolve(this.#directory, 'server/database/schema.snapshot.json'),
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Creates a database service and captures its application directory once.
|
|
167
|
+
* @param connection - Connection owned by the application or its caller.
|
|
168
|
+
* @param options - Model registry, migration policy and schema/query settings.
|
|
169
|
+
* @param directory - App root supplied by App; standalone services default to the current directory.
|
|
170
|
+
*/
|
|
171
|
+
constructor(
|
|
172
|
+
private readonly connection: Knex,
|
|
173
|
+
private readonly options: DatabaseOptions = {},
|
|
174
|
+
directory: string = process.cwd(),
|
|
175
|
+
) {
|
|
176
|
+
this.#directory = resolve(directory);
|
|
177
|
+
this.monitor = enableDefaultQueryMonitor(
|
|
178
|
+
this.connection,
|
|
179
|
+
this.options.queryMonitor,
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Collects database schema metadata from every field on a model.
|
|
185
|
+
*/
|
|
186
|
+
static getSchema<TRecord extends ActiveRecord>(
|
|
187
|
+
Model: ActiveRecordClass<TRecord>,
|
|
188
|
+
dialect?: DatabaseDialect,
|
|
189
|
+
): Required<DbSchemaPart> {
|
|
190
|
+
const columns = new Map<string, DbColumnSpec>();
|
|
191
|
+
const indexes: DbIndexSpec[] = [];
|
|
192
|
+
const foreignKeys: DbForeignKeySpec[] = [];
|
|
193
|
+
|
|
194
|
+
for (const [fieldName, field] of Object.entries(Model.getFields())) {
|
|
195
|
+
const schema = field.getDbSchema({
|
|
196
|
+
model: Model,
|
|
197
|
+
fieldName,
|
|
198
|
+
dialect,
|
|
199
|
+
});
|
|
200
|
+
const fieldComment = normalizeDatabaseComment(field.config.comment);
|
|
201
|
+
|
|
202
|
+
for (const column of schema.columns ?? []) {
|
|
203
|
+
const columnWithComment = fieldComment && !column.comment
|
|
204
|
+
? {
|
|
205
|
+
...column,
|
|
206
|
+
comment: fieldComment,
|
|
207
|
+
}
|
|
208
|
+
: column;
|
|
209
|
+
|
|
210
|
+
if (columns.has(columnWithComment.name)) {
|
|
211
|
+
throw new Error(
|
|
212
|
+
`Duplicate column "${columnWithComment.name}" on model ${Model.name}`,
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
columns.set(columnWithComment.name, columnWithComment);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
indexes.push(...(schema.indexes ?? []));
|
|
220
|
+
foreignKeys.push(...(schema.foreignKeys ?? []));
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return {
|
|
224
|
+
columns: [...columns.values()],
|
|
225
|
+
indexes,
|
|
226
|
+
foreignKeys,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Returns the raw Knex connection for low-level database work.
|
|
232
|
+
*/
|
|
233
|
+
get knex(): Knex {
|
|
234
|
+
return this.connection;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Returns the query monitor attached to this connection, when enabled.
|
|
239
|
+
*/
|
|
240
|
+
get queryMonitor(): QueryMonitor | null {
|
|
241
|
+
return this.monitor;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Configures the application-owned implementation used by `backup()`.
|
|
246
|
+
*
|
|
247
|
+
* @param handler - Function that creates and persists one database backup.
|
|
248
|
+
* @returns This database service for fluent application wiring.
|
|
249
|
+
*/
|
|
250
|
+
setBackupHandler(handler: database.DatabaseBackupHandler): this {
|
|
251
|
+
this.#backupHandler = handler;
|
|
252
|
+
|
|
253
|
+
return this;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Creates a database backup through the active application's backup policy.
|
|
258
|
+
*
|
|
259
|
+
* @param request - Durable, JSON-safe metadata identifying the backup request.
|
|
260
|
+
* @returns Application-defined backup result, such as a completed manifest.
|
|
261
|
+
*
|
|
262
|
+
* @example
|
|
263
|
+
* const manifest = await app().db.backup<DatabaseBackupManifest>({
|
|
264
|
+
* backupId,
|
|
265
|
+
* createdAt,
|
|
266
|
+
* trigger: 'manual',
|
|
267
|
+
* });
|
|
268
|
+
*/
|
|
269
|
+
async backup<TResult = unknown>(request: Record<string, unknown>): Promise<TResult> {
|
|
270
|
+
if (!this.#backupHandler) {
|
|
271
|
+
throw new Error('Database backup has not been configured for this application.');
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return await this.#backupHandler(request) as TResult;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Starts a raw Knex query against a table.
|
|
279
|
+
*/
|
|
280
|
+
table<TRecord extends {} = any, TResult = TRecord[]>(
|
|
281
|
+
tableName: string,
|
|
282
|
+
): Knex.QueryBuilder<TRecord, TResult> {
|
|
283
|
+
return this.connection<TRecord, TResult>(tableName);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Creates database tables for one or more ActiveRecord models.
|
|
288
|
+
*/
|
|
289
|
+
async install(...models: ActiveRecordClass[]): Promise<void>;
|
|
290
|
+
async install(
|
|
291
|
+
options: DatabaseInstallOptions,
|
|
292
|
+
...models: ActiveRecordClass[]
|
|
293
|
+
): Promise<void>;
|
|
294
|
+
async install(...input: InstallArgs): Promise<void> {
|
|
295
|
+
const {
|
|
296
|
+
models,
|
|
297
|
+
options,
|
|
298
|
+
} = resolveInstallArgs(input);
|
|
299
|
+
const tableComments = await this.tableCommentsFor(models);
|
|
300
|
+
const modelsWithPotentialDiffs: ActiveRecordClass[] = [];
|
|
301
|
+
|
|
302
|
+
for (const Model of models) {
|
|
303
|
+
const hasPotentialDiff = await this.installModel(
|
|
304
|
+
Model,
|
|
305
|
+
options,
|
|
306
|
+
tableComments.get(Model.table),
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
if (hasPotentialDiff) {
|
|
310
|
+
modelsWithPotentialDiffs.push(Model);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
await this.reportDiffAfterInstall(modelsWithPotentialDiffs, options);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Compares model schema metadata with the live database without changing it.
|
|
319
|
+
*
|
|
320
|
+
* This intentionally reports a small, high-signal subset instead of trying to
|
|
321
|
+
* be a migration planner.
|
|
322
|
+
*/
|
|
323
|
+
async diff(...models: ActiveRecordClass[]): Promise<DatabaseSchemaDiff[]> {
|
|
324
|
+
const diffs: DatabaseSchemaDiff[] = [];
|
|
325
|
+
|
|
326
|
+
for (const Model of models) {
|
|
327
|
+
const schema = this.getSchema(Model);
|
|
328
|
+
const differences: DatabaseSchemaDifference[] = [];
|
|
329
|
+
const tableExists = await this.connection.schema.hasTable(Model.table);
|
|
330
|
+
|
|
331
|
+
if (!tableExists) {
|
|
332
|
+
differences.push({
|
|
333
|
+
kind: 'missing_table',
|
|
334
|
+
table: Model.table,
|
|
335
|
+
modelValue: Model.table,
|
|
336
|
+
message: `Table ${Model.table} is missing.`,
|
|
337
|
+
});
|
|
338
|
+
} else {
|
|
339
|
+
const columnInfo = await this.connection(Model.table).columnInfo();
|
|
340
|
+
const existingColumnNames = new Set(Object.keys(columnInfo));
|
|
341
|
+
const tableIndexes = await this.getTableIndexes(Model.table);
|
|
342
|
+
|
|
343
|
+
for (const column of schema.columns) {
|
|
344
|
+
const info = columnInfo[column.name];
|
|
345
|
+
|
|
346
|
+
if (!info) {
|
|
347
|
+
differences.push({
|
|
348
|
+
kind: 'missing_column',
|
|
349
|
+
table: Model.table,
|
|
350
|
+
column: column.name,
|
|
351
|
+
modelValue: describeColumn(column),
|
|
352
|
+
message: `Column ${Model.table}.${column.name} is missing; model expects ${describeColumn(column)}.`,
|
|
353
|
+
});
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const databaseNullable = columnAllowsNull(info);
|
|
358
|
+
const modelNullable = modelColumnAllowsNull(column);
|
|
359
|
+
|
|
360
|
+
if (
|
|
361
|
+
databaseNullable !== null
|
|
362
|
+
&& databaseNullable !== modelNullable
|
|
363
|
+
) {
|
|
364
|
+
const rowsWithNull = databaseNullable && !modelNullable
|
|
365
|
+
? await this.countRowsWithNull(Model.table, column.name)
|
|
366
|
+
: undefined;
|
|
367
|
+
|
|
368
|
+
differences.push({
|
|
369
|
+
kind: 'nullable_mismatch',
|
|
370
|
+
table: Model.table,
|
|
371
|
+
column: column.name,
|
|
372
|
+
databaseValue: databaseNullable,
|
|
373
|
+
modelValue: modelNullable,
|
|
374
|
+
rowsWithNull,
|
|
375
|
+
blocked: Boolean(rowsWithNull),
|
|
376
|
+
message: nullableMismatchMessage(
|
|
377
|
+
Model.table,
|
|
378
|
+
column.name,
|
|
379
|
+
databaseNullable,
|
|
380
|
+
modelNullable,
|
|
381
|
+
rowsWithNull,
|
|
382
|
+
),
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const typeDifference = columnTypeDifference(
|
|
387
|
+
Model.table,
|
|
388
|
+
column,
|
|
389
|
+
info,
|
|
390
|
+
tableIndexes,
|
|
391
|
+
);
|
|
392
|
+
|
|
393
|
+
if (typeDifference) {
|
|
394
|
+
differences.push(typeDifference);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
const missingIndexes = findMissingIndexes(
|
|
399
|
+
schema.indexes,
|
|
400
|
+
tableIndexes,
|
|
401
|
+
existingColumnNames,
|
|
402
|
+
);
|
|
403
|
+
|
|
404
|
+
for (const missingIndex of missingIndexes) {
|
|
405
|
+
differences.push({
|
|
406
|
+
kind: 'missing_index',
|
|
407
|
+
table: Model.table,
|
|
408
|
+
index: missingIndex.index.name,
|
|
409
|
+
columns: missingIndex.index.columns.map(indexColumnName),
|
|
410
|
+
modelValue: describeIndex(missingIndex.index),
|
|
411
|
+
blocked: missingIndex.blocked,
|
|
412
|
+
message: missingIndex.message,
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (differences.length > 0) {
|
|
418
|
+
diffs.push({
|
|
419
|
+
model: Model.name,
|
|
420
|
+
table: Model.table,
|
|
421
|
+
differences,
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
return diffs;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Renders schema diffs for logs or CLI output.
|
|
431
|
+
*/
|
|
432
|
+
formatDiff(diffs: DatabaseSchemaDiff[]): string {
|
|
433
|
+
if (diffs.length === 0) {
|
|
434
|
+
return 'Database schema matches model schema.';
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
return diffs
|
|
438
|
+
.flatMap(diff => {
|
|
439
|
+
return [
|
|
440
|
+
`${diff.table} (${diff.model})`,
|
|
441
|
+
...diff.differences.map(difference => {
|
|
442
|
+
return ` - ${difference.message}`;
|
|
443
|
+
}),
|
|
444
|
+
];
|
|
445
|
+
})
|
|
446
|
+
.join('\n');
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Collects database schema metadata from every field on a model.
|
|
451
|
+
*/
|
|
452
|
+
getSchema<TRecord extends ActiveRecord>(
|
|
453
|
+
Model: ActiveRecordClass<TRecord>,
|
|
454
|
+
): Required<DbSchemaPart> {
|
|
455
|
+
return Database.getSchema(Model, this.dialect());
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Runs work inside a transaction and exposes the transaction as a Database.
|
|
460
|
+
*/
|
|
461
|
+
async transaction<TResult>(
|
|
462
|
+
callback: (db: Database) => Promise<TResult>,
|
|
463
|
+
): Promise<TResult> {
|
|
464
|
+
return this.connection.transaction(async transaction => {
|
|
465
|
+
const transactionConnection = transaction as unknown as Knex;
|
|
466
|
+
|
|
467
|
+
return ActiveRecordBase.withDb(transactionConnection, () => {
|
|
468
|
+
return callback(new Database(transactionConnection, this.options, this.#directory));
|
|
469
|
+
});
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Installs or safely synchronizes one ActiveRecord model.
|
|
475
|
+
*
|
|
476
|
+
* Existing column and index metadata is loaded once and shared by every
|
|
477
|
+
* synchronization step. The return value records whether the initial schema
|
|
478
|
+
* may have contained a reportable difference that should be checked after
|
|
479
|
+
* synchronization.
|
|
480
|
+
*
|
|
481
|
+
* @param Model - ActiveRecord model whose schema should be installed.
|
|
482
|
+
* @param options - Per-install synchronization options.
|
|
483
|
+
* @param currentTableComment - Existing database comment for this table.
|
|
484
|
+
* @returns Whether a post-install diff may still be useful.
|
|
485
|
+
*/
|
|
486
|
+
private async installModel<TRecord extends ActiveRecord>(
|
|
487
|
+
Model: ActiveRecordClass<TRecord>,
|
|
488
|
+
options: DatabaseInstallOptions,
|
|
489
|
+
currentTableComment: string | null | undefined,
|
|
490
|
+
): Promise<boolean> {
|
|
491
|
+
const exists = await this.connection.schema.hasTable(Model.table);
|
|
492
|
+
const schema = this.getSchema(Model);
|
|
493
|
+
const tableComment = normalizeDatabaseComment(Model.comment);
|
|
494
|
+
|
|
495
|
+
if (exists) {
|
|
496
|
+
const installedSchema = await this.installedTableSchema(Model.table);
|
|
497
|
+
const hasPotentialDiff = this.tableHasPotentialDiff(
|
|
498
|
+
Model.table,
|
|
499
|
+
schema,
|
|
500
|
+
installedSchema,
|
|
501
|
+
);
|
|
502
|
+
|
|
503
|
+
await this.syncTableComment(
|
|
504
|
+
Model.table,
|
|
505
|
+
tableComment,
|
|
506
|
+
currentTableComment,
|
|
507
|
+
);
|
|
508
|
+
|
|
509
|
+
let addedColumnNames = new Set<string>();
|
|
510
|
+
|
|
511
|
+
if (this.shouldSyncColumns(options)) {
|
|
512
|
+
addedColumnNames = await this.syncMissingColumns(
|
|
513
|
+
Model.table,
|
|
514
|
+
schema,
|
|
515
|
+
installedSchema.columnInfo,
|
|
516
|
+
);
|
|
517
|
+
await this.syncWidenedTextColumns(
|
|
518
|
+
Model.table,
|
|
519
|
+
schema,
|
|
520
|
+
installedSchema,
|
|
521
|
+
);
|
|
522
|
+
await this.syncNullableColumns(
|
|
523
|
+
Model.table,
|
|
524
|
+
schema,
|
|
525
|
+
installedSchema.columnInfo,
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
if (this.shouldSyncIndexes(options)) {
|
|
530
|
+
await this.syncMissingIndexes(
|
|
531
|
+
Model.table,
|
|
532
|
+
schema,
|
|
533
|
+
installedSchema,
|
|
534
|
+
addedColumnNames,
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
return hasPotentialDiff;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
await this.connection.schema.createTable(Model.table, table => {
|
|
542
|
+
if (tableComment && this.dialect().supportsTableComments) {
|
|
543
|
+
table.comment(tableComment);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
const dialect = this.dialect();
|
|
547
|
+
const indexes: DbIndexSpec[] = [];
|
|
548
|
+
const foreignKeys: DbForeignKeySpec[] = [];
|
|
549
|
+
|
|
550
|
+
for (const [fieldName, field] of Object.entries(Model.getFields())) {
|
|
551
|
+
const part = field.getDbSchema({
|
|
552
|
+
model: Model,
|
|
553
|
+
fieldName,
|
|
554
|
+
dialect,
|
|
555
|
+
table,
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
indexes.push(...(part.indexes ?? []));
|
|
559
|
+
foreignKeys.push(...(part.foreignKeys ?? []));
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
for (const index of indexes) {
|
|
563
|
+
installIndex(table, index, dialect);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
for (const foreignKey of foreignKeys) {
|
|
567
|
+
installForeignKey(table, foreignKey);
|
|
568
|
+
}
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
return true;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Synchronizes a model-owned table comment only when its value changed.
|
|
576
|
+
*
|
|
577
|
+
* @param tableName - Existing database table name.
|
|
578
|
+
* @param comment - Normalized comment declared by the model.
|
|
579
|
+
* @param currentComment - Comment currently stored by the database.
|
|
580
|
+
* @returns Promise that resolves when any required comment change completes.
|
|
581
|
+
*/
|
|
582
|
+
private async syncTableComment(
|
|
583
|
+
tableName: string,
|
|
584
|
+
comment: string | null,
|
|
585
|
+
currentComment: string | null | undefined,
|
|
586
|
+
): Promise<void> {
|
|
587
|
+
if (!comment) return;
|
|
588
|
+
if (!this.dialect().supportsTableComments) return;
|
|
589
|
+
if (comment === normalizeDatabaseComment(currentComment)) return;
|
|
590
|
+
|
|
591
|
+
await this.connection.schema.alterTable(tableName, table => {
|
|
592
|
+
table.comment(comment);
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Resolves whether model columns should be synchronized for this install.
|
|
598
|
+
*
|
|
599
|
+
* @param options - Per-install overrides.
|
|
600
|
+
* @returns Whether safe column synchronization is enabled.
|
|
601
|
+
*/
|
|
602
|
+
private shouldSyncColumns(options: DatabaseInstallOptions): boolean {
|
|
603
|
+
return options.syncColumns ?? this.options.syncColumns ?? true;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Resolves whether model indexes should be synchronized for this install.
|
|
608
|
+
*
|
|
609
|
+
* @param options - Per-install overrides.
|
|
610
|
+
* @returns Whether missing-index synchronization is enabled.
|
|
611
|
+
*/
|
|
612
|
+
private shouldSyncIndexes(options: DatabaseInstallOptions): boolean {
|
|
613
|
+
return options.syncIndexes ?? this.options.syncIndexes ?? true;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Adds model columns missing from an existing table.
|
|
618
|
+
*
|
|
619
|
+
* @param tableName - Existing database table name.
|
|
620
|
+
* @param schema - Current model schema.
|
|
621
|
+
* @param columnInfo - Column metadata captured before synchronization.
|
|
622
|
+
* @returns Names of columns added during this synchronization pass.
|
|
623
|
+
*/
|
|
624
|
+
private async syncMissingColumns(
|
|
625
|
+
tableName: string,
|
|
626
|
+
schema: Required<DbSchemaPart>,
|
|
627
|
+
columnInfo: Record<string, unknown>,
|
|
628
|
+
): Promise<Set<string>> {
|
|
629
|
+
const existingColumnNames = new Set(Object.keys(columnInfo));
|
|
630
|
+
const missingColumns = schema.columns.filter(column => {
|
|
631
|
+
return !existingColumnNames.has(column.name);
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
if (missingColumns.length === 0) {
|
|
635
|
+
return new Set();
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
const missingColumnNames = new Set(
|
|
639
|
+
missingColumns.map(column => column.name),
|
|
640
|
+
);
|
|
641
|
+
const nextColumnNames = new Set([
|
|
642
|
+
...existingColumnNames,
|
|
643
|
+
...missingColumnNames,
|
|
644
|
+
]);
|
|
645
|
+
|
|
646
|
+
const newColumnIndexes = schema.indexes.filter(index => {
|
|
647
|
+
return index.columns.some(column => {
|
|
648
|
+
return missingColumnNames.has(indexColumnName(column));
|
|
649
|
+
})
|
|
650
|
+
&& index.columns.every(column => {
|
|
651
|
+
return nextColumnNames.has(indexColumnName(column));
|
|
652
|
+
});
|
|
653
|
+
});
|
|
654
|
+
const newColumnForeignKeys = schema.foreignKeys.filter(foreignKey => {
|
|
655
|
+
return missingColumnNames.has(foreignKey.column);
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
await this.connection.schema.alterTable(tableName, table => {
|
|
659
|
+
for (const column of missingColumns) {
|
|
660
|
+
installColumn(table, column);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
for (const index of newColumnIndexes) {
|
|
664
|
+
installIndex(table, index, this.dialect());
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
for (const foreignKey of newColumnForeignKeys) {
|
|
668
|
+
installForeignKey(table, foreignKey);
|
|
669
|
+
}
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
return missingColumnNames;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/**
|
|
676
|
+
* Relaxes existing columns that are optional in the current model.
|
|
677
|
+
*
|
|
678
|
+
* @param tableName - Existing database table name.
|
|
679
|
+
* @param schema - Current model schema.
|
|
680
|
+
* @param columnInfo - Column metadata captured before synchronization.
|
|
681
|
+
* @returns Promise that resolves when nullable columns are synchronized.
|
|
682
|
+
*/
|
|
683
|
+
private async syncNullableColumns(
|
|
684
|
+
tableName: string,
|
|
685
|
+
schema: Required<DbSchemaPart>,
|
|
686
|
+
columnInfo: Record<string, unknown>,
|
|
687
|
+
): Promise<void> {
|
|
688
|
+
const columnsToRelax = schema.columns.filter(column => {
|
|
689
|
+
if (column.primary || column.nullable === false) return false;
|
|
690
|
+
|
|
691
|
+
return columnAllowsNull(columnInfo[column.name]) === false;
|
|
692
|
+
});
|
|
693
|
+
|
|
694
|
+
if (columnsToRelax.length === 0) return;
|
|
695
|
+
|
|
696
|
+
await this.connection.schema.alterTable(tableName, table => {
|
|
697
|
+
for (const column of columnsToRelax) {
|
|
698
|
+
installColumn(table, column, {
|
|
699
|
+
alter: true,
|
|
700
|
+
alterNullable: true,
|
|
701
|
+
applyDefault: false,
|
|
702
|
+
applyComment: false,
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* Widens existing non-indexed string columns required by text model fields.
|
|
710
|
+
*
|
|
711
|
+
* @param tableName - Existing database table name.
|
|
712
|
+
* @param schema - Current model schema.
|
|
713
|
+
* @param installedSchema - Column and index metadata captured before sync.
|
|
714
|
+
* @returns Promise that resolves when safe text widening completes.
|
|
715
|
+
*/
|
|
716
|
+
private async syncWidenedTextColumns(
|
|
717
|
+
tableName: string,
|
|
718
|
+
schema: Required<DbSchemaPart>,
|
|
719
|
+
installedSchema: InstalledTableSchema,
|
|
720
|
+
): Promise<void> {
|
|
721
|
+
const columnsToWiden = schema.columns.filter(column => {
|
|
722
|
+
return columnNeedsTextWidening(
|
|
723
|
+
column,
|
|
724
|
+
installedSchema.columnInfo[column.name],
|
|
725
|
+
)
|
|
726
|
+
&& !isColumnIndexed(column.name, installedSchema.indexes);
|
|
727
|
+
});
|
|
728
|
+
|
|
729
|
+
if (columnsToWiden.length === 0) return;
|
|
730
|
+
|
|
731
|
+
await this.connection.schema.alterTable(tableName, table => {
|
|
732
|
+
for (const column of columnsToWiden) {
|
|
733
|
+
installColumn(table, column, {
|
|
734
|
+
alter: true,
|
|
735
|
+
alterType: true,
|
|
736
|
+
applyDefault: false,
|
|
737
|
+
applyComment: false,
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
/**
|
|
744
|
+
* Adds model indexes missing from an existing table.
|
|
745
|
+
*
|
|
746
|
+
* Indexes involving columns added in this pass are skipped here because
|
|
747
|
+
* `syncMissingColumns()` creates them alongside those columns.
|
|
748
|
+
* Each remaining index is installed separately so a concurrent application
|
|
749
|
+
* process can win the same synchronization race without preventing later
|
|
750
|
+
* indexes from being considered. A failed addition is accepted only when a
|
|
751
|
+
* fresh schema read confirms that the required index now exists.
|
|
752
|
+
*
|
|
753
|
+
* @param tableName - Existing database table name.
|
|
754
|
+
* @param schema - Current model schema.
|
|
755
|
+
* @param installedSchema - Column and index metadata captured before sync.
|
|
756
|
+
* @param addedColumnNames - Columns created earlier in this install pass.
|
|
757
|
+
* @returns Promise that resolves when missing indexes are synchronized.
|
|
758
|
+
*/
|
|
759
|
+
private async syncMissingIndexes(
|
|
760
|
+
tableName: string,
|
|
761
|
+
schema: Required<DbSchemaPart>,
|
|
762
|
+
installedSchema: InstalledTableSchema,
|
|
763
|
+
addedColumnNames: Set<string>,
|
|
764
|
+
): Promise<void> {
|
|
765
|
+
const existingColumnNames = new Set([
|
|
766
|
+
...Object.keys(installedSchema.columnInfo),
|
|
767
|
+
...addedColumnNames,
|
|
768
|
+
]);
|
|
769
|
+
const missingIndexes = findMissingIndexes(
|
|
770
|
+
schema.indexes,
|
|
771
|
+
installedSchema.indexes,
|
|
772
|
+
existingColumnNames,
|
|
773
|
+
).filter(missingIndex => {
|
|
774
|
+
return !missingIndex.blocked
|
|
775
|
+
&& !missingIndex.index.columns.some(column => {
|
|
776
|
+
return addedColumnNames.has(indexColumnName(column));
|
|
777
|
+
});
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
if (missingIndexes.length === 0) return;
|
|
781
|
+
|
|
782
|
+
for (const missingIndex of missingIndexes) {
|
|
783
|
+
try {
|
|
784
|
+
await this.connection.schema.alterTable(tableName, table => {
|
|
785
|
+
installIndex(table, missingIndex.index, this.dialect());
|
|
786
|
+
});
|
|
787
|
+
} catch (error) {
|
|
788
|
+
const currentIndexes = await this.getTableIndexes(tableName);
|
|
789
|
+
const installedConcurrently = currentIndexes.some(index => {
|
|
790
|
+
return indexMatches(missingIndex.index, index);
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
if (!installedConcurrently) throw error;
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
private async countRowsWithNull(
|
|
799
|
+
tableName: string,
|
|
800
|
+
columnName: string,
|
|
801
|
+
): Promise<number> {
|
|
802
|
+
const result = await this.connection(tableName)
|
|
803
|
+
.whereNull(columnName)
|
|
804
|
+
.count<{ total: number | string }[]>({
|
|
805
|
+
total: '*',
|
|
806
|
+
});
|
|
807
|
+
|
|
808
|
+
return Number(result[0]?.total ?? 0);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* Loads reusable column and index metadata for one existing table.
|
|
813
|
+
*
|
|
814
|
+
* @param tableName - Existing database table name.
|
|
815
|
+
* @returns Column and index metadata used by every synchronization step.
|
|
816
|
+
*/
|
|
817
|
+
private async installedTableSchema(tableName: string): Promise<InstalledTableSchema> {
|
|
818
|
+
const [
|
|
819
|
+
columnInfo,
|
|
820
|
+
indexes,
|
|
821
|
+
] = await Promise.all([
|
|
822
|
+
this.connection(tableName).columnInfo(),
|
|
823
|
+
this.getTableIndexes(tableName),
|
|
824
|
+
]);
|
|
825
|
+
|
|
826
|
+
return {
|
|
827
|
+
columnInfo,
|
|
828
|
+
indexes,
|
|
829
|
+
};
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/**
|
|
833
|
+
* Detects whether an existing table may need a post-install schema report.
|
|
834
|
+
*
|
|
835
|
+
* This mirrors the inexpensive metadata checks used by `diff()` without
|
|
836
|
+
* running row-count queries. A fully synchronized table can therefore skip
|
|
837
|
+
* the second complete inspection previously performed after every install.
|
|
838
|
+
*
|
|
839
|
+
* @param tableName - Existing database table name.
|
|
840
|
+
* @param schema - Current model schema.
|
|
841
|
+
* @param installedSchema - Reusable live table metadata.
|
|
842
|
+
* @returns Whether the initial table shape contained a potential difference.
|
|
843
|
+
*/
|
|
844
|
+
private tableHasPotentialDiff(
|
|
845
|
+
tableName: string,
|
|
846
|
+
schema: Required<DbSchemaPart>,
|
|
847
|
+
installedSchema: InstalledTableSchema,
|
|
848
|
+
): boolean {
|
|
849
|
+
const existingColumnNames = new Set(
|
|
850
|
+
Object.keys(installedSchema.columnInfo),
|
|
851
|
+
);
|
|
852
|
+
|
|
853
|
+
for (const column of schema.columns) {
|
|
854
|
+
const info = installedSchema.columnInfo[column.name];
|
|
855
|
+
|
|
856
|
+
if (!info) return true;
|
|
857
|
+
|
|
858
|
+
const databaseNullable = columnAllowsNull(info);
|
|
859
|
+
const modelNullable = modelColumnAllowsNull(column);
|
|
860
|
+
|
|
861
|
+
if (
|
|
862
|
+
databaseNullable !== null
|
|
863
|
+
&& databaseNullable !== modelNullable
|
|
864
|
+
) {
|
|
865
|
+
return true;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
if (columnTypeDifference(
|
|
869
|
+
tableName,
|
|
870
|
+
column,
|
|
871
|
+
info,
|
|
872
|
+
installedSchema.indexes,
|
|
873
|
+
)) {
|
|
874
|
+
return true;
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
return findMissingIndexes(
|
|
879
|
+
schema.indexes,
|
|
880
|
+
installedSchema.indexes,
|
|
881
|
+
existingColumnNames,
|
|
882
|
+
).length > 0;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
/**
|
|
886
|
+
* Reads existing comments for models that declare table comments.
|
|
887
|
+
*
|
|
888
|
+
* @param models - Models participating in this install pass.
|
|
889
|
+
* @returns Existing comments keyed by database table name.
|
|
890
|
+
*/
|
|
891
|
+
private async tableCommentsFor(
|
|
892
|
+
models: ActiveRecordClass[],
|
|
893
|
+
): Promise<Map<string, string | null>> {
|
|
894
|
+
const tableNames = models
|
|
895
|
+
.filter(Model => normalizeDatabaseComment(Model.comment))
|
|
896
|
+
.map(Model => Model.table);
|
|
897
|
+
|
|
898
|
+
if (tableNames.length === 0) {
|
|
899
|
+
return new Map();
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
return this.dialect().getTableComments(this.connection, tableNames);
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
/**
|
|
906
|
+
* Reads normalized index metadata for one table through the active dialect.
|
|
907
|
+
*
|
|
908
|
+
* @param tableName - Existing database table name.
|
|
909
|
+
* @returns Normalized primary, unique, normal, and vector indexes.
|
|
910
|
+
*/
|
|
911
|
+
private async getTableIndexes(tableName: string): Promise<TableIndexSpec[]> {
|
|
912
|
+
return this.dialect().getTableIndexes(this.connection, tableName);
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* Reports schema differences that may remain after safe synchronization.
|
|
917
|
+
*
|
|
918
|
+
* @param models - Models whose pre-install metadata contained differences.
|
|
919
|
+
* @param options - Per-install reporting options.
|
|
920
|
+
* @returns Promise that resolves after reporting completes.
|
|
921
|
+
*/
|
|
922
|
+
private async reportDiffAfterInstall(
|
|
923
|
+
models: ActiveRecordClass[],
|
|
924
|
+
options: DatabaseInstallOptions,
|
|
925
|
+
): Promise<void> {
|
|
926
|
+
const reporter = options.reportSchemaDiff
|
|
927
|
+
?? this.options.reportSchemaDiff
|
|
928
|
+
?? 'warn';
|
|
929
|
+
|
|
930
|
+
if (reporter === false) return;
|
|
931
|
+
if (models.length === 0) return;
|
|
932
|
+
|
|
933
|
+
const diffs = await this.diff(...models);
|
|
934
|
+
|
|
935
|
+
if (diffs.length === 0) return;
|
|
936
|
+
|
|
937
|
+
if (reporter === 'warn') {
|
|
938
|
+
console.warn(this.formatDiff(diffs));
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
await reporter(diffs, this);
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
/**
|
|
946
|
+
* Returns the dialect associated with this database connection.
|
|
947
|
+
*/
|
|
948
|
+
private dialect(): DatabaseDialect {
|
|
949
|
+
return databaseDialectForConnection(this.connection);
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
function installColumn(
|
|
954
|
+
table: Knex.TableBuilder,
|
|
955
|
+
column: DbColumnSpec,
|
|
956
|
+
options: InstallColumnOptions = {},
|
|
957
|
+
): void {
|
|
958
|
+
writeDbColumn(table, column, options);
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
function installIndex(
|
|
962
|
+
table: Knex.TableBuilder,
|
|
963
|
+
index: DbIndexSpec,
|
|
964
|
+
dialect: DatabaseDialect,
|
|
965
|
+
): void {
|
|
966
|
+
const columns = indexColumnsForKnex(table, index.columns);
|
|
967
|
+
|
|
968
|
+
if (index.type === 'vector') {
|
|
969
|
+
if (!dialect.supportsVectorIndexes) return;
|
|
970
|
+
|
|
971
|
+
table.index(columns, index.name, 'vector');
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
if (index.unique) {
|
|
976
|
+
table.unique(columns, index.name);
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
table.index(columns, index.name);
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
function installForeignKey(
|
|
984
|
+
table: Knex.TableBuilder,
|
|
985
|
+
foreignKey: DbForeignKeySpec,
|
|
986
|
+
): void {
|
|
987
|
+
let builder = table
|
|
988
|
+
.foreign(foreignKey.column)
|
|
989
|
+
.references(foreignKey.referencesColumn)
|
|
990
|
+
.inTable(foreignKey.referencesTable);
|
|
991
|
+
|
|
992
|
+
if (foreignKey.onDelete) {
|
|
993
|
+
builder = builder.onDelete(foreignKey.onDelete);
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
if (foreignKey.onUpdate) {
|
|
997
|
+
builder.onUpdate(foreignKey.onUpdate);
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
function indexColumnsForKnex(
|
|
1002
|
+
table: Knex.TableBuilder,
|
|
1003
|
+
columns: DbIndexColumnSpec[],
|
|
1004
|
+
): string | (string | Knex.Raw)[] {
|
|
1005
|
+
const normalizedColumns = columns.map(column => {
|
|
1006
|
+
if (typeof column === 'string' || !column.order) return indexColumnName(column);
|
|
1007
|
+
|
|
1008
|
+
const client = (table as unknown as { client: Knex }).client;
|
|
1009
|
+
|
|
1010
|
+
return client.raw(`?? ${column.order}`, [column.name]);
|
|
1011
|
+
});
|
|
1012
|
+
|
|
1013
|
+
return normalizedColumns.length === 1 && typeof normalizedColumns[0] === 'string'
|
|
1014
|
+
? normalizedColumns[0]
|
|
1015
|
+
: normalizedColumns;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
function findMissingIndexes(
|
|
1019
|
+
requiredIndexes: DbIndexSpec[],
|
|
1020
|
+
existingIndexes: TableIndexSpec[],
|
|
1021
|
+
existingColumnNames: Set<string>,
|
|
1022
|
+
): MissingIndex[] {
|
|
1023
|
+
return requiredIndexes.flatMap(index => {
|
|
1024
|
+
const missingColumns = index.columns
|
|
1025
|
+
.map(indexColumnName)
|
|
1026
|
+
.filter(column => {
|
|
1027
|
+
return !existingColumnNames.has(column);
|
|
1028
|
+
});
|
|
1029
|
+
|
|
1030
|
+
if (missingColumns.length > 0) {
|
|
1031
|
+
return [];
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
if (existingIndexes.some(existingIndex => indexMatches(index, existingIndex))) {
|
|
1035
|
+
return [];
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
const blocked = Boolean(
|
|
1039
|
+
index.name && existingIndexes.some(existingIndex => {
|
|
1040
|
+
return existingIndex.name === index.name;
|
|
1041
|
+
}),
|
|
1042
|
+
);
|
|
1043
|
+
|
|
1044
|
+
return [{
|
|
1045
|
+
index,
|
|
1046
|
+
blocked,
|
|
1047
|
+
message: missingIndexMessage(index, blocked),
|
|
1048
|
+
}];
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
function indexMatches(
|
|
1053
|
+
requiredIndex: DbIndexSpec,
|
|
1054
|
+
existingIndex: TableIndexSpec,
|
|
1055
|
+
): boolean {
|
|
1056
|
+
if (existingIndex.primary) return false;
|
|
1057
|
+
if ((requiredIndex.type ?? 'normal') !== (existingIndex.type ?? 'normal')) return false;
|
|
1058
|
+
if (Boolean(requiredIndex.unique) !== existingIndex.unique) return false;
|
|
1059
|
+
|
|
1060
|
+
const requiredColumns = requiredIndex.columns.map(normalizeIndexColumn);
|
|
1061
|
+
|
|
1062
|
+
if (requiredColumns.length !== existingIndex.columns.length) return false;
|
|
1063
|
+
|
|
1064
|
+
return requiredColumns.every((requiredColumn, index) => {
|
|
1065
|
+
const existingColumn = existingIndex.columns[index];
|
|
1066
|
+
|
|
1067
|
+
if (requiredColumn.name !== existingColumn.name) return false;
|
|
1068
|
+
|
|
1069
|
+
return !requiredColumn.order || requiredColumn.order === existingColumn.order;
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
function normalizeIndexColumn(column: DbIndexColumnSpec): NormalizedIndexColumn {
|
|
1074
|
+
return typeof column === 'string'
|
|
1075
|
+
? { name: column }
|
|
1076
|
+
: column;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
function indexColumnName(column: DbIndexColumnSpec): string {
|
|
1080
|
+
return typeof column === 'string'
|
|
1081
|
+
? column
|
|
1082
|
+
: column.name;
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
function missingIndexMessage(index: DbIndexSpec, blocked: boolean): string {
|
|
1086
|
+
const name = index.name ? ` ${index.name}` : '';
|
|
1087
|
+
const blockedMessage = blocked
|
|
1088
|
+
? ' A different index with that name already exists.'
|
|
1089
|
+
: '';
|
|
1090
|
+
|
|
1091
|
+
return `Index${name} on ${describeIndex(index)} is missing.${blockedMessage}`;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
function describeIndex(index: DbIndexSpec): string {
|
|
1095
|
+
const columns = index.columns.map(column => {
|
|
1096
|
+
if (typeof column === 'string' || !column.order) return indexColumnName(column);
|
|
1097
|
+
|
|
1098
|
+
return `${column.name} ${column.order.toUpperCase()}`;
|
|
1099
|
+
});
|
|
1100
|
+
const type = index.type === 'vector' ? 'vector ' : '';
|
|
1101
|
+
|
|
1102
|
+
return `${type}(${columns.join(', ')})`;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
function modelColumnAllowsNull(column: DbColumnSpec): boolean {
|
|
1106
|
+
return !(column.primary || column.nullable === false);
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
function describeColumn(column: DbColumnSpec): string {
|
|
1110
|
+
const nullable = modelColumnAllowsNull(column) ? 'nullable' : 'not null';
|
|
1111
|
+
|
|
1112
|
+
return `${column.type} ${nullable}`;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
function describeColumnInfo(info: unknown): string {
|
|
1116
|
+
const type = columnInfoType(info) ?? 'unknown';
|
|
1117
|
+
const maxLength = columnInfoMaxLength(info);
|
|
1118
|
+
|
|
1119
|
+
return maxLength ? `${type}(${maxLength})` : type;
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
function columnTypeDifference(
|
|
1123
|
+
tableName: string,
|
|
1124
|
+
column: DbColumnSpec,
|
|
1125
|
+
info: unknown,
|
|
1126
|
+
tableIndexes: TableIndexSpec[],
|
|
1127
|
+
): DatabaseSchemaDifference | null {
|
|
1128
|
+
if (!columnNeedsTextWidening(column, info)) return null;
|
|
1129
|
+
|
|
1130
|
+
const blocked = isColumnIndexed(column.name, tableIndexes);
|
|
1131
|
+
|
|
1132
|
+
return {
|
|
1133
|
+
kind: 'type_mismatch',
|
|
1134
|
+
table: tableName,
|
|
1135
|
+
column: column.name,
|
|
1136
|
+
databaseValue: describeColumnInfo(info),
|
|
1137
|
+
modelValue: describeColumn(column),
|
|
1138
|
+
blocked,
|
|
1139
|
+
message: typeMismatchMessage(
|
|
1140
|
+
tableName,
|
|
1141
|
+
column.name,
|
|
1142
|
+
describeColumnInfo(info),
|
|
1143
|
+
describeColumn(column),
|
|
1144
|
+
blocked,
|
|
1145
|
+
),
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
function typeMismatchMessage(
|
|
1150
|
+
tableName: string,
|
|
1151
|
+
columnName: string,
|
|
1152
|
+
databaseValue: string,
|
|
1153
|
+
modelValue: string,
|
|
1154
|
+
blocked: boolean,
|
|
1155
|
+
): string {
|
|
1156
|
+
const blocker = blocked ? ' Column is indexed, so this must be changed manually.' : '';
|
|
1157
|
+
|
|
1158
|
+
return `Column ${tableName}.${columnName} type differs: database is ${databaseValue}, model expects ${modelValue}.${blocker}`;
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
function columnNeedsTextWidening(
|
|
1162
|
+
column: DbColumnSpec,
|
|
1163
|
+
info: unknown,
|
|
1164
|
+
): boolean {
|
|
1165
|
+
const modelType = normalizeColumnType(column.type);
|
|
1166
|
+
|
|
1167
|
+
if (modelType !== 'text' && modelType !== 'longtext') return false;
|
|
1168
|
+
|
|
1169
|
+
const databaseType = columnInfoType(info);
|
|
1170
|
+
|
|
1171
|
+
if (!databaseType) return false;
|
|
1172
|
+
if (modelType === 'longtext' && isTextColumnType(databaseType)) {
|
|
1173
|
+
return databaseType.toLowerCase() !== 'longtext';
|
|
1174
|
+
}
|
|
1175
|
+
if (modelType === 'text' && isTextColumnType(databaseType)) return false;
|
|
1176
|
+
|
|
1177
|
+
return isStringColumnType(databaseType);
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
function columnInfoType(info: unknown): string | null {
|
|
1181
|
+
if (!info || typeof info !== 'object') return null;
|
|
1182
|
+
|
|
1183
|
+
const type = (info as { type?: unknown }).type;
|
|
1184
|
+
|
|
1185
|
+
return typeof type === 'string' && type !== '' ? type : null;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
function columnInfoMaxLength(info: unknown): number | null {
|
|
1189
|
+
if (!info || typeof info !== 'object') return null;
|
|
1190
|
+
|
|
1191
|
+
const maxLength = (info as { maxLength?: unknown }).maxLength;
|
|
1192
|
+
|
|
1193
|
+
if (typeof maxLength === 'number' && Number.isFinite(maxLength)) return maxLength;
|
|
1194
|
+
if (typeof maxLength === 'string' && maxLength.trim() !== '') {
|
|
1195
|
+
const parsed = Number(maxLength);
|
|
1196
|
+
|
|
1197
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
return null;
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
function isTextColumnType(type: string): boolean {
|
|
1204
|
+
return /^(?:tinytext|text|mediumtext|longtext)$/i.test(normalizeColumnType(type));
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
function isStringColumnType(type: string): boolean {
|
|
1208
|
+
return /^(?:char|varchar|string)$/i.test(normalizeColumnType(type));
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
function normalizeColumnType(type: string): string {
|
|
1212
|
+
return type.trim().toLowerCase().replace(/\(.+$/, '');
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
function isColumnIndexed(
|
|
1216
|
+
columnName: string,
|
|
1217
|
+
tableIndexes: TableIndexSpec[],
|
|
1218
|
+
): boolean {
|
|
1219
|
+
return tableIndexes.some(index => {
|
|
1220
|
+
return index.columns.some(column => column.name === columnName);
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
function nullableMismatchMessage(
|
|
1225
|
+
tableName: string,
|
|
1226
|
+
columnName: string,
|
|
1227
|
+
databaseNullable: boolean,
|
|
1228
|
+
modelNullable: boolean,
|
|
1229
|
+
rowsWithNull: number | undefined,
|
|
1230
|
+
): string {
|
|
1231
|
+
const databaseValue = databaseNullable ? 'nullable' : 'not null';
|
|
1232
|
+
const modelValue = modelNullable ? 'nullable' : 'not null';
|
|
1233
|
+
const blocker = rowsWithNull
|
|
1234
|
+
? `; ${rowsWithNull} rows currently contain NULL`
|
|
1235
|
+
: '';
|
|
1236
|
+
|
|
1237
|
+
return `Column ${tableName}.${columnName} nullability differs: database is ${databaseValue}, model expects ${modelValue}${blocker}.`;
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
function columnAllowsNull(info: unknown): boolean | null {
|
|
1241
|
+
if (!info || typeof info !== 'object') return null;
|
|
1242
|
+
|
|
1243
|
+
const nullable = (info as { nullable?: unknown }).nullable;
|
|
1244
|
+
|
|
1245
|
+
if (typeof nullable === 'boolean') return nullable;
|
|
1246
|
+
|
|
1247
|
+
if (typeof nullable === 'string') {
|
|
1248
|
+
const value = nullable.toLowerCase().trim();
|
|
1249
|
+
|
|
1250
|
+
if (['1', 'true', 'yes'].includes(value)) return true;
|
|
1251
|
+
if (['0', 'false', 'no'].includes(value)) return false;
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
return null;
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
function resolveInstallArgs(input: InstallArgs): {
|
|
1258
|
+
models: ActiveRecordClass[];
|
|
1259
|
+
options: DatabaseInstallOptions;
|
|
1260
|
+
} {
|
|
1261
|
+
const [
|
|
1262
|
+
first,
|
|
1263
|
+
...rest
|
|
1264
|
+
] = input;
|
|
1265
|
+
|
|
1266
|
+
if (isInstallOptions(first)) {
|
|
1267
|
+
return {
|
|
1268
|
+
models: rest as ActiveRecordClass[],
|
|
1269
|
+
options: first,
|
|
1270
|
+
};
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
return {
|
|
1274
|
+
models: input as ActiveRecordClass[],
|
|
1275
|
+
options: {},
|
|
1276
|
+
};
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
function isInstallOptions(
|
|
1280
|
+
input: ActiveRecordClass | DatabaseInstallOptions | undefined,
|
|
1281
|
+
): input is DatabaseInstallOptions {
|
|
1282
|
+
return Boolean(input && typeof input === 'object');
|
|
1283
|
+
}
|