@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.
Files changed (653) hide show
  1. package/README.md +75 -17
  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
@@ -1,6 +1,7 @@
1
1
  import { ActiveRecord, RecordValidationError, withQueryMonitorCategory } from '../../db/index.js';
2
2
  import { FailedJob } from '../FailedJob.js';
3
3
  import { QueuedJob } from '../QueuedJob.js';
4
+ import { jobEnvelopeHasPrefix } from '../jobEnvelopeHasPrefix.js';
4
5
  /**
5
6
  * Queue driver that stores pending and failed jobs in the app database.
6
7
  */
@@ -15,6 +16,28 @@ export class DatabaseQueueDriver {
15
16
  constructor(db) {
16
17
  this.db = db;
17
18
  }
19
+ /** Discovers queue names from the queue index, including delayed and reserved work. */
20
+ async queueNames() {
21
+ return withQueueQueryCategory(() => ActiveRecord.withDb(this.db.knex, async () => {
22
+ const rows = await QueuedJob.query().toKnex().distinct('queue').orderBy('queue');
23
+ return rows.map(row => String(row.queue));
24
+ }));
25
+ }
26
+ /** Scans active work in bounded pages during quiesced maintenance, including delayed and chained payloads. */
27
+ async hasPendingJobs(jobPrefix) {
28
+ if (!(await this.db.knex.schema.hasTable(QueuedJob.table)))
29
+ return false;
30
+ let after = 0;
31
+ while (true) {
32
+ const rows = await this.db.knex(QueuedJob.table).select('id', 'payload').where('id', '>', after).orderBy('id').limit(100);
33
+ for (const row of rows)
34
+ if (jobEnvelopeHasPrefix(typeof row.payload === 'string' ? JSON.parse(row.payload) : row.payload, jobPrefix))
35
+ return true;
36
+ if (rows.length < 100)
37
+ return false;
38
+ after = rows[rows.length - 1].id;
39
+ }
40
+ }
18
41
  /**
19
42
  * Persists a job in the `jobs` table.
20
43
  *
@@ -22,7 +45,8 @@ export class DatabaseQueueDriver {
22
45
  * @returns Database id of the queued job record.
23
46
  */
24
47
  async push(job) {
25
- return withQueueQueryCategory(() => ActiveRecord.withDb(this.db.knex, async () => {
48
+ const connection = ActiveRecord.getScopedDb() ?? this.db.knex;
49
+ return withQueueQueryCategory(() => ActiveRecord.withDb(connection, async () => {
26
50
  const record = QueuedJob.create({
27
51
  queue: job.queue,
28
52
  payload: job.payload,
@@ -39,7 +63,7 @@ export class DatabaseQueueDriver {
39
63
  isInsert: true,
40
64
  onlyDirty: false,
41
65
  });
42
- const [jobId] = await this.db.knex(QueuedJob.table).insert(row);
66
+ const [jobId] = await connection(QueuedJob.table).insert(row);
43
67
  return Number(jobId);
44
68
  }));
45
69
  }
@@ -93,7 +117,7 @@ export class DatabaseQueueDriver {
93
117
  * @returns True when the current attempt still owns the job.
94
118
  */
95
119
  async touch(job, _retryAfterSeconds) {
96
- return withQueueQueryCategory(() => ActiveRecord.withDb(this.db.knex, async () => {
120
+ return withQueueQueryCategory(() => ActiveRecord.withDb(ActiveRecord.getScopedDb() ?? this.db.knex, async () => {
97
121
  const updated = await QueuedJob
98
122
  .where('id', job.id)
99
123
  .where('attempts', job.attempts)
@@ -29,6 +29,13 @@ export declare class RedisQueueDriver implements queue.QueueDriver {
29
29
  * @returns Redis queue job id.
30
30
  */
31
31
  push<TData extends Record<string, unknown>>(job: queue.QueueDriverPushInput<TData>): Promise<queue.QueueJobId>;
32
+ /**
33
+ * Discovers queue names from ready/delayed/reserved keys without reading payloads.
34
+ * SCAN includes existing queues written before this capability was introduced.
35
+ */
36
+ queueNames(): Promise<string[]>;
37
+ /** Scans active Redis payloads during quiesced maintenance; includes delayed, reserved and chained jobs. */
38
+ hasPendingJobs(jobPrefix: string): Promise<boolean>;
32
39
  /**
33
40
  * Claims the next available job from a Redis queue.
34
41
  *
@@ -1,5 +1,6 @@
1
1
  import { createClient } from '@redis/client';
2
2
  import { unknownErrorMessage } from '@db3.ai/pure';
3
+ import { jobEnvelopeHasPrefix } from '../jobEnvelopeHasPrefix.js';
3
4
  const PUSH_SCRIPT = `
4
5
  local id = tostring(redis.call('INCR', KEYS[1]))
5
6
  local record = cjson.decode(ARGV[1])
@@ -171,6 +172,42 @@ export class RedisQueueDriver {
171
172
  ]);
172
173
  return String(id);
173
174
  }
175
+ /**
176
+ * Discovers queue names from ready/delayed/reserved keys without reading payloads.
177
+ * SCAN includes existing queues written before this capability was introduced.
178
+ */
179
+ async queueNames() {
180
+ const prefix = `${this.#key('queues')}:`;
181
+ const pattern = prefix.replace(/[\\*?\[\]]/g, '\\$&') + '*';
182
+ const names = new Set();
183
+ let cursor = '0';
184
+ do {
185
+ const [next, keys] = await this.#command(['SCAN', cursor, 'MATCH', pattern, 'COUNT', 100]);
186
+ cursor = String(next);
187
+ for (const key of keys) {
188
+ if (!key.startsWith(prefix))
189
+ continue;
190
+ const suffix = key.slice(prefix.length).match(/^(.*):(ready|delayed|reserved)$/);
191
+ if (suffix?.[1])
192
+ names.add(suffix[1]);
193
+ }
194
+ } while (cursor !== '0');
195
+ return [...names].sort();
196
+ }
197
+ /** Scans active Redis payloads during quiesced maintenance; includes delayed, reserved and chained jobs. */
198
+ async hasPendingJobs(jobPrefix) {
199
+ let cursor = '0';
200
+ do {
201
+ const result = await this.#command(['HSCAN', this.#jobsKey(), cursor, 'COUNT', 100]);
202
+ cursor = String(result[0]);
203
+ for (let index = 1; index < result[1].length; index += 2) {
204
+ const record = JSON.parse(result[1][index]);
205
+ if (jobEnvelopeHasPrefix(record.payload, jobPrefix))
206
+ return true;
207
+ }
208
+ } while (cursor !== '0');
209
+ return false;
210
+ }
174
211
  /**
175
212
  * Claims the next available job from a Redis queue.
176
213
  *
@@ -11,3 +11,8 @@ export * from './drivers/DatabaseQueueDriver.js';
11
11
  export * from './drivers/RedisQueueDriver.js';
12
12
  export * from './contracts/index.js';
13
13
  export * from './createJob.js';
14
+ export * from './QueueTerminalError.js';
15
+ export * from './RunnableJob.js';
16
+ export * from './JobRunAttempt.js';
17
+ export * from './JobRunEvent.js';
18
+ export * from './JobRunStoppedError.js';
@@ -11,3 +11,8 @@ export * from './drivers/DatabaseQueueDriver.js';
11
11
  export * from './drivers/RedisQueueDriver.js';
12
12
  export * from './contracts/index.js';
13
13
  export * from './createJob.js';
14
+ export * from './QueueTerminalError.js';
15
+ export * from './RunnableJob.js';
16
+ export * from './JobRunAttempt.js';
17
+ export * from './JobRunEvent.js';
18
+ export * from './JobRunStoppedError.js';
@@ -0,0 +1,3 @@
1
+ import type { SerializedQueuedJob } from './contracts/index.js';
2
+ /** Checks active work and nested chained continuations without inspecting application-owned payload data. */
3
+ export declare function jobEnvelopeHasPrefix(envelope: Pick<SerializedQueuedJob, 'job' | 'chained'>, prefix: string): boolean;
@@ -0,0 +1,4 @@
1
+ /** Checks active work and nested chained continuations without inspecting application-owned payload data. */
2
+ export function jobEnvelopeHasPrefix(envelope, prefix) {
3
+ return envelope.job.startsWith(prefix) || Boolean(envelope.chained?.some(job => jobEnvelopeHasPrefix(job, prefix)));
4
+ }
@@ -5,7 +5,7 @@ import type * as scheduler from './contracts/index.js';
5
5
  export declare abstract class ScheduledEvent {
6
6
  abstract readonly kind: scheduler.ScheduledTaskKind;
7
7
  protected configuredName: string | null;
8
- protected configuredFrequency: scheduler.DailyScheduleFrequency | null;
8
+ protected configuredFrequency: scheduler.ScheduleFrequency | null;
9
9
  protected configuredTimezone: string;
10
10
  /**
11
11
  * Sets the stable identity used for deduplication and history.
@@ -14,6 +14,10 @@ export declare abstract class ScheduledEvent {
14
14
  * @returns This scheduled event.
15
15
  */
16
16
  name(name: string): this;
17
+ /** Schedules one occurrence for each evaluated UTC minute, independent of timezone. */
18
+ everyMinute(): this;
19
+ /** Schedules one occurrence at minute zero of each UTC hour, independent of timezone. */
20
+ hourly(): this;
17
21
  /**
18
22
  * Schedules this task every day at local midnight.
19
23
  *
@@ -38,7 +42,7 @@ export declare abstract class ScheduledEvent {
38
42
  * Returns whether this event is due at one canonical UTC minute.
39
43
  *
40
44
  * @param instant - UTC minute being evaluated.
41
- * @returns True when the configured daily time matches.
45
+ * @returns True when the configured frequency matches a valid minute.
42
46
  */
43
47
  isDue(instant: Date): boolean;
44
48
  /**
@@ -54,9 +58,9 @@ export declare abstract class ScheduledEvent {
54
58
  */
55
59
  protected resolvedName(): string;
56
60
  /**
57
- * Returns the daily frequency or throws when none was configured.
61
+ * Returns the frequency or throws when none was configured.
58
62
  *
59
- * @returns Configured daily frequency.
63
+ * @returns Configured frequency.
60
64
  */
61
65
  private frequency;
62
66
  /**
@@ -23,6 +23,16 @@ export class ScheduledEvent {
23
23
  this.configuredName = normalized;
24
24
  return this;
25
25
  }
26
+ /** Schedules one occurrence for each evaluated UTC minute, independent of timezone. */
27
+ everyMinute() {
28
+ this.configuredFrequency = { type: 'minute' };
29
+ return this;
30
+ }
31
+ /** Schedules one occurrence at minute zero of each UTC hour, independent of timezone. */
32
+ hourly() {
33
+ this.configuredFrequency = { type: 'hourly' };
34
+ return this;
35
+ }
26
36
  /**
27
37
  * Schedules this task every day at local midnight.
28
38
  *
@@ -58,10 +68,14 @@ export class ScheduledEvent {
58
68
  * Returns whether this event is due at one canonical UTC minute.
59
69
  *
60
70
  * @param instant - UTC minute being evaluated.
61
- * @returns True when the configured daily time matches.
71
+ * @returns True when the configured frequency matches a valid minute.
62
72
  */
63
73
  isDue(instant) {
64
74
  const frequency = this.frequency();
75
+ if (frequency.type === 'minute')
76
+ return Number.isFinite(instant.getTime());
77
+ if (frequency.type === 'hourly')
78
+ return Number.isFinite(instant.getTime()) && instant.getUTCMinutes() === 0;
65
79
  return dailyScheduleIsDue(instant, frequency.time, this.configuredTimezone);
66
80
  }
67
81
  /**
@@ -94,9 +108,9 @@ export class ScheduledEvent {
94
108
  return name;
95
109
  }
96
110
  /**
97
- * Returns the daily frequency or throws when none was configured.
111
+ * Returns the frequency or throws when none was configured.
98
112
  *
99
- * @returns Configured daily frequency.
113
+ * @returns Configured frequency.
100
114
  */
101
115
  frequency() {
102
116
  if (!this.configuredFrequency) {
@@ -1,4 +1,4 @@
1
- import { type QueueableJob } from '../queue/index.js';
1
+ import { type QueueableJobContract as QueueableJob } from '../queue/index.js';
2
2
  import type * as scheduler from './contracts/index.js';
3
3
  import { ScheduledEvent } from './ScheduledEvent.js';
4
4
  /**
@@ -31,6 +31,11 @@ export declare class Scheduler {
31
31
  * @returns Fluent scheduled call definition.
32
32
  */
33
33
  call(callback: scheduler.ScheduledCallHandler): ScheduledCall;
34
+ /**
35
+ * Atomically registers an owned schedule group. Declarations are synchronous and do not execute jobs.
36
+ * Names are prefixed with the owner unless already namespaced. Failed declarations register nothing.
37
+ */
38
+ register(owner: string, configure: (schedule: scheduler.Schedule) => void, run?: scheduler.ScheduleRunner): scheduler.ScheduleRegistration;
34
39
  /**
35
40
  * Returns validated normalized definitions in registration order.
36
41
  *
@@ -13,6 +13,8 @@ export class Scheduler {
13
13
  database;
14
14
  queue;
15
15
  #events = [];
16
+ #owners = new Map();
17
+ #groups = new Set();
16
18
  #unsubscribeQueueEvents;
17
19
  /**
18
20
  * Creates a scheduler and attaches durable queue lifecycle recording.
@@ -50,13 +52,57 @@ export class Scheduler {
50
52
  this.#events.push(event);
51
53
  return event;
52
54
  }
55
+ /**
56
+ * Atomically registers an owned schedule group. Declarations are synchronous and do not execute jobs.
57
+ * Names are prefixed with the owner unless already namespaced. Failed declarations register nothing.
58
+ */
59
+ register(owner, configure, run = operation => operation()) {
60
+ if (!/^[a-z][a-z0-9_]{0,39}$/.test(owner) || this.#groups.has(owner))
61
+ throw new Error(`Invalid or duplicate schedule owner "${owner}".`);
62
+ const events = [];
63
+ const declaration = configure({
64
+ /** Collects a queued declaration without attaching it to the running scheduler yet. */
65
+ job: source => { const event = new ScheduledJob(source); events.push(event); return event; },
66
+ /** Collects a short callback under the same group ownership. */
67
+ call: handler => { const event = new ScheduledCall(handler); events.push(event); return event; },
68
+ });
69
+ if (declaration && typeof declaration.then === 'function')
70
+ throw new Error('Schedule declarations must be synchronous.');
71
+ const names = new Set(this.definitions().map(definition => definition.name));
72
+ const definitions = events.map(event => {
73
+ const name = event.definition().name;
74
+ if (!name.startsWith(`${owner}.`))
75
+ event.name(`${owner}.${name}`);
76
+ const definition = { ...event.definition(), owner };
77
+ if (names.has(definition.name))
78
+ throw new Error(`Duplicate scheduled event name "${definition.name}".`);
79
+ names.add(definition.name);
80
+ return definition;
81
+ });
82
+ this.#groups.add(owner);
83
+ for (const event of events) {
84
+ this.#events.push(event);
85
+ this.#owners.set(event, { owner, run });
86
+ }
87
+ let closed = false;
88
+ return { definitions, close: () => {
89
+ if (closed)
90
+ return;
91
+ closed = true;
92
+ for (const event of events) {
93
+ this.#events.splice(this.#events.indexOf(event), 1);
94
+ this.#owners.delete(event);
95
+ }
96
+ this.#groups.delete(owner);
97
+ } };
98
+ }
53
99
  /**
54
100
  * Returns validated normalized definitions in registration order.
55
101
  *
56
102
  * @returns Registered scheduler definitions.
57
103
  */
58
104
  definitions() {
59
- const definitions = this.#events.map(event => event.definition());
105
+ const definitions = this.#events.map(event => ({ ...event.definition(), ...(this.#owners.has(event) ? { owner: this.#owners.get(event).owner } : {}) }));
60
106
  const names = new Set();
61
107
  for (const definition of definitions) {
62
108
  if (names.has(definition.name)) {
@@ -93,36 +139,54 @@ export class Scheduler {
93
139
  failures: [],
94
140
  };
95
141
  for (const event of dueEvents) {
96
- const definition = event.definition();
97
- const occurrence = await ActiveRecord.withDb(this.database.knex, () => {
98
- return ScheduledOccurrence.claim({
99
- name: definition.name,
100
- kind: definition.kind,
101
- scheduledFor: evaluatedFor,
102
- jobName: definition.jobName,
142
+ const owner = this.#owners.get(event);
143
+ /** Runs a complete occurrence inside its registration owner's lifecycle gate. */
144
+ const execute = async () => {
145
+ if (!this.#events.includes(event)) {
146
+ result.skipped++;
147
+ return;
148
+ }
149
+ const definition = event.definition();
150
+ const occurrence = await ActiveRecord.withDb(this.database.knex, () => {
151
+ return ScheduledOccurrence.claim({
152
+ name: definition.name,
153
+ kind: definition.kind,
154
+ scheduledFor: evaluatedFor,
155
+ jobName: definition.jobName,
156
+ });
103
157
  });
104
- });
105
- if (!occurrence) {
106
- result.skipped += 1;
107
- continue;
108
- }
109
- result.claimed += 1;
110
- try {
111
- if (event instanceof ScheduledJob) {
112
- await this.dispatchJob(event, occurrence);
113
- result.dispatched += 1;
158
+ if (!occurrence) {
159
+ result.skipped += 1;
160
+ return;
114
161
  }
115
- else if (event instanceof ScheduledCall) {
116
- await this.runCall(event, occurrence);
117
- result.completed += 1;
162
+ result.claimed += 1;
163
+ try {
164
+ if (event instanceof ScheduledJob) {
165
+ await this.dispatchJob(event, occurrence);
166
+ result.dispatched += 1;
167
+ }
168
+ else if (event instanceof ScheduledCall) {
169
+ await this.runCall(event, occurrence);
170
+ result.completed += 1;
171
+ }
172
+ }
173
+ catch (error) {
174
+ await this.failOccurrence(occurrence, error);
175
+ result.failures.push({
176
+ name: definition.name,
177
+ error: errorDetails(error),
178
+ });
179
+ }
180
+ };
181
+ if (!owner)
182
+ await execute();
183
+ else {
184
+ try {
185
+ await owner.run(execute);
186
+ }
187
+ catch (error) {
188
+ result.failures.push({ name: event.definition().name, error: errorDetails(error) });
118
189
  }
119
- }
120
- catch (error) {
121
- await this.failOccurrence(occurrence, error);
122
- result.failures.push({
123
- name: definition.name,
124
- error: errorDetails(error),
125
- });
126
190
  }
127
191
  }
128
192
  result.finishedAt = new Date();
@@ -0,0 +1,16 @@
1
+ import { ActiveRecord } from '../db/index.js';
2
+ import type { SchedulerCheckpoint } from './contracts/index.js';
3
+ declare const SchedulerCheckpointRecord_base: import("../db/index.js").DefinedActiveRecord<typeof ActiveRecord, {
4
+ id: import("../db/index.js").UlidField;
5
+ name: import("../db/index.js").StringField;
6
+ value: import("../db/index.js").JsonField<{
7
+ evaluatedFor: string;
8
+ } | null>;
9
+ updatedAt: import("../db/index.js").TimestampField;
10
+ }>;
11
+ /** Durable scheduler restart progress; register this model in the application's migration registry. */
12
+ export declare class SchedulerCheckpointRecord extends SchedulerCheckpointRecord_base {
13
+ /** Returns restart persistence for one stable scheduler name; concurrent saves never regress progress. */
14
+ static checkpoint(name?: string): SchedulerCheckpoint;
15
+ }
16
+ export {};
@@ -0,0 +1,53 @@
1
+ import { ActiveRecord } from '../db/index.js';
2
+ /** Durable scheduler restart progress; register this model in the application's migration registry. */
3
+ export class SchedulerCheckpointRecord extends ActiveRecord.define({
4
+ table: 'scheduler_checkpoints',
5
+ fields: field => ({
6
+ id: field.ulid(),
7
+ name: field.string({ required: true, length: 120, unique: true }),
8
+ value: field.json({ required: true }),
9
+ updatedAt: field.timestamp({ column: 'updated_at', auto: 'update' }),
10
+ }),
11
+ }) {
12
+ /** Returns restart persistence for one stable scheduler name; concurrent saves never regress progress. */
13
+ static checkpoint(name = 'default') {
14
+ return {
15
+ /** Establishes coverage before the first dispatch without resetting an existing scheduler. */
16
+ async load(firstMinute) {
17
+ let record = await SchedulerCheckpointRecord.where('name', name).first();
18
+ if (!record) {
19
+ try {
20
+ record = await SchedulerCheckpointRecord.create({ name, value: { evaluatedFor: new Date(firstMinute.getTime() - 60_000).toISOString() } }).save();
21
+ }
22
+ catch (error) {
23
+ record = await SchedulerCheckpointRecord.where('name', name).first();
24
+ if (!record)
25
+ throw error;
26
+ }
27
+ }
28
+ return checkpointMinute(record.value.evaluatedFor);
29
+ },
30
+ /** Advances only a valid, initialized UTC-minute cursor under a database row lock. */
31
+ async save(evaluatedFor) {
32
+ const minute = checkpointMinute(evaluatedFor.toISOString());
33
+ await SchedulerCheckpointRecord.getDb().transaction(transaction => ActiveRecord.withDb(transaction, async () => {
34
+ const row = await SchedulerCheckpointRecord.where('name', name).toKnex().forUpdate().first();
35
+ if (!row)
36
+ throw new Error('Scheduler checkpoint must be initialized before advancing it.');
37
+ const record = SchedulerCheckpointRecord.fromDb(row);
38
+ if (checkpointMinute(record.value.evaluatedFor).getTime() >= minute.getTime())
39
+ return;
40
+ record.value = { evaluatedFor: minute.toISOString() };
41
+ await record.save();
42
+ }));
43
+ },
44
+ };
45
+ }
46
+ }
47
+ /** Rejects corrupt progress rather than silently skipping an unknown scheduling window. */
48
+ function checkpointMinute(value) {
49
+ const minute = new Date(typeof value === 'string' ? value : NaN);
50
+ if (!Number.isFinite(minute.getTime()) || minute.getTime() % 60_000 !== 0)
51
+ throw new Error('Scheduler checkpoint requires a valid UTC minute.');
52
+ return minute;
53
+ }
@@ -14,7 +14,9 @@ export declare class SchedulerWorker {
14
14
  */
15
15
  constructor(schedulerService: Scheduler, options?: scheduler.SchedulerWorkerOptions);
16
16
  /**
17
- * Runs immediately, then evaluates at each subsequent wall-clock minute.
17
+ * Evaluates every uncovered minute in order, including time spent dispatching
18
+ * earlier batches. Catch-up yields after sixty minutes without discarding work.
19
+ * A durable checkpoint resumes coverage across replacement processes.
18
20
  *
19
21
  * @throws Error when the same worker instance is started twice.
20
22
  */
@@ -23,10 +25,6 @@ export declare class SchedulerWorker {
23
25
  * Requests graceful shutdown and interrupts the current minute wait.
24
26
  */
25
27
  stop(): void;
26
- /**
27
- * Evaluates one scheduler minute and reports failures without ending work.
28
- */
29
- private runTick;
30
28
  }
31
29
  /**
32
30
  * Calculates the delay from one instant to the next UTC minute boundary.
@@ -1,4 +1,8 @@
1
+ import { utcMinute } from './scheduleTime.js';
1
2
  const DEFAULT_SLOW_TICK_WARNING_MS = 50_000;
3
+ const MINUTE_MS = 60_000;
4
+ const MAX_MINUTES_PER_BATCH = 60;
5
+ const FAILED_TICK_RETRY_MS = 1_000;
2
6
  /**
3
7
  * Long-running minute-aligned process adapter around Scheduler.runDue().
4
8
  */
@@ -7,6 +11,9 @@ export class SchedulerWorker {
7
11
  #running = false;
8
12
  #abortController = null;
9
13
  #now;
14
+ #nextMinute = null;
15
+ #onTick;
16
+ #checkpoint;
10
17
  #sleep;
11
18
  #logger;
12
19
  #slowTickWarningMs;
@@ -18,6 +25,8 @@ export class SchedulerWorker {
18
25
  */
19
26
  constructor(schedulerService, options = {}) {
20
27
  this.schedulerService = schedulerService;
28
+ this.#onTick = options.onTick;
29
+ this.#checkpoint = options.checkpoint;
21
30
  this.#now = options.now ?? (() => new Date());
22
31
  this.#sleep = options.sleep ?? schedulerSleep;
23
32
  this.#logger = options.logger ?? consoleSchedulerLogger();
@@ -25,7 +34,9 @@ export class SchedulerWorker {
25
34
  ?? DEFAULT_SLOW_TICK_WARNING_MS;
26
35
  }
27
36
  /**
28
- * Runs immediately, then evaluates at each subsequent wall-clock minute.
37
+ * Evaluates every uncovered minute in order, including time spent dispatching
38
+ * earlier batches. Catch-up yields after sixty minutes without discarding work.
39
+ * A durable checkpoint resumes coverage across replacement processes.
29
40
  *
30
41
  * @throws Error when the same worker instance is started twice.
31
42
  */
@@ -36,11 +47,30 @@ export class SchedulerWorker {
36
47
  this.#running = true;
37
48
  this.#abortController = new AbortController();
38
49
  try {
50
+ if (this.#nextMinute === null) {
51
+ const firstMinute = utcMinute(this.#now());
52
+ const previous = await this.#checkpoint?.load(firstMinute);
53
+ this.#nextMinute = previous ? utcMinute(previous).getTime() + MINUTE_MS : firstMinute.getTime();
54
+ }
55
+ let batchSize = 0;
39
56
  while (this.#running) {
40
- await this.runTick();
41
- if (!this.#running)
42
- break;
43
- await this.#sleep(millisecondsUntilNextMinute(this.#now()), this.#abortController.signal);
57
+ const now = this.#now();
58
+ const currentMinute = utcMinute(now).getTime();
59
+ if (this.#nextMinute <= currentMinute) {
60
+ const completed = await this.#runTick(new Date(this.#nextMinute));
61
+ if (completed)
62
+ this.#nextMinute += MINUTE_MS;
63
+ if (!this.#running)
64
+ break;
65
+ if (!completed || ++batchSize >= MAX_MINUTES_PER_BATCH) {
66
+ await this.#sleep(completed ? 1 : FAILED_TICK_RETRY_MS, this.#abortController.signal);
67
+ batchSize = 0;
68
+ }
69
+ continue;
70
+ }
71
+ batchSize = 0;
72
+ // An early timer or backward clock step must not skip or repeat a minute.
73
+ await this.#sleep(Math.min(MINUTE_MS, Math.max(1, this.#nextMinute - now.getTime())), this.#abortController.signal);
44
74
  }
45
75
  }
46
76
  finally {
@@ -56,12 +86,22 @@ export class SchedulerWorker {
56
86
  this.#abortController?.abort();
57
87
  }
58
88
  /**
59
- * Evaluates one scheduler minute and reports failures without ending work.
89
+ * Evaluates one fixed minute, preserving progress only after the whole batch.
90
+ * Recorded event failures remain visible and do not prevent later minutes;
91
+ * incomplete evaluations and checkpoint failures retry this same minute.
92
+ *
93
+ * @param evaluatedFor - Original scheduled minute, independent of dispatch duration.
94
+ * @returns Whether the complete minute was evaluated and its checkpoint saved.
60
95
  */
61
- async runTick() {
96
+ async #runTick(evaluatedFor) {
62
97
  const startedAt = performance.now();
98
+ let completed = false;
63
99
  try {
64
- const result = await this.schedulerService.runDue(this.#now());
100
+ const result = await this.schedulerService.runDue(evaluatedFor);
101
+ if (result.failures.length === 0)
102
+ await this.#onTick?.(result);
103
+ await this.#checkpoint?.save(evaluatedFor);
104
+ completed = true;
65
105
  if (result.due > 0 || result.failures.length > 0) {
66
106
  this.#logger.info(`[scheduler] ${result.evaluatedFor.toISOString()} due=${result.due} claimed=${result.claimed} dispatched=${result.dispatched} completed=${result.completed} skipped=${result.skipped} failed=${result.failures.length}.`);
67
107
  }
@@ -70,12 +110,13 @@ export class SchedulerWorker {
70
110
  }
71
111
  }
72
112
  catch (error) {
73
- this.#logger.error('[scheduler] Tick failed; the worker will continue.', error);
113
+ this.#logger.error(`[scheduler] Evaluation for ${evaluatedFor.toISOString()} did not finish; retrying the same minute.`, error);
74
114
  }
75
115
  const durationMs = performance.now() - startedAt;
76
116
  if (durationMs >= this.#slowTickWarningMs) {
77
117
  this.#logger.warn(`[scheduler] Tick took ${Math.round(durationMs)}ms; inline calls should remain short.`);
78
118
  }
119
+ return completed;
79
120
  }
80
121
  }
81
122
  /**
@@ -96,13 +137,16 @@ export function millisecondsUntilNextMinute(now) {
96
137
  */
97
138
  async function schedulerSleep(delayMs, signal) {
98
139
  await new Promise(resolve => {
99
- const timeout = setTimeout(resolve, delayMs);
100
- signal.addEventListener('abort', () => {
140
+ /** Clears the timer and its abort subscription on either completion path. */
141
+ const finish = () => {
101
142
  clearTimeout(timeout);
143
+ signal.removeEventListener('abort', finish);
102
144
  resolve();
103
- }, {
104
- once: true,
105
- });
145
+ };
146
+ const timeout = setTimeout(finish, delayMs);
147
+ signal.addEventListener('abort', finish, { once: true });
148
+ if (signal.aborted)
149
+ finish();
106
150
  });
107
151
  }
108
152
  /**