@qlever-llc/trellis 0.10.22 → 0.11.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (406) hide show
  1. package/esm/auth/mod.d.ts +1 -1
  2. package/esm/auth/mod.d.ts.map +1 -1
  3. package/esm/auth/mod.js +1 -1
  4. package/esm/auth/protocol.d.ts +55 -0
  5. package/esm/auth/protocol.d.ts.map +1 -1
  6. package/esm/browser.d.ts +3 -3
  7. package/esm/browser.d.ts.map +1 -1
  8. package/esm/browser.js +1 -1
  9. package/esm/client_connect.d.ts +12 -3
  10. package/esm/client_connect.d.ts.map +1 -1
  11. package/esm/client_connect.js +112 -7
  12. package/esm/codec.d.ts +7 -6
  13. package/esm/codec.d.ts.map +1 -1
  14. package/esm/codec.js +125 -6
  15. package/esm/contract_support/canonical.d.ts +3 -0
  16. package/esm/contract_support/canonical.d.ts.map +1 -1
  17. package/esm/contract_support/canonical.js +3 -0
  18. package/esm/contract_support/mod.d.ts +125 -10
  19. package/esm/contract_support/mod.d.ts.map +1 -1
  20. package/esm/contract_support/mod.js +159 -5
  21. package/esm/contract_support/protocol.d.ts +92 -7
  22. package/esm/contract_support/protocol.d.ts.map +1 -1
  23. package/esm/contract_support/protocol.js +41 -7
  24. package/esm/contract_support/runtime.d.ts +4 -1
  25. package/esm/contract_support/runtime.d.ts.map +1 -1
  26. package/esm/errors/SchemaValidationError.d.ts +49 -0
  27. package/esm/errors/SchemaValidationError.d.ts.map +1 -0
  28. package/esm/errors/SchemaValidationError.js +67 -0
  29. package/esm/errors/index.d.ts +38 -9
  30. package/esm/errors/index.d.ts.map +1 -1
  31. package/esm/errors/index.js +16 -0
  32. package/esm/generated-sdk/auth/api.d.ts +33 -605
  33. package/esm/generated-sdk/auth/api.d.ts.map +1 -1
  34. package/esm/generated-sdk/auth/api.js +6 -1
  35. package/esm/generated-sdk/auth/client.d.ts +129 -134
  36. package/esm/generated-sdk/auth/client.d.ts.map +1 -1
  37. package/esm/generated-sdk/auth/contract.d.ts +2 -601
  38. package/esm/generated-sdk/auth/contract.d.ts.map +1 -1
  39. package/esm/generated-sdk/auth/contract.js +310 -93
  40. package/esm/generated-sdk/auth/mod.d.ts +1 -1
  41. package/esm/generated-sdk/auth/mod.d.ts.map +1 -1
  42. package/esm/generated-sdk/auth/owned_api.d.ts +88 -86
  43. package/esm/generated-sdk/auth/owned_api.d.ts.map +1 -1
  44. package/esm/generated-sdk/auth/owned_api.js +6 -0
  45. package/esm/generated-sdk/auth/schemas.d.ts +284 -136
  46. package/esm/generated-sdk/auth/schemas.d.ts.map +1 -1
  47. package/esm/generated-sdk/auth/schemas.js +231 -92
  48. package/esm/generated-sdk/auth/types.d.ts +565 -89
  49. package/esm/generated-sdk/auth/types.d.ts.map +1 -1
  50. package/esm/generated-sdk/auth/types.js +1 -1
  51. package/esm/generated-sdk/health/api.d.ts +29 -18
  52. package/esm/generated-sdk/health/api.d.ts.map +1 -1
  53. package/esm/generated-sdk/health/client.d.ts +7 -21
  54. package/esm/generated-sdk/health/client.d.ts.map +1 -1
  55. package/esm/generated-sdk/health/contract.d.ts +2 -15
  56. package/esm/generated-sdk/health/contract.d.ts.map +1 -1
  57. package/esm/generated-sdk/health/contract.js +2 -10
  58. package/esm/generated-sdk/health/mod.d.ts +1 -1
  59. package/esm/generated-sdk/health/mod.d.ts.map +1 -1
  60. package/esm/generated-sdk/health/owned_api.d.ts +2 -2
  61. package/esm/generated-sdk/health/schemas.d.ts +1 -14
  62. package/esm/generated-sdk/health/schemas.d.ts.map +1 -1
  63. package/esm/generated-sdk/health/schemas.js +1 -9
  64. package/esm/generated-sdk/health/types.d.ts +10 -5
  65. package/esm/generated-sdk/health/types.d.ts.map +1 -1
  66. package/esm/generated-sdk/health/types.js +1 -2
  67. package/esm/generated-sdk/jobs/api.d.ts +29 -109
  68. package/esm/generated-sdk/jobs/api.d.ts.map +1 -1
  69. package/esm/generated-sdk/jobs/client.d.ts +21 -33
  70. package/esm/generated-sdk/jobs/client.d.ts.map +1 -1
  71. package/esm/generated-sdk/jobs/contract.d.ts +2 -106
  72. package/esm/generated-sdk/jobs/contract.d.ts.map +1 -1
  73. package/esm/generated-sdk/jobs/contract.js +268 -1
  74. package/esm/generated-sdk/jobs/mod.d.ts +1 -1
  75. package/esm/generated-sdk/jobs/mod.d.ts.map +1 -1
  76. package/esm/generated-sdk/jobs/owned_api.d.ts +22 -9
  77. package/esm/generated-sdk/jobs/owned_api.d.ts.map +1 -1
  78. package/esm/generated-sdk/jobs/owned_api.js +20 -1
  79. package/esm/generated-sdk/jobs/schemas.d.ts +437 -0
  80. package/esm/generated-sdk/jobs/schemas.d.ts.map +1 -1
  81. package/esm/generated-sdk/jobs/schemas.js +211 -0
  82. package/esm/generated-sdk/jobs/types.d.ts +195 -12
  83. package/esm/generated-sdk/jobs/types.d.ts.map +1 -1
  84. package/esm/generated-sdk/jobs/types.js +1 -1
  85. package/esm/generated-sdk/state/api.d.ts +29 -68
  86. package/esm/generated-sdk/state/api.d.ts.map +1 -1
  87. package/esm/generated-sdk/state/client.d.ts +17 -31
  88. package/esm/generated-sdk/state/client.d.ts.map +1 -1
  89. package/esm/generated-sdk/state/contract.d.ts +1 -64
  90. package/esm/generated-sdk/state/contract.d.ts.map +1 -1
  91. package/esm/generated-sdk/state/mod.d.ts +1 -1
  92. package/esm/generated-sdk/state/mod.d.ts.map +1 -1
  93. package/esm/generated-sdk/state/owned_api.d.ts +7 -7
  94. package/esm/generated-sdk/state/types.d.ts +52 -9
  95. package/esm/generated-sdk/state/types.d.ts.map +1 -1
  96. package/esm/generated-sdk/trellis-core/api.d.ts +33 -45
  97. package/esm/generated-sdk/trellis-core/api.d.ts.map +1 -1
  98. package/esm/generated-sdk/trellis-core/api.js +6 -1
  99. package/esm/generated-sdk/trellis-core/client.d.ts +31 -20
  100. package/esm/generated-sdk/trellis-core/client.d.ts.map +1 -1
  101. package/esm/generated-sdk/trellis-core/contract.d.ts +2 -41
  102. package/esm/generated-sdk/trellis-core/contract.d.ts.map +1 -1
  103. package/esm/generated-sdk/trellis-core/contract.js +91 -1
  104. package/esm/generated-sdk/trellis-core/mod.d.ts +1 -1
  105. package/esm/generated-sdk/trellis-core/mod.d.ts.map +1 -1
  106. package/esm/generated-sdk/trellis-core/owned_api.d.ts +4 -4
  107. package/esm/generated-sdk/trellis-core/schemas.d.ts +113 -0
  108. package/esm/generated-sdk/trellis-core/schemas.d.ts.map +1 -1
  109. package/esm/generated-sdk/trellis-core/schemas.js +81 -0
  110. package/esm/generated-sdk/trellis-core/types.d.ts +54 -7
  111. package/esm/generated-sdk/trellis-core/types.d.ts.map +1 -1
  112. package/esm/generated-sdk/trellis-core/types.js +1 -1
  113. package/esm/health.d.ts +1 -1
  114. package/esm/health.d.ts.map +1 -1
  115. package/esm/health.js +1 -1
  116. package/esm/index.d.ts +4 -4
  117. package/esm/index.d.ts.map +1 -1
  118. package/esm/index.js +2 -2
  119. package/esm/jobs.d.ts +69 -3
  120. package/esm/jobs.d.ts.map +1 -1
  121. package/esm/jobs.js +92 -3
  122. package/esm/server/health.d.ts +2 -6
  123. package/esm/server/health.d.ts.map +1 -1
  124. package/esm/server/health_schemas.d.ts +0 -8
  125. package/esm/server/health_schemas.d.ts.map +1 -1
  126. package/esm/server/health_schemas.js +0 -5
  127. package/esm/server/internal_jobs/bindings.d.ts +11 -0
  128. package/esm/server/internal_jobs/bindings.d.ts.map +1 -1
  129. package/esm/server/internal_jobs/job-manager.d.ts +58 -2
  130. package/esm/server/internal_jobs/job-manager.d.ts.map +1 -1
  131. package/esm/server/internal_jobs/job-manager.js +429 -55
  132. package/esm/server/internal_jobs/key-coordinator.d.ts +269 -0
  133. package/esm/server/internal_jobs/key-coordinator.d.ts.map +1 -0
  134. package/esm/server/internal_jobs/key-coordinator.js +677 -0
  135. package/esm/server/internal_jobs/projection.d.ts.map +1 -1
  136. package/esm/server/internal_jobs/projection.js +2 -0
  137. package/esm/server/internal_jobs/runtime-worker.d.ts +5 -1
  138. package/esm/server/internal_jobs/runtime-worker.d.ts.map +1 -1
  139. package/esm/server/internal_jobs/runtime-worker.js +14 -2
  140. package/esm/server/internal_jobs/types.d.ts +5 -5
  141. package/esm/server/internal_jobs/types.d.ts.map +1 -1
  142. package/esm/server/internal_jobs/types.js +6 -0
  143. package/esm/server/runtime.d.ts.map +1 -1
  144. package/esm/server/service.d.ts +81 -112
  145. package/esm/server/service.d.ts.map +1 -1
  146. package/esm/server/service.js +372 -130
  147. package/esm/server.d.ts +3 -3
  148. package/esm/server.d.ts.map +1 -1
  149. package/esm/service/deno.d.ts +1 -1
  150. package/esm/service/deno.d.ts.map +1 -1
  151. package/esm/service/drizzle.d.ts +52 -0
  152. package/esm/service/drizzle.d.ts.map +1 -0
  153. package/esm/service/drizzle.js +108 -0
  154. package/esm/service/mod.d.ts +3 -3
  155. package/esm/service/mod.d.ts.map +1 -1
  156. package/esm/service/mod.js +2 -2
  157. package/esm/service/node.d.ts +1 -1
  158. package/esm/service/node.d.ts.map +1 -1
  159. package/esm/service/outbox_inbox.d.ts +76 -22
  160. package/esm/service/outbox_inbox.d.ts.map +1 -1
  161. package/esm/service/outbox_inbox.js +231 -70
  162. package/esm/telemetry/metrics.d.ts +55 -0
  163. package/esm/telemetry/metrics.d.ts.map +1 -1
  164. package/esm/telemetry/metrics.js +86 -0
  165. package/esm/telemetry/mod.d.ts +2 -1
  166. package/esm/telemetry/mod.d.ts.map +1 -1
  167. package/esm/telemetry/mod.js +1 -1
  168. package/esm/trellis.d.ts +62 -30
  169. package/esm/trellis.d.ts.map +1 -1
  170. package/esm/trellis.js +125 -42
  171. package/package.json +14 -2
  172. package/script/auth/mod.d.ts +1 -1
  173. package/script/auth/mod.d.ts.map +1 -1
  174. package/script/auth/mod.js +11 -4
  175. package/script/auth/protocol.d.ts +55 -0
  176. package/script/auth/protocol.d.ts.map +1 -1
  177. package/script/browser.d.ts +3 -3
  178. package/script/browser.d.ts.map +1 -1
  179. package/script/browser.js +3 -2
  180. package/script/client_connect.d.ts +12 -3
  181. package/script/client_connect.d.ts.map +1 -1
  182. package/script/client_connect.js +111 -6
  183. package/script/codec.d.ts +7 -6
  184. package/script/codec.d.ts.map +1 -1
  185. package/script/codec.js +124 -5
  186. package/script/contract_support/canonical.d.ts +3 -0
  187. package/script/contract_support/canonical.d.ts.map +1 -1
  188. package/script/contract_support/canonical.js +3 -0
  189. package/script/contract_support/mod.d.ts +125 -10
  190. package/script/contract_support/mod.d.ts.map +1 -1
  191. package/script/contract_support/mod.js +165 -5
  192. package/script/contract_support/protocol.d.ts +92 -7
  193. package/script/contract_support/protocol.d.ts.map +1 -1
  194. package/script/contract_support/protocol.js +42 -8
  195. package/script/contract_support/runtime.d.ts +4 -1
  196. package/script/contract_support/runtime.d.ts.map +1 -1
  197. package/script/errors/SchemaValidationError.d.ts +49 -0
  198. package/script/errors/SchemaValidationError.d.ts.map +1 -0
  199. package/script/errors/SchemaValidationError.js +74 -0
  200. package/script/errors/index.d.ts +38 -9
  201. package/script/errors/index.d.ts.map +1 -1
  202. package/script/errors/index.js +20 -1
  203. package/script/generated-sdk/auth/api.d.ts +33 -605
  204. package/script/generated-sdk/auth/api.d.ts.map +1 -1
  205. package/script/generated-sdk/auth/api.js +6 -1
  206. package/script/generated-sdk/auth/client.d.ts +129 -134
  207. package/script/generated-sdk/auth/client.d.ts.map +1 -1
  208. package/script/generated-sdk/auth/contract.d.ts +2 -601
  209. package/script/generated-sdk/auth/contract.d.ts.map +1 -1
  210. package/script/generated-sdk/auth/contract.js +310 -93
  211. package/script/generated-sdk/auth/mod.d.ts +1 -1
  212. package/script/generated-sdk/auth/mod.d.ts.map +1 -1
  213. package/script/generated-sdk/auth/owned_api.d.ts +88 -86
  214. package/script/generated-sdk/auth/owned_api.d.ts.map +1 -1
  215. package/script/generated-sdk/auth/owned_api.js +6 -0
  216. package/script/generated-sdk/auth/schemas.d.ts +284 -136
  217. package/script/generated-sdk/auth/schemas.d.ts.map +1 -1
  218. package/script/generated-sdk/auth/schemas.js +231 -92
  219. package/script/generated-sdk/auth/types.d.ts +565 -89
  220. package/script/generated-sdk/auth/types.d.ts.map +1 -1
  221. package/script/generated-sdk/auth/types.js +1 -1
  222. package/script/generated-sdk/health/api.d.ts +29 -18
  223. package/script/generated-sdk/health/api.d.ts.map +1 -1
  224. package/script/generated-sdk/health/client.d.ts +7 -21
  225. package/script/generated-sdk/health/client.d.ts.map +1 -1
  226. package/script/generated-sdk/health/contract.d.ts +2 -15
  227. package/script/generated-sdk/health/contract.d.ts.map +1 -1
  228. package/script/generated-sdk/health/contract.js +2 -10
  229. package/script/generated-sdk/health/mod.d.ts +1 -1
  230. package/script/generated-sdk/health/mod.d.ts.map +1 -1
  231. package/script/generated-sdk/health/owned_api.d.ts +2 -2
  232. package/script/generated-sdk/health/schemas.d.ts +1 -14
  233. package/script/generated-sdk/health/schemas.d.ts.map +1 -1
  234. package/script/generated-sdk/health/schemas.js +1 -9
  235. package/script/generated-sdk/health/types.d.ts +10 -5
  236. package/script/generated-sdk/health/types.d.ts.map +1 -1
  237. package/script/generated-sdk/health/types.js +1 -2
  238. package/script/generated-sdk/jobs/api.d.ts +29 -109
  239. package/script/generated-sdk/jobs/api.d.ts.map +1 -1
  240. package/script/generated-sdk/jobs/client.d.ts +21 -33
  241. package/script/generated-sdk/jobs/client.d.ts.map +1 -1
  242. package/script/generated-sdk/jobs/contract.d.ts +2 -106
  243. package/script/generated-sdk/jobs/contract.d.ts.map +1 -1
  244. package/script/generated-sdk/jobs/contract.js +268 -1
  245. package/script/generated-sdk/jobs/mod.d.ts +1 -1
  246. package/script/generated-sdk/jobs/mod.d.ts.map +1 -1
  247. package/script/generated-sdk/jobs/owned_api.d.ts +22 -9
  248. package/script/generated-sdk/jobs/owned_api.d.ts.map +1 -1
  249. package/script/generated-sdk/jobs/owned_api.js +19 -0
  250. package/script/generated-sdk/jobs/schemas.d.ts +437 -0
  251. package/script/generated-sdk/jobs/schemas.d.ts.map +1 -1
  252. package/script/generated-sdk/jobs/schemas.js +212 -1
  253. package/script/generated-sdk/jobs/types.d.ts +195 -12
  254. package/script/generated-sdk/jobs/types.d.ts.map +1 -1
  255. package/script/generated-sdk/jobs/types.js +1 -1
  256. package/script/generated-sdk/state/api.d.ts +29 -68
  257. package/script/generated-sdk/state/api.d.ts.map +1 -1
  258. package/script/generated-sdk/state/client.d.ts +17 -31
  259. package/script/generated-sdk/state/client.d.ts.map +1 -1
  260. package/script/generated-sdk/state/contract.d.ts +1 -64
  261. package/script/generated-sdk/state/contract.d.ts.map +1 -1
  262. package/script/generated-sdk/state/mod.d.ts +1 -1
  263. package/script/generated-sdk/state/mod.d.ts.map +1 -1
  264. package/script/generated-sdk/state/owned_api.d.ts +7 -7
  265. package/script/generated-sdk/state/types.d.ts +52 -9
  266. package/script/generated-sdk/state/types.d.ts.map +1 -1
  267. package/script/generated-sdk/trellis-core/api.d.ts +33 -45
  268. package/script/generated-sdk/trellis-core/api.d.ts.map +1 -1
  269. package/script/generated-sdk/trellis-core/api.js +6 -1
  270. package/script/generated-sdk/trellis-core/client.d.ts +31 -20
  271. package/script/generated-sdk/trellis-core/client.d.ts.map +1 -1
  272. package/script/generated-sdk/trellis-core/contract.d.ts +2 -41
  273. package/script/generated-sdk/trellis-core/contract.d.ts.map +1 -1
  274. package/script/generated-sdk/trellis-core/contract.js +91 -1
  275. package/script/generated-sdk/trellis-core/mod.d.ts +1 -1
  276. package/script/generated-sdk/trellis-core/mod.d.ts.map +1 -1
  277. package/script/generated-sdk/trellis-core/owned_api.d.ts +4 -4
  278. package/script/generated-sdk/trellis-core/schemas.d.ts +113 -0
  279. package/script/generated-sdk/trellis-core/schemas.d.ts.map +1 -1
  280. package/script/generated-sdk/trellis-core/schemas.js +81 -0
  281. package/script/generated-sdk/trellis-core/types.d.ts +54 -7
  282. package/script/generated-sdk/trellis-core/types.d.ts.map +1 -1
  283. package/script/generated-sdk/trellis-core/types.js +1 -1
  284. package/script/health.d.ts +1 -1
  285. package/script/health.d.ts.map +1 -1
  286. package/script/health.js +1 -2
  287. package/script/index.d.ts +4 -4
  288. package/script/index.d.ts.map +1 -1
  289. package/script/index.js +2 -2
  290. package/script/jobs.d.ts +69 -3
  291. package/script/jobs.d.ts.map +1 -1
  292. package/script/jobs.js +93 -3
  293. package/script/server/health.d.ts +2 -6
  294. package/script/server/health.d.ts.map +1 -1
  295. package/script/server/health_schemas.d.ts +0 -8
  296. package/script/server/health_schemas.d.ts.map +1 -1
  297. package/script/server/health_schemas.js +1 -6
  298. package/script/server/internal_jobs/bindings.d.ts +11 -0
  299. package/script/server/internal_jobs/bindings.d.ts.map +1 -1
  300. package/script/server/internal_jobs/job-manager.d.ts +58 -2
  301. package/script/server/internal_jobs/job-manager.d.ts.map +1 -1
  302. package/script/server/internal_jobs/job-manager.js +429 -54
  303. package/script/server/internal_jobs/key-coordinator.d.ts +269 -0
  304. package/script/server/internal_jobs/key-coordinator.d.ts.map +1 -0
  305. package/script/server/internal_jobs/key-coordinator.js +690 -0
  306. package/script/server/internal_jobs/projection.d.ts.map +1 -1
  307. package/script/server/internal_jobs/projection.js +2 -0
  308. package/script/server/internal_jobs/runtime-worker.d.ts +5 -1
  309. package/script/server/internal_jobs/runtime-worker.d.ts.map +1 -1
  310. package/script/server/internal_jobs/runtime-worker.js +14 -2
  311. package/script/server/internal_jobs/types.d.ts +5 -5
  312. package/script/server/internal_jobs/types.d.ts.map +1 -1
  313. package/script/server/internal_jobs/types.js +6 -0
  314. package/script/server/runtime.d.ts.map +1 -1
  315. package/script/server/service.d.ts +81 -112
  316. package/script/server/service.d.ts.map +1 -1
  317. package/script/server/service.js +369 -127
  318. package/script/server.d.ts +3 -3
  319. package/script/server.d.ts.map +1 -1
  320. package/script/service/deno.d.ts +1 -1
  321. package/script/service/deno.d.ts.map +1 -1
  322. package/script/service/drizzle.d.ts +52 -0
  323. package/script/service/drizzle.d.ts.map +1 -0
  324. package/script/service/drizzle.js +113 -0
  325. package/script/service/mod.d.ts +3 -3
  326. package/script/service/mod.d.ts.map +1 -1
  327. package/script/service/mod.js +4 -3
  328. package/script/service/node.d.ts +1 -1
  329. package/script/service/node.d.ts.map +1 -1
  330. package/script/service/outbox_inbox.d.ts +76 -22
  331. package/script/service/outbox_inbox.d.ts.map +1 -1
  332. package/script/service/outbox_inbox.js +233 -70
  333. package/script/telemetry/metrics.d.ts +55 -0
  334. package/script/telemetry/metrics.d.ts.map +1 -1
  335. package/script/telemetry/metrics.js +88 -0
  336. package/script/telemetry/mod.d.ts +2 -1
  337. package/script/telemetry/mod.d.ts.map +1 -1
  338. package/script/telemetry/mod.js +3 -1
  339. package/script/trellis.d.ts +62 -30
  340. package/script/trellis.d.ts.map +1 -1
  341. package/script/trellis.js +124 -41
  342. package/src/auth/mod.ts +7 -0
  343. package/src/browser.ts +5 -7
  344. package/src/client_connect.ts +200 -12
  345. package/src/codec.ts +186 -11
  346. package/src/contract_support/canonical.ts +3 -0
  347. package/src/contract_support/mod.ts +380 -9
  348. package/src/contract_support/protocol.ts +57 -10
  349. package/src/contract_support/runtime.ts +7 -0
  350. package/src/errors/SchemaValidationError.ts +67 -0
  351. package/src/errors/index.ts +28 -0
  352. package/src/health.ts +0 -1
  353. package/src/index.ts +7 -8
  354. package/src/jobs.ts +138 -1
  355. package/src/sdk/_generated/auth/api.ts +38 -7
  356. package/src/sdk/_generated/auth/client.ts +168 -530
  357. package/src/sdk/_generated/auth/contract.ts +310 -93
  358. package/src/sdk/_generated/auth/mod.ts +0 -1
  359. package/src/sdk/_generated/auth/owned_api.ts +92 -86
  360. package/src/sdk/_generated/auth/schemas.ts +231 -92
  361. package/src/sdk/_generated/auth/types.ts +1069 -273
  362. package/src/sdk/_generated/core/api.ts +38 -7
  363. package/src/sdk/_generated/core/client.ts +47 -73
  364. package/src/sdk/_generated/core/contract.ts +91 -1
  365. package/src/sdk/_generated/core/mod.ts +0 -1
  366. package/src/sdk/_generated/core/owned_api.ts +4 -4
  367. package/src/sdk/_generated/core/schemas.ts +81 -0
  368. package/src/sdk/_generated/core/types.ts +79 -15
  369. package/src/sdk/_generated/health/api.ts +29 -5
  370. package/src/sdk/_generated/health/client.ts +11 -58
  371. package/src/sdk/_generated/health/contract.ts +2 -10
  372. package/src/sdk/_generated/health/mod.ts +0 -1
  373. package/src/sdk/_generated/health/owned_api.ts +2 -2
  374. package/src/sdk/_generated/health/schemas.ts +1 -9
  375. package/src/sdk/_generated/health/types.ts +23 -2
  376. package/src/sdk/_generated/jobs/api.ts +29 -5
  377. package/src/sdk/_generated/jobs/client.ts +25 -109
  378. package/src/sdk/_generated/jobs/contract.ts +269 -1
  379. package/src/sdk/_generated/jobs/mod.ts +0 -1
  380. package/src/sdk/_generated/jobs/owned_api.ts +30 -9
  381. package/src/sdk/_generated/jobs/schemas.ts +213 -0
  382. package/src/sdk/_generated/jobs/types.ts +252 -18
  383. package/src/sdk/_generated/state/api.ts +29 -5
  384. package/src/sdk/_generated/state/client.ts +18 -95
  385. package/src/sdk/_generated/state/mod.ts +0 -1
  386. package/src/sdk/_generated/state/owned_api.ts +7 -7
  387. package/src/sdk/_generated/state/types.ts +91 -15
  388. package/src/server/health.ts +2 -6
  389. package/src/server/health_schemas.ts +0 -6
  390. package/src/server/internal_jobs/bindings.ts +11 -0
  391. package/src/server/internal_jobs/job-manager.ts +553 -24
  392. package/src/server/internal_jobs/key-coordinator.ts +1080 -0
  393. package/src/server/internal_jobs/projection.ts +2 -0
  394. package/src/server/internal_jobs/runtime-worker.ts +17 -1
  395. package/src/server/internal_jobs/types.ts +6 -0
  396. package/src/server/runtime.ts +4 -0
  397. package/src/server/service.ts +645 -625
  398. package/src/server.ts +14 -7
  399. package/src/service/deno.ts +0 -5
  400. package/src/service/drizzle.ts +184 -0
  401. package/src/service/mod.ts +17 -7
  402. package/src/service/node.ts +0 -5
  403. package/src/service/outbox_inbox.ts +354 -88
  404. package/src/telemetry/metrics.ts +198 -1
  405. package/src/telemetry/mod.ts +6 -0
  406. package/src/trellis.ts +286 -105
