@ontrails/core 1.0.0-beta.15 → 1.0.0-beta.16

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 (348) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +61 -16
  3. package/package.json +9 -8
  4. package/src/activation-provenance.ts +111 -0
  5. package/src/activation-source-compatibility.ts +430 -0
  6. package/src/activation-source-projection.ts +221 -0
  7. package/src/activation-source.ts +91 -0
  8. package/src/blob-ref.ts +51 -0
  9. package/src/context.ts +4 -0
  10. package/src/{internal/cross-batch.ts → cross-batch.ts} +3 -11
  11. package/src/detours.ts +8 -0
  12. package/src/draft.ts +4 -0
  13. package/src/error-projection.ts +51 -0
  14. package/src/errors.ts +192 -39
  15. package/src/execute.ts +443 -44
  16. package/src/fire.ts +965 -91
  17. package/src/index.ts +285 -38
  18. package/src/layer-projection.ts +192 -0
  19. package/src/layer.ts +32 -1
  20. package/src/observe.ts +361 -0
  21. package/src/permits.ts +12 -0
  22. package/src/redaction/patterns.ts +6 -3
  23. package/src/resilience.ts +8 -8
  24. package/src/resource-config.ts +477 -44
  25. package/src/resource.ts +21 -1
  26. package/src/result.ts +18 -0
  27. package/src/run.ts +2 -2
  28. package/src/schedule-runtime.ts +689 -0
  29. package/src/schedule.ts +324 -0
  30. package/src/serialization.ts +90 -57
  31. package/src/signal-diagnostics.ts +633 -0
  32. package/src/{internal/signal-ref.ts → signal-ref.ts} +1 -1
  33. package/src/signal.ts +37 -0
  34. package/src/store/accessor-protocol.ts +5 -5
  35. package/src/structured-examples.ts +245 -0
  36. package/src/surface-derivation.ts +91 -0
  37. package/src/surface-filter.ts +7 -13
  38. package/src/topo.ts +386 -6
  39. package/src/tracing.ts +345 -0
  40. package/src/trail.ts +168 -22
  41. package/src/trails/derive-trail.ts +1 -1
  42. package/src/trails/ingest.ts +7 -15
  43. package/src/{internal/trails-db.ts → trails-db.ts} +42 -21
  44. package/src/transport-error-map.ts +146 -28
  45. package/src/types.ts +82 -28
  46. package/src/validate-established-topo.ts +6 -0
  47. package/src/validate-topo.ts +212 -5
  48. package/src/validation.ts +58 -1
  49. package/src/webhook.ts +276 -0
  50. package/src/{internal/zod-wrappers.ts → zod-wrappers.ts} +0 -6
  51. package/.turbo/turbo-build.log +0 -1
  52. package/.turbo/turbo-lint.log +0 -3
  53. package/.turbo/turbo-typecheck.log +0 -1
  54. package/dist/blob-ref.d.ts +0 -20
  55. package/dist/blob-ref.d.ts.map +0 -1
  56. package/dist/blob-ref.js +0 -22
  57. package/dist/blob-ref.js.map +0 -1
  58. package/dist/branded.d.ts +0 -36
  59. package/dist/branded.d.ts.map +0 -1
  60. package/dist/branded.js +0 -89
  61. package/dist/branded.js.map +0 -1
  62. package/dist/collections.d.ts +0 -31
  63. package/dist/collections.d.ts.map +0 -1
  64. package/dist/collections.js +0 -60
  65. package/dist/collections.js.map +0 -1
  66. package/dist/context.d.ts +0 -22
  67. package/dist/context.d.ts.map +0 -1
  68. package/dist/context.js +0 -37
  69. package/dist/context.js.map +0 -1
  70. package/dist/contour.d.ts +0 -81
  71. package/dist/contour.d.ts.map +0 -1
  72. package/dist/contour.js +0 -176
  73. package/dist/contour.js.map +0 -1
  74. package/dist/cross-schema.d.ts +0 -18
  75. package/dist/cross-schema.d.ts.map +0 -1
  76. package/dist/cross-schema.js +0 -29
  77. package/dist/cross-schema.js.map +0 -1
  78. package/dist/derive.d.ts +0 -44
  79. package/dist/derive.d.ts.map +0 -1
  80. package/dist/derive.js +0 -149
  81. package/dist/derive.js.map +0 -1
  82. package/dist/draft.d.ts +0 -28
  83. package/dist/draft.d.ts.map +0 -1
  84. package/dist/draft.js +0 -157
  85. package/dist/draft.js.map +0 -1
  86. package/dist/errors.d.ts +0 -141
  87. package/dist/errors.d.ts.map +0 -1
  88. package/dist/errors.js +0 -185
  89. package/dist/errors.js.map +0 -1
  90. package/dist/execute.d.ts +0 -52
  91. package/dist/execute.d.ts.map +0 -1
  92. package/dist/execute.js +0 -511
  93. package/dist/execute.js.map +0 -1
  94. package/dist/fetch.d.ts +0 -15
  95. package/dist/fetch.d.ts.map +0 -1
  96. package/dist/fetch.js +0 -102
  97. package/dist/fetch.js.map +0 -1
  98. package/dist/fire.d.ts +0 -43
  99. package/dist/fire.d.ts.map +0 -1
  100. package/dist/fire.js +0 -185
  101. package/dist/fire.js.map +0 -1
  102. package/dist/guards.d.ts +0 -17
  103. package/dist/guards.d.ts.map +0 -1
  104. package/dist/guards.js +0 -25
  105. package/dist/guards.js.map +0 -1
  106. package/dist/index.d.ts +0 -59
  107. package/dist/index.d.ts.map +0 -1
  108. package/dist/index.js +0 -61
  109. package/dist/index.js.map +0 -1
  110. package/dist/internal/cross-batch.d.ts +0 -44
  111. package/dist/internal/cross-batch.d.ts.map +0 -1
  112. package/dist/internal/cross-batch.js +0 -58
  113. package/dist/internal/cross-batch.js.map +0 -1
  114. package/dist/internal/fork-ctx.d.ts +0 -41
  115. package/dist/internal/fork-ctx.d.ts.map +0 -1
  116. package/dist/internal/fork-ctx.js +0 -47
  117. package/dist/internal/fork-ctx.js.map +0 -1
  118. package/dist/internal/signal-ref.d.ts +0 -15
  119. package/dist/internal/signal-ref.d.ts.map +0 -1
  120. package/dist/internal/signal-ref.js +0 -41
  121. package/dist/internal/signal-ref.js.map +0 -1
  122. package/dist/internal/topo-saves.d.ts +0 -53
  123. package/dist/internal/topo-saves.d.ts.map +0 -1
  124. package/dist/internal/topo-saves.js +0 -449
  125. package/dist/internal/topo-saves.js.map +0 -1
  126. package/dist/internal/topo-snapshots.d.ts +0 -57
  127. package/dist/internal/topo-snapshots.d.ts.map +0 -1
  128. package/dist/internal/topo-snapshots.js +0 -372
  129. package/dist/internal/topo-snapshots.js.map +0 -1
  130. package/dist/internal/topo-store-read.d.ts +0 -70
  131. package/dist/internal/topo-store-read.d.ts.map +0 -1
  132. package/dist/internal/topo-store-read.js +0 -221
  133. package/dist/internal/topo-store-read.js.map +0 -1
  134. package/dist/internal/topo-store.d.ts +0 -26
  135. package/dist/internal/topo-store.d.ts.map +0 -1
  136. package/dist/internal/topo-store.js +0 -621
  137. package/dist/internal/topo-store.js.map +0 -1
  138. package/dist/internal/tracing.d.ts +0 -98
  139. package/dist/internal/tracing.d.ts.map +0 -1
  140. package/dist/internal/tracing.js +0 -102
  141. package/dist/internal/tracing.js.map +0 -1
  142. package/dist/internal/trails-db.d.ts +0 -16
  143. package/dist/internal/trails-db.d.ts.map +0 -1
  144. package/dist/internal/trails-db.js +0 -118
  145. package/dist/internal/trails-db.js.map +0 -1
  146. package/dist/internal/zod-wrappers.d.ts +0 -40
  147. package/dist/internal/zod-wrappers.d.ts.map +0 -1
  148. package/dist/internal/zod-wrappers.js +0 -59
  149. package/dist/internal/zod-wrappers.js.map +0 -1
  150. package/dist/layer.d.ts +0 -23
  151. package/dist/layer.d.ts.map +0 -1
  152. package/dist/layer.js +0 -21
  153. package/dist/layer.js.map +0 -1
  154. package/dist/path-security.d.ts +0 -28
  155. package/dist/path-security.d.ts.map +0 -1
  156. package/dist/path-security.js +0 -63
  157. package/dist/path-security.js.map +0 -1
  158. package/dist/patterns/bulk.d.ts +0 -15
  159. package/dist/patterns/bulk.d.ts.map +0 -1
  160. package/dist/patterns/bulk.js +0 -14
  161. package/dist/patterns/bulk.js.map +0 -1
  162. package/dist/patterns/change.d.ts +0 -10
  163. package/dist/patterns/change.d.ts.map +0 -1
  164. package/dist/patterns/change.js +0 -10
  165. package/dist/patterns/change.js.map +0 -1
  166. package/dist/patterns/date-range.d.ts +0 -10
  167. package/dist/patterns/date-range.d.ts.map +0 -1
  168. package/dist/patterns/date-range.js +0 -10
  169. package/dist/patterns/date-range.js.map +0 -1
  170. package/dist/patterns/index.d.ts +0 -9
  171. package/dist/patterns/index.d.ts.map +0 -1
  172. package/dist/patterns/index.js +0 -9
  173. package/dist/patterns/index.js.map +0 -1
  174. package/dist/patterns/pagination.d.ts +0 -18
  175. package/dist/patterns/pagination.d.ts.map +0 -1
  176. package/dist/patterns/pagination.js +0 -18
  177. package/dist/patterns/pagination.js.map +0 -1
  178. package/dist/patterns/progress.d.ts +0 -11
  179. package/dist/patterns/progress.d.ts.map +0 -1
  180. package/dist/patterns/progress.js +0 -11
  181. package/dist/patterns/progress.js.map +0 -1
  182. package/dist/patterns/sorting.d.ts +0 -13
  183. package/dist/patterns/sorting.d.ts.map +0 -1
  184. package/dist/patterns/sorting.js +0 -10
  185. package/dist/patterns/sorting.js.map +0 -1
  186. package/dist/patterns/status.d.ts +0 -15
  187. package/dist/patterns/status.d.ts.map +0 -1
  188. package/dist/patterns/status.js +0 -9
  189. package/dist/patterns/status.js.map +0 -1
  190. package/dist/patterns/timestamps.d.ts +0 -10
  191. package/dist/patterns/timestamps.d.ts.map +0 -1
  192. package/dist/patterns/timestamps.js +0 -10
  193. package/dist/patterns/timestamps.js.map +0 -1
  194. package/dist/redaction/index.d.ts +0 -4
  195. package/dist/redaction/index.d.ts.map +0 -1
  196. package/dist/redaction/index.js +0 -3
  197. package/dist/redaction/index.js.map +0 -1
  198. package/dist/redaction/patterns.d.ts +0 -9
  199. package/dist/redaction/patterns.d.ts.map +0 -1
  200. package/dist/redaction/patterns.js +0 -39
  201. package/dist/redaction/patterns.js.map +0 -1
  202. package/dist/redaction/redactor.d.ts +0 -27
  203. package/dist/redaction/redactor.d.ts.map +0 -1
  204. package/dist/redaction/redactor.js +0 -89
  205. package/dist/redaction/redactor.js.map +0 -1
  206. package/dist/resilience.d.ts +0 -34
  207. package/dist/resilience.d.ts.map +0 -1
  208. package/dist/resilience.js +0 -164
  209. package/dist/resilience.js.map +0 -1
  210. package/dist/resource-config.d.ts +0 -22
  211. package/dist/resource-config.d.ts.map +0 -1
  212. package/dist/resource-config.js +0 -210
  213. package/dist/resource-config.js.map +0 -1
  214. package/dist/resource.d.ts +0 -74
  215. package/dist/resource.d.ts.map +0 -1
  216. package/dist/resource.js +0 -61
  217. package/dist/resource.js.map +0 -1
  218. package/dist/result.d.ts +0 -57
  219. package/dist/result.d.ts.map +0 -1
  220. package/dist/result.js +0 -156
  221. package/dist/result.js.map +0 -1
  222. package/dist/run.d.ts +0 -28
  223. package/dist/run.d.ts.map +0 -1
  224. package/dist/run.js +0 -35
  225. package/dist/run.js.map +0 -1
  226. package/dist/serialization.d.ts +0 -27
  227. package/dist/serialization.d.ts.map +0 -1
  228. package/dist/serialization.js +0 -154
  229. package/dist/serialization.js.map +0 -1
  230. package/dist/signal.d.ts +0 -33
  231. package/dist/signal.d.ts.map +0 -1
  232. package/dist/signal.js +0 -17
  233. package/dist/signal.js.map +0 -1
  234. package/dist/store/accessor-protocol.d.ts +0 -51
  235. package/dist/store/accessor-protocol.d.ts.map +0 -1
  236. package/dist/store/accessor-protocol.js +0 -2
  237. package/dist/store/accessor-protocol.js.map +0 -1
  238. package/dist/store/index.d.ts +0 -2
  239. package/dist/store/index.d.ts.map +0 -1
  240. package/dist/store/index.js +0 -2
  241. package/dist/store/index.js.map +0 -1
  242. package/dist/surface-filter.d.ts +0 -13
  243. package/dist/surface-filter.d.ts.map +0 -1
  244. package/dist/surface-filter.js +0 -76
  245. package/dist/surface-filter.js.map +0 -1
  246. package/dist/topo-store.d.ts +0 -62
  247. package/dist/topo-store.d.ts.map +0 -1
  248. package/dist/topo-store.js +0 -319
  249. package/dist/topo-store.js.map +0 -1
  250. package/dist/topo.d.ts +0 -39
  251. package/dist/topo.d.ts.map +0 -1
  252. package/dist/topo.js +0 -241
  253. package/dist/topo.js.map +0 -1
  254. package/dist/trail.d.ts +0 -163
  255. package/dist/trail.d.ts.map +0 -1
  256. package/dist/trail.js +0 -75
  257. package/dist/trail.js.map +0 -1
  258. package/dist/trails/derive-trail.d.ts +0 -66
  259. package/dist/trails/derive-trail.d.ts.map +0 -1
  260. package/dist/trails/derive-trail.js +0 -378
  261. package/dist/trails/derive-trail.js.map +0 -1
  262. package/dist/trails/index.d.ts +0 -5
  263. package/dist/trails/index.d.ts.map +0 -1
  264. package/dist/trails/index.js +0 -3
  265. package/dist/trails/index.js.map +0 -1
  266. package/dist/trails/ingest.d.ts +0 -24
  267. package/dist/trails/ingest.d.ts.map +0 -1
  268. package/dist/trails/ingest.js +0 -63
  269. package/dist/trails/ingest.js.map +0 -1
  270. package/dist/transport-error-map.d.ts +0 -106
  271. package/dist/transport-error-map.d.ts.map +0 -1
  272. package/dist/transport-error-map.js +0 -24
  273. package/dist/transport-error-map.js.map +0 -1
  274. package/dist/type-checks.test-d.d.ts +0 -71
  275. package/dist/type-checks.test-d.d.ts.map +0 -1
  276. package/dist/type-checks.test-d.js +0 -12
  277. package/dist/type-checks.test-d.js.map +0 -1
  278. package/dist/type-utils.d.ts +0 -33
  279. package/dist/type-utils.d.ts.map +0 -1
  280. package/dist/type-utils.js +0 -12
  281. package/dist/type-utils.js.map +0 -1
  282. package/dist/types.d.ts +0 -177
  283. package/dist/types.d.ts.map +0 -1
  284. package/dist/types.js +0 -3
  285. package/dist/types.js.map +0 -1
  286. package/dist/validate-established-topo.d.ts +0 -76
  287. package/dist/validate-established-topo.d.ts.map +0 -1
  288. package/dist/validate-established-topo.js +0 -43
  289. package/dist/validate-established-topo.js.map +0 -1
  290. package/dist/validate-topo.d.ts +0 -24
  291. package/dist/validate-topo.d.ts.map +0 -1
  292. package/dist/validate-topo.js +0 -193
  293. package/dist/validate-topo.js.map +0 -1
  294. package/dist/validation.d.ts +0 -27
  295. package/dist/validation.d.ts.map +0 -1
  296. package/dist/validation.js +0 -165
  297. package/dist/validation.js.map +0 -1
  298. package/dist/workspace.d.ts +0 -25
  299. package/dist/workspace.d.ts.map +0 -1
  300. package/dist/workspace.js +0 -57
  301. package/dist/workspace.js.map +0 -1
  302. package/src/__tests__/blob-ref.test.ts +0 -103
  303. package/src/__tests__/branded.test.ts +0 -148
  304. package/src/__tests__/collections.test.ts +0 -126
  305. package/src/__tests__/context.test.ts +0 -77
  306. package/src/__tests__/contour.test.ts +0 -263
  307. package/src/__tests__/derive-trail.test.ts +0 -668
  308. package/src/__tests__/derive.test.ts +0 -260
  309. package/src/__tests__/errors.test.ts +0 -427
  310. package/src/__tests__/execute.test.ts +0 -1563
  311. package/src/__tests__/fetch.test.ts +0 -217
  312. package/src/__tests__/fire.test.ts +0 -1056
  313. package/src/__tests__/fork-ctx.test.ts +0 -83
  314. package/src/__tests__/guards.test.ts +0 -102
  315. package/src/__tests__/ingest.test.ts +0 -191
  316. package/src/__tests__/layer.test.ts +0 -125
  317. package/src/__tests__/path-security.test.ts +0 -114
  318. package/src/__tests__/patterns.test.ts +0 -273
  319. package/src/__tests__/redaction.test.ts +0 -244
  320. package/src/__tests__/resilience.test.ts +0 -246
  321. package/src/__tests__/resource.test.ts +0 -204
  322. package/src/__tests__/result.test.ts +0 -155
  323. package/src/__tests__/run.test.ts +0 -181
  324. package/src/__tests__/serialization.test.ts +0 -401
  325. package/src/__tests__/service-config.test.ts +0 -224
  326. package/src/__tests__/signal.test.ts +0 -82
  327. package/src/__tests__/surface-filter.test.ts +0 -196
  328. package/src/__tests__/topo-store-read.test.ts +0 -256
  329. package/src/__tests__/topo-store.test.ts +0 -869
  330. package/src/__tests__/topo.test.ts +0 -573
  331. package/src/__tests__/trail-permit.test.ts +0 -60
  332. package/src/__tests__/trail.test.ts +0 -426
  333. package/src/__tests__/trails-db.test.ts +0 -198
  334. package/src/__tests__/transport-error-map.test.ts +0 -82
  335. package/src/__tests__/type-utils.test.ts +0 -118
  336. package/src/__tests__/validate-topo.test.ts +0 -611
  337. package/src/__tests__/validation.test.ts +0 -336
  338. package/src/__tests__/workspace.test.ts +0 -183
  339. package/src/__tests__/zod-wrappers.test.ts +0 -62
  340. package/src/internal/topo-snapshots.ts +0 -517
  341. package/src/internal/topo-store-read.ts +0 -481
  342. package/src/internal/topo-store.ts +0 -1192
  343. package/src/internal/tracing.ts +0 -187
  344. package/src/topo-store.ts +0 -510
  345. package/src/type-checks.test-d.ts +0 -106
  346. package/tsconfig.json +0 -9
  347. package/tsconfig.tests.json +0 -10
  348. package/tsconfig.tsbuildinfo +0 -1
