@weave-kit/engine 0.5.0 → 0.6.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 (622) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +6 -6
  3. package/dist/adapters/auth/index.d.ts +4 -2
  4. package/dist/adapters/auth/index.d.ts.map +1 -1
  5. package/dist/adapters/auth/index.js +1 -0
  6. package/dist/adapters/auth/index.js.map +1 -1
  7. package/dist/adapters/auth/source.d.ts +4 -4
  8. package/dist/adapters/auth/source.d.ts.map +1 -1
  9. package/dist/adapters/auth/subject.d.ts +22 -0
  10. package/dist/adapters/auth/subject.d.ts.map +1 -0
  11. package/dist/adapters/auth/subject.js +42 -0
  12. package/dist/adapters/auth/subject.js.map +1 -0
  13. package/dist/adapters/auth/verify.d.ts +12 -0
  14. package/dist/adapters/auth/verify.d.ts.map +1 -0
  15. package/dist/adapters/auth/verify.js +2 -0
  16. package/dist/adapters/auth/verify.js.map +1 -0
  17. package/dist/adapters/events/index.d.ts +2 -1
  18. package/dist/adapters/events/index.d.ts.map +1 -1
  19. package/dist/adapters/events/index.js +2 -1
  20. package/dist/adapters/events/index.js.map +1 -1
  21. package/dist/adapters/mcp/generate.d.ts +3 -3
  22. package/dist/adapters/mcp/generate.d.ts.map +1 -1
  23. package/dist/adapters/mcp/generate.js +34 -11
  24. package/dist/adapters/mcp/generate.js.map +1 -1
  25. package/dist/adapters/mcp/guardrails.d.ts +1 -1
  26. package/dist/adapters/mcp/http.d.ts +3 -1
  27. package/dist/adapters/mcp/http.d.ts.map +1 -1
  28. package/dist/adapters/mcp/http.js +2 -2
  29. package/dist/adapters/mcp/http.js.map +1 -1
  30. package/dist/adapters/mcp/index.d.ts +13 -4
  31. package/dist/adapters/mcp/index.d.ts.map +1 -1
  32. package/dist/adapters/mcp/index.js +12 -8
  33. package/dist/adapters/mcp/index.js.map +1 -1
  34. package/dist/adapters/mcp/session.d.ts +5 -5
  35. package/dist/adapters/mcp/session.d.ts.map +1 -1
  36. package/dist/adapters/mcp/tools.d.ts +6 -0
  37. package/dist/adapters/mcp/tools.d.ts.map +1 -1
  38. package/dist/adapters/mcp/tools.js +38 -14
  39. package/dist/adapters/mcp/tools.js.map +1 -1
  40. package/dist/adapters/mcp/types.d.ts +3 -1
  41. package/dist/adapters/mcp/types.d.ts.map +1 -1
  42. package/dist/adapters/mcp/types.js +1 -1
  43. package/dist/adapters/mcp/types.js.map +1 -1
  44. package/dist/adapters/openapi/document.d.ts.map +1 -1
  45. package/dist/adapters/openapi/document.js +72 -2
  46. package/dist/adapters/openapi/document.js.map +1 -1
  47. package/dist/adapters/openapi/schema.d.ts.map +1 -1
  48. package/dist/adapters/openapi/schema.js +40 -4
  49. package/dist/adapters/openapi/schema.js.map +1 -1
  50. package/dist/adapters/openapi/types.d.ts +1 -0
  51. package/dist/adapters/openapi/types.d.ts.map +1 -1
  52. package/dist/adapters/openapi/types.js +2 -0
  53. package/dist/adapters/openapi/types.js.map +1 -1
  54. package/dist/adapters/rest/approvals.d.ts +2 -2
  55. package/dist/adapters/rest/approvals.js +2 -2
  56. package/dist/adapters/rest/audit.d.ts +2 -2
  57. package/dist/adapters/rest/audit.js +2 -2
  58. package/dist/adapters/rest/common.d.ts +3 -3
  59. package/dist/adapters/rest/common.d.ts.map +1 -1
  60. package/dist/adapters/rest/common.js +1 -1
  61. package/dist/adapters/rest/guardrails.d.ts +1 -1
  62. package/dist/adapters/rest/guardrails.js +1 -1
  63. package/dist/adapters/rest/identities.d.ts +4 -4
  64. package/dist/adapters/rest/identities.d.ts.map +1 -1
  65. package/dist/adapters/rest/identities.js +3 -3
  66. package/dist/adapters/rest/identities.js.map +1 -1
  67. package/dist/adapters/rest/identityAdmin.d.ts +18 -0
  68. package/dist/adapters/rest/identityAdmin.d.ts.map +1 -0
  69. package/dist/adapters/rest/identityAdmin.js +58 -0
  70. package/dist/adapters/rest/identityAdmin.js.map +1 -0
  71. package/dist/adapters/rest/index.d.ts +4 -0
  72. package/dist/adapters/rest/index.d.ts.map +1 -1
  73. package/dist/adapters/rest/index.js +3 -0
  74. package/dist/adapters/rest/index.js.map +1 -1
  75. package/dist/adapters/rest/metadata.d.ts +1 -1
  76. package/dist/adapters/rest/metadata.js +1 -1
  77. package/dist/adapters/rest/pages.d.ts +1 -1
  78. package/dist/adapters/rest/pages.d.ts.map +1 -1
  79. package/dist/adapters/rest/permissions.d.ts +1 -1
  80. package/dist/adapters/rest/permissions.js +1 -1
  81. package/dist/adapters/rest/plugin.d.ts +2 -2
  82. package/dist/adapters/rest/plugin.d.ts.map +1 -1
  83. package/dist/adapters/rest/schemas.d.ts +1 -1
  84. package/dist/adapters/rest/schemas.d.ts.map +1 -1
  85. package/dist/adapters/rest/workflow.d.ts +15 -0
  86. package/dist/adapters/rest/workflow.d.ts.map +1 -0
  87. package/dist/adapters/rest/workflow.js +89 -0
  88. package/dist/adapters/rest/workflow.js.map +1 -0
  89. package/dist/adapters/rest/workflowSource.d.ts +15 -0
  90. package/dist/adapters/rest/workflowSource.d.ts.map +1 -0
  91. package/dist/adapters/rest/workflowSource.js +63 -0
  92. package/dist/adapters/rest/workflowSource.js.map +1 -0
  93. package/dist/cli/commands/build.js +1 -1
  94. package/dist/cli/commands/build.js.map +1 -1
  95. package/dist/cli/commands/connect.d.ts +1 -1
  96. package/dist/cli/commands/default-view.d.ts +2 -2
  97. package/dist/cli/commands/default-view.js +2 -2
  98. package/dist/cli/commands/dev.d.ts.map +1 -1
  99. package/dist/cli/commands/dev.js +18 -9
  100. package/dist/cli/commands/dev.js.map +1 -1
  101. package/dist/cli/commands/identity.d.ts +15 -0
  102. package/dist/cli/commands/identity.d.ts.map +1 -0
  103. package/dist/cli/commands/identity.js +115 -0
  104. package/dist/cli/commands/identity.js.map +1 -0
  105. package/dist/cli/commands/introspect.d.ts.map +1 -1
  106. package/dist/cli/commands/introspect.js +23 -0
  107. package/dist/cli/commands/introspect.js.map +1 -1
  108. package/dist/cli/commands/mcp-config.js +1 -1
  109. package/dist/cli/commands/mcp-config.js.map +1 -1
  110. package/dist/cli/commands/migrate.js +2 -2
  111. package/dist/cli/commands/migrate.js.map +1 -1
  112. package/dist/cli/commands/module.d.ts +2 -2
  113. package/dist/cli/commands/module.d.ts.map +1 -1
  114. package/dist/cli/commands/module.js +2 -2
  115. package/dist/cli/commands/module.js.map +1 -1
  116. package/dist/cli/commands/object-create.d.ts.map +1 -1
  117. package/dist/cli/commands/object-create.js +15 -15
  118. package/dist/cli/commands/object-create.js.map +1 -1
  119. package/dist/cli/commands/workflow-close.d.ts +9 -0
  120. package/dist/cli/commands/workflow-close.d.ts.map +1 -0
  121. package/dist/cli/commands/workflow-close.js +48 -0
  122. package/dist/cli/commands/workflow-close.js.map +1 -0
  123. package/dist/cli/commands/workflow-migrate.d.ts +11 -0
  124. package/dist/cli/commands/workflow-migrate.d.ts.map +1 -0
  125. package/dist/cli/commands/workflow-migrate.js +120 -0
  126. package/dist/cli/commands/workflow-migrate.js.map +1 -0
  127. package/dist/cli/commands/workflow-open.d.ts +10 -0
  128. package/dist/cli/commands/workflow-open.d.ts.map +1 -0
  129. package/dist/cli/commands/workflow-open.js +112 -0
  130. package/dist/cli/commands/workflow-open.js.map +1 -0
  131. package/dist/cli/commands/workflow-starter.d.ts +10 -0
  132. package/dist/cli/commands/workflow-starter.d.ts.map +1 -0
  133. package/dist/cli/commands/workflow-starter.js +29 -0
  134. package/dist/cli/commands/workflow-starter.js.map +1 -0
  135. package/dist/cli/commands/workflow-switch.d.ts +10 -0
  136. package/dist/cli/commands/workflow-switch.d.ts.map +1 -0
  137. package/dist/cli/commands/workflow-switch.js +60 -0
  138. package/dist/cli/commands/workflow-switch.js.map +1 -0
  139. package/dist/cli/commands/workflow-upgrade.d.ts +12 -0
  140. package/dist/cli/commands/workflow-upgrade.d.ts.map +1 -0
  141. package/dist/cli/commands/workflow-upgrade.js +116 -0
  142. package/dist/cli/commands/workflow-upgrade.js.map +1 -0
  143. package/dist/cli/index.js +72 -3
  144. package/dist/cli/index.js.map +1 -1
  145. package/dist/cli/project-types/manifest.d.ts +25 -0
  146. package/dist/cli/project-types/manifest.d.ts.map +1 -0
  147. package/dist/cli/project-types/manifest.js +40 -0
  148. package/dist/cli/project-types/manifest.js.map +1 -0
  149. package/dist/cli/ready-screen.js +1 -1
  150. package/dist/cli/ready-screen.js.map +1 -1
  151. package/dist/cli/scaffold.d.ts.map +1 -1
  152. package/dist/cli/scaffold.js +21 -34
  153. package/dist/cli/scaffold.js.map +1 -1
  154. package/dist/cli/types/commands.d.ts +46 -0
  155. package/dist/cli/types/commands.d.ts.map +1 -1
  156. package/dist/cli/types/index.d.ts +1 -1
  157. package/dist/cli/types/index.d.ts.map +1 -1
  158. package/dist/cli/types/values.d.ts +9 -0
  159. package/dist/cli/types/values.d.ts.map +1 -1
  160. package/dist/cli/types/values.js +9 -0
  161. package/dist/cli/types/values.js.map +1 -1
  162. package/dist/core/api/error.d.ts.map +1 -1
  163. package/dist/core/api/error.js +7 -4
  164. package/dist/core/api/error.js.map +1 -1
  165. package/dist/core/audit/types.d.ts +4 -2
  166. package/dist/core/audit/types.d.ts.map +1 -1
  167. package/dist/core/audit/types.js +2 -0
  168. package/dist/core/audit/types.js.map +1 -1
  169. package/dist/core/formula/validate.d.ts.map +1 -1
  170. package/dist/core/formula/validate.js +6 -0
  171. package/dist/core/formula/validate.js.map +1 -1
  172. package/dist/core/i18n/ar.d.ts.map +1 -1
  173. package/dist/core/i18n/ar.js +37 -3
  174. package/dist/core/i18n/ar.js.map +1 -1
  175. package/dist/core/i18n/de.d.ts.map +1 -1
  176. package/dist/core/i18n/de.js +37 -3
  177. package/dist/core/i18n/de.js.map +1 -1
  178. package/dist/core/i18n/en.d.ts +38 -4
  179. package/dist/core/i18n/en.d.ts.map +1 -1
  180. package/dist/core/i18n/en.js +38 -4
  181. package/dist/core/i18n/en.js.map +1 -1
  182. package/dist/core/i18n/es.d.ts.map +1 -1
  183. package/dist/core/i18n/es.js +37 -3
  184. package/dist/core/i18n/es.js.map +1 -1
  185. package/dist/core/i18n/fr.d.ts.map +1 -1
  186. package/dist/core/i18n/fr.js +37 -3
  187. package/dist/core/i18n/fr.js.map +1 -1
  188. package/dist/core/i18n/hi.d.ts.map +1 -1
  189. package/dist/core/i18n/hi.js +37 -3
  190. package/dist/core/i18n/hi.js.map +1 -1
  191. package/dist/core/i18n/id.d.ts.map +1 -1
  192. package/dist/core/i18n/id.js +37 -3
  193. package/dist/core/i18n/id.js.map +1 -1
  194. package/dist/core/i18n/ja.d.ts.map +1 -1
  195. package/dist/core/i18n/ja.js +37 -3
  196. package/dist/core/i18n/ja.js.map +1 -1
  197. package/dist/core/i18n/ko.d.ts.map +1 -1
  198. package/dist/core/i18n/ko.js +37 -3
  199. package/dist/core/i18n/ko.js.map +1 -1
  200. package/dist/core/i18n/pt.d.ts.map +1 -1
  201. package/dist/core/i18n/pt.js +37 -3
  202. package/dist/core/i18n/pt.js.map +1 -1
  203. package/dist/core/i18n/ru.d.ts.map +1 -1
  204. package/dist/core/i18n/ru.js +37 -3
  205. package/dist/core/i18n/ru.js.map +1 -1
  206. package/dist/core/i18n/vi.d.ts.map +1 -1
  207. package/dist/core/i18n/vi.js +37 -3
  208. package/dist/core/i18n/vi.js.map +1 -1
  209. package/dist/core/i18n/zh-hant.d.ts.map +1 -1
  210. package/dist/core/i18n/zh-hant.js +37 -3
  211. package/dist/core/i18n/zh-hant.js.map +1 -1
  212. package/dist/core/i18n/zh.d.ts.map +1 -1
  213. package/dist/core/i18n/zh.js +38 -4
  214. package/dist/core/i18n/zh.js.map +1 -1
  215. package/dist/core/object/describe.d.ts +34 -3
  216. package/dist/core/object/describe.d.ts.map +1 -1
  217. package/dist/core/object/describe.js +48 -8
  218. package/dist/core/object/describe.js.map +1 -1
  219. package/dist/core/object/gen-types.d.ts.map +1 -1
  220. package/dist/core/object/gen-types.js +12 -1
  221. package/dist/core/object/gen-types.js.map +1 -1
  222. package/dist/core/object/graph.d.ts.map +1 -1
  223. package/dist/core/object/graph.js +52 -22
  224. package/dist/core/object/graph.js.map +1 -1
  225. package/dist/core/object/index.d.ts +5 -1
  226. package/dist/core/object/index.d.ts.map +1 -1
  227. package/dist/core/object/index.js +5 -1
  228. package/dist/core/object/index.js.map +1 -1
  229. package/dist/core/object/migrations.d.ts.map +1 -1
  230. package/dist/core/object/migrations.js +39 -0
  231. package/dist/core/object/migrations.js.map +1 -1
  232. package/dist/core/object/parse.d.ts +7 -0
  233. package/dist/core/object/parse.d.ts.map +1 -1
  234. package/dist/core/object/parse.js +32 -1
  235. package/dist/core/object/parse.js.map +1 -1
  236. package/dist/core/object/record-key.d.ts +19 -0
  237. package/dist/core/object/record-key.d.ts.map +1 -0
  238. package/dist/core/object/record-key.js +100 -0
  239. package/dist/core/object/record-key.js.map +1 -0
  240. package/dist/core/object/schema-version.d.ts +1 -1
  241. package/dist/core/object/schema-version.js +1 -1
  242. package/dist/core/object/system-objects.d.ts +16 -0
  243. package/dist/core/object/system-objects.d.ts.map +1 -0
  244. package/dist/core/object/system-objects.js +72 -0
  245. package/dist/core/object/system-objects.js.map +1 -0
  246. package/dist/core/object/validate/field.d.ts.map +1 -1
  247. package/dist/core/object/validate/field.js +235 -35
  248. package/dist/core/object/validate/field.js.map +1 -1
  249. package/dist/core/object/validate/formulas.d.ts.map +1 -1
  250. package/dist/core/object/validate/formulas.js +6 -0
  251. package/dist/core/object/validate/formulas.js.map +1 -1
  252. package/dist/core/object/validate/object.d.ts +2 -0
  253. package/dist/core/object/validate/object.d.ts.map +1 -1
  254. package/dist/core/object/validate/object.js +51 -19
  255. package/dist/core/object/validate/object.js.map +1 -1
  256. package/dist/core/object/validate/permissions.d.ts.map +1 -1
  257. package/dist/core/object/validate/permissions.js +4 -0
  258. package/dist/core/object/validate/permissions.js.map +1 -1
  259. package/dist/core/object/validate/primitives.d.ts +0 -1
  260. package/dist/core/object/validate/primitives.d.ts.map +1 -1
  261. package/dist/core/object/validate/primitives.js +1 -2
  262. package/dist/core/object/validate/primitives.js.map +1 -1
  263. package/dist/core/object/validate/workflow.d.ts +10 -0
  264. package/dist/core/object/validate/workflow.d.ts.map +1 -0
  265. package/dist/core/object/validate/workflow.js +143 -0
  266. package/dist/core/object/validate/workflow.js.map +1 -0
  267. package/dist/core/object/workflow-hash.d.ts +10 -0
  268. package/dist/core/object/workflow-hash.d.ts.map +1 -0
  269. package/dist/core/object/workflow-hash.js +27 -0
  270. package/dist/core/object/workflow-hash.js.map +1 -0
  271. package/dist/core/object/workflow-migrations.d.ts +27 -0
  272. package/dist/core/object/workflow-migrations.d.ts.map +1 -0
  273. package/dist/core/object/workflow-migrations.js +125 -0
  274. package/dist/core/object/workflow-migrations.js.map +1 -0
  275. package/dist/core/provider/event/index.d.ts +1 -1
  276. package/dist/core/provider/event/index.d.ts.map +1 -1
  277. package/dist/core/provider/event/index.js.map +1 -1
  278. package/dist/core/provider/event/types.d.ts +17 -2
  279. package/dist/core/provider/event/types.d.ts.map +1 -1
  280. package/dist/core/provider/event/types.js +2 -1
  281. package/dist/core/provider/event/types.js.map +1 -1
  282. package/dist/core/provider/identity/directory.d.ts +90 -0
  283. package/dist/core/provider/identity/directory.d.ts.map +1 -0
  284. package/dist/core/provider/identity/directory.js +3 -0
  285. package/dist/core/provider/identity/directory.js.map +1 -0
  286. package/dist/core/provider/identity/index.d.ts +5 -1
  287. package/dist/core/provider/identity/index.d.ts.map +1 -1
  288. package/dist/core/provider/identity/index.js +2 -1
  289. package/dist/core/provider/identity/index.js.map +1 -1
  290. package/dist/core/provider/identity/source.d.ts +22 -0
  291. package/dist/core/provider/identity/source.d.ts.map +1 -0
  292. package/dist/core/provider/identity/source.js +3 -0
  293. package/dist/core/provider/identity/source.js.map +1 -0
  294. package/dist/core/provider/identity/types.d.ts +62 -7
  295. package/dist/core/provider/identity/types.d.ts.map +1 -1
  296. package/dist/core/provider/identity/types.js +13 -0
  297. package/dist/core/provider/identity/types.js.map +1 -1
  298. package/dist/core/proxy/types.d.ts +4 -4
  299. package/dist/core/proxy/types.d.ts.map +1 -1
  300. package/dist/core/rbac/authorize.d.ts +10 -9
  301. package/dist/core/rbac/authorize.d.ts.map +1 -1
  302. package/dist/core/rbac/authorize.js +23 -18
  303. package/dist/core/rbac/authorize.js.map +1 -1
  304. package/dist/core/rbac/details.d.ts +33 -0
  305. package/dist/core/rbac/details.d.ts.map +1 -0
  306. package/dist/core/rbac/details.js +74 -0
  307. package/dist/core/rbac/details.js.map +1 -0
  308. package/dist/core/rbac/fields.d.ts +2 -1
  309. package/dist/core/rbac/fields.d.ts.map +1 -1
  310. package/dist/core/rbac/fields.js +3 -2
  311. package/dist/core/rbac/fields.js.map +1 -1
  312. package/dist/core/rbac/index.d.ts +3 -2
  313. package/dist/core/rbac/index.d.ts.map +1 -1
  314. package/dist/core/rbac/index.js +2 -1
  315. package/dist/core/rbac/index.js.map +1 -1
  316. package/dist/core/rbac/resolve.d.ts +3 -1
  317. package/dist/core/rbac/resolve.d.ts.map +1 -1
  318. package/dist/core/rbac/resolve.js +17 -9
  319. package/dist/core/rbac/resolve.js.map +1 -1
  320. package/dist/core/rbac/rls.d.ts +6 -0
  321. package/dist/core/rbac/rls.d.ts.map +1 -1
  322. package/dist/core/rbac/rls.js +52 -7
  323. package/dist/core/rbac/rls.js.map +1 -1
  324. package/dist/core/rbac/rowScope.d.ts +13 -6
  325. package/dist/core/rbac/rowScope.d.ts.map +1 -1
  326. package/dist/core/rbac/rowScope.js +88 -16
  327. package/dist/core/rbac/rowScope.js.map +1 -1
  328. package/dist/core/rbac/types.d.ts +6 -7
  329. package/dist/core/rbac/types.d.ts.map +1 -1
  330. package/dist/core/script/types.d.ts +1 -1
  331. package/dist/core/script/types.d.ts.map +1 -1
  332. package/dist/core/storage/diff.d.ts +4 -2
  333. package/dist/core/storage/diff.d.ts.map +1 -1
  334. package/dist/core/storage/diff.js +20 -17
  335. package/dist/core/storage/diff.js.map +1 -1
  336. package/dist/core/storage/index.d.ts +7 -1
  337. package/dist/core/storage/index.d.ts.map +1 -1
  338. package/dist/core/storage/index.js +6 -1
  339. package/dist/core/storage/index.js.map +1 -1
  340. package/dist/core/storage/inspect.d.ts +12 -3
  341. package/dist/core/storage/inspect.d.ts.map +1 -1
  342. package/dist/core/storage/inspect.js +39 -22
  343. package/dist/core/storage/inspect.js.map +1 -1
  344. package/dist/core/storage/introspect.d.ts +9 -2
  345. package/dist/core/storage/introspect.d.ts.map +1 -1
  346. package/dist/core/storage/introspect.js +100 -43
  347. package/dist/core/storage/introspect.js.map +1 -1
  348. package/dist/core/storage/link-table.d.ts +47 -0
  349. package/dist/core/storage/link-table.d.ts.map +1 -0
  350. package/dist/core/storage/link-table.js +110 -0
  351. package/dist/core/storage/link-table.js.map +1 -0
  352. package/dist/core/storage/map.d.ts.map +1 -1
  353. package/dist/core/storage/map.js +135 -81
  354. package/dist/core/storage/map.js.map +1 -1
  355. package/dist/core/storage/meta.d.ts +6 -3
  356. package/dist/core/storage/meta.d.ts.map +1 -1
  357. package/dist/core/storage/meta.js +9 -5
  358. package/dist/core/storage/meta.js.map +1 -1
  359. package/dist/core/storage/migrate.d.ts.map +1 -1
  360. package/dist/core/storage/migrate.js +144 -11
  361. package/dist/core/storage/migrate.js.map +1 -1
  362. package/dist/core/storage/record-key-sql.d.ts +19 -0
  363. package/dist/core/storage/record-key-sql.d.ts.map +1 -0
  364. package/dist/core/storage/record-key-sql.js +43 -0
  365. package/dist/core/storage/record-key-sql.js.map +1 -0
  366. package/dist/core/storage/record-meta.d.ts +68 -0
  367. package/dist/core/storage/record-meta.d.ts.map +1 -0
  368. package/dist/core/storage/record-meta.js +108 -0
  369. package/dist/core/storage/record-meta.js.map +1 -0
  370. package/dist/core/storage/report.d.ts.map +1 -1
  371. package/dist/core/storage/report.js +17 -7
  372. package/dist/core/storage/report.js.map +1 -1
  373. package/dist/core/storage/sql-literals.d.ts +9 -0
  374. package/dist/core/storage/sql-literals.d.ts.map +1 -0
  375. package/dist/core/storage/sql-literals.js +13 -0
  376. package/dist/core/storage/sql-literals.js.map +1 -0
  377. package/dist/core/storage/system-tables.d.ts +44 -0
  378. package/dist/core/storage/system-tables.d.ts.map +1 -0
  379. package/dist/core/storage/system-tables.js +268 -0
  380. package/dist/core/storage/system-tables.js.map +1 -0
  381. package/dist/core/tools/policies.d.ts +2 -2
  382. package/dist/core/tools/policies.js +2 -2
  383. package/dist/core/tools/types.d.ts +6 -6
  384. package/dist/core/tools/types.d.ts.map +1 -1
  385. package/dist/core/tools/values.d.ts +5 -0
  386. package/dist/core/tools/values.d.ts.map +1 -1
  387. package/dist/core/tools/values.js +9 -1
  388. package/dist/core/tools/values.js.map +1 -1
  389. package/dist/core/types/currency.d.ts +9 -0
  390. package/dist/core/types/currency.d.ts.map +1 -0
  391. package/dist/core/types/currency.js +28 -0
  392. package/dist/core/types/currency.js.map +1 -0
  393. package/dist/core/types/field-type.d.ts +4 -1
  394. package/dist/core/types/field-type.d.ts.map +1 -1
  395. package/dist/core/types/fields.d.ts +105 -19
  396. package/dist/core/types/fields.d.ts.map +1 -1
  397. package/dist/core/types/index.d.ts +8 -6
  398. package/dist/core/types/index.d.ts.map +1 -1
  399. package/dist/core/types/index.js +4 -3
  400. package/dist/core/types/index.js.map +1 -1
  401. package/dist/core/types/object.d.ts +18 -1
  402. package/dist/core/types/object.d.ts.map +1 -1
  403. package/dist/core/types/permission.d.ts +5 -0
  404. package/dist/core/types/permission.d.ts.map +1 -1
  405. package/dist/core/types/primaryField.d.ts +6 -1
  406. package/dist/core/types/primaryField.d.ts.map +1 -1
  407. package/dist/core/types/primaryField.js +8 -1
  408. package/dist/core/types/primaryField.js.map +1 -1
  409. package/dist/core/types/registry.d.ts +6 -4
  410. package/dist/core/types/registry.d.ts.map +1 -1
  411. package/dist/core/types/registry.js +40 -30
  412. package/dist/core/types/registry.js.map +1 -1
  413. package/dist/core/types/values.d.ts +97 -27
  414. package/dist/core/types/values.d.ts.map +1 -1
  415. package/dist/core/types/values.js +64 -29
  416. package/dist/core/types/values.js.map +1 -1
  417. package/dist/core/types/workflow.d.ts +140 -0
  418. package/dist/core/types/workflow.d.ts.map +1 -0
  419. package/dist/core/types/workflow.js +49 -0
  420. package/dist/core/types/workflow.js.map +1 -0
  421. package/dist/index.d.ts +2 -0
  422. package/dist/index.d.ts.map +1 -1
  423. package/dist/index.js +5 -3
  424. package/dist/index.js.map +1 -1
  425. package/dist/infrastructure/event/bus.d.ts.map +1 -1
  426. package/dist/infrastructure/event/bus.js +14 -0
  427. package/dist/infrastructure/event/bus.js.map +1 -1
  428. package/dist/infrastructure/identity.d.ts +2 -2
  429. package/dist/infrastructure/identity.d.ts.map +1 -1
  430. package/dist/infrastructure/identity.js.map +1 -1
  431. package/dist/layout-format.d.ts +6 -6
  432. package/dist/layout-format.js +4 -4
  433. package/dist/runtime/data-access/builder.d.ts +15 -5
  434. package/dist/runtime/data-access/builder.d.ts.map +1 -1
  435. package/dist/runtime/data-access/builder.js +222 -30
  436. package/dist/runtime/data-access/builder.js.map +1 -1
  437. package/dist/runtime/data-access/details.d.ts.map +1 -1
  438. package/dist/runtime/data-access/details.js +7 -2
  439. package/dist/runtime/data-access/details.js.map +1 -1
  440. package/dist/runtime/data-access/formula.d.ts +11 -3
  441. package/dist/runtime/data-access/formula.d.ts.map +1 -1
  442. package/dist/runtime/data-access/formula.js +82 -19
  443. package/dist/runtime/data-access/formula.js.map +1 -1
  444. package/dist/runtime/data-access/index.d.ts +1 -1
  445. package/dist/runtime/data-access/index.d.ts.map +1 -1
  446. package/dist/runtime/data-access/index.js +1 -1
  447. package/dist/runtime/data-access/index.js.map +1 -1
  448. package/dist/runtime/data-access/link.d.ts +7 -0
  449. package/dist/runtime/data-access/link.d.ts.map +1 -0
  450. package/dist/runtime/data-access/link.js +80 -0
  451. package/dist/runtime/data-access/link.js.map +1 -0
  452. package/dist/runtime/data-access/query.d.ts +48 -3
  453. package/dist/runtime/data-access/query.d.ts.map +1 -1
  454. package/dist/runtime/data-access/query.js +381 -45
  455. package/dist/runtime/data-access/query.js.map +1 -1
  456. package/dist/runtime/data-access/rbac.d.ts.map +1 -1
  457. package/dist/runtime/data-access/rbac.js +134 -16
  458. package/dist/runtime/data-access/rbac.js.map +1 -1
  459. package/dist/runtime/data-access/seqno.d.ts +0 -2
  460. package/dist/runtime/data-access/seqno.d.ts.map +1 -1
  461. package/dist/runtime/data-access/seqno.js +0 -9
  462. package/dist/runtime/data-access/seqno.js.map +1 -1
  463. package/dist/runtime/data-access/sql-executor.d.ts +13 -3
  464. package/dist/runtime/data-access/sql-executor.d.ts.map +1 -1
  465. package/dist/runtime/data-access/sql-executor.js +20 -14
  466. package/dist/runtime/data-access/sql-executor.js.map +1 -1
  467. package/dist/runtime/data-access/sql-gate.d.ts +4 -4
  468. package/dist/runtime/data-access/sql-gate.d.ts.map +1 -1
  469. package/dist/runtime/data-access/sql-gate.js +5 -5
  470. package/dist/runtime/data-access/sql-gate.js.map +1 -1
  471. package/dist/runtime/data-access/tx.d.ts +1 -1
  472. package/dist/runtime/data-access/tx.js +1 -1
  473. package/dist/runtime/data-access/types.d.ts +31 -3
  474. package/dist/runtime/data-access/types.d.ts.map +1 -1
  475. package/dist/runtime/data-access/validate.d.ts.map +1 -1
  476. package/dist/runtime/data-access/validate.js +79 -15
  477. package/dist/runtime/data-access/validate.js.map +1 -1
  478. package/dist/runtime/data-access/workflow.d.ts +146 -0
  479. package/dist/runtime/data-access/workflow.d.ts.map +1 -0
  480. package/dist/runtime/data-access/workflow.js +636 -0
  481. package/dist/runtime/data-access/workflow.js.map +1 -0
  482. package/dist/runtime/engine.d.ts +89 -14
  483. package/dist/runtime/engine.d.ts.map +1 -1
  484. package/dist/runtime/engine.js +123 -26
  485. package/dist/runtime/engine.js.map +1 -1
  486. package/dist/runtime/fieldtypes/loader.d.ts.map +1 -1
  487. package/dist/runtime/fieldtypes/loader.js +12 -1
  488. package/dist/runtime/fieldtypes/loader.js.map +1 -1
  489. package/dist/runtime/git/guardrailSource.d.ts +1 -1
  490. package/dist/runtime/git/index.d.ts +4 -2
  491. package/dist/runtime/git/index.d.ts.map +1 -1
  492. package/dist/runtime/git/index.js +2 -1
  493. package/dist/runtime/git/index.js.map +1 -1
  494. package/dist/runtime/git/layoutSource.d.ts +1 -1
  495. package/dist/runtime/git/loader.d.ts.map +1 -1
  496. package/dist/runtime/git/loader.js +18 -6
  497. package/dist/runtime/git/loader.js.map +1 -1
  498. package/dist/runtime/git/pageCatalog.d.ts +1 -1
  499. package/dist/runtime/git/schemaChange.d.ts +22 -0
  500. package/dist/runtime/git/schemaChange.d.ts.map +1 -1
  501. package/dist/runtime/git/schemaChange.js +28 -2
  502. package/dist/runtime/git/schemaChange.js.map +1 -1
  503. package/dist/runtime/git/schemaSource.d.ts +1 -1
  504. package/dist/runtime/git/sourceFile.d.ts +1 -1
  505. package/dist/runtime/git/sourceFile.js +1 -1
  506. package/dist/runtime/git/sourceTransaction.d.ts +1 -1
  507. package/dist/runtime/git/workflowSource.d.ts +40 -0
  508. package/dist/runtime/git/workflowSource.d.ts.map +1 -0
  509. package/dist/runtime/git/workflowSource.js +45 -0
  510. package/dist/runtime/git/workflowSource.js.map +1 -0
  511. package/dist/runtime/identity/admin.d.ts +18 -0
  512. package/dist/runtime/identity/admin.d.ts.map +1 -0
  513. package/dist/runtime/identity/admin.js +27 -0
  514. package/dist/runtime/identity/admin.js.map +1 -0
  515. package/dist/runtime/identity/directory.d.ts +12 -0
  516. package/dist/runtime/identity/directory.d.ts.map +1 -0
  517. package/dist/runtime/identity/directory.js +22 -0
  518. package/dist/runtime/identity/directory.js.map +1 -0
  519. package/dist/runtime/identity/index.d.ts +11 -0
  520. package/dist/runtime/identity/index.d.ts.map +1 -0
  521. package/dist/runtime/identity/index.js +8 -0
  522. package/dist/runtime/identity/index.js.map +1 -0
  523. package/dist/runtime/identity/resolve.d.ts +10 -0
  524. package/dist/runtime/identity/resolve.d.ts.map +1 -0
  525. package/dist/runtime/identity/resolve.js +16 -0
  526. package/dist/runtime/identity/resolve.js.map +1 -0
  527. package/dist/runtime/identity/sources/function.d.ts +10 -0
  528. package/dist/runtime/identity/sources/function.d.ts.map +1 -0
  529. package/dist/runtime/identity/sources/function.js +9 -0
  530. package/dist/runtime/identity/sources/function.js.map +1 -0
  531. package/dist/runtime/identity/sources/pg.d.ts +42 -0
  532. package/dist/runtime/identity/sources/pg.d.ts.map +1 -0
  533. package/dist/runtime/identity/sources/pg.js +121 -0
  534. package/dist/runtime/identity/sources/pg.js.map +1 -0
  535. package/dist/runtime/identity/store.d.ts +27 -0
  536. package/dist/runtime/identity/store.d.ts.map +1 -0
  537. package/dist/runtime/identity/store.js +139 -0
  538. package/dist/runtime/identity/store.js.map +1 -0
  539. package/dist/runtime/identity/sync.d.ts +34 -0
  540. package/dist/runtime/identity/sync.d.ts.map +1 -0
  541. package/dist/runtime/identity/sync.js +149 -0
  542. package/dist/runtime/identity/sync.js.map +1 -0
  543. package/dist/runtime/metadata/cache.d.ts +0 -2
  544. package/dist/runtime/metadata/cache.d.ts.map +1 -1
  545. package/dist/runtime/metadata/cache.js +0 -11
  546. package/dist/runtime/metadata/cache.js.map +1 -1
  547. package/dist/runtime/metadata/index.d.ts +1 -1
  548. package/dist/runtime/metadata/index.d.ts.map +1 -1
  549. package/dist/runtime/metadata/index.js +1 -1
  550. package/dist/runtime/metadata/index.js.map +1 -1
  551. package/dist/runtime/record-meta/index.d.ts +2 -0
  552. package/dist/runtime/record-meta/index.d.ts.map +1 -0
  553. package/dist/runtime/record-meta/index.js +2 -0
  554. package/dist/runtime/record-meta/index.js.map +1 -0
  555. package/dist/runtime/record-meta/store.d.ts +43 -0
  556. package/dist/runtime/record-meta/store.d.ts.map +1 -0
  557. package/dist/runtime/record-meta/store.js +88 -0
  558. package/dist/runtime/record-meta/store.js.map +1 -0
  559. package/dist/runtime/sql-analyzer/index.d.ts.map +1 -1
  560. package/dist/runtime/sql-analyzer/index.js +59 -0
  561. package/dist/runtime/sql-analyzer/index.js.map +1 -1
  562. package/dist/runtime/tools/executor.d.ts +11 -11
  563. package/dist/runtime/tools/executor.d.ts.map +1 -1
  564. package/dist/runtime/tools/executor.js +6 -6
  565. package/dist/runtime/tools/executor.js.map +1 -1
  566. package/dist/runtime/tools/index.d.ts +2 -0
  567. package/dist/runtime/tools/index.d.ts.map +1 -1
  568. package/dist/runtime/tools/index.js +1 -0
  569. package/dist/runtime/tools/index.js.map +1 -1
  570. package/dist/runtime/tools/policies.d.ts +22 -5
  571. package/dist/runtime/tools/policies.d.ts.map +1 -1
  572. package/dist/runtime/tools/policies.js +42 -12
  573. package/dist/runtime/tools/policies.js.map +1 -1
  574. package/dist/runtime/tunnel/connector.d.ts +1 -1
  575. package/dist/runtime/tunnel/forwarder.js +1 -1
  576. package/dist/runtime/tunnel/framing.d.ts +1 -1
  577. package/dist/runtime/tunnel/server.d.ts +1 -1
  578. package/dist/subsystems/approvals/index.d.ts +4 -4
  579. package/dist/subsystems/approvals/index.d.ts.map +1 -1
  580. package/dist/subsystems/approvals/index.js +5 -6
  581. package/dist/subsystems/approvals/index.js.map +1 -1
  582. package/dist/subsystems/approvals/store.d.ts +1 -3
  583. package/dist/subsystems/approvals/store.d.ts.map +1 -1
  584. package/dist/subsystems/approvals/store.js +1 -16
  585. package/dist/subsystems/approvals/store.js.map +1 -1
  586. package/dist/subsystems/audit/index.d.ts +1 -1
  587. package/dist/subsystems/audit/index.d.ts.map +1 -1
  588. package/dist/subsystems/audit/index.js +2 -3
  589. package/dist/subsystems/audit/index.js.map +1 -1
  590. package/dist/subsystems/audit/store.d.ts +0 -2
  591. package/dist/subsystems/audit/store.d.ts.map +1 -1
  592. package/dist/subsystems/audit/store.js +0 -21
  593. package/dist/subsystems/audit/store.js.map +1 -1
  594. package/dist/subsystems/quota/store.d.ts +9 -0
  595. package/dist/subsystems/quota/store.d.ts.map +1 -1
  596. package/dist/subsystems/quota/store.js +0 -8
  597. package/dist/subsystems/quota/store.js.map +1 -1
  598. package/dist/subsystems/script/backend/isolated-vm.js +1 -1
  599. package/dist/subsystems/script/backend/types.d.ts +2 -2
  600. package/dist/subsystems/script/backend/types.d.ts.map +1 -1
  601. package/dist/subsystems/script/bridge.d.ts +1 -1
  602. package/dist/subsystems/script/bridge.d.ts.map +1 -1
  603. package/dist/subsystems/script/bridge.js +6 -4
  604. package/dist/subsystems/script/bridge.js.map +1 -1
  605. package/dist/subsystems/script/dispatcher.d.ts.map +1 -1
  606. package/dist/subsystems/script/dispatcher.js +3 -1
  607. package/dist/subsystems/script/dispatcher.js.map +1 -1
  608. package/dist/subsystems/workflow/index.d.ts +4 -0
  609. package/dist/subsystems/workflow/index.d.ts.map +1 -0
  610. package/dist/subsystems/workflow/index.js +3 -0
  611. package/dist/subsystems/workflow/index.js.map +1 -0
  612. package/dist/subsystems/workflow/scheduler.d.ts +27 -0
  613. package/dist/subsystems/workflow/scheduler.d.ts.map +1 -0
  614. package/dist/subsystems/workflow/scheduler.js +109 -0
  615. package/dist/subsystems/workflow/scheduler.js.map +1 -0
  616. package/dist/subsystems/workflow/store.d.ts +10 -0
  617. package/dist/subsystems/workflow/store.d.ts.map +1 -0
  618. package/dist/subsystems/workflow/store.js +44 -0
  619. package/dist/subsystems/workflow/store.js.map +1 -0
  620. package/dist/version.d.ts +1 -1
  621. package/dist/version.js +1 -1
  622. package/package.json +7 -3
