@agilesyndrome/cf-genai-base 5.0.2 → 6.0.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 (696) hide show
  1. package/CHANGELOG.md +99 -0
  2. package/CLI.md +9 -13
  3. package/CONTRACT.md +32 -15
  4. package/README.md +95 -28
  5. package/bin/cf-genai.js +24 -8
  6. package/dist/admin/auth.d.ts +12 -0
  7. package/dist/admin/auth.d.ts.map +1 -0
  8. package/dist/admin/auth.js +103 -0
  9. package/dist/admin/auth.js.map +1 -0
  10. package/dist/admin/index.d.ts +2 -0
  11. package/dist/admin/index.d.ts.map +1 -0
  12. package/dist/admin/index.js +2 -0
  13. package/dist/admin/index.js.map +1 -0
  14. package/dist/admin/router.d.ts +4 -0
  15. package/dist/admin/router.d.ts.map +1 -0
  16. package/dist/admin/router.js +24 -0
  17. package/dist/admin/router.js.map +1 -0
  18. package/dist/admin/types.d.ts +43 -0
  19. package/dist/admin/types.d.ts.map +1 -0
  20. package/dist/admin/types.js +2 -0
  21. package/dist/admin/types.js.map +1 -0
  22. package/dist/api/client.d.ts +34 -0
  23. package/dist/api/client.d.ts.map +1 -0
  24. package/dist/api/client.js +59 -0
  25. package/dist/api/client.js.map +1 -0
  26. package/dist/api/contracts.d.ts +31 -0
  27. package/dist/api/contracts.d.ts.map +1 -0
  28. package/dist/api/contracts.js +101 -0
  29. package/dist/api/contracts.js.map +1 -0
  30. package/dist/api/http.d.ts +12 -0
  31. package/dist/api/http.d.ts.map +1 -0
  32. package/dist/api/http.js +36 -0
  33. package/dist/api/http.js.map +1 -0
  34. package/dist/api/index.d.ts +14 -0
  35. package/dist/api/index.d.ts.map +1 -0
  36. package/dist/api/index.js +11 -0
  37. package/dist/api/index.js.map +1 -0
  38. package/dist/api/testing.d.ts +10 -0
  39. package/dist/api/testing.d.ts.map +1 -0
  40. package/dist/api/testing.js +26 -0
  41. package/dist/api/testing.js.map +1 -0
  42. package/dist/app.d.ts +21 -0
  43. package/dist/app.d.ts.map +1 -0
  44. package/dist/app.js +23 -0
  45. package/dist/app.js.map +1 -0
  46. package/dist/auth/constants.d.ts +9 -0
  47. package/dist/auth/constants.d.ts.map +1 -0
  48. package/{src → dist}/auth/constants.js +2 -2
  49. package/dist/auth/constants.js.map +1 -0
  50. package/dist/auth/domains.d.ts +3 -0
  51. package/dist/auth/domains.d.ts.map +1 -0
  52. package/dist/auth/domains.js +8 -0
  53. package/dist/auth/domains.js.map +1 -0
  54. package/dist/auth/encoding.d.ts +7 -0
  55. package/dist/auth/encoding.d.ts.map +1 -0
  56. package/dist/auth/encoding.js +41 -0
  57. package/dist/auth/encoding.js.map +1 -0
  58. package/dist/auth/groups/d1.d.ts +16 -0
  59. package/dist/auth/groups/d1.d.ts.map +1 -0
  60. package/dist/auth/groups/d1.js +66 -0
  61. package/dist/auth/groups/d1.js.map +1 -0
  62. package/dist/auth/groups/domain.d.ts +8 -0
  63. package/dist/auth/groups/domain.d.ts.map +1 -0
  64. package/dist/auth/groups/domain.js +99 -0
  65. package/dist/auth/groups/domain.js.map +1 -0
  66. package/dist/auth/groups/index.d.ts +7 -0
  67. package/dist/auth/groups/index.d.ts.map +1 -0
  68. package/dist/auth/groups/index.js +7 -0
  69. package/dist/auth/groups/index.js.map +1 -0
  70. package/dist/auth/groups/model.d.ts +38 -0
  71. package/dist/auth/groups/model.d.ts.map +1 -0
  72. package/dist/auth/groups/model.js +2 -0
  73. package/dist/auth/groups/model.js.map +1 -0
  74. package/dist/auth/groups/policy.d.ts +5 -0
  75. package/dist/auth/groups/policy.d.ts.map +1 -0
  76. package/dist/auth/groups/policy.js +8 -0
  77. package/dist/auth/groups/policy.js.map +1 -0
  78. package/dist/auth/groups/service.d.ts +20 -0
  79. package/dist/auth/groups/service.d.ts.map +1 -0
  80. package/dist/auth/groups/service.js +40 -0
  81. package/dist/auth/groups/service.js.map +1 -0
  82. package/dist/auth/groups/validation.d.ts +5 -0
  83. package/dist/auth/groups/validation.d.ts.map +1 -0
  84. package/dist/auth/groups/validation.js +22 -0
  85. package/dist/auth/groups/validation.js.map +1 -0
  86. package/dist/auth/groups/views/list.d.ts +10 -0
  87. package/dist/auth/groups/views/list.d.ts.map +1 -0
  88. package/dist/auth/groups/views/list.js +4 -0
  89. package/dist/auth/groups/views/list.js.map +1 -0
  90. package/dist/auth/identity/index.d.ts +58 -0
  91. package/dist/auth/identity/index.d.ts.map +1 -0
  92. package/dist/auth/identity/index.js +58 -0
  93. package/dist/auth/identity/index.js.map +1 -0
  94. package/dist/auth/impersonation/constants.d.ts +2 -0
  95. package/dist/auth/impersonation/constants.d.ts.map +1 -0
  96. package/dist/auth/impersonation/constants.js +2 -0
  97. package/dist/auth/impersonation/constants.js.map +1 -0
  98. package/dist/auth/impersonation/domain.d.ts +6 -0
  99. package/dist/auth/impersonation/domain.d.ts.map +1 -0
  100. package/dist/auth/impersonation/domain.js +16 -0
  101. package/dist/auth/impersonation/domain.js.map +1 -0
  102. package/dist/auth/impersonation/index.d.ts +6 -0
  103. package/dist/auth/impersonation/index.d.ts.map +1 -0
  104. package/dist/auth/impersonation/index.js +6 -0
  105. package/dist/auth/impersonation/index.js.map +1 -0
  106. package/dist/auth/impersonation/model.d.ts +12 -0
  107. package/dist/auth/impersonation/model.d.ts.map +1 -0
  108. package/dist/auth/impersonation/model.js +2 -0
  109. package/dist/auth/impersonation/model.js.map +1 -0
  110. package/dist/auth/impersonation/service.d.ts +4 -0
  111. package/dist/auth/impersonation/service.d.ts.map +1 -0
  112. package/dist/auth/impersonation/service.js +32 -0
  113. package/dist/auth/impersonation/service.js.map +1 -0
  114. package/dist/auth/impersonation/validation.d.ts +4 -0
  115. package/dist/auth/impersonation/validation.d.ts.map +1 -0
  116. package/dist/auth/impersonation/validation.js +14 -0
  117. package/dist/auth/impersonation/validation.js.map +1 -0
  118. package/dist/auth/index.d.ts +13 -0
  119. package/dist/auth/index.d.ts.map +1 -0
  120. package/dist/auth/index.js +13 -0
  121. package/dist/auth/index.js.map +1 -0
  122. package/dist/auth/oauth-single/constants.d.ts +4 -0
  123. package/dist/auth/oauth-single/constants.d.ts.map +1 -0
  124. package/dist/auth/oauth-single/constants.js +5 -0
  125. package/dist/auth/oauth-single/constants.js.map +1 -0
  126. package/dist/auth/oauth-single/cookies.d.ts +10 -0
  127. package/dist/auth/oauth-single/cookies.d.ts.map +1 -0
  128. package/dist/auth/oauth-single/cookies.js +59 -0
  129. package/dist/auth/oauth-single/cookies.js.map +1 -0
  130. package/dist/auth/oauth-single/domain.d.ts +14 -0
  131. package/dist/auth/oauth-single/domain.d.ts.map +1 -0
  132. package/dist/auth/oauth-single/domain.js +12 -0
  133. package/dist/auth/oauth-single/domain.js.map +1 -0
  134. package/dist/auth/oauth-single/index.d.ts +31 -0
  135. package/dist/auth/oauth-single/index.d.ts.map +1 -0
  136. package/dist/auth/oauth-single/index.js +215 -0
  137. package/dist/auth/oauth-single/index.js.map +1 -0
  138. package/dist/auth/oauth-single/model.d.ts +75 -0
  139. package/dist/auth/oauth-single/model.d.ts.map +1 -0
  140. package/dist/auth/oauth-single/model.js +2 -0
  141. package/dist/auth/oauth-single/model.js.map +1 -0
  142. package/dist/auth/oauth-single/protocol.d.ts +9 -0
  143. package/dist/auth/oauth-single/protocol.d.ts.map +1 -0
  144. package/dist/auth/oauth-single/protocol.js +190 -0
  145. package/dist/auth/oauth-single/protocol.js.map +1 -0
  146. package/dist/auth/oauth-single/session.d.ts +7 -0
  147. package/dist/auth/oauth-single/session.d.ts.map +1 -0
  148. package/dist/auth/oauth-single/session.js +78 -0
  149. package/dist/auth/oauth-single/session.js.map +1 -0
  150. package/dist/auth/repositories.d.ts +58 -0
  151. package/dist/auth/repositories.d.ts.map +1 -0
  152. package/dist/auth/repositories.js +31 -0
  153. package/dist/auth/repositories.js.map +1 -0
  154. package/dist/auth/scopes/d1.d.ts +17 -0
  155. package/dist/auth/scopes/d1.d.ts.map +1 -0
  156. package/dist/auth/scopes/d1.js +54 -0
  157. package/dist/auth/scopes/d1.js.map +1 -0
  158. package/dist/auth/scopes/domain.d.ts +7 -0
  159. package/dist/auth/scopes/domain.d.ts.map +1 -0
  160. package/dist/auth/scopes/domain.js +25 -0
  161. package/dist/auth/scopes/domain.js.map +1 -0
  162. package/dist/auth/scopes/index.d.ts +4 -0
  163. package/dist/auth/scopes/index.d.ts.map +1 -0
  164. package/dist/auth/scopes/index.js +4 -0
  165. package/dist/auth/scopes/index.js.map +1 -0
  166. package/dist/auth/scopes/model.d.ts +26 -0
  167. package/dist/auth/scopes/model.d.ts.map +1 -0
  168. package/dist/auth/scopes/model.js +2 -0
  169. package/dist/auth/scopes/model.js.map +1 -0
  170. package/dist/auth/scopes/policy.d.ts +3 -0
  171. package/dist/auth/scopes/policy.d.ts.map +1 -0
  172. package/dist/auth/scopes/policy.js +4 -0
  173. package/dist/auth/scopes/policy.js.map +1 -0
  174. package/dist/auth/scopes/service.d.ts +4 -0
  175. package/dist/auth/scopes/service.d.ts.map +1 -0
  176. package/dist/auth/scopes/service.js +4 -0
  177. package/dist/auth/scopes/service.js.map +1 -0
  178. package/dist/auth/scopes/validation.d.ts +6 -0
  179. package/dist/auth/scopes/validation.d.ts.map +1 -0
  180. package/dist/auth/scopes/validation.js +33 -0
  181. package/dist/auth/scopes/validation.js.map +1 -0
  182. package/dist/auth/scopes/views/list.d.ts +9 -0
  183. package/dist/auth/scopes/views/list.d.ts.map +1 -0
  184. package/dist/auth/scopes/views/list.js +4 -0
  185. package/dist/auth/scopes/views/list.js.map +1 -0
  186. package/dist/auth/subscriptions/d1.d.ts +10 -0
  187. package/dist/auth/subscriptions/d1.d.ts.map +1 -0
  188. package/dist/auth/subscriptions/d1.js +86 -0
  189. package/dist/auth/subscriptions/d1.js.map +1 -0
  190. package/dist/auth/subscriptions/domain.d.ts +10 -0
  191. package/dist/auth/subscriptions/domain.d.ts.map +1 -0
  192. package/dist/auth/subscriptions/domain.js +33 -0
  193. package/dist/auth/subscriptions/domain.js.map +1 -0
  194. package/dist/auth/subscriptions/index.d.ts +6 -0
  195. package/dist/auth/subscriptions/index.d.ts.map +1 -0
  196. package/dist/auth/subscriptions/index.js +6 -0
  197. package/dist/auth/subscriptions/index.js.map +1 -0
  198. package/dist/auth/subscriptions/model.d.ts +20 -0
  199. package/dist/auth/subscriptions/model.d.ts.map +1 -0
  200. package/dist/auth/subscriptions/model.js +2 -0
  201. package/dist/auth/subscriptions/model.js.map +1 -0
  202. package/dist/auth/subscriptions/service.d.ts +12 -0
  203. package/dist/auth/subscriptions/service.d.ts.map +1 -0
  204. package/dist/auth/subscriptions/service.js +71 -0
  205. package/dist/auth/subscriptions/service.js.map +1 -0
  206. package/dist/auth/subscriptions/validation.d.ts +3 -0
  207. package/dist/auth/subscriptions/validation.d.ts.map +1 -0
  208. package/dist/auth/subscriptions/validation.js +21 -0
  209. package/dist/auth/subscriptions/validation.js.map +1 -0
  210. package/dist/auth/tenants/d1.d.ts +12 -0
  211. package/dist/auth/tenants/d1.d.ts.map +1 -0
  212. package/dist/auth/tenants/d1.js +40 -0
  213. package/dist/auth/tenants/d1.js.map +1 -0
  214. package/dist/auth/tenants/delete.d.ts +3 -0
  215. package/dist/auth/tenants/delete.d.ts.map +1 -0
  216. package/dist/auth/tenants/delete.js +28 -0
  217. package/dist/auth/tenants/delete.js.map +1 -0
  218. package/dist/auth/tenants/domain.d.ts +8 -0
  219. package/dist/auth/tenants/domain.d.ts.map +1 -0
  220. package/dist/auth/tenants/domain.js +64 -0
  221. package/dist/auth/tenants/domain.js.map +1 -0
  222. package/dist/auth/tenants/index.d.ts +7 -0
  223. package/dist/auth/tenants/index.d.ts.map +1 -0
  224. package/dist/auth/tenants/index.js +7 -0
  225. package/dist/auth/tenants/index.js.map +1 -0
  226. package/dist/auth/tenants/model.d.ts +28 -0
  227. package/dist/auth/tenants/model.d.ts.map +1 -0
  228. package/dist/auth/tenants/model.js +2 -0
  229. package/dist/auth/tenants/model.js.map +1 -0
  230. package/dist/auth/tenants/policy.d.ts +3 -0
  231. package/dist/auth/tenants/policy.d.ts.map +1 -0
  232. package/dist/auth/tenants/policy.js +4 -0
  233. package/dist/auth/tenants/policy.js.map +1 -0
  234. package/dist/auth/tenants/service.d.ts +14 -0
  235. package/dist/auth/tenants/service.d.ts.map +1 -0
  236. package/dist/auth/tenants/service.js +37 -0
  237. package/dist/auth/tenants/service.js.map +1 -0
  238. package/dist/auth/tenants/validation.d.ts +5 -0
  239. package/dist/auth/tenants/validation.d.ts.map +1 -0
  240. package/dist/auth/tenants/validation.js +21 -0
  241. package/dist/auth/tenants/validation.js.map +1 -0
  242. package/dist/auth/tenants/views/list.d.ts +8 -0
  243. package/dist/auth/tenants/views/list.d.ts.map +1 -0
  244. package/dist/auth/tenants/views/list.js +3 -0
  245. package/dist/auth/tenants/views/list.js.map +1 -0
  246. package/dist/auth/users/access.d.ts +9 -0
  247. package/dist/auth/users/access.d.ts.map +1 -0
  248. package/dist/auth/users/access.js +53 -0
  249. package/dist/auth/users/access.js.map +1 -0
  250. package/dist/auth/users/d1.d.ts +19 -0
  251. package/dist/auth/users/d1.d.ts.map +1 -0
  252. package/dist/auth/users/d1.js +68 -0
  253. package/dist/auth/users/d1.js.map +1 -0
  254. package/dist/auth/users/domain.d.ts +13 -0
  255. package/dist/auth/users/domain.d.ts.map +1 -0
  256. package/dist/auth/users/domain.js +129 -0
  257. package/dist/auth/users/domain.js.map +1 -0
  258. package/dist/auth/users/index.d.ts +7 -0
  259. package/dist/auth/users/index.d.ts.map +1 -0
  260. package/dist/auth/users/index.js +7 -0
  261. package/dist/auth/users/index.js.map +1 -0
  262. package/dist/auth/users/model.d.ts +44 -0
  263. package/dist/auth/users/model.d.ts.map +1 -0
  264. package/dist/auth/users/model.js +2 -0
  265. package/dist/auth/users/model.js.map +1 -0
  266. package/dist/auth/users/service.d.ts +8 -0
  267. package/dist/auth/users/service.d.ts.map +1 -0
  268. package/dist/auth/users/service.js +62 -0
  269. package/dist/auth/users/service.js.map +1 -0
  270. package/dist/auth/users/validation.d.ts +4 -0
  271. package/dist/auth/users/validation.d.ts.map +1 -0
  272. package/dist/auth/users/validation.js +23 -0
  273. package/dist/auth/users/validation.js.map +1 -0
  274. package/dist/cli/cli.d.ts +9 -0
  275. package/dist/cli/cli.d.ts.map +1 -0
  276. package/dist/cli/cli.js +201 -0
  277. package/dist/cli/cli.js.map +1 -0
  278. package/dist/cli/d1.d.ts +24 -0
  279. package/dist/cli/d1.d.ts.map +1 -0
  280. package/dist/cli/d1.js +175 -0
  281. package/dist/cli/d1.js.map +1 -0
  282. package/dist/cli/operations.d.ts +3 -0
  283. package/dist/cli/operations.d.ts.map +1 -0
  284. package/dist/cli/operations.js +63 -0
  285. package/dist/cli/operations.js.map +1 -0
  286. package/dist/cli/project.d.ts +136 -0
  287. package/dist/cli/project.d.ts.map +1 -0
  288. package/dist/cli/project.js +738 -0
  289. package/dist/cli/project.js.map +1 -0
  290. package/dist/cli/status.d.ts +24 -0
  291. package/dist/cli/status.d.ts.map +1 -0
  292. package/dist/cli/status.js +55 -0
  293. package/dist/cli/status.js.map +1 -0
  294. package/dist/cli/tenants.d.ts +9 -0
  295. package/dist/cli/tenants.d.ts.map +1 -0
  296. package/dist/cli/tenants.js +32 -0
  297. package/dist/cli/tenants.js.map +1 -0
  298. package/dist/cli/types.d.ts +43 -0
  299. package/dist/cli/types.d.ts.map +1 -0
  300. package/dist/cli/types.js +2 -0
  301. package/dist/cli/types.js.map +1 -0
  302. package/dist/cli/users.d.ts +8 -0
  303. package/dist/cli/users.d.ts.map +1 -0
  304. package/dist/cli/users.js +74 -0
  305. package/dist/cli/users.js.map +1 -0
  306. package/dist/cli/version.d.ts +12 -0
  307. package/dist/cli/version.d.ts.map +1 -0
  308. package/dist/cli/version.js +60 -0
  309. package/dist/cli/version.js.map +1 -0
  310. package/dist/core/circuits/availability.d.ts +48 -0
  311. package/dist/core/circuits/availability.d.ts.map +1 -0
  312. package/dist/core/circuits/availability.js +87 -0
  313. package/dist/core/circuits/availability.js.map +1 -0
  314. package/dist/core/circuits/d1.d.ts +11 -0
  315. package/dist/core/circuits/d1.d.ts.map +1 -0
  316. package/dist/core/circuits/d1.js +83 -0
  317. package/dist/core/circuits/d1.js.map +1 -0
  318. package/dist/core/circuits/domain.d.ts +7 -0
  319. package/dist/core/circuits/domain.d.ts.map +1 -0
  320. package/dist/core/circuits/domain.js +36 -0
  321. package/dist/core/circuits/domain.js.map +1 -0
  322. package/dist/core/circuits/index.d.ts +6 -0
  323. package/dist/core/circuits/index.d.ts.map +1 -0
  324. package/dist/core/circuits/index.js +6 -0
  325. package/dist/core/circuits/index.js.map +1 -0
  326. package/dist/core/circuits/model.d.ts +50 -0
  327. package/dist/core/circuits/model.d.ts.map +1 -0
  328. package/dist/core/circuits/model.js +2 -0
  329. package/dist/core/circuits/model.js.map +1 -0
  330. package/dist/core/circuits/service.d.ts +9 -0
  331. package/dist/core/circuits/service.d.ts.map +1 -0
  332. package/dist/core/circuits/service.js +63 -0
  333. package/dist/core/circuits/service.js.map +1 -0
  334. package/dist/core/circuits/validation.d.ts +4 -0
  335. package/dist/core/circuits/validation.d.ts.map +1 -0
  336. package/dist/core/circuits/validation.js +35 -0
  337. package/dist/core/circuits/validation.js.map +1 -0
  338. package/dist/core/constants.d.ts +9 -0
  339. package/dist/core/constants.d.ts.map +1 -0
  340. package/{src → dist}/core/constants.js +2 -1
  341. package/dist/core/constants.js.map +1 -0
  342. package/dist/core/database/index.d.ts +14 -0
  343. package/dist/core/database/index.d.ts.map +1 -0
  344. package/dist/core/database/index.js +65 -0
  345. package/dist/core/database/index.js.map +1 -0
  346. package/dist/core/domains.d.ts +2 -0
  347. package/dist/core/domains.d.ts.map +1 -0
  348. package/dist/core/domains.js +7 -0
  349. package/dist/core/domains.js.map +1 -0
  350. package/dist/core/events/audit.d.ts +8 -0
  351. package/dist/core/events/audit.d.ts.map +1 -0
  352. package/dist/core/events/audit.js +27 -0
  353. package/dist/core/events/audit.js.map +1 -0
  354. package/dist/core/events/domain.d.ts +19 -0
  355. package/dist/core/events/domain.d.ts.map +1 -0
  356. package/dist/core/events/domain.js +39 -0
  357. package/dist/core/events/domain.js.map +1 -0
  358. package/dist/core/events/hub.d.ts +10 -0
  359. package/dist/core/events/hub.d.ts.map +1 -0
  360. package/dist/core/events/hub.js +56 -0
  361. package/dist/core/events/hub.js.map +1 -0
  362. package/dist/core/events/index.d.ts +57 -0
  363. package/dist/core/events/index.d.ts.map +1 -0
  364. package/dist/core/events/index.js +170 -0
  365. package/dist/core/events/index.js.map +1 -0
  366. package/dist/core/healthchecks/d1.d.ts +7 -0
  367. package/dist/core/healthchecks/d1.d.ts.map +1 -0
  368. package/dist/core/healthchecks/d1.js +43 -0
  369. package/dist/core/healthchecks/d1.js.map +1 -0
  370. package/dist/core/healthchecks/domain.d.ts +7 -0
  371. package/dist/core/healthchecks/domain.d.ts.map +1 -0
  372. package/dist/core/healthchecks/domain.js +51 -0
  373. package/dist/core/healthchecks/domain.js.map +1 -0
  374. package/dist/core/healthchecks/features.d.ts +19 -0
  375. package/dist/core/healthchecks/features.d.ts.map +1 -0
  376. package/dist/core/healthchecks/features.js +100 -0
  377. package/dist/core/healthchecks/features.js.map +1 -0
  378. package/dist/core/healthchecks/index.d.ts +6 -0
  379. package/dist/core/healthchecks/index.d.ts.map +1 -0
  380. package/dist/core/healthchecks/index.js +6 -0
  381. package/dist/core/healthchecks/index.js.map +1 -0
  382. package/dist/core/healthchecks/model.d.ts +64 -0
  383. package/dist/core/healthchecks/model.d.ts.map +1 -0
  384. package/dist/core/healthchecks/model.js +2 -0
  385. package/dist/core/healthchecks/model.js.map +1 -0
  386. package/dist/core/healthchecks/service.d.ts +8 -0
  387. package/dist/core/healthchecks/service.d.ts.map +1 -0
  388. package/dist/core/healthchecks/service.js +29 -0
  389. package/dist/core/healthchecks/service.js.map +1 -0
  390. package/dist/core/healthchecks/validation.d.ts +5 -0
  391. package/dist/core/healthchecks/validation.d.ts.map +1 -0
  392. package/dist/core/healthchecks/validation.js +51 -0
  393. package/dist/core/healthchecks/validation.js.map +1 -0
  394. package/dist/core/index.d.ts +9 -0
  395. package/dist/core/index.d.ts.map +1 -0
  396. package/dist/core/index.js +9 -0
  397. package/dist/core/index.js.map +1 -0
  398. package/dist/core/jobs/d1.d.ts +19 -0
  399. package/dist/core/jobs/d1.d.ts.map +1 -0
  400. package/dist/core/jobs/d1.js +139 -0
  401. package/dist/core/jobs/d1.js.map +1 -0
  402. package/dist/core/jobs/domain.d.ts +8 -0
  403. package/dist/core/jobs/domain.d.ts.map +1 -0
  404. package/dist/core/jobs/domain.js +59 -0
  405. package/dist/core/jobs/domain.js.map +1 -0
  406. package/dist/core/jobs/events.d.ts +3 -0
  407. package/dist/core/jobs/events.d.ts.map +1 -0
  408. package/dist/core/jobs/events.js +25 -0
  409. package/dist/core/jobs/events.js.map +1 -0
  410. package/dist/core/jobs/index.d.ts +7 -0
  411. package/dist/core/jobs/index.d.ts.map +1 -0
  412. package/dist/core/jobs/index.js +7 -0
  413. package/dist/core/jobs/index.js.map +1 -0
  414. package/dist/core/jobs/model.d.ts +86 -0
  415. package/dist/core/jobs/model.d.ts.map +1 -0
  416. package/dist/core/jobs/model.js +2 -0
  417. package/dist/core/jobs/model.js.map +1 -0
  418. package/dist/core/jobs/service.d.ts +39 -0
  419. package/dist/core/jobs/service.d.ts.map +1 -0
  420. package/dist/core/jobs/service.js +84 -0
  421. package/dist/core/jobs/service.js.map +1 -0
  422. package/dist/core/jobs/validation.d.ts +8 -0
  423. package/dist/core/jobs/validation.d.ts.map +1 -0
  424. package/dist/core/jobs/validation.js +39 -0
  425. package/dist/core/jobs/validation.js.map +1 -0
  426. package/dist/core/security/index.d.ts +30 -0
  427. package/dist/core/security/index.d.ts.map +1 -0
  428. package/dist/core/security/index.js +138 -0
  429. package/dist/core/security/index.js.map +1 -0
  430. package/dist/data/context.d.ts +20 -0
  431. package/dist/data/context.d.ts.map +1 -0
  432. package/dist/data/context.js +65 -0
  433. package/dist/data/context.js.map +1 -0
  434. package/dist/data/index.d.ts +5 -0
  435. package/dist/data/index.d.ts.map +1 -0
  436. package/{src → dist}/data/index.js +2 -0
  437. package/dist/data/index.js.map +1 -0
  438. package/dist/data/json.d.ts +3 -0
  439. package/dist/data/json.d.ts.map +1 -0
  440. package/dist/data/json.js +14 -0
  441. package/dist/data/json.js.map +1 -0
  442. package/dist/data/model.d.ts +96 -0
  443. package/dist/data/model.d.ts.map +1 -0
  444. package/dist/data/model.js +3 -0
  445. package/dist/data/model.js.map +1 -0
  446. package/dist/data/policy.d.ts +14 -0
  447. package/dist/data/policy.d.ts.map +1 -0
  448. package/dist/data/policy.js +89 -0
  449. package/dist/data/policy.js.map +1 -0
  450. package/dist/data/reader.d.ts +9 -0
  451. package/dist/data/reader.d.ts.map +1 -0
  452. package/dist/data/reader.js +203 -0
  453. package/dist/data/reader.js.map +1 -0
  454. package/dist/data/resources.d.ts +9 -0
  455. package/dist/data/resources.d.ts.map +1 -0
  456. package/dist/data/resources.js +129 -0
  457. package/dist/data/resources.js.map +1 -0
  458. package/dist/domain/app-domain.d.ts +36 -0
  459. package/dist/domain/app-domain.d.ts.map +1 -0
  460. package/dist/domain/app-domain.js +79 -0
  461. package/dist/domain/app-domain.js.map +1 -0
  462. package/dist/domain/index.d.ts +3 -0
  463. package/dist/domain/index.d.ts.map +1 -0
  464. package/dist/domain/index.js +3 -0
  465. package/dist/domain/index.js.map +1 -0
  466. package/dist/domain/model.d.ts +37 -0
  467. package/dist/domain/model.d.ts.map +1 -0
  468. package/dist/domain/model.js +2 -0
  469. package/dist/domain/model.js.map +1 -0
  470. package/dist/features/index.d.ts +25 -0
  471. package/dist/features/index.d.ts.map +1 -0
  472. package/dist/features/index.js +61 -0
  473. package/dist/features/index.js.map +1 -0
  474. package/dist/features/llm/client.d.ts +3 -0
  475. package/dist/features/llm/client.d.ts.map +1 -0
  476. package/dist/features/llm/client.js +327 -0
  477. package/dist/features/llm/client.js.map +1 -0
  478. package/dist/features/llm/config.d.ts +7 -0
  479. package/dist/features/llm/config.d.ts.map +1 -0
  480. package/dist/features/llm/config.js +93 -0
  481. package/dist/features/llm/config.js.map +1 -0
  482. package/dist/features/llm/constants.d.ts +5 -0
  483. package/dist/features/llm/constants.d.ts.map +1 -0
  484. package/dist/features/llm/constants.js +6 -0
  485. package/dist/features/llm/constants.js.map +1 -0
  486. package/dist/features/llm/errors.d.ts +12 -0
  487. package/dist/features/llm/errors.d.ts.map +1 -0
  488. package/dist/features/llm/errors.js +19 -0
  489. package/dist/features/llm/errors.js.map +1 -0
  490. package/dist/features/llm/feature.d.ts +6 -0
  491. package/dist/features/llm/feature.d.ts.map +1 -0
  492. package/dist/features/llm/feature.js +37 -0
  493. package/dist/features/llm/feature.js.map +1 -0
  494. package/dist/features/llm/index.d.ts +9 -0
  495. package/dist/features/llm/index.d.ts.map +1 -0
  496. package/dist/features/llm/index.js +6 -0
  497. package/dist/features/llm/index.js.map +1 -0
  498. package/dist/features/llm/model.d.ts +171 -0
  499. package/dist/features/llm/model.d.ts.map +1 -0
  500. package/dist/features/llm/model.js +2 -0
  501. package/dist/features/llm/model.js.map +1 -0
  502. package/dist/features/llm/schema.d.ts +4 -0
  503. package/dist/features/llm/schema.d.ts.map +1 -0
  504. package/dist/features/llm/schema.js +82 -0
  505. package/dist/features/llm/schema.js.map +1 -0
  506. package/dist/features/llm/service.d.ts +29 -0
  507. package/dist/features/llm/service.d.ts.map +1 -0
  508. package/dist/features/llm/service.js +55 -0
  509. package/dist/features/llm/service.js.map +1 -0
  510. package/dist/features/messaging/constants.d.ts +3 -0
  511. package/dist/features/messaging/constants.d.ts.map +1 -0
  512. package/dist/features/messaging/constants.js +4 -0
  513. package/dist/features/messaging/constants.js.map +1 -0
  514. package/dist/features/messaging/domain.d.ts +9 -0
  515. package/dist/features/messaging/domain.d.ts.map +1 -0
  516. package/dist/features/messaging/domain.js +14 -0
  517. package/dist/features/messaging/domain.js.map +1 -0
  518. package/dist/features/messaging/feature.d.ts +7 -0
  519. package/dist/features/messaging/feature.d.ts.map +1 -0
  520. package/dist/features/messaging/feature.js +23 -0
  521. package/dist/features/messaging/feature.js.map +1 -0
  522. package/dist/features/messaging/index.d.ts +12 -0
  523. package/dist/features/messaging/index.d.ts.map +1 -0
  524. package/dist/features/messaging/index.js +8 -0
  525. package/dist/features/messaging/index.js.map +1 -0
  526. package/dist/features/messaging/jobs.d.ts +38 -0
  527. package/dist/features/messaging/jobs.d.ts.map +1 -0
  528. package/dist/features/messaging/jobs.js +40 -0
  529. package/dist/features/messaging/jobs.js.map +1 -0
  530. package/dist/features/messaging/models.d.ts +65 -0
  531. package/dist/features/messaging/models.d.ts.map +1 -0
  532. package/dist/features/messaging/models.js +97 -0
  533. package/dist/features/messaging/models.js.map +1 -0
  534. package/dist/features/messaging/resources.d.ts +8 -0
  535. package/dist/features/messaging/resources.d.ts.map +1 -0
  536. package/dist/features/messaging/resources.js +11 -0
  537. package/dist/features/messaging/resources.js.map +1 -0
  538. package/dist/features/messaging/store.d.ts +46 -0
  539. package/dist/features/messaging/store.d.ts.map +1 -0
  540. package/dist/features/messaging/store.js +208 -0
  541. package/dist/features/messaging/store.js.map +1 -0
  542. package/dist/index.d.ts +20 -0
  543. package/dist/index.d.ts.map +1 -0
  544. package/{src → dist}/index.js +7 -2
  545. package/dist/index.js.map +1 -0
  546. package/dist/input.d.ts +18 -0
  547. package/dist/input.d.ts.map +1 -0
  548. package/dist/input.js +49 -0
  549. package/dist/input.js.map +1 -0
  550. package/dist/repository/model.d.ts +61 -0
  551. package/dist/repository/model.d.ts.map +1 -0
  552. package/dist/repository/model.js +2 -0
  553. package/dist/repository/model.js.map +1 -0
  554. package/dist/repository.d.ts +11 -0
  555. package/dist/repository.d.ts.map +1 -0
  556. package/dist/repository.js +118 -0
  557. package/dist/repository.js.map +1 -0
  558. package/dist/runtime/domains.d.ts +14 -0
  559. package/dist/runtime/domains.d.ts.map +1 -0
  560. package/dist/runtime/domains.js +42 -0
  561. package/dist/runtime/domains.js.map +1 -0
  562. package/dist/runtime/features.d.ts +10 -0
  563. package/dist/runtime/features.d.ts.map +1 -0
  564. package/dist/runtime/features.js +37 -0
  565. package/dist/runtime/features.js.map +1 -0
  566. package/dist/runtime/health.d.ts +6 -0
  567. package/dist/runtime/health.d.ts.map +1 -0
  568. package/dist/runtime/health.js +28 -0
  569. package/dist/runtime/health.js.map +1 -0
  570. package/dist/runtime/hono.d.ts +30 -0
  571. package/dist/runtime/hono.d.ts.map +1 -0
  572. package/dist/runtime/hono.js +50 -0
  573. package/dist/runtime/hono.js.map +1 -0
  574. package/dist/runtime/model.d.ts +133 -0
  575. package/dist/runtime/model.d.ts.map +1 -0
  576. package/dist/runtime/model.js +2 -0
  577. package/dist/runtime/model.js.map +1 -0
  578. package/dist/runtime/responses.d.ts +9 -0
  579. package/dist/runtime/responses.d.ts.map +1 -0
  580. package/dist/runtime/responses.js +14 -0
  581. package/dist/runtime/responses.js.map +1 -0
  582. package/dist/runtime/worker.d.ts +10 -0
  583. package/dist/runtime/worker.d.ts.map +1 -0
  584. package/dist/runtime/worker.js +216 -0
  585. package/dist/runtime/worker.js.map +1 -0
  586. package/dist/ui/index.d.ts +3 -0
  587. package/dist/ui/index.d.ts.map +1 -0
  588. package/dist/ui/index.js +3 -0
  589. package/dist/ui/index.js.map +1 -0
  590. package/dist/ui/react/admin-access.d.ts +2 -0
  591. package/dist/ui/react/admin-access.d.ts.map +1 -0
  592. package/dist/ui/react/admin-access.js +47 -0
  593. package/dist/ui/react/admin-access.js.map +1 -0
  594. package/dist/ui/react/admin-audit.d.ts +2 -0
  595. package/dist/ui/react/admin-audit.d.ts.map +1 -0
  596. package/dist/ui/react/admin-audit.js +13 -0
  597. package/dist/ui/react/admin-audit.js.map +1 -0
  598. package/dist/ui/react/admin-catalogs.d.ts +6 -0
  599. package/dist/ui/react/admin-catalogs.d.ts.map +1 -0
  600. package/dist/ui/react/admin-catalogs.js +37 -0
  601. package/dist/ui/react/admin-catalogs.js.map +1 -0
  602. package/dist/ui/react/admin-dashboard.d.ts +39 -0
  603. package/dist/ui/react/admin-dashboard.d.ts.map +1 -0
  604. package/dist/ui/react/admin-dashboard.js +135 -0
  605. package/dist/ui/react/admin-dashboard.js.map +1 -0
  606. package/dist/ui/react/admin-details.d.ts +27 -0
  607. package/dist/ui/react/admin-details.d.ts.map +1 -0
  608. package/dist/ui/react/admin-details.js +82 -0
  609. package/dist/ui/react/admin-details.js.map +1 -0
  610. package/dist/ui/react/admin-shell.d.ts +20 -0
  611. package/dist/ui/react/admin-shell.d.ts.map +1 -0
  612. package/dist/ui/react/admin-shell.js +24 -0
  613. package/dist/ui/react/admin-shell.js.map +1 -0
  614. package/dist/ui/react/bootstrap.d.ts +9 -0
  615. package/dist/ui/react/bootstrap.d.ts.map +1 -0
  616. package/dist/ui/react/bootstrap.js +45 -0
  617. package/dist/ui/react/bootstrap.js.map +1 -0
  618. package/dist/ui/react/foundation.d.ts +35 -0
  619. package/dist/ui/react/foundation.d.ts.map +1 -0
  620. package/dist/ui/react/foundation.js +62 -0
  621. package/dist/ui/react/foundation.js.map +1 -0
  622. package/dist/ui/react/index.d.ts +12 -0
  623. package/dist/ui/react/index.d.ts.map +1 -0
  624. package/dist/ui/react/index.js +12 -0
  625. package/dist/ui/react/index.js.map +1 -0
  626. package/dist/ui/react/jobs.d.ts +62 -0
  627. package/dist/ui/react/jobs.d.ts.map +1 -0
  628. package/dist/ui/react/jobs.js +114 -0
  629. package/dist/ui/react/jobs.js.map +1 -0
  630. package/dist/ui/react/live-events.d.ts +18 -0
  631. package/dist/ui/react/live-events.d.ts.map +1 -0
  632. package/dist/ui/react/live-events.js +94 -0
  633. package/dist/ui/react/live-events.js.map +1 -0
  634. package/dist/ui/react/types.d.ts +79 -0
  635. package/dist/ui/react/types.d.ts.map +1 -0
  636. package/dist/ui/react/types.js +32 -0
  637. package/dist/ui/react/types.js.map +1 -0
  638. package/dist/ui/ssr.d.ts +55 -0
  639. package/dist/ui/ssr.d.ts.map +1 -0
  640. package/dist/ui/ssr.js +30 -0
  641. package/dist/ui/ssr.js.map +1 -0
  642. package/{src → dist}/ui/styles.css +22 -1
  643. package/migrations/0007_messaging.sql +52 -0
  644. package/migrations/0008_messaging_tenant_integrity.sql +44 -0
  645. package/migrations/0009_healthcheck_measurements.sql +3 -0
  646. package/migrations/0010_admin_dashboard_refinements.sql +24 -0
  647. package/package.json +162 -21
  648. package/changelog.md +0 -25
  649. package/src/admin/index.js +0 -1
  650. package/src/admin/routes.js +0 -64
  651. package/src/api/client.js +0 -8
  652. package/src/api/contracts.js +0 -24
  653. package/src/api/index.js +0 -7
  654. package/src/api/jobs.js +0 -37
  655. package/src/api/testing.js +0 -13
  656. package/src/app.js +0 -5
  657. package/src/auth/encoding.js +0 -6
  658. package/src/auth/groups.js +0 -5
  659. package/src/auth/impersonation.js +0 -15
  660. package/src/auth/index.js +0 -8
  661. package/src/auth/oauth-single.js +0 -204
  662. package/src/auth/scopes.js +0 -32
  663. package/src/auth/subscriptions.js +0 -42
  664. package/src/auth/tenants.js +0 -34
  665. package/src/auth/users.js +0 -40
  666. package/src/cli/cli.js +0 -133
  667. package/src/cli/d1.js +0 -165
  668. package/src/cli/operations.js +0 -34
  669. package/src/cli/project.js +0 -560
  670. package/src/cli/status.js +0 -46
  671. package/src/cli/tenants.js +0 -16
  672. package/src/cli/users.js +0 -34
  673. package/src/cli/version.js +0 -54
  674. package/src/core/circuits.js +0 -134
  675. package/src/core/d1.js +0 -54
  676. package/src/core/event-hub.js +0 -29
  677. package/src/core/events.js +0 -63
  678. package/src/core/identity.js +0 -39
  679. package/src/core/index.js +0 -7
  680. package/src/core/jobs.js +0 -185
  681. package/src/core/security.js +0 -88
  682. package/src/data/context.js +0 -16
  683. package/src/data/reader.js +0 -63
  684. package/src/data/resources.js +0 -42
  685. package/src/repository.js +0 -63
  686. package/src/runtime/features.js +0 -17
  687. package/src/runtime/health.js +0 -17
  688. package/src/runtime/worker.js +0 -58
  689. package/src/ui/index.js +0 -1
  690. package/src/ui/react/admin-access.jsx +0 -29
  691. package/src/ui/react/admin-catalogs.jsx +0 -39
  692. package/src/ui/react/admin-shell.jsx +0 -17
  693. package/src/ui/react/foundation.jsx +0 -40
  694. package/src/ui/react/index.jsx +0 -6
  695. package/src/ui/react/jobs.jsx +0 -63
  696. package/src/ui/react/live-events.jsx +0 -55