@@ -10,63 +10,131 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
10
10
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
11
  };
12
12
  var _MemoryOutboxRepository_messages, _MemoryInboxRepository_seen, _OutboxDispatcher_instances, _OutboxDispatcher_repository, _OutboxDispatcher_runtime, _OutboxDispatcher_options, _OutboxDispatcher_wakeTimer, _OutboxDispatcher_retryTimer, _OutboxDispatcher_idleTimer, _OutboxDispatcher_running, _OutboxDispatcher_pending, _OutboxDispatcher_retryDue, _OutboxDispatcher_stopped, _OutboxDispatcher_scheduleWakeup, _OutboxDispatcher_scheduleRetryWakeup, _OutboxDispatcher_scheduleIdleRetry, _OutboxDispatcher_run, _OutboxDispatcher_dispatchBatch, _OutboxDispatcher_retryDelayMs, _OutboxDispatcher_clearTimer;
13
- import { isErr } from "@qlever-llc/result";
13
+ import { isErr, } from "@qlever-llc/result";
14
14
  import { Type } from "typebox";
15
15
  import { recordTrellisError } from "../telemetry/mod.js";
16
+ /** Default Trellis helper-table names for SQL outbox and inbox storage. */
16
17
  export const defaultSqlOutboxTables = Object.freeze({
17
18
  outbox: "trellis_outbox",
18
19
  inbox: "trellis_inbox",
19
20
  });