@@ -1,14 +1,22 @@
1
- import { SchemaError, primaryKeyOf } from '../../core/index.js';
2
- import { DETAILS_COLUMNS, FIELD_TYPES } from '../../core/index.js';
1
+ import { SchemaError, primaryFieldsOf, encodeRecordKey, decodeRecordKey, canonicalizePrimaryValue } from '../../core/index.js';
2
+ import { DETAILS_COLUMNS, FIELD_TYPES, isSideTableVirtualField, RECORD_META_ID_FIELD, recordKeySql, recordMetaTableName } from '../../core/index.js';
3
3
  import { AUDIT_ACTOR_TYPES, DATA_ACTIONS } from '../../core/audit/index.js';
4
4
  import { NOOP_SCRIPT_DISPATCHER, SCRIPT_HOOKS } from '../../core/index.js';
5
+ import { evaluateTransition } from '../tools/policies.js';
5
6
  import { buildCountSql, buildFindSql, scopeSuffix } from './builder.js';
6
7
  import { deleteDetailsChildren, insertDetails } from './details.js';
8
+ import { insertLinks, replaceLinks } from './link.js';
9
+ import { runWorkflowTransition, getWorkflowStatus, acquireWorkflowLock, releaseWorkflowLock, getWorkflowHistory, getWorkflowTodos, overrideWorkflow, } from './workflow.js';
7
10
  import { computeFormulas } from './formula.js';
