@north-light/cli 0.3.530 → 0.3.532

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 (495) hide show
  1. package/dist/clients/attach/session/connection.js +1 -1
  2. package/dist/clients/attach/session/reconnect.js +1 -1
  3. package/dist/clients/attach/viewer.js +508 -508
  4. package/dist/core/async-array.d.ts +7 -0
  5. package/dist/core/async-array.js +1 -0
  6. package/dist/core/audit.d.ts +1 -1
  7. package/dist/core/audit.js +2 -2
  8. package/dist/core/canvas/attention.d.ts +4 -4
  9. package/dist/core/canvas/attention.js +1 -1
  10. package/dist/core/canvas/boot.d.ts +4 -4
  11. package/dist/core/canvas/boot.js +1 -1
  12. package/dist/core/canvas/canvas.d.ts +59 -59
  13. package/dist/core/canvas/canvas.js +19 -19
  14. package/dist/core/canvas/context-strip.js +2 -2
  15. package/dist/core/canvas/crons.d.ts +27 -27
  16. package/dist/core/canvas/crons.js +11 -11
  17. package/dist/core/canvas/daemon-actions.d.ts +10 -10
  18. package/dist/core/canvas/daemon-actions.js +8 -8
  19. package/dist/core/canvas/daemon-owner.d.ts +3 -3
  20. package/dist/core/canvas/daemon-owner.js +2 -2
  21. package/dist/core/canvas/db.d.ts +19 -30
  22. package/dist/core/canvas/db.js +3 -2
  23. package/dist/core/canvas/deliveries.d.ts +16 -16
  24. package/dist/core/canvas/deliveries.js +24 -24
  25. package/dist/core/canvas/executions.d.ts +8 -8
  26. package/dist/core/canvas/executions.js +1 -1
  27. package/dist/core/canvas/focuses.d.ts +8 -8
  28. package/dist/core/canvas/focuses.js +1 -1
  29. package/dist/core/canvas/history.d.ts +3 -3
  30. package/dist/core/canvas/history.js +9 -9
  31. package/dist/core/canvas/install-id.d.ts +1 -1
  32. package/dist/core/canvas/install-id.js +1 -1
  33. package/dist/core/canvas/managed-worktree-sweep-candidates.d.ts +1 -1
  34. package/dist/core/canvas/managed-worktree-sweep-candidates.js +2 -2
  35. package/dist/core/canvas/memory-reads.d.ts +6 -6
  36. package/dist/core/canvas/memory-reads.js +1 -1
  37. package/dist/core/canvas/nav-model.d.ts +13 -13
  38. package/dist/core/canvas/nav-model.js +1 -1
  39. package/dist/core/canvas/node-agent-paths.d.ts +6 -6
  40. package/dist/core/canvas/node-agent-paths.js +1 -1
  41. package/dist/core/canvas/node-tokens.d.ts +7 -7
  42. package/dist/core/canvas/node-tokens.js +3 -3
  43. package/dist/core/canvas/outcome-actions.d.ts +5 -5
  44. package/dist/core/canvas/outcome-actions.js +3 -3
  45. package/dist/core/canvas/recovery.d.ts +26 -26
  46. package/dist/core/canvas/recovery.js +2 -2
  47. package/dist/core/canvas/render-source.d.ts +1 -1
  48. package/dist/core/canvas/render-source.js +1 -1
  49. package/dist/core/canvas/sessions.d.ts +10 -10
  50. package/dist/core/canvas/sessions.js +4 -4
  51. package/dist/core/canvas/source.js +1 -1
  52. package/dist/core/canvas/structured-requests.d.ts +15 -15
  53. package/dist/core/canvas/structured-requests.js +5 -5
  54. package/dist/core/canvas/tree.d.ts +9 -9
  55. package/dist/core/canvas/tree.js +5 -5
  56. package/dist/core/canvas/waits.d.ts +13 -13
  57. package/dist/core/canvas/waits.js +6 -6
  58. package/dist/core/canvas/worktrees.d.ts +15 -15
  59. package/dist/core/canvas/worktrees.js +1 -1
  60. package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -1
  61. package/dist/core/conversation-store/file-store.d.ts +7 -7
  62. package/dist/core/conversation-store/file-store.js +9 -9
  63. package/dist/core/conversation-store/index.d.ts +16 -14
  64. package/dist/core/conversation-store/index.js +1 -1
  65. package/dist/core/conversation-store/listener.js +5 -5
  66. package/dist/core/conversation-store/patch.d.ts +3 -1
  67. package/dist/core/conversation-store/patch.js +1 -1
  68. package/dist/core/feed/feed.js +3 -3
  69. package/dist/core/feed/inbox.d.ts +2 -2
  70. package/dist/core/feed/inbox.js +1 -1
  71. package/dist/core/feed/messages.d.ts +11 -12
  72. package/dist/core/feed/messages.js +5 -5
  73. package/dist/core/feed/reports.d.ts +4 -4
  74. package/dist/core/feed/reports.js +2 -2
  75. package/dist/core/grants/cover.d.ts +1 -1
  76. package/dist/core/grants/cover.js +1 -1
  77. package/dist/core/grants/local.d.ts +1 -1
  78. package/dist/core/grants/local.js +1 -1
  79. package/dist/core/grants/mirror.d.ts +19 -19
  80. package/dist/core/grants/mirror.js +2 -2
  81. package/dist/core/grants/on-sync.d.ts +1 -1
  82. package/dist/core/grants/on-sync.js +1 -1
  83. package/dist/core/grants/remove.js +1 -1
  84. package/dist/core/grants/sync.js +1 -1
  85. package/dist/core/graph/access.d.ts +17 -17
  86. package/dist/core/graph/access.js +3 -3
  87. package/dist/core/graph/custom.d.ts +16 -16
  88. package/dist/core/graph/custom.js +9 -9
  89. package/dist/core/graph/deletion.d.ts +3 -7
  90. package/dist/core/graph/deletion.js +4 -4
  91. package/dist/core/graph/documents.d.ts +24 -27
  92. package/dist/core/graph/documents.js +7 -7
  93. package/dist/core/graph/edges.d.ts +13 -13
  94. package/dist/core/graph/edges.js +1 -1
  95. package/dist/core/graph/events.d.ts +7 -9
  96. package/dist/core/graph/events.js +8 -8
  97. package/dist/core/graph/exposures.d.ts +6 -6
  98. package/dist/core/graph/exposures.js +4 -4
  99. package/dist/core/graph/jobs.d.ts +6 -8
  100. package/dist/core/graph/jobs.js +2 -2
  101. package/dist/core/graph/kinds/action.js +1 -1
  102. package/dist/core/graph/kinds/custom.js +2 -2
  103. package/dist/core/graph/kinds/document.d.ts +1 -0
  104. package/dist/core/graph/kinds/document.js +4 -4
  105. package/dist/core/graph/kinds/dto.d.ts +2 -2
  106. package/dist/core/graph/kinds/dto.js +1 -1
  107. package/dist/core/graph/kinds/job.js +2 -2
  108. package/dist/core/graph/kinds/kind.d.ts +6 -8
  109. package/dist/core/graph/kinds/kind.js +1 -1
  110. package/dist/core/graph/kinds/node.js +5 -5
  111. package/dist/core/graph/kinds/owner.js +2 -2
  112. package/dist/core/graph/kinds/registry.d.ts +6 -9
  113. package/dist/core/graph/kinds/registry.js +1 -1
  114. package/dist/core/graph/names.d.ts +6 -6
  115. package/dist/core/graph/names.js +3 -3
  116. package/dist/core/graph/object-waits.d.ts +4 -7
  117. package/dist/core/graph/object-waits.js +1 -1
  118. package/dist/core/graph/objects.d.ts +14 -14
  119. package/dist/core/graph/objects.js +9 -9
  120. package/dist/core/graph/package-docs.d.ts +2 -7
  121. package/dist/core/graph/package-docs.js +5 -5
  122. package/dist/core/graph/package-kinds.d.ts +2 -5
  123. package/dist/core/graph/package-kinds.js +1 -1
  124. package/dist/core/graph/package-reconcile.d.ts +2 -5
  125. package/dist/core/graph/package-reconcile.js +1 -1
  126. package/dist/core/graph/reader.d.ts +18 -18
  127. package/dist/core/graph/reader.js +3 -3
  128. package/dist/core/graph/receivers.d.ts +4 -4
  129. package/dist/core/graph/receivers.js +5 -5
  130. package/dist/core/graph/repo-sync/exchange.d.ts +3 -7
  131. package/dist/core/graph/repo-sync/exchange.js +2 -2
  132. package/dist/core/graph/repo-sync/repos.d.ts +7 -5
  133. package/dist/core/graph/repo-sync/repos.js +3 -3
  134. package/dist/core/graph/repo-sync/sync.d.ts +3 -6
  135. package/dist/core/graph/repo-sync/sync.js +2 -2
  136. package/dist/core/graph/rules.d.ts +5 -5
  137. package/dist/core/graph/rules.js +3 -3
  138. package/dist/core/graph/spaces/app.js +1 -1
  139. package/dist/core/graph/spaces/index.d.ts +4 -5
  140. package/dist/core/graph/spaces/index.js +1 -1
  141. package/dist/core/graph/spaces/own-memory.d.ts +4 -4
  142. package/dist/core/graph/spaces/own-memory.js +1 -1
  143. package/dist/core/graph/spaces/person.js +3 -3
  144. package/dist/core/graph/spaces/repo.d.ts +1 -1
  145. package/dist/core/graph/spaces/repo.js +1 -1
  146. package/dist/core/graph/watches.d.ts +15 -15
  147. package/dist/core/graph/watches.js +10 -10
  148. package/dist/core/human/feedback-companion.d.ts +2 -2
  149. package/dist/core/human/feedback-companion.js +1 -1
  150. package/dist/core/human/feedback.d.ts +3 -3
  151. package/dist/core/human/feedback.js +1 -1
  152. package/dist/core/human/requests.d.ts +34 -33
  153. package/dist/core/human/requests.js +20 -20
  154. package/dist/core/human/scan.d.ts +2 -2
  155. package/dist/core/human/scan.js +1 -1
  156. package/dist/core/human/tickets.d.ts +9 -9
  157. package/dist/core/human/tickets.js +1 -1
  158. package/dist/core/llm/app-rungs.d.ts +1 -1
  159. package/dist/core/llm/app-rungs.js +1 -1
  160. package/dist/core/llm/run.js +2 -2
  161. package/dist/core/peer/directory.d.ts +1 -1
  162. package/dist/core/peer/directory.js +1 -1
  163. package/dist/core/peer/envelope.d.ts +3 -3
  164. package/dist/core/peer/envelope.js +1 -1
  165. package/dist/core/peer/home.d.ts +13 -7
  166. package/dist/core/peer/home.js +2 -2
  167. package/dist/core/peer/ingest.d.ts +6 -6
  168. package/dist/core/peer/ingest.js +1 -1
  169. package/dist/core/peer/outbox-store.d.ts +14 -14
  170. package/dist/core/peer/outbox-store.js +5 -5
  171. package/dist/core/peer/receiver.d.ts +2 -2
  172. package/dist/core/peer/receiver.js +1 -1
  173. package/dist/core/peer/stubs.d.ts +10 -10
  174. package/dist/core/peer/stubs.js +1 -1
  175. package/dist/core/providers/approval.d.ts +2 -2
  176. package/dist/core/providers/approval.js +2 -2
  177. package/dist/core/providers/audit.d.ts +3 -3
  178. package/dist/core/providers/audit.js +2 -2
  179. package/dist/core/providers/bundles.js +2 -2
  180. package/dist/core/providers/call.d.ts +2 -2
  181. package/dist/core/providers/call.js +1 -1
  182. package/dist/core/providers/files.d.ts +1 -1
  183. package/dist/core/providers/files.js +1 -1
  184. package/dist/core/providers/mint.js +1 -1
  185. package/dist/core/providers/receipts.d.ts +1 -1
  186. package/dist/core/providers/receipts.js +2 -2
  187. package/dist/core/review/birth.js +1 -1
  188. package/dist/core/review/comments.d.ts +19 -19
  189. package/dist/core/review/comments.js +5 -5
  190. package/dist/core/review/companion.d.ts +1 -1
  191. package/dist/core/review/companion.js +1 -1
  192. package/dist/core/review/document.d.ts +3 -3
  193. package/dist/core/review/document.js +2 -2
  194. package/dist/core/review/fork.js +2 -2
  195. package/dist/core/review/realize.js +1 -1
  196. package/dist/core/review/remap.d.ts +2 -2
  197. package/dist/core/review/remap.js +4 -4
  198. package/dist/core/review/stage.d.ts +1 -1
  199. package/dist/core/review/stage.js +1 -1
  200. package/dist/core/review/store.d.ts +21 -21
  201. package/dist/core/review/store.js +1 -1
  202. package/dist/core/runs/activity.d.ts +1 -1
  203. package/dist/core/runs/activity.js +5 -5
  204. package/dist/core/runs/confinement.d.ts +7 -7
  205. package/dist/core/runs/confinement.js +2 -2
  206. package/dist/core/runs/events.d.ts +12 -12
  207. package/dist/core/runs/events.js +4 -4
  208. package/dist/core/runs/operations.d.ts +11 -11
  209. package/dist/core/runs/operations.js +5 -5
  210. package/dist/core/runs/questions.d.ts +10 -10
  211. package/dist/core/runs/questions.js +3 -3
  212. package/dist/core/runtime/auth-reload.js +1 -1
  213. package/dist/core/runtime/bearings.d.ts +5 -5
  214. package/dist/core/runtime/bearings.js +6 -6
  215. package/dist/core/runtime/broker-inventory.js +1 -1
  216. package/dist/core/runtime/broker-request.js +1 -1
  217. package/dist/core/runtime/broker.js +1 -1
  218. package/dist/core/runtime/close.d.ts +3 -3
  219. package/dist/core/runtime/close.js +1 -1
  220. package/dist/core/runtime/deliver-live.js +1 -1
  221. package/dist/core/runtime/fleet.d.ts +2 -2
  222. package/dist/core/runtime/host.d.ts +3 -3
  223. package/dist/core/runtime/host.js +3 -3
  224. package/dist/core/runtime/kickoff.d.ts +12 -12
  225. package/dist/core/runtime/kickoff.js +17 -17
  226. package/dist/core/runtime/launch-target.d.ts +1 -1
  227. package/dist/core/runtime/launch-target.js +1 -1
  228. package/dist/core/runtime/ledger.d.ts +3 -3
  229. package/dist/core/runtime/ledger.js +3 -3
  230. package/dist/core/runtime/lifecycle.d.ts +1 -1
  231. package/dist/core/runtime/lifecycle.js +2 -2
  232. package/dist/core/runtime/memory-admission.js +1 -1
  233. package/dist/core/runtime/model-swap.d.ts +2 -2
  234. package/dist/core/runtime/model-swap.js +1 -1
  235. package/dist/core/runtime/node-read.d.ts +1 -1
  236. package/dist/core/runtime/node-read.js +2 -2
  237. package/dist/core/runtime/nodes.d.ts +6 -6
  238. package/dist/core/runtime/nodes.js +1 -1
  239. package/dist/core/runtime/outcome-document.d.ts +1 -1
  240. package/dist/core/runtime/outcome-document.js +1 -1
  241. package/dist/core/runtime/persona.d.ts +3 -3
  242. package/dist/core/runtime/persona.js +2 -2
  243. package/dist/core/runtime/placement.d.ts +11 -11
  244. package/dist/core/runtime/placement.js +1 -1
  245. package/dist/core/runtime/promote.d.ts +3 -3
  246. package/dist/core/runtime/promote.js +1 -1
  247. package/dist/core/runtime/recycle.js +1 -1
  248. package/dist/core/runtime/reopen.d.ts +5 -5
  249. package/dist/core/runtime/reopen.js +1 -1
  250. package/dist/core/runtime/reset.d.ts +4 -4
  251. package/dist/core/runtime/reset.js +1 -1
  252. package/dist/core/runtime/revive-all.d.ts +2 -2
  253. package/dist/core/runtime/revive-all.js +1 -1
  254. package/dist/core/runtime/revive.d.ts +4 -4
  255. package/dist/core/runtime/revive.js +2 -2
  256. package/dist/core/runtime/roadmap.d.ts +6 -6
  257. package/dist/core/runtime/roadmap.js +5 -5
  258. package/dist/core/runtime/session-branch.d.ts +1 -1
  259. package/dist/core/runtime/session-branch.js +1 -1
  260. package/dist/core/runtime/session-list-cache.js +1 -1
  261. package/dist/core/runtime/situational-live.js +1 -1
  262. package/dist/core/runtime/spawn.d.ts +2 -2
  263. package/dist/core/runtime/spawn.js +2 -2
  264. package/dist/core/runtime/stop-guard.d.ts +2 -2
  265. package/dist/core/runtime/stop-guard.js +3 -3
  266. package/dist/core/runtime/warm-pool.d.ts +2 -2
  267. package/dist/core/runtime/warm-pool.js +1 -1
  268. package/dist/core/spaces/mounts.d.ts +2 -2
  269. package/dist/core/spaces/mounts.js +1 -1
  270. package/dist/core/spaces/permissions.d.ts +1 -1
  271. package/dist/core/spaces/permissions.js +1 -1
  272. package/dist/core/spaces/process.d.ts +1 -1
  273. package/dist/core/spaces/process.js +1 -1
  274. package/dist/core/spaces/space.js +1 -1
  275. package/dist/core/spaces/stop.d.ts +3 -3
  276. package/dist/core/spaces/stop.js +2 -2
  277. package/dist/core/spaces/users.d.ts +6 -6
  278. package/dist/core/spaces/users.js +1 -1
  279. package/dist/core/storage/attachments.d.ts +2 -2
  280. package/dist/core/storage/attachments.js +1 -1
  281. package/dist/core/storage/shares.d.ts +2 -2
  282. package/dist/core/storage/shares.js +1 -1
  283. package/dist/core/storage/tables.d.ts +21 -21
  284. package/dist/core/storage/tables.js +3 -3
  285. package/dist/core/substrate/delivery/corpus.d.ts +5 -8
  286. package/dist/core/substrate/delivery/corpus.js +3 -3
  287. package/dist/core/substrate/delivery/deliver.d.ts +10 -15
  288. package/dist/core/substrate/delivery/deliver.js +3 -3
  289. package/dist/core/substrate/delivery/plan.d.ts +2 -12
  290. package/dist/core/substrate/delivery/plan.js +3 -3
  291. package/dist/core/substrate/delivery/render-boot.d.ts +4 -4
  292. package/dist/core/substrate/delivery/render-boot.js +18 -18
  293. package/dist/core/substrate/delivery/render-event.d.ts +7 -14
  294. package/dist/core/substrate/delivery/render-event.js +4 -4
  295. package/dist/core/substrate/subject.d.ts +2 -2
  296. package/dist/core/substrate/subject.js +1 -1
  297. package/dist/core/usage/ledger.d.ts +6 -6
  298. package/dist/core/usage/ledger.js +4 -4
  299. package/dist/core/worktree-close.js +4 -4
  300. package/dist/core/worktree-mutation-async.js +7 -7
  301. package/dist/core/worktree-quarantine.js +1 -1
  302. package/dist/core/worktree-sweep.d.ts +1 -1
  303. package/dist/core/worktree-sweep.js +6 -6
  304. package/dist/core/worktree.d.ts +5 -5
  305. package/dist/core/worktree.js +13 -13
  306. package/dist/daemon/analytics/compute.d.ts +2 -2
  307. package/dist/daemon/analytics/compute.js +1 -1
  308. package/dist/daemon/api/app-listener.d.ts +4 -4
  309. package/dist/daemon/api/app-listener.js +13 -13
  310. package/dist/daemon/api/bridge.js +5 -5
  311. package/dist/daemon/api/document-listener.js +6 -6
  312. package/dist/daemon/api/handlers/analytics.js +1 -1
  313. package/dist/daemon/api/handlers/attach.js +1 -1
  314. package/dist/daemon/api/handlers/bash-jobs.js +1 -1
  315. package/dist/daemon/api/handlers/bash.js +1 -1
  316. package/dist/daemon/api/handlers/broker-ops.d.ts +1 -1
  317. package/dist/daemon/api/handlers/broker-ops.js +1 -1
  318. package/dist/daemon/api/handlers/broker-recovery.d.ts +1 -1
  319. package/dist/daemon/api/handlers/broker-recovery.js +1 -1
  320. package/dist/daemon/api/handlers/broker-signals.d.ts +2 -2
  321. package/dist/daemon/api/handlers/broker-signals.js +2 -2
  322. package/dist/daemon/api/handlers/canvas.d.ts +1 -1
  323. package/dist/daemon/api/handlers/canvas.js +4 -4
  324. package/dist/daemon/api/handlers/chat-inventory.js +1 -1
  325. package/dist/daemon/api/handlers/crons.js +1 -1
  326. package/dist/daemon/api/handlers/custom-objects.d.ts +4 -4
  327. package/dist/daemon/api/handlers/custom-objects.js +3 -3
  328. package/dist/daemon/api/handlers/delivery-retry.js +1 -1
  329. package/dist/daemon/api/handlers/delivery.js +1 -1
  330. package/dist/daemon/api/handlers/docs.d.ts +4 -4
  331. package/dist/daemon/api/handlers/docs.js +1 -1
  332. package/dist/daemon/api/handlers/feedback-comments.js +3 -3
  333. package/dist/daemon/api/handlers/files.js +1 -1
  334. package/dist/daemon/api/handlers/focus.js +1 -1
  335. package/dist/daemon/api/handlers/health.js +3 -3
  336. package/dist/daemon/api/handlers/hook-exec.js +1 -1
  337. package/dist/daemon/api/handlers/human-requests.js +1 -1
  338. package/dist/daemon/api/handlers/inbox-page.d.ts +1 -1
  339. package/dist/daemon/api/handlers/inbox-page.js +1 -1
  340. package/dist/daemon/api/handlers/inbox.d.ts +1 -1
  341. package/dist/daemon/api/handlers/inbox.js +1 -1
  342. package/dist/daemon/api/handlers/llm.d.ts +1 -1
  343. package/dist/daemon/api/handlers/llm.js +3 -3
  344. package/dist/daemon/api/handlers/memory-reads.js +1 -1
  345. package/dist/daemon/api/handlers/memory.d.ts +5 -5
  346. package/dist/daemon/api/handlers/memory.js +5 -5
  347. package/dist/daemon/api/handlers/messages.js +2 -2
  348. package/dist/daemon/api/handlers/node-events.d.ts +2 -2
  349. package/dist/daemon/api/handlers/node-events.js +3 -3
  350. package/dist/daemon/api/handlers/node-outcomes.js +1 -1
  351. package/dist/daemon/api/handlers/node-records.js +2 -2
  352. package/dist/daemon/api/handlers/nodes.d.ts +1 -1
  353. package/dist/daemon/api/handlers/nodes.js +1 -1
  354. package/dist/daemon/api/handlers/objects.js +3 -3
  355. package/dist/daemon/api/handlers/package-docs.js +1 -1
  356. package/dist/daemon/api/handlers/plugin-app-token.d.ts +1 -1
  357. package/dist/daemon/api/handlers/plugin-app-token.js +1 -1
  358. package/dist/daemon/api/handlers/profiles.d.ts +3 -3
  359. package/dist/daemon/api/handlers/profiles.js +1 -1
  360. package/dist/daemon/api/handlers/providers.d.ts +1 -1
  361. package/dist/daemon/api/handlers/providers.js +1 -1
  362. package/dist/daemon/api/handlers/questions.js +1 -1
  363. package/dist/daemon/api/handlers/reports.d.ts +1 -1
  364. package/dist/daemon/api/handlers/reports.js +5 -5
  365. package/dist/daemon/api/handlers/review-comments.js +1 -1
  366. package/dist/daemon/api/handlers/reviews.js +1 -1
  367. package/dist/daemon/api/handlers/runs.js +1 -1
  368. package/dist/daemon/api/handlers/structured-requests.js +1 -1
  369. package/dist/daemon/api/handlers/subscriptions.js +1 -1
  370. package/dist/daemon/api/handlers/transfer.js +1 -1
  371. package/dist/daemon/api/map.d.ts +3 -3
  372. package/dist/daemon/api/map.js +1 -1
  373. package/dist/daemon/api/principal.d.ts +1 -1
  374. package/dist/daemon/api/principal.js +1 -1
  375. package/dist/daemon/api/reader.d.ts +5 -5
  376. package/dist/daemon/api/reader.js +1 -1
  377. package/dist/daemon/api/router.d.ts +5 -5
  378. package/dist/daemon/api/router.js +1 -1
  379. package/dist/daemon/api/server.js +1 -1
  380. package/dist/daemon/broker-signals/bus.d.ts +1 -1
  381. package/dist/daemon/broker-signals/bus.js +1 -1
  382. package/dist/daemon/companion-retire.js +1 -1
  383. package/dist/daemon/cron/armed-context.d.ts +2 -2
  384. package/dist/daemon/cron/armed-context.js +1 -1
  385. package/dist/daemon/cron/authority.d.ts +2 -2
  386. package/dist/daemon/cron/authority.js +1 -1
  387. package/dist/daemon/cron/disposition.js +1 -1
  388. package/dist/daemon/cron/ended.d.ts +1 -1
  389. package/dist/daemon/cron/ended.js +2 -2
  390. package/dist/daemon/cron/escalation.js +3 -3
  391. package/dist/daemon/cron/folders.d.ts +1 -1
  392. package/dist/daemon/cron/folders.js +1 -1
  393. package/dist/daemon/cron/held.d.ts +1 -1
  394. package/dist/daemon/cron/held.js +1 -1
  395. package/dist/daemon/cron/lease-recovery.d.ts +1 -1
  396. package/dist/daemon/cron/lease-recovery.js +1 -1
  397. package/dist/daemon/cron/passes.d.ts +2 -2
  398. package/dist/daemon/cron/passes.js +1 -1
  399. package/dist/daemon/cron/run-socket.d.ts +1 -1
  400. package/dist/daemon/cron/run-socket.js +1 -1
  401. package/dist/daemon/cron/settle.js +1 -1
  402. package/dist/daemon/cron/sinks.d.ts +1 -1
  403. package/dist/daemon/cron/sinks.js +2 -2
  404. package/dist/daemon/cron-run.d.ts +12 -3
  405. package/dist/daemon/cron-run.js +2 -2
  406. package/dist/daemon/crtrd.js +6 -6
  407. package/dist/daemon/delivery/run-delivery.js +1 -1
  408. package/dist/daemon/due-sources.d.ts +3 -3
  409. package/dist/daemon/due-sources.js +1 -1
  410. package/dist/daemon/due.d.ts +3 -3
  411. package/dist/daemon/due.js +7 -7
  412. package/dist/daemon/fleet.d.ts +2 -2
  413. package/dist/daemon/fleet.js +11 -11
  414. package/dist/daemon/human/finish.js +3 -3
  415. package/dist/daemon/human/settle.d.ts +1 -1
  416. package/dist/daemon/human/settle.js +1 -1
  417. package/dist/daemon/human/sweep.js +1 -1
  418. package/dist/daemon/joined-owner.d.ts +2 -2
  419. package/dist/daemon/joined-owner.js +1 -1
  420. package/dist/daemon/messaging/node-message.js +1 -1
  421. package/dist/daemon/park-activity.d.ts +2 -2
  422. package/dist/daemon/park-activity.js +1 -1
  423. package/dist/daemon/peer/authority.js +1 -1
  424. package/dist/daemon/peer/forward.d.ts +13 -6
  425. package/dist/daemon/peer/forward.js +1 -1
  426. package/dist/daemon/peer/handlers.js +1 -1
  427. package/dist/daemon/peer/ingress.d.ts +4 -4
  428. package/dist/daemon/peer/ingress.js +1 -1
  429. package/dist/daemon/peer/outbox.d.ts +2 -2
  430. package/dist/daemon/peer/outbox.js +1 -1
  431. package/dist/daemon/peer/relay-service.js +1 -1
  432. package/dist/daemon/plugin-objects/read-leaf.d.ts +2 -2
  433. package/dist/daemon/plugin-objects/read-leaf.js +2 -2
  434. package/dist/daemon/profile-delete.js +1 -1
  435. package/dist/daemon/readiness.d.ts +2 -2
  436. package/dist/daemon/readiness.js +1 -1
  437. package/dist/daemon/reconcilers/action-lane.d.ts +1 -1
  438. package/dist/daemon/reconcilers/action-lane.js +1 -1
  439. package/dist/daemon/reconcilers/bash-deadline.js +2 -2
  440. package/dist/daemon/reconcilers/broker-supervision.d.ts +1 -1
  441. package/dist/daemon/reconcilers/broker-supervision.js +4 -4
  442. package/dist/daemon/reconcilers/controller-death.d.ts +1 -1
  443. package/dist/daemon/reconcilers/controller-death.js +1 -1
  444. package/dist/daemon/reconcilers/cron-lane.d.ts +1 -1
  445. package/dist/daemon/reconcilers/cron-lane.js +1 -1
  446. package/dist/daemon/reconcilers/delivery-lane.d.ts +1 -1
  447. package/dist/daemon/reconcilers/delivery-lane.js +2 -2
  448. package/dist/daemon/reconcilers/fault-retry-backstop.d.ts +3 -3
  449. package/dist/daemon/reconcilers/fault-retry-backstop.js +1 -1
  450. package/dist/daemon/reconcilers/grove-instance-sweep.d.ts +2 -2
  451. package/dist/daemon/reconcilers/grove-instance-sweep.js +1 -1
  452. package/dist/daemon/reconcilers/live-obligation.d.ts +6 -6
  453. package/dist/daemon/reconcilers/live-obligation.js +1 -1
  454. package/dist/daemon/reconcilers/managed-worktree-sweep.js +1 -1
  455. package/dist/daemon/reconcilers/node-deadline.d.ts +1 -1
  456. package/dist/daemon/reconcilers/node-deadline.js +1 -1
  457. package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
  458. package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.d.ts +3 -3
  459. package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.js +1 -1
  460. package/dist/daemon/reconcilers/node-lifecycle/terminating.js +1 -1
  461. package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
  462. package/dist/daemon/reconcilers/node-lifecycle/wants-execution.d.ts +1 -1
  463. package/dist/daemon/reconcilers/node-lifecycle/wants-execution.js +1 -1
  464. package/dist/daemon/reconcilers/pending-review-submit.d.ts +1 -1
  465. package/dist/daemon/reconcilers/pending-review-submit.js +1 -1
  466. package/dist/daemon/reconcilers/storage-due-work.js +1 -1
  467. package/dist/daemon/reconcilers/storage-maintenance.d.ts +1 -1
  468. package/dist/daemon/reconcilers/storage-maintenance.js +2 -2
  469. package/dist/daemon/reconcilers/structured-request-lane.d.ts +1 -1
  470. package/dist/daemon/reconcilers/structured-request-lane.js +1 -1
  471. package/dist/daemon/review/comment-notify.js +2 -2
  472. package/dist/daemon/review/companion.d.ts +3 -3
  473. package/dist/daemon/review/companion.js +1 -1
  474. package/dist/daemon/review/finish.js +1 -1
  475. package/dist/daemon/review/sweep.js +1 -1
  476. package/dist/daemon/run-notices.d.ts +4 -4
  477. package/dist/daemon/run-notices.js +1 -1
  478. package/dist/daemon/runs/append-section.d.ts +2 -2
  479. package/dist/daemon/runs/append-section.js +2 -2
  480. package/dist/daemon/runs/observer.d.ts +2 -2
  481. package/dist/daemon/runs/observer.js +2 -2
  482. package/dist/daemon/structured-requests/boot.d.ts +1 -1
  483. package/dist/daemon/structured-requests/boot.js +1 -1
  484. package/dist/daemon/structured-requests/effects.js +1 -1
  485. package/dist/daemon/structured-requests/sidecar.d.ts +1 -1
  486. package/dist/daemon/structured-requests/sidecar.js +1 -1
  487. package/dist/migrations/004-canvas-documents/apply.d.ts +3 -3
  488. package/dist/migrations/004-canvas-documents/apply.js +1 -1
  489. package/dist/migrations/004-canvas-documents/index.d.ts +2 -2
  490. package/dist/migrations/004-canvas-documents/index.js +2 -2
  491. package/dist/migrations/activation.js +2 -2
  492. package/docs/public-api.md +11 -0
  493. package/package.json +3 -2
  494. package/packages/crouter-identity/package.json +1 -1
  495. package/runtime.lock.json +12 -12
