@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
@@ -0,0 +1,93 @@
1
+ import { errorCodeForStatus, isDevelopmentEnvironment, isSqlError } from '@db3.ai/pure';
2
+ import { ulid } from '@db3.ai/pure/ulid';
3
+ import { RecordNotFoundError } from '../db/index.js';
4
+ import { publicServerErrorMessage } from './publicServerErrorMessage.js';
5
+ import { registerBrowserJsonFormatting } from './registerBrowserJsonFormatting.js';
6
+ /**
7
+ * Installs framework error logging and production-safe HTTP responses.
8
+ *
9
+ * Call immediately after constructing Fastify, before registering any routes or
10
+ * plugins. The inherited send hook also sanitizes explicit 5xx responses and
11
+ * child-plugin error handlers. Only deliberate mapped client errors and Fastify
12
+ * request errors retain public messages. Browser JSON formatting is installed
13
+ * after this boundary so it only sees the safe serialized response. Never send
14
+ * internal errors as 2xx data.
15
+ *
16
+ * @param fastify - HTTP host, still owned and closed by the caller.
17
+ * @param options - Application error classification and support-record observer.
18
+ * @example
19
+ * const server = Fastify({ logger: true });
20
+ * registerHttpErrorHandler(server);
21
+ * server.get('/example', async () => loadExample());
22
+ */
23
+ export function registerHttpErrorHandler(fastify, options = {}) {
24
+ const failures = new WeakMap();
25
+ /** Records the original exception once, keeping support-store failures private. */
26
+ function recordFailure(request, reply, error, responseBody) {
27
+ const existing = failures.get(reply);
28
+ if (existing?.reference)
29
+ return existing.reference;
30
+ const reference = ulid();
31
+ failures.set(reply, { error, reference });
32
+ const context = { request, statusCode: reply.statusCode, reference, responseBody };
33
+ request.log.error({ err: error, requestMethod: request.method, requestUrl: request.url, statusCode: reply.statusCode, reference, responseBody }, 'Request failed with server error');
34
+ try {
35
+ options.onServerError?.(error, context);
36
+ }
37
+ catch (observerError) {
38
+ request.log.error({ err: observerError, reference }, 'Server error observer failed');
39
+ }
40
+ return reference;
41
+ }
42
+ fastify.addHook('onError', (_request, reply, error, done) => {
43
+ failures.set(reply, { error });
44
+ done();
45
+ });
46
+ fastify.setErrorHandler((error, request, reply) => {
47
+ const mapped = isSqlError(error) ? undefined : options.mapError?.(error);
48
+ const response = mapped && Number.isInteger(mapped.statusCode) && mapped.statusCode >= 400 && mapped.statusCode <= 599
49
+ ? mapped
50
+ : defaultErrorResponse(error);
51
+ reply.type('application/json').code(response.statusCode);
52
+ if (response.statusCode < 500)
53
+ return reply.send(response.body);
54
+ const reference = recordFailure(request, reply, error);
55
+ return reply.send({ ...response.body, reference });
56
+ });
57
+ fastify.addHook('onSend', (request, reply, payload, done) => {
58
+ const failure = failures.get(reply);
59
+ if (reply.statusCode < 500) {
60
+ if (!isSqlError(failure?.error))
61
+ return done(null, payload);
62
+ // A child handler cannot make a database failure public by labelling
63
+ // it a client error or a successful response.
64
+ reply.code(500);
65
+ }
66
+ const responseBody = typeof payload === 'string' ? payload : Buffer.isBuffer(payload) ? payload.toString('utf8') : undefined;
67
+ const reference = recordFailure(request, reply, failure?.error ?? new Error(`HTTP ${reply.statusCode} response`), responseBody);
68
+ if (isDevelopmentEnvironment(process.env.NODE_ENV))
69
+ return done(null, payload);
70
+ // Replace the serialized body too: route schemas and child handlers must
71
+ // not reintroduce stack traces, SQL, provider codes or arbitrary metadata.
72
+ if (payload && typeof payload === 'object' && 'destroy' in payload && typeof payload.destroy === 'function')
73
+ payload.destroy();
74
+ reply.removeHeader('content-length');
75
+ reply.removeHeader('content-encoding');
76
+ reply.type('application/json').header('cache-control', 'no-store');
77
+ return done(null, JSON.stringify({ error: 'server_error', message: publicServerErrorMessage(failure?.error), reference }));
78
+ });
79
+ registerBrowserJsonFormatting(fastify);
80
+ }
81
+ /** Classifies framework client errors without trusting third-party status codes. */
82
+ function defaultErrorResponse(error) {
83
+ if (!isSqlError(error) && error instanceof RecordNotFoundError) {
84
+ return { statusCode: 404, body: { error: 'not_found', message: error.message } };
85
+ }
86
+ if (!isSqlError(error) && error instanceof Error) {
87
+ const { code, statusCode } = error;
88
+ if (typeof code === 'string' && code.startsWith('FST_') && typeof statusCode === 'number' && Number.isInteger(statusCode) && statusCode >= 400 && statusCode < 500) {
89
+ return { statusCode, body: { error: errorCodeForStatus(statusCode), message: error.message } };
90
+ }
91
+ }
92
+ return { statusCode: 500, body: { error: 'server_error', message: publicServerErrorMessage(error) } };
93
+ }
@@ -28,6 +28,8 @@ export interface FastifyViteSsrOptions<TState extends object = SsrState> {
28
28
  template?: string;
29
29
  /** Vite development server-entry module id. */
30
30
  developmentEntry?: string;
31
+ /** Additional development-only Vite source routes, for example ['/client/*', '/apps/*']. */
32
+ developmentAssetRoutes?: readonly string[];
31
33
  /** Production client build directory containing the transformed template. */
32
34
  clientOutDir?: string;
33
35
  /** Production server bundle exporting the application renderer. */
@@ -46,7 +46,7 @@ export function fastifyViteSsr(options) {
46
46
  const runtime = await developmentRuntime(server.server, options);
47
47
  await server.register((await import('@fastify/middie')).default);
48
48
  server.use(runtime.vite.middlewares);
49
- registerDevelopmentAssetRoutes(server);
49
+ registerDevelopmentAssetRoutes(server, options.developmentAssetRoutes);
50
50
  server.addHook('onClose', async () => {
51
51
  await runtime.vite.close();
52
52
  });
@@ -82,9 +82,10 @@ export function fastifyViteSsr(options) {
82
82
  * application's ordinary not-found boundary remains authoritative.
83
83
  *
84
84
  * @param server - Encapsulated Fastify instance hosting the Vite middleware.
85
+ * @param additionalRoutes - Explicit browser source namespaces owned by this application.
85
86
  */
86
- function registerDevelopmentAssetRoutes(server) {
87
- for (const route of DEVELOPMENT_ASSET_ROUTES) {
87
+ function registerDevelopmentAssetRoutes(server, additionalRoutes = []) {
88
+ for (const route of new Set([...DEVELOPMENT_ASSET_ROUTES, ...additionalRoutes])) {
88
89
  server.get(route, (_request, reply) => reply.callNotFound());
89
90
  }
90
91
  }
@@ -1,5 +1,5 @@
1
- import { storageContentsToBuffer } from '../contents.js';
2
- import { mimeTypeFromPath } from '../mime.js';
1
+ import { storageContentsToBuffer } from '../storageContentsToBuffer.js';
2
+ import { mimeTypeFromPath } from '../mimeTypeFromPath.js';
3
3
  import { normalizeStorageDirectoryPath, normalizeStoragePath } from '../path.js';
4
4
  import { FlystorageListing } from './FlystorageListing.js';
5
5
  /**
@@ -1,7 +1,7 @@
1
1
  export * from './Storage.js';
2
- export * from './contents.js';
2
+ export * from './storageContentsToBuffer.js';
3
3
  export * from './contracts/index.js';
4
4
  export * from './drivers/index.js';
5
- export * from './mime.js';
5
+ export * from './mimeTypeFromPath.js';
6
6
  export * from './path.js';
7
7
  export * from './types.js';
@@ -1,7 +1,7 @@
1
1
  export * from './Storage.js';
2
- export * from './contents.js';
2
+ export * from './storageContentsToBuffer.js';
3
3
  export * from './contracts/index.js';
4
4
  export * from './drivers/index.js';
5
- export * from './mime.js';
5
+ export * from './mimeTypeFromPath.js';
6
6
  export * from './path.js';
7
7
  export * from './types.js';
@@ -0,0 +1,18 @@
1
+ import type { WebSocketContext, WebSocketChannelDefinition } from './contracts/index.js';
2
+ /** Local fan-out for trusted server memberships and authorized browser subscriptions. */
3
+ export declare class WebSocketChannels {
4
+ #private;
5
+ /** Joins an already-authorized connection and automatically leaves when its signal aborts. */
6
+ join(name: string, context: WebSocketContext<any>): () => void;
7
+ /** Sends JSON to current local members. Returns accepted transport sends, never durable delivery. */
8
+ publish(name: string, data: unknown): Promise<number>;
9
+ /**
10
+ * Handles the reserved subscription protocol. Unknown channels and denied access reveal no payload.
11
+ * @returns Whether this was a framework subscription command.
12
+ */
13
+ handle(definitions: readonly WebSocketChannelDefinition[], context: WebSocketContext<any>, data: unknown): Promise<boolean>;
14
+ /** Publishes a named event only to current authorized resource subscribers in this process. */
15
+ publishEvent(name: string, event: string, data: unknown): Promise<number>;
16
+ /** Drops local memberships during application shutdown. */
17
+ clear(): void;
18
+ }
@@ -0,0 +1,129 @@
1
+ /** Local fan-out for trusted server memberships and authorized browser subscriptions. */
2
+ export class WebSocketChannels {
3
+ #subscriptions = new Map();
4
+ #counts = new Map();
5
+ #channels = new Map();
6
+ /** Joins an already-authorized connection and automatically leaves when its signal aborts. */
7
+ join(name, context) {
8
+ if (context.signal.aborted)
9
+ return () => { };
10
+ let members = this.#channels.get(name);
11
+ if (!members) {
12
+ members = new Map();
13
+ this.#channels.set(name, members);
14
+ }
15
+ const existing = members.get(context.id);
16
+ if (existing)
17
+ return existing.leave;
18
+ /** Removes only this membership and releases its abort listener. */
19
+ const leave = () => {
20
+ if (members.get(context.id)?.context === context)
21
+ members.delete(context.id);
22
+ if (!members.size && this.#channels.get(name) === members)
23
+ this.#channels.delete(name);
24
+ context.signal.removeEventListener('abort', leave);
25
+ };
26
+ context.signal.addEventListener('abort', leave, { once: true });
27
+ members.set(context.id, { context, leave });
28
+ return leave;
29
+ }
30
+ /** Sends JSON to current local members. Returns accepted transport sends, never durable delivery. */
31
+ async publish(name, data) {
32
+ const results = await Promise.all([...this.#channels.get(name)?.values() ?? []].map(member => member.context.send(data)));
33
+ return results.filter(Boolean).length;
34
+ }
35
+ /**
36
+ * Handles the reserved subscription protocol. Unknown channels and denied access reveal no payload.
37
+ * @returns Whether this was a framework subscription command.
38
+ */
39
+ async handle(definitions, context, data) {
40
+ if (!data || typeof data !== 'object' || !('type' in data) || !['channel.subscribe', 'channel.unsubscribe'].includes(String(data.type)))
41
+ return false;
42
+ const name = 'channel' in data ? data.channel : null;
43
+ if (typeof name !== 'string' || name.length > 256 || !/^[a-zA-Z0-9_.-]+(?::[a-zA-Z0-9_.-]+)*$/.test(name)) {
44
+ context.close();
45
+ return true;
46
+ }
47
+ const existing = this.#subscriptions.get(name)?.get(context.id);
48
+ if (data.type === 'channel.unsubscribe') {
49
+ existing?.leave();
50
+ return true;
51
+ }
52
+ const matches = definitions.map(definition => ({ definition, params: matchChannel(definition.pattern, name) })).filter(match => match.params !== null);
53
+ const match = matches.length === 1 ? matches[0] : undefined;
54
+ if (!context.user || !context.userId || !match || !await match.definition.authorize({ ...context, userId: context.userId, channel: name, params: match.params })) {
55
+ existing?.leave();
56
+ await context.send({ type: 'channel.denied', channel: name });
57
+ return true;
58
+ }
59
+ if (context.signal.aborted)
60
+ return true;
61
+ if (!existing) {
62
+ if ((this.#counts.get(context.id) ?? 0) >= 128) {
63
+ await context.send({ type: 'channel.denied', channel: name });
64
+ return true;
65
+ }
66
+ let members = this.#subscriptions.get(name);
67
+ if (!members) {
68
+ members = new Map();
69
+ this.#subscriptions.set(name, members);
70
+ }
71
+ /** Removes this connection's subscription exactly once, including during in-flight authorization. */
72
+ const leave = () => {
73
+ if (!members.delete(context.id))
74
+ return;
75
+ if (!members.size)
76
+ this.#subscriptions.delete(name);
77
+ const count = (this.#counts.get(context.id) ?? 1) - 1;
78
+ if (count)
79
+ this.#counts.set(context.id, count);
80
+ else
81
+ this.#counts.delete(context.id);
82
+ context.signal.removeEventListener('abort', leave);
83
+ };
84
+ members.set(context.id, { context, definition: match.definition, params: match.params, leave });
85
+ this.#counts.set(context.id, (this.#counts.get(context.id) ?? 0) + 1);
86
+ context.signal.addEventListener('abort', leave, { once: true });
87
+ }
88
+ await context.send({ type: 'channel.subscribed', channel: name });
89
+ return true;
90
+ }
91
+ /** Publishes a named event only to current authorized resource subscribers in this process. */
92
+ async publishEvent(name, event, data) {
93
+ if (!event || event.length > 256)
94
+ throw new Error('Invalid channel event.');
95
+ const members = this.#subscriptions.get(name);
96
+ const results = await Promise.all([...members?.values() ?? []].map(member => member.context.send({ type: 'channel.event', channel: name, event, data }, async (context) => {
97
+ if (members?.get(context.id) !== member)
98
+ return false;
99
+ if (!context.user || !context.userId || !await member.definition.authorize({ ...context, userId: context.userId, channel: name, params: member.params })) {
100
+ member.leave();
101
+ return false;
102
+ }
103
+ return members?.get(context.id) === member;
104
+ })));
105
+ return results.filter(Boolean).length;
106
+ }
107
+ /** Drops local memberships during application shutdown. */
108
+ clear() { for (const members of this.#subscriptions.values())
109
+ for (const member of members.values())
110
+ member.leave(); for (const members of this.#channels.values())
111
+ for (const member of members.values())
112
+ member.leave(); }
113
+ }
114
+ /** Matches whole colon-delimited segments; parameter values never include separators. */
115
+ function matchChannel(pattern, name) {
116
+ const expected = pattern.split(':');
117
+ const actual = name.split(':');
118
+ if (expected.length !== actual.length)
119
+ return null;
120
+ const params = Object.create(null);
121
+ for (let index = 0; index < expected.length; index++) {
122
+ const segment = expected[index];
123
+ if (/^\{[a-zA-Z][a-zA-Z0-9_]*\}$/.test(segment))
124
+ params[segment.slice(1, -1)] = actual[index];
125
+ else if (segment !== actual[index])
126
+ return null;
127
+ }
128
+ return params;
129
+ }
@@ -0,0 +1,25 @@
1
+ import type { IncomingMessage } from 'node:http';
2
+ import { WebSocket } from 'ws';
3
+ import type { App } from '../server/App.js';
4
+ import type * as socket from './contracts/index.js';
5
+ /** One bounded JSON connection with fresh request authentication for application work. */
6
+ export declare class WebSocketConnection {
7
+ #private;
8
+ readonly ws: WebSocket;
9
+ readonly request: IncomingMessage;
10
+ readonly app: App;
11
+ readonly endpoint: socket.WebSocketEndpoint<any, any>;
12
+ readonly limits: socket.WebSocketLimits;
13
+ readonly report: (error: unknown) => void;
14
+ readonly presenceChanged: () => void;
15
+ readonly resolveToken?: socket.WebSocketOptions['resolveToken'];
16
+ readonly id: `${string}-${string}-${string}-${string}-${string}`;
17
+ /** Attaches listeners synchronously so early frames cannot bypass authentication. */
18
+ constructor(ws: WebSocket, request: IncomingMessage, app: App, endpoint: socket.WebSocketEndpoint<any, any>, limits: socket.WebSocketLimits, report: (error: unknown) => void, presenceChanged: () => void, resolveToken?: socket.WebSocketOptions['resolveToken']);
19
+ /** Stops delivery immediately and bounds the close handshake for unresponsive peers. */
20
+ stop(code?: number): void;
21
+ /** Resolves when the socket and application cleanup are finished. */
22
+ finished(): Promise<void>;
23
+ /** Returns local presence only after authorization and until shutdown/disconnection. */
24
+ get userId(): string | null;
25
+ }
@@ -0,0 +1,244 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { WebSocket } from 'ws';
3
+ /** One bounded JSON connection with fresh request authentication for application work. */
4
+ export class WebSocketConnection {
5
+ ws;
6
+ request;
7
+ app;
8
+ endpoint;
9
+ limits;
10
+ report;
11
+ presenceChanged;
12
+ resolveToken;
13
+ id = randomUUID();
14
+ #abort = new AbortController();
15
+ #token = '';
16
+ #userId = '';
17
+ #ready = false;
18
+ #pending = 0;
19
+ /** Bounds retained payloads and concurrent access checks before transport buffering. */
20
+ #pendingSends = 0;
21
+ #chain = Promise.resolve();
22
+ #alive = true;
23
+ #checking = false;
24
+ #timer;
25
+ #heartbeat;
26
+ #finished;
27
+ #finish;
28
+ /** Attaches listeners synchronously so early frames cannot bypass authentication. */
29
+ constructor(ws, request, app, endpoint, limits, report, presenceChanged, resolveToken) {
30
+ this.ws = ws;
31
+ this.request = request;
32
+ this.app = app;
33
+ this.endpoint = endpoint;
34
+ this.limits = limits;
35
+ this.report = report;
36
+ this.presenceChanged = presenceChanged;
37
+ this.resolveToken = resolveToken;
38
+ this.#finished = new Promise(resolve => { this.#finish = resolve; });
39
+ this.#abort.signal.addEventListener('abort', () => { if (this.#ready)
40
+ this.presenceChanged(); }, { once: true });
41
+ this.#timer = setTimeout(() => this.stop(4401), limits.authTimeoutMs);
42
+ this.#heartbeat = setInterval(() => void this.#tick(), limits.heartbeatMs);
43
+ this.#timer.unref();
44
+ this.#heartbeat.unref();
45
+ ws.on('pong', () => { this.#alive = true; });
46
+ ws.on('error', () => this.stop(1011));
47
+ ws.on('message', (data, binary) => this.#receive(data, binary));
48
+ ws.once('close', code => {
49
+ this.#abort.abort();
50
+ this.#token = '';
51
+ clearTimeout(this.#timer);
52
+ clearInterval(this.#heartbeat);
53
+ // Wait for open/message work before cleanup, including an open action that closed itself.
54
+ void this.#chain.then(async () => {
55
+ if (this.#ready)
56
+ await this.endpoint.close?.({ id: this.id, userId: this.#userId || null, code });
57
+ }).catch(this.report).finally(this.#finish);
58
+ });
59
+ }
60
+ /** Stops delivery immediately and bounds the close handshake for unresponsive peers. */
61
+ stop(code = 1000) {
62
+ if (this.#abort.signal.aborted)
63
+ return;
64
+ this.#abort.abort();
65
+ clearTimeout(this.#timer);
66
+ clearInterval(this.#heartbeat);
67
+ this.ws.close(code);
68
+ this.#timer = setTimeout(() => this.ws.terminate(), this.limits.shutdownTimeoutMs);
69
+ this.#timer.unref();
70
+ }
71
+ /** Resolves when the socket and application cleanup are finished. */
72
+ finished() { return this.#finished; }
73
+ /** Returns local presence only after authorization and until shutdown/disconnection. */
74
+ get userId() { return this.#ready && !this.#abort.signal.aborted ? this.#userId : null; }
75
+ /** Queues bounded text messages; the first frame is reserved for authentication. */
76
+ #receive(data, binary) {
77
+ if (this.#abort.signal.aborted)
78
+ return;
79
+ if (binary) {
80
+ this.stop(1003);
81
+ return;
82
+ }
83
+ if (++this.#pending > this.limits.maxPendingMessages) {
84
+ this.stop(1008);
85
+ return;
86
+ }
87
+ const text = data.toString();
88
+ this.#chain = this.#chain.then(async () => {
89
+ if (this.#abort.signal.aborted)
90
+ return;
91
+ let frame;
92
+ try {
93
+ frame = JSON.parse(text);
94
+ }
95
+ catch {
96
+ this.stop(1007);
97
+ return;
98
+ }
99
+ if (!this.#ready) {
100
+ if (this.endpoint.auth === 'public') {
101
+ if (frame?.type !== 'connect') {
102
+ this.stop(1008);
103
+ return;
104
+ }
105
+ }
106
+ else {
107
+ if (frame?.type !== 'authenticate') {
108
+ this.stop(4401);
109
+ return;
110
+ }
111
+ const token = this.resolveToken ? await this.resolveToken(this.request) : frame.token;
112
+ if (typeof token !== 'string' || !token || token.length > 4096) {
113
+ this.stop(4401);
114
+ return;
115
+ }
116
+ this.#token = token;
117
+ }
118
+ await this.#authorized(async (context) => {
119
+ this.#ready = true;
120
+ clearTimeout(this.#timer);
121
+ this.#write({ type: 'ready' });
122
+ this.presenceChanged();
123
+ await this.endpoint.open?.(context);
124
+ });
125
+ return;
126
+ }
127
+ if (frame?.type !== 'message' || !Object.hasOwn(frame, 'data')) {
128
+ this.stop(1008);
129
+ return;
130
+ }
131
+ await this.#authorized(async (context) => {
132
+ if (await this.app.webSockets.channels.handle(this.endpoint.channels ?? [], context, frame.data))
133
+ return;
134
+ let data;
135
+ try {
136
+ data = this.endpoint.parse ? await this.endpoint.parse(frame.data) : frame.data;
137
+ }
138
+ catch {
139
+ this.stop(1008);
140
+ return;
141
+ }
142
+ if (!this.#abort.signal.aborted)
143
+ await this.endpoint.message?.(context, data);
144
+ });
145
+ }).catch(error => { this.report(error); this.stop(1011); }).finally(() => { this.#pending--; });
146
+ }
147
+ /** Revalidates sessions and application access without retaining request-scoped Auth memoization. */
148
+ async #authorized(action) {
149
+ if (this.#abort.signal.aborted)
150
+ return false;
151
+ return this.app.requestContext.run(async () => {
152
+ const publicEndpoint = this.endpoint.auth === 'public';
153
+ const user = publicEndpoint ? null : await this.app.auth.authenticateToken(this.#token);
154
+ if (this.#abort.signal.aborted)
155
+ return false;
156
+ if (!publicEndpoint && !user) {
157
+ this.stop(4401);
158
+ return false;
159
+ }
160
+ const userId = user ? String(user.get(user.constructor.primaryKey)) : null;
161
+ if (this.#userId && this.#userId !== userId) {
162
+ this.stop(4401);
163
+ return false;
164
+ }
165
+ this.#userId = userId ?? '';
166
+ const context = {
167
+ id: this.id, userId, user, request: this.request, signal: this.#abort.signal,
168
+ send: (data, authorize) => this.#send(data, authorize), close: () => this.stop(),
169
+ };
170
+ if (this.endpoint.authorize && !await this.endpoint.authorize(context)) {
171
+ this.stop(4403);
172
+ return false;
173
+ }
174
+ if (this.#abort.signal.aborted)
175
+ return false;
176
+ await action(context);
177
+ return true;
178
+ });
179
+ }
180
+ /** Bounds in-flight sends before fresh access checks; overload disconnects without queuing or replay. */
181
+ async #send(data, authorize) {
182
+ if (this.#abort.signal.aborted)
183
+ return false;
184
+ if (this.#pendingSends >= this.limits.maxPendingSends) {
185
+ this.stop(1013);
186
+ return false;
187
+ }
188
+ this.#pendingSends++;
189
+ try {
190
+ let sent = false;
191
+ await this.#authorized(async (context) => {
192
+ if (!authorize || await authorize(context))
193
+ sent = this.#write({ type: 'message', data });
194
+ });
195
+ return sent;
196
+ }
197
+ catch (error) {
198
+ this.report(error);
199
+ this.stop(1011);
200
+ return false;
201
+ }
202
+ finally {
203
+ this.#pendingSends--;
204
+ }
205
+ }
206
+ /** Enforces frame and buffered-byte limits before handing data to the socket. */
207
+ #write(frame) {
208
+ if (this.#abort.signal.aborted || this.ws.readyState !== WebSocket.OPEN)
209
+ return false;
210
+ const value = JSON.stringify(frame);
211
+ const bytes = Buffer.byteLength(value);
212
+ if (bytes > this.limits.maxPayloadBytes || this.ws.bufferedAmount + bytes > this.limits.maxBufferedBytes) {
213
+ this.stop(1009);
214
+ return false;
215
+ }
216
+ this.ws.send(value, error => { if (error)
217
+ this.stop(1011); });
218
+ return true;
219
+ }
220
+ /** Detects dead peers and revokes idle authenticated sockets as well as active ones. */
221
+ async #tick() {
222
+ if (this.#abort.signal.aborted)
223
+ return;
224
+ if (!this.#alive || this.#checking) {
225
+ this.stop(1011);
226
+ return;
227
+ }
228
+ this.#alive = false;
229
+ this.ws.ping();
230
+ if (!this.#ready)
231
+ return;
232
+ this.#checking = true;
233
+ try {
234
+ await this.#authorized(async () => { });
235
+ }
236
+ catch (error) {
237
+ this.report(error);
238
+ this.stop(1011);
239
+ }
240
+ finally {
241
+ this.#checking = false;
242
+ }
243
+ }
244
+ }
@@ -0,0 +1,41 @@
1
+ import type { Server } from 'node:http';
2
+ import type { App } from '../server/App.js';
3
+ import { WebSocketChannels } from './WebSocketChannels.js';
4
+ import type * as socket from './contracts/index.js';
5
+ /** App-owned WebSocket endpoints on an existing Node HTTP/S listener. */
6
+ export declare class WebSockets {
7
+ #private;
8
+ readonly app: App;
9
+ readonly options: socket.WebSocketServiceOptions;
10
+ /** Process-local, server-authorized channels. Each delivery rechecks the connection's policy. */
11
+ readonly channels: WebSocketChannels;
12
+ /** Configures worker HTTP delivery without opening a connection or starting a polling loop. */
13
+ constructor(app: App, options?: socket.WebSocketServiceOptions);
14
+ /** Returns a publisher for a concrete authorized resource channel. No client subscription is created. */
15
+ channel(name: string): socket.WebSocketChannelPublisher;
16
+ /**
17
+ * Mounts exact-path endpoint actions on one existing HTTP/S server.
18
+ * @param server - Host-owned listener; the service never opens or closes its port.
19
+ * @param options - Allowed origins, controller definitions and resource limits.
20
+ */
21
+ mount(server: Server, options: socket.WebSocketOptions): void;
22
+ /** Stops accepting upgrades and bounds socket/application cleanup; safe to call repeatedly. */
23
+ close(): Promise<void>;
24
+ /**
25
+ * Lists distinct authenticated users connected to an exact endpoint in this process.
26
+ * Application code must authorize disclosure; this is never exposed automatically.
27
+ * Presence is approximate and excludes the other instance during blue/green overlap.
28
+ * @param path - Registered endpoint path, excluding query parameters.
29
+ * @returns Current user IDs and connection counts; no session tokens or profile data.
30
+ */
31
+ presence(path: string): socket.WebSocketPresence[];
32
+ /**
33
+ * Subscribes to local presence changes on one exact endpoint, without exposing them to browsers.
34
+ * Call presence(path) inside the listener to read current users. The listener has no Auth context
35
+ * and does not serialize asynchronous listeners; connection.send() reauthenticates its recipient.
36
+ * @param path - Exact endpoint whose authenticated connections should be observed.
37
+ * @param listener - Application callback for connect, disconnect or revocation changes.
38
+ * @returns Idempotent unsubscribe callback; register it on the owning connection's abort signal.
39
+ */
40
+ onPresence(path: string, listener: () => void | Promise<void>): () => void;
41
+ }