21
+ const sqlIdentifierPattern = /^[A-Za-z_][A-Za-z0-9_]*$/;
20
22
  /**
21
- * Creates SQL outbox/inbox repositories plus DDL for caller-owned migrations.
23
+ * Creates SQL outbox/inbox repositories plus current helper-table DDL.
22
24
  *
23
- * Trellis does not import Drizzle here to avoid making every service depend on a
24
- * specific migration library. Services should include the returned DDL, or an
25
- * equivalent Drizzle table definition using these table and column names, in
26
- * their own Drizzle-managed migration flow.
25
+ * Use {@link getSqlOutboxMigrations} when services need versioned Trellis-owned
26
+ * migration artifacts for their normal database migration tooling.
27
27
  */
28
28
  export function createSqlOutboxAdapter(executor, dialect, tables = defaultSqlOutboxTables) {
29
+ const sqlTables = validateSqlOutboxTables(tables);
29
30
  return {
30
- outbox: new SqlOutboxRepository(executor, dialect, tables),
31
- inbox: new SqlInboxRepository(executor, dialect, tables),
31
+ outbox: new SqlOutboxRepository(executor, dialect, sqlTables),
32
+ inbox: new SqlInboxRepository(executor, dialect, sqlTables),
32
33
  ddl: dialect === "postgres"
33
- ? createPostgresOutboxSchema(tables)
34
- : createSqliteOutboxSchema(tables),
34
+ ? createPostgresOutboxSchema(sqlTables)
35
+ : createSqliteOutboxSchema(sqlTables),
35
36
  };
36
37
  }