@@ -1,9 +1,9 @@
1
- import type { DatabaseSync } from 'node:sqlite';
2
1
  import type { ObjectRow, Privacy, Reader } from './types.js';
2
+ import type { CanvasDb } from '../canvas/db.js';
3
3
  export type OwnerType = 'person' | 'app' | 'repo' | 'profile';
4
- export declare function getById(db: DatabaseSync, id: string): ObjectRow | null;
5
- export declare function getByRowid(db: DatabaseSync, rowid: number): ObjectRow | null;
6
- export declare function createObject(db: DatabaseSync, spec: {
4
+ export declare function getById(db: CanvasDb, id: string): Promise<ObjectRow | null>;
5
+ export declare function getByRowid(db: CanvasDb, rowid: number): Promise<ObjectRow | null>;
6
+ export declare function createObject(db: CanvasDb, spec: {
7
7
  id?: string;
8
8
  type: string;
9
9
  kind: string | null;
@@ -13,25 +13,25 @@ export declare function createObject(db: DatabaseSync, spec: {
13
13
  preview: string;
14
14
  /** Set for a stub, in the insert itself: the name indexes cover only rows without it. */
15
15
  home_machine?: string;
16
- }): ObjectRow;
16
+ }): Promise<ObjectRow>;
17
17
  /** The owner object for an identity, created on first sight. Idempotent on
18
18
  * (scheme, externalId). Handles are unique per owner type: a handle already held
19
19
  * by a different identity of the same type throws `conflict` naming both; it is
20
20
  * never renamed silently. */
21
- export declare function ensureOwner(db: DatabaseSync, type: OwnerType, scheme: string, externalId: string, handle: string, owner?: ObjectRow): ObjectRow;
21
+ export declare function ensureOwner(db: CanvasDb, type: OwnerType, scheme: string, externalId: string, handle: string, owner?: ObjectRow): Promise<ObjectRow>;
22
22
  /** Give the live profile object of `profileId` the handle `handle`, so `[[handle/x]]` links,
23
23
  * `owner=` listings and `--owner profile:<handle>` follow a profile rename. Refuses with
24
24
  * `conflict` — before changing anything — when another live profile object holds the handle.
25
25
  * A profile with no object yet has nothing to rename (its object is created from the manifest name
26
26
  * on first use). Returns whether an object was renamed. Links are edges to ids, so they keep resolving. */
27
- export declare function renameProfileObject(db: DatabaseSync, profileId: string, handle: string): boolean;
27
+ export declare function renameProfileObject(db: CanvasDb, profileId: string, handle: string): Promise<boolean>;
28
28
  /** The owner object of a node grantee: `user:local` → person `user`; `app:<x>` → app `<x>`. */
29
- export declare function ownerForGrantee(db: DatabaseSync, grantee: string): ObjectRow;
29
+ export declare function ownerForGrantee(db: CanvasDb, grantee: string): Promise<ObjectRow>;
30
30
  /** The owner's live document named `name`, or null. */
31
- export declare function liveDocumentNamed(db: DatabaseSync, owner: number, name: string): ObjectRow | null;
32
- export declare function nodeObject(db: DatabaseSync, nodeId: string): ObjectRow;
33
- export declare function setObjectName(db: DatabaseSync, object: ObjectRow, name: string): void;
34
- export declare function setObjectKind(db: DatabaseSync, object: ObjectRow, kind: string | null): void;
31
+ export declare function liveDocumentNamed(db: CanvasDb, owner: number, name: string): Promise<ObjectRow | null>;
32
+ export declare function nodeObject(db: CanvasDb, nodeId: string): Promise<ObjectRow>;
33
+ export declare function setObjectName(db: CanvasDb, object: ObjectRow, name: string): Promise<void>;
34
+ export declare function setObjectKind(db: CanvasDb, object: ObjectRow, kind: string | null): Promise<void>;
35
35
  export interface ObjectFilter {
36
36
  type?: string;
37
37
  kind?: string;
@@ -45,7 +45,7 @@ export interface Page {
45
45
  after_rowid?: number;
46
46
  }
47
47
  /** Objects the reader can read, in rowid order. Records nothing. `limit` ≤ 100. */
48
- export declare function listObjects(db: DatabaseSync, reader: Reader, filter: ObjectFilter, page?: Page): ObjectRow[];
48
+ export declare function listObjects(db: CanvasDb, reader: Reader, filter: ObjectFilter, page?: Page): Promise<ObjectRow[]>;
49
49
  export interface SearchQuery {
50
50
  text: string;
51
51
  body?: boolean;
@@ -61,4 +61,4 @@ export interface SearchHit {
61
61
  * matches name, preview and document summary as a substring; `body` also scans
62
62
  * each document's head bodies for the substring, and `grep` scans them for `text`
63
63
  * as a regular expression. Body search reads every readable body: linear, no index. */
64
- export declare function searchObjects(db: DatabaseSync, reader: Reader, query: SearchQuery): SearchHit[];
64
+ export declare function searchObjects(db: CanvasDb, reader: Reader, query: SearchQuery): Promise<SearchHit[]>;
@@ -1,11 +1,11 @@
1
- var _=Object.defineProperty;var s=(t,e)=>_(t,"name",{value:e,configurable:!0});import{prepared as d}from"../sqlite-statements.js";import{CrtrError as O,notFound as b}from"../errors.js";import{ExitCode as R}from"../../types.js";import{newNodeId as A}from"../runtime/nodes.js";import{kindOf as I}from"./kinds/registry.js";import{canRead as h}from"./access.js";import{bodyOf as T}from"./bodies.js";const y=new Set(["person","app","repo","profile"]);function N(t){return t||null}s(N,"rowFrom");function x(t,e){return N(d(t,"SELECT * FROM objects WHERE id = ?").get(e))}s(x,"getById");function P(t,e){return N(d(t,"SELECT * FROM objects WHERE rowid = ?").get(e))}s(P,"getByRowid");function D(t,e){return I(t,e.type),d(t,`INSERT INTO objects (id, type, kind, owner, privacy, name, preview, created_at, home_machine)
2
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`).get(e.id??A(),e.type,e.kind,e.owner,e.privacy,e.name,e.preview,new Date().toISOString(),e.home_machine??null)}s(D,"createObject");function S(t,e,o,i,n,r){if(!y.has(e))throw new Error(`ensureOwner: ${e} is not an owner type`);const E=d(t,`SELECT o.* FROM identities i JOIN objects o ON o.rowid = i.object
3
- WHERE i.scheme = ? AND i.external_id = ?`).get(o,i);if(E)return E;const a=d(t,`SELECT o.id, o.type, i.scheme, i.external_id FROM objects o
1
+ var y=Object.defineProperty;var a=(o,e)=>y(o,"name",{value:e,configurable:!0});import{CrtrError as L,notFound as j}from"../errors.js";import{ExitCode as O}from"../../types.js";import{newNodeId as _}from"../runtime/nodes.js";import{kindOf as b}from"./kinds/registry.js";import{canRead as l}from"./access.js";import{bodyOf as A}from"./bodies.js";const I=new Set(["person","app","repo","profile"]);function h(o){return o||null}a(h,"rowFrom");async function T(o,e){return h(await o.prepare("SELECT * FROM objects WHERE id = ?").get(e))}a(T,"getById");async function M(o,e){return h(await o.prepare("SELECT * FROM objects WHERE rowid = ?").get(e))}a(M,"getByRowid");async function x(o,e){return await b(o,e.type),await o.prepare(`INSERT INTO objects (id, type, kind, owner, privacy, name, preview, created_at, home_machine)
2
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`).get(e.id??await _(),e.type,e.kind,e.owner,e.privacy,e.name,e.preview,new Date().toISOString(),e.home_machine??null)}a(x,"createObject");async function R(o,e,t,i,n,r){if(!I.has(e))throw new Error(`ensureOwner: ${e} is not an owner type`);const d=await o.prepare(`SELECT o.* FROM identities i JOIN objects o ON o.rowid = i.object
3
+ WHERE i.scheme = ? AND i.external_id = ?`).get(t,i);if(d)return d;const s=await o.prepare(`SELECT o.id, o.type, i.scheme, i.external_id FROM objects o
4
4
  LEFT JOIN identities i ON i.object = o.rowid
5
- WHERE o.name = ? AND o.type = ? AND o.home_machine IS NULL`).get(n,e);if(a)throw new O("conflict",`handle "${n}" is held by ${a.type} ${a.id} (${a.scheme}:${a.external_id}); cannot give it to ${e} ${o}:${i}`,R.GENERAL,{handle:n,holder:a.id});const u=D(t,{type:e,kind:null,owner:e==="profile"?r?.rowid??null:null,privacy:"public",name:n,preview:""});return d(t,"INSERT INTO identities (object, scheme, external_id) VALUES (?, ?, ?)").run(u.rowid,o,i),u}s(S,"ensureOwner");function J(t,e,o){const i=d(t,`SELECT o.* FROM identities i JOIN objects o ON o.rowid = i.object
6
- WHERE i.scheme = 'profile' AND i.external_id = ? AND o.type = 'profile' AND o.deleted_at IS NULL`).get(e),n=d(t,`SELECT o.id FROM objects o
7
- WHERE o.name = ? AND o.type = 'profile' AND o.deleted_at IS NULL AND o.home_machine IS NULL AND o.rowid <> ?`).get(o,i?i.rowid:-1);if(n)throw new O("conflict",`handle "${o}" is already held by profile object ${n.id}; cannot rename profile ${e} to it`,R.GENERAL,{handle:o,holder:n.id});if(!i)return!1;const r=i;return r.name===o?!1:(g(t,r,o),!0)}s(J,"renameProfileObject");function B(t,e){if(e==="user:local")return S(t,"person","local-user",e,"user");if(/^app:[a-z0-9][a-z0-9._-]*$/.test(e))return S(t,"app","app",e,e.slice(4));throw new Error(`node grantee ${JSON.stringify(e)} is neither app:<name> nor user:local`)}s(B,"ownerForGrantee");function G(t,e,o){return N(d(t,"SELECT * FROM objects WHERE (type = 'document' OR instr(type, '.') > 0) AND owner = ? AND name = ? AND deleted_at IS NULL AND home_machine IS NULL").get(e,o))}s(G,"liveDocumentNamed");function K(t,e){const o=x(t,e);if(!o||o.type!=="node")throw b(`no node object ${e}`);return o}s(K,"nodeObject");function g(t,e,o){d(t,"UPDATE objects SET name = ? WHERE rowid = ?").run(o,e.rowid)}s(g,"setObjectName");function Y(t,e,o){d(t,"UPDATE objects SET kind = ? WHERE rowid = ?").run(o,e.rowid)}s(Y,"setObjectKind");function z(t,e,o,i={}){const n=["rowid > ?"],r=[i.after_rowid??0];return o.type!==void 0&&(n.push("type = ?"),r.push(o.type)),o.kind!==void 0&&(n.push("kind = ?"),r.push(o.kind)),o.owner!==void 0&&(n.push("owner = ?"),r.push(o.owner.rowid)),o.privacy!==void 0&&(n.push("privacy = ?"),r.push(o.privacy)),o.name!==void 0&&(n.push("name = ?"),r.push(o.name)),n.push("home_machine IS NULL"),n.push(o.deleted?"deleted_at IS NOT NULL":"deleted_at IS NULL"),C(t,e,`SELECT * FROM objects WHERE ${n.join(" AND ")}`,r,Math.min(i.limit??100,100))}s(z,"listObjects");function V(t,e,o){const n=[],r=`%${o.text.replace(/[\\%_]/g,c=>`\\${c}`)}%`;if(!o.grep){const c=d(t,`SELECT o.*, d.summary AS _summary FROM objects o LEFT JOIN documents d ON d.object = o.rowid
5
+ WHERE o.name = ? AND o.type = ? AND o.home_machine IS NULL`).get(n,e);if(s)throw new L("conflict",`handle "${n}" is held by ${s.type} ${s.id} (${s.scheme}:${s.external_id}); cannot give it to ${e} ${t}:${i}`,O.GENERAL,{handle:n,holder:s.id});const p=await x(o,{type:e,kind:null,owner:e==="profile"?r?.rowid??null:null,privacy:"public",name:n,preview:""});return await o.prepare("INSERT INTO identities (object, scheme, external_id) VALUES (?, ?, ?)").run(p.rowid,t,i),p}a(R,"ensureOwner");async function k(o,e,t){const i=await o.prepare(`SELECT o.* FROM identities i JOIN objects o ON o.rowid = i.object
6
+ WHERE i.scheme = 'profile' AND i.external_id = ? AND o.type = 'profile' AND o.deleted_at IS NULL`).get(e),n=await o.prepare(`SELECT o.id FROM objects o
7
+ WHERE o.name = ? AND o.type = 'profile' AND o.deleted_at IS NULL AND o.home_machine IS NULL AND o.rowid <> ?`).get(t,i?i.rowid:-1);if(n)throw new L("conflict",`handle "${t}" is already held by profile object ${n.id}; cannot rename profile ${e} to it`,O.GENERAL,{handle:t,holder:n.id});if(!i)return!1;const r=i;return r.name===t?!1:(await D(o,r,t),!0)}a(k,"renameProfileObject");async function P(o,e){if(e==="user:local")return await R(o,"person","local-user",e,"user");if(/^app:[a-z0-9][a-z0-9._-]*$/.test(e))return await R(o,"app","app",e,e.slice(4));throw new Error(`node grantee ${JSON.stringify(e)} is neither app:<name> nor user:local`)}a(P,"ownerForGrantee");async function J(o,e,t){return h(await o.prepare("SELECT * FROM objects WHERE (type = 'document' OR instr(type, '.') > 0) AND owner = ? AND name = ? AND deleted_at IS NULL AND home_machine IS NULL").get(e,t))}a(J,"liveDocumentNamed");async function B(o,e){const t=await T(o,e);if(!t||t.type!=="node")throw j(`no node object ${e}`);return t}a(B,"nodeObject");async function D(o,e,t){await o.prepare("UPDATE objects SET name = ? WHERE rowid = ?").run(t,e.rowid)}a(D,"setObjectName");async function G(o,e,t){await o.prepare("UPDATE objects SET kind = ? WHERE rowid = ?").run(t,e.rowid)}a(G,"setObjectKind");async function K(o,e,t,i={}){const n=["rowid > ?"],r=[i.after_rowid??0];return t.type!==void 0&&(n.push("type = ?"),r.push(t.type)),t.kind!==void 0&&(n.push("kind = ?"),r.push(t.kind)),t.owner!==void 0&&(n.push("owner = ?"),r.push(t.owner.rowid)),t.privacy!==void 0&&(n.push("privacy = ?"),r.push(t.privacy)),t.name!==void 0&&(n.push("name = ?"),r.push(t.name)),n.push("home_machine IS NULL"),n.push(t.deleted?"deleted_at IS NOT NULL":"deleted_at IS NULL"),await g(o,e,`SELECT * FROM objects WHERE ${n.join(" AND ")}`,r,Math.min(i.limit??100,100))}a(K,"listObjects");async function Y(o,e,t){const n=[],r=`%${t.text.replace(/[\\%_]/g,c=>`\\${c}`)}%`;if(!t.grep){const c=await o.prepare(`SELECT o.*, d.summary AS _summary FROM objects o LEFT JOIN documents d ON d.object = o.rowid
8
8
  WHERE o.deleted_at IS NULL AND o.home_machine IS NULL AND (o.name LIKE ?1 ESCAPE '\\' OR o.preview LIKE ?1 ESCAPE '\\' OR d.summary LIKE ?1 ESCAPE '\\')
9
- ORDER BY o.rowid`).all(r),p=o.text.toLowerCase();for(const l of c){const{_summary:w,...m}=l,f=m;if(!h(t,e,f))continue;const L=f.name.toLowerCase().includes(p)?"name":f.preview.toLowerCase().includes(p)?"preview":"summary";if(n.push({object:f,field:L,...L==="summary"?{text:String(w)}:{}}),n.length>=100)return n}}if(!o.body&&!o.grep)return n;const E=new Set(n.map(c=>c.object.rowid)),a=o.grep?(c=>p=>c.test(p))(new RegExp(o.text)):c=>c.includes(o.text),u=d(t,"SELECT * FROM objects WHERE type = 'document' AND deleted_at IS NULL ORDER BY rowid").all(),j=d(t,`SELECT r.body_hash, d.source_path FROM revisions r JOIN documents d ON d.object = r.document WHERE r.document = ?
10
- AND NOT EXISTS (SELECT 1 FROM revision_parents p WHERE p.parent = r.rowid)`);for(const c of u)if(!(E.has(c.rowid)||!h(t,e,c)))for(const{body_hash:p,source_path:l}of j.all(c.rowid)){const w=T(p,l).split(`
11
- `),m=w.findIndex(a);if(!(m<0)){if(n.push({object:c,field:"body",line:m+1,text:w[m]}),n.length>=100)return n;break}}return n}s(V,"searchObjects");function C(t,e,o,i,n){const r=[],E=t.prepare(`${o} ORDER BY rowid LIMIT ${n*4}`);for(;;){const a=E.all(...i);for(const u of a)if(h(t,e,u)&&r.push(u),r.length===n)return r;if(a.length<n*4)return r;i[0]=a[a.length-1].rowid}}s(C,"readablePages");export{D as createObject,S as ensureOwner,x as getById,P as getByRowid,z as listObjects,G as liveDocumentNamed,K as nodeObject,B as ownerForGrantee,J as renameProfileObject,V as searchObjects,Y as setObjectKind,g as setObjectName};
9
+ ORDER BY o.rowid`).all(r),w=t.text.toLowerCase();for(const f of c){const{_summary:E,...u}=f,m=u;if(!await l(o,e,m))continue;const N=m.name.toLowerCase().includes(w)?"name":m.preview.toLowerCase().includes(w)?"preview":"summary";if(n.push({object:m,field:N,...N==="summary"?{text:String(E)}:{}}),n.length>=100)return n}}if(!t.body&&!t.grep)return n;const d=new Set(n.map(c=>c.object.rowid)),s=t.grep?(c=>w=>c.test(w))(new RegExp(t.text)):c=>c.includes(t.text),p=await o.prepare("SELECT * FROM objects WHERE type = 'document' AND deleted_at IS NULL ORDER BY rowid").all(),S=o.prepare(`SELECT r.body_hash, d.source_path FROM revisions r JOIN documents d ON d.object = r.document WHERE r.document = ?
10
+ AND NOT EXISTS (SELECT 1 FROM revision_parents p WHERE p.parent = r.rowid)`);for(const c of p)if(!(d.has(c.rowid)||!await l(o,e,c)))for(const{body_hash:w,source_path:f}of await S.all(c.rowid)){const E=A(w,f).split(`
11
+ `),u=E.findIndex(s);if(!(u<0)){if(n.push({object:c,field:"body",line:u+1,text:E[u]}),n.length>=100)return n;break}}return n}a(Y,"searchObjects");async function g(o,e,t,i,n){const r=[],d=o.prepareUncached(`${t} ORDER BY rowid LIMIT ${n*4}`);for(;;){const s=await d.all(...i);for(const p of s)if(await l(o,e,p)&&r.push(p),r.length===n)return r;if(s.length<n*4)return r;i[0]=s[s.length-1].rowid}}a(g,"readablePages");export{x as createObject,R as ensureOwner,T as getById,M as getByRowid,K as listObjects,J as liveDocumentNamed,B as nodeObject,P as ownerForGrantee,k as renameProfileObject,Y as searchObjects,G as setObjectKind,D as setObjectName};
@@ -1,10 +1,5 @@
1
- /** Package documents: builtin (`crtr`) and plugin documents stay files in their package; this
2
- * converges their `objects`/`documents` rows, their one revision and their rules onto those
3
- * files (contract §6.6). Bodies are read from `documents.source_path`, never the body store.
4
- * A plugin is an app: its documents belong to the app `<plugin>` (identity `app:<plugin>`,
5
- * the one `ownerForGrantee` gives), and a document with a `source_path` is shipped. */
6
- import type { DatabaseSync } from 'node:sqlite';
7
1
  import { type QuarantinedPlugin } from '../plugin-quarantine.js';
2
+ import type { CanvasDb } from '../canvas/db.js';
8
3
  export interface PackageSource {
9
4
  plugin: string;
10
5
  dir: string;
@@ -32,4 +27,4 @@ export interface PackageReconcileReport {
32
27
  * each document's link edges, which land the same). A changed body replaces the
33
28
  * document's single revision and publishes `edited`; a vanished file (or plugin) marks its
34
29
  * document deleted and publishes `deleted`. */
35
- export declare function reconcilePackageDocuments(db: DatabaseSync, explicitSources?: readonly PackageSource[]): PackageReconcileReport;
30
+ export declare function reconcilePackageDocuments(db: CanvasDb, explicitSources?: readonly PackageSource[]): Promise<PackageReconcileReport>;
@@ -1,5 +1,5 @@
1
- var O=Object.defineProperty;var u=(e,s)=>O(e,"name",{value:s,configurable:!0});import{prepared as p}from"../sqlite-statements.js";import{createHash as _,randomUUID as D}from"node:crypto";import{CrtrError as N}from"../errors.js";import{emitEvent as I}from"../events/emit.js";import{quarantineBrokenPlugins as A}from"../plugin-quarantine.js";import{listInstalledPlugins as k}from"../resolver.js";import{builtinMemoryRoot as L,pluginMemoryDir as T}from"../scope.js";import{documentFields as j}from"../../migrations/004-canvas-documents/fields.js";import{applyDocumentFields as R,deleteDocument as x,documentRecord as U,heads as F,importDocument as b,linksIn as J,moveDocument as C}from"./documents.js";import{isShipped as H}from"./access.js";import{setLinks as W}from"./edges.js";import{publish as M}from"./events.js";import{resolveName as P}from"./names.js";import{packageFiles as q}from"./package-files.js";import{ensureOwner as B,getByRowid as E,setObjectKind as K}from"./objects.js";import{checkoutsForCwd as $}from"./repo-sync/repos.js";import{rulesOf as z}from"./rules.js";function G(){return[{plugin:"crtr",dir:L()},...k("user").filter(e=>e.enabled).map(e=>({plugin:e.name,dir:T(e)}))]}u(G,"packageSources");const Q=u(e=>_("sha256").update(e,"utf8").digest("hex"),"sha256");function ge(e,s){const n={created:0,updated:0,deleted:0,conflicts:[],invalid:[],quarantined:[]};if(s===void 0){n.quarantined=A();for(const t of n.quarantined)I({level:"error",event:"daemon.plugins.quarantined",fields:{plugin:t.name,file:t.file,reason:t.reason,...t.movedTo!==void 0?{moved_to:t.movedTo}:{}}})}const f=s??G(),m=u(t=>$(e,t),"reposFn"),r=new Set,i=[],w=new Set;for(const t of f){let a;try{if(w.has(t.plugin))throw new N("conflict",`plugin "${t.plugin}" is already provided by another package`);w.add(t.plugin),a=B(e,"app","app",`app:${t.plugin}`,t.plugin)}catch(d){if(!(d instanceof N)||d.code!=="conflict")throw d;n.conflicts.push({plugin:t.plugin,message:d.message});continue}r.add(a.rowid);const{files:l,invalid:g}=q(t.dir);n.invalid.push(...g);const h=new Set;for(const d of l){const c=X(e,a,d,n,m);h.add(c),i.push({owner:a,rowid:c,body:d.body})}v(e,a,h,n,m)}const o=p(e,`SELECT DISTINCT o.owner AS rowid FROM objects o JOIN documents d ON d.object = o.rowid
2
- WHERE o.type = 'document' AND o.deleted_at IS NULL AND d.source_path IS NOT NULL`).all();for(const{rowid:t}of o)r.has(t)||v(e,E(e,t),new Set,n,m);for(const{owner:t,rowid:a,body:l}of i)V(e,t,E(e,a),l);return n}u(ge,"reconcilePackageDocuments");function V(e,s,n,f){if(n.deleted_at!==null)return;const m={class:"app",app:s,scopes:[]},r=[];for(const o of J(f)){const t=P(e,m,o);"object"in t&&t.object.rowid!==n.rowid&&H(e,t.object)&&r.push({written_as:o,dst:t.object})}const i=u(o=>JSON.stringify(o.map(t=>[t.dst,t.written_as]).sort()),"key"),w=p(e,"SELECT dst, written_as FROM edges WHERE type = 'links-to' AND src = ?").all(n.rowid);i(w)!==i(r.map(o=>({dst:o.dst.rowid,written_as:o.written_as})))&&W(e,n,r)}u(V,"deriveLinks");function X(e,s,n,f,m){const r=j(n.frontmatter,n.body,{missingPrivacy:"public"}),i={preview:r.preview.trim()===""?n.name:r.preview,summary:r.summary,whyItExists:r.whyItExists,unlisted:r.unlisted,rules:r.rules,lintIgnore:Array.isArray(r.lintIgnore)?r.lintIgnore.filter(c=>typeof c=="string"):null,extensions:r.extensions!==null&&typeof r.extensions=="object"&&!Array.isArray(r.extensions)?r.extensions:null},w=Q(n.body);let o=p(e,`SELECT o.* FROM objects o JOIN documents d ON d.object = o.rowid
3
- WHERE o.type = 'document' AND o.owner = ? AND o.deleted_at IS NULL AND d.source_path = ?`).get(s.rowid,n.path);if(o||(o=p(e,`SELECT o.* FROM objects o JOIN documents d ON d.object = o.rowid
4
- WHERE o.type = 'document' AND o.owner = ? AND o.deleted_at IS NULL AND o.name = ? AND d.source_path IS NOT NULL`).get(s.rowid,n.name),o&&p(e,"UPDATE documents SET source_path = ? WHERE object = ?").run(n.path,o.rowid)),!o){const c=b(e,{owner:s,name:n.name,kind:r.kind,privacy:"public",...i,revisions:[{body_hash:w,author:s,rationale:null,created_at:new Date().toISOString()}]});return p(e,"UPDATE documents SET source_path = ? WHERE object = ?").run(n.path,c.rowid),f.created+=1,c.rowid}const t=o.name!==n.name||o.kind!==r.kind;o.name!==n.name&&(o=C(e,null,o,{name:n.name})),o.kind!==r.kind&&(K(e,o,r.kind),o=E(e,o.rowid));const a=U(e,o),[l]=F(e,o),g=l?.body_hash!==w,h=o.preview!==i.preview||a.summary!==i.summary||a.why_it_exists!==i.whyItExists||a.unlisted!==i.unlisted||JSON.stringify(a.lint_ignore)!==JSON.stringify(i.lintIgnore)||JSON.stringify(a.extensions)!==JSON.stringify(i.extensions)||JSON.stringify(z(e,o).map(S))!==JSON.stringify(i.rules.map(S));if(!g&&!h&&!t)return o.rowid;const d=R(e,o,i);if(g&&l){const c=D(),y=l.number+1;p(e,"UPDATE revisions SET rev_id = ?, number = ?, body_hash = ?, created_at = ? WHERE rowid = ?").run(c,y,w,new Date().toISOString(),l.rowid),p(e,"UPDATE documents SET heads_key = ?, revision = ? WHERE object = ?").run(c,y,d.rowid),M(e,{event:"edited",object:d,actor:s,pointer:c,attrs:{revision:y,from_revision:l.number,rationale:"package file changed"}},m)}return f.updated+=1,d.rowid}u(X,"convergeFile");function S(e){return[e.on,e.deliver,e.match??null,e.matchFrontmatter??null,e.if??null]}u(S,"ruleKey");function v(e,s,n,f,m){const r=p(e,`SELECT o.* FROM objects o JOIN documents d ON d.object = o.rowid
5
- WHERE o.type = 'document' AND o.owner = ? AND o.deleted_at IS NULL AND d.source_path IS NOT NULL`).all(s.rowid);for(const i of r)n.has(i.rowid)||(x(e,null,i,m),f.deleted+=1)}u(v,"deleteMissing");export{G as packageSources,ge as reconcilePackageDocuments};
1
+ var v=Object.defineProperty;var u=(e,a)=>v(e,"name",{value:a,configurable:!0});import{createHash as O,randomUUID as _}from"node:crypto";import{CrtrError as E}from"../errors.js";import{emitEvent as D}from"../events/emit.js";import{quarantineBrokenPlugins as I}from"../plugin-quarantine.js";import{listInstalledPlugins as A}from"../resolver.js";import{builtinMemoryRoot as k,pluginMemoryDir as L}from"../scope.js";import{documentFields as T}from"../../migrations/004-canvas-documents/fields.js";import{applyDocumentFields as j,deleteDocument as R,documentRecord as x,heads as U,importDocument as F,linksIn as b,moveDocument as J}from"./documents.js";import{isShipped as C}from"./access.js";import{setLinks as H}from"./edges.js";import{publish as W}from"./events.js";import{resolveName as M}from"./names.js";import{packageFiles as P}from"./package-files.js";import{ensureOwner as q,getByRowid as h,setObjectKind as B}from"./objects.js";import{checkoutsForCwd as K}from"./repo-sync/repos.js";import{rulesOf as $}from"./rules.js";function z(){return[{plugin:"crtr",dir:k()},...A("user").filter(e=>e.enabled).map(e=>({plugin:e.name,dir:L(e)}))]}u(z,"packageSources");const G=u(e=>O("sha256").update(e,"utf8").digest("hex"),"sha256");async function we(e,a){const n={created:0,updated:0,deleted:0,conflicts:[],invalid:[],quarantined:[]};if(a===void 0){n.quarantined=I();for(const o of n.quarantined)D({level:"error",event:"daemon.plugins.quarantined",fields:{plugin:o.name,file:o.file,reason:o.reason,...o.movedTo!==void 0?{moved_to:o.movedTo}:{}}})}const l=a??z(),p=u(async o=>await K(e,o),"reposFn"),i=new Set,r=[],w=new Set;for(const o of l){let s;try{if(w.has(o.plugin))throw new E("conflict",`plugin "${o.plugin}" is already provided by another package`);w.add(o.plugin),s=await q(e,"app","app",`app:${o.plugin}`,o.plugin)}catch(c){if(!(c instanceof E)||c.code!=="conflict")throw c;n.conflicts.push({plugin:o.plugin,message:c.message});continue}i.add(s.rowid);const{files:m,invalid:f}=P(o.dir);n.invalid.push(...f);const y=new Set;for(const c of m){const d=await V(e,s,c,n,p);y.add(d),r.push({owner:s,rowid:d,body:c.body})}await S(e,s,y,n,p)}const t=await e.prepare(`SELECT DISTINCT o.owner AS rowid FROM objects o JOIN documents d ON d.object = o.rowid
2
+ WHERE o.type = 'document' AND o.deleted_at IS NULL AND d.source_path IS NOT NULL`).all();for(const{rowid:o}of t)i.has(o)||await S(e,await h(e,o),new Set,n,p);for(const{owner:o,rowid:s,body:m}of r)await Q(e,o,await h(e,s),m);return n}u(we,"reconcilePackageDocuments");async function Q(e,a,n,l){if(n.deleted_at!==null)return;const p={class:"app",app:a,scopes:[]},i=[];for(const t of b(l)){const o=await M(e,p,t);"object"in o&&o.object.rowid!==n.rowid&&await C(e,o.object)&&i.push({written_as:t,dst:o.object})}const r=u(t=>JSON.stringify(t.map(o=>[o.dst,o.written_as]).sort()),"key"),w=await e.prepare("SELECT dst, written_as FROM edges WHERE type = 'links-to' AND src = ?").all(n.rowid);r(w)!==r(i.map(t=>({dst:t.dst.rowid,written_as:t.written_as})))&&await H(e,n,i)}u(Q,"deriveLinks");async function V(e,a,n,l,p){const i=T(n.frontmatter,n.body,{missingPrivacy:"public"}),r={preview:i.preview.trim()===""?n.name:i.preview,summary:i.summary,whyItExists:i.whyItExists,unlisted:i.unlisted,rules:i.rules,lintIgnore:Array.isArray(i.lintIgnore)?i.lintIgnore.filter(d=>typeof d=="string"):null,extensions:i.extensions!==null&&typeof i.extensions=="object"&&!Array.isArray(i.extensions)?i.extensions:null},w=G(n.body);let t=await e.prepare(`SELECT o.* FROM objects o JOIN documents d ON d.object = o.rowid
3
+ WHERE o.type = 'document' AND o.owner = ? AND o.deleted_at IS NULL AND d.source_path = ?`).get(a.rowid,n.path);if(t||(t=await e.prepare(`SELECT o.* FROM objects o JOIN documents d ON d.object = o.rowid
4
+ WHERE o.type = 'document' AND o.owner = ? AND o.deleted_at IS NULL AND o.name = ? AND d.source_path IS NOT NULL`).get(a.rowid,n.name),t&&await e.prepare("UPDATE documents SET source_path = ? WHERE object = ?").run(n.path,t.rowid)),!t){const d=await F(e,{owner:a,name:n.name,kind:i.kind,privacy:"public",...r,revisions:[{body_hash:w,author:a,rationale:null,created_at:new Date().toISOString()}]});return await e.prepare("UPDATE documents SET source_path = ? WHERE object = ?").run(n.path,d.rowid),l.created+=1,d.rowid}const o=t.name!==n.name||t.kind!==i.kind;t.name!==n.name&&(t=await J(e,null,t,{name:n.name})),t.kind!==i.kind&&(await B(e,t,i.kind),t=await h(e,t.rowid));const s=await x(e,t),[m]=await U(e,t),f=m?.body_hash!==w,y=t.preview!==r.preview||s.summary!==r.summary||s.why_it_exists!==r.whyItExists||s.unlisted!==r.unlisted||JSON.stringify(s.lint_ignore)!==JSON.stringify(r.lintIgnore)||JSON.stringify(s.extensions)!==JSON.stringify(r.extensions)||JSON.stringify((await $(e,t)).map(N))!==JSON.stringify(r.rules.map(N));if(!f&&!y&&!o)return t.rowid;const c=await j(e,t,r);if(f&&m){const d=_(),g=m.number+1;await e.prepare("UPDATE revisions SET rev_id = ?, number = ?, body_hash = ?, created_at = ? WHERE rowid = ?").run(d,g,w,new Date().toISOString(),m.rowid),await e.prepare("UPDATE documents SET heads_key = ?, revision = ? WHERE object = ?").run(d,g,c.rowid),await W(e,{event:"edited",object:c,actor:a,pointer:d,attrs:{revision:g,from_revision:m.number,rationale:"package file changed"}},p)}return l.updated+=1,c.rowid}u(V,"convergeFile");function N(e){return[e.on,e.deliver,e.match??null,e.matchFrontmatter??null,e.if??null]}u(N,"ruleKey");async function S(e,a,n,l,p){const i=await e.prepare(`SELECT o.* FROM objects o JOIN documents d ON d.object = o.rowid
5
+ WHERE o.type = 'document' AND o.owner = ? AND o.deleted_at IS NULL AND d.source_path IS NOT NULL`).all(a.rowid);for(const r of i)n.has(r.rowid)||(await R(e,null,r,p),l.deleted+=1)}u(S,"deleteMissing");export{z as packageSources,we as reconcilePackageDocuments};
@@ -1,7 +1,4 @@
1
- /** Installed plugins' `object_kinds` blocks → `object_kinds` rows. Runs in the caller's write transaction.
2
- * A kind is never deleted and its catalog is never altered when undeclared: only `declared` flips, so the
3
- * instances of a dropped kind go inert instead of vanishing. */
4
- import type { DatabaseSync } from 'node:sqlite';
1
+ import type { CanvasDb } from '../canvas/db.js';
5
2
  export interface KindsReport {
6
3
  /** every kind a valid plugin declares that now has its row, and what upserting it did */
7
4
  applied: Array<{
@@ -22,4 +19,4 @@ export interface KindsReport {
22
19
  error: string;
23
20
  }>;
24
21
  }
25
- export declare function reconcilePackageKinds(db: DatabaseSync): KindsReport;
22
+ export declare function reconcilePackageKinds(db: CanvasDb): Promise<KindsReport>;
@@ -1 +1 @@
1
- var f=Object.defineProperty;var d=(o,i)=>f(o,"name",{value:i,configurable:!0});import{CrtrError as p}from"../errors.js";import{invalidAppPlugins as l,kindPlugins as g}from"../plugin-app.js";import{prepared as m}from"../sqlite-statements.js";import{upsertKind as h}from"./custom.js";import{ensureOwner as k}from"./objects.js";function S(o){const i={applied:[],refused:[],invalid:l().map(e=>({plugin:e.plugin.name,error:e.error}))},a=new Set;for(const e of g()){const c=Object.entries(e.manifest.object_kinds??{});if(c.length===0)continue;let s;try{s=k(o,"app","app",`app:${e.name}`,e.name)}catch(n){if(!(n instanceof p)||n.code!=="conflict")throw n;i.invalid.push({plugin:e.name,error:n.message});continue}for(const[n,t]of c)try{const r=h(o,{name:n,owner:s,description:t.description,events:t.events,read:t.read===void 0?null:{command:t.read.command},source:"manifest"});if(r.outcome==="skipped")continue;a.add(n),i.applied.push({plugin:e.name,kind:n,outcome:r.outcome})}catch(r){if(!(r instanceof p)||r.code!=="kind_owned")throw r;i.refused.push({plugin:e.name,kind:n,code:"kind_owned",message:r.message})}}const u=m(o,"SELECT name FROM object_kinds WHERE source = 'manifest' AND declared = 1").all();for(const{name:e}of u)a.has(e)||m(o,"UPDATE object_kinds SET declared = 0 WHERE name = ?").run(e);return i}d(S,"reconcilePackageKinds");export{S as reconcilePackageKinds};
1
+ var u=Object.defineProperty;var d=(o,i)=>u(o,"name",{value:i,configurable:!0});import{CrtrError as p}from"../errors.js";import{invalidAppPlugins as l,kindPlugins as f}from"../plugin-app.js";import{upsertKind as g}from"./custom.js";import{ensureOwner as w}from"./objects.js";async function j(o){const i={applied:[],refused:[],invalid:l().map(e=>({plugin:e.plugin.name,error:e.error}))},t=new Set;for(const e of f()){const s=Object.entries(e.manifest.object_kinds??{});if(s.length===0)continue;let c;try{c=await w(o,"app","app",`app:${e.name}`,e.name)}catch(n){if(!(n instanceof p)||n.code!=="conflict")throw n;i.invalid.push({plugin:e.name,error:n.message});continue}for(const[n,a]of s)try{const r=await g(o,{name:n,owner:c,description:a.description,events:a.events,read:a.read===void 0?null:{command:a.read.command},source:"manifest"});if(r.outcome==="skipped")continue;t.add(n),i.applied.push({plugin:e.name,kind:n,outcome:r.outcome})}catch(r){if(!(r instanceof p)||r.code!=="kind_owned")throw r;i.refused.push({plugin:e.name,kind:n,code:"kind_owned",message:r.message})}}const m=await o.prepare("SELECT name FROM object_kinds WHERE source = 'manifest' AND declared = 1").all();for(const{name:e}of m)t.has(e)||await o.prepare("UPDATE object_kinds SET declared = 0 WHERE name = ?").run(e);return i}d(j,"reconcilePackageKinds");export{j as reconcilePackageKinds};
@@ -1,9 +1,6 @@
1
- /** The one package reconcile pass: documents, then kinds, then plugin app tokens. Runs in the caller's write
2
- * transaction. The token writes go to the secrets store and are idempotent, so a rolled-back pass re-converges
3
- * on the next one. */
4
- import type { DatabaseSync } from 'node:sqlite';
5
1
  import { type KindsReport } from './package-kinds.js';
6
2
  import { type PackageReconcileReport } from './package-docs.js';
3
+ import type { CanvasDb } from '../canvas/db.js';
7
4
  export interface TokensReport {
8
5
  /** plugins holding a `crtr_app_` token, with the manifest scopes it carries */
9
6
  granted: Array<{
@@ -17,4 +14,4 @@ export interface PackagesReport extends PackageReconcileReport {
17
14
  kinds: KindsReport;
18
15
  tokens: TokensReport;
19
16
  }
20
- export declare function reconcilePackages(db: DatabaseSync): PackagesReport;
17
+ export declare function reconcilePackages(db: CanvasDb): Promise<PackagesReport>;
@@ -1 +1 @@
1
- var a=Object.defineProperty;var p=(o,t)=>a(o,"name",{value:t,configurable:!0});import{appPlugins as u}from"../plugin-app.js";import{ensurePluginAppToken as f,listScopedApiTokens as g,revokePluginAppTokens as l}from"../secrets.js";import{reconcilePackageKinds as m}from"./package-kinds.js";import{reconcilePackageDocuments as d}from"./package-docs.js";function S(o){const t=d(o),i=m(o),s={granted:[],revoked:[]},r=new Set;for(const e of u()){const n=e.manifest.scopes??[];f(e.name,n),r.add(e.name),s.granted.push({plugin:e.name,scopes:[...n]})}const c=new Set;for(const e of g("user")){if(!e.token.startsWith("crtr_app_")||!e.grantee.startsWith("app:"))continue;const n=e.grantee.slice(4);r.has(n)||c.add(n)}for(const e of c)l(e)&&s.revoked.push(e);return{...t,kinds:i,tokens:s}}p(S,"reconcilePackages");export{S as reconcilePackages};
1
+ var p=Object.defineProperty;var a=(o,t)=>p(o,"name",{value:t,configurable:!0});import{appPlugins as u}from"../plugin-app.js";import{ensurePluginAppToken as f,listScopedApiTokens as g,revokePluginAppTokens as l}from"../secrets.js";import{reconcilePackageKinds as m}from"./package-kinds.js";import{reconcilePackageDocuments as d}from"./package-docs.js";async function A(o){const t=await d(o),i=await m(o),s={granted:[],revoked:[]},r=new Set;for(const e of u()){const n=e.manifest.scopes??[];f(e.name,n),r.add(e.name),s.granted.push({plugin:e.name,scopes:[...n]})}const c=new Set;for(const e of g("user")){if(!e.token.startsWith("crtr_app_")||!e.grantee.startsWith("app:"))continue;const n=e.grantee.slice(4);r.has(n)||c.add(n)}for(const e of c)l(e)&&s.revoked.push(e);return{...t,kinds:i,tokens:s}}a(A,"reconcilePackages");export{A as reconcilePackages};
@@ -1,43 +1,43 @@
1
- import type { DatabaseSync } from 'node:sqlite';
2
1
  import type { RequestPrincipal } from '../../daemon/api/router.js';
3
2
  import { type ActiveGrant } from '../grants/mirror.js';
3
+ import { type CanvasDb } from '../canvas/db.js';
4
4
  import type { Checkout, ObjectRow, Reader } from './types.js';
5
5
  /** The repos enclosing a directory, with their checkout roots, nearest first. */
6
- export type ReposFn = (cwd: string) => Checkout[];
6
+ export type ReposFn = (cwd: string) => Promise<Checkout[]>;
7
7
  /** A node's view of repos: the ones enclosing its cwd, then those of each project path of its profile
8
8
  * (manifest order), each repo once. A project path that no longer exists, is not in a repo, or has no
9
9
  * work tree (a bare repository) contributes nothing. */
10
- export declare function viewRepos(cwd: string, profileId: string | null, reposFn: ReposFn, lookups: Pick<ReaderLookups, 'projectPaths'>): Pick<Extract<Reader, {
10
+ export declare function viewRepos(cwd: string, profileId: string | null, reposFn: ReposFn, lookups: Pick<ReaderLookups, 'projectPaths'>): Promise<Pick<Extract<Reader, {
11
11
  class: 'node';
12
- }>, 'repos' | 'checkouts' | 'projectRepos' | 'projectCheckouts'>;
13
- export declare function readerFor(db: DatabaseSync, principal: RequestPrincipal, reposFn: ReposFn): Exclude<Reader, {
12
+ }>, 'repos' | 'checkouts' | 'projectRepos' | 'projectCheckouts'>>;
13
+ export declare function readerFor(db: CanvasDb, principal: RequestPrincipal, reposFn: ReposFn): Promise<Exclude<Reader, {
14
14
  class: 'object';
15
- }>;
16
- export declare function readerForNode(db: DatabaseSync, nodeId: string, reposFn: ReposFn, lookups?: ReaderLookups, allowRevoked?: boolean): Extract<Reader, {
15
+ }>>;
16
+ export declare function readerForNode(db: CanvasDb, nodeId: string, reposFn: ReposFn, lookups?: ReaderLookups, allowRevoked?: boolean): Promise<Extract<Reader, {
17
17
  class: 'node';
18
- }>;
18
+ }>>;
19
19
  /** A receiving object reads using its owner's app grant, not its registering caller's rights. */
20
- export declare function readerForObject(db: DatabaseSync, watcher: ObjectRow, reposFn?: ReposFn, lookups?: ReaderLookups): Extract<Reader, {
20
+ export declare function readerForObject(db: CanvasDb, watcher: ObjectRow, reposFn?: ReposFn, lookups?: ReaderLookups): Promise<Extract<Reader, {
21
21
  class: 'node' | 'object';
22
- }>;
22
+ }>>;
23
23
  /** The scopes `app` (an app object) holds now: its one active grant's always-scopes, or a local plugin's `crtr_app_` token scopes when it has no
24
24
  * grant; null for several grants or none that applies. The same rule as an app-owned object's reader (`readerForObject`). */
25
- export declare function appScopesNow(db: DatabaseSync, app: ObjectRow, lookups: ReaderLookups): readonly string[] | null;
25
+ export declare function appScopesNow(db: CanvasDb, app: ObjectRow, lookups: ReaderLookups): Promise<readonly string[] | null>;
26
26
  /** What building a node reader looks up besides the node's own row. `liveLookups` reads each
27
27
  * one per call; `publishLookups` memoizes them for one publish inside its transaction, so the
28
28
  * readers of one event share a single config read and one lookup per grant, owner and
29
29
  * profile. Never keep a memoized one past that transaction. */
30
30
  export interface ReaderLookups {
31
- grantById(grantId: string): ActiveGrant | null;
32
- grantFor(app: string, sub: string): ActiveGrant | null;
31
+ grantById(grantId: string): Promise<ActiveGrant | null>;
32
+ grantFor(app: string, sub: string): Promise<ActiveGrant | null>;
33
33
  terminalHasIssuer(): boolean;
34
34
  /** The scopes of the `crtr_app_` token a local plugin's app (`app:<plugin>`) holds, or null when it holds none. */
35
35
  pluginScopes(grantee: string): readonly string[] | null;
36
- object(rowid: number): ObjectRow | null;
37
- profile(profileId: string, app: ObjectRow): ObjectRow;
36
+ object(rowid: number): Promise<ObjectRow | null>;
37
+ profile(profileId: string, app: ObjectRow): Promise<ObjectRow>;
38
38
  /** The profile's project paths in manifest order; none in a sandboxed node, whose profile store is unreadable. */
39
39
  projectPaths(profileId: string): readonly string[];
40
40
  }
41
- export declare function liveLookups(db: DatabaseSync): ReaderLookups;
42
- export declare function publishLookups(db: DatabaseSync): ReaderLookups;
43
- export declare function profileObject(db: DatabaseSync, profileId: string, app: ObjectRow): ObjectRow;
41
+ export declare function liveLookups(db: CanvasDb): ReaderLookups;
42
+ export declare function publishLookups(db: CanvasDb): ReaderLookups;
43
+ export declare function profileObject(db: CanvasDb, profileId: string, app: ObjectRow): Promise<ObjectRow>;
@@ -1,3 +1,3 @@
1
- var C=Object.defineProperty;var p=(o,e)=>C(o,"name",{value:e,configurable:!0});import{prepared as f}from"../sqlite-statements.js";import{coveredByAny as m,isSandboxedNode as L}from"../../shared/env.js";import{existsSync as A}from"node:fs";import{CrtrError as b}from"../errors.js";import{getStoredProfile as $}from"../scoped-state/profiles.js";import{userScopeRoot as M}from"../scope.js";import{parseScope as O}from"@north-light/identity";import{activeGrant as v,grantFor as N}from"../grants/mirror.js";import{prepared as F}from"../canvas/db.js";import{ApiError as T}from"../../api/errors.js";import{readConfig as W}from"../config.js";import{pluginAppToken as D}from"../secrets.js";import{SCOPE_VOCABULARY as E}from"../scopes.js";import{loadExactProfileManifest as B}from"../profiles/manifest.js";import{ensureOwner as S,getByRowid as P,nodeObject as I}from"./objects.js";function x(o,e,t,s){const r=e===null?[]:s.projectPaths(e),n=t(o),c=new Set(n.map(a=>a.repo.rowid)),l=[];for(const a of r){if(!A(a))continue;let u;try{u=t(a)}catch(i){if(i instanceof b&&i.code==="git-lookup-failed")continue;throw i}for(const i of u)c.has(i.repo.rowid)||(c.add(i.repo.rowid),l.push(i))}return{repos:n.map(a=>a.repo),checkouts:n,projectRepos:l.map(a=>a.repo),projectCheckouts:l}}p(x,"viewRepos");function ae(o,e,t){if(e.class==="anonymous")throw new Error("a publish token cannot read as a principal");if(e.class==="person")return{class:"person",person:g(o)};if(e.class==="app")return{class:"app",app:j(o,e.app),scopes:e.scopes};if(e.class==="machine")throw new Error("a machine token cannot read as a principal");if(e.class==="forwarded"){if(e.actor.kind==="person")return{class:"person",person:g(o)};const l=N(e.actor.app,e.sub);if(!l)throw new T(403,"app_not_granted",`${e.actor.app} holds no active grant for ${e.sub} on this machine`);const a=e.actor.node_scopes;return{class:"app",app:j(o,e.actor.app),place:e.actor.place,launched:a,scopes:a===null?l.resolved:a.filter(u=>m(l.resolved,u))}}if(e.class==="cron"){const l=e.grant?v(e.grant)?.resolved??[]:E,a=e.scopes;return{class:"app",app:j(o,e.app),scopes:a===null?l:a.filter(u=>m(l,u)),launched:a,place:{run:e.origin_run??"",isolated:e.isolated}}}const s=w(o),r=I(o,e.node),n=r.owner===null?null:s.object(r.owner);if(!n)throw new Error(`node ${e.node} has no owner`);const c=f(o,"SELECT cwd, profile_id FROM nodes WHERE node_id = ?").get(e.node);return{class:"node",node:r,app:n,scopes:H(e.app,e.sub,e.grant,e.scopes,s),launched:e.scopes,cwd:c.cwd,...x(c.cwd,c.profile_id,t,s),profile:c.profile_id===null?null:s.profile(c.profile_id,n)}}p(ae,"readerFor");function J(o,e,t,s=w(o),r=!1){const n=F(o,"SELECT o.* FROM objects o WHERE o.id = ? AND o.type = 'node'").get(e),c=F(o,`SELECT (SELECT external_id FROM identities WHERE object = ?) AS grantee,
2
- sub, grant_id, scopes_json, cwd, profile_id FROM nodes WHERE node_id = ?`).get(n?.owner??null,e);if(!n||!c)throw new Error(`no node ${e}`);const{grantee:l,sub:a,grant_id:u,scopes_json:i,cwd:d,profile_id:h}=c,_=n.owner===null?null:s.object(n.owner);if(!_)throw new Error(`node ${e} has no owner`);const R=i===null?null:JSON.parse(i);return{class:"node",node:n,app:_,scopes:H(l,a??"",u,R,s,r),launched:R,cwd:d,...x(d,h,t,s),profile:h===null?null:s.profile(h,_)}}p(J,"readerForNode");function pe(o,e,t=()=>[],s=w(o)){const r=f(o,"SELECT envelope_json FROM peer_stubs WHERE object = ?").get(e.rowid);if(r!==void 0)return y(o,e,r.envelope_json===null?null:JSON.parse(r.envelope_json),s);if(e.type==="node")return J(o,e.id,t,s,!0);const n=e.owner===null?null:s.object(e.owner);if(!n)throw new Error(`watcher ${e.id} has no owner`);const l=(n.type==="app"?n:n.type==="profile"&&n.owner!==null?s.object(n.owner):null)??f(o,"SELECT o.* FROM identities i JOIN objects o ON o.rowid = i.object WHERE i.external_id = 'app:terminal' AND i.scheme = 'app'").get()??f(o,"SELECT * FROM objects WHERE type = 'person' AND name = 'user' AND home_machine IS NULL").get();if(!l)throw new Error("no terminal app or person object");const a=f(o,"SELECT external_id FROM identities WHERE object = ? AND scheme = 'app'").get(l.rowid)?.external_id??"app:terminal",u=f(o,"SELECT resolved_scopes_json FROM grants WHERE grantee = ? AND status = 'active'").all(a),i=n.type==="person"?null:u.length===0?a==="app:terminal"&&!s.terminalHasIssuer()?E:s.pluginScopes(a):u.length===1?JSON.parse(u[0].resolved_scopes_json).filter(d=>d.mode==="always").map(d=>O(d.scope)):null;return{class:"object",object:e,node:e,owner:n,app:l,scopes:i,repos:n.type==="repo"?[n]:[]}}p(pe,"readerForObject");function le(o,e,t){const s=f(o,"SELECT external_id FROM identities WHERE object = ? AND scheme = 'app'").get(e.rowid)?.external_id;if(s===void 0)return null;const r=f(o,"SELECT resolved_scopes_json FROM grants WHERE grantee = ? AND status = 'active'").all(s);return r.length===0?s==="app:terminal"&&!t.terminalHasIssuer()?E:t.pluginScopes(s):r.length>1?null:JSON.parse(r[0].resolved_scopes_json).filter(n=>n.mode==="always").map(n=>O(n.scope))}p(le,"appScopesNow");function y(o,e,t,s){const r=g(o);if(t!==null&&t.app===null)return{class:"object",object:e,node:e,owner:r,app:r,scopes:null,repos:[]};const n=t?.app==null?null:j(o,t.app),c=t?.app==null?null:s.grantFor(t.app,t.sub),l=t===null||c===null?null:t.node_scopes===null?c.resolved:t.node_scopes.filter(u=>m(c.resolved,u)),a=n??(e.owner===null?r:s.object(e.owner)??r);return{class:"object",object:e,node:e,owner:a,app:a,scopes:l,launched:t?.node_scopes??null,repos:[],...t?.place==null?{}:{place:t.place}}}p(y,"readerForStub");function w(o){return{grantById:v,grantFor:N,terminalHasIssuer:p(()=>!!W("user").runtime?.issuer,"terminalHasIssuer"),pluginScopes:p(e=>D(e.replace(/^app:/,""))?.scopes??null,"pluginScopes"),object:p(e=>P(o,e),"object"),profile:p((e,t)=>U(o,e,t),"profile"),projectPaths:p(e=>L()?[]:$(M(),e)?.manifest.projects.map(t=>t.path)??[],"projectPaths")}}p(w,"liveLookups");function ce(o){const e=w(o),t=new Map,s=p((r,n)=>(t.has(r)||t.set(r,n()),t.get(r)),"memo");return{grantById:p(r=>s(`g\0${r}`,()=>e.grantById(r)),"grantById"),grantFor:p((r,n)=>s(`a\0${r}\0${n}`,()=>e.grantFor(r,n)),"grantFor"),terminalHasIssuer:p(()=>s("issuer",()=>e.terminalHasIssuer()),"terminalHasIssuer"),pluginScopes:p(r=>s(`t\0${r}`,()=>e.pluginScopes(r)),"pluginScopes"),object:p(r=>s(`o\0${r}`,()=>e.object(r)),"object"),profile:p((r,n)=>s(`p\0${r}\0${n.rowid}`,()=>e.profile(r,n)),"profile"),projectPaths:p(r=>s(`j\0${r}`,()=>e.projectPaths(r)),"projectPaths")}}p(ce,"publishLookups");function H(o,e,t,s,r,n=!1){const c=t?r.grantById(t):r.grantFor(o,e),l=c&&c.grantee===o?c.resolved:o==="app:terminal"&&!r.terminalHasIssuer()?E:null;if(l===null){if(n)return null;throw new Error(`the grant of ${o} is not active`)}return s===null?l:s.filter(a=>m(l,a))}p(H,"nodeScopes");function g(o){return S(o,"person","local-user","user:local","user")}p(g,"personObject");function j(o,e){return e==="user:local"?g(o):S(o,"app","app",e,e.replace(/^app:/,""))}p(j,"appObject");function U(o,e,t){return f(o,`SELECT o.* FROM identities i JOIN objects o ON o.rowid = i.object
3
- WHERE i.scheme = 'profile' AND i.external_id = ?`).get(e)??S(o,"profile","profile",e,B(e).manifest.name,t)}p(U,"profileObject");export{le as appScopesNow,w as liveLookups,U as profileObject,ce as publishLookups,ae as readerFor,J as readerForNode,pe as readerForObject,x as viewRepos};
1
+ var F=Object.defineProperty;var p=(o,e)=>F(o,"name",{value:e,configurable:!0});import{coveredByAny as f,isSandboxedNode as x}from"../../shared/env.js";import{existsSync as H}from"node:fs";import{CrtrError as C}from"../errors.js";import{getStoredProfile as L}from"../scoped-state/profiles.js";import{userScopeRoot as A}from"../scope.js";import{parseScope as R}from"@north-light/identity";import{activeGrant as O,grantFor as v}from"../grants/mirror.js";import{ApiError as b}from"../../api/errors.js";import{readConfig as $}from"../config.js";import{pluginAppToken as M}from"../secrets.js";import{SCOPE_VOCABULARY as d}from"../scopes.js";import{loadExactProfileManifest as T}from"../profiles/manifest.js";import{ensureOwner as _,getByRowid as W,nodeObject as D}from"./objects.js";async function y(o,e,t,a){const r=e===null?[]:a.projectPaths(e),n=await t(o),l=new Set(n.map(s=>s.repo.rowid)),c=[];for(const s of r){if(!H(s))continue;let i;try{i=await t(s)}catch(u){if(u instanceof C&&u.code==="git-lookup-failed")continue;throw u}for(const u of i)l.has(u.repo.rowid)||(l.add(u.repo.rowid),c.push(u))}return{repos:n.map(s=>s.repo),checkouts:n,projectRepos:c.map(s=>s.repo),projectCheckouts:c}}p(y,"viewRepos");async function re(o,e,t){if(e.class==="anonymous")throw new Error("a publish token cannot read as a principal");if(e.class==="person")return{class:"person",person:await E(o)};if(e.class==="app")return{class:"app",app:await g(o,e.app),scopes:e.scopes};if(e.class==="machine")throw new Error("a machine token cannot read as a principal");if(e.class==="forwarded"){if(e.actor.kind==="person")return{class:"person",person:await E(o)};const c=await v(e.actor.app,e.sub);if(!c)throw new b(403,"app_not_granted",`${e.actor.app} holds no active grant for ${e.sub} on this machine`);const s=e.actor.node_scopes;return{class:"app",app:await g(o,e.actor.app),place:e.actor.place,launched:s,scopes:s===null?c.resolved:s.filter(i=>f(c.resolved,i))}}if(e.class==="cron"){const c=e.grant?(await O(e.grant))?.resolved??[]:d,s=e.scopes;return{class:"app",app:await g(o,e.app),scopes:s===null?c:s.filter(i=>f(c,i)),launched:s,place:{run:e.origin_run??"",isolated:e.isolated}}}const a=m(o),r=await D(o,e.node),n=r.owner===null?null:await a.object(r.owner);if(!n)throw new Error(`node ${e.node} has no owner`);const l=await o.prepare("SELECT cwd, profile_id FROM nodes WHERE node_id = ?").get(e.node);return{class:"node",node:r,app:n,scopes:await N(e.app,e.sub,e.grant,e.scopes,a),launched:e.scopes,cwd:l.cwd,...await y(l.cwd,l.profile_id,t,a),profile:l.profile_id===null?null:await a.profile(l.profile_id,n)}}p(re,"readerFor");async function B(o,e,t,a=m(o),r=!1){const n=await o.prepare("SELECT o.* FROM objects o WHERE o.id = ? AND o.type = 'node'").get(e),l=await o.prepare(`SELECT (SELECT external_id FROM identities WHERE object = ?) AS grantee,
2
+ sub, grant_id, scopes_json, cwd, profile_id FROM nodes WHERE node_id = ?`).get(n?.owner??null,e);if(!n||!l)throw new Error(`no node ${e}`);const{grantee:c,sub:s,grant_id:i,scopes_json:u,cwd:w,profile_id:j}=l,h=n.owner===null?null:await a.object(n.owner);if(!h)throw new Error(`node ${e} has no owner`);const S=u===null?null:JSON.parse(u);return{class:"node",node:n,app:h,scopes:await N(c,s??"",i,S,a,r),launched:S,cwd:w,...await y(w,j,t,a),profile:j===null?null:await a.profile(j,h)}}p(B,"readerForNode");async function ne(o,e,t=async()=>[],a=m(o)){const r=await o.prepare("SELECT envelope_json FROM peer_stubs WHERE object = ?").get(e.rowid);if(r!==void 0)return await P(o,e,r.envelope_json===null?null:JSON.parse(r.envelope_json),a);if(e.type==="node")return await B(o,e.id,t,a,!0);const n=e.owner===null?null:await a.object(e.owner);if(!n)throw new Error(`watcher ${e.id} has no owner`);const c=(n.type==="app"?n:n.type==="profile"&&n.owner!==null?await a.object(n.owner):null)??await o.prepare("SELECT o.* FROM identities i JOIN objects o ON o.rowid = i.object WHERE i.external_id = 'app:terminal' AND i.scheme = 'app'").get()??await o.prepare("SELECT * FROM objects WHERE type = 'person' AND name = 'user' AND home_machine IS NULL").get();if(!c)throw new Error("no terminal app or person object");const s=(await o.prepare("SELECT external_id FROM identities WHERE object = ? AND scheme = 'app'").get(c.rowid))?.external_id??"app:terminal",i=await o.prepare("SELECT resolved_scopes_json FROM grants WHERE grantee = ? AND status = 'active'").all(s),u=n.type==="person"?null:i.length===0?s==="app:terminal"&&!a.terminalHasIssuer()?d:a.pluginScopes(s):i.length===1?JSON.parse(i[0].resolved_scopes_json).filter(w=>w.mode==="always").map(w=>R(w.scope)):null;return{class:"object",object:e,node:e,owner:n,app:c,scopes:u,repos:n.type==="repo"?[n]:[]}}p(ne,"readerForObject");async function te(o,e,t){const a=(await o.prepare("SELECT external_id FROM identities WHERE object = ? AND scheme = 'app'").get(e.rowid))?.external_id;if(a===void 0)return null;const r=await o.prepare("SELECT resolved_scopes_json FROM grants WHERE grantee = ? AND status = 'active'").all(a);return r.length===0?a==="app:terminal"&&!t.terminalHasIssuer()?d:t.pluginScopes(a):r.length>1?null:JSON.parse(r[0].resolved_scopes_json).filter(n=>n.mode==="always").map(n=>R(n.scope))}p(te,"appScopesNow");async function P(o,e,t,a){const r=await E(o);if(t!==null&&t.app===null)return{class:"object",object:e,node:e,owner:r,app:r,scopes:null,repos:[]};const n=t?.app==null?null:await g(o,t.app),l=t?.app==null?null:await a.grantFor(t.app,t.sub),c=t===null||l===null?null:t.node_scopes===null?l.resolved:t.node_scopes.filter(i=>f(l.resolved,i)),s=n??(e.owner===null?r:await a.object(e.owner)??r);return{class:"object",object:e,node:e,owner:s,app:s,scopes:c,launched:t?.node_scopes??null,repos:[],...t?.place==null?{}:{place:t.place}}}p(P,"readerForStub");function m(o){return{grantById:O,grantFor:v,terminalHasIssuer:p(()=>!!$("user").runtime?.issuer,"terminalHasIssuer"),pluginScopes:p(e=>M(e.replace(/^app:/,""))?.scopes??null,"pluginScopes"),object:p(async e=>await W(o,e),"object"),profile:p(async(e,t)=>await I(o,e,t),"profile"),projectPaths:p(e=>x()?[]:L(A(),e)?.manifest.projects.map(t=>t.path)??[],"projectPaths")}}p(m,"liveLookups");function ae(o){const e=m(o),t=new Map,a=p((r,n)=>(t.has(r)||t.set(r,n()),t.get(r)),"memo");return{grantById:p(r=>a(`g\0${r}`,()=>e.grantById(r)),"grantById"),grantFor:p((r,n)=>a(`a\0${r}\0${n}`,()=>e.grantFor(r,n)),"grantFor"),terminalHasIssuer:p(()=>a("issuer",()=>e.terminalHasIssuer()),"terminalHasIssuer"),pluginScopes:p(r=>a(`t\0${r}`,()=>e.pluginScopes(r)),"pluginScopes"),object:p(async r=>await a(`o\0${r}`,async()=>await e.object(r)),"object"),profile:p(async(r,n)=>await a(`p\0${r}\0${n.rowid}`,async()=>await e.profile(r,n)),"profile"),projectPaths:p(r=>a(`j\0${r}`,()=>e.projectPaths(r)),"projectPaths")}}p(ae,"publishLookups");async function N(o,e,t,a,r,n=!1){const l=t?await r.grantById(t):await r.grantFor(o,e),c=l&&l.grantee===o?l.resolved:o==="app:terminal"&&!r.terminalHasIssuer()?d:null;if(c===null){if(n)return null;throw new Error(`the grant of ${o} is not active`)}return a===null?c:a.filter(s=>f(c,s))}p(N,"nodeScopes");async function E(o){return await _(o,"person","local-user","user:local","user")}p(E,"personObject");async function g(o,e){return e==="user:local"?await E(o):await _(o,"app","app",e,e.replace(/^app:/,""))}p(g,"appObject");async function I(o,e,t){return await o.prepare(`SELECT o.* FROM identities i JOIN objects o ON o.rowid = i.object
3
+ WHERE i.scheme = 'profile' AND i.external_id = ?`).get(e)??await _(o,"profile","profile",e,T(e).manifest.name,t)}p(I,"profileObject");export{te as appScopesNow,m as liveLookups,I as profileObject,ae as publishLookups,re as readerFor,B as readerForNode,ne as readerForObject,y as viewRepos};
@@ -1,5 +1,5 @@
1
- import type { DatabaseSync } from 'node:sqlite';
2
1
  import type { ObjectRow, Level, ListenDelivery } from './types.js';
2
+ import type { CanvasDb } from '../canvas/db.js';
3
3
  export interface ReceiverDestination {
4
4
  id: string;
5
5
  reception: 1 | 2;
@@ -16,13 +16,13 @@ export interface ReceivedMessage {
16
16
  }
17
17
  export interface Receiver {
18
18
  bodyOwner(destinations: readonly ReceiverDestination[]): string | null;
19
- enqueue(db: DatabaseSync, message: ReceivedMessage, destinations: readonly ReceiverDestination[]): void;
19
+ enqueue(db: CanvasDb, message: ReceivedMessage, destinations: readonly ReceiverDestination[]): Promise<void>;
20
20
  }
21
21
  export type ReceiverName = 'inbox' | 'argv' | 'url' | 'queue' | 'peer';
22
22
  /** The receiver is per instance, not per kind. An action's historical argv JSON is unchanged. */
23
- export declare function receiverForObject(db: DatabaseSync, object: ObjectRow): ReceiverName | undefined;
23
+ export declare function receiverForObject(db: CanvasDb, object: ObjectRow): Promise<ReceiverName | undefined>;
24
24
  export declare const BACKLOG_CAP = 1000;
25
- export declare function onQueueSignal(objectId: string, cb: () => void): () => void;
25
+ export declare function onQueueSignal(objectId: string, cb: () => void): Promise<() => void>;
26
26
  export declare function signalQueue(id: string): void;
27
27
  export declare const argvReceiver: Receiver;
28
28
  export declare const RECEIVERS: Readonly<Record<ReceiverName, Receiver>>;
@@ -1,7 +1,7 @@
1
- var f=Object.defineProperty;var i=(e,t)=>f(e,"name",{value:t,configurable:!0});import{prepared as o}from"../sqlite-statements.js";import{randomBytes as p}from"node:crypto";import{nodeInbox as g}from"./kinds/node.js";import{peerReceiver as _}from"../peer/receiver.js";function N(e,t){const r=o(e,"SELECT receiver_json FROM custom_objects WHERE object = ?").get(t.rowid);if(!r?.receiver_json)return;const n=JSON.parse(r.receiver_json);if(n==="queue")return"queue";if(n&&typeof n=="object"&&!Array.isArray(n)){if("url"in n)return"url";if("argv"in n)return"argv"}}i(N,"receiverForObject");const E=1e3,a=new Map;function w(e,t){const r=a.get(e)??new Set;return r.add(t),a.set(e,r),()=>{r.delete(t),r.size===0&&a.delete(e)}}i(w,"onQueueSignal");function m(e){setImmediate(()=>{for(const t of a.get(e)??[])t()})}i(m,"signalQueue");function R(e,t){const r=o(e,`SELECT COUNT(*) AS n FROM deliveries WHERE destination_id = ?
2
- AND state = 'pending' AND canceled_at IS NULL`).get(t).n;if(r<=E)return;const n=o(e,`SELECT delivery_id, message_id FROM deliveries
1
+ var p=Object.defineProperty;var i=(e,r)=>p(e,"name",{value:r,configurable:!0});import{randomBytes as l}from"node:crypto";import{nodeInbox as f}from"./kinds/node.js";import{peerReceiver as g}from"../peer/receiver.js";async function T(e,r){const t=await e.prepare("SELECT receiver_json FROM custom_objects WHERE object = ?").get(r.rowid);if(!t?.receiver_json)return;const n=JSON.parse(t.receiver_json);if(n==="queue")return"queue";if(n&&typeof n=="object"&&!Array.isArray(n)){if("url"in n)return"url";if("argv"in n)return"argv"}}i(T,"receiverForObject");const u=1e3,s=new Map;async function y(e,r){const t=s.get(e)??new Set;return t.add(r),s.set(e,t),()=>{t.delete(r),t.size===0&&s.delete(e)}}i(y,"onQueueSignal");function _(e){setImmediate(()=>{for(const r of s.get(e)??[])r()})}i(_,"signalQueue");async function R(e,r){const t=(await e.prepare(`SELECT COUNT(*) AS n FROM deliveries WHERE destination_id = ?
2
+ AND state = 'pending' AND canceled_at IS NULL`).get(r)).n;if(t<=u)return;const n=await e.prepare(`SELECT delivery_id, message_id FROM deliveries
3
3
  WHERE destination_id = ? AND state = 'pending' AND canceled_at IS NULL
4
- ORDER BY created_at, rowid LIMIT ?`).all(t,r-E);for(const s of n)o(e,"DELETE FROM deliveries WHERE delivery_id = ?").run(s.delivery_id),o(e,"DELETE FROM messages WHERE message_id = ? AND NOT EXISTS (SELECT 1 FROM deliveries WHERE message_id = ?)").run(s.message_id,s.message_id);n.length&&o(e,`UPDATE custom_objects SET dropped = dropped + ? WHERE object =
5
- (SELECT rowid FROM objects WHERE id = ?)`).run(n.length,t)}i(R,"cap");function c(e,t){return{bodyOwner:i(()=>null,"bodyOwner"),enqueue(r,n,s){const d=Date.now(),l=o(r,`INSERT INTO deliveries
4
+ ORDER BY created_at, rowid LIMIT ?`).all(r,t-u);for(const a of n)await e.prepare("DELETE FROM deliveries WHERE delivery_id = ?").run(a.delivery_id),await e.prepare("DELETE FROM messages WHERE message_id = ? AND NOT EXISTS (SELECT 1 FROM deliveries WHERE message_id = ?)").run(a.message_id,a.message_id);n.length&&await e.prepare(`UPDATE custom_objects SET dropped = dropped + ? WHERE object =
5
+ (SELECT rowid FROM objects WHERE id = ?)`).run(n.length,r)}i(R,"cap");function c(e,r){return{bodyOwner:i(()=>null,"bodyOwner"),async enqueue(t,n,a){const o=Date.now(),E=t.prepare(`INSERT INTO deliveries
6
6
  (delivery_id, message_id, destination_id, urgency, wake, state, next_attempt_at, created_at, updated_at)
7
- VALUES (?, ?, ?, 'normal', 0, 'pending', ?, ?, ?)`);for(const u of s)l.run(p(16).toString("hex"),n.messageId,u.id,e?d:null,d,d),R(r,u.id),t&&m(u.id)}}}i(c,"pushReceiver");const v=c(!0,!1),x={inbox:g,argv:v,url:c(!0,!1),queue:c(!1,!0),peer:_};export{E as BACKLOG_CAP,x as RECEIVERS,v as argvReceiver,w as onQueueSignal,N as receiverForObject,m as signalQueue};
7
+ VALUES (?, ?, ?, 'normal', 0, 'pending', ?, ?, ?)`);for(const d of a)await E.run(l(16).toString("hex"),n.messageId,d.id,e?o:null,o,o),await R(t,d.id),r&&_(d.id)}}}i(c,"pushReceiver");const m=c(!0,!1),L={inbox:f,argv:m,url:c(!0,!1),queue:c(!1,!0),peer:g};export{u as BACKLOG_CAP,L as RECEIVERS,m as argvReceiver,y as onQueueSignal,T as receiverForObject,_ as signalQueue};
@@ -1,10 +1,6 @@
1
- /** The canvas side of repo sync: export a repo space's public documents to `refs/crtr/docs`
2
- * tree files, and import a changed tree back into canvas.db. Export only reads; import only
3
- * adds revisions (never drops one) and publishes `created`, `edited` and `deleted` with a
4
- * null actor, since the act happened on another runtime. */
5
- import type { DatabaseSync } from 'node:sqlite';
6
1
  import type { ReposFn } from '../reader.js';
7
2
  import type { ObjectRow } from '../types.js';
3
+ import { type CanvasDb } from '../../canvas/db.js';
8
4
  /**
9
5
  * The tree (path → file text) of every public document the repo space owns, deleted ones
10
6
  * included. A revision already in `previous` is copied verbatim, so a remote author and the
@@ -12,7 +8,7 @@ import type { ObjectRow } from '../types.js';
12
8
  * a head carries the document's current `links-to` edges. `carry` names paths of `previous` that
13
9
  * are copied through untouched (files whose import was refused and is still pending).
14
10
  */
15
- export declare function exportRepo(db: DatabaseSync, repo: ObjectRow, previous: Map<string, string> | null, imported?: Map<string, string> | null): Map<string, string>;
11
+ export declare function exportRepo(db: CanvasDb, repo: ObjectRow, previous: Map<string, string> | null, imported?: Map<string, string> | null): Promise<Map<string, string>>;
16
12
  /** Paths of `tree` whose text differs from the baseline last imported: files that arrived but
17
13
  * have not landed in canvas.db. */
18
14
  export declare function pendingPaths(tree: Map<string, string> | null, imported: Map<string, string> | null): string[];
@@ -35,6 +31,6 @@ export interface ImportResult {
35
31
  * publishes once: `created`, `edited` (with `heads` and `needs_merge`) or `deleted`. A
36
32
  * document that fails is rolled back alone and reported in `refused`.
37
33
  */
38
- export declare function importTree(db: DatabaseSync, repo: ObjectRow, before: Map<string, string>, after: Map<string, string>, reposFn?: ReposFn): ImportResult;
34
+ export declare function importTree(db: CanvasDb, repo: ObjectRow, before: Map<string, string>, after: Map<string, string>, reposFn?: ReposFn): Promise<ImportResult>;
39
35
  /** Whether any link target in a serialized ref file is one of `arrived`. */
40
36
  export declare function namesArrived(text: string, arrived: ReadonlySet<string>): boolean;
@@ -1,2 +1,2 @@
1
- var H=Object.defineProperty;var p=(t,i)=>H(t,"name",{value:i,configurable:!0});import{prepared as g}from"../../sqlite-statements.js";import{get as W,put as P}from"../bodies.js";import{setLinks as J,setUnresolved as U}from"../edges.js";import{collectUnlinked as Y,deleteDocument as M,documentRecord as C,heads as D,importDocument as z,insertImportedRevisions as K,moveDocument as V,restoreDocument as G,setDocumentRecord as q}from"../documents.js";import{CrtrError as F}from"../../errors.js";import{publish as T}from"../events.js";import{getById as x,getByRowid as N,setObjectKind as Q}from"../objects.js";import{rulesOf as X}from"../rules.js";import{SPACES as Z}from"../spaces/index.js";import{docPath as b,mergeDoc as ee,parseDoc as y,serializeDoc as $}from"./ref-format.js";function L(t){const i=Z[t.type];if(t.owner!==null||!i||i.sync!=="repo-ref")throw new Error(`${t.type} ${t.id} is not a space that syncs through a repo ref`)}p(L,"assertRepoRefSpace");function te(t){const i=new Map;for(const[o,n]of t??[]){const _=y(o,n);_.ok&&i.set(_.doc.id,_.doc)}return i}p(te,"parseMap");function Oe(t,i,o,n=null){L(i);const _=te(o),m=g(t,"SELECT * FROM objects WHERE type = 'document' AND owner = ? AND privacy = 'public' ORDER BY rowid").all(i.rowid),l=g(t,"SELECT rowid, rev_id, number, body_hash, author, rationale, created_at FROM revisions WHERE document = ? ORDER BY number, rev_id"),v=g(t,"SELECT p.rev_id FROM revision_parents rp JOIN revisions p ON p.rowid = rp.parent WHERE rp.child = ?"),r=g(t,`SELECT e.written_as, o.id FROM edges e JOIN objects o ON o.rowid = e.dst
2
- WHERE e.type = 'links-to' AND e.src = ? ORDER BY e.written_as, o.id`),a=new Map;for(const e of m){const d=C(t,e),c=new Map((_.get(e.id)?.revisions??[]).map(s=>[s.rev_id,s])),h=new Set(D(t,e).map(s=>s.rev_id)),w=r.all(e.rowid).map(s=>({written_as:s.written_as??"",dst:s.id})),R=l.all(e.rowid).map(s=>c.get(s.rev_id)??{rev_id:s.rev_id,number:s.number,parents:v.all(s.rowid).map(O=>O.rev_id),body:W(s.body_hash),body_hash:s.body_hash,author:s.author===null?null:N(t,s.author)?.id??null,rationale:s.rationale,created_at:s.created_at,links:h.has(s.rev_id)?w:[]});if(R.length===0)continue;const E=X(t,e).map(s=>({position:s.position,on:s.on,match:s.match??null,match_frontmatter:s.matchFrontmatter??null,if:s.if??null,deliver:s.deliver})),A={id:e.id,name:e.name,kind:e.kind??"document",privacy:"public",preview:e.preview,summary:d.summary,why_it_exists:d.why_it_exists,unlisted:d.unlisted,lint_ignore:d.lint_ignore,extensions:d.extensions,created_at:e.created_at,deleted_at:e.deleted_at,rules:E,revisions:R};a.set(b(e.id),$(A))}for(const e of ne(o,n)){const d=o.get(e),c=a.get(e);if(c===void 0){a.set(e,d);continue}const h=y(e,d),w=y(e,c);if(!h.ok){a.set(e,d);continue}if(!w.ok)continue;const R=n?.has(e)?y(e,n.get(e)):null,E=ee(R?.ok?R.doc:null,w.doc,h.doc);E&&a.set(e,$(E))}return a}p(Oe,"exportRepo");function ne(t,i){return[...t??[]].filter(([o,n])=>i?.get(o)!==n).map(([o])=>o)}p(ne,"pendingPaths");function ie(t){return[...t].sort((i,o)=>i.position-o.position).map(i=>({on:i.on,deliver:i.deliver,...i.match!==null&&i.match!==void 0?{match:i.match}:{},...i.match_frontmatter!==null&&i.match_frontmatter!==void 0?{matchFrontmatter:i.match_frontmatter}:{},...i.if!==null&&i.if!==void 0?{if:i.if}:{}}))}p(ie,"toRuleSpecs");const oe=p((t,i)=>JSON.stringify(t??null)===JSON.stringify(i??null),"same");function j(t,i){const o={},n=p(_=>!t||!oe(t[_],i[_]),"differs");return n("preview")&&(o.preview=i.preview),n("summary")&&(o.summary=i.summary),n("why_it_exists")&&(o.whyItExists=i.why_it_exists),n("unlisted")&&(o.unlisted=i.unlisted),n("lint_ignore")&&(o.lintIgnore=i.lint_ignore),n("extensions")&&(o.extensions=i.extensions),n("rules")&&(o.rules=ie(i.rules)),o}p(j,"changedFields");let re=0;function B(t,i){const o=`repo_sync_import_${++re}`;t.exec(`SAVEPOINT ${o}`);try{const n=i();return t.exec(`RELEASE ${o}`),n}catch(n){throw t.exec(`ROLLBACK TO ${o}`),t.exec(`RELEASE ${o}`),n}}p(B,"atomic");function Se(t,i,o,n,_){L(i);const m={created:0,revisions:0,deleted:0,needsMerge:[],refused:[]},l=[];for(const[r,a]of n){if(o.get(r)===a)continue;const e=y(r,a);if(!e.ok){m.refused.push({path:r,reason:e.reason});continue}const d=o.has(r)?y(r,o.get(r)):null;l.push({path:r,prior:d?.ok?d.doc:null,doc:e.doc})}for(const[r,a]of o){if(n.has(r))continue;const e=y(r,a);e.ok&&l.push({path:r,prior:e.doc,doc:null,priorId:e.doc.id})}for(const r of l)for(const a of r.doc?.revisions??[])P(a.body);const v=[];return B(t,()=>{let r=l;for(;;){const a=[];for(const e of r){const d={created:0,revisions:0,deleted:0,needsMerge:[],refused:[]};try{const c=[];B(t,()=>ue(t,i,e.prior,e.doc,e.priorId??e.doc.id,d,_,c)),v.push(...c),m.created+=d.created,m.revisions+=d.revisions,m.deleted+=d.deleted,m.needsMerge.push(...d.needsMerge)}catch(c){le(c)?a.push({w:e,error:c}):m.refused.push({path:e.path,reason:c.message})}}if(a.length===0)break;if(a.length===r.length){for(const e of a)m.refused.push({path:e.w.path,reason:e.error.message});break}r=a.map(e=>e.w)}se(t,n,new Set(v),new Set(l.map(a=>a.path)))}),m}p(Se,"importTree");function se(t,i,o,n){if(o.size===0)return;const _=g(t,"INSERT OR IGNORE INTO edges (type, src, dst, written_as, created_at) VALUES ('links-to', ?, ?, ?, ?)"),m=new Date().toISOString();for(const[l,v]of i){if(!n.has(l)&&!de(v,o))continue;const r=y(l,v);if(!r.ok||r.doc.deleted_at)continue;const a=x(t,r.doc.id);if(!a||a.type!=="document"||a.deleted_at)continue;const e=D(t,a)[0],d=r.doc.revisions.find(c=>c.rev_id===e?.rev_id)?.links??[];for(const c of d){const h=x(t,c.dst);h&&h.rowid!==a.rowid&&_.run(a.rowid,h.rowid,c.written_as,m)}}}p(se,"completeLinks");const ae=/"dst":\s*"((?:[^"\\]|\\.)*)"/g;function de(t,i){for(const o of t.matchAll(ae))if(i.has(ce(o[1])))return!0;return!1}p(de,"namesArrived");function ce(t){if(!t.includes("\\"))return t;try{return JSON.parse(`"${t}"`)}catch{return t}}p(ce,"decodeJsonString");function le(t){return t instanceof F&&t.code==="conflict"&&t.details?.holder!==void 0}p(le,"isNameConflict");function ue(t,i,o,n,_,m,l,v){const r=x(t,_);if(r&&(r.type!=="document"||r.owner!==i.rowid))throw new Error(`id ${_} is held by ${r.type} ${r.name} outside ${i.name}`);if(!n){r&&!r.deleted_at&&(M(t,null,r,l),m.deleted++);return}const a=g(t,"SELECT count(*) AS n FROM revisions WHERE document = ?");let e,d=!1,c=!1,h=0,w=0;if(r){e=r,h=C(t,e).revision,e.created_at!==n.created_at&&(g(t,"UPDATE objects SET created_at = ? WHERE rowid = ?").run(n.created_at,e.rowid),e=N(t,e.rowid));const u=n.kind;(o?o.kind!==u:e.kind!==u)&&Q(t,e,u),c=!!e.deleted_at&&n.deleted_at===null&&(o===null||o.deleted_at!=null);let f=j(c?null:o,n);if(n.deleted_at&&e.deleted_at){const{rules:k,...S}=f;f=S}c&&(e=G(t,e,n.name,l),v?.push(e.id)),Object.keys(f).length>0&&(e=q(t,null,e,f)),n.name!==e.name&&!e.deleted_at&&(e=V(t,null,e,{name:n.name},l))}else{const f=n.revisions.filter(k=>k.parents.length===0).sort((k,S)=>k.number-S.number||k.rev_id.localeCompare(S.rev_id))[0];if(!f)throw new Error(`${n.name}: no root revision`);e=z(t,{id:n.id,owner:i,name:n.name,kind:n.kind,preview:n.preview,privacy:"public",...j(null,n),revisions:[{rev_id:f.rev_id,body_hash:f.body_hash,author:null,rationale:f.rationale,created_at:f.created_at}]},l),e.created_at!==n.created_at&&(g(t,"UPDATE objects SET created_at = ? WHERE rowid = ?").run(n.created_at,e.rowid),e=N(t,e.rowid)),d=!0,v?.push(e.id),w=1}const R=a.get(e.rowid).n,{headCount:E}=K(t,e,n.revisions.map(u=>({rev_id:u.rev_id,parents:u.parents,body_hash:u.body_hash,rationale:u.rationale,created_at:u.created_at})));w+=a.get(e.rowid).n-R,m.revisions+=w;const s=D(t,e)[0],O=new Map(n.revisions.map(u=>[u.rev_id,u]));if(w>0||c){const u=(O.get(s.rev_id)?.links??[]).map(f=>({written_as:f.written_as,dst:x(t,f.dst)})).filter(f=>f.dst!==null);Y(t,J(t,e,u),l),U(t,e,[])}if(E>1&&m.needsMerge.push(e.id),n.deleted_at&&!e.deleted_at){M(t,null,e,l,n.deleted_at),m.deleted++;return}if(n.deleted_at&&e.deleted_at&&e.deleted_at!==n.deleted_at&&g(t,"UPDATE objects SET deleted_at = ? WHERE rowid = ?").run(n.deleted_at,e.rowid),d){m.created++,T(t,{event:"created",object:e,actor:null,attrs:{revision:s.number},pointer:s.rev_id},l);return}if(c){m.created++,T(t,{event:"created",object:e,actor:null,attrs:{revision:s.number},pointer:s.rev_id},l);return}if(w===0)return;const I=n.revisions.filter(u=>!o?.revisions.some(f=>f.rev_id===u.rev_id)).sort((u,f)=>f.number-u.number||f.created_at.localeCompare(u.created_at))[0]??O.get(s.rev_id);T(t,{event:"edited",object:e,actor:null,pointer:s.rev_id,attrs:{revision:s.number,from_revision:h,rationale:I?.rationale??null,author:I?.author??null,heads:E,needs_merge:E>1}},l)}p(ue,"importOne");export{Oe as exportRepo,Se as importTree,de as namesArrived,ne as pendingPaths};
1
+ var $=Object.defineProperty;var w=(t,i)=>$(t,"name",{value:i,configurable:!0});import{get as B,put as J}from"../bodies.js";import{setLinks as P,setUnresolved as U}from"../edges.js";import{collectUnlinked as Y,deleteDocument as I,documentRecord as C,heads as x,importDocument as z,insertImportedRevisions as G,moveDocument as K,restoreDocument as V,setDocumentRecord as b}from"../documents.js";import{CrtrError as q}from"../../errors.js";import{publish as D}from"../events.js";import{getById as S,getByRowid as M,setObjectKind as F}from"../objects.js";import{rulesOf as Q}from"../rules.js";import{SPACES as X}from"../spaces/index.js";import{docPath as Z,mergeDoc as ee,parseDoc as g,serializeDoc as A}from"./ref-format.js";import{withCanvasWrite as W}from"../../canvas/db.js";import{mapAsync as j}from"../../async-array.js";function H(t){const i=X[t.type];if(t.owner!==null||!i||i.sync!=="repo-ref")throw new Error(`${t.type} ${t.id} is not a space that syncs through a repo ref`)}w(H,"assertRepoRefSpace");function te(t){const i=new Map;for(const[r,n]of t??[]){const m=g(r,n);m.ok&&i.set(m.doc.id,m.doc)}return i}w(te,"parseMap");async function Oe(t,i,r,n=null){H(i);const m=te(r),p=await t.prepare("SELECT * FROM objects WHERE type = 'document' AND owner = ? AND privacy = 'public' ORDER BY rowid").all(i.rowid),l=t.prepare("SELECT rowid, rev_id, number, body_hash, author, rationale, created_at FROM revisions WHERE document = ? ORDER BY number, rev_id"),h=t.prepare("SELECT p.rev_id FROM revision_parents rp JOIN revisions p ON p.rowid = rp.parent WHERE rp.child = ?"),o=t.prepare(`SELECT e.written_as, o.id FROM edges e JOIN objects o ON o.rowid = e.dst
2
+ WHERE e.type = 'links-to' AND e.src = ? ORDER BY e.written_as, o.id`),s=new Map;for(const e of p){const d=await C(t,e),c=new Map((m.get(e.id)?.revisions??[]).map(a=>[a.rev_id,a])),_=new Set((await x(t,e)).map(a=>a.rev_id)),v=(await o.all(e.rowid)).map(a=>({written_as:a.written_as??"",dst:a.id})),E=await j(await l.all(e.rowid),async a=>c.get(a.rev_id)??{rev_id:a.rev_id,number:a.number,parents:(await h.all(a.rowid)).map(R=>R.rev_id),body:B(a.body_hash),body_hash:a.body_hash,author:a.author===null?null:(await M(t,a.author))?.id??null,rationale:a.rationale,created_at:a.created_at,links:_.has(a.rev_id)?v:[]});if(E.length===0)continue;const y=(await Q(t,e)).map(a=>({position:a.position,on:a.on,match:a.match??null,match_frontmatter:a.matchFrontmatter??null,if:a.if??null,deliver:a.deliver})),N={id:e.id,name:e.name,kind:e.kind??"document",privacy:"public",preview:e.preview,summary:d.summary,why_it_exists:d.why_it_exists,unlisted:d.unlisted,lint_ignore:d.lint_ignore,extensions:d.extensions,created_at:e.created_at,deleted_at:e.deleted_at,rules:y,revisions:E};s.set(Z(e.id),A(N))}for(const e of ne(r,n)){const d=r.get(e),c=s.get(e);if(c===void 0){s.set(e,d);continue}const _=g(e,d),v=g(e,c);if(!_.ok){s.set(e,d);continue}if(!v.ok)continue;const E=n?.has(e)?g(e,n.get(e)):null,y=ee(E?.ok?E.doc:null,v.doc,_.doc);y&&s.set(e,A(y))}return s}w(Oe,"exportRepo");function ne(t,i){return[...t??[]].filter(([r,n])=>i?.get(r)!==n).map(([r])=>r)}w(ne,"pendingPaths");function ie(t){return[...t].sort((i,r)=>i.position-r.position).map(i=>({on:i.on,deliver:i.deliver,...i.match!==null&&i.match!==void 0?{match:i.match}:{},...i.match_frontmatter!==null&&i.match_frontmatter!==void 0?{matchFrontmatter:i.match_frontmatter}:{},...i.if!==null&&i.if!==void 0?{if:i.if}:{}}))}w(ie,"toRuleSpecs");const re=w((t,i)=>JSON.stringify(t??null)===JSON.stringify(i??null),"same");function L(t,i){const r={},n=w(m=>!t||!re(t[m],i[m]),"differs");return n("preview")&&(r.preview=i.preview),n("summary")&&(r.summary=i.summary),n("why_it_exists")&&(r.whyItExists=i.why_it_exists),n("unlisted")&&(r.unlisted=i.unlisted),n("lint_ignore")&&(r.lintIgnore=i.lint_ignore),n("extensions")&&(r.extensions=i.extensions),n("rules")&&(r.rules=ie(i.rules)),r}w(L,"changedFields");async function Se(t,i,r,n,m){H(i);const p={created:0,revisions:0,deleted:0,needsMerge:[],refused:[]},l=[];for(const[o,s]of n){if(r.get(o)===s)continue;const e=g(o,s);if(!e.ok){p.refused.push({path:o,reason:e.reason});continue}const d=r.has(o)?g(o,r.get(o)):null;l.push({path:o,prior:d?.ok?d.doc:null,doc:e.doc})}for(const[o,s]of r){if(n.has(o))continue;const e=g(o,s);e.ok&&l.push({path:o,prior:e.doc,doc:null,priorId:e.doc.id})}for(const o of l)for(const s of o.doc?.revisions??[])J(s.body);const h=[];return await W(async()=>{let o=l;for(;;){const s=[];for(const e of o){const d={created:0,revisions:0,deleted:0,needsMerge:[],refused:[]};try{const c=[];await W(async()=>await le(t,i,e.prior,e.doc,e.priorId??e.doc.id,d,m,c),{savepoint:!0}),h.push(...c),p.created+=d.created,p.revisions+=d.revisions,p.deleted+=d.deleted,p.needsMerge.push(...d.needsMerge)}catch(c){ce(c)?s.push({w:e,error:c}):p.refused.push({path:e.path,reason:c.message})}}if(s.length===0)break;if(s.length===o.length){for(const e of s)p.refused.push({path:e.w.path,reason:e.error.message});break}o=s.map(e=>e.w)}await oe(t,n,new Set(h),new Set(l.map(s=>s.path)))},{savepoint:!0}),p}w(Se,"importTree");async function oe(t,i,r,n){if(r.size===0)return;const m=t.prepare("INSERT OR IGNORE INTO edges (type, src, dst, written_as, created_at) VALUES ('links-to', ?, ?, ?, ?)"),p=new Date().toISOString();for(const[l,h]of i){if(!n.has(l)&&!se(h,r))continue;const o=g(l,h);if(!o.ok||o.doc.deleted_at)continue;const s=await S(t,o.doc.id);if(!s||s.type!=="document"||s.deleted_at)continue;const e=(await x(t,s))[0],d=o.doc.revisions.find(c=>c.rev_id===e?.rev_id)?.links??[];for(const c of d){const _=await S(t,c.dst);_&&_.rowid!==s.rowid&&await m.run(s.rowid,_.rowid,c.written_as,p)}}}w(oe,"completeLinks");const ae=/"dst":\s*"((?:[^"\\]|\\.)*)"/g;function se(t,i){for(const r of t.matchAll(ae))if(i.has(de(r[1])))return!0;return!1}w(se,"namesArrived");function de(t){if(!t.includes("\\"))return t;try{return JSON.parse(`"${t}"`)}catch{return t}}w(de,"decodeJsonString");function ce(t){return t instanceof q&&t.code==="conflict"&&t.details?.holder!==void 0}w(ce,"isNameConflict");async function le(t,i,r,n,m,p,l,h){const o=await S(t,m);if(o&&(o.type!=="document"||o.owner!==i.rowid))throw new Error(`id ${m} is held by ${o.type} ${o.name} outside ${i.name}`);if(!n){o&&!o.deleted_at&&(await I(t,null,o,l),p.deleted++);return}const s=t.prepare("SELECT count(*) AS n FROM revisions WHERE document = ?");let e,d=!1,c=!1,_=0,v=0;if(o){e=o,_=(await C(t,e)).revision,e.created_at!==n.created_at&&(await t.prepare("UPDATE objects SET created_at = ? WHERE rowid = ?").run(n.created_at,e.rowid),e=await M(t,e.rowid));const u=n.kind;(r?r.kind!==u:e.kind!==u)&&await F(t,e,u),c=!!e.deleted_at&&n.deleted_at===null&&(r===null||r.deleted_at!=null);let f=L(c?null:r,n);if(n.deleted_at&&e.deleted_at){const{rules:k,...O}=f;f=O}c&&(e=await V(t,e,n.name,l),h?.push(e.id)),Object.keys(f).length>0&&(e=await b(t,null,e,f)),n.name!==e.name&&!e.deleted_at&&(e=await K(t,null,e,{name:n.name},l))}else{const f=n.revisions.filter(k=>k.parents.length===0).sort((k,O)=>k.number-O.number||k.rev_id.localeCompare(O.rev_id))[0];if(!f)throw new Error(`${n.name}: no root revision`);e=await z(t,{id:n.id,owner:i,name:n.name,kind:n.kind,preview:n.preview,privacy:"public",...L(null,n),revisions:[{rev_id:f.rev_id,body_hash:f.body_hash,author:null,rationale:f.rationale,created_at:f.created_at}]},l),e.created_at!==n.created_at&&(await t.prepare("UPDATE objects SET created_at = ? WHERE rowid = ?").run(n.created_at,e.rowid),e=await M(t,e.rowid)),d=!0,h?.push(e.id),v=1}const E=(await s.get(e.rowid)).n,{headCount:y}=await G(t,e,n.revisions.map(u=>({rev_id:u.rev_id,parents:u.parents,body_hash:u.body_hash,rationale:u.rationale,created_at:u.created_at})));v+=(await s.get(e.rowid)).n-E,p.revisions+=v;const a=(await x(t,e))[0],R=new Map(n.revisions.map(u=>[u.rev_id,u]));if(v>0||c){const u=(await j(R.get(a.rev_id)?.links??[],async f=>({written_as:f.written_as,dst:await S(t,f.dst)}))).filter(f=>f.dst!==null);await Y(t,await P(t,e,u),l),await U(t,e,[])}if(y>1&&p.needsMerge.push(e.id),n.deleted_at&&!e.deleted_at){await I(t,null,e,l,n.deleted_at),p.deleted++;return}if(n.deleted_at&&e.deleted_at&&e.deleted_at!==n.deleted_at&&await t.prepare("UPDATE objects SET deleted_at = ? WHERE rowid = ?").run(n.deleted_at,e.rowid),d){p.created++,await D(t,{event:"created",object:e,actor:null,attrs:{revision:a.number},pointer:a.rev_id},l);return}if(c){p.created++,await D(t,{event:"created",object:e,actor:null,attrs:{revision:a.number},pointer:a.rev_id},l);return}if(v===0)return;const T=n.revisions.filter(u=>!r?.revisions.some(f=>f.rev_id===u.rev_id)).sort((u,f)=>f.number-u.number||f.created_at.localeCompare(u.created_at))[0]??R.get(a.rev_id);await D(t,{event:"edited",object:e,actor:null,pointer:a.rev_id,attrs:{revision:a.number,from_revision:_,rationale:T?.rationale??null,author:T?.author??null,heads:y,needs_merge:y>1}},l)}w(le,"importOne");export{Oe as exportRepo,Se as importTree,se as namesArrived,ne as pendingPaths};
@@ -1,7 +1,6 @@
1
- /** Repo objects on the canvas: one per repo identity, handle chosen once. */
2
- import type { DatabaseSync } from 'node:sqlite';
3
1
  import type { Checkout, ObjectRow } from '../types.js';
4
2
  import { handleHint } from './identity.js';
3
+ import type { CanvasDb } from '../../canvas/db.js';
5
4
  export { handleHint };
6
5
  export interface RepoIdentity {
7
6
  scheme: 'git' | 'local-path';
@@ -10,10 +9,13 @@ export interface RepoIdentity {
10
9
  }
11
10
  /** The repo object for an identity, created on first sight. A handle already
12
11
  * held by another repo gets `-2`, `-3`, … appended. */
13
- export declare function ensureRepo(db: DatabaseSync, id: RepoIdentity, handle?: string): ObjectRow;
12
+ export declare function ensureRepo(db: CanvasDb, id: RepoIdentity, handle?: string): Promise<ObjectRow>;
14
13
  /** Repos enclosing `cwd`, nearest first: every enclosing git checkout (created
15
14
  * on first sight) and every existing local-path repo whose path is `cwd` or
16
15
  * an ancestor of it. A non-git folder is never created here. */
17
- export declare function reposForCwd(db: DatabaseSync, cwd: string): ObjectRow[];
16
+ export declare function reposForCwd(db: CanvasDb, cwd: string): Promise<ObjectRow[]>;
17
+ /** Run the git lookups for `cwd`'s checkouts now, so a later `checkoutsForCwd` inside a canvas write hits the identity
18
+ * cache instead of spawning git while every other db caller waits on the write lock. */
19
+ export declare function warmCheckoutIdentities(cwd: string): void;
18
20
  /** `reposForCwd` with the directory each repo is checked out at. */
19
- export declare function checkoutsForCwd(db: DatabaseSync, cwd: string): Checkout[];
21
+ export declare function checkoutsForCwd(db: CanvasDb, cwd: string): Promise<Checkout[]>;
@@ -1,3 +1,3 @@
1
- var h=Object.defineProperty;var s=(t,e)=>h(t,"name",{value:e,configurable:!0});import{prepared as a}from"../../sqlite-statements.js";import{resolve as d,sep as f}from"node:path";import{CrtrError as m}from"../../errors.js";import{realpathOrSelf as l}from"../../fs-utils.js";import{ExitCode as u}from"../../../types.js";import{ensureOwner as E}from"../objects.js";import{checkoutChain as w,handleHint as N}from"./identity.js";function x(t,e,r){return a(t,`SELECT o.* FROM identities i JOIN objects o ON o.rowid = i.object
2
- WHERE o.type = 'repo' AND i.scheme = ? AND i.external_id = ?`).get(e,r)??null}s(x,"existingRepo");function O(t,e,r){const n=x(t,e.scheme,e.externalId);if(n)return n;const p=r??e.handleHint,c=a(t,"SELECT 1 FROM objects WHERE name = ? AND type = 'repo' AND home_machine IS NULL");let o=p;for(let i=2;c.get(o);i++)o=`${p}-${i}`;return E(t,"repo",e.scheme,e.externalId,o)}s(O,"ensureRepo");function F(t,e){return R(t,e).map(r=>r.repo)}s(F,"reposForCwd");function R(t,e){const r=l(d(e)),n=[];for(const o of w(r)){if(!o.ok)throw new m("git-lookup-failed",`cannot identify the repo at ${o.dir}: ${o.reason}`,u.GENERAL,{dir:o.dir});n.push({root:o.root,repo:O(t,o)})}const p=a(t,`SELECT o.*, i.external_id AS path FROM identities i JOIN objects o ON o.rowid = i.object
3
- WHERE o.type = 'repo' AND i.scheme = 'local-path'`).all();for(const{path:o,...i}of p)(r===o||r.startsWith(o.endsWith(f)?o:o+f))&&n.push({root:o,repo:i});n.sort((o,i)=>i.root.length-o.root.length);const c=new Set;return n.filter(({repo:o})=>!c.has(o.rowid)&&(c.add(o.rowid),!0))}s(R,"checkoutsForCwd");export{R as checkoutsForCwd,O as ensureRepo,N as handleHint,F as reposForCwd};
1
+ var l=Object.defineProperty;var a=(t,o)=>l(t,"name",{value:o,configurable:!0});import{resolve as c,sep as f}from"node:path";import{CrtrError as u}from"../../errors.js";import{realpathOrSelf as h}from"../../fs-utils.js";import{ExitCode as m}from"../../../types.js";import{ensureOwner as w}from"../objects.js";import{checkoutChain as d,handleHint as E}from"./identity.js";async function x(t,o,r){return await t.prepare(`SELECT o.* FROM identities i JOIN objects o ON o.rowid = i.object
2
+ WHERE o.type = 'repo' AND i.scheme = ? AND i.external_id = ?`).get(o,r)??null}a(x,"existingRepo");async function N(t,o,r){const n=await x(t,o.scheme,o.externalId);if(n)return n;const s=r??o.handleHint,p=t.prepare("SELECT 1 FROM objects WHERE name = ? AND type = 'repo' AND home_machine IS NULL");let e=s;for(let i=2;await p.get(e);i++)e=`${s}-${i}`;return await w(t,"repo",o.scheme,o.externalId,e)}a(N,"ensureRepo");async function I(t,o){return(await C(t,o)).map(r=>r.repo)}a(I,"reposForCwd");function L(t){d(h(c(t)))}a(L,"warmCheckoutIdentities");async function C(t,o){const r=h(c(o)),n=[];for(const e of d(r)){if(!e.ok)throw new u("git-lookup-failed",`cannot identify the repo at ${e.dir}: ${e.reason}`,m.GENERAL,{dir:e.dir});n.push({root:e.root,repo:await N(t,e)})}const s=await t.prepare(`SELECT o.*, i.external_id AS path FROM identities i JOIN objects o ON o.rowid = i.object
3
+ WHERE o.type = 'repo' AND i.scheme = 'local-path'`).all();for(const{path:e,...i}of s)(r===e||r.startsWith(e.endsWith(f)?e:e+f))&&n.push({root:e,repo:i});n.sort((e,i)=>i.root.length-e.root.length);const p=new Set;return n.filter(({repo:e})=>!p.has(e.rowid)&&(p.add(e.rowid),!0))}a(C,"checkoutsForCwd");export{C as checkoutsForCwd,N as ensureRepo,E as handleHint,I as reposForCwd,L as warmCheckoutIdentities};