package/src/cli/users.js DELETED
@@ -1,34 +0,0 @@
1
- import { executeJson, parseJsonRows } from "./d1.js";
2
-
3
- function sql(value) { return "'" + String(value).replaceAll("'", "''") + "'"; }
4
- function query(database, target, command, options) { return parseJsonRows(executeJson(options.wranglerCommand, database, target, command, options)); }
5
- function csv(value) { return String(value).split(",").map((item) => item.trim()).filter(Boolean); }
6
-
7
- export function runUserCommand({ action, username, options }) {
8
- const target = options.target || "local";
9
- if (!["local", "staging", "production"].includes(target)) throw new Error("User target must be local, staging, or production.");
10
- if (action === "list") {
11
- const users = query(options.database, target, "SELECT id,email,display_name,provider,subject,is_admin,created_at,updated_at FROM auth_users ORDER BY email COLLATE NOCASE;", options);
12
- return console.log(JSON.stringify(users.map((user) => ({ ...user, tenants: query(options.database, target, "SELECT t.id,t.name FROM auth_tenants t JOIN auth_user_tenants ut ON ut.tenant_id=t.id WHERE ut.user_id=" + sql(user.id) + " ORDER BY t.name COLLATE NOCASE;", options) })), null, 2));
13
- }
14
- if (!username) throw new Error("A username, email, subject, or user id is required.");
15
- const where = `(id=${sql(username)} OR email=${sql(username)} OR subject=${sql(username)})`;
16
- const rows = query(options.database, target, `SELECT id,email,display_name,provider,subject,is_admin,created_at,updated_at FROM auth_users WHERE ${where} LIMIT 1;`, options);
17
- if (!rows[0]) throw new Error(`User not found: ${username}`);
18
- if (action === "get") {
19
- const user = rows[0];
20
- const scopes = query(options.database, target, `SELECT scope_name,granted_at FROM auth_user_scopes WHERE user_id=${sql(user.id)} ORDER BY scope_name;`, options);
21
- const groups = query(options.database, target, `SELECT group_name,granted_at FROM auth_user_groups WHERE user_id=${sql(user.id)} ORDER BY group_name;`, options);
22
- const tenants = query(options.database, target, `SELECT t.id,t.name,ut.joined_at FROM auth_tenants t JOIN auth_user_tenants ut ON ut.tenant_id=t.id WHERE ut.user_id=${sql(user.id)} ORDER BY t.name COLLATE NOCASE;`, options);
23
- return console.log(JSON.stringify({ ...user, scopes, groups, tenants }, null, 2));
24
- }
25
- if (action !== "update") throw new Error("Unknown user action.");
26
- const assignments = [];
27
- if (options.roles !== undefined) assignments.push(`is_admin=${csv(options.roles).includes("admin") ? 1 : 0}`);
28
- if (!assignments.length && options.scopes === undefined && options.groups === undefined && options.tenants === undefined) throw new Error("user:update requires --roles, --scopes, --groups, or --tenants.");
29
- if (assignments.length) query(options.database, target, `UPDATE auth_users SET ${assignments.join(",")},updated_at=CURRENT_TIMESTAMP WHERE id=${sql(rows[0].id)};`, options);
30
- if (options.scopes !== undefined) { query(options.database, target, "DELETE FROM auth_user_scopes WHERE user_id=" + sql(rows[0].id) + ";", options); for (const scope of csv(options.scopes)) query(options.database, target, "INSERT OR IGNORE INTO auth_user_scopes (user_id,scope_name,granted_by) VALUES (" + sql(rows[0].id) + "," + sql(scope) + ",'human:cli');", options); }
31
- if (options.groups !== undefined) { query(options.database, target, "DELETE FROM auth_user_groups WHERE user_id=" + sql(rows[0].id) + ";", options); for (const group of csv(options.groups)) query(options.database, target, "INSERT OR IGNORE INTO auth_user_groups (user_id,group_name,granted_by) VALUES (" + sql(rows[0].id) + "," + sql(group) + ",'human:cli');", options); }
32
- if (options.tenants !== undefined) { const tenants = csv(options.tenants); if (tenants.length) { const available = query(options.database, target, "SELECT id FROM auth_tenants WHERE id IN (" + tenants.map(sql).join(",") + ");", options); const found = new Set(available.map((tenant) => tenant.id)); if (found.size !== tenants.length) throw new Error("One or more tenants do not exist."); } query(options.database, target, "DELETE FROM auth_user_tenants WHERE user_id=" + sql(rows[0].id) + ";", options); for (const tenant of tenants) query(options.database, target, "INSERT OR IGNORE INTO auth_user_tenants (user_id,tenant_id) VALUES (" + sql(rows[0].id) + "," + sql(tenant) + ");", options); }
33
- return runUserCommand({ action: "get", username: rows[0].id, options });
34
- }
@@ -1,54 +0,0 @@
1
- import { readFileSync } from "node:fs";
2
- import { spawnSync } from "node:child_process";
3
-
4
- export const PACKAGE_NAME = "@agilesyndrome/cf-genai-base";
5
-
6
- export function localVersion() {
7
- const packageUrl = new URL("../../package.json", import.meta.url);
8
- return JSON.parse(readFileSync(packageUrl, "utf8")).version;
9
- }
10
-
11
- export function latestVersion(packageName = PACKAGE_NAME) {
12
- const result = spawnSync("npm", ["view", packageName, "version"], {
13
- stdio: ["ignore", "pipe", "pipe"],
14
- encoding: "utf8",
15
- });
16
- if (result.error || result.status !== 0) return null;
17
- const value = result.stdout.trim();
18
- return value || null;
19
- }
20
-
21
- function parsedVersion(value) {
22
- const match = String(value).trim().replace(/^v/, "").match(/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?/);
23
- if (!match) return null;
24
- return {
25
- numbers: match.slice(1, 4).map(Number),
26
- prerelease: match[4]?.split(".") ?? [],
27
- };
28
- }
29
-
30
- export function compareVersions(left, right) {
31
- const a = parsedVersion(left);
32
- const b = parsedVersion(right);
33
- if (!a || !b) return String(left).localeCompare(String(right));
34
- for (let index = 0; index < 3; index += 1) {
35
- if (a.numbers[index] !== b.numbers[index]) return a.numbers[index] - b.numbers[index];
36
- }
37
- if (a.prerelease.length === 0 && b.prerelease.length > 0) return 1;
38
- if (a.prerelease.length > 0 && b.prerelease.length === 0) return -1;
39
- return String(a.prerelease).localeCompare(String(b.prerelease), undefined, { numeric: true });
40
- }
41
-
42
- export function formatVersionOutput({ local, latest, packageName = PACKAGE_NAME }) {
43
- const lines = [`${packageName} local: ${local}`, `${packageName} latest: ${latest ?? "unavailable"}`];
44
- if (latest && compareVersions(latest, local) > 0) {
45
- lines.push("Upgrade available:", ` npm i -g ${packageName}`);
46
- }
47
- return lines.join("\n");
48
- }
49
-
50
- export function runVersionCommand() {
51
- const local = localVersion();
52
- const latest = latestVersion();
53
- console.log(formatVersionOutput({ local, latest }));
54
- }
@@ -1,134 +0,0 @@
1
- import { auditLog, eventLog } from "./events.js";
2
- import { createD1 } from "./d1.js";
3
- import { secureJson } from "./security.js";
4
- import { BASE_PACKAGE_NAME, BASE_VERSION, CIRCUIT_BREAKER_STATES, HEALTHCHECK_MODES, HEALTHCHECK_STATES } from "./constants.js";
5
-
6
- export async function featureCircuit(env, id, who = "system:read") {
7
- return getCircuitBreaker(env, id, { who }).catch((error) => {
8
- eventLog("error", "feature.circuit.read.failed", { breaker: id, errorName: error?.name || "Error", errorMessage: String(error?.message || "Unknown circuit breaker error").slice(0, 300) });
9
- void env?.event?.("feature.circuit.read.failed", "feature", { breaker: id, who, errorName: error?.name || "Error" });
10
- return null;
11
- });
12
- }
13
-
14
- export async function featureAvailable(env, id, who = "system:read") { return (await featureCircuit(env, id, who))?.state === "on"; }
15
-
16
- export async function requireFeatureCircuit(env, { feature, breakerId, operation, requestId, who, message = "The requested feature is unavailable." }) {
17
- const breaker = await featureCircuit(env, breakerId, who || "system:read");
18
- if (breaker?.state === "on") return breaker;
19
- const details = { feature, breaker: breakerId, state: breaker?.state || "missing", operation, requestId: requestId || null };
20
- eventLog("warn", "feature.request.blocked", details);
21
- auditLog({ who: who || "system:read", operation: "blocked", resource: `feature:${feature}`, details });
22
- await env?.event?.("feature.request.blocked", "feature", { ...details, who: who || "system:read" });
23
- throw Object.assign(new Error(message), { status: 503, code: "feature_circuit_unavailable", feature, breakerId, circuitState: breaker?.state || "missing" });
24
- }
25
-
26
- export function createAvailabilityFeature({ name = "base", breakerId = `${name}:site-available`, displayName = "Site availability", publicPaths = ["/health", "/api/health"] } = {}) {
27
- return {
28
- name,
29
- packageName: BASE_PACKAGE_NAME,
30
- version: BASE_VERSION,
31
- healthcheck: async () => ({ feature: name, component: "site-available", displayName, state: "green", metadata: { endpoint: "/health", expectedStatus: 200 } }),
32
- circuitBreakers: [{ id: breakerId, name: "site-available", displayName, state: "on", allowSelfHealing: false, healthchecks: [`${name}:site-available`] }],
33
- async middleware(request, env, ctx, next) {
34
- const pathname = new URL(request.url).pathname;
35
- if (publicPaths.some((path) => pathname === path || pathname.startsWith(`${path}/`))) return next(request);
36
- const breaker = await featureCircuit(env, breakerId, "system:read");
37
- if (breaker?.state === "on") return next(request);
38
- await env.event?.("feature.maintenance", "availability", { feature: name, breaker: breakerId, state: breaker?.state || "missing", pathname, method: request.method });
39
- return secureJson({ error: "The site is temporarily unavailable." }, 503);
40
- },
41
- };
42
- }
43
-
44
- export function normalizeHealthcheck(input = {}) {
45
- const state = String(input.state || "yellow").toLowerCase();
46
- if (!HEALTHCHECK_STATES.includes(state)) throw new Error("Healthcheck state must be red, yellow, or green");
47
- if (!input.feature || !input.component || !input.displayName) throw new Error("Healthchecks require feature, component, and displayName");
48
- return { feature: String(input.feature), component: String(input.component), displayName: String(input.displayName), state, metadata: input.metadata || {} };
49
- }
50
-
51
- export function normalizeCircuitBreaker(input = {}) {
52
- const state = String(input.state || "off").toLowerCase();
53
- const healthcheckMode = String(input.healthcheckMode || "any").toLowerCase();
54
- if (!CIRCUIT_BREAKER_STATES.includes(state)) throw new Error("Circuit breaker state must be off, tripped, or on");
55
- if (!HEALTHCHECK_MODES.includes(healthcheckMode)) throw new Error("Circuit breaker healthcheckMode must be any or all");
56
- if (!input.feature || !input.name || !input.displayName) throw new Error("Circuit breakers require feature, name, and displayName");
57
- return { feature: String(input.feature), name: String(input.name), displayName: String(input.displayName), state, healthcheckMode, allowSelfHealing: Boolean(input.allowSelfHealing), healthchecks: Array.isArray(input.healthchecks) ? input.healthchecks.map(String) : [], dependsOnCircuitBreakers: Array.isArray(input.dependsOnCircuitBreakers || input.dependencies) ? (input.dependsOnCircuitBreakers || input.dependencies).map(String) : [], metadata: input.metadata || {} };
58
- }
59
-
60
- export async function registerHealthcheck(env, input, { who = "system:read" } = {}) {
61
- const item = normalizeHealthcheck(input); const db = createD1(env, { who }); const id = String(input.id || `${item.feature}:${item.component}`);
62
- await db.prepare(`INSERT INTO core_healthchecks (id,feature,component,display_name,state,metadata_json) VALUES (?,?,?,?,?,?) ON CONFLICT(feature,component) DO UPDATE SET display_name=excluded.display_name,metadata_json=excluded.metadata_json,updated_at=CURRENT_TIMESTAMP`).bind(id, item.feature, item.component, item.displayName, item.state, JSON.stringify(item.metadata)).run();
63
- return getHealthcheck(env, id, { who });
64
- }
65
-
66
- export async function updateHealthcheck(env, id, state, { who = "system:read" } = {}) {
67
- if (!HEALTHCHECK_STATES.includes(String(state).toLowerCase())) throw new Error("Healthcheck state must be red, yellow, or green");
68
- const item = await getHealthcheck(env, id, { who }); if (!item) return null;
69
- await createD1(env, { who }).prepare("UPDATE core_healthchecks SET state=?,updated_at=CURRENT_TIMESTAMP WHERE id=?").bind(String(state).toLowerCase(), id).run();
70
- auditLog({ who, operation: "update", resource: `feature:${item.feature} component:${item.component} ${String(state).toLowerCase()}` });
71
- return getHealthcheck(env, id, { who });
72
- }
73
-
74
- export async function getHealthcheck(env, id, { who = "system:read" } = {}) { return (await createD1(env, { who }).prepare("SELECT * FROM core_healthchecks WHERE id=?").bind(id).first()) || null; }
75
- export async function listHealthchecks(env, { who = "system:read" } = {}) { return (await createD1(env, { who }).prepare("SELECT * FROM core_healthchecks ORDER BY feature,component").bind().all()).results || []; }
76
-
77
- export async function registerCircuitBreaker(env, input, { who = "system:read" } = {}) {
78
- const item = normalizeCircuitBreaker(input); const db = createD1(env, { who }); const id = String(input.id || `${item.feature}:${item.name}`);
79
- await db.prepare(`INSERT INTO core_circuit_breakers (id,feature,name,display_name,state,healthcheck_mode,allow_self_healing,metadata_json) VALUES (?,?,?,?,?,?,?,?) ON CONFLICT(feature,name) DO UPDATE SET display_name=excluded.display_name,healthcheck_mode=excluded.healthcheck_mode,allow_self_healing=excluded.allow_self_healing,metadata_json=excluded.metadata_json,updated_at=CURRENT_TIMESTAMP`).bind(id, item.feature, item.name, item.displayName, item.state, item.healthcheckMode, item.allowSelfHealing ? 1 : 0, JSON.stringify(item.metadata)).run();
80
- await db.batch([db.prepare("DELETE FROM core_circuit_breaker_healthchecks WHERE circuit_breaker_id=?").bind(id), db.prepare("DELETE FROM core_circuit_breaker_dependencies WHERE circuit_breaker_id=?").bind(id), ...item.healthchecks.map((healthcheckId) => db.prepare("INSERT OR IGNORE INTO core_circuit_breaker_healthchecks (circuit_breaker_id,healthcheck_id) VALUES (?,?)").bind(id, healthcheckId)), ...item.dependsOnCircuitBreakers.map((dependencyId) => db.prepare("INSERT OR IGNORE INTO core_circuit_breaker_dependencies (circuit_breaker_id,dependency_id) VALUES (?,?)").bind(id, dependencyId))]);
81
- return getCircuitBreaker(env, id, { who });
82
- }
83
-
84
- export async function getCircuitBreaker(env, id, { who = "system:read" } = {}) { const db = createD1(env, { who }); const breaker = await db.prepare("SELECT * FROM core_circuit_breakers WHERE id=?").bind(id).first(); if (!breaker) return null; breaker.healthchecks = (await db.prepare("SELECT healthcheck_id FROM core_circuit_breaker_healthchecks WHERE circuit_breaker_id=?").bind(id).all()).results.map((row) => row.healthcheck_id); breaker.depends_on_circuit_breakers = (await db.prepare("SELECT dependency_id FROM core_circuit_breaker_dependencies WHERE circuit_breaker_id=?").bind(id).all()).results.map((row) => row.dependency_id); return breaker; }
85
- export async function listCircuitBreakers(env, { who = "system:read" } = {}) { const rows = (await createD1(env, { who }).prepare("SELECT * FROM core_circuit_breakers ORDER BY feature,name").bind().all()).results || []; return Promise.all(rows.map((row) => getCircuitBreaker(env, row.id, { who }))); }
86
-
87
- export async function setCircuitBreaker(env, id, state, { who = "system:read", automated = false } = {}) {
88
- const next = String(state).toLowerCase(); if (!CIRCUIT_BREAKER_STATES.includes(next)) throw new Error("Circuit breaker state must be off, tripped, or on");
89
- const current = await getCircuitBreaker(env, id, { who }); if (!current) return null;
90
- if (automated && !((current.state === "on" && next === "tripped") || (current.state === "tripped" && next === "on" && Boolean(current.allow_self_healing)))) return current;
91
- if (automated && next === "off") return current;
92
- await createD1(env, { who }).prepare("UPDATE core_circuit_breakers SET state=?,updated_at=CURRENT_TIMESTAMP WHERE id=?").bind(next, id).run();
93
- auditLog({ who, operation: "update", resource: `feature:${current.feature} circuit_breaker:${current.name} ${next}` });
94
- return getCircuitBreaker(env, id, { who });
95
- }
96
-
97
- export async function evaluateCircuitBreaker(env, id, { who = "system:read" } = {}) {
98
- const breaker = await getCircuitBreaker(env, id, { who }); if (!breaker) return null; const db = createD1(env, { who });
99
- const rows = (await db.prepare("SELECT h.state FROM core_healthchecks h JOIN core_circuit_breaker_healthchecks b ON b.healthcheck_id=h.id WHERE b.circuit_breaker_id=?").bind(id).all()).results || [];
100
- const failing = rows.map((row) => row.state === "red"); const dependencies = (await db.prepare("SELECT b.state FROM core_circuit_breakers b JOIN core_circuit_breaker_dependencies d ON d.dependency_id=b.id WHERE d.circuit_breaker_id=?").bind(id).all()).results || [];
101
- const dependencyFailed = dependencies.some((row) => row.state === "tripped"); const shouldTrip = dependencyFailed || (failing.length > 0 && (breaker.healthcheck_mode === "all" ? failing.every(Boolean) : failing.some(Boolean)));
102
- if (breaker.state === "on" && shouldTrip) return setCircuitBreaker(env, id, "tripped", { who, automated: true });
103
- if (breaker.state === "tripped" && !shouldTrip && breaker.allow_self_healing) return setCircuitBreaker(env, id, "on", { who, automated: true });
104
- return breaker;
105
- }
106
-
107
- export async function registerFeatureManifests(env, features = [], { who = "system:read" } = {}) {
108
- for (const feature of features) {
109
- const name = String(feature?.name || feature?.id || "feature"); const declaredResult = typeof feature?.healthcheck === "function" ? await feature.healthcheck(env, { who }) : (feature?.healthchecks || feature?.healthChecks || []); const declaredHealthchecks = Array.isArray(declaredResult) ? declaredResult : [declaredResult]; const healthchecks = []; const breakers = [];
110
- for (const healthcheck of declaredHealthchecks) healthchecks.push(await registerHealthcheck(env, { ...healthcheck, feature: healthcheck.feature || name }, { who }));
111
- for (const breaker of feature?.circuitBreakers || feature?.circuit_breakers || []) breakers.push(await registerCircuitBreaker(env, { ...breaker, feature: breaker.feature || name }, { who }));
112
- await registerCircuitBreaker(env, { id: `${name}:rollup`, feature: name, name: "rollup", displayName: `${name} feature`, state: "on", allowSelfHealing: true, healthchecks: healthchecks.filter(Boolean).map((item) => item.id), dependsOnCircuitBreakers: breakers.filter(Boolean).map((item) => item.id) }, { who });
113
- }
114
- }
115
-
116
- export async function listFeatureHealth(env, { who = "system:read" } = {}) {
117
- const checks = await listHealthchecks(env, { who }); const severity = { green: 0, yellow: 1, red: 2 }; const features = {};
118
- for (const check of checks) { const name = check.feature; if (!features[name] || severity[check.state] > severity[features[name].state]) features[name] = { feature: name, state: check.state, healthchecks: 0 }; features[name].healthchecks += 1; }
119
- return Object.values(features).sort((a, b) => a.feature.localeCompare(b.feature));
120
- }
121
-
122
- export function normalizeFeatureManifest(feature = {}) {
123
- const source = feature && typeof feature === "object" ? feature : {}; const manifest = source.manifest && typeof source.manifest === "object" ? source.manifest : source; const name = String(source.name || source.id || manifest.name || "feature"); const packageName = source.packageName || source.package_name || source.package || manifest.packageName || manifest.package_name || manifest.package; const version = source.version || source.packageVersion || source.package_version || manifest.version;
124
- return { feature: name, display_name: String(source.displayName || source.display_name || manifest.displayName || manifest.display_name || name), package_name: packageName ? String(packageName) : null, version: version ? String(version) : null };
125
- }
126
-
127
- export async function listFeatureCatalog(env, features = [], { who = "system:read" } = {}) {
128
- const [healthchecks, circuitBreakers] = await Promise.all([listHealthchecks(env, { who }), listCircuitBreakers(env, { who })]); const manifests = new Map([["base", { feature: "base", display_name: "Base platform", package_name: BASE_PACKAGE_NAME, version: BASE_VERSION }]]);
129
- for (const feature of features) { const manifest = normalizeFeatureManifest(feature); manifests.set(manifest.feature, manifest); }
130
- for (const item of healthchecks) if (!manifests.has(item.feature)) manifests.set(item.feature, normalizeFeatureManifest({ name: item.feature }));
131
- for (const item of circuitBreakers) if (!manifests.has(item.feature)) manifests.set(item.feature, normalizeFeatureManifest({ name: item.feature }));
132
- const severity = { green: 0, yellow: 1, red: 2 }; const state = (items) => items.reduce((current, item) => severity[item.state] > severity[current] ? item.state : current, "green");
133
- return [...manifests.values()].sort((a, b) => a.feature.localeCompare(b.feature)).map((manifest) => { const featureHealthchecks = healthchecks.filter((item) => item.feature === manifest.feature); const featureBreakers = circuitBreakers.filter((item) => item.feature === manifest.feature); const rollup = featureBreakers.find((item) => item.name === "rollup") || null; return { ...manifest, health: featureHealthchecks.length ? state(featureHealthchecks) : "yellow", healthchecks: featureHealthchecks, circuit_breakers: featureBreakers, circuit_breaker: rollup }; });
134
- }
package/src/core/d1.js DELETED
@@ -1,54 +0,0 @@
1
- import { auditLog, eventLog } from "./events.js";
2
-
3
- export function createD1(env, { who = "system:read" } = {}) {
4
- if (!env?.DB) throw new Error("A DB binding is required");
5
- const db = env.DB;
6
- return {
7
- prepare(sql) {
8
- const statement = db.prepare(sql);
9
- return new Proxy(statement, { get(target, property) {
10
- const value = target[property];
11
- if (typeof value !== "function" || !["run", "first", "all", "raw"].includes(property)) return typeof value === "function" ? value.bind(target) : value;
12
- return async (...args) => { auditD1(who, sql); return value.apply(target, args); };
13
- }});
14
- },
15
- async batch(statements) {
16
- auditD1(who, "BATCH");
17
- return typeof db.batch === "function" ? db.batch(statements) : Promise.all(statements.map((statement) => statement.run()));
18
- },
19
- };
20
- }
21
-
22
- export function auditedD1(db, who = "system:read") {
23
- if (!db) return db;
24
- return new Proxy(db, {
25
- get(target, property) {
26
- const value = target[property];
27
- if (property === "prepare") return (sql) => {
28
- const statement = value.call(target, sql);
29
- return new Proxy(statement, {
30
- get(statementTarget, statementProperty) {
31
- const method = statementTarget[statementProperty];
32
- if (!["run", "first", "all", "raw"].includes(statementProperty) || typeof method !== "function") return typeof method === "function" ? method.bind(statementTarget) : method;
33
- return async (...args) => { auditD1(who, sql); return method.apply(statementTarget, args); };
34
- },
35
- });
36
- };
37
- if (property === "batch") return (statements) => { auditD1(who, "BATCH"); return typeof value === "function" ? value.call(target, statements) : Promise.all(statements.map((statement) => statement.run())); };
38
- return typeof value === "function" ? value.bind(target) : value;
39
- },
40
- });
41
- }
42
-
43
- export function auditedEnv(env, who = "system:read") {
44
- if (!env?.DB) return env;
45
- const result = Object.create(env);
46
- result.DB = auditedD1(env.DB, who);
47
- return result;
48
- }
49
-
50
- function auditD1(who, sql) {
51
- const operation = String(sql).trim().match(/^(SELECT|INSERT|UPDATE|DELETE|REPLACE|WITH)/i)?.[1]?.toLowerCase() || "execute";
52
- eventLog("debug", "d1.operation", { who, operation });
53
- auditLog({ who, operation, resource: "d1" });
54
- }
@@ -1,29 +0,0 @@
1
- import { DurableObject } from "cloudflare:workers";
2
-
3
- export class EventHub extends DurableObject {
4
- async fetch(request) {
5
- const url = new URL(request.url);
6
- if (request.method === "POST" && url.pathname === "/publish") {
7
- if (request.headers.get("X-CF-GenAI-Event") !== "1") return new Response("Not found", { status: 404 });
8
- const event = await request.json().catch(() => null);
9
- if (!event?.id || !event?.what) return Response.json({ error: "Invalid event" }, { status: 400 });
10
- const message = JSON.stringify({ type: "event", event });
11
- for (const socket of this.ctx.getWebSockets()) {
12
- try { socket.send(message); } catch { socket.close(1011, "Event delivery failed"); }
13
- }
14
- return Response.json({ ok: true });
15
- }
16
- if (request.method !== "GET" || request.headers.get("Upgrade")?.toLowerCase() !== "websocket") return new Response("WebSocket upgrade required", { status: 426 });
17
- const pair = new WebSocketPair();
18
- const [client, server] = Object.values(pair);
19
- this.ctx.acceptWebSocket(server);
20
- return new Response(null, { status: 101, webSocket: client });
21
- }
22
-
23
- webSocketMessage(socket, message) {
24
- if (message === "ping") socket.send(JSON.stringify({ type: "pong" }));
25
- }
26
-
27
- webSocketClose() {}
28
- webSocketError() {}
29
- }
@@ -1,63 +0,0 @@
1
- export function Event(who, what, where, when = new Date(), details = {}) {
2
- return {
3
- id: crypto.randomUUID(),
4
- who: String(who || "system"),
5
- what: String(what || "event"),
6
- where: String(where || "application"),
7
- when: when instanceof Date ? when.toISOString() : new Date(when || Date.now()).toISOString(),
8
- details: details && typeof details === "object" ? details : { value: details },
9
- };
10
- }
11
-
12
- export function createEventHandler(features = [], { eventHubBinding = "EVENT_HUB" } = {}) {
13
- const handlers = features.flatMap((feature) => {
14
- const handler = feature?.eventHandler || feature?.event_handler;
15
- return typeof handler === "function" ? [handler.bind(feature)] : [];
16
- });
17
- return async (event, env, ctx) => {
18
- if (!event) return null;
19
- eventLog("info", event.what, { who: event.who, where: event.where, when: event.when, ...event.details });
20
- await Promise.all([
21
- ...handlers.map((handler) => Promise.resolve(handler(event, { env, ctx }))),
22
- publishLiveEvent(env, event, eventHubBinding),
23
- ]);
24
- return event;
25
- };
26
- }
27
-
28
- export function eventRooms(event) {
29
- const audience = event?.details?.audience || {};
30
- const rooms = [];
31
- if (audience.userId) rooms.push(`user:${audience.userId}`);
32
- if (audience.tenantId) rooms.push(`tenant:${audience.tenantId}`);
33
- if (!rooms.length && String(event?.who || "").startsWith("user:")) rooms.push(String(event.who));
34
- return [...new Set(rooms)];
35
- }
36
-
37
- async function publishLiveEvent(env, event, bindingName) {
38
- const namespace = bindingName && env?.[bindingName];
39
- if (!namespace || typeof namespace.idFromName !== "function") return;
40
- for (const room of eventRooms(event)) {
41
- try {
42
- const stub = namespace.get(namespace.idFromName(room));
43
- await stub.fetch("https://cf-genai-event-hub/publish", { method: "POST", headers: { "X-CF-GenAI-Event": "1", "Content-Type": "application/json" }, body: JSON.stringify(event) });
44
- } catch (error) {
45
- eventLog("warn", "live.event.publish.failed", { room, error: error?.message || String(error) });
46
- }
47
- }
48
- }
49
-
50
- export async function emitEvent(env, event, ctx) {
51
- if (typeof env?.eventHandler === "function") return env.eventHandler(event, env, ctx);
52
- if (event) eventLog("info", event.what, { who: event.who, where: event.where, when: event.when, ...event.details });
53
- return event;
54
- }
55
-
56
- export function eventLog(level, event, details = {}) {
57
- const method = ["debug", "info", "warn", "error"].includes(level) ? level : "info";
58
- console[method](`[EventLog] ${event}`, details);
59
- }
60
-
61
- export function auditLog({ who = "system", operation, resource, details = {} }) {
62
- console.info(`[AuditLog] ${who}:${operation} ${resource}`, details);
63
- }
@@ -1,39 +0,0 @@
1
- import { Event, emitEvent } from "./events.js";
2
-
3
- export function requestActor(state = {}) {
4
- if (state.requestedBy) return String(state.requestedBy);
5
- const canonical = authUser(state);
6
- if (canonical?.id) return `user:${canonical.id}`;
7
- if (state.user?.auth_strategy === "http_basic") return "user:admin";
8
- if (state.user?.sub) return `user:${state.user.sub}`;
9
- return "system:read";
10
- }
11
-
12
- export function authUser(value) {
13
- return value?.authUser || value?.user?.authUser || value?.state?.authUser || value?.state?.user?.authUser || (value?.id && value?.provider && value?.subject ? value : null) || null;
14
- }
15
-
16
- export function userId(value) {
17
- return authUser(value)?.id || value?.userId || value?.sub || value?.email || null;
18
- }
19
-
20
- export function requestIdentity(state = {}) {
21
- const canonical = authUser(state);
22
- return {
23
- user: state.user || null,
24
- authUser: canonical,
25
- userId: canonical?.id || null,
26
- who: requestActor(state),
27
- isAuthenticated: Boolean(canonical || state.user),
28
- isAdmin: Boolean(state.user?.auth_strategy === "http_basic" || canonical?.is_admin),
29
- };
30
- }
31
-
32
- export function requestContext({ request, env, ctx, state, data } = {}) {
33
- const identity = requestIdentity(state);
34
- return {
35
- request, env, ctx, state, data: data || state?.data,
36
- ...identity,
37
- event: (what, where = "application", details = {}, when = new Date()) => emitEvent(env, Event(identity.who, what, where, when, details), ctx),
38
- };
39
- }
package/src/core/index.js DELETED
@@ -1,7 +0,0 @@
1
- export * from "./constants.js";
2
- export * from "./events.js";
3
- export * from "./identity.js";
4
- export * from "./security.js";
5
- export * from "./d1.js";
6
- export * from "./circuits.js";
7
- export * from "./jobs.js";
package/src/core/jobs.js DELETED
@@ -1,185 +0,0 @@
1
- import { Event, emitEvent } from "./events.js";
2
- import { createD1 } from "./d1.js";
3
-
4
- export const JOB_STATUSES = Object.freeze(["queued", "running", "succeeded", "failed", "cancelled"]);
5
- const JOB_STATUS_SET = new Set(JOB_STATUSES);
6
- const TERMINAL_STATUSES = new Set(["succeeded", "failed", "cancelled"]);
7
-
8
- export async function createJob(env, definition = {}, { who = "system:update", ctx } = {}) {
9
- const id = String(definition.id || crypto.randomUUID());
10
- const type = required(definition.type, "Job type");
11
- const status = normalizeStatus(definition.status || "queued");
12
- const now = new Date().toISOString();
13
- const db = createD1(env, { who });
14
- await db.prepare(`
15
- INSERT INTO core_jobs
16
- (id, type, status, owner_id, tenant_id, resource_type, resource_id,
17
- input_json, result_json, error_json, progress_json, created_at, updated_at, expires_at)
18
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, '{}', NULL, ?, ?, ?, ?)
19
- `).bind(
20
- id,
21
- type,
22
- status,
23
- nullable(definition.ownerId),
24
- nullable(definition.tenantId),
25
- nullable(definition.resourceType),
26
- nullable(definition.resourceId),
27
- encode(definition.input),
28
- encode(definition.progress),
29
- now,
30
- now,
31
- nullable(definition.expiresAt),
32
- ).run();
33
- const job = await getJob(env, id, { who });
34
- await publishJobEvent(env, job, "job.created", who, ctx);
35
- return job;
36
- }
37
-
38
- export async function getJob(env, id, { who = "system:read" } = {}) {
39
- const row = await createD1(env, { who }).prepare("SELECT * FROM core_jobs WHERE id = ?").bind(String(id)).first();
40
- return row ? normalizeJob(row) : null;
41
- }
42
-
43
- export async function listJobs(env, filters = {}, { who = "system:read" } = {}) {
44
- const clauses = [];
45
- const values = [];
46
- if (filters.ownerId !== undefined) { clauses.push("owner_id = ?"); values.push(nullable(filters.ownerId)); }
47
- if (filters.tenantId !== undefined) { clauses.push("tenant_id = ?"); values.push(nullable(filters.tenantId)); }
48
- if (filters.type) { clauses.push("type = ?"); values.push(String(filters.type)); }
49
- if (filters.status) { clauses.push("status = ?"); values.push(normalizeStatus(filters.status)); }
50
- if (filters.resourceType) { clauses.push("resource_type = ?"); values.push(String(filters.resourceType)); }
51
- if (filters.resourceId) { clauses.push("resource_id = ?"); values.push(String(filters.resourceId)); }
52
- const limit = boundedLimit(filters.limit);
53
- const sql = `SELECT * FROM core_jobs${clauses.length ? ` WHERE ${clauses.join(" AND ")}` : ""} ORDER BY updated_at DESC LIMIT ?`;
54
- const result = await createD1(env, { who }).prepare(sql).bind(...values, limit).all();
55
- return (result?.results || []).map(normalizeJob);
56
- }
57
-
58
- export async function listJobEvents(env, jobId, { who = "system:read", limit = 100 } = {}) {
59
- const result = await createD1(env, { who }).prepare("SELECT * FROM core_job_events WHERE job_id = ? ORDER BY created_at ASC LIMIT ?").bind(String(jobId), boundedLimit(limit, 500)).all();
60
- return (result?.results || []).map(normalizeJobEvent);
61
- }
62
-
63
- export async function startJob(env, id, options = {}) {
64
- return updateJob(env, id, { status: "running", startedAt: new Date().toISOString() }, options);
65
- }
66
-
67
- export async function updateJobProgress(env, id, progress, options = {}) {
68
- return updateJob(env, id, { progress }, options);
69
- }
70
-
71
- export async function completeJob(env, id, result = {}, options = {}) {
72
- return updateJob(env, id, { status: "succeeded", result, finishedAt: new Date().toISOString() }, options);
73
- }
74
-
75
- export async function failJob(env, id, error, options = {}) {
76
- const details = error instanceof Error ? { name: error.name, message: error.message, code: error.code || null } : error;
77
- return updateJob(env, id, { status: "failed", error: details, finishedAt: new Date().toISOString() }, options);
78
- }
79
-
80
- export async function cancelJob(env, id, options = {}) {
81
- return updateJob(env, id, { status: "cancelled", finishedAt: new Date().toISOString() }, options);
82
- }
83
-
84
- export async function dispatchJob(env, definition, { workflow, params = {}, retention, who = "system:update", ctx } = {}) {
85
- if (!workflow || typeof workflow.create !== "function") throw new TypeError("A Workflow binding is required to dispatch a job");
86
- const job = await createJob(env, definition, { who, ctx });
87
- try {
88
- await workflow.create({
89
- id: job.id,
90
- params: { ...params, jobId: job.id },
91
- ...(retention ? { retention } : {}),
92
- });
93
- return job;
94
- } catch (error) {
95
- await failJob(env, job.id, error, { who, ctx });
96
- throw error;
97
- }
98
- }
99
-
100
- export async function executeJob(env, id, execute, { who = "system:update", ctx, toJobResult = identity } = {}) {
101
- if (typeof execute !== "function") throw new TypeError("Job executor must be a function");
102
- const running = await startJob(env, id, { who, ctx });
103
- if (!running) throw new TypeError(`Unknown job: ${id}`);
104
- const report = (progress) => updateJobProgress(env, id, progress, { who, ctx });
105
- try {
106
- const value = await execute({ job: running, report });
107
- const result = await toJobResult(value);
108
- const job = await completeJob(env, id, result === undefined ? {} : result, { who, ctx });
109
- return { job, value };
110
- } catch (error) {
111
- await failJob(env, id, error, { who, ctx });
112
- throw error;
113
- }
114
- }
115
-
116
- export async function runJob(env, definition, execute, options = {}) {
117
- const job = await createJob(env, definition, options);
118
- return executeJob(env, job.id, execute, options);
119
- }
120
-
121
- export async function updateJob(env, id, patch = {}, { who = "system:update", ctx } = {}) {
122
- const current = await getJob(env, id, { who });
123
- if (!current) return null;
124
- const nextStatus = patch.status === undefined ? current.status : normalizeStatus(patch.status);
125
- const values = [];
126
- const assignments = [];
127
- const fields = [
128
- ["status", nextStatus],
129
- ["result_json", patch.result === undefined ? undefined : encode(patch.result)],
130
- ["error_json", patch.error === undefined ? undefined : (patch.error == null ? null : encode(patch.error))],
131
- ["progress_json", patch.progress === undefined ? undefined : encode(patch.progress)],
132
- ["started_at", patch.startedAt === undefined ? undefined : nullable(patch.startedAt)],
133
- ["finished_at", patch.finishedAt === undefined ? undefined : nullable(patch.finishedAt)],
134
- ["expires_at", patch.expiresAt === undefined ? undefined : nullable(patch.expiresAt)],
135
- ];
136
- if (nextStatus === "running" && !current.startedAt && patch.startedAt === undefined) fields[4] = ["started_at", new Date().toISOString()];
137
- if (TERMINAL_STATUSES.has(nextStatus) && !current.finishedAt && patch.finishedAt === undefined) fields[5] = ["finished_at", new Date().toISOString()];
138
- for (const [column, value] of fields) { if (value !== undefined) { assignments.push(`${column} = ?`); values.push(value); } }
139
- assignments.push("updated_at = ?"); values.push(new Date().toISOString(), String(id));
140
- await createD1(env, { who }).prepare(`UPDATE core_jobs SET ${assignments.join(", ")} WHERE id = ?`).bind(...values).run();
141
- const job = await getJob(env, id, { who });
142
- await publishJobEvent(env, job, patch.progress !== undefined && patch.status === undefined ? "job.progress" : `job.${nextStatus}`, who, ctx);
143
- return job;
144
- }
145
-
146
- export function normalizeJob(row) {
147
- return {
148
- id: String(row.id),
149
- type: String(row.type),
150
- status: String(row.status),
151
- ownerId: row.owner_id || null,
152
- tenantId: row.tenant_id || null,
153
- resourceType: row.resource_type || null,
154
- resourceId: row.resource_id || null,
155
- input: decode(row.input_json),
156
- result: decode(row.result_json),
157
- error: decode(row.error_json),
158
- progress: decode(row.progress_json),
159
- createdAt: row.created_at || null,
160
- startedAt: row.started_at || null,
161
- finishedAt: row.finished_at || null,
162
- updatedAt: row.updated_at || null,
163
- expiresAt: row.expires_at || null,
164
- };
165
- }
166
-
167
- export function normalizeJobEvent(row) {
168
- return { id: String(row.id), jobId: String(row.job_id), type: String(row.type), payload: decode(row.payload_json), createdAt: row.created_at || null };
169
- }
170
-
171
- async function publishJobEvent(env, job, type, who, ctx) {
172
- const payload = { jobId: job.id, type: job.type, status: job.status, ownerId: job.ownerId, tenantId: job.tenantId, resource: job.resourceType && job.resourceId ? { type: job.resourceType, id: job.resourceId } : null, progress: job.progress, result: type === "job.succeeded" ? job.result : undefined, error: type === "job.failed" ? job.error : undefined };
173
- const event = Event(who, type, "job", new Date(), { ...payload, audience: { userId: job.ownerId, tenantId: job.tenantId } });
174
- const db = createD1(env, { who });
175
- await db.prepare("INSERT INTO core_job_events (id, job_id, type, payload_json) VALUES (?, ?, ?, ?)").bind(event.id, job.id, type, encode(payload)).run();
176
- await emitEvent(env, event, ctx);
177
- }
178
-
179
- function normalizeStatus(status) { const value = String(status).toLowerCase(); if (!JOB_STATUS_SET.has(value)) throw new TypeError(`Unsupported job status: ${status}`); return value; }
180
- function required(value, label) { const normalized = String(value || "").trim(); if (!normalized) throw new TypeError(`${label} is required`); return normalized; }
181
- function nullable(value) { return value === undefined || value === null || value === "" ? null : String(value); }
182
- function encode(value) { return JSON.stringify(value === undefined ? {} : value); }
183
- function decode(value) { if (value == null || value === "") return null; try { return JSON.parse(value); } catch { return null; } }
184
- function boundedLimit(value, maximum = 100) { const normalized = Number(value); return Number.isFinite(normalized) && normalized > 0 ? Math.min(Math.floor(normalized), maximum) : Math.min(50, maximum); }
185
- function identity(value) { return value; }