@@ -1,481 +0,0 @@
1
- import type { Database, SQLQueryBindings } from 'bun:sqlite';
2
-
3
- import { ValidationError } from '../errors.js';
4
- import type {
5
- ListTopoSnapshotsOptions,
6
- TopoSnapshot,
7
- } from './topo-snapshots.js';
8
- import {
9
- listTopoSnapshots,
10
- readPinnedTopoSnapshot,
11
- readTopoSnapshot,
12
- } from './topo-snapshots.js';
13
- import type { StoredTopoExport } from './topo-store.js';
14
- import { getStoredTopoExport } from './topo-store.js';
15
-
16
- export interface TopoStoreRef {
17
- readonly pin?: string;
18
- readonly snapshotId?: string;
19
- }
20
-
21
- export interface TopoStoreTrailRecord {
22
- readonly description: string | null;
23
- readonly exampleCount: number;
24
- readonly hasExamples: boolean;
25
- readonly hasOutput: boolean;
26
- readonly id: string;
27
- readonly idempotent: boolean;
28
- readonly intent: 'destroy' | 'read' | 'write';
29
- readonly kind: 'trail';
30
- readonly meta: Readonly<Record<string, unknown>> | null;
31
- readonly pattern: string | null;
32
- readonly safety: '-' | 'destroy' | 'read' | 'write';
33
- readonly snapshotId: string;
34
- }
35
-
36
- export interface TopoStoreExampleRecord {
37
- readonly description: string | null;
38
- readonly error: string | null;
39
- readonly expected: unknown;
40
- readonly input: unknown;
41
- readonly name: string;
42
- readonly ordinal: number;
43
- }
44
-
45
- export interface TopoStoreTrailDetailRecord extends TopoStoreTrailRecord {
46
- readonly crosses: readonly string[];
47
- readonly detours:
48
- | readonly { readonly on: string; readonly maxAttempts: number }[]
49
- | null;
50
- readonly examples: readonly TopoStoreExampleRecord[];
51
- readonly resources: readonly string[];
52
- }
53
-
54
- export interface TopoStoreResourceRecord {
55
- readonly description: string | null;
56
- readonly hasHealth: boolean;
57
- readonly hasMock: boolean;
58
- readonly health: 'available' | 'none';
59
- readonly id: string;
60
- readonly kind: 'resource';
61
- readonly lifetime: 'singleton';
62
- readonly snapshotId: string;
63
- readonly usedBy: readonly string[];
64
- }
65
-
66
- export interface TopoStoreExportRecord extends StoredTopoExport {
67
- readonly snapshot: TopoSnapshot;
68
- }
69
-
70
- interface TopoTrailRow {
71
- readonly description: string | null;
72
- readonly example_count: number;
73
- readonly has_examples: number;
74
- readonly has_output: number;
75
- readonly id: string;
76
- readonly idempotent: number;
77
- readonly intent: string | null;
78
- readonly meta: string | null;
79
- readonly pattern: string | null;
80
- readonly snapshot_id: string;
81
- }
82
-
83
- interface TopoCrossingRow {
84
- readonly target_id: string;
85
- }
86
-
87
- interface TopoTrailResourceRow {
88
- readonly resource_id: string;
89
- }
90
-
91
- interface TopoExampleRow {
92
- readonly description: string | null;
93
- readonly error: string | null;
94
- readonly expected: string | null;
95
- readonly input: string;
96
- readonly name: string;
97
- readonly ordinal: number;
98
- }
99
-
100
- interface TopoResourceRow {
101
- readonly has_health: number;
102
- readonly has_mock: number;
103
- readonly id: string;
104
- readonly snapshot_id: string;
105
- }
106
-
107
- interface StoredSurfaceMapEntry {
108
- readonly description?: string;
109
- readonly detours?: readonly {
110
- readonly on: string;
111
- readonly maxAttempts: number;
112
- }[];
113
- readonly healthcheck?: boolean;
114
- readonly id: string;
115
- readonly kind: 'contour' | 'resource' | 'signal' | 'trail';
116
- }
117
-
118
- interface StoredSurfaceMap {
119
- readonly entries: readonly StoredSurfaceMapEntry[];
120
- }
121
-
122
- const ensureSingleRefSelector = (ref?: TopoStoreRef): void => {
123
- if (ref?.pin !== undefined && ref.snapshotId !== undefined) {
124
- throw new ValidationError(
125
- 'Topo store references may use pin or snapshotId, not both'
126
- );
127
- }
128
- };
129
-
130
- const normalizeIntent = (
131
- intent: string | null
132
- ): TopoStoreTrailRecord['intent'] => {
133
- if (intent === 'destroy' || intent === 'read') {
134
- return intent;
135
- }
136
- return 'write';
137
- };
138
-
139
- const safetyForIntent = (
140
- intent: TopoStoreTrailRecord['intent']
141
- ): TopoStoreTrailRecord['safety'] => {
142
- if (intent === 'destroy') {
143
- return 'destroy';
144
- }
145
- if (intent === 'read') {
146
- return 'read';
147
- }
148
- return 'write';
149
- };
150
-
151
- const parseMeta = (
152
- value: string | null
153
- ): Readonly<Record<string, unknown>> | null =>
154
- value === null
155
- ? null
156
- : (JSON.parse(value) as Readonly<Record<string, unknown>>);
157
-
158
- const parseJson = (value: string): unknown => JSON.parse(value) as unknown;
159
-
160
- const readSnapshotRef = (
161
- db: Database,
162
- ref?: TopoStoreRef
163
- ): TopoSnapshot | undefined => {
164
- ensureSingleRefSelector(ref);
165
-
166
- if (ref?.snapshotId !== undefined) {
167
- return readTopoSnapshot(db, ref.snapshotId);
168
- }
169
-
170
- if (ref?.pin !== undefined) {
171
- return readPinnedTopoSnapshot(db, ref.pin);
172
- }
173
-
174
- return listTopoSnapshots(db, { limit: 1 })[0];
175
- };
176
-
177
- const readStoredEntry = (
178
- db: Database,
179
- snapshotId: string,
180
- kind: StoredSurfaceMapEntry['kind'],
181
- id: string
182
- ): StoredSurfaceMapEntry | undefined => {
183
- const stored = getStoredTopoExport(db, snapshotId);
184
- if (stored === undefined) {
185
- return undefined;
186
- }
187
-
188
- const map = JSON.parse(stored.surfaceMapJson) as StoredSurfaceMap;
189
- return map.entries.find((entry) => entry.id === id && entry.kind === kind);
190
- };
191
-
192
- const mapTrailRow = (row: TopoTrailRow): TopoStoreTrailRecord => {
193
- const intent = normalizeIntent(row.intent);
194
-
195
- return {
196
- description: row.description,
197
- exampleCount: row.example_count,
198
- hasExamples: row.has_examples === 1,
199
- hasOutput: row.has_output === 1,
200
- id: row.id,
201
- idempotent: row.idempotent === 1,
202
- intent,
203
- kind: 'trail',
204
- meta: parseMeta(row.meta),
205
- pattern: row.pattern,
206
- safety: safetyForIntent(intent),
207
- snapshotId: row.snapshot_id,
208
- };
209
- };
210
-
211
- const readTrailCrossings = (
212
- db: Database,
213
- snapshotId: string,
214
- trailId: string
215
- ): readonly string[] =>
216
- db
217
- .query<TopoCrossingRow, [string, string]>(
218
- `SELECT target_id
219
- FROM topo_crossings
220
- WHERE snapshot_id = ? AND source_id = ?
221
- ORDER BY target_id ASC`
222
- )
223
- .all(snapshotId, trailId)
224
- .map((row) => row.target_id);
225
-
226
- const readTrailResourceIds = (
227
- db: Database,
228
- snapshotId: string,
229
- trailId: string
230
- ): readonly string[] =>
231
- db
232
- .query<TopoTrailResourceRow, [string, string]>(
233
- `SELECT resource_id
234
- FROM topo_trail_resources
235
- WHERE snapshot_id = ? AND trail_id = ?
236
- ORDER BY resource_id ASC`
237
- )
238
- .all(snapshotId, trailId)
239
- .map((row) => row.resource_id);
240
-
241
- const readTrailExamples = (
242
- db: Database,
243
- snapshotId: string,
244
- trailId: string
245
- ): readonly TopoStoreExampleRecord[] =>
246
- db
247
- .query<TopoExampleRow, [string, string]>(
248
- `SELECT ordinal, name, description, input, expected, error
249
- FROM topo_examples
250
- WHERE snapshot_id = ? AND trail_id = ?
251
- ORDER BY ordinal ASC`
252
- )
253
- .all(snapshotId, trailId)
254
- .map((row) => ({
255
- description: row.description,
256
- error: row.error,
257
- expected: row.expected === null ? null : parseJson(row.expected),
258
- input: parseJson(row.input),
259
- name: row.name,
260
- ordinal: row.ordinal,
261
- }));
262
-
263
- const readResourceUsage = (
264
- db: Database,
265
- snapshotId: string
266
- ): ReadonlyMap<string, readonly string[]> => {
267
- const rows = db
268
- .query<{ resource_id: string; trail_id: string }, [string]>(
269
- `SELECT resource_id, trail_id
270
- FROM topo_trail_resources
271
- WHERE snapshot_id = ?
272
- ORDER BY resource_id ASC, trail_id ASC`
273
- )
274
- .all(snapshotId);
275
-
276
- const usage = new Map<string, string[]>();
277
- for (const row of rows) {
278
- const trails = usage.get(row.resource_id) ?? [];
279
- trails.push(row.trail_id);
280
- usage.set(row.resource_id, trails);
281
- }
282
-
283
- return new Map(
284
- [...usage.entries()].map(([id, trails]) => [id, trails] as const)
285
- );
286
- };
287
-
288
- export const readTopoStoreSnapshot = (
289
- db: Database,
290
- ref?: TopoStoreRef
291
- ): TopoSnapshot | undefined => readSnapshotRef(db, ref);
292
-
293
- export const listTopoStoreSnapshots = (
294
- db: Database,
295
- options?: ListTopoSnapshotsOptions
296
- ): readonly TopoSnapshot[] => listTopoSnapshots(db, options);
297
-
298
- export const getTopoStoreExport = (
299
- db: Database,
300
- ref?: TopoStoreRef
301
- ): TopoStoreExportRecord | undefined => {
302
- const snapshot = readSnapshotRef(db, ref);
303
- if (snapshot === undefined) {
304
- return undefined;
305
- }
306
-
307
- const stored = getStoredTopoExport(db, snapshot.id);
308
- if (stored === undefined) {
309
- return undefined;
310
- }
311
-
312
- return {
313
- ...stored,
314
- snapshot,
315
- };
316
- };
317
-
318
- export const listTopoStoreTrails = (
319
- db: Database,
320
- options?: {
321
- readonly intent?: TopoStoreTrailRecord['intent'];
322
- readonly snapshot?: TopoStoreRef;
323
- }
324
- ): readonly TopoStoreTrailRecord[] => {
325
- const snapshot = readSnapshotRef(db, options?.snapshot);
326
- if (snapshot === undefined) {
327
- return [];
328
- }
329
-
330
- const baseQuery = `SELECT id, intent, idempotent, has_output, has_examples, example_count, description, pattern, meta, snapshot_id
331
- FROM topo_trails`;
332
-
333
- let rows: TopoTrailRow[];
334
- if (options?.intent === undefined) {
335
- rows = db
336
- .query<TopoTrailRow, [string]>(
337
- `${baseQuery} WHERE snapshot_id = ? ORDER BY id ASC`
338
- )
339
- .all(snapshot.id);
340
- } else if (options.intent === 'write') {
341
- rows = db
342
- .query<TopoTrailRow, [string]>(
343
- `${baseQuery} WHERE snapshot_id = ? AND intent = 'write' ORDER BY id ASC`
344
- )
345
- .all(snapshot.id);
346
- } else {
347
- rows = db
348
- .query<TopoTrailRow, [string, string]>(
349
- `${baseQuery} WHERE snapshot_id = ? AND intent = ? ORDER BY id ASC`
350
- )
351
- .all(snapshot.id, options.intent);
352
- }
353
-
354
- return rows.map(mapTrailRow);
355
- };
356
-
357
- export const getTopoStoreTrail = (
358
- db: Database,
359
- trailId: string,
360
- options?: { readonly snapshot?: TopoStoreRef }
361
- ): TopoStoreTrailDetailRecord | undefined => {
362
- const snapshot = readSnapshotRef(db, options?.snapshot);
363
- if (snapshot === undefined) {
364
- return undefined;
365
- }
366
-
367
- const row = db
368
- .query<TopoTrailRow, [string, string]>(
369
- `SELECT id, intent, idempotent, has_output, has_examples, example_count, description, pattern, meta, snapshot_id
370
- FROM topo_trails
371
- WHERE snapshot_id = ? AND id = ?
372
- LIMIT 1`
373
- )
374
- .get(snapshot.id, trailId);
375
-
376
- if (row === null || row === undefined) {
377
- return undefined;
378
- }
379
-
380
- const storedEntry = readStoredEntry(db, snapshot.id, 'trail', trailId);
381
-
382
- return {
383
- ...mapTrailRow(row),
384
- crosses: readTrailCrossings(db, snapshot.id, trailId),
385
- detours: storedEntry?.detours ?? null,
386
- examples: readTrailExamples(db, snapshot.id, trailId),
387
- resources: readTrailResourceIds(db, snapshot.id, trailId),
388
- };
389
- };
390
-
391
- const mapResourceRow = (
392
- row: TopoResourceRow,
393
- usedBy: readonly string[],
394
- storedEntry?: StoredSurfaceMapEntry
395
- ): TopoStoreResourceRecord => ({
396
- description: storedEntry?.description ?? null,
397
- hasHealth: row.has_health === 1,
398
- hasMock: row.has_mock === 1,
399
- health:
400
- row.has_health === 1 || storedEntry?.healthcheck === true
401
- ? 'available'
402
- : 'none',
403
- id: row.id,
404
- kind: 'resource',
405
- lifetime: 'singleton',
406
- snapshotId: row.snapshot_id,
407
- usedBy,
408
- });
409
-
410
- export const listTopoStoreResources = (
411
- db: Database,
412
- options?: { readonly snapshot?: TopoStoreRef }
413
- ): readonly TopoStoreResourceRecord[] => {
414
- const snapshot = readSnapshotRef(db, options?.snapshot);
415
- if (snapshot === undefined) {
416
- return [];
417
- }
418
-
419
- const usage = readResourceUsage(db, snapshot.id);
420
- const rows = db
421
- .query<TopoResourceRow, [string]>(
422
- `SELECT id, has_mock, has_health, snapshot_id
423
- FROM topo_resources
424
- WHERE snapshot_id = ?
425
- ORDER BY id ASC`
426
- )
427
- .all(snapshot.id);
428
-
429
- const stored = getStoredTopoExport(db, snapshot.id);
430
- const entries = stored
431
- ? (JSON.parse(stored.surfaceMapJson) as StoredSurfaceMap).entries
432
- : [];
433
-
434
- return rows.map((row) =>
435
- mapResourceRow(
436
- row,
437
- usage.get(row.id) ?? [],
438
- entries.find((entry) => entry.id === row.id && entry.kind === 'resource')
439
- )
440
- );
441
- };
442
-
443
- export const getTopoStoreResource = (
444
- db: Database,
445
- resourceId: string,
446
- options?: { readonly snapshot?: TopoStoreRef }
447
- ): TopoStoreResourceRecord | undefined => {
448
- const snapshot = readSnapshotRef(db, options?.snapshot);
449
- if (snapshot === undefined) {
450
- return undefined;
451
- }
452
-
453
- const row = db
454
- .query<TopoResourceRow, [string, string]>(
455
- `SELECT id, has_mock, has_health, snapshot_id
456
- FROM topo_resources
457
- WHERE snapshot_id = ? AND id = ?
458
- LIMIT 1`
459
- )
460
- .get(snapshot.id, resourceId);
461
-
462
- if (row === null || row === undefined) {
463
- return undefined;
464
- }
465
-
466
- const usage = readResourceUsage(db, snapshot.id);
467
- return mapResourceRow(
468
- row,
469
- usage.get(resourceId) ?? [],
470
- readStoredEntry(db, snapshot.id, 'resource', resourceId)
471
- );
472
- };
473
-
474
- export const queryTopoStore = <TRow extends Record<string, unknown>>(
475
- db: Database,
476
- sql: string,
477
- bindings?: readonly SQLQueryBindings[]
478
- ): readonly TRow[] =>
479
- db
480
- .query<TRow, SQLQueryBindings[]>(sql)
481
- .all(...(bindings === undefined ? [] : [...bindings]));