@db3.ai/app 0.1.0-beta.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -17
- package/agent-instructions.md +76 -0
- package/dist/ai/AIErrors.d.ts +7 -1
- package/dist/ai/AIErrors.js +8 -1
- package/dist/ai/AIFailover.d.ts +10 -0
- package/dist/ai/AIFailover.js +3 -2
- package/dist/ai/AIProviderAdmission.d.ts +101 -0
- package/dist/ai/AIProviderAdmission.js +336 -0
- package/dist/ai/AIRateLimiter.d.ts +11 -2
- package/dist/ai/AIRateLimiter.js +125 -10
- package/dist/ai/AIRequestTrackingError.d.ts +22 -0
- package/dist/ai/AIRequestTrackingError.js +33 -0
- package/dist/ai/Agent.d.ts +7 -7
- package/dist/ai/Agent.js +84 -56
- package/dist/ai/Ai.d.ts +11 -3
- package/dist/ai/Ai.js +94 -44
- package/dist/ai/OpenAIProviderError.js +1 -1
- package/dist/ai/ProviderSseObserver.d.ts +19 -0
- package/dist/ai/ProviderSseObserver.js +98 -0
- package/dist/ai/aiServiceTier.d.ts +5 -0
- package/dist/ai/aiServiceTier.js +14 -0
- package/dist/ai/chunkEmbeddingText.d.ts +14 -0
- package/dist/ai/chunkEmbeddingText.js +147 -0
- package/dist/ai/contracts/AI.d.ts +16 -0
- package/dist/ai/contracts/AIRequestErrorDiagnostics.d.ts +12 -0
- package/dist/ai/contracts/AIRequestErrorDiagnostics.js +1 -0
- package/dist/ai/contracts/AIServiceTier.d.ts +2 -0
- package/dist/ai/contracts/AIServiceTier.js +1 -0
- package/dist/ai/contracts/Agent.d.ts +3 -0
- package/dist/ai/contracts/EmbeddingTextChunk.d.ts +25 -0
- package/dist/ai/contracts/EmbeddingTextChunk.js +1 -0
- package/dist/ai/contracts/Pricing.d.ts +7 -1
- package/dist/ai/contracts/Providers.d.ts +2 -0
- package/dist/ai/contracts/index.d.ts +2 -0
- package/dist/ai/contracts/index.js +1 -0
- package/dist/ai/index.d.ts +8 -2
- package/dist/ai/index.js +5 -2
- package/dist/ai/{Models.d.ts → modelPricing.d.ts} +2 -2
- package/dist/ai/{Models.js → modelPricing.js} +38 -4
- package/dist/apps/AppInstallation.d.ts +21 -0
- package/dist/apps/AppInstallation.js +16 -0
- package/dist/apps/AppRouteError.d.ts +6 -0
- package/dist/apps/AppRouteError.js +10 -0
- package/dist/apps/AppService.d.ts +24 -0
- package/dist/apps/AppService.js +21 -0
- package/dist/apps/Apps.d.ts +59 -0
- package/dist/apps/Apps.js +566 -0
- package/dist/apps/appsPlugin.d.ts +3 -0
- package/dist/apps/appsPlugin.js +36 -0
- package/dist/apps/commands/disableApp.d.ts +2 -0
- package/dist/apps/commands/disableApp.js +5 -0
- package/dist/apps/commands/enableApp.d.ts +2 -0
- package/dist/apps/commands/enableApp.js +5 -0
- package/dist/apps/commands/index.d.ts +10 -0
- package/dist/apps/commands/index.js +27 -0
- package/dist/apps/commands/installApp.d.ts +2 -0
- package/dist/apps/commands/installApp.js +5 -0
- package/dist/apps/commands/listApps.d.ts +2 -0
- package/dist/apps/commands/listApps.js +5 -0
- package/dist/apps/commands/makeAppMigration.d.ts +2 -0
- package/dist/apps/commands/makeAppMigration.js +9 -0
- package/dist/apps/commands/rollbackApp.d.ts +2 -0
- package/dist/apps/commands/rollbackApp.js +5 -0
- package/dist/apps/commands/uninstallApp.d.ts +2 -0
- package/dist/apps/commands/uninstallApp.js +5 -0
- package/dist/apps/contracts/AppAction.d.ts +2 -0
- package/dist/apps/contracts/AppAction.js +1 -0
- package/dist/apps/contracts/AppDefinition.d.ts +45 -0
- package/dist/apps/contracts/AppDefinition.js +1 -0
- package/dist/apps/contracts/AppDescription.d.ts +32 -0
- package/dist/apps/contracts/AppDescription.js +1 -0
- package/dist/apps/contracts/AppManifest.d.ts +30 -0
- package/dist/apps/contracts/AppManifest.js +1 -0
- package/dist/apps/contracts/AppNavigation.d.ts +9 -0
- package/dist/apps/contracts/AppNavigation.js +1 -0
- package/dist/apps/contracts/AppNavigationBadge.d.ts +6 -0
- package/dist/apps/contracts/AppNavigationBadge.js +1 -0
- package/dist/apps/contracts/AppNavigationContext.d.ts +8 -0
- package/dist/apps/contracts/AppNavigationContext.js +1 -0
- package/dist/apps/contracts/AppNavigationResult.d.ts +12 -0
- package/dist/apps/contracts/AppNavigationResult.js +1 -0
- package/dist/apps/contracts/AppRoute.d.ts +19 -0
- package/dist/apps/contracts/AppRoute.js +1 -0
- package/dist/apps/contracts/DiscoveredApp.d.ts +10 -0
- package/dist/apps/contracts/DiscoveredApp.js +1 -0
- package/dist/apps/contracts/InstalledApps.d.ts +3 -0
- package/dist/apps/contracts/InstalledApps.js +1 -0
- package/dist/apps/contracts/index.d.ts +11 -0
- package/dist/apps/contracts/index.js +1 -0
- package/dist/apps/defineApp.d.ts +7 -0
- package/dist/apps/defineApp.js +8 -0
- package/dist/apps/discoverApps.d.ts +3 -0
- package/dist/apps/discoverApps.js +62 -0
- package/dist/apps/fastify.d.ts +1 -0
- package/dist/apps/fastify.js +1 -0
- package/dist/apps/index.d.ts +7 -0
- package/dist/apps/index.js +7 -0
- package/dist/apps/normalizeAppNavigation.d.ts +3 -0
- package/dist/apps/normalizeAppNavigation.js +30 -0
- package/dist/apps/registerAppRoutes.d.ts +6 -0
- package/dist/apps/registerAppRoutes.js +52 -0
- package/dist/apps/validateAppDefinitions.d.ts +3 -0
- package/dist/apps/validateAppDefinitions.js +65 -0
- package/dist/apps/vite.d.ts +1 -0
- package/dist/apps/vite.js +1 -0
- package/dist/apps/writeAppTypes.d.ts +2 -0
- package/dist/apps/writeAppTypes.js +13 -0
- package/dist/auth/Auth.d.ts +18 -0
- package/dist/auth/Auth.js +89 -13
- package/dist/auth/PasswordLoginAttempt.d.ts +50 -0
- package/dist/auth/PasswordLoginAttempt.js +60 -0
- package/dist/auth/PasswordSuspendedError.d.ts +10 -0
- package/dist/auth/PasswordSuspendedError.js +13 -0
- package/dist/auth/contracts/PasswordAuthProviderOptions.d.ts +26 -0
- package/dist/auth/contracts/PasswordAuthProviderOptions.js +1 -0
- package/dist/auth/contracts/PasswordSuspension.d.ts +7 -0
- package/dist/auth/contracts/PasswordSuspension.js +1 -0
- package/dist/auth/contracts/PasswordSuspensionOptions.d.ts +10 -0
- package/dist/auth/contracts/PasswordSuspensionOptions.js +1 -0
- package/dist/auth/contracts/index.d.ts +3 -0
- package/dist/auth/contracts/index.js +3 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.js +2 -0
- package/dist/auth/providers/PasswordAuthProvider.d.ts +19 -23
- package/dist/auth/providers/PasswordAuthProvider.js +96 -8
- package/dist/auth/providers/resolveAuthProviders.js +1 -0
- package/dist/cli/Cli.d.ts +2 -0
- package/dist/cli/Cli.js +8 -0
- package/dist/cli/commands/repl.js +2 -1
- package/dist/cli/contracts/CliCommand.d.ts +2 -0
- package/dist/cli/contracts/CliCommandInfo.d.ts +12 -0
- package/dist/cli/contracts/CliCommandInfo.js +1 -0
- package/dist/cli/contracts/index.d.ts +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +1 -0
- package/dist/cli/listDb3Commands.d.ts +8 -0
- package/dist/cli/listDb3Commands.js +10 -0
- package/dist/cli/runDb3.d.ts +3 -6
- package/dist/cli/runDb3.js +5 -59
- package/dist/cli/withDb3Cli.d.ts +4 -0
- package/dist/cli/withDb3Cli.js +60 -0
- package/dist/db/ActiveQueryBuilder.d.ts +8 -0
- package/dist/db/ActiveQueryBuilder.js +11 -0
- package/dist/db/ActiveRecord.d.ts +6 -0
- package/dist/db/ActiveRecord.js +8 -0
- package/dist/db/connection.js +14 -2
- package/dist/db/fields/TimestampField.d.ts +1 -1
- package/dist/db/fields/TimestampField.js +7 -12
- package/dist/db/migrations/DatabaseMigrationManager.d.ts +3 -1
- package/dist/db/migrations/DatabaseMigrationManager.js +9 -3
- package/dist/db/migrations/contracts/DatabaseMigration.d.ts +7 -0
- package/dist/db/migrations/index.d.ts +1 -1
- package/dist/db/migrations/index.js +1 -1
- package/dist/db/migrations/{KnexMigrationRenderer.d.ts → renderKnexMigration.d.ts} +4 -3
- package/dist/db/migrations/{KnexMigrationRenderer.js → renderKnexMigration.js} +7 -6
- package/dist/flows/FlowCompiler.js +1 -1
- package/dist/flows/Flows.js +1 -1
- package/dist/flows/index.d.ts +1 -1
- package/dist/flows/index.js +1 -1
- package/dist/health/Health.d.ts +41 -0
- package/dist/health/Health.js +153 -0
- package/dist/health/contracts/Health.d.ts +36 -0
- package/dist/health/contracts/Health.js +1 -0
- package/dist/health/contracts/HealthHttp.d.ts +15 -0
- package/dist/health/contracts/HealthHttp.js +1 -0
- package/dist/health/contracts/index.d.ts +2 -0
- package/dist/health/contracts/index.js +1 -0
- package/dist/health/databaseHealthCheck.d.ts +15 -0
- package/dist/health/databaseHealthCheck.js +18 -0
- package/dist/health/fastify.d.ts +13 -0
- package/dist/health/fastify.js +44 -0
- package/dist/health/index.d.ts +3 -0
- package/dist/health/index.js +2 -0
- package/dist/in-app/InApp.d.ts +33 -0
- package/dist/in-app/InApp.js +191 -0
- package/dist/in-app/InAppError.d.ts +6 -0
- package/dist/in-app/InAppError.js +10 -0
- package/dist/in-app/InAppRecord.d.ts +36 -0
- package/dist/in-app/InAppRecord.js +24 -0
- package/dist/in-app/contracts/InAppInbox.d.ts +45 -0
- package/dist/in-app/contracts/InAppInbox.js +1 -0
- package/dist/in-app/contracts/InAppMessage.d.ts +22 -0
- package/dist/in-app/contracts/InAppMessage.js +1 -0
- package/dist/in-app/contracts/InAppScope.d.ts +17 -0
- package/dist/in-app/contracts/InAppScope.js +1 -0
- package/dist/in-app/contracts/index.d.ts +3 -0
- package/dist/in-app/contracts/index.js +3 -0
- package/dist/in-app/index.d.ts +4 -0
- package/dist/in-app/index.js +4 -0
- package/dist/in-app/validation.d.ts +21 -0
- package/dist/in-app/validation.js +50 -0
- package/dist/index.d.ts +2 -14
- package/dist/index.js +2 -5
- package/dist/logging/DevelopmentConsole.d.ts +42 -0
- package/dist/logging/DevelopmentConsole.js +162 -0
- package/dist/logging/Log.d.ts +3 -1
- package/dist/logging/Log.js +5 -2
- package/dist/logging/PrettyLogFormatter.d.ts +16 -0
- package/dist/logging/PrettyLogFormatter.js +151 -0
- package/dist/logging/acquireDevelopmentConsole.d.ts +6 -0
- package/dist/logging/acquireDevelopmentConsole.js +21 -0
- package/dist/logging/contracts/DevelopmentConsoleOptions.d.ts +16 -0
- package/dist/logging/contracts/DevelopmentConsoleOptions.js +1 -0
- package/dist/logging/contracts/EmailLogOptions.d.ts +8 -0
- package/dist/logging/contracts/EmailLogOptions.js +1 -0
- package/dist/logging/contracts/HttpExchangeMonitorOptions.d.ts +12 -0
- package/dist/logging/contracts/HttpExchangeMonitorOptions.js +1 -0
- package/dist/logging/contracts/LogTransportOptions.d.ts +19 -0
- package/dist/logging/contracts/LogTransportOptions.js +1 -0
- package/dist/logging/contracts/LoggingOptions.d.ts +12 -1
- package/dist/logging/contracts/index.d.ts +4 -0
- package/dist/logging/contracts/index.js +4 -0
- package/dist/logging/drivers/PinoLoggerDriver.d.ts +3 -1
- package/dist/logging/drivers/PinoLoggerDriver.js +75 -16
- package/dist/logging/formatLogEmail.d.ts +4 -0
- package/dist/logging/formatLogEmail.js +21 -0
- package/dist/logging/highlightQueueMessage.d.ts +11 -0
- package/dist/logging/highlightQueueMessage.js +36 -0
- package/dist/logging/httpBodyCapture.d.ts +24 -0
- package/dist/logging/httpBodyCapture.js +321 -0
- package/dist/logging/index.d.ts +2 -0
- package/dist/logging/index.js +2 -0
- package/dist/logging/redactLogEmail.d.ts +2 -0
- package/dist/logging/redactLogEmail.js +12 -0
- package/dist/logging/registerHttpExchangeMonitor.d.ts +10 -0
- package/dist/logging/registerHttpExchangeMonitor.js +43 -0
- package/dist/logging/transports/EmailLogTransport.d.ts +18 -0
- package/dist/logging/transports/EmailLogTransport.js +47 -0
- package/dist/mail/Mail.d.ts +2 -0
- package/dist/mail/Mail.js +3 -0
- package/dist/mail/MailDeliveryError.d.ts +9 -0
- package/dist/mail/MailDeliveryError.js +16 -0
- package/dist/mail/index.d.ts +1 -0
- package/dist/mail/index.js +1 -0
- package/dist/mail/transports/MailgunTransport.js +2 -0
- package/dist/mail/transports/ResendTransport.d.ts +3 -2
- package/dist/mail/transports/ResendTransport.js +22 -14
- package/dist/media/MediaManager.d.ts +4 -2
- package/dist/media/MediaManager.js +40 -8
- package/dist/network/BlockedUrlError.d.ts +16 -0
- package/dist/network/BlockedUrlError.js +19 -0
- package/dist/network/assertPublicUrl.d.ts +22 -0
- package/dist/network/assertPublicUrl.js +67 -0
- package/dist/network/contracts/GuardedFetch.d.ts +35 -0
- package/dist/network/contracts/GuardedFetch.js +1 -0
- package/dist/network/contracts/PublicUrlOptions.d.ts +17 -0
- package/dist/network/contracts/PublicUrlOptions.js +1 -0
- package/dist/network/contracts/index.d.ts +2 -0
- package/dist/network/contracts/index.js +2 -0
- package/dist/network/guardedFetch.d.ts +29 -0
- package/dist/network/guardedFetch.js +133 -0
- package/dist/network/index.d.ts +6 -0
- package/dist/network/index.js +6 -0
- package/dist/network/playwright/GuardedBrowserProxy.d.ts +32 -0
- package/dist/network/playwright/GuardedBrowserProxy.js +172 -0
- package/dist/network/playwright/contracts/GuardedBrowserContextOptions.d.ts +37 -0
- package/dist/network/playwright/contracts/GuardedBrowserContextOptions.js +1 -0
- package/dist/network/playwright/contracts/index.d.ts +1 -0
- package/dist/network/playwright/contracts/index.js +1 -0
- package/dist/network/playwright/index.d.ts +2 -0
- package/dist/network/playwright/index.js +2 -0
- package/dist/network/playwright/newGuardedBrowserContext.d.ts +21 -0
- package/dist/network/playwright/newGuardedBrowserContext.js +86 -0
- package/dist/network/privateNetworkAddresses.d.ts +44 -0
- package/dist/network/privateNetworkAddresses.js +157 -0
- package/dist/network/publicAddressLookup.d.ts +26 -0
- package/dist/network/publicAddressLookup.js +42 -0
- package/dist/notifications/Notifications.d.ts +27 -0
- package/dist/notifications/Notifications.js +99 -0
- package/dist/notifications/contracts/Notification.d.ts +56 -0
- package/dist/notifications/contracts/Notification.js +1 -0
- package/dist/notifications/contracts/NotificationDelivery.d.ts +11 -0
- package/dist/notifications/contracts/NotificationDelivery.js +1 -0
- package/dist/notifications/contracts/index.d.ts +2 -0
- package/dist/notifications/contracts/index.js +2 -0
- package/dist/notifications/index.d.ts +2 -0
- package/dist/notifications/index.js +2 -0
- package/dist/queue/JobRunAttempt.d.ts +16 -0
- package/dist/queue/JobRunAttempt.js +17 -0
- package/dist/queue/JobRunEvent.d.ts +15 -0
- package/dist/queue/JobRunEvent.js +16 -0
- package/dist/queue/JobRunStoppedError.d.ts +6 -0
- package/dist/queue/JobRunStoppedError.js +10 -0
- package/dist/queue/Queue.d.ts +19 -4
- package/dist/queue/Queue.js +122 -9
- package/dist/queue/QueueTerminalError.d.ts +9 -0
- package/dist/queue/QueueTerminalError.js +12 -0
- package/dist/queue/QueueWorker.d.ts +12 -5
- package/dist/queue/QueueWorker.js +94 -9
- package/dist/queue/QueueWorkerReporter.d.ts +17 -0
- package/dist/queue/QueueWorkerReporter.js +71 -0
- package/dist/queue/QueueableJob.d.ts +2 -2
- package/dist/queue/RunnableJob.d.ts +78 -0
- package/dist/queue/RunnableJob.js +284 -0
- package/dist/queue/console.d.ts +8 -0
- package/dist/queue/console.js +53 -19
- package/dist/queue/contracts/QueueDriver.d.ts +8 -0
- package/dist/queue/contracts/QueueJobRunner.d.ts +4 -0
- package/dist/queue/contracts/QueueJobRunner.js +1 -0
- package/dist/queue/contracts/QueuePayload.d.ts +1 -1
- package/dist/queue/contracts/QueueSelection.d.ts +11 -0
- package/dist/queue/contracts/QueueSelection.js +1 -0
- package/dist/queue/contracts/QueueService.d.ts +18 -4
- package/dist/queue/contracts/QueueWorkerLifecycle.d.ts +2 -2
- package/dist/queue/contracts/QueueWorkerSnapshot.d.ts +14 -0
- package/dist/queue/contracts/QueueWorkerSnapshot.js +1 -0
- package/dist/queue/contracts/QueueableJob.d.ts +7 -3
- package/dist/queue/contracts/QueueableJobContract.d.ts +12 -0
- package/dist/queue/contracts/QueueableJobContract.js +1 -0
- package/dist/queue/contracts/index.d.ts +4 -0
- package/dist/queue/contracts/index.js +2 -0
- package/dist/queue/drivers/DatabaseQueueDriver.d.ts +4 -0
- package/dist/queue/drivers/DatabaseQueueDriver.js +27 -3
- package/dist/queue/drivers/RedisQueueDriver.d.ts +7 -0
- package/dist/queue/drivers/RedisQueueDriver.js +37 -0
- package/dist/queue/index.d.ts +5 -0
- package/dist/queue/index.js +5 -0
- package/dist/queue/jobEnvelopeHasPrefix.d.ts +3 -0
- package/dist/queue/jobEnvelopeHasPrefix.js +4 -0
- package/dist/scheduler/ScheduledEvent.d.ts +8 -4
- package/dist/scheduler/ScheduledEvent.js +17 -3
- package/dist/scheduler/ScheduledJob.d.ts +1 -1
- package/dist/scheduler/Scheduler.d.ts +5 -0
- package/dist/scheduler/Scheduler.js +92 -28
- package/dist/scheduler/SchedulerCheckpointRecord.d.ts +16 -0
- package/dist/scheduler/SchedulerCheckpointRecord.js +53 -0
- package/dist/scheduler/SchedulerWorker.d.ts +3 -5
- package/dist/scheduler/SchedulerWorker.js +58 -14
- package/dist/scheduler/console.js +3 -1
- package/dist/scheduler/contracts/Schedule.d.ts +19 -0
- package/dist/scheduler/contracts/Schedule.js +1 -0
- package/dist/scheduler/contracts/Scheduler.d.ts +18 -6
- package/dist/scheduler/contracts/SchedulerCheckpoint.d.ts +23 -0
- package/dist/scheduler/contracts/SchedulerCheckpoint.js +1 -0
- package/dist/scheduler/contracts/SchedulerConsole.d.ts +5 -0
- package/dist/scheduler/contracts/SchedulerWorker.d.ts +6 -1
- package/dist/scheduler/contracts/index.d.ts +2 -0
- package/dist/scheduler/contracts/index.js +2 -0
- package/dist/scheduler/index.d.ts +1 -0
- package/dist/scheduler/index.js +1 -0
- package/dist/server/App.d.ts +36 -4
- package/dist/server/App.js +57 -7
- package/dist/server/contracts/HttpErrorHandlerOptions.d.ts +29 -0
- package/dist/server/contracts/HttpErrorHandlerOptions.js +1 -0
- package/dist/server/contracts/index.d.ts +1 -0
- package/dist/server/contracts/index.js +1 -0
- package/dist/server/index.d.ts +4 -0
- package/dist/server/index.js +4 -0
- package/dist/server/publicServerErrorMessage.d.ts +11 -0
- package/dist/server/publicServerErrorMessage.js +16 -0
- package/dist/server/registerBrowserJsonFormatting.d.ts +16 -0
- package/dist/server/registerBrowserJsonFormatting.js +100 -0
- package/dist/server/registerHttpErrorHandler.d.ts +20 -0
- package/dist/server/registerHttpErrorHandler.js +93 -0
- package/dist/ssr/vite/contracts/ViteSsrOptions.d.ts +2 -0
- package/dist/ssr/vite/fastifyViteSsr.js +4 -3
- package/dist/storage/drivers/FlystorageDisk.js +2 -2
- package/dist/storage/index.d.ts +2 -2
- package/dist/storage/index.js +2 -2
- package/dist/websocket/WebSocketChannels.d.ts +18 -0
- package/dist/websocket/WebSocketChannels.js +129 -0
- package/dist/websocket/WebSocketConnection.d.ts +25 -0
- package/dist/websocket/WebSocketConnection.js +244 -0
- package/dist/websocket/WebSockets.d.ts +41 -0
- package/dist/websocket/WebSockets.js +194 -0
- package/dist/websocket/client/WebSocketClient.d.ts +21 -0
- package/dist/websocket/client/WebSocketClient.js +230 -0
- package/dist/websocket/client/index.d.ts +3 -0
- package/dist/websocket/client/index.js +1 -0
- package/dist/websocket/contracts/WebSocketChannel.d.ts +20 -0
- package/dist/websocket/contracts/WebSocketChannel.js +1 -0
- package/dist/websocket/contracts/WebSocketClient.d.ts +45 -0
- package/dist/websocket/contracts/WebSocketClient.js +1 -0
- package/dist/websocket/contracts/WebSocketEndpoint.d.ts +43 -0
- package/dist/websocket/contracts/WebSocketEndpoint.js +1 -0
- package/dist/websocket/contracts/WebSocketOptions.d.ts +48 -0
- package/dist/websocket/contracts/WebSocketOptions.js +1 -0
- package/dist/websocket/contracts/WebSocketPresence.d.ts +6 -0
- package/dist/websocket/contracts/WebSocketPresence.js +1 -0
- package/dist/websocket/contracts/WebSocketServiceOptions.d.ts +12 -0
- package/dist/websocket/contracts/WebSocketServiceOptions.js +1 -0
- package/dist/websocket/contracts/index.d.ts +6 -0
- package/dist/websocket/contracts/index.js +1 -0
- package/dist/websocket/defineChannel.d.ts +8 -0
- package/dist/websocket/defineChannel.js +13 -0
- package/dist/websocket/defineWebSocket.d.ts +14 -0
- package/dist/websocket/defineWebSocket.js +4 -0
- package/dist/websocket/fastify.d.ts +11 -0
- package/dist/websocket/fastify.js +38 -0
- package/dist/websocket/index.d.ts +5 -0
- package/dist/websocket/index.js +4 -0
- package/package.json +108 -7
- package/src/ai/AIErrors.ts +10 -0
- package/src/ai/AIFailover.ts +3 -2
- package/src/ai/AIProviderAdmission.ts +329 -0
- package/src/ai/AIRateLimiter.ts +134 -10
- package/src/ai/AIRequestTrackingError.ts +37 -0
- package/src/ai/Agent.ts +85 -71
- package/src/ai/Ai.ts +104 -48
- package/src/ai/OpenAIProviderError.ts +1 -1
- package/src/ai/ProviderSseObserver.ts +89 -0
- package/src/ai/README.md +216 -11
- package/src/ai/aiServiceTier.ts +14 -0
- package/src/ai/chunkEmbeddingText.ts +137 -0
- package/src/ai/contracts/AI.ts +17 -0
- package/src/ai/contracts/AIRequestErrorDiagnostics.ts +12 -0
- package/src/ai/contracts/AIServiceTier.ts +2 -0
- package/src/ai/contracts/Agent.ts +3 -0
- package/src/ai/contracts/EmbeddingTextChunk.ts +26 -0
- package/src/ai/contracts/Pricing.ts +7 -1
- package/src/ai/contracts/Providers.ts +2 -0
- package/src/ai/contracts/index.ts +2 -0
- package/src/ai/examples/prepareDocumentEmbeddings.ts +20 -0
- package/src/ai/index.ts +9 -2
- package/src/ai/{Models.ts → modelPricing.ts} +37 -4
- package/src/apps/AppInstallation.ts +25 -0
- package/src/apps/AppRouteError.ts +8 -0
- package/src/apps/AppService.ts +30 -0
- package/src/apps/Apps.ts +508 -0
- package/src/apps/README.md +354 -0
- package/src/apps/appsPlugin.ts +34 -0
- package/src/apps/commands/disableApp.ts +6 -0
- package/src/apps/commands/enableApp.ts +6 -0
- package/src/apps/commands/index.ts +29 -0
- package/src/apps/commands/installApp.ts +6 -0
- package/src/apps/commands/listApps.ts +6 -0
- package/src/apps/commands/makeAppMigration.ts +9 -0
- package/src/apps/commands/rollbackApp.ts +6 -0
- package/src/apps/commands/uninstallApp.ts +6 -0
- package/src/apps/contracts/AppAction.ts +2 -0
- package/src/apps/contracts/AppDefinition.ts +49 -0
- package/src/apps/contracts/AppDescription.ts +27 -0
- package/src/apps/contracts/AppManifest.ts +32 -0
- package/src/apps/contracts/AppNavigation.ts +10 -0
- package/src/apps/contracts/AppNavigationBadge.ts +6 -0
- package/src/apps/contracts/AppNavigationContext.ts +6 -0
- package/src/apps/contracts/AppNavigationResult.ts +9 -0
- package/src/apps/contracts/AppRoute.ts +18 -0
- package/src/apps/contracts/DiscoveredApp.ts +11 -0
- package/src/apps/contracts/InstalledApps.ts +2 -0
- package/src/apps/contracts/index.ts +11 -0
- package/src/apps/defineApp.ts +10 -0
- package/src/apps/discoverApps.ts +56 -0
- package/src/apps/fastify.ts +1 -0
- package/src/apps/index.ts +7 -0
- package/src/apps/normalizeAppNavigation.ts +29 -0
- package/src/apps/registerAppRoutes.ts +48 -0
- package/src/apps/validateAppDefinitions.ts +52 -0
- package/src/apps/vite.ts +1 -0
- package/src/apps/writeAppTypes.ts +14 -0
- package/src/auth/Auth.ts +89 -23
- package/src/auth/PasswordLoginAttempt.ts +72 -0
- package/src/auth/PasswordSuspendedError.ts +13 -0
- package/src/auth/README.md +94 -4
- package/src/auth/contracts/PasswordAuthProviderOptions.ts +30 -0
- package/src/auth/contracts/PasswordSuspension.ts +7 -0
- package/src/auth/contracts/PasswordSuspensionOptions.ts +10 -0
- package/src/auth/contracts/index.ts +3 -0
- package/src/auth/examples/runPasswordAuth.ts +6 -6
- package/src/auth/index.ts +2 -0
- package/src/auth/providers/PasswordAuthProvider.ts +96 -30
- package/src/auth/providers/resolveAuthProviders.ts +1 -0
- package/src/cli/Cli.ts +9 -0
- package/src/cli/README.md +19 -0
- package/src/cli/commands/repl.ts +2 -1
- package/src/cli/contracts/CliCommand.ts +2 -0
- package/src/cli/contracts/CliCommandInfo.ts +13 -0
- package/src/cli/contracts/index.ts +1 -0
- package/src/cli/index.ts +1 -0
- package/src/cli/listDb3Commands.ts +12 -0
- package/src/cli/runDb3.ts +5 -51
- package/src/cli/withDb3Cli.ts +55 -0
- package/src/db/ActiveQueryBuilder.ts +12 -0
- package/src/db/ActiveRecord.ts +9 -0
- package/src/db/README.md +45 -1
- package/src/db/connection.ts +12 -1
- package/src/db/examples/FieldNote.ts +7 -13
- package/src/db/examples/KnowledgeNote.ts +7 -13
- package/src/db/examples/runNoteMigrations.ts +11 -11
- package/src/db/fields/TimestampField.ts +8 -17
- package/src/db/migrations/DatabaseMigrationManager.ts +12 -4
- package/src/db/migrations/contracts/DatabaseMigration.ts +9 -0
- package/src/db/migrations/index.ts +1 -1
- package/src/db/migrations/{KnexMigrationRenderer.ts → renderKnexMigration.ts} +8 -14
- package/src/flows/FlowCompiler.ts +1 -1
- package/src/flows/Flows.ts +1 -1
- package/src/flows/index.ts +1 -1
- package/src/health/Health.ts +163 -0
- package/src/health/README.md +46 -0
- package/src/health/contracts/Health.ts +47 -0
- package/src/health/contracts/HealthHttp.ts +19 -0
- package/src/health/contracts/index.ts +2 -0
- package/src/health/databaseHealthCheck.ts +21 -0
- package/src/health/fastify.ts +49 -0
- package/src/health/index.ts +3 -0
- package/src/in-app/InApp.ts +173 -0
- package/src/in-app/InAppError.ts +8 -0
- package/src/in-app/InAppRecord.ts +41 -0
- package/src/in-app/README.md +193 -0
- package/src/in-app/contracts/InAppInbox.ts +51 -0
- package/src/in-app/contracts/InAppMessage.ts +19 -0
- package/src/in-app/contracts/InAppScope.ts +12 -0
- package/src/in-app/contracts/index.ts +3 -0
- package/src/in-app/examples/sendReportReady.ts +14 -0
- package/src/in-app/index.ts +4 -0
- package/src/in-app/validation.ts +49 -0
- package/src/index.ts +2 -22
- package/src/logging/DevelopmentConsole.ts +154 -0
- package/src/logging/Log.ts +5 -2
- package/src/logging/PrettyLogFormatter.ts +165 -0
- package/src/logging/README.md +52 -109
- package/src/logging/acquireDevelopmentConsole.ts +19 -0
- package/src/logging/contracts/DevelopmentConsoleOptions.ts +13 -0
- package/src/logging/contracts/EmailLogOptions.ts +9 -0
- package/src/logging/contracts/HttpExchangeMonitorOptions.ts +13 -0
- package/src/logging/contracts/LogTransportOptions.ts +10 -0
- package/src/logging/contracts/LoggingOptions.ts +12 -1
- package/src/logging/contracts/index.ts +4 -0
- package/src/logging/development/README.md +88 -0
- package/src/logging/drivers/PinoLoggerDriver.ts +72 -20
- package/src/logging/examples/runDevelopmentLogs.ts +36 -0
- package/src/logging/formatLogEmail.ts +24 -0
- package/src/logging/highlightQueueMessage.ts +38 -0
- package/src/logging/httpBodyCapture.ts +393 -0
- package/src/logging/index.ts +2 -0
- package/src/logging/redactLogEmail.ts +12 -0
- package/src/logging/registerHttpExchangeMonitor.ts +45 -0
- package/src/logging/transports/EmailLogTransport.ts +46 -0
- package/src/mail/Mail.ts +5 -0
- package/src/mail/MailDeliveryError.ts +8 -0
- package/src/mail/README.md +11 -1
- package/src/mail/index.ts +1 -0
- package/src/mail/transports/MailgunTransport.ts +2 -0
- package/src/mail/transports/ResendTransport.ts +24 -22
- package/src/media/MediaManager.ts +31 -10
- package/src/media/README.md +4 -0
- package/src/media/examples/runPrivateFiles.ts +2 -2
- package/src/network/BlockedUrlError.ts +19 -0
- package/src/network/README.md +133 -0
- package/src/network/assertPublicUrl.ts +77 -0
- package/src/network/contracts/GuardedFetch.ts +40 -0
- package/src/network/contracts/PublicUrlOptions.ts +17 -0
- package/src/network/contracts/index.ts +2 -0
- package/src/network/examples/runGuardedFetch.ts +35 -0
- package/src/network/guardedFetch.ts +150 -0
- package/src/network/index.ts +6 -0
- package/src/network/playwright/GuardedBrowserProxy.ts +172 -0
- package/src/network/playwright/contracts/GuardedBrowserContextOptions.ts +43 -0
- package/src/network/playwright/contracts/index.ts +1 -0
- package/src/network/playwright/index.ts +2 -0
- package/src/network/playwright/newGuardedBrowserContext.ts +74 -0
- package/src/network/privateNetworkAddresses.ts +166 -0
- package/src/network/publicAddressLookup.ts +49 -0
- package/src/notifications/Notifications.ts +105 -0
- package/src/notifications/README.md +59 -0
- package/src/notifications/contracts/Notification.ts +65 -0
- package/src/notifications/contracts/NotificationDelivery.ts +11 -0
- package/src/notifications/contracts/index.ts +2 -0
- package/src/notifications/examples/ReportReadyNotification.ts +31 -0
- package/src/notifications/index.ts +2 -0
- package/src/queue/JobRunAttempt.ts +17 -0
- package/src/queue/JobRunEvent.ts +16 -0
- package/src/queue/JobRunStoppedError.ts +8 -0
- package/src/queue/Queue.ts +112 -11
- package/src/queue/QueueTerminalError.ts +12 -0
- package/src/queue/QueueWorker.ts +86 -7
- package/src/queue/QueueWorkerReporter.ts +59 -0
- package/src/queue/QueueableJob.ts +2 -2
- package/src/queue/README.md +142 -1
- package/src/queue/RunnableJob.ts +272 -0
- package/src/queue/console.ts +54 -21
- package/src/queue/contracts/QueueDriver.ts +9 -0
- package/src/queue/contracts/QueueJobRunner.ts +4 -0
- package/src/queue/contracts/QueuePayload.ts +1 -1
- package/src/queue/contracts/QueueSelection.ts +11 -0
- package/src/queue/contracts/QueueService.ts +19 -4
- package/src/queue/contracts/QueueWorkerLifecycle.ts +2 -2
- package/src/queue/contracts/QueueWorkerSnapshot.ts +15 -0
- package/src/queue/contracts/QueueableJob.ts +7 -3
- package/src/queue/contracts/QueueableJobContract.ts +13 -0
- package/src/queue/contracts/index.ts +6 -0
- package/src/queue/drivers/DatabaseQueueDriver.ts +25 -3
- package/src/queue/drivers/RedisQueueDriver.ts +36 -0
- package/src/queue/examples/runQueueSelection.ts +34 -0
- package/src/queue/index.ts +7 -0
- package/src/queue/jobEnvelopeHasPrefix.ts +6 -0
- package/src/scheduler/README.md +50 -9
- package/src/scheduler/ScheduledEvent.ts +20 -5
- package/src/scheduler/ScheduledJob.ts +1 -1
- package/src/scheduler/Scheduler.ts +73 -27
- package/src/scheduler/SchedulerCheckpointRecord.ts +51 -0
- package/src/scheduler/SchedulerWorker.ts +54 -19
- package/src/scheduler/console.ts +3 -1
- package/src/scheduler/contracts/Schedule.ts +22 -0
- package/src/scheduler/contracts/Scheduler.ts +21 -6
- package/src/scheduler/contracts/SchedulerCheckpoint.ts +23 -0
- package/src/scheduler/contracts/SchedulerConsole.ts +5 -0
- package/src/scheduler/contracts/SchedulerWorker.ts +6 -1
- package/src/scheduler/contracts/index.ts +2 -0
- package/src/scheduler/examples/runSchedulerWindow.ts +54 -0
- package/src/scheduler/index.ts +1 -0
- package/src/server/App.ts +73 -10
- package/src/server/README.md +95 -2
- package/src/server/contracts/HttpErrorHandlerOptions.ts +29 -0
- package/src/server/contracts/index.ts +1 -0
- package/src/server/examples/createFirstServer.ts +5 -3
- package/src/server/index.ts +4 -0
- package/src/server/publicServerErrorMessage.ts +17 -0
- package/src/server/registerBrowserJsonFormatting.ts +94 -0
- package/src/server/registerHttpErrorHandler.ts +96 -0
- package/src/ssr/README.md +6 -0
- package/src/ssr/vite/contracts/ViteSsrOptions.ts +2 -0
- package/src/ssr/vite/fastifyViteSsr.ts +4 -3
- package/src/storage/drivers/FlystorageDisk.ts +2 -2
- package/src/storage/index.ts +2 -2
- package/src/websocket/README.md +458 -0
- package/src/websocket/WebSocketChannels.ts +99 -0
- package/src/websocket/WebSocketConnection.ts +162 -0
- package/src/websocket/WebSockets.ts +157 -0
- package/src/websocket/client/WebSocketClient.ts +188 -0
- package/src/websocket/client/index.ts +3 -0
- package/src/websocket/contracts/WebSocketChannel.ts +23 -0
- package/src/websocket/contracts/WebSocketClient.ts +48 -0
- package/src/websocket/contracts/WebSocketEndpoint.ts +46 -0
- package/src/websocket/contracts/WebSocketOptions.ts +50 -0
- package/src/websocket/contracts/WebSocketPresence.ts +6 -0
- package/src/websocket/contracts/WebSocketServiceOptions.ts +12 -0
- package/src/websocket/contracts/index.ts +6 -0
- package/src/websocket/defineChannel.ts +14 -0
- package/src/websocket/defineWebSocket.ts +15 -0
- package/src/websocket/examples/board/LiveBoard.ts +97 -0
- package/src/websocket/examples/board/SummarizeBoardJob.ts +52 -0
- package/src/websocket/examples/board/boardSnapshot.ts +16 -0
- package/src/websocket/examples/board/createBoardClient.ts +43 -0
- package/src/websocket/examples/board/createBoardStore.ts +58 -0
- package/src/websocket/examples/board/registerBoardRoutes.ts +31 -0
- package/src/websocket/examples/createChannelSync.ts +66 -0
- package/src/websocket/examples/deploymentEndpoint.ts +13 -0
- package/src/websocket/examples/deploymentSnapshot.ts +36 -0
- package/src/websocket/examples/resourceChannels.ts +18 -0
- package/src/websocket/examples/userEndpoint.ts +27 -0
- package/src/websocket/fastify.ts +39 -0
- package/src/websocket/index.ts +5 -0
- package/templates/AGENTS.md +33 -2
- /package/dist/flows/{FlowValueValidator.d.ts → flowValueValidator.d.ts} +0 -0
- /package/dist/flows/{FlowValueValidator.js → flowValueValidator.js} +0 -0
- /package/dist/storage/{mime.d.ts → mimeTypeFromPath.d.ts} +0 -0
- /package/dist/storage/{mime.js → mimeTypeFromPath.js} +0 -0
- /package/dist/storage/{contents.d.ts → storageContentsToBuffer.d.ts} +0 -0
- /package/dist/storage/{contents.js → storageContentsToBuffer.js} +0 -0
- /package/src/flows/{FlowValueValidator.ts → flowValueValidator.ts} +0 -0
- /package/src/storage/{mime.ts → mimeTypeFromPath.ts} +0 -0
- /package/src/storage/{contents.ts → storageContentsToBuffer.ts} +0 -0
package/src/index.ts
CHANGED
|
@@ -9,6 +9,7 @@ export {
|
|
|
9
9
|
export * from './cache';
|
|
10
10
|
export * from './config';
|
|
11
11
|
export * from './events';
|
|
12
|
+
export * from './health';
|
|
12
13
|
export * from './logging';
|
|
13
14
|
export * from './media';
|
|
14
15
|
export * from './security';
|
|
@@ -16,25 +17,4 @@ export * from './serialization';
|
|
|
16
17
|
export * from './url';
|
|
17
18
|
export * from './validation';
|
|
18
19
|
|
|
19
|
-
export
|
|
20
|
-
id: string;
|
|
21
|
-
name: string;
|
|
22
|
-
version: string;
|
|
23
|
-
description?: string;
|
|
24
|
-
icon?: string;
|
|
25
|
-
entry?: string;
|
|
26
|
-
adminPath?: string;
|
|
27
|
-
capabilities?: string[];
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface AppDefinition<TManifest extends AppManifest = AppManifest> {
|
|
31
|
-
manifest: TManifest;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function defineApp<TManifest extends AppManifest>(
|
|
35
|
-
manifest: TManifest,
|
|
36
|
-
): AppDefinition<TManifest> {
|
|
37
|
-
return {
|
|
38
|
-
manifest,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
20
|
+
export * from './apps';
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { StringDecoder } from 'node:string_decoder';
|
|
2
|
+
import { Writable } from 'node:stream';
|
|
3
|
+
import { stripVTControlCharacters } from 'node:util';
|
|
4
|
+
import { PrettyLogFormatter } from './PrettyLogFormatter';
|
|
5
|
+
import type * as logging from './contracts';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Owns grouped log output and a bounded live pending area in one terminal.
|
|
9
|
+
* Multi-process launchers must pipe every child's output through this owner;
|
|
10
|
+
* unrelated processes writing directly to the same TTY cannot be coordinated.
|
|
11
|
+
*/
|
|
12
|
+
export class DevelopmentConsole {
|
|
13
|
+
readonly #output: NonNullable<logging.DevelopmentConsoleOptions['output']>;
|
|
14
|
+
readonly #write: Writable['write'];
|
|
15
|
+
readonly #formatter: PrettyLogFormatter;
|
|
16
|
+
readonly #interactive: boolean;
|
|
17
|
+
readonly #restore: Array<() => void> = [];
|
|
18
|
+
#lines: string[] = [];
|
|
19
|
+
#timer?: ReturnType<typeof setInterval>;
|
|
20
|
+
#closed = false;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Creates a console owner without starting an HTTP server or taking stream ownership.
|
|
24
|
+
* @param options - Destination, terminal capability and stdio coordination.
|
|
25
|
+
*/
|
|
26
|
+
constructor(options: logging.DevelopmentConsoleOptions = {}) {
|
|
27
|
+
this.#output = options.output ?? process.stdout;
|
|
28
|
+
this.#write = this.#output.write.bind(this.#output);
|
|
29
|
+
this.#interactive = options.interactive ?? Boolean(this.#output.isTTY && process.env.TERM !== 'dumb');
|
|
30
|
+
this.#formatter = new PrettyLogFormatter(options.color ?? consoleColor(Boolean(this.#output.isTTY), process.env));
|
|
31
|
+
if (this.#interactive) {
|
|
32
|
+
if (options.coordinateStdio !== false && this.#output === process.stdout) {
|
|
33
|
+
this.#coordinate(process.stdout);
|
|
34
|
+
this.#coordinate(process.stderr);
|
|
35
|
+
}
|
|
36
|
+
this.#timer = setInterval(() => {
|
|
37
|
+
if (this.#lines.length && !this.#output.writableNeedDrain) this.#render('');
|
|
38
|
+
}, 250);
|
|
39
|
+
this.#timer.unref();
|
|
40
|
+
const resize = (): void => { this.#render(''); };
|
|
41
|
+
this.#output.on('resize', resize);
|
|
42
|
+
this.#restore.push(() => { this.#output.off('resize', resize); });
|
|
43
|
+
}
|
|
44
|
+
const exit = (): void => { this.close(); };
|
|
45
|
+
process.once('exit', exit);
|
|
46
|
+
this.#restore.push(() => { process.off('exit', exit); });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Accepts a complete Pino JSON line, retaining ordinary non-log text verbatim. */
|
|
50
|
+
write(line: string): void {
|
|
51
|
+
if (this.#closed) return;
|
|
52
|
+
try {
|
|
53
|
+
const record = JSON.parse(line);
|
|
54
|
+
if (record && typeof record === 'object' && typeof record.level === 'number') {
|
|
55
|
+
this.#render(this.#formatter.format(record));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
} catch { /* Non-JSON output from tools is ordinary terminal text. */ }
|
|
59
|
+
this.writeText(line);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Writes tool output above pending rows, removing controls that clear terminal history. */
|
|
63
|
+
writeText(text: string): void {
|
|
64
|
+
if (this.#closed || !text) return;
|
|
65
|
+
const safe = stripVTControlCharacters(text).replace(/\r/g, '').replace(/[\x00-\x08\x0b-\x1f\x7f]/g, '');
|
|
66
|
+
this.#render(safe.endsWith('\n') ? safe : `${safe}\n`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Creates a separately buffered child stdout/stderr sink, handling split UTF-8
|
|
71
|
+
* and final unterminated lines. Long non-JSON lines are forwarded in bounded chunks.
|
|
72
|
+
* @returns A writable input; end it when its child stream closes.
|
|
73
|
+
*/
|
|
74
|
+
createInput(): Writable {
|
|
75
|
+
const decoder = new StringDecoder('utf8');
|
|
76
|
+
let pending = '';
|
|
77
|
+
const consume = (text: string): void => {
|
|
78
|
+
pending += text;
|
|
79
|
+
let newline: number;
|
|
80
|
+
while ((newline = pending.indexOf('\n')) !== -1) {
|
|
81
|
+
this.write(pending.slice(0, newline));
|
|
82
|
+
pending = pending.slice(newline + 1);
|
|
83
|
+
}
|
|
84
|
+
if (pending.length > 256 * 1024) { this.writeText(pending); pending = ''; }
|
|
85
|
+
};
|
|
86
|
+
return new Writable({
|
|
87
|
+
write: (chunk, _encoding, callback) => { consume(decoder.write(chunk)); callback(); },
|
|
88
|
+
final: callback => { consume(decoder.end()); if (pending) this.write(pending); callback(); },
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Finalizes pending work from an exited child without disturbing other children. */
|
|
93
|
+
endSource(pid: number): void { this.#render(this.#formatter.finish(pid)); }
|
|
94
|
+
|
|
95
|
+
/** Waits for previously rendered output to reach the caller-owned destination. */
|
|
96
|
+
async flush(): Promise<void> {
|
|
97
|
+
await new Promise<void>((resolve, reject) => { this.#write('', error => error ? reject(error) : resolve()); });
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Clears only owned rows, releases timers/listeners and restores patched stdio. */
|
|
101
|
+
close(): void {
|
|
102
|
+
if (this.#closed) return;
|
|
103
|
+
clearInterval(this.#timer);
|
|
104
|
+
this.#render(this.#formatter.finish());
|
|
105
|
+
this.#closed = true;
|
|
106
|
+
for (const restore of this.#restore.reverse()) restore();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Replaces only the live footer and appends immutable completed output above it. */
|
|
110
|
+
#render(text: string): void {
|
|
111
|
+
if (this.#closed) return;
|
|
112
|
+
if (!this.#interactive) { if (text) this.#write(text); return; }
|
|
113
|
+
const columns = Math.max(1, this.#output.columns ?? 80);
|
|
114
|
+
const occupied = this.#lines.reduce((rows, line) => rows + Math.max(1, Math.ceil(line.length / columns)), 0);
|
|
115
|
+
const clear = occupied ? `\u001b[${occupied}A\r\u001b[J` : '';
|
|
116
|
+
const pending = this.#formatter.pending();
|
|
117
|
+
const maximum = Math.max(1, Math.min(5, (this.#output.rows ?? 24) - 3));
|
|
118
|
+
const visible = pending.slice(0, maximum);
|
|
119
|
+
if (pending.length > maximum) visible[maximum - 1] = `[http] … ${pending.length - maximum + 1} more requests waiting`;
|
|
120
|
+
// ASCII in mutable rows gives exact terminal-cell counts across resizes.
|
|
121
|
+
this.#lines = columns < 20 ? [] : visible.map(line => line.replace(/→/g, '->').replace(/[^\x20-\x7e]/g, ' ').slice(0, columns - 1));
|
|
122
|
+
const footer = this.#lines.length ? this.#lines.join('\n') + '\n' : '';
|
|
123
|
+
if (clear || text || footer) this.#write(clear + text + footer);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Serializes same-process writes with redraws while preserving write callbacks. */
|
|
127
|
+
#coordinate(stream: NodeJS.WriteStream): void {
|
|
128
|
+
const original = stream.write;
|
|
129
|
+
const write: typeof stream.write = (chunk: string | Uint8Array, encoding?: BufferEncoding | ((error?: Error | null) => void), callback?: (error?: Error | null) => void): boolean => {
|
|
130
|
+
this.writeText(typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString(typeof encoding === 'string' ? encoding : 'utf8'));
|
|
131
|
+
const done = typeof encoding === 'function' ? encoding : callback;
|
|
132
|
+
return this.#write('', done);
|
|
133
|
+
};
|
|
134
|
+
stream.write = write;
|
|
135
|
+
this.#restore.push(() => { if (stream.write === write) stream.write = original; });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Whether the pretty console uses colour. `NO_COLOR` turns it off; a set
|
|
141
|
+
* `FORCE_COLOR` (other than `0` or `false`) turns it on even without a TTY, as
|
|
142
|
+
* when a process manager pipes output into its own terminal view; otherwise a
|
|
143
|
+
* TTY decides.
|
|
144
|
+
*
|
|
145
|
+
* @param isTTY - Whether the output stream is a terminal.
|
|
146
|
+
* @param env - Process environment.
|
|
147
|
+
* @returns Whether to emit ANSI colours.
|
|
148
|
+
*/
|
|
149
|
+
export function consoleColor(isTTY: boolean, env: NodeJS.ProcessEnv): boolean {
|
|
150
|
+
if (env.NO_COLOR !== undefined) return false;
|
|
151
|
+
const force = env.FORCE_COLOR;
|
|
152
|
+
if (force === '0' || force === 'false') return false;
|
|
153
|
+
return force !== undefined || isTTY;
|
|
154
|
+
}
|
package/src/logging/Log.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ChildLoggerOptions } from 'pino';
|
|
2
|
+
import type { Mail } from '../mail';
|
|
2
3
|
|
|
3
4
|
import { PinoLoggerDriver } from './drivers/PinoLoggerDriver';
|
|
4
5
|
import type * as logging from './contracts';
|
|
@@ -19,9 +20,11 @@ export class Log implements logging.Logger {
|
|
|
19
20
|
* Creates the application logger from explicit options or the Pino driver.
|
|
20
21
|
*
|
|
21
22
|
* @param options - Logging level, destinations, context, and driver overrides.
|
|
23
|
+
* @param mail - Lazy application Mail resolver, required when email is configured.
|
|
22
24
|
*/
|
|
23
|
-
constructor(options: logging.LoggingOptions = {}) {
|
|
24
|
-
|
|
25
|
+
constructor(options: logging.LoggingOptions = {}, mail?: () => Mail) {
|
|
26
|
+
if (options.driver && options.transports !== undefined) throw new Error('Configured logging transports require the default Pino driver.');
|
|
27
|
+
this.#driver = options.driver ?? new PinoLoggerDriver(options, undefined, mail);
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
/** Returns the current trace function, respecting runtime level changes. */
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { STATUS_CODES } from 'node:http';
|
|
2
|
+
import { highlightQueueMessage } from './highlightQueueMessage';
|
|
3
|
+
|
|
4
|
+
/** Minimal retained HTTP context, bounded independently of the original log sinks. */
|
|
5
|
+
interface PendingRequest {
|
|
6
|
+
record: Record<string, unknown>;
|
|
7
|
+
route: string;
|
|
8
|
+
started: number;
|
|
9
|
+
exchange?: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Groups redacted HTTP lifecycle records while preserving ordinary diagnostic logs. */
|
|
13
|
+
export class PrettyLogFormatter {
|
|
14
|
+
readonly #requests = new Map<string, PendingRequest>();
|
|
15
|
+
readonly #ended = new Set<string>();
|
|
16
|
+
readonly #color: boolean;
|
|
17
|
+
|
|
18
|
+
/** Creates a formatter; terminal capability is resolved by the console owner. */
|
|
19
|
+
constructor(color = false) { this.#color = color; }
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Accepts one redacted Pino record and returns any completed output.
|
|
23
|
+
* Request context is bounded to 1,000 entries. Eviction is explicitly reported;
|
|
24
|
+
* later completions still print even when their earlier context is unavailable.
|
|
25
|
+
*/
|
|
26
|
+
format(record: Record<string, unknown>, now = Date.now()): string {
|
|
27
|
+
const message = record.msg;
|
|
28
|
+
const key = requestKey(record);
|
|
29
|
+
const request = object(record.req);
|
|
30
|
+
const exchange = object(record.httpExchange);
|
|
31
|
+
const route = requestRoute(request);
|
|
32
|
+
if (message === 'incoming request' && record.reqId != null && route) {
|
|
33
|
+
this.#ended.delete(key);
|
|
34
|
+
let evicted = '';
|
|
35
|
+
if (this.#requests.size >= 1000) {
|
|
36
|
+
const oldest = this.#requests.keys().next().value!;
|
|
37
|
+
const pending = this.#requests.get(oldest)!;
|
|
38
|
+
evicted = this.#http(pending.record, pending, 'tracking limit reached; response still pending');
|
|
39
|
+
this.#requests.delete(oldest);
|
|
40
|
+
}
|
|
41
|
+
this.#requests.set(key, { record, route, started: now });
|
|
42
|
+
return evicted;
|
|
43
|
+
}
|
|
44
|
+
if (message === 'request exchange' && exchange && Number(record.level ?? 30) <= 30) {
|
|
45
|
+
if (record.reqId != null && this.#ended.has(key)) return '';
|
|
46
|
+
const pending = this.#requests.get(key);
|
|
47
|
+
if (pending) {
|
|
48
|
+
pending.exchange = exchange;
|
|
49
|
+
return '';
|
|
50
|
+
}
|
|
51
|
+
// A missing arrival (e.g. a filtered log level) must not lose the payload.
|
|
52
|
+
return this.#http(record, { record, route: requestRoute(object(exchange.request)) || 'Request', started: now, exchange });
|
|
53
|
+
}
|
|
54
|
+
if (['request completed', 'request errored', 'request aborted', 'request timed out'].includes(String(message))) {
|
|
55
|
+
if (record.reqId != null) {
|
|
56
|
+
if (this.#ended.has(key)) return '';
|
|
57
|
+
if (this.#ended.size >= 1000) this.#ended.delete(this.#ended.values().next().value!);
|
|
58
|
+
this.#ended.add(key);
|
|
59
|
+
}
|
|
60
|
+
const pending = this.#requests.get(key);
|
|
61
|
+
this.#requests.delete(key);
|
|
62
|
+
const outcome = message === 'request completed' ? undefined : message === 'request errored' ? 'failed' : message === 'request aborted' ? 'cancelled' : 'timed out';
|
|
63
|
+
return this.#http(record, pending ?? { record, route: route || 'Request', started: now }, outcome);
|
|
64
|
+
}
|
|
65
|
+
const severity = Number(record.level ?? 30);
|
|
66
|
+
const category = severity >= 50 ? 'error' : severity >= 40 ? 'warn' : typeof record.component === 'string' ? record.component : severity <= 20 ? 'debug' : 'app';
|
|
67
|
+
const context = Object.entries(record).filter(([key, value]) => !hiddenFields.has(key) && value != null).slice(0, 8).map(([key, value]) => `${compact(key, 40)}=${compact(value, 100)}`).join(' ');
|
|
68
|
+
const details = errorDetails(record.err ?? record.error);
|
|
69
|
+
return `${this.#paint(timestamp(record.time), 90)} ${this.#paint(`[${compact(category, 30)}]`, severity >= 50 ? 31 : severity >= 40 ? 33 : 36)} ${this.#message(compact(record.msg ?? '', 500))}${context ? ` ${this.#paint(context, 90)}` : ''}\n${details ? indent(details) + '\n' : ''}`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Returns waiting rows without mutating completed output or request order. */
|
|
73
|
+
pending(now = Date.now()): string[] {
|
|
74
|
+
return [...this.#requests.values()].map(request => {
|
|
75
|
+
const elapsed = Math.max(0, now - request.started);
|
|
76
|
+
return `[http] ${request.route} ${elapsed >= 5000 ? 'slow · ' : ''}waiting · ${(elapsed / 1000).toFixed(1)} s #${request.record.reqId}`;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Finalizes requests whose transport ended before a completion record arrived. */
|
|
81
|
+
finish(sourcePid?: number): string {
|
|
82
|
+
let output = '';
|
|
83
|
+
for (const [key, pending] of this.#requests) {
|
|
84
|
+
if (sourcePid !== undefined && pending.record.pid !== sourcePid) continue;
|
|
85
|
+
output += this.#http(pending.record, pending, 'interrupted · process stopped before response');
|
|
86
|
+
this.#requests.delete(key);
|
|
87
|
+
}
|
|
88
|
+
return output;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Renders a single immutable HTTP block, including readable payload previews. */
|
|
92
|
+
#http(record: Record<string, unknown>, pending: PendingRequest, outcome?: string): string {
|
|
93
|
+
const status = object(record.res)?.statusCode ?? object(pending.exchange?.response)?.statusCode;
|
|
94
|
+
const statusText = typeof status === 'number' ? `${status} ${STATUS_CODES[status] ?? ''}`.trim() : '';
|
|
95
|
+
const elapsed = typeof record.responseTime === 'number' && Number.isFinite(record.responseTime) ? ` · ${Math.round(record.responseTime)} ms` : '';
|
|
96
|
+
const tone = outcome || Number(status) >= 500 ? 31 : Number(status) >= 400 ? 33 : 32;
|
|
97
|
+
const reference = record.reqId == null ? '' : ` #${compact(record.reqId, 60)}`;
|
|
98
|
+
const bodies = bodyPreview(object(object(pending.exchange?.request)?.body), '> request') + bodyPreview(object(object(pending.exchange?.response)?.body), '< response');
|
|
99
|
+
const details = errorDetails(record.err ?? record.error);
|
|
100
|
+
return `${this.#paint(timestamp(pending.record.time), 90)} ${this.#paint('[http]', 36)} ${compact(pending.route, 240)} ${this.#paint(outcome ?? (statusText || 'response'), tone)}${elapsed}${this.#paint(reference, 90)}\n${bodies}${details ? indent(details) + '\n' : ''}\n`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Colours structural labels only, never application-controlled terminal escapes. */
|
|
104
|
+
#paint(text: string, code: number | string): string { return this.#color ? `\u001b[${code}m${text}\u001b[0m` : text; }
|
|
105
|
+
|
|
106
|
+
/** Highlights queue states and job labels when colouring. */
|
|
107
|
+
#message(text: string): string { return this.#color ? highlightQueueMessage(text, (part, code) => this.#paint(part, code)) : text; }
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const hiddenFields = new Set(['level', 'time', 'pid', 'hostname', 'source', 'environment', 'release', 'component', 'msg', 'req', 'res', 'httpExchange', 'responseTime', 'err', 'error']);
|
|
111
|
+
|
|
112
|
+
/** Separates processes and sources that independently allocate Fastify request IDs. */
|
|
113
|
+
function requestKey(record: Record<string, unknown>): string { return JSON.stringify([record.pid, record.source, record.reqId]); }
|
|
114
|
+
|
|
115
|
+
/** Narrows optional parsed context without trusting arbitrary application values. */
|
|
116
|
+
function object(value: unknown): Record<string, unknown> | undefined { return value !== null && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : undefined; }
|
|
117
|
+
|
|
118
|
+
/** Extracts the method and URL without headers or payload duplication. */
|
|
119
|
+
function requestRoute(request: Record<string, unknown> | undefined): string { return typeof request?.method === 'string' && typeof request.url === 'string' ? `${request.method} → ${request.url}` : ''; }
|
|
120
|
+
|
|
121
|
+
/** Formats local wall time with a stable fallback for non-Pino input. */
|
|
122
|
+
function timestamp(value: unknown): string {
|
|
123
|
+
const date = new Date(typeof value === 'number' || typeof value === 'string' ? value : NaN);
|
|
124
|
+
return Number.isNaN(date.getTime()) ? '--:--:--' : [date.getHours(), date.getMinutes(), date.getSeconds()].map(part => String(part).padStart(2, '0')).join(':');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** Prevents control injection and bounds single-line summaries. */
|
|
128
|
+
function compact(value: unknown, limit: number): string {
|
|
129
|
+
const text = clean(typeof value === 'string' ? value : JSON.stringify(value) ?? String(value)).replace(/\s+/g, ' ');
|
|
130
|
+
return text.length > limit ? `${text.slice(0, limit - 1)}…` : text;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Strips terminal controls while retaining readable line breaks. */
|
|
134
|
+
function clean(text: string): string { return text.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g, '').replace(/[\u0000-\u0009\u000b-\u001f\u007f-\u009f]/g, ''); }
|
|
135
|
+
|
|
136
|
+
/** Indents diagnostic text consistently beneath its owning request or message. */
|
|
137
|
+
function indent(text: string): string { return text.split('\n').map(line => ` ${line}`).join('\n'); }
|
|
138
|
+
|
|
139
|
+
/** Shows small JSON inline and larger JSON as a bounded, explicitly shortened preview. */
|
|
140
|
+
function bodyPreview(body: Record<string, unknown> | undefined, label: string): string {
|
|
141
|
+
if (!body || body.kind === 'empty') return '';
|
|
142
|
+
let text: string;
|
|
143
|
+
if (body.value === undefined) text = String(body.note ?? `${body.kind} body omitted`);
|
|
144
|
+
else if (body.kind === 'json' && !body.truncated) {
|
|
145
|
+
const expanded = JSON.stringify(body.value, null, 2);
|
|
146
|
+
const inline = expanded.replace(/\n\s*/g, ' ');
|
|
147
|
+
text = inline.length <= 90 ? inline : expanded;
|
|
148
|
+
} else text = String(body.value);
|
|
149
|
+
const lines = clean(text).split('\n');
|
|
150
|
+
const visible = lines.slice(0, 20).map(line => line.length > 160 ? `${line.slice(0, 159)}… [line shortened]` : line);
|
|
151
|
+
if (lines.length > 20) visible.push(`… ${lines.length - 20} more lines (full captured body in JSON logs/devtools)`);
|
|
152
|
+
if (body.truncated) visible.push(`… capture truncated (${body.sizeBytes ?? 'unknown'} bytes before limit)`);
|
|
153
|
+
return ` ${label}\n${indent(visible.join('\n'))}\n`;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** Preserves bounded error stacks and nested causes without terminal control sequences. */
|
|
157
|
+
function errorDetails(value: unknown, depth = 0): string {
|
|
158
|
+
if (value == null || depth > 4) return '';
|
|
159
|
+
const error = object(value);
|
|
160
|
+
if (!error) return compact(value, 2000);
|
|
161
|
+
const stack = typeof error.stack === 'string' ? clean(error.stack) : compact(`${error.type ?? 'Error'}: ${error.message ?? JSON.stringify(error)}`, 2000);
|
|
162
|
+
const detail = stack.length > 16000 ? stack.slice(0, 16000) + '\n… stack shortened' : stack;
|
|
163
|
+
const cause = errorDetails(error.cause, depth + 1);
|
|
164
|
+
return `${detail}${cause ? `\nCaused by: ${cause}` : ''}`;
|
|
165
|
+
}
|
package/src/logging/README.md
CHANGED
|
@@ -1,139 +1,82 @@
|
|
|
1
1
|
# Logging
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
`app().log`. Pino is the default driver, while the framework owns service discovery,
|
|
5
|
-
configuration, redaction, transport selection, and shutdown.
|
|
3
|
+
`app().log` uses Pino; the framework owns configuration, redaction, transports and shutdown.
|
|
6
4
|
|
|
7
|
-
##
|
|
5
|
+
## Writing logs
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
```sh
|
|
12
|
-
mkdir -p examples
|
|
13
|
-
cp -R node_modules/@db3.ai/app/src/logging/examples/. examples/
|
|
14
|
-
npx tsx examples/runNoteLogs.ts
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
This captures the real Pino driver's output in a writable stream, with devtools HTTP delivery disabled. Expect three records: `Note saved`, `Summary failed`, and `Diagnostics enabled`. The first debug message is filtered, then changing `log.level` enables debug output. Changing it to silent suppresses later errors. The output omits unstable metadata and stack text only for readability.
|
|
18
|
-
|
|
19
|
-
The [Logging guide](https://db3.ai/docs/logging#testing) contains the exact consumer test. Save it as `tests/logging/runNoteLogs.test.ts` and run:
|
|
20
|
-
|
|
21
|
-
```sh
|
|
22
|
-
npx vitest run tests/logging/runNoteLogs.test.ts
|
|
23
|
-
npx tsc --noEmit --target ES2022 --module ESNext --moduleResolution Bundler --types node --skipLibCheck examples/*.ts
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
The test asserts structured context, error serialization, level changes and the absence of synthetic password/token/provider-key values. It uses the real logger, not a framework mock. This does not prove remote log ingestion or retention.
|
|
27
|
-
|
|
28
|
-
## Writing Logs
|
|
29
|
-
|
|
30
|
-
Prefer a short message plus structured fields:
|
|
31
|
-
|
|
32
|
-
```ts
|
|
33
|
-
app().log.info({
|
|
34
|
-
websiteId,
|
|
35
|
-
pageCount,
|
|
36
|
-
}, 'Website crawl completed');
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
Pass errors under `err` so Pino retains their name, message, stack, and cause:
|
|
7
|
+
Use structured context and put exceptions under `err` to retain name, message, stack and cause:
|
|
40
8
|
|
|
41
9
|
```ts
|
|
42
|
-
app().log.error({
|
|
43
|
-
|
|
44
|
-
websiteId,
|
|
45
|
-
}, 'Website crawl failed');
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
Use child loggers for context shared by several records:
|
|
49
|
-
|
|
50
|
-
```ts
|
|
51
|
-
const log = app().log.child({
|
|
52
|
-
component: 'crawler',
|
|
53
|
-
websiteId,
|
|
54
|
-
});
|
|
55
|
-
|
|
10
|
+
app().log.error({ err: error, websiteId }, 'Website crawl failed');
|
|
11
|
+
const log = app().log.child({ component: 'crawler', websiteId });
|
|
56
12
|
log.info('Crawl started');
|
|
57
|
-
log.debug({ url }, 'Page discovered');
|
|
58
13
|
```
|
|
59
14
|
|
|
60
|
-
|
|
61
|
-
|
|
15
|
+
Levels are `trace`, `debug`, `info`, `warn`, `error`, `fatal` and `silent`.
|
|
16
|
+
The default is `info`, or `silent` in tests. Application boundaries must log exceptions explicitly.
|
|
62
17
|
|
|
63
|
-
##
|
|
64
|
-
|
|
65
|
-
Configure logging through `AppOptions.log`:
|
|
18
|
+
## Configuration
|
|
66
19
|
|
|
67
20
|
```ts
|
|
68
21
|
const app = new App({
|
|
69
22
|
log: {
|
|
70
|
-
level: '
|
|
23
|
+
level: 'info',
|
|
71
24
|
source: 'example-api',
|
|
72
|
-
bindings: {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
25
|
+
bindings: { release: process.env.RELEASE_SHA },
|
|
26
|
+
transports: [
|
|
27
|
+
{ type: 'console' },
|
|
28
|
+
{ type: 'file', destination: '/storage/logs/app.jsonl' },
|
|
29
|
+
{ type: 'email', level: 'error', to: 'operator@example.com' },
|
|
30
|
+
],
|
|
76
31
|
},
|
|
77
32
|
});
|
|
78
33
|
```
|
|
79
34
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
- `PLATFORM_LOG_DEVTOOLS`: explicitly enables or disables devtools delivery.
|
|
85
|
-
- `PLATFORM_DEVTOOLS_EVENTS_URL`: complete development ingestion endpoint.
|
|
86
|
-
- `PLATFORM_DEVTOOLS_HOST`: development service host when no URL is supplied.
|
|
87
|
-
- `PLATFORM_DEVTOOLS_API_PORT`: development service port, defaulting to `9998`.
|
|
88
|
-
|
|
89
|
-
Newline-delimited JSON is written to standard output by default. Interactive
|
|
90
|
-
development also enables the framework devtools transport automatically. Tests
|
|
91
|
-
do not enable network delivery unless explicitly configured.
|
|
35
|
+
`transports` replaces defaults; `[]` disables output. Omit it for legacy/environment
|
|
36
|
+
defaults. Route thresholds combine with the logger minimum; email defaults to `error`,
|
|
37
|
+
others inherit it. `silent` disables a route. Pino permits one console and devtools via
|
|
38
|
+
`{ type: 'devtools', options: { url } }`.
|
|
92
39
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
instrumentation:
|
|
98
|
-
|
|
99
|
-
```text
|
|
100
|
-
app().log
|
|
101
|
-
-> Pino worker transport
|
|
102
|
-
-> POST /api/events
|
|
103
|
-
-> development event store
|
|
104
|
-
-> WebSocket
|
|
105
|
-
-> Logs panel
|
|
106
|
-
```
|
|
40
|
+
Environment defaults: `PLATFORM_LOG_LEVEL`, `PLATFORM_LOG_SOURCE`, `PLATFORM_LOG_FORMAT`
|
|
41
|
+
(`auto`, `pretty`, `json`), `PLATFORM_LOG_FILE`, `PLATFORM_LOG_DEVTOOLS`,
|
|
42
|
+
`PLATFORM_DEVTOOLS_EVENTS_URL`, `PLATFORM_DEVTOOLS_HOST`, `PLATFORM_DEVTOOLS_API_PORT` (9998).
|
|
43
|
+
Legacy `log.file` adds a file alongside stdout unless `console: false`.
|
|
107
44
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
delivery pauses for one second. Logging therefore remains observability rather
|
|
112
|
-
than an application dependency.
|
|
45
|
+
Terminals show pending requests and grouped exchanges; production/tests/pipes use JSON.
|
|
46
|
+
`consoleFormat` overrides presentation. Files/devtools stay structured; test devtools
|
|
47
|
+
requires opt-in. See [development logging](development/README.md).
|
|
113
48
|
|
|
114
|
-
|
|
115
|
-
entrypoints should always use the framework shutdown lifecycle rather than
|
|
116
|
-
calling `process.exit()` directly after writing a log.
|
|
49
|
+
## Email
|
|
117
50
|
|
|
118
|
-
|
|
51
|
+
Every matching record, including repeats, gets a separate submission through `app.mail`.
|
|
52
|
+
Logging formats redacted primitive context and exception message/stack/cause as text and
|
|
53
|
+
escaped HTML, excluding arbitrary nested payloads. Common credentials are masked.
|
|
54
|
+
There is no grouping, deduplication, cooldown, retry or database dependency.
|
|
55
|
+
Operation backoff remains the caller's responsibility.
|
|
119
56
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
57
|
+
Sends are asynchronous and ordered; flush/close drains them. Abrupt exits lose pending
|
|
58
|
+
mail. Refusals go to stderr without recursive emails; later sends continue. Keep raw logs:
|
|
59
|
+
acceptance is not inbox delivery. App supplies the lazy Mail resolver accepted by `Log`.
|
|
60
|
+
Database, PostHog and OpenTelemetry transports are not included.
|
|
123
61
|
|
|
124
|
-
|
|
125
|
-
payment details, or personal data. Prefer explicit safe fields over logging
|
|
126
|
-
large application objects.
|
|
62
|
+
## Delivery and shutdown
|
|
127
63
|
|
|
128
|
-
|
|
64
|
+
Devtools sends worker-thread HTTP batches to `/api/events`: at most 25 records per batch,
|
|
65
|
+
100ms partial-batch wait, 1,000 pending events. Overflow drops oldest events; failed batches
|
|
66
|
+
are discarded and delivery pauses one second. Its event store feeds the Logs panel.
|
|
129
67
|
|
|
130
|
-
`
|
|
68
|
+
`App.close()` flushes logging and closes owned workers; use it instead of immediate
|
|
69
|
+
`process.exit()`. Caller-supplied streams remain caller-owned. File transports create parent
|
|
70
|
+
directories; mount files persistently and manage rotation, retention, permissions and capacity.
|
|
71
|
+
`Log.level` changes affect subsequent method lookups, not previously captured functions.
|
|
131
72
|
|
|
132
|
-
##
|
|
73
|
+
## Security and boundaries
|
|
133
74
|
|
|
134
|
-
|
|
135
|
-
|
|
75
|
+
Pino removes common credential, authorization and cookie paths. Add paths with `log.redact`;
|
|
76
|
+
`false` disables protection. Path redaction cannot remove arbitrary secret substrings,
|
|
77
|
+
private prose or unfamiliar nested fields. Avoid sensitive messages, URL queries and bodies;
|
|
78
|
+
log explicit safe fields and test application-specific redaction.
|
|
136
79
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
80
|
+
Logs must not trigger application behavior. Database, queue and flow events keep their
|
|
81
|
+
own typed contracts; correlate them using request/job/website/flow IDs and component fields.
|
|
82
|
+
See the [API](https://db3.ai/docs/logging-api) for contracts.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { DevelopmentConsole } from './DevelopmentConsole';
|
|
2
|
+
|
|
3
|
+
let active: DevelopmentConsole | undefined;
|
|
4
|
+
let leases = 0;
|
|
5
|
+
|
|
6
|
+
/** Shares one terminal owner across application loggers in the same process. */
|
|
7
|
+
export function acquireDevelopmentConsole(): { console: DevelopmentConsole; release: () => void } {
|
|
8
|
+
active ??= new DevelopmentConsole();
|
|
9
|
+
leases++;
|
|
10
|
+
let released = false;
|
|
11
|
+
return {
|
|
12
|
+
console: active,
|
|
13
|
+
release: () => {
|
|
14
|
+
if (released) return;
|
|
15
|
+
released = true;
|
|
16
|
+
if (--leases === 0) { active?.close(); active = undefined; }
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Writable } from 'node:stream';
|
|
2
|
+
|
|
3
|
+
/** Terminal capabilities for the one renderer that owns a development output stream. */
|
|
4
|
+
export interface DevelopmentConsoleOptions {
|
|
5
|
+
/** Output destination; defaults to process.stdout. The caller retains stream ownership. */
|
|
6
|
+
output?: Writable & { isTTY?: boolean; columns?: number; rows?: number };
|
|
7
|
+
/** Enable pending-row redraws. Defaults to the output's terminal capability. */
|
|
8
|
+
interactive?: boolean;
|
|
9
|
+
/** Enable structural ANSI colours. Defaults to terminal support, respecting NO_COLOR. */
|
|
10
|
+
color?: boolean;
|
|
11
|
+
/** Coordinate console.log/warn and direct stdout/stderr writes in this process. Defaults to true for interactive stdout. */
|
|
12
|
+
coordinateStdio?: boolean;
|
|
13
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { MailAddress } from '../../mail';
|
|
2
|
+
|
|
3
|
+
/** Sends each error or fatal record to the configured operator through the application's Mail service. */
|
|
4
|
+
export interface EmailLogOptions {
|
|
5
|
+
/** Explicit operator destination; disabled unless configured. */
|
|
6
|
+
to: MailAddress | MailAddress[];
|
|
7
|
+
/** Optional subject prefix identifying the application. Defaults to Application error. */
|
|
8
|
+
subjectPrefix?: string;
|
|
9
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FastifyRequest } from 'fastify';
|
|
2
|
+
|
|
3
|
+
/** Development HTTP payload capture policy, owned by the host application. */
|
|
4
|
+
export interface HttpExchangeMonitorOptions {
|
|
5
|
+
/** Defaults to NODE_ENV; production and test never capture payloads. */
|
|
6
|
+
environment?: string;
|
|
7
|
+
/** Explicitly disables body capture independently of console presentation. */
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
/** Maximum bytes retained per body; defaults to 16 KiB, capped at 64 KiB. */
|
|
10
|
+
maxBodyBytes?: number;
|
|
11
|
+
/** Excludes sensitive routes from payload capture. Request summaries remain governed by route logging. */
|
|
12
|
+
exclude?: (request: FastifyRequest) => boolean;
|
|
13
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { EmailLogOptions } from './EmailLogOptions';
|
|
2
|
+
import type { LogLevel } from './Logger';
|
|
3
|
+
import type { DevtoolsLogOptions } from './LoggingOptions';
|
|
4
|
+
|
|
5
|
+
/** A configured destination receiving records at its minimum severity or above. */
|
|
6
|
+
export type LogTransportOptions =
|
|
7
|
+
| { type: 'console'; level?: LogLevel }
|
|
8
|
+
| { type: 'file'; level?: LogLevel; destination: string }
|
|
9
|
+
| ({ type: 'email'; level?: LogLevel } & EmailLogOptions)
|
|
10
|
+
| { type: 'devtools'; level?: LogLevel; options?: DevtoolsLogOptions };
|