@db3.ai/app 0.1.0-beta.1 → 0.1.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (653) hide show
  1. package/README.md +68 -9
  2. package/agent-instructions.md +76 -0
  3. package/dist/ai/AIErrors.d.ts +7 -1
  4. package/dist/ai/AIErrors.js +8 -1
  5. package/dist/ai/AIFailover.d.ts +10 -0
  6. package/dist/ai/AIFailover.js +3 -2
  7. package/dist/ai/AIProviderAdmission.d.ts +101 -0
  8. package/dist/ai/AIProviderAdmission.js +336 -0
  9. package/dist/ai/AIRateLimiter.d.ts +11 -2
  10. package/dist/ai/AIRateLimiter.js +125 -10
  11. package/dist/ai/AIRequestTrackingError.d.ts +22 -0
  12. package/dist/ai/AIRequestTrackingError.js +33 -0
  13. package/dist/ai/Agent.d.ts +7 -7
  14. package/dist/ai/Agent.js +84 -56
  15. package/dist/ai/Ai.d.ts +11 -3
  16. package/dist/ai/Ai.js +94 -44
  17. package/dist/ai/OpenAIProviderError.js +1 -1
  18. package/dist/ai/ProviderSseObserver.d.ts +19 -0
  19. package/dist/ai/ProviderSseObserver.js +98 -0
  20. package/dist/ai/aiServiceTier.d.ts +5 -0
  21. package/dist/ai/aiServiceTier.js +14 -0
  22. package/dist/ai/chunkEmbeddingText.d.ts +14 -0
  23. package/dist/ai/chunkEmbeddingText.js +147 -0
  24. package/dist/ai/contracts/AI.d.ts +16 -0
  25. package/dist/ai/contracts/AIRequestErrorDiagnostics.d.ts +12 -0
  26. package/dist/ai/contracts/AIRequestErrorDiagnostics.js +1 -0
  27. package/dist/ai/contracts/AIServiceTier.d.ts +2 -0
  28. package/dist/ai/contracts/AIServiceTier.js +1 -0
  29. package/dist/ai/contracts/Agent.d.ts +3 -0
  30. package/dist/ai/contracts/EmbeddingTextChunk.d.ts +25 -0
  31. package/dist/ai/contracts/EmbeddingTextChunk.js +1 -0
  32. package/dist/ai/contracts/Pricing.d.ts +7 -1
  33. package/dist/ai/contracts/Providers.d.ts +2 -0
  34. package/dist/ai/contracts/index.d.ts +2 -0
  35. package/dist/ai/contracts/index.js +1 -0
  36. package/dist/ai/index.d.ts +8 -2
  37. package/dist/ai/index.js +5 -2
  38. package/dist/ai/{Models.d.ts → modelPricing.d.ts} +2 -2
  39. package/dist/ai/{Models.js → modelPricing.js} +38 -4
  40. package/dist/apps/AppInstallation.d.ts +21 -0
  41. package/dist/apps/AppInstallation.js +16 -0
  42. package/dist/apps/AppRouteError.d.ts +6 -0
  43. package/dist/apps/AppRouteError.js +10 -0
  44. package/dist/apps/AppService.d.ts +24 -0
  45. package/dist/apps/AppService.js +21 -0
  46. package/dist/apps/Apps.d.ts +59 -0
  47. package/dist/apps/Apps.js +566 -0
  48. package/dist/apps/appsPlugin.d.ts +3 -0
  49. package/dist/apps/appsPlugin.js +36 -0
  50. package/dist/apps/commands/disableApp.d.ts +2 -0
  51. package/dist/apps/commands/disableApp.js +5 -0
  52. package/dist/apps/commands/enableApp.d.ts +2 -0
  53. package/dist/apps/commands/enableApp.js +5 -0
  54. package/dist/apps/commands/index.d.ts +10 -0
  55. package/dist/apps/commands/index.js +27 -0
  56. package/dist/apps/commands/installApp.d.ts +2 -0
  57. package/dist/apps/commands/installApp.js +5 -0
  58. package/dist/apps/commands/listApps.d.ts +2 -0
  59. package/dist/apps/commands/listApps.js +5 -0
  60. package/dist/apps/commands/makeAppMigration.d.ts +2 -0
  61. package/dist/apps/commands/makeAppMigration.js +9 -0
  62. package/dist/apps/commands/rollbackApp.d.ts +2 -0
  63. package/dist/apps/commands/rollbackApp.js +5 -0
  64. package/dist/apps/commands/uninstallApp.d.ts +2 -0
  65. package/dist/apps/commands/uninstallApp.js +5 -0
  66. package/dist/apps/contracts/AppAction.d.ts +2 -0
  67. package/dist/apps/contracts/AppAction.js +1 -0
  68. package/dist/apps/contracts/AppDefinition.d.ts +45 -0
  69. package/dist/apps/contracts/AppDefinition.js +1 -0
  70. package/dist/apps/contracts/AppDescription.d.ts +32 -0
  71. package/dist/apps/contracts/AppDescription.js +1 -0
  72. package/dist/apps/contracts/AppManifest.d.ts +30 -0
  73. package/dist/apps/contracts/AppManifest.js +1 -0
  74. package/dist/apps/contracts/AppNavigation.d.ts +9 -0
  75. package/dist/apps/contracts/AppNavigation.js +1 -0
  76. package/dist/apps/contracts/AppNavigationBadge.d.ts +6 -0
  77. package/dist/apps/contracts/AppNavigationBadge.js +1 -0
  78. package/dist/apps/contracts/AppNavigationContext.d.ts +8 -0
  79. package/dist/apps/contracts/AppNavigationContext.js +1 -0
  80. package/dist/apps/contracts/AppNavigationResult.d.ts +12 -0
  81. package/dist/apps/contracts/AppNavigationResult.js +1 -0
  82. package/dist/apps/contracts/AppRoute.d.ts +19 -0
  83. package/dist/apps/contracts/AppRoute.js +1 -0
  84. package/dist/apps/contracts/DiscoveredApp.d.ts +10 -0
  85. package/dist/apps/contracts/DiscoveredApp.js +1 -0
  86. package/dist/apps/contracts/InstalledApps.d.ts +3 -0
  87. package/dist/apps/contracts/InstalledApps.js +1 -0
  88. package/dist/apps/contracts/index.d.ts +11 -0
  89. package/dist/apps/contracts/index.js +1 -0
  90. package/dist/apps/defineApp.d.ts +7 -0
  91. package/dist/apps/defineApp.js +8 -0
  92. package/dist/apps/discoverApps.d.ts +3 -0
  93. package/dist/apps/discoverApps.js +62 -0
  94. package/dist/apps/fastify.d.ts +1 -0
  95. package/dist/apps/fastify.js +1 -0
  96. package/dist/apps/index.d.ts +7 -0
  97. package/dist/apps/index.js +7 -0
  98. package/dist/apps/normalizeAppNavigation.d.ts +3 -0
  99. package/dist/apps/normalizeAppNavigation.js +30 -0
  100. package/dist/apps/registerAppRoutes.d.ts +6 -0
  101. package/dist/apps/registerAppRoutes.js +52 -0
  102. package/dist/apps/validateAppDefinitions.d.ts +3 -0
  103. package/dist/apps/validateAppDefinitions.js +65 -0
  104. package/dist/apps/vite.d.ts +1 -0
  105. package/dist/apps/vite.js +1 -0
  106. package/dist/apps/writeAppTypes.d.ts +2 -0
  107. package/dist/apps/writeAppTypes.js +13 -0
  108. package/dist/auth/Auth.d.ts +18 -0
  109. package/dist/auth/Auth.js +89 -13
  110. package/dist/auth/PasswordLoginAttempt.d.ts +50 -0
  111. package/dist/auth/PasswordLoginAttempt.js +60 -0
  112. package/dist/auth/PasswordSuspendedError.d.ts +10 -0
  113. package/dist/auth/PasswordSuspendedError.js +13 -0
  114. package/dist/auth/contracts/PasswordAuthProviderOptions.d.ts +26 -0
  115. package/dist/auth/contracts/PasswordAuthProviderOptions.js +1 -0
  116. package/dist/auth/contracts/PasswordSuspension.d.ts +7 -0
  117. package/dist/auth/contracts/PasswordSuspension.js +1 -0
  118. package/dist/auth/contracts/PasswordSuspensionOptions.d.ts +10 -0
  119. package/dist/auth/contracts/PasswordSuspensionOptions.js +1 -0
  120. package/dist/auth/contracts/index.d.ts +3 -0
  121. package/dist/auth/contracts/index.js +3 -0
  122. package/dist/auth/index.d.ts +2 -0
  123. package/dist/auth/index.js +2 -0
  124. package/dist/auth/providers/PasswordAuthProvider.d.ts +19 -23
  125. package/dist/auth/providers/PasswordAuthProvider.js +96 -8
  126. package/dist/auth/providers/resolveAuthProviders.js +1 -0
  127. package/dist/cli/Cli.d.ts +2 -0
  128. package/dist/cli/Cli.js +8 -0
  129. package/dist/cli/commands/repl.js +2 -1
  130. package/dist/cli/contracts/CliCommand.d.ts +2 -0
  131. package/dist/cli/contracts/CliCommandInfo.d.ts +12 -0
  132. package/dist/cli/contracts/CliCommandInfo.js +1 -0
  133. package/dist/cli/contracts/index.d.ts +1 -0
  134. package/dist/cli/index.d.ts +1 -0
  135. package/dist/cli/index.js +1 -0
  136. package/dist/cli/listDb3Commands.d.ts +8 -0
  137. package/dist/cli/listDb3Commands.js +10 -0
  138. package/dist/cli/runDb3.d.ts +3 -6
  139. package/dist/cli/runDb3.js +5 -59
  140. package/dist/cli/withDb3Cli.d.ts +4 -0
  141. package/dist/cli/withDb3Cli.js +60 -0
  142. package/dist/db/ActiveQueryBuilder.d.ts +8 -0
  143. package/dist/db/ActiveQueryBuilder.js +11 -0
  144. package/dist/db/ActiveRecord.d.ts +6 -0
  145. package/dist/db/ActiveRecord.js +8 -0
  146. package/dist/db/connection.js +14 -2
  147. package/dist/db/fields/TimestampField.d.ts +1 -1
  148. package/dist/db/fields/TimestampField.js +7 -12
  149. package/dist/db/migrations/DatabaseMigrationManager.d.ts +3 -1
  150. package/dist/db/migrations/DatabaseMigrationManager.js +9 -3
  151. package/dist/db/migrations/contracts/DatabaseMigration.d.ts +7 -0
  152. package/dist/db/migrations/index.d.ts +1 -1
  153. package/dist/db/migrations/index.js +1 -1
  154. package/dist/db/migrations/{KnexMigrationRenderer.d.ts → renderKnexMigration.d.ts} +4 -3
  155. package/dist/db/migrations/{KnexMigrationRenderer.js → renderKnexMigration.js} +7 -6
  156. package/dist/flows/FlowCompiler.js +1 -1
  157. package/dist/flows/Flows.js +1 -1
  158. package/dist/flows/index.d.ts +1 -1
  159. package/dist/flows/index.js +1 -1
  160. package/dist/health/Health.d.ts +41 -0
  161. package/dist/health/Health.js +153 -0
  162. package/dist/health/contracts/Health.d.ts +36 -0
  163. package/dist/health/contracts/Health.js +1 -0
  164. package/dist/health/contracts/HealthHttp.d.ts +15 -0
  165. package/dist/health/contracts/HealthHttp.js +1 -0
  166. package/dist/health/contracts/index.d.ts +2 -0
  167. package/dist/health/contracts/index.js +1 -0
  168. package/dist/health/databaseHealthCheck.d.ts +15 -0
  169. package/dist/health/databaseHealthCheck.js +18 -0
  170. package/dist/health/fastify.d.ts +13 -0
  171. package/dist/health/fastify.js +44 -0
  172. package/dist/health/index.d.ts +3 -0
  173. package/dist/health/index.js +2 -0
  174. package/dist/in-app/InApp.d.ts +33 -0
  175. package/dist/in-app/InApp.js +191 -0
  176. package/dist/in-app/InAppError.d.ts +6 -0
  177. package/dist/in-app/InAppError.js +10 -0
  178. package/dist/in-app/InAppRecord.d.ts +36 -0
  179. package/dist/in-app/InAppRecord.js +24 -0
  180. package/dist/in-app/contracts/InAppInbox.d.ts +45 -0
  181. package/dist/in-app/contracts/InAppInbox.js +1 -0
  182. package/dist/in-app/contracts/InAppMessage.d.ts +22 -0
  183. package/dist/in-app/contracts/InAppMessage.js +1 -0
  184. package/dist/in-app/contracts/InAppScope.d.ts +17 -0
  185. package/dist/in-app/contracts/InAppScope.js +1 -0
  186. package/dist/in-app/contracts/index.d.ts +3 -0
  187. package/dist/in-app/contracts/index.js +3 -0
  188. package/dist/in-app/index.d.ts +4 -0
  189. package/dist/in-app/index.js +4 -0
  190. package/dist/in-app/validation.d.ts +21 -0
  191. package/dist/in-app/validation.js +50 -0
  192. package/dist/index.d.ts +2 -14
  193. package/dist/index.js +2 -5
  194. package/dist/logging/DevelopmentConsole.d.ts +42 -0
  195. package/dist/logging/DevelopmentConsole.js +162 -0
  196. package/dist/logging/Log.d.ts +3 -1
  197. package/dist/logging/Log.js +5 -2
  198. package/dist/logging/PrettyLogFormatter.d.ts +16 -0
  199. package/dist/logging/PrettyLogFormatter.js +151 -0
  200. package/dist/logging/acquireDevelopmentConsole.d.ts +6 -0
  201. package/dist/logging/acquireDevelopmentConsole.js +21 -0
  202. package/dist/logging/contracts/DevelopmentConsoleOptions.d.ts +16 -0
  203. package/dist/logging/contracts/DevelopmentConsoleOptions.js +1 -0
  204. package/dist/logging/contracts/EmailLogOptions.d.ts +8 -0
  205. package/dist/logging/contracts/EmailLogOptions.js +1 -0
  206. package/dist/logging/contracts/HttpExchangeMonitorOptions.d.ts +12 -0
  207. package/dist/logging/contracts/HttpExchangeMonitorOptions.js +1 -0
  208. package/dist/logging/contracts/LogTransportOptions.d.ts +19 -0
  209. package/dist/logging/contracts/LogTransportOptions.js +1 -0
  210. package/dist/logging/contracts/LoggingOptions.d.ts +12 -1
  211. package/dist/logging/contracts/index.d.ts +4 -0
  212. package/dist/logging/contracts/index.js +4 -0
  213. package/dist/logging/drivers/PinoLoggerDriver.d.ts +3 -1
  214. package/dist/logging/drivers/PinoLoggerDriver.js +75 -16
  215. package/dist/logging/formatLogEmail.d.ts +4 -0
  216. package/dist/logging/formatLogEmail.js +21 -0
  217. package/dist/logging/highlightQueueMessage.d.ts +11 -0
  218. package/dist/logging/highlightQueueMessage.js +36 -0
  219. package/dist/logging/httpBodyCapture.d.ts +24 -0
  220. package/dist/logging/httpBodyCapture.js +321 -0
  221. package/dist/logging/index.d.ts +2 -0
  222. package/dist/logging/index.js +2 -0
  223. package/dist/logging/redactLogEmail.d.ts +2 -0
  224. package/dist/logging/redactLogEmail.js +12 -0
  225. package/dist/logging/registerHttpExchangeMonitor.d.ts +10 -0
  226. package/dist/logging/registerHttpExchangeMonitor.js +43 -0
  227. package/dist/logging/transports/EmailLogTransport.d.ts +18 -0
  228. package/dist/logging/transports/EmailLogTransport.js +47 -0
  229. package/dist/mail/Mail.d.ts +2 -0
  230. package/dist/mail/Mail.js +3 -0
  231. package/dist/mail/MailDeliveryError.d.ts +9 -0
  232. package/dist/mail/MailDeliveryError.js +16 -0
  233. package/dist/mail/index.d.ts +1 -0
  234. package/dist/mail/index.js +1 -0
  235. package/dist/mail/transports/MailgunTransport.js +2 -0
  236. package/dist/mail/transports/ResendTransport.d.ts +3 -2
  237. package/dist/mail/transports/ResendTransport.js +22 -14
  238. package/dist/media/MediaManager.d.ts +4 -2
  239. package/dist/media/MediaManager.js +40 -8
  240. package/dist/network/BlockedUrlError.d.ts +16 -0
  241. package/dist/network/BlockedUrlError.js +19 -0
  242. package/dist/network/assertPublicUrl.d.ts +22 -0
  243. package/dist/network/assertPublicUrl.js +67 -0
  244. package/dist/network/contracts/GuardedFetch.d.ts +35 -0
  245. package/dist/network/contracts/GuardedFetch.js +1 -0
  246. package/dist/network/contracts/PublicUrlOptions.d.ts +17 -0
  247. package/dist/network/contracts/PublicUrlOptions.js +1 -0
  248. package/dist/network/contracts/index.d.ts +2 -0
  249. package/dist/network/contracts/index.js +2 -0
  250. package/dist/network/guardedFetch.d.ts +29 -0
  251. package/dist/network/guardedFetch.js +133 -0
  252. package/dist/network/index.d.ts +6 -0
  253. package/dist/network/index.js +6 -0
  254. package/dist/network/playwright/GuardedBrowserProxy.d.ts +32 -0
  255. package/dist/network/playwright/GuardedBrowserProxy.js +172 -0
  256. package/dist/network/playwright/contracts/GuardedBrowserContextOptions.d.ts +37 -0
  257. package/dist/network/playwright/contracts/GuardedBrowserContextOptions.js +1 -0
  258. package/dist/network/playwright/contracts/index.d.ts +1 -0
  259. package/dist/network/playwright/contracts/index.js +1 -0
  260. package/dist/network/playwright/index.d.ts +2 -0
  261. package/dist/network/playwright/index.js +2 -0
  262. package/dist/network/playwright/newGuardedBrowserContext.d.ts +21 -0
  263. package/dist/network/playwright/newGuardedBrowserContext.js +86 -0
  264. package/dist/network/privateNetworkAddresses.d.ts +44 -0
  265. package/dist/network/privateNetworkAddresses.js +157 -0
  266. package/dist/network/publicAddressLookup.d.ts +26 -0
  267. package/dist/network/publicAddressLookup.js +42 -0
  268. package/dist/notifications/Notifications.d.ts +27 -0
  269. package/dist/notifications/Notifications.js +99 -0
  270. package/dist/notifications/contracts/Notification.d.ts +56 -0
  271. package/dist/notifications/contracts/Notification.js +1 -0
  272. package/dist/notifications/contracts/NotificationDelivery.d.ts +11 -0
  273. package/dist/notifications/contracts/NotificationDelivery.js +1 -0
  274. package/dist/notifications/contracts/index.d.ts +2 -0
  275. package/dist/notifications/contracts/index.js +2 -0
  276. package/dist/notifications/index.d.ts +2 -0
  277. package/dist/notifications/index.js +2 -0
  278. package/dist/queue/JobRunAttempt.d.ts +16 -0
  279. package/dist/queue/JobRunAttempt.js +17 -0
  280. package/dist/queue/JobRunEvent.d.ts +15 -0
  281. package/dist/queue/JobRunEvent.js +16 -0
  282. package/dist/queue/JobRunStoppedError.d.ts +6 -0
  283. package/dist/queue/JobRunStoppedError.js +10 -0
  284. package/dist/queue/Queue.d.ts +19 -4
  285. package/dist/queue/Queue.js +122 -9
  286. package/dist/queue/QueueTerminalError.d.ts +9 -0
  287. package/dist/queue/QueueTerminalError.js +12 -0
  288. package/dist/queue/QueueWorker.d.ts +12 -5
  289. package/dist/queue/QueueWorker.js +94 -9
  290. package/dist/queue/QueueWorkerReporter.d.ts +17 -0
  291. package/dist/queue/QueueWorkerReporter.js +71 -0
  292. package/dist/queue/QueueableJob.d.ts +2 -2
  293. package/dist/queue/RunnableJob.d.ts +78 -0
  294. package/dist/queue/RunnableJob.js +284 -0
  295. package/dist/queue/console.d.ts +8 -0
  296. package/dist/queue/console.js +53 -19
  297. package/dist/queue/contracts/QueueDriver.d.ts +8 -0
  298. package/dist/queue/contracts/QueueJobRunner.d.ts +4 -0
  299. package/dist/queue/contracts/QueueJobRunner.js +1 -0
  300. package/dist/queue/contracts/QueuePayload.d.ts +1 -1
  301. package/dist/queue/contracts/QueueSelection.d.ts +11 -0
  302. package/dist/queue/contracts/QueueSelection.js +1 -0
  303. package/dist/queue/contracts/QueueService.d.ts +18 -4
  304. package/dist/queue/contracts/QueueWorkerLifecycle.d.ts +2 -2
  305. package/dist/queue/contracts/QueueWorkerSnapshot.d.ts +14 -0
  306. package/dist/queue/contracts/QueueWorkerSnapshot.js +1 -0
  307. package/dist/queue/contracts/QueueableJob.d.ts +7 -3
  308. package/dist/queue/contracts/QueueableJobContract.d.ts +12 -0
  309. package/dist/queue/contracts/QueueableJobContract.js +1 -0
  310. package/dist/queue/contracts/index.d.ts +4 -0
  311. package/dist/queue/contracts/index.js +2 -0
  312. package/dist/queue/drivers/DatabaseQueueDriver.d.ts +4 -0
  313. package/dist/queue/drivers/DatabaseQueueDriver.js +27 -3
  314. package/dist/queue/drivers/RedisQueueDriver.d.ts +7 -0
  315. package/dist/queue/drivers/RedisQueueDriver.js +37 -0
  316. package/dist/queue/index.d.ts +5 -0
  317. package/dist/queue/index.js +5 -0
  318. package/dist/queue/jobEnvelopeHasPrefix.d.ts +3 -0
  319. package/dist/queue/jobEnvelopeHasPrefix.js +4 -0
  320. package/dist/scheduler/ScheduledEvent.d.ts +8 -4
  321. package/dist/scheduler/ScheduledEvent.js +17 -3
  322. package/dist/scheduler/ScheduledJob.d.ts +1 -1
  323. package/dist/scheduler/Scheduler.d.ts +5 -0
  324. package/dist/scheduler/Scheduler.js +92 -28
  325. package/dist/scheduler/SchedulerCheckpointRecord.d.ts +16 -0
  326. package/dist/scheduler/SchedulerCheckpointRecord.js +53 -0
  327. package/dist/scheduler/SchedulerWorker.d.ts +3 -5
  328. package/dist/scheduler/SchedulerWorker.js +58 -14
  329. package/dist/scheduler/console.js +3 -1
  330. package/dist/scheduler/contracts/Schedule.d.ts +19 -0
  331. package/dist/scheduler/contracts/Schedule.js +1 -0
  332. package/dist/scheduler/contracts/Scheduler.d.ts +18 -6
  333. package/dist/scheduler/contracts/SchedulerCheckpoint.d.ts +23 -0
  334. package/dist/scheduler/contracts/SchedulerCheckpoint.js +1 -0
  335. package/dist/scheduler/contracts/SchedulerConsole.d.ts +5 -0
  336. package/dist/scheduler/contracts/SchedulerWorker.d.ts +6 -1
  337. package/dist/scheduler/contracts/index.d.ts +2 -0
  338. package/dist/scheduler/contracts/index.js +2 -0
  339. package/dist/scheduler/index.d.ts +1 -0
  340. package/dist/scheduler/index.js +1 -0
  341. package/dist/server/App.d.ts +36 -4
  342. package/dist/server/App.js +57 -7
  343. package/dist/server/contracts/HttpErrorHandlerOptions.d.ts +29 -0
  344. package/dist/server/contracts/HttpErrorHandlerOptions.js +1 -0
  345. package/dist/server/contracts/index.d.ts +1 -0
  346. package/dist/server/contracts/index.js +1 -0
  347. package/dist/server/index.d.ts +4 -0
  348. package/dist/server/index.js +4 -0
  349. package/dist/server/publicServerErrorMessage.d.ts +11 -0
  350. package/dist/server/publicServerErrorMessage.js +16 -0
  351. package/dist/server/registerBrowserJsonFormatting.d.ts +16 -0
  352. package/dist/server/registerBrowserJsonFormatting.js +100 -0
  353. package/dist/server/registerHttpErrorHandler.d.ts +20 -0
  354. package/dist/server/registerHttpErrorHandler.js +93 -0
  355. package/dist/ssr/vite/contracts/ViteSsrOptions.d.ts +2 -0
  356. package/dist/ssr/vite/fastifyViteSsr.js +4 -3
  357. package/dist/storage/drivers/FlystorageDisk.js +2 -2
  358. package/dist/storage/index.d.ts +2 -2
  359. package/dist/storage/index.js +2 -2
  360. package/dist/websocket/WebSocketChannels.d.ts +18 -0
  361. package/dist/websocket/WebSocketChannels.js +129 -0
  362. package/dist/websocket/WebSocketConnection.d.ts +25 -0
  363. package/dist/websocket/WebSocketConnection.js +244 -0
  364. package/dist/websocket/WebSockets.d.ts +41 -0
  365. package/dist/websocket/WebSockets.js +194 -0
  366. package/dist/websocket/client/WebSocketClient.d.ts +21 -0
  367. package/dist/websocket/client/WebSocketClient.js +230 -0
  368. package/dist/websocket/client/index.d.ts +3 -0
  369. package/dist/websocket/client/index.js +1 -0
  370. package/dist/websocket/contracts/WebSocketChannel.d.ts +20 -0
  371. package/dist/websocket/contracts/WebSocketChannel.js +1 -0
  372. package/dist/websocket/contracts/WebSocketClient.d.ts +45 -0
  373. package/dist/websocket/contracts/WebSocketClient.js +1 -0
  374. package/dist/websocket/contracts/WebSocketEndpoint.d.ts +43 -0
  375. package/dist/websocket/contracts/WebSocketEndpoint.js +1 -0
  376. package/dist/websocket/contracts/WebSocketOptions.d.ts +48 -0
  377. package/dist/websocket/contracts/WebSocketOptions.js +1 -0
  378. package/dist/websocket/contracts/WebSocketPresence.d.ts +6 -0
  379. package/dist/websocket/contracts/WebSocketPresence.js +1 -0
  380. package/dist/websocket/contracts/WebSocketServiceOptions.d.ts +12 -0
  381. package/dist/websocket/contracts/WebSocketServiceOptions.js +1 -0
  382. package/dist/websocket/contracts/index.d.ts +6 -0
  383. package/dist/websocket/contracts/index.js +1 -0
  384. package/dist/websocket/defineChannel.d.ts +8 -0
  385. package/dist/websocket/defineChannel.js +13 -0
  386. package/dist/websocket/defineWebSocket.d.ts +14 -0
  387. package/dist/websocket/defineWebSocket.js +4 -0
  388. package/dist/websocket/fastify.d.ts +11 -0
  389. package/dist/websocket/fastify.js +38 -0
  390. package/dist/websocket/index.d.ts +5 -0
  391. package/dist/websocket/index.js +4 -0
  392. package/package.json +108 -7
  393. package/src/ai/AIErrors.ts +10 -0
  394. package/src/ai/AIFailover.ts +3 -2
  395. package/src/ai/AIProviderAdmission.ts +329 -0
  396. package/src/ai/AIRateLimiter.ts +134 -10
  397. package/src/ai/AIRequestTrackingError.ts +37 -0
  398. package/src/ai/Agent.ts +85 -71
  399. package/src/ai/Ai.ts +104 -48
  400. package/src/ai/OpenAIProviderError.ts +1 -1
  401. package/src/ai/ProviderSseObserver.ts +89 -0
  402. package/src/ai/README.md +216 -11
  403. package/src/ai/aiServiceTier.ts +14 -0
  404. package/src/ai/chunkEmbeddingText.ts +137 -0
  405. package/src/ai/contracts/AI.ts +17 -0
  406. package/src/ai/contracts/AIRequestErrorDiagnostics.ts +12 -0
  407. package/src/ai/contracts/AIServiceTier.ts +2 -0
  408. package/src/ai/contracts/Agent.ts +3 -0
  409. package/src/ai/contracts/EmbeddingTextChunk.ts +26 -0
  410. package/src/ai/contracts/Pricing.ts +7 -1
  411. package/src/ai/contracts/Providers.ts +2 -0
  412. package/src/ai/contracts/index.ts +2 -0
  413. package/src/ai/examples/prepareDocumentEmbeddings.ts +20 -0
  414. package/src/ai/index.ts +9 -2
  415. package/src/ai/{Models.ts → modelPricing.ts} +37 -4
  416. package/src/apps/AppInstallation.ts +25 -0
  417. package/src/apps/AppRouteError.ts +8 -0
  418. package/src/apps/AppService.ts +30 -0
  419. package/src/apps/Apps.ts +508 -0
  420. package/src/apps/README.md +354 -0
  421. package/src/apps/appsPlugin.ts +34 -0
  422. package/src/apps/commands/disableApp.ts +6 -0
  423. package/src/apps/commands/enableApp.ts +6 -0
  424. package/src/apps/commands/index.ts +29 -0
  425. package/src/apps/commands/installApp.ts +6 -0
  426. package/src/apps/commands/listApps.ts +6 -0
  427. package/src/apps/commands/makeAppMigration.ts +9 -0
  428. package/src/apps/commands/rollbackApp.ts +6 -0
  429. package/src/apps/commands/uninstallApp.ts +6 -0
  430. package/src/apps/contracts/AppAction.ts +2 -0
  431. package/src/apps/contracts/AppDefinition.ts +49 -0
  432. package/src/apps/contracts/AppDescription.ts +27 -0
  433. package/src/apps/contracts/AppManifest.ts +32 -0
  434. package/src/apps/contracts/AppNavigation.ts +10 -0
  435. package/src/apps/contracts/AppNavigationBadge.ts +6 -0
  436. package/src/apps/contracts/AppNavigationContext.ts +6 -0
  437. package/src/apps/contracts/AppNavigationResult.ts +9 -0
  438. package/src/apps/contracts/AppRoute.ts +18 -0
  439. package/src/apps/contracts/DiscoveredApp.ts +11 -0
  440. package/src/apps/contracts/InstalledApps.ts +2 -0
  441. package/src/apps/contracts/index.ts +11 -0
  442. package/src/apps/defineApp.ts +10 -0
  443. package/src/apps/discoverApps.ts +56 -0
  444. package/src/apps/fastify.ts +1 -0
  445. package/src/apps/index.ts +7 -0
  446. package/src/apps/normalizeAppNavigation.ts +29 -0
  447. package/src/apps/registerAppRoutes.ts +48 -0
  448. package/src/apps/validateAppDefinitions.ts +52 -0
  449. package/src/apps/vite.ts +1 -0
  450. package/src/apps/writeAppTypes.ts +14 -0
  451. package/src/auth/Auth.ts +89 -23
  452. package/src/auth/PasswordLoginAttempt.ts +72 -0
  453. package/src/auth/PasswordSuspendedError.ts +13 -0
  454. package/src/auth/README.md +94 -4
  455. package/src/auth/contracts/PasswordAuthProviderOptions.ts +30 -0
  456. package/src/auth/contracts/PasswordSuspension.ts +7 -0
  457. package/src/auth/contracts/PasswordSuspensionOptions.ts +10 -0
  458. package/src/auth/contracts/index.ts +3 -0
  459. package/src/auth/examples/runPasswordAuth.ts +6 -6
  460. package/src/auth/index.ts +2 -0
  461. package/src/auth/providers/PasswordAuthProvider.ts +96 -30
  462. package/src/auth/providers/resolveAuthProviders.ts +1 -0
  463. package/src/cli/Cli.ts +9 -0
  464. package/src/cli/README.md +19 -0
  465. package/src/cli/commands/repl.ts +2 -1
  466. package/src/cli/contracts/CliCommand.ts +2 -0
  467. package/src/cli/contracts/CliCommandInfo.ts +13 -0
  468. package/src/cli/contracts/index.ts +1 -0
  469. package/src/cli/index.ts +1 -0
  470. package/src/cli/listDb3Commands.ts +12 -0
  471. package/src/cli/runDb3.ts +5 -51
  472. package/src/cli/withDb3Cli.ts +55 -0
  473. package/src/db/ActiveQueryBuilder.ts +12 -0
  474. package/src/db/ActiveRecord.ts +9 -0
  475. package/src/db/README.md +45 -1
  476. package/src/db/connection.ts +12 -1
  477. package/src/db/examples/FieldNote.ts +7 -13
  478. package/src/db/examples/KnowledgeNote.ts +7 -13
  479. package/src/db/examples/runNoteMigrations.ts +11 -11
  480. package/src/db/fields/TimestampField.ts +8 -17
  481. package/src/db/migrations/DatabaseMigrationManager.ts +12 -4
  482. package/src/db/migrations/contracts/DatabaseMigration.ts +9 -0
  483. package/src/db/migrations/index.ts +1 -1
  484. package/src/db/migrations/{KnexMigrationRenderer.ts → renderKnexMigration.ts} +8 -14
  485. package/src/flows/FlowCompiler.ts +1 -1
  486. package/src/flows/Flows.ts +1 -1
  487. package/src/flows/index.ts +1 -1
  488. package/src/health/Health.ts +163 -0
  489. package/src/health/README.md +46 -0
  490. package/src/health/contracts/Health.ts +47 -0
  491. package/src/health/contracts/HealthHttp.ts +19 -0
  492. package/src/health/contracts/index.ts +2 -0
  493. package/src/health/databaseHealthCheck.ts +21 -0
  494. package/src/health/fastify.ts +49 -0
  495. package/src/health/index.ts +3 -0
  496. package/src/in-app/InApp.ts +173 -0
  497. package/src/in-app/InAppError.ts +8 -0
  498. package/src/in-app/InAppRecord.ts +41 -0
  499. package/src/in-app/README.md +193 -0
  500. package/src/in-app/contracts/InAppInbox.ts +51 -0
  501. package/src/in-app/contracts/InAppMessage.ts +19 -0
  502. package/src/in-app/contracts/InAppScope.ts +12 -0
  503. package/src/in-app/contracts/index.ts +3 -0
  504. package/src/in-app/examples/sendReportReady.ts +14 -0
  505. package/src/in-app/index.ts +4 -0
  506. package/src/in-app/validation.ts +49 -0
  507. package/src/index.ts +2 -22
  508. package/src/logging/DevelopmentConsole.ts +154 -0
  509. package/src/logging/Log.ts +5 -2
  510. package/src/logging/PrettyLogFormatter.ts +165 -0
  511. package/src/logging/README.md +52 -109
  512. package/src/logging/acquireDevelopmentConsole.ts +19 -0
  513. package/src/logging/contracts/DevelopmentConsoleOptions.ts +13 -0
  514. package/src/logging/contracts/EmailLogOptions.ts +9 -0
  515. package/src/logging/contracts/HttpExchangeMonitorOptions.ts +13 -0
  516. package/src/logging/contracts/LogTransportOptions.ts +10 -0
  517. package/src/logging/contracts/LoggingOptions.ts +12 -1
  518. package/src/logging/contracts/index.ts +4 -0
  519. package/src/logging/development/README.md +88 -0
  520. package/src/logging/drivers/PinoLoggerDriver.ts +72 -20
  521. package/src/logging/examples/runDevelopmentLogs.ts +36 -0
  522. package/src/logging/formatLogEmail.ts +24 -0
  523. package/src/logging/highlightQueueMessage.ts +38 -0
  524. package/src/logging/httpBodyCapture.ts +393 -0
  525. package/src/logging/index.ts +2 -0
  526. package/src/logging/redactLogEmail.ts +12 -0
  527. package/src/logging/registerHttpExchangeMonitor.ts +45 -0
  528. package/src/logging/transports/EmailLogTransport.ts +46 -0
  529. package/src/mail/Mail.ts +5 -0
  530. package/src/mail/MailDeliveryError.ts +8 -0
  531. package/src/mail/README.md +11 -1
  532. package/src/mail/index.ts +1 -0
  533. package/src/mail/transports/MailgunTransport.ts +2 -0
  534. package/src/mail/transports/ResendTransport.ts +24 -22
  535. package/src/media/MediaManager.ts +31 -10
  536. package/src/media/README.md +4 -0
  537. package/src/media/examples/runPrivateFiles.ts +2 -2
  538. package/src/network/BlockedUrlError.ts +19 -0
  539. package/src/network/README.md +133 -0
  540. package/src/network/assertPublicUrl.ts +77 -0
  541. package/src/network/contracts/GuardedFetch.ts +40 -0
  542. package/src/network/contracts/PublicUrlOptions.ts +17 -0
  543. package/src/network/contracts/index.ts +2 -0
  544. package/src/network/examples/runGuardedFetch.ts +35 -0
  545. package/src/network/guardedFetch.ts +150 -0
  546. package/src/network/index.ts +6 -0
  547. package/src/network/playwright/GuardedBrowserProxy.ts +172 -0
  548. package/src/network/playwright/contracts/GuardedBrowserContextOptions.ts +43 -0
  549. package/src/network/playwright/contracts/index.ts +1 -0
  550. package/src/network/playwright/index.ts +2 -0
  551. package/src/network/playwright/newGuardedBrowserContext.ts +74 -0
  552. package/src/network/privateNetworkAddresses.ts +166 -0
  553. package/src/network/publicAddressLookup.ts +49 -0
  554. package/src/notifications/Notifications.ts +105 -0
  555. package/src/notifications/README.md +59 -0
  556. package/src/notifications/contracts/Notification.ts +65 -0
  557. package/src/notifications/contracts/NotificationDelivery.ts +11 -0
  558. package/src/notifications/contracts/index.ts +2 -0
  559. package/src/notifications/examples/ReportReadyNotification.ts +31 -0
  560. package/src/notifications/index.ts +2 -0
  561. package/src/queue/JobRunAttempt.ts +17 -0
  562. package/src/queue/JobRunEvent.ts +16 -0
  563. package/src/queue/JobRunStoppedError.ts +8 -0
  564. package/src/queue/Queue.ts +112 -11
  565. package/src/queue/QueueTerminalError.ts +12 -0
  566. package/src/queue/QueueWorker.ts +86 -7
  567. package/src/queue/QueueWorkerReporter.ts +59 -0
  568. package/src/queue/QueueableJob.ts +2 -2
  569. package/src/queue/README.md +142 -1
  570. package/src/queue/RunnableJob.ts +272 -0
  571. package/src/queue/console.ts +54 -21
  572. package/src/queue/contracts/QueueDriver.ts +9 -0
  573. package/src/queue/contracts/QueueJobRunner.ts +4 -0
  574. package/src/queue/contracts/QueuePayload.ts +1 -1
  575. package/src/queue/contracts/QueueSelection.ts +11 -0
  576. package/src/queue/contracts/QueueService.ts +19 -4
  577. package/src/queue/contracts/QueueWorkerLifecycle.ts +2 -2
  578. package/src/queue/contracts/QueueWorkerSnapshot.ts +15 -0
  579. package/src/queue/contracts/QueueableJob.ts +7 -3
  580. package/src/queue/contracts/QueueableJobContract.ts +13 -0
  581. package/src/queue/contracts/index.ts +6 -0
  582. package/src/queue/drivers/DatabaseQueueDriver.ts +25 -3
  583. package/src/queue/drivers/RedisQueueDriver.ts +36 -0
  584. package/src/queue/examples/runQueueSelection.ts +34 -0
  585. package/src/queue/index.ts +7 -0
  586. package/src/queue/jobEnvelopeHasPrefix.ts +6 -0
  587. package/src/scheduler/README.md +50 -9
  588. package/src/scheduler/ScheduledEvent.ts +20 -5
  589. package/src/scheduler/ScheduledJob.ts +1 -1
  590. package/src/scheduler/Scheduler.ts +73 -27
  591. package/src/scheduler/SchedulerCheckpointRecord.ts +51 -0
  592. package/src/scheduler/SchedulerWorker.ts +54 -19
  593. package/src/scheduler/console.ts +3 -1
  594. package/src/scheduler/contracts/Schedule.ts +22 -0
  595. package/src/scheduler/contracts/Scheduler.ts +21 -6
  596. package/src/scheduler/contracts/SchedulerCheckpoint.ts +23 -0
  597. package/src/scheduler/contracts/SchedulerConsole.ts +5 -0
  598. package/src/scheduler/contracts/SchedulerWorker.ts +6 -1
  599. package/src/scheduler/contracts/index.ts +2 -0
  600. package/src/scheduler/examples/runSchedulerWindow.ts +54 -0
  601. package/src/scheduler/index.ts +1 -0
  602. package/src/server/App.ts +73 -10
  603. package/src/server/README.md +95 -2
  604. package/src/server/contracts/HttpErrorHandlerOptions.ts +29 -0
  605. package/src/server/contracts/index.ts +1 -0
  606. package/src/server/examples/createFirstServer.ts +5 -3
  607. package/src/server/index.ts +4 -0
  608. package/src/server/publicServerErrorMessage.ts +17 -0
  609. package/src/server/registerBrowserJsonFormatting.ts +94 -0
  610. package/src/server/registerHttpErrorHandler.ts +96 -0
  611. package/src/ssr/README.md +6 -0
  612. package/src/ssr/vite/contracts/ViteSsrOptions.ts +2 -0
  613. package/src/ssr/vite/fastifyViteSsr.ts +4 -3
  614. package/src/storage/drivers/FlystorageDisk.ts +2 -2
  615. package/src/storage/index.ts +2 -2
  616. package/src/websocket/README.md +458 -0
  617. package/src/websocket/WebSocketChannels.ts +99 -0
  618. package/src/websocket/WebSocketConnection.ts +162 -0
  619. package/src/websocket/WebSockets.ts +157 -0
  620. package/src/websocket/client/WebSocketClient.ts +188 -0
  621. package/src/websocket/client/index.ts +3 -0
  622. package/src/websocket/contracts/WebSocketChannel.ts +23 -0
  623. package/src/websocket/contracts/WebSocketClient.ts +48 -0
  624. package/src/websocket/contracts/WebSocketEndpoint.ts +46 -0
  625. package/src/websocket/contracts/WebSocketOptions.ts +50 -0
  626. package/src/websocket/contracts/WebSocketPresence.ts +6 -0
  627. package/src/websocket/contracts/WebSocketServiceOptions.ts +12 -0
  628. package/src/websocket/contracts/index.ts +6 -0
  629. package/src/websocket/defineChannel.ts +14 -0
  630. package/src/websocket/defineWebSocket.ts +15 -0
  631. package/src/websocket/examples/board/LiveBoard.ts +97 -0
  632. package/src/websocket/examples/board/SummarizeBoardJob.ts +52 -0
  633. package/src/websocket/examples/board/boardSnapshot.ts +16 -0
  634. package/src/websocket/examples/board/createBoardClient.ts +43 -0
  635. package/src/websocket/examples/board/createBoardStore.ts +58 -0
  636. package/src/websocket/examples/board/registerBoardRoutes.ts +31 -0
  637. package/src/websocket/examples/createChannelSync.ts +66 -0
  638. package/src/websocket/examples/deploymentEndpoint.ts +13 -0
  639. package/src/websocket/examples/deploymentSnapshot.ts +36 -0
  640. package/src/websocket/examples/resourceChannels.ts +18 -0
  641. package/src/websocket/examples/userEndpoint.ts +27 -0
  642. package/src/websocket/fastify.ts +39 -0
  643. package/src/websocket/index.ts +5 -0
  644. package/templates/AGENTS.md +33 -2
  645. /package/dist/flows/{FlowValueValidator.d.ts → flowValueValidator.d.ts} +0 -0
  646. /package/dist/flows/{FlowValueValidator.js → flowValueValidator.js} +0 -0
  647. /package/dist/storage/{mime.d.ts → mimeTypeFromPath.d.ts} +0 -0
  648. /package/dist/storage/{mime.js → mimeTypeFromPath.js} +0 -0
  649. /package/dist/storage/{contents.d.ts → storageContentsToBuffer.d.ts} +0 -0
  650. /package/dist/storage/{contents.js → storageContentsToBuffer.js} +0 -0
  651. /package/src/flows/{FlowValueValidator.ts → flowValueValidator.ts} +0 -0
  652. /package/src/storage/{mime.ts → mimeTypeFromPath.ts} +0 -0
  653. /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 interface AppManifest {
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
+ }
@@ -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
- this.#driver = options.driver ?? new PinoLoggerDriver(options);
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
+ }
@@ -1,139 +1,82 @@
1
1
  # Logging