38
+ /**
39
+ * Returns Trellis-owned SQL outbox/inbox migration artifacts for a dialect.
40
+ *
41
+ * Trellis generates the helper-table SQL, but services remain responsible for
42
+ * running these artifacts through their normal database migration tooling.
43
+ */
44
+ export function getSqlOutboxMigrations(options) {
45
+ const tables = resolveSqlOutboxTables(options.tables);
46
+ const up = options.dialect === "postgres"
47
+ ? createPostgresOutboxSchema(tables)
48
+ : createSqliteOutboxSchema(tables);
49
+ const down = createSqlOutboxDownSchema(tables);
50
+ return Object.freeze([
51
+ Object.freeze({
52
+ id: `trellis_sql_outbox_inbox_${options.dialect}_v1`,
53
+ version: 1,
54
+ dialect: options.dialect,
55
+ up,
56
+ down,
57
+ checksum: checksumMigrationSql(up, down),
58
+ }),
59
+ ]);
60
+ }
37
61
  /** Returns SQLite DDL for Trellis outbox and inbox tables. */
38
62
  export function createSqliteOutboxSchema(tables = defaultSqlOutboxTables) {
63
+ const sqlTables = validateSqlOutboxTables(tables);
39
64
  return [
40
- `CREATE TABLE IF NOT EXISTS ${tables.outbox} (id TEXT PRIMARY KEY, event TEXT NOT NULL, subject TEXT NOT NULL, payload TEXT NOT NULL, headers TEXT NOT NULL, state TEXT NOT NULL, attempts INTEGER NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL, next_attempt_at TEXT, last_error TEXT)`,
41
- `CREATE INDEX IF NOT EXISTS ${tables.outbox}_due_idx ON ${tables.outbox} (state, next_attempt_at)`,
42
- `CREATE TABLE IF NOT EXISTS ${tables.inbox} (message_id TEXT PRIMARY KEY, received_at TEXT NOT NULL)`,
65
+ `CREATE TABLE IF NOT EXISTS ${sqlTables.outbox} (id TEXT PRIMARY KEY, kind TEXT NOT NULL, name TEXT NOT NULL, subject TEXT NOT NULL, payload TEXT NOT NULL, headers TEXT NOT NULL, state TEXT NOT NULL, attempts INTEGER NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL, next_attempt_at TEXT, last_error TEXT, outcome TEXT)`,
66
+ `CREATE INDEX IF NOT EXISTS ${sqlTables.outbox}_due_idx ON ${sqlTables.outbox} (state, next_attempt_at)`,
67
+ `CREATE TABLE IF NOT EXISTS ${sqlTables.inbox} (message_id TEXT PRIMARY KEY, received_at TEXT NOT NULL)`,
43
68
  ];
44
69
  }