8
- import { ensureSeqTable, generateSeqNo } from './seqno.js';
11
+ import { generateSeqNo } from './seqno.js';
9
12
  import { validateRecord } from './validate.js';
10
13
  import { WRITE_MODES } from './values.js';
14
+ import { upsertRecordMeta, deleteRecordMeta } from '../record-meta/index.js';
11
15
  const q = (id) => `"${id}"`;
16
+ /** cross-object formula authorization derived from the request context */
17
+ function formulaAuth(ctx) {
18
+ return { subject: ctx.subject, roles: ctx.subject?.roles ?? [], locale: ctx.locale };
19
+ }
12
20
  /** PG error 42703 = undefined_column: a query referenced a column that doesn't exist */
13
21
  function isUndefinedColumn(error) {
14
22
  return typeof error === 'object' && error !== null && error.code === '42703';
@@ -82,7 +90,7 @@ function scriptUserOf(ctx) {
82
90
  return {
83
91
  id: ctx.subject?.id ?? 'system',
84
92
  roles: ctx.subject?.roles ?? [],
85
- teamId: ctx.subject?.teamId,
93
+ departmentId: ctx.subject?.departmentId,
86
94
  };
87
95
  }
88
96
  const PARENT_COLUMNS = new Set([
@@ -102,7 +110,99 @@ function requireDef(ctx, objectName) {
102
110
  return def;
103
111
  }
104
112
  function bctx(ctx, objectName) {
105
- return { object: objectName, locale: ctx.locale, allowParentCols: isDetailsChild(ctx.registry, objectName) };
113
+ return {
114
+ object: objectName,
115
+ locale: ctx.locale,
116
+ allowParentCols: isDetailsChild(ctx.registry, objectName),
117
+ lookup: ctx.registry,
118
+ ...(ctx.subject === undefined ? {} : { subject: ctx.subject }),
119
+ };
120
+ }
121
+ /** hidden select column carrying the SQL-computed record_key for a fetched row */
122
+ const META_KEY_COL = '__weave_record_key';
123
+ /** select expression for the SQL-computed record_key (lossless for temporal keys) */
124
+ function recordKeySelect(def) {
125
+ return `${recordKeySql(def, (name) => q(name))} AS ${q(META_KEY_COL)}`;
126
+ }
127
+ /** the record_key of a row, from its declared primary fields (declaration order) */
128
+ function recordKeyOfRow(def, record) {
129
+ return encodeRecordKey(primaryFieldsOf(def).map((f) => canonicalizePrimaryValue(record[f.name])));
130
+ }
131
+ /** declared primary field names, in declaration order */
132
+ function primaryNames(def) {
133
+ return primaryFieldsOf(def).map((f) => f.name);
134
+ }
135
+ /** decode an external id (the record_key, for single and composite keys alike) into primary values */
136
+ function pkValuesOf(def, id, ctx) {
137
+ const names = primaryNames(def);
138
+ let values;
139
+ try {
140
+ values = decodeRecordKey(id);
141
+ }
142
+ catch {
143
+ throw new SchemaError('recordKey.invalid', { key: id }, ctx.locale);
144
+ }
145
+ if (values.length !== names.length) {
146
+ throw new SchemaError('recordKey.invalid', { key: id }, ctx.locale);
147
+ }
148
+ return values;
149
+ }
150
+ /** primary-key filter object for `find` (declared names zipped with values) */
151
+ function pkFilter(def, values) {
152
+ const filter = {};
153
+ primaryNames(def).forEach((name, i) => {
154
+ filter[name] = values[i];
155
+ });
156
+ return filter;
157
+ }
158
+ /** `"a" = $1 AND "b" = $2` predicate for the primary names, starting at `startIndex` */
159
+ function pkWhereSql(def, startIndex) {
160
+ return primaryNames(def)
161
+ .map((name, i) => `${q(name)} = $${startIndex + i}`)
162
+ .join(' AND ');
163
+ }
164
+ /** the external id of a record: always its record_key (single and composite keys alike) */
165
+ function externalIdOf(def, record) {
166
+ return recordKeyOfRow(def, record);
167
+ }
168
+ /** true when the query references a side-table virtual field (`weave_*` minus the derived `weave_id`) */
169
+ function needsSideTable(opts) {
170
+ if ((opts.fields ?? []).some((f) => isSideTableVirtualField(f)))
171
+ return true;
172
+ if ((opts.sort ?? []).some((s) => isSideTableVirtualField(s.field)))
173
+ return true;
174
+ const filter = opts.filter;
175
+ if (filter !== undefined) {
176
+ for (const [key, value] of Object.entries(filter)) {
177
+ if (key === '$or') {
178
+ if (Array.isArray(value) &&
179
+ value.some((group) => group !== null &&
180
+ typeof group === 'object' &&
181
+ Object.keys(group).some((k) => isSideTableVirtualField(k)))) {
182
+ return true;
183
+ }
184
+ }
185
+ else if (isSideTableVirtualField(key)) {
186
+ return true;
187
+ }
188
+ }
189
+ }
190
+ return false;
191
+ }
192
+ /**
193
+ * Narrow `ToolDataAccess` over this data-access for guardrail policies: a policy
194
+ * calls `ctx.dataAccess.find(obj, opts, { subject? })` with no pool/registry, so
195
+ * those are injected from the execution context (mirrors the tool executor's
196
+ * wrapper; `...c` lets a policy override the subject per call).
197
+ */
198
+ function toolDataAccessOver(inner, base) {
199
+ return {
200
+ find: (n, o, c) => inner.find(n, o, { ...base, ...c }),
201
+ findOne: (n, id, c) => inner.findOne(n, id, { ...base, ...c }),
202
+ create: (n, d, c) => inner.create(n, d, { ...base, ...c }),
203
+ update: (n, id, changes, c) => inner.update(n, id, changes, { ...base, ...c }),
204
+ delete: (n, id, c) => inner.delete(n, id, { ...base, ...c }),
205
+ };
106
206
  }
107
207
  /**
108
208
  * Serialize a value for binding to a DB column. pg (node-postgres) auto-stringifies
@@ -111,7 +211,10 @@ function bctx(ctx, objectName) {
111
211
  * (arrays/objects/numbers/booleans) to valid JSON text. `null` stays SQL NULL.
112
212
  */
113
213
  function dbJsonValue(field, value) {
114
- if (field !== undefined && field.type === FIELD_TYPES.JSON && value !== null && typeof value !== 'string') {
214
+ if (field !== undefined &&
215
+ (field.type === FIELD_TYPES.JSON || field.type === FIELD_TYPES.JSONB) &&
216
+ value !== null &&
217
+ typeof value !== 'string') {
115
218
  return JSON.stringify(value);
116
219
  }
117
220
  return value;
@@ -120,17 +223,26 @@ function dbJsonValue(field, value) {
120
223
  export class DefaultObjectDataAccess {
121
224
  audit;
122
225
  script;
123
- /** M10 diff replay: attach before/after row snapshots to update/delete audit events */
226
+ /** audit diff replay: attach before/after row snapshots to update/delete audit events */
124
227
  replay;
125
- /** M12 live events: publish committed writes to the bus (undefined = zero overhead) */
228
+ /** live events: publish committed writes to the bus (undefined = zero overhead) */
126
229
  events;
127
230
  /** objects currently dispatching onLoad — skips re-entrant onLoad (a hook re-reading the same object) */
128
231
  onLoadInFlight = new Set();
232
+ /** guardrail policies shared with the open-contract (empty = no policy gate on transitions) */
233
+ policies;
234
+ /** approval queue used when a policy or a transition requires approval */
235
+ approvals;
236
+ /** workflow timer handle: re-arm/cancel a record's `onTimeout` on state changes */
237
+ workflowTimers;
129
238
  constructor(options = {}) {
130
239
  this.audit = options.audit;
131
240
  this.script = options.script ?? NOOP_SCRIPT_DISPATCHER;
132
241
  this.replay = options.replay ?? false;
133
242
  this.events = options.events;
243
+ this.policies = options.policies ?? [];
244
+ this.approvals = options.approvals;
245
+ this.workflowTimers = options.workflowTimers;
134
246
  }
135
247
  /**
136
248
  * Run the read hook (`onLoad`) over a fetched batch. The hook receives the
@@ -168,13 +280,14 @@ export class DefaultObjectDataAccess {
168
280
  * hook failure → the surrounding transaction rolls back. Returns the
169
281
  * possibly-modified changes from beforeUpdate (undefined = keep original).
170
282
  */
171
- async runBeforeHook(hook, objectName, record, changes, ctx) {
283
+ async runBeforeHook(hook, objectName, record, changes, ctx, extra) {
172
284
  if (!this.script.has(objectName, hook))
173
285
  return undefined;
174
286
  const result = await this.script.dispatch(objectName, hook, {
175
287
  record,
176
288
  changes,
177
289
  user: scriptUserOf(ctx),
290
+ ...(extra ?? {}),
178
291
  });
179
292
  return result.changes;
180
293
  }
@@ -183,7 +296,7 @@ export class DefaultObjectDataAccess {
183
296
  * committed, so a hook failure is a non-fatal warning: recorded to audit and
184
297
  * delivered via `ctx.onWarnings`, never rethrown.
185
298
  */
186
- async runAfterHook(hook, action, objectName, record, changes, ctx, warnings, objectId) {
299
+ async runAfterHook(hook, action, objectName, record, changes, ctx, warnings, objectId, extra) {
187
300
  if (!this.script.has(objectName, hook))
188
301
  return;
189
302
  try {
@@ -191,6 +304,7 @@ export class DefaultObjectDataAccess {
191
304
  record,
192
305
  changes,
193
306
  user: scriptUserOf(ctx),
307
+ ...(extra ?? {}),
194
308
  });
195
309
  }
196
310
  catch (error) {
@@ -207,26 +321,33 @@ export class DefaultObjectDataAccess {
207
321
  async find(objectName, opts, ctx) {
208
322
  const def = requireDef(ctx, objectName);
209
323
  const q = ctx.client ?? ctx.pool;
210
- const { sql, params } = buildFindSql(def, opts, bctx(ctx, objectName), ctx.rowScope, opts.exclude);
324
+ // `weave_*` virtual fields live in the engine side table; when referenced,
325
+ // LEFT JOIN it and select/filter/sort them in SQL (never customer columns)
326
+ const meta = needsSideTable(opts) ? { table: recordMetaTableName(def.name) } : undefined;
327
+ const buildCtx = { ...bctx(ctx, objectName), ...(meta === undefined ? {} : { meta }) };
328
+ const { sql, params } = buildFindSql(def, opts, buildCtx, ctx.rowScope, opts.exclude);
211
329
  const { rows } = await runTableQuery(q, objectName, sql, params, ctx.locale);
212
- const { sql: countSql, params: countParams } = buildCountSql(def, opts, bctx(ctx, objectName), ctx.rowScope);
330
+ const { sql: countSql, params: countParams } = buildCountSql(def, opts, buildCtx, ctx.rowScope);
213
331
  const { rows: countRows } = await runTableQuery(q, objectName, countSql, countParams, ctx.locale);
214
332
  const loaded = await this.runOnLoad(objectName, rows, ctx);
215
333
  return { rows: loaded, total: countRows[0].total };
216
334
  }
217
335
  async findOne(objectName, id, ctx) {
218
336
  const def = requireDef(ctx, objectName);
219
- const pk = primaryKeyOf(def);
220
- if (pk === undefined) {
337
+ if (primaryNames(def).length === 0) {
221
338
  throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
222
339
  }
223
- const result = await this.find(objectName, { filter: { [pk]: id }, limit: 1 }, ctx);
340
+ // project every declared column plus the derived `weave_id` (the record's
341
+ // external id) so a fetched record is self-identifying
342
+ const cols = def.fields.filter((f) => f.type !== FIELD_TYPES.DETAILS).map((f) => f.name);
343
+ if (isDetailsChild(ctx.registry, objectName))
344
+ cols.push(...PARENT_COLUMNS);
345
+ const result = await this.find(objectName, { filter: pkFilter(def, pkValuesOf(def, id, ctx)), limit: 1, fields: [...cols, RECORD_META_ID_FIELD] }, ctx);
224
346
  return result.rows[0] ?? null;
225
347
  }
226
348
  async create(objectName, data, ctx) {
227
349
  const def = requireDef(ctx, objectName);
228
- const pk = primaryKeyOf(def);
229
- if (pk === undefined) {
350
+ if (primaryNames(def).length === 0) {
230
351
  throw new SchemaError('data.recordNotFound', { object: objectName }, ctx.locale);
231
352
  }
232
353
  let client;
@@ -261,14 +382,16 @@ export class DefaultObjectDataAccess {
261
382
  if (payload[field.name] !== undefined)
262
383
  continue;
263
384
  record[field.name] =
264
- (field.type === FIELD_TYPES.DATETIME || field.type === FIELD_TYPES.DATE) && raw.default === 'now'
385
+ (field.type === FIELD_TYPES.DATE ||
386
+ field.type === FIELD_TYPES.TIMESTAMP ||
387
+ field.type === FIELD_TYPES.TIMESTAMPTZ) &&
388
+ raw.default === 'now'
265
389
  ? now.toISOString()
266
390
  : raw.default;
267
391
  }
268
392
  Object.assign(record, payload);
269
393
  const seqFields = def.fields.filter((f) => f.type === FIELD_TYPES.SEQ_NO);
270
394
  if (seqFields.length > 0) {
271
- await ensureSeqTable(client);
272
395
  for (const f of seqFields)
273
396
  record[f.name] = await generateSeqNo(client, def.name, f, now);
274
397
  }
@@ -279,29 +402,37 @@ export class DefaultObjectDataAccess {
279
402
  record[DETAILS_COLUMNS.PARENT_IDX] = res.rows[0].n;
280
403
  }
281
404
  const cols = [
282
- ...def.fields.filter((f) => f.type !== FIELD_TYPES.DETAILS).map((f) => f.name),
405
+ ...def.fields
406
+ .filter((f) => f.type !== FIELD_TYPES.DETAILS && f.type !== FIELD_TYPES.MULTI_RELATION)
407
+ .map((f) => f.name),
283
408
  ...(child ? [...PARENT_COLUMNS] : []),
284
409
  ];
285
410
  const fieldByName = new Map(def.fields.map((f) => [f.name, f]));
286
411
  const values = cols.map((c) => dbJsonValue(fieldByName.get(c), record[c] ?? null));
287
412
  const placeholders = cols.map((_, i) => `$${i + 1}`).join(', ');
288
- await runTableQuery(client, def.name, `INSERT INTO ${q(def.name)} (${cols.map(q).join(', ')}) VALUES (${placeholders})`, values, ctx.locale);
289
- await insertDetails(client, def, record[pk], payload, ctx.registry, ctx.locale);
413
+ const insertRes = await runTableQuery(client, def.name, `INSERT INTO ${q(def.name)} (${cols.map(q).join(', ')}) VALUES (${placeholders}) RETURNING ${recordKeySql(def, q)} AS ${q(META_KEY_COL)}`, values, ctx.locale);
414
+ const metaKey = String(insertRes.rows[0]?.[META_KEY_COL] ?? '');
415
+ const externalId = metaKey;
416
+ record[RECORD_META_ID_FIELD] = externalId;
417
+ await insertDetails(client, def, externalId, payload, ctx.registry, ctx.locale);
418
+ await insertLinks(client, def, primaryFieldsOf(def).map((f) => record[f.name]), payload, ctx.registry, ctx.locale);
290
419
  // compute formula fields AFTER children exist (aggregates see them), then persist
291
- await computeFormulas(def, record, client, ctx.registry, now);
420
+ await computeFormulas(def, record, client, ctx.registry, now, externalId, formulaAuth(ctx));
292
421
  const formulaCols = def.fields
293
422
  .filter((f) => f.formula !== undefined)
294
423
  .map((f) => f.name);
295
424
  if (formulaCols.length > 0) {
296
425
  const setSql = formulaCols.map((c, i) => `${q(c)} = $${i + 1}`).join(', ');
297
426
  const formulaValues = formulaCols.map((c) => record[c] ?? null);
298
- await runTableQuery(client, def.name, `UPDATE ${q(def.name)} SET ${setSql} WHERE ${q(pk)} = $${formulaCols.length + 1}`, [...formulaValues, record[pk]], ctx.locale);
427
+ const pkValues = pkValuesOf(def, externalId, ctx);
428
+ await runTableQuery(client, def.name, `UPDATE ${q(def.name)} SET ${setSql} WHERE ${pkWhereSql(def, formulaCols.length + 1)}`, [...formulaValues, ...pkValues], ctx.locale);
299
429
  }
430
+ await this.writeRecordMeta(client, def, metaKey, ctx, now, true);
300
431
  if (owned)
301
432
  await client.query('COMMIT');
302
- auditWrite(this.audit, ctx, DATA_ACTIONS.CREATE, objectName, String(record[pk] ?? ''), record);
303
- this.events?.publishRecordChange('created', objectName, String(record[pk] ?? ''));
304
- await this.runAfterHook(SCRIPT_HOOKS.AFTER_UPDATE, DATA_ACTIONS.CREATE, objectName, record, payload, ctx, warnings, String(record[pk] ?? ''));
433
+ auditWrite(this.audit, ctx, DATA_ACTIONS.CREATE, objectName, externalId, record);
434
+ this.events?.publishRecordChange('created', objectName, externalId);
435
+ await this.runAfterHook(SCRIPT_HOOKS.AFTER_UPDATE, DATA_ACTIONS.CREATE, objectName, record, payload, ctx, warnings, externalId);
305
436
  if (warnings.length > 0)
306
437
  ctx.onWarnings?.(warnings);
307
438
  const loaded = await this.runOnLoad(objectName, [record], ctx);
@@ -310,7 +441,10 @@ export class DefaultObjectDataAccess {
310
441
  catch (err) {
311
442
  if (owned)
312
443
  await client.query('ROLLBACK');
313
- auditWrite(this.audit, ctx, DATA_ACTIONS.CREATE, objectName, data[pk] === undefined ? undefined : String(data[pk]), data, err);
444
+ const failedId = primaryNames(def).every((n) => data[n] !== undefined)
445
+ ? externalIdOf(def, data)
446
+ : undefined;
447
+ auditWrite(this.audit, ctx, DATA_ACTIONS.CREATE, objectName, failedId, data, err);
314
448
  throw err;
315
449
  }
316
450
  finally {
@@ -320,10 +454,10 @@ export class DefaultObjectDataAccess {
320
454
  }
321
455
  async update(objectName, id, changes, ctx) {
322
456
  const def = requireDef(ctx, objectName);
323
- const pk = primaryKeyOf(def);
324
- if (pk === undefined) {
457
+ if (primaryNames(def).length === 0) {
325
458
  throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
326
459
  }
460
+ const pkValues = pkValuesOf(def, id, ctx);
327
461
  let client;
328
462
  let owned = false;
329
463
  if (ctx.client !== undefined) {
@@ -338,21 +472,31 @@ export class DefaultObjectDataAccess {
338
472
  if (owned)
339
473
  await client.query('BEGIN');
340
474
  await validateRecord(def, changes, WRITE_MODES.UPDATE, { pool: client, registry: ctx.registry, locale: ctx.locale });
341
- const { sql, params } = buildFindSql(def, { filter: { [pk]: id }, limit: 1 }, bctx(ctx, objectName), ctx.rowScope);
475
+ const { sql, params } = buildFindSql(def, { filter: pkFilter(def, pkValues), limit: 1 }, bctx(ctx, objectName), ctx.rowScope, undefined, [recordKeySelect(def)]);
342
476
  const { rows } = await runTableQuery(client, objectName, sql, params, ctx.locale);
343
- const existing = rows[0];
344
- if (existing === undefined) {
477
+ const raw = rows[0];
478
+ if (raw === undefined) {
345
479
  throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
346
480
  }
481
+ const metaKey = String(raw[META_KEY_COL] ?? '');
482
+ const existing = { ...raw };
483
+ delete existing[META_KEY_COL];
347
484
  // validate → beforeUpdate; hooks see the pre-update record and may rewrite changes
348
485
  await this.runBeforeHook(SCRIPT_HOOKS.VALIDATE, objectName, existing, changes, ctx);
349
486
  let payload = changes;
350
487
  const before = await this.runBeforeHook(SCRIPT_HOOKS.BEFORE_UPDATE, objectName, existing, changes, ctx);
351
488
  if (before !== undefined)
352
489
  payload = before;
490
+ // primary keys are immutable: reject any attempt to change them (drift-free record_key)
491
+ for (const name of primaryNames(def)) {
492
+ if (payload[name] !== undefined) {
493
+ throw new SchemaError('object.primary.mutable', { object: objectName, field: name }, ctx.locale);
494
+ }
495
+ }
353
496
  const now = new Date();
354
497
  const record = { ...existing, ...payload };
355
- await computeFormulas(def, record, client, ctx.registry, now);
498
+ record[RECORD_META_ID_FIELD] = metaKey;
499
+ await computeFormulas(def, record, client, ctx.registry, now, metaKey, formulaAuth(ctx));
356
500
  const settable = new Set();
357
501
  for (const key of Object.keys(payload)) {
358
502
  if (isDetailsChild(ctx.registry, def.name) && PARENT_COLUMNS.has(key)) {
@@ -360,21 +504,25 @@ export class DefaultObjectDataAccess {
360
504
  continue;
361
505
  }
362
506
  const field = def.fields.find((f) => f.name === key);
363
- if (field !== undefined && field.type !== FIELD_TYPES.DETAILS)
507
+ if (field !== undefined && field.type !== FIELD_TYPES.DETAILS && field.type !== FIELD_TYPES.MULTI_RELATION) {
364
508
  settable.add(key);
509
+ }
365
510
  }
366
511
  for (const field of def.fields) {
367
512
  if (field.formula !== undefined)
368
513
  settable.add(field.name);
369
514
  }
370
- settable.delete(pk);
515
+ for (const name of primaryNames(def))
516
+ settable.delete(name);
371
517
  if (settable.size > 0) {
372
518
  const cols = [...settable];
373
519
  const setSql = cols.map((c, i) => `${q(c)} = $${i + 1}`).join(', ');
374
- const scope = ctx.rowScope !== undefined ? scopeSuffix(ctx.rowScope, cols.length + 1) : undefined;
520
+ const scope = ctx.rowScope !== undefined ? scopeSuffix(ctx.rowScope, cols.length + pkValues.length) : undefined;
375
521
  const values = cols.map((c) => dbJsonValue(def.fields.find((f) => f.name === c), record[c] ?? null));
376
- await runTableQuery(client, objectName, `UPDATE ${q(def.name)} SET ${setSql} WHERE ${q(pk)} = $${cols.length + 1}${scope !== undefined ? ` AND (${scope.sql})` : ''}`, [...values, id, ...(scope?.params ?? [])], ctx.locale);
522
+ await runTableQuery(client, objectName, `UPDATE ${q(def.name)} SET ${setSql} WHERE ${pkWhereSql(def, cols.length + 1)}${scope !== undefined ? ` AND (${scope.sql})` : ''}`, [...values, ...pkValues, ...(scope?.params ?? [])], ctx.locale);
377
523
  }
524
+ await this.writeRecordMeta(client, def, metaKey, ctx, now, false);
525
+ await replaceLinks(client, def, pkValues, payload, ctx.registry, ctx.locale);
378
526
  if (owned)
379
527
  await client.query('COMMIT');
380
528
  auditWrite(this.audit, ctx, DATA_ACTIONS.UPDATE, objectName, id, payload, undefined, this.replay ? existing : undefined, this.replay ? record : undefined);
@@ -396,12 +544,195 @@ export class DefaultObjectDataAccess {
396
544
  client.release();
397
545
  }
398
546
  }
547
+ /**
548
+ * Fire a workflow action against the three-layer runtime (instance/step/
549
+ * workitem). Runs in one transaction: the instance row is locked, the current
550
+ * step's workitems are quorum-evaluated, the new step/workitems are opened and
551
+ * the side-table status mirror is updated. The customer row is never touched.
552
+ */
553
+ async transition(objectName, id, action, ctx, payload) {
554
+ const def = requireDef(ctx, objectName);
555
+ if (def.workflow === undefined) {
556
+ throw new SchemaError('workflow.transition.unknown', { object: objectName, action }, ctx.locale);
557
+ }
558
+ if (primaryNames(def).length === 0) {
559
+ throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
560
+ }
561
+ const pkValues = pkValuesOf(def, id, ctx);
562
+ let client;
563
+ let owned = false;
564
+ if (ctx.client !== undefined) {
565
+ client = ctx.client;
566
+ }
567
+ else {
568
+ owned = true;
569
+ client = await ctx.pool.connect();
570
+ }
571
+ try {
572
+ if (owned)
573
+ await client.query('BEGIN');
574
+ // the customer record must exist (transitions never create records)
575
+ const { sql, params } = buildFindSql(def, { filter: pkFilter(def, pkValues), limit: 1 }, bctx(ctx, objectName), undefined, undefined, [recordKeySelect(def)]);
576
+ const found = await runTableQuery(client, objectName, sql, params, ctx.locale);
577
+ if (found.rows[0] === undefined) {
578
+ throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
579
+ }
580
+ // guardrail policy + approval gate (shared policy set with the open contract):
581
+ // a policy self-filters on `workflow.transition.<object>.<action>`; a node may
582
+ // also declare `requiresApproval`. deny → error; requireApproval → pending.
583
+ const currentNode = await getWorkflowStatus(client, def, id, ctx.subject);
584
+ const nodeDef = currentNode.node === undefined ? undefined : def.workflow.nodes.find((n) => n.id === currentNode.node);
585
+ const requireApproval = nodeDef?.requiresApproval === true;
586
+ if (this.policies.length > 0 || requireApproval) {
587
+ const actorId = ctx.subject?.id ?? 'system';
588
+ const guardrailCtx = {
589
+ actor: { key: actorId, label: actorId, onBehalfOf: actorId },
590
+ subject: ctx.subject ?? { id: 'system', roles: [] },
591
+ action: `workflow.transition.${def.name}.${action}`,
592
+ args: { object: def.name, id, action },
593
+ dataAccess: toolDataAccessOver(this, {
594
+ pool: ctx.pool,
595
+ registry: ctx.registry,
596
+ ...(ctx.locale === undefined ? {} : { locale: ctx.locale }),
597
+ ...(ctx.client === undefined ? {} : { client: ctx.client }),
598
+ ...(ctx.subject === undefined ? {} : { subject: ctx.subject }),
599
+ }),
600
+ };
601
+ const gate = await evaluateTransition(this.policies, this.approvals, guardrailCtx, requireApproval);
602
+ if (gate.kind === 'deny') {
603
+ throw new SchemaError(gate.code, { object: objectName, action, reason: gate.reason ?? '' }, ctx.locale);
604
+ }
605
+ if (gate.kind === 'pending') {
606
+ throw new SchemaError('workflow.transition.pending', { object: objectName, action, approvalKey: gate.approvalKey }, ctx.locale);
607
+ }
608
+ }
609
+ const outcome = await runWorkflowTransition(client, def, id, action, ctx.subject, payload, ctx.locale);
610
+ if (owned)
611
+ await client.query('COMMIT');
612
+ auditWrite(this.audit, ctx, DATA_ACTIONS.TRANSITION, objectName, id, {
613
+ action,
614
+ node: outcome.toNodeId ?? null,
615
+ from: outcome.fromNodeId ?? null,
616
+ ...(def.workflowHash === undefined ? {} : { workflowHash: def.workflowHash }),
617
+ });
618
+ this.events?.publishRecordChange('updated', objectName, id);
619
+ this.events?.publishRecordTransitioned(objectName, id, outcome.fromNodeId ?? '', outcome.toNodeId ?? '', action, def.workflow.version, def.workflowHash);
620
+ if (outcome.nodeId !== undefined) {
621
+ await this.workflowTimers?.sync(objectName, id, outcome.nodeId).catch(() => { });
622
+ }
623
+ else {
624
+ await this.workflowTimers?.cancel(objectName, id).catch(() => { });
625
+ }
626
+ const updated = await this.findOne(objectName, id, ctx);
627
+ const transitionInfo = { from: outcome.fromNodeId ?? '', to: outcome.toNodeId ?? '' };
628
+ const warnings = [];
629
+ if (updated !== null) {
630
+ await this.runAfterHook(SCRIPT_HOOKS.ON_EXIT, DATA_ACTIONS.TRANSITION, objectName, updated, {}, ctx, warnings, id, { transition: transitionInfo, state: outcome.fromNodeId });
631
+ await this.runAfterHook(SCRIPT_HOOKS.ON_ENTER, DATA_ACTIONS.TRANSITION, objectName, updated, {}, ctx, warnings, id, { transition: transitionInfo, state: outcome.toNodeId });
632
+ await this.runAfterHook(SCRIPT_HOOKS.AFTER_TRANSITION, DATA_ACTIONS.TRANSITION, objectName, updated, {}, ctx, warnings, id, { transition: transitionInfo, state: outcome.toNodeId });
633
+ }
634
+ if (warnings.length > 0)
635
+ ctx.onWarnings?.(warnings);
636
+ return updated;
637
+ }
638
+ catch (err) {
639
+ if (owned)
640
+ await client.query('ROLLBACK');
641
+ auditWrite(this.audit, ctx, DATA_ACTIONS.TRANSITION, objectName, id, { action }, err);
642
+ throw err;
643
+ }
644
+ finally {
645
+ if (owned)
646
+ client.release();
647
+ }
648
+ }
649
+ /**
650
+ * Read a record's workflow status (state/node/actions/own workitems).
651
+ */
652
+ async workflowStatus(objectName, id, ctx) {
653
+ const def = requireDef(ctx, objectName);
654
+ if (def.workflow === undefined) {
655
+ throw new SchemaError('workflow.transition.unknown', { object: objectName, action: 'status' }, ctx.locale);
656
+ }
657
+ return getWorkflowStatus(ctx.client ?? ctx.pool, def, id, ctx.subject);
658
+ }
659
+ /** Acquire/renew the caller's presence lock on the current step (TTL lease). */
660
+ async acquireWorkflowLock(objectName, id, ctx) {
661
+ const def = requireDef(ctx, objectName);
662
+ return acquireWorkflowLock(ctx.pool, def, id, ctx.subject, ctx.locale);
663
+ }
664
+ /** Release the caller's presence lock. */
665
+ async releaseWorkflowLock(objectName, id, ctx) {
666
+ const def = requireDef(ctx, objectName);
667
+ await releaseWorkflowLock(ctx.pool, def, id, ctx.subject);
668
+ }
669
+ /** Read a record's workflow history (steps + workitems). */
670
+ async workflowHistory(objectName, id, ctx) {
671
+ const def = requireDef(ctx, objectName);
672
+ if (def.workflow === undefined) {
673
+ throw new SchemaError('workflow.transition.unknown', { object: objectName, action: 'history' }, ctx.locale);
674
+ }
675
+ return getWorkflowHistory(ctx.client ?? ctx.pool, def, id);
676
+ }
677
+ /** The subject's pending workitems across all objects. */
678
+ async workflowTodos(ctx) {
679
+ return getWorkflowTodos(ctx.pool, ctx.subject);
680
+ }
681
+ /** Admin override: jump the record to a node or terminate the instance. */
682
+ async overrideWorkflow(objectName, id, patch, ctx) {
683
+ const def = requireDef(ctx, objectName);
684
+ if (def.workflow === undefined) {
685
+ throw new SchemaError('workflow.transition.unknown', { object: objectName, action: 'override' }, ctx.locale);
686
+ }
687
+ let client;
688
+ let owned = false;
689
+ if (ctx.client !== undefined) {
690
+ client = ctx.client;
691
+ }
692
+ else {
693
+ owned = true;
694
+ client = await ctx.pool.connect();
695
+ }
696
+ try {
697
+ if (owned)
698
+ await client.query('BEGIN');
699
+ const result = await overrideWorkflow(client, def, id, patch, ctx.subject, ctx.locale);
700
+ if (owned)
701
+ await client.query('COMMIT');
702
+ if (result.nodeId !== undefined) {
703
+ await this.workflowTimers?.sync(objectName, id, result.nodeId).catch(() => { });
704
+ }
705
+ else {
706
+ await this.workflowTimers?.cancel(objectName, id).catch(() => { });
707
+ }
708
+ return result;
709
+ }
710
+ catch (err) {
711
+ if (owned)
712
+ await client.query('ROLLBACK');
713
+ throw err;
714
+ }
715
+ finally {
716
+ if (owned)
717
+ client.release();
718
+ }
719
+ }
720
+ /**
721
+ * Upsert a record's sparse metadata side-table row (status/owner/timestamps)
722
+ * inside the caller's transaction. `created` also stamps the creation facts.
723
+ */
724
+ async writeRecordMeta(client, def, key, ctx, now, created) {
725
+ const actor = ctx.subject?.id ?? 'system';
726
+ await upsertRecordMeta(client, def.name, key, created
727
+ ? { createdBy: actor, modifiedBy: actor, createdTime: now, modifiedTime: now }
728
+ : { modifiedBy: actor, modifiedTime: now });
729
+ }
399
730
  async delete(objectName, id, ctx) {
400
731
  const def = requireDef(ctx, objectName);
401
- const pk = primaryKeyOf(def);
402
- if (pk === undefined) {
732
+ if (primaryNames(def).length === 0) {
403
733
  throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
404
734
  }
735
+ const pkValues = pkValuesOf(def, id, ctx);
405
736
  let client;
406
737
  let owned = false;
407
738
  if (ctx.client !== undefined) {
@@ -415,22 +746,27 @@ export class DefaultObjectDataAccess {
415
746
  try {
416
747
  if (owned)
417
748
  await client.query('BEGIN');
418
- const { sql, params } = buildFindSql(def, { filter: { [pk]: id }, limit: 1 }, bctx(ctx, objectName), ctx.rowScope);
749
+ const { sql, params } = buildFindSql(def, { filter: pkFilter(def, pkValues), limit: 1 }, bctx(ctx, objectName), ctx.rowScope, undefined, [recordKeySelect(def)]);
419
750
  const { rows } = await runTableQuery(client, objectName, sql, params, ctx.locale);
420
- const existing = rows[0];
421
- if (existing === undefined) {
751
+ const raw = rows[0];
752
+ if (raw === undefined) {
422
753
  throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
423
754
  }
755
+ const metaKey = String(raw[META_KEY_COL] ?? '');
756
+ const existing = { ...raw };
757
+ delete existing[META_KEY_COL];
424
758
  await this.runBeforeHook(SCRIPT_HOOKS.BEFORE_DELETE, objectName, existing, {}, ctx);
425
759
  await deleteDetailsChildren(client, def, id, ctx.registry);
426
- const scope = ctx.rowScope !== undefined ? scopeSuffix(ctx.rowScope, 1) : undefined;
427
- const res = await runTableQuery(client, objectName, `DELETE FROM ${q(def.name)} WHERE ${q(pk)} = $1${scope !== undefined ? ` AND (${scope.sql})` : ''}`, [id, ...(scope?.params ?? [])], ctx.locale);
760
+ const scope = ctx.rowScope !== undefined ? scopeSuffix(ctx.rowScope, pkValues.length) : undefined;
761
+ const res = await runTableQuery(client, objectName, `DELETE FROM ${q(def.name)} WHERE ${pkWhereSql(def, 1)}${scope !== undefined ? ` AND (${scope.sql})` : ''}`, [...pkValues, ...(scope?.params ?? [])], ctx.locale);
428
762
  if (res.rowCount === 0)
429
763
  throw new SchemaError('data.recordNotFound', { object: objectName, id }, ctx.locale);
764
+ await deleteRecordMeta(client, def.name, metaKey);
430
765
  if (owned)
431
766
  await client.query('COMMIT');
432
767
  auditWrite(this.audit, ctx, DATA_ACTIONS.DELETE, objectName, id, undefined, undefined, this.replay ? existing : undefined);
433
768
  this.events?.publishRecordChange('deleted', objectName, id);
769
+ await this.workflowTimers?.cancel(objectName, id).catch(() => { });
434
770
  await this.runAfterHook(SCRIPT_HOOKS.AFTER_DELETE, DATA_ACTIONS.DELETE, objectName, existing, {}, ctx, warnings, id);
435
771
  if (warnings.length > 0)
436
772
  ctx.onWarnings?.(warnings);