2
2
 
3
- `@db3.ai/app/logging` provides the application logger exposed through
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
- ## Run a structured logging lab
5
+ ## Writing logs
8
6
 
9
- From your independent app after [Installation](https://db3.ai/docs/installation):
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
- err: error,
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
- The standard levels are `trace`, `debug`, `info`, `warn`, `error`, `fatal`,
61
- and `silent`. The default level is `info`; tests default to `silent`.
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
- ## Application Configuration
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: 'debug',
23
+ level: 'info',
71
24
  source: 'example-api',
72
- bindings: {
73
- release: process.env.RELEASE_SHA,
74
- },
75
- devtools: true,
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
- Supported environment values:
81
-
82
- - `PLATFORM_LOG_LEVEL`: minimum standard log level.
83
- - `PLATFORM_LOG_SOURCE`: source name copied to every record.
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
- ## Development Log Stream
94
-
95
- The Pino transport runs in a worker thread and sends bounded, best-effort HTTP
96
- batches to the same generic event endpoint used by database and queue
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
- The default batch contains at most 25 records and a partial batch waits at most
109
- 100 milliseconds. At most 1,000 unsent events are retained; the oldest event is
110
- discarded when that bound is exceeded. A failed batch is discarded and later
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
- `App.close()` flushes the logger and closes its worker transport. Application
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
- ## Security
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
- The default Pino driver removes common password, secret, token, authorization,
121
- and cookie paths before records reach stdout or devtools. Applications can add
122
- more redaction paths through `AppOptions.log.redact`.
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
- Redaction is a safeguard, not permission to log request bodies, credentials,
125
- payment details, or personal data. Prefer explicit safe fields over logging
126
- large application objects.
62
+ ## Delivery and shutdown
127
63
 
128
- Redaction removes configured paths, not arbitrary secret substrings. Error messages, URL query strings and unfamiliar nested properties may still contain sensitive data. Test your application paths and never embed a credential in the log message itself. `redact: false` disables the protection.
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
- `Log.level` changes take effect on subsequent method lookups; avoid capturing a log function and then expecting it to be replaced when the level changes. `App.close()` owns its logger; a manually supplied output stream remains the creator's resource to end. The [full API](https://db3.ai/docs/logging-api) includes all current logger, driver, options and HTTP exchange contracts.
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
- ## Framework Boundaries
73
+ ## Security and boundaries
133
74
 
134
- Logs describe operations for people and observability tools. They are not a
135
- framework event bus and must not trigger application behavior.
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
- Database query events, queue lifecycle events, and durable flow events retain
138
- their own typed contracts. They can be correlated with logs through fields such
139
- as `requestId`, `jobId`, `websiteId`, `flowId`, and `component`.
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 };