45
70
  /** Returns Postgres DDL for Trellis outbox and inbox tables. */
46
71
  export function createPostgresOutboxSchema(tables = defaultSqlOutboxTables) {
72
+ const sqlTables = validateSqlOutboxTables(tables);
47
73
  return [
48
- `CREATE TABLE IF NOT EXISTS ${tables.outbox} (id text PRIMARY KEY, event text NOT NULL, subject text NOT NULL, payload text NOT NULL, headers jsonb NOT NULL, state text NOT NULL, attempts integer NOT NULL, created_at timestamptz NOT NULL, updated_at timestamptz NOT NULL, next_attempt_at timestamptz, last_error text)`,
49
- `CREATE INDEX IF NOT EXISTS ${tables.outbox}_due_idx ON ${tables.outbox} (state, next_attempt_at)`,
50
- `CREATE TABLE IF NOT EXISTS ${tables.inbox} (message_id text PRIMARY KEY, received_at timestamptz NOT NULL)`,
74
+ `CREATE TABLE IF NOT EXISTS ${sqlTables.outbox} (id text PRIMARY KEY, kind text NOT NULL, name text NOT NULL, subject text NOT NULL, payload text NOT NULL, headers jsonb NOT NULL, state text NOT NULL, attempts integer NOT NULL, created_at timestamptz NOT NULL, updated_at timestamptz NOT NULL, next_attempt_at timestamptz, last_error text, outcome jsonb)`,
75
+ `CREATE INDEX IF NOT EXISTS ${sqlTables.outbox}_due_idx ON ${sqlTables.outbox} (state, next_attempt_at)`,
76
+ `CREATE TABLE IF NOT EXISTS ${sqlTables.inbox} (message_id text PRIMARY KEY, received_at timestamptz NOT NULL)`,
51
77
  ];
52
78
  }
79
+ function createSqlOutboxDownSchema(tables) {
80
+ const sqlTables = validateSqlOutboxTables(tables);
81
+ return [
82
+ `DROP INDEX IF EXISTS ${sqlTables.outbox}_due_idx`,
83
+ `DROP TABLE IF EXISTS ${sqlTables.inbox}`,
84
+ `DROP TABLE IF EXISTS ${sqlTables.outbox}`,
85
+ ];
86
+ }
87
+ function resolveSqlOutboxTables(tables) {
88
+ return validateSqlOutboxTables({
89
+ outbox: tables?.outbox ?? defaultSqlOutboxTables.outbox,
90
+ inbox: tables?.inbox ?? defaultSqlOutboxTables.inbox,
91
+ });
92
+ }
93
+ function validateSqlOutboxTables(tables) {
94
+ validateSqlIdentifier("outbox", tables.outbox);
95
+ validateSqlIdentifier("inbox", tables.inbox);
96
+ return Object.freeze({ outbox: tables.outbox, inbox: tables.inbox });
97
+ }
98
+ function validateSqlIdentifier(kind, name) {
99
+ if (!sqlIdentifierPattern.test(name)) {
100
+ throw new Error(`Invalid SQL ${kind} table name "${name}". Use a simple identifier matching ${sqlIdentifierPattern.source}.`);
101
+ }
102
+ }
103
+ function checksumMigrationSql(up, down) {
104
+ return `fnv1a64:${fnv1a64Hex([
105
+ "-- up",
106
+ ...up,
107
+ "-- down",
108
+ ...down,
109
+ ].join("\n"))}`;
110
+ }
111
+ function fnv1a64Hex(input) {
112
+ let hash = 0xcbf29ce484222325n;
113
+ const prime = 0x100000001b3n;
114
+ for (const character of input) {
115
+ hash ^= BigInt(character.codePointAt(0) ?? 0);
116
+ hash = BigInt.asUintN(64, hash * prime);
117
+ }
118
+ return hash.toString(16).padStart(16, "0");
119
+ }
53
120
  /** In-memory outbox repository intended for tests and local process adapters. */
54
121
  export class MemoryOutboxRepository {
55
122
  constructor() {
56
123
  _MemoryOutboxRepository_messages.set(this, new Map());
57
124
  }
58
- async enqueue(event) {
125
+ async enqueue(record) {
59
126
  const now = new Date().toISOString();
60
- const id = messageId(event);
127
+ const id = record.id;
61
128
  const existing = __classPrivateFieldGet(this, _MemoryOutboxRepository_messages, "f").get(id);
62
129
  if (existing)
63
130
  return existing;
64
131
  const message = {
65
132
  id,
66
- event: event.event,
67
- subject: event.subject,
68
- payload: event.encodedPayload,
69
- headers: { ...event.headers },
133
+ kind: record.kind,
134
+ name: record.name,
135
+ subject: record.subject,
136
+ payload: record.payload,
137
+ headers: { ...record.headers },
70
138
  state: "pending",
71
139
  attempts: 0,
72
140
  createdAt: now,
@@ -90,7 +158,7 @@ export class MemoryOutboxRepository {
90
158
  }
91
159
  return claimed;
92
160
  }
93
- async markDispatched(id, now) {
161
+ async markDispatched(id, now, outcome) {
94
162
  const message = __classPrivateFieldGet(this, _MemoryOutboxRepository_messages, "f").get(id);
95
163
  if (!message)
96
164
  return;
@@ -100,6 +168,7 @@ export class MemoryOutboxRepository {
100
168
  updatedAt: now.toISOString(),
101
169
  nextAttemptAt: undefined,
102
170
  lastError: undefined,
171
+ outcome: outcome ?? message.outcome,
103
172
  });
104
173
  }
105
174
  async markFailed(id, failure) {
@@ -155,17 +224,19 @@ export class SqlOutboxRepository {
155
224
  enumerable: true,
156
225
  configurable: true,
157
226
  writable: true,
158
- value: tables
227
+ value: void 0
159
228
  });
229
+ this.tables = validateSqlOutboxTables(tables);
160
230
  }
161
- async enqueue(event) {
231
+ async enqueue(record) {
162
232
  const now = new Date().toISOString();
163
233
  const message = {
164
- id: messageId(event),
165
- event: event.event,
166
- subject: event.subject,
167
- payload: event.encodedPayload,
168
- headers: { ...event.headers },
234
+ id: record.id,
235
+ kind: record.kind,
236
+ name: record.name,
237
+ subject: record.subject,
238
+ payload: record.payload,
239
+ headers: { ...record.headers },
169
240
  state: "pending",
170
241
  attempts: 0,
171
242
  createdAt: now,
@@ -175,9 +246,10 @@ export class SqlOutboxRepository {
175
246
  const conflict = this.dialect === "postgres"
176
247
  ? "ON CONFLICT (id) DO NOTHING"
177
248
  : "ON CONFLICT(id) DO NOTHING";
178
- await this.executor.execute(`INSERT INTO ${this.tables.outbox} (id, event, subject, payload, headers, state, attempts, created_at, updated_at, next_attempt_at, last_error) VALUES (${placeholders(this.dialect, 11)}) ${conflict}`, [
249
+ await this.executor.execute(`INSERT INTO ${this.tables.outbox} (id, kind, name, subject, payload, headers, state, attempts, created_at, updated_at, next_attempt_at, last_error, outcome) VALUES (${placeholders(this.dialect, 13)}) ${conflict}`, [
179
250
  message.id,
180
- message.event,
251
+ message.kind,
252
+ message.name,
181
253
  message.subject,
182
254
  message.payload,
183
255
  headers,
@@ -187,15 +259,17 @@ export class SqlOutboxRepository {
187
259
  message.updatedAt,
188
260
  null,
189
261
  null,
262
+ null,
190
263
  ]);
191
264
  return message;
192
265
  }
193
266
  async claimDue(limit, now) {
194
- const rows = await this.executor.query(`SELECT id, event, subject, payload, headers, state, attempts, created_at, updated_at, next_attempt_at, last_error FROM ${this.tables.outbox} WHERE state != ${placeholder(this.dialect, 1)} AND (next_attempt_at IS NULL OR next_attempt_at <= ${placeholder(this.dialect, 2)}) ORDER BY created_at LIMIT ${placeholder(this.dialect, 3)}`, ["dispatched", now.toISOString(), limit]);
267
+ const rows = await this.executor.query(`SELECT id, kind, name, subject, payload, headers, state, attempts, created_at, updated_at, next_attempt_at, last_error, outcome FROM ${this.tables.outbox} WHERE state != ${placeholder(this.dialect, 1)} AND (next_attempt_at IS NULL OR next_attempt_at <= ${placeholder(this.dialect, 2)}) ORDER BY created_at LIMIT ${placeholder(this.dialect, 3)}`, ["dispatched", now.toISOString(), limit]);
195
268
  return rows.map(rowToOutboxMessage);
196
269
  }
197
- async markDispatched(id, now) {
198
- await this.executor.execute(`UPDATE ${this.tables.outbox} SET state = ${placeholder(this.dialect, 1)}, updated_at = ${placeholder(this.dialect, 2)}, next_attempt_at = NULL, last_error = NULL WHERE id = ${placeholder(this.dialect, 3)}`, ["dispatched", now.toISOString(), id]);
270
+ async markDispatched(id, now, outcome) {
271
+ const outcomeJson = outcome !== undefined ? JSON.stringify(outcome) : null;
272
+ await this.executor.execute(`UPDATE ${this.tables.outbox} SET state = ${placeholder(this.dialect, 1)}, updated_at = ${placeholder(this.dialect, 2)}, next_attempt_at = NULL, last_error = NULL, outcome = ${placeholder(this.dialect, 3)} WHERE id = ${placeholder(this.dialect, 4)}`, ["dispatched", now.toISOString(), outcomeJson, id]);
199
273
  }
200
274
  async markFailed(id, failure) {
201
275
  await this.executor.execute(`UPDATE ${this.tables.outbox} SET state = ${placeholder(this.dialect, 1)}, attempts = attempts + 1, updated_at = ${placeholder(this.dialect, 2)}, next_attempt_at = ${placeholder(this.dialect, 3)}, last_error = ${placeholder(this.dialect, 4)} WHERE id = ${placeholder(this.dialect, 5)}`, [
@@ -226,8 +300,9 @@ export class SqlInboxRepository {
226
300
  enumerable: true,
227
301
  configurable: true,
228
302
  writable: true,
229
- value: tables
303
+ value: void 0
230
304
  });
305
+ this.tables = validateSqlOutboxTables(tables);
231
306
  }
232
307
  async record(messageId, now = new Date()) {
233
308
  try {
@@ -254,7 +329,8 @@ const KvInboxRecordSchema = Type.Object({
254
329
  });
255
330
  export const KvOutboxRecordSchema = Type.Object({
256
331
  id: Type.String(),
257
- event: Type.String(),
332
+ kind: Type.String(),
333
+ name: Type.String(),
258
334
  subject: Type.String(),
259
335
  payload: Type.String(),
260
336
  headers: Type.Record(Type.String(), Type.String()),
@@ -269,6 +345,7 @@ export const KvOutboxRecordSchema = Type.Object({
269
345
  updatedAt: Type.String(),
270
346
  nextAttemptAt: Type.Optional(Type.String()),
271
347
  lastError: Type.Optional(Type.String()),
348
+ outcome: Type.Optional(Type.String()),
272
349
  });
273
350
  /** Durable NATS KV outbox repository for services without SQL state. */
274
351
  export class NatsKvOutboxRepository {
@@ -280,14 +357,15 @@ export class NatsKvOutboxRepository {
280
357
  value: kv
281
358
  });
282
359
  }
283
- async enqueue(event) {
360
+ async enqueue(rec) {
284
361
  const now = new Date().toISOString();
285
362
  const record = {
286
- id: messageId(event),
287
- event: event.event,
288
- subject: event.subject,
289
- payload: event.encodedPayload,
290
- headers: { ...event.headers },
363
+ id: rec.id,
364
+ kind: rec.kind,
365
+ name: rec.name,
366
+ subject: rec.subject,
367
+ payload: rec.payload,
368
+ headers: { ...rec.headers },
291
369
  state: "pending",
292
370
  attempts: 0,
293
371
  createdAt: now,
@@ -341,19 +419,23 @@ export class NatsKvOutboxRepository {
341
419
  }
342
420
  return claimed;
343
421
  }
344
- async markDispatched(id, now) {
422
+ async markDispatched(id, now, outcome) {
345
423
  const loaded = await this.kv.get(id).take();
346
424
  if (isErr(loaded)) {
347
425
  if (hasKvReason(loaded.error, "not found"))
348
426
  return;
349
427
  throw loaded.error;
350
428
  }
429
+ const outcomeStr = outcome !== undefined
430
+ ? JSON.stringify(outcome)
431
+ : undefined;
351
432
  const stored = await loaded.put({
352
433
  ...loaded.value,
353
434
  state: "dispatched",
354
435
  updatedAt: now.toISOString(),
355
436
  nextAttemptAt: undefined,
356
437
  lastError: undefined,
438
+ outcome: outcomeStr ?? loaded.value.outcome,
357
439
  }, true).take();
358
440
  if (isErr(stored))
359
441
  throw stored.error;
@@ -550,7 +632,7 @@ _OutboxDispatcher_repository = new WeakMap(), _OutboxDispatcher_runtime = new We
550
632
  __classPrivateFieldSet(this, _OutboxDispatcher_idleTimer, undefined, "f");
551
633
  }
552
634
  };
553
- /** Dispatches due outbox messages through a Trellis runtime publisher. */
635
+ /** Dispatches due outbox messages through a dispatch runtime. */
554
636
  export async function dispatchOutbox(repository, runtime, options = {}) {
555
637
  const now = options.now ?? new Date();
556
638
  const retryDelayMs = options.retryDelayMs ?? 1000;
@@ -558,47 +640,115 @@ export async function dispatchOutbox(repository, runtime, options = {}) {
558
640
  let dispatched = 0;
559
641
  let failed = 0;
560
642
  for (const message of messages) {
561
- const result = await runtime.publishPrepared(outboxMessageToPrepared(message));
562
- const value = result.take();
563
- if (isErr(value)) {
564
- recordTrellisError(value.error, {
643
+ if (message.kind === "event.publish") {
644
+ const result = await runtime.publishPreparedEvent(outboxMessageToPreparedEvent(message));
645
+ const value = result.take();
646
+ if (isErr(value)) {
647
+ recordTrellisError(value.error, {
648
+ surface: "outbox",
649
+ direction: "dispatcher",
650
+ operation: message.name,
651
+ phase: "publish",
652
+ messagingSystem: "nats",
653
+ });
654
+ failed += 1;
655
+ await repository.markFailed(message.id, {
656
+ error: value.error.message,
657
+ nextAttemptAt: new Date(now.getTime() + retryDelayMs),
658
+ now,
659
+ });
660
+ continue;
661
+ }
662
+ dispatched += 1;
663
+ await repository.markDispatched(message.id, now);
664
+ }
665
+ else if (message.kind === "job.create" || message.kind === "job.submit") {
666
+ if (runtime.dispatchJobSubmission) {
667
+ const result = await runtime.dispatchJobSubmission(message);
668
+ const value = result.take();
669
+ if (isErr(value)) {
670
+ recordTrellisError(value.error, {
671
+ surface: "outbox",
672
+ direction: "dispatcher",
673
+ operation: message.name,
674
+ phase: "job.dispatch",
675
+ });
676
+ failed += 1;
677
+ await repository.markFailed(message.id, {
678
+ error: value.error.message,
679
+ nextAttemptAt: new Date(now.getTime() + retryDelayMs),
680
+ now,
681
+ });
682
+ continue;
683
+ }
684
+ dispatched += 1;
685
+ await repository.markDispatched(message.id, now);
686
+ }
687
+ else {
688
+ recordTrellisError(new Error(`job dispatch not supported`), {
689
+ surface: "outbox",
690
+ direction: "dispatcher",
691
+ operation: message.name,
692
+ phase: "dispatch",
693
+ });
694
+ await repository.markDispatched(message.id, now, {
695
+ error: "job dispatch not supported",
696
+ });
697
+ }
698
+ }
699
+ else {
700
+ const error = `Unknown outbox record kind: ${message.kind}`;
701
+ recordTrellisError(new Error(error), {
565
702
  surface: "outbox",
566
703
  direction: "dispatcher",
567
- operation: message.event,
568
- phase: "publish",
569
- messagingSystem: "nats",
704
+ operation: message.name,
705
+ phase: "dispatch",
570
706
  });
571
- failed += 1;
572
- await repository.markFailed(message.id, {
573
- error: value.error.message,
574
- nextAttemptAt: new Date(now.getTime() + retryDelayMs),
575
- now,
576
- });
577
- continue;
707
+ await repository.markDispatched(message.id, now, { error });
578
708
  }
579
- dispatched += 1;
580
- await repository.markDispatched(message.id, now);
581
709
  }
582
710
  return { dispatched, failed };
583
711
  }
584
- /** Rehydrates a persisted outbox row into a prepared event. */
585
- export function outboxMessageToPrepared(message) {
712
+ /** Rehydrates a persisted outbox event row into a prepared event. */
713
+ export function outboxMessageToPreparedEvent(message) {
714
+ if (message.kind !== "event.publish") {
715
+ throw new Error(`Expected event.publish kind, got ${message.kind}`);
716
+ }
717
+ const payload = JSON.parse(message.payload);
718
+ const header = eventHeaderFromMessage(message.headers);
586
719
  return Object.freeze({
587
- event: message.event,
720
+ event: message.name,
588
721
  subject: message.subject,
589
- payload: Object.freeze(JSON.parse(message.payload)),
722
+ header: Object.freeze(header),
723
+ payload: Object.freeze(payload),
590
724
  encodedPayload: message.payload,
591
725
  headers: Object.freeze({ ...message.headers }),
592
726
  });
593
727
  }
594
- function messageId(event) {
595
- return event.headers["Nats-Msg-Id"] ?? event.headers["nats-msg-id"] ??
596
- event.payload.header.id;
728
+ /** Adapts a prepared Trellis event into a generic outbox record. */
729
+ export function preparedTrellisEventToOutboxRecord(event) {
730
+ return {
731
+ id: event.headers["Nats-Msg-Id"] ?? event.header.id,
732
+ kind: "event.publish",
733
+ name: event.event,
734
+ subject: event.subject,
735
+ payload: event.encodedPayload,
736
+ headers: event.headers,
737
+ };
738
+ }
739
+ function eventHeaderFromMessage(headers) {
740
+ const id = headers["Nats-Msg-Id"] ?? headers["nats-msg-id"];
741
+ const time = headers["Trellis-Event-Time"] ?? headers["trellis-event-time"];
742
+ return {
743
+ id: typeof id === "string" ? id : "",
744
+ time: typeof time === "string" ? time : new Date(0).toISOString(),
745
+ };
597
746
  }
598
747
  function rowToOutboxMessage(row) {
599
748
  return {
600
749
  id: stringField(row, "id"),
601
- event: stringField(row, "event"),
750
+ kind: kindField(row, "kind"),
751
+ name: stringField(row, "name"),
602
752
  subject: stringField(row, "subject"),
603
753
  payload: stringField(row, "payload"),
604
754
  headers: parseHeaders(row["headers"]),
@@ -608,12 +758,14 @@ function rowToOutboxMessage(row) {
608
758
  updatedAt: stringField(row, "updated_at"),
609
759
  nextAttemptAt: optionalStringField(row, "next_attempt_at"),
610
760
  lastError: optionalStringField(row, "last_error"),
761
+ outcome: optionalStringField(row, "outcome"),
611
762
  };
612
763
  }
613
764
  function kvRecordToOutboxMessage(record) {
614
765
  return {
615
766
  id: record.id,
616
- event: record.event,
767
+ kind: record.kind,
768
+ name: record.name,
617
769
  subject: record.subject,
618
770
  payload: record.payload,
619
771
  headers: { ...record.headers },
@@ -623,6 +775,7 @@ function kvRecordToOutboxMessage(record) {
623
775
  updatedAt: record.updatedAt,
624
776
  nextAttemptAt: record.nextAttemptAt,
625
777
  lastError: record.lastError,
778
+ outcome: record.outcome,
626
779
  };
627
780
  }
628
781
  function placeholder(dialect, index) {
@@ -677,6 +830,14 @@ function numberField(row, field) {
677
830
  }
678
831
  return value;
679
832
  }
833
+ function kindField(row, field) {
834
+ const value = stringField(row, field);
835
+ if (value === "event.publish" || value === "job.create" ||
836
+ value === "job.submit") {
837
+ return value;
838
+ }
839
+ throw new Error(`Expected SQL field ${field} to be an outbox record kind`);
840
+ }
680
841
  function stateField(row, field) {
681
842
  const value = stringField(row, field);
682
843
  if (value === "pending" || value === "dispatched" || value === "failed") {
@@ -20,8 +20,63 @@ export type TrellisErrorMetricAttributes = {
20
20
  /** Static messaging operation name, when already known. */
21
21
  messagingOperation?: string;
22
22
  };
23
+ /** Duration metric names accepted by {@link recordTrellisDuration}. */
24
+ export type TrellisDurationMetricName = "trellis.connect.duration" | "trellis.auth.flow.duration" | "trellis.auth.approval_resolution.duration" | "trellis.auth.callout.duration" | "trellis.admin.workflow.duration" | "trellis.contract.analysis.duration";
25
+ /** Low-cardinality attributes accepted by {@link recordTrellisDuration}. */
26
+ export type TrellisDurationMetricAttributes = {
27
+ /** Stable Trellis surface name, such as `rpc`, `jobs`, or `operations`. */
28
+ surface?: string;
29
+ /** Stable operation kind or method name. Do not pass IDs, subjects, or URLs. */
30
+ operation?: string;
31
+ /** Stable lifecycle phase such as `bootstrap`, `encode`, or `total`. */
32
+ phase?: string;
33
+ /** Stable outcome label such as `ok` or `error`. */
34
+ outcome?: string;
35
+ /** Participant kind such as `admin`, `client`, `service`, or `device`. */
36
+ participantKind?: string;
37
+ /** Session kind such as `user`, `service`, or `device`. */
38
+ sessionKind?: string;
39
+ /** Auth flow such as `local`, `oauth`, `device`, or `bootstrap`. */
40
+ authFlow?: string;
41
+ /** Auth approval outcome such as `approved`, `denied`, `required`, or `none`. */
42
+ authApproval?: string;
43
+ /** Whether a deployment authority is present. */
44
+ authorityPresent?: boolean;
45
+ /** Plan classification such as `install`, `update`, `migration`, `noop`, or `unknown`. */
46
+ planClassification?: string;
47
+ /** Contract kind such as `app`, `service`, `device`, `builtin`, or `unknown`. */
48
+ contractKind?: string;
49
+ /** Static messaging system name, when already known. */
50
+ messagingSystem?: string;
51
+ /** Static messaging operation name, when already known. */
52
+ messagingOperation?: string;
53
+ };
23
54
  /** Returns the shared Trellis OpenTelemetry meter. */
24
55
  export declare function getTrellisMeter(): Meter;
25
56
  /** Records one Trellis error with only stable, low-cardinality attributes. */
26
57
  export declare function recordTrellisError(error: unknown, attributes?: TrellisErrorMetricAttributes): void;
58
+ /**
59
+ * Records one duration measurement on the given Trellis histogram.
60
+ *
61
+ * Converts `durationMs` to seconds. Negative, NaN, and infinite values are
62
+ * silently ignored.
63
+ *
64
+ * Histogram instruments are cached by metric name so `createHistogram` is
65
+ * called at most once per metric name.
66
+ *
67
+ * @param name - The duration metric name.
68
+ * @param durationMs - The measured duration in milliseconds.
69
+ * @param attributes - Optional low-cardinality attributes. Only values that
70
+ * pass sanitization are included.
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * recordTrellisDuration("trellis.connect.duration", 42.5, {
75
+ * phase: "nats_connect",
76
+ * outcome: "ok",
77
+ * participantKind: "client",
78
+ * });
79
+ * ```
80
+ */
81
+ export declare function recordTrellisDuration(name: TrellisDurationMetricName, durationMs: number, attributes?: TrellisDurationMetricAttributes): void;
27
82
  //# sourceMappingURL=metrics.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/telemetry/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAW,MAAM,oBAAoB,CAAC;AAiDzD,yEAAyE;AACzE,MAAM,MAAM,4BAA4B,GAAG;IACzC,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AASF,sDAAsD;AACtD,wBAAgB,eAAe,IAAI,KAAK,CAEvC;AAED,8EAA8E;AAC9E,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,OAAO,EACd,UAAU,GAAE,4BAAiC,GAC5C,IAAI,CAWN"}
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/telemetry/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,KAAK,EAAW,MAAM,oBAAoB,CAAC;AAiDzE,yEAAyE;AACzE,MAAM,MAAM,4BAA4B,GAAG;IACzC,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,uEAAuE;AACvE,MAAM,MAAM,yBAAyB,GACjC,0BAA0B,GAC1B,4BAA4B,GAC5B,2CAA2C,GAC3C,+BAA+B,GAC/B,iCAAiC,GACjC,oCAAoC,CAAC;AAEzC,4EAA4E;AAC5E,MAAM,MAAM,+BAA+B,GAAG;IAC5C,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,0FAA0F;IAC1F,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wDAAwD;IACxD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAWF,sDAAsD;AACtD,wBAAgB,eAAe,IAAI,KAAK,CAEvC;AAED,8EAA8E;AAC9E,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,OAAO,EACd,UAAU,GAAE,4BAAiC,GAC5C,IAAI,CAWN;AAsJD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,yBAAyB,EAC/B,UAAU,EAAE,MAAM,EAClB,UAAU,CAAC,EAAE,+BAA+B,GAC3C,IAAI,CAaN"}
@@ -42,6 +42,7 @@ const AUTH_REASONS = new Set([
42
42
  "device_identity_key_mismatch",
43
43
  "invalid_device_qr_mac",
44
44
  ]);
45
+ const DURATION_HISTOGRAM_CACHE = new Map();
45
46
  /** Returns the shared Trellis OpenTelemetry meter. */
46
47
  export function getTrellisMeter() {
47
48
  return metrics.getMeter(TRELLIS_METER_NAME);
@@ -79,6 +80,91 @@ export function buildTrellisErrorMetricAttributes(error, attributes = {}) {
79
80
  setLowCardinalityAttribute(metricAttributes, "messaging.operation", attributes.messagingOperation);
80
81
  return metricAttributes;
81
82
  }
83
+ /**
84
+ * Builds sanitized, low-cardinality attributes for duration histograms.
85
+ *
86
+ * @internal Exported for focused tests; runtime callers should use
87
+ * {@link recordTrellisDuration}.
88
+ */
89
+ export function buildTrellisDurationMetricAttributes(attributes = {}) {
90
+ const metricAttributes = {};
91
+ setLowCardinalityAttribute(metricAttributes, "trellis.surface", attributes.surface);
92
+ setLowCardinalityAttribute(metricAttributes, "trellis.operation", attributes.operation);
93
+ setLowCardinalityAttribute(metricAttributes, "trellis.phase", attributes.phase);
94
+ setLowCardinalityAttribute(metricAttributes, "trellis.outcome", attributes.outcome);
95
+ setLowCardinalityAttribute(metricAttributes, "trellis.participant.kind", attributes.participantKind);
96
+ setLowCardinalityAttribute(metricAttributes, "trellis.session.kind", attributes.sessionKind);
97
+ setLowCardinalityAttribute(metricAttributes, "trellis.auth.flow", attributes.authFlow);
98
+ setLowCardinalityAttribute(metricAttributes, "trellis.auth.approval", attributes.authApproval);
99
+ setLowCardinalityAttribute(metricAttributes, "trellis.plan.classification", attributes.planClassification);
100
+ setLowCardinalityAttribute(metricAttributes, "trellis.contract.kind", attributes.contractKind);
101
+ setLowCardinalityAttribute(metricAttributes, "messaging.system", attributes.messagingSystem);
102
+ setLowCardinalityAttribute(metricAttributes, "messaging.operation", attributes.messagingOperation);
103
+ if (attributes.authorityPresent !== undefined) {
104
+ setLowCardinalityAttribute(metricAttributes, "trellis.authority.present", String(attributes.authorityPresent));
105
+ }
106
+ return metricAttributes;
107
+ }
108
+ /**
109
+ * Records one duration measurement on the given Trellis histogram.
110
+ *
111
+ * Converts `durationMs` to seconds. Negative, NaN, and infinite values are
112
+ * silently ignored.
113
+ *
114
+ * Histogram instruments are cached by metric name so `createHistogram` is
115
+ * called at most once per metric name.
116
+ *
117
+ * @param name - The duration metric name.
118
+ * @param durationMs - The measured duration in milliseconds.
119
+ * @param attributes - Optional low-cardinality attributes. Only values that
120
+ * pass sanitization are included.
121
+ *
122
+ * @example
123
+ * ```ts
124
+ * recordTrellisDuration("trellis.connect.duration", 42.5, {
125
+ * phase: "nats_connect",
126
+ * outcome: "ok",
127
+ * participantKind: "client",
128
+ * });
129
+ * ```
130
+ */
131
+ export function recordTrellisDuration(name, durationMs, attributes) {
132
+ if (typeof durationMs !== "number" ||
133
+ durationMs < 0 ||
134
+ !Number.isFinite(durationMs)) {
135
+ return;
136
+ }
137
+ const histogram = getDurationHistogram(name);
138
+ const metricAttributes = buildTrellisDurationMetricAttributes(attributes);
139
+ histogram.record(durationMs / 1000, metricAttributes);
140
+ }
141
+ function getDurationHistogram(name) {
142
+ let histogram = DURATION_HISTOGRAM_CACHE.get(name);
143
+ if (!histogram) {
144
+ histogram = getTrellisMeter().createHistogram(name, {
145
+ description: histogramDescription(name),
146
+ unit: "s",
147
+ });
148
+ DURATION_HISTOGRAM_CACHE.set(name, histogram);
149
+ }
150
+ return histogram;
151
+ }
152
+ function histogramDescription(name) {
153
+ switch (name) {
154
+ case "trellis.connect.duration":
155
+ return "Duration of connection lifecycle phases.";
156
+ case "trellis.auth.flow.duration":
157
+ return "Duration of auth flow phases.";
158
+ case "trellis.auth.approval_resolution.duration":
159
+ return "Duration of approval resolution phases.";
160
+ case "trellis.auth.callout.duration":
161
+ return "Duration of NATS auth callout phases.";
162
+ case "trellis.admin.workflow.duration":
163
+ return "Duration of admin workflow phases.";
164
+ case "trellis.contract.analysis.duration":
165
+ return "Duration of contract analysis phases.";
166
+ }
167
+ }
82
168
  function trellisErrorType(error, serializable, override) {
83
169
  const overrideType = lowCardinalityValue(override);
84
170
  if (overrideType)