ai-database 2.1.3 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. package/CHANGELOG.md +35 -1
  2. package/README.md +880 -669
  3. package/dist/actions.d.ts +2 -2
  4. package/dist/actions.d.ts.map +1 -1
  5. package/dist/actions.js +1 -1
  6. package/dist/actions.js.map +1 -1
  7. package/dist/ai-promise-db.d.ts +49 -23
  8. package/dist/ai-promise-db.d.ts.map +1 -1
  9. package/dist/ai-promise-db.js +91 -63
  10. package/dist/ai-promise-db.js.map +1 -1
  11. package/dist/authorization.d.ts.map +1 -1
  12. package/dist/authorization.js +38 -30
  13. package/dist/authorization.js.map +1 -1
  14. package/dist/cascade-orchestrator.d.ts +404 -0
  15. package/dist/cascade-orchestrator.d.ts.map +1 -0
  16. package/dist/cascade-orchestrator.js +828 -0
  17. package/dist/cascade-orchestrator.js.map +1 -0
  18. package/dist/cascade-write-strategy.d.ts +584 -0
  19. package/dist/cascade-write-strategy.d.ts.map +1 -0
  20. package/dist/cascade-write-strategy.js +590 -0
  21. package/dist/cascade-write-strategy.js.map +1 -0
  22. package/dist/ch-adapter.d.ts +358 -0
  23. package/dist/ch-adapter.d.ts.map +1 -0
  24. package/dist/ch-adapter.js +929 -0
  25. package/dist/ch-adapter.js.map +1 -0
  26. package/dist/client/index.d.ts +42 -0
  27. package/dist/client/index.d.ts.map +1 -0
  28. package/dist/client/index.js +43 -0
  29. package/dist/client/index.js.map +1 -0
  30. package/dist/client.d.ts +266 -0
  31. package/dist/client.d.ts.map +1 -0
  32. package/dist/client.js +81 -0
  33. package/dist/client.js.map +1 -0
  34. package/dist/constants.d.ts +64 -1
  35. package/dist/constants.d.ts.map +1 -1
  36. package/dist/constants.js +52 -2
  37. package/dist/constants.js.map +1 -1
  38. package/dist/dataloader.d.ts +99 -0
  39. package/dist/dataloader.d.ts.map +1 -0
  40. package/dist/dataloader.js +225 -0
  41. package/dist/dataloader.js.map +1 -0
  42. package/dist/db-provider-port.d.ts +501 -0
  43. package/dist/db-provider-port.d.ts.map +1 -0
  44. package/dist/db-provider-port.js +113 -0
  45. package/dist/db-provider-port.js.map +1 -0
  46. package/dist/digital-objects-provider.d.ts +49 -0
  47. package/dist/digital-objects-provider.d.ts.map +1 -0
  48. package/dist/digital-objects-provider.js +55 -0
  49. package/dist/digital-objects-provider.js.map +1 -0
  50. package/dist/do-sqlite-adapter.d.ts +402 -0
  51. package/dist/do-sqlite-adapter.d.ts.map +1 -0
  52. package/dist/do-sqlite-adapter.js +745 -0
  53. package/dist/do-sqlite-adapter.js.map +1 -0
  54. package/dist/docs-rels/custom-types.d.ts +134 -0
  55. package/dist/docs-rels/custom-types.d.ts.map +1 -0
  56. package/dist/docs-rels/custom-types.js +70 -0
  57. package/dist/docs-rels/custom-types.js.map +1 -0
  58. package/dist/docs-rels/index.d.ts +16 -0
  59. package/dist/docs-rels/index.d.ts.map +1 -0
  60. package/dist/docs-rels/index.js +16 -0
  61. package/dist/docs-rels/index.js.map +1 -0
  62. package/dist/docs-rels/migrations/index.d.ts +30 -0
  63. package/dist/docs-rels/migrations/index.d.ts.map +1 -0
  64. package/dist/docs-rels/migrations/index.js +128 -0
  65. package/dist/docs-rels/migrations/index.js.map +1 -0
  66. package/dist/docs-rels/schema.d.ts +2961 -0
  67. package/dist/docs-rels/schema.d.ts.map +1 -0
  68. package/dist/docs-rels/schema.js +244 -0
  69. package/dist/docs-rels/schema.js.map +1 -0
  70. package/dist/durable-clickhouse.d.ts.map +1 -1
  71. package/dist/durable-clickhouse.js +16 -13
  72. package/dist/durable-clickhouse.js.map +1 -1
  73. package/dist/durable-promise.d.ts.map +1 -1
  74. package/dist/durable-promise.js +34 -15
  75. package/dist/durable-promise.js.map +1 -1
  76. package/dist/errors.d.ts +127 -0
  77. package/dist/errors.d.ts.map +1 -0
  78. package/dist/errors.js +210 -0
  79. package/dist/errors.js.map +1 -0
  80. package/dist/eventbridge.d.ts +117 -0
  81. package/dist/eventbridge.d.ts.map +1 -0
  82. package/dist/eventbridge.js +238 -0
  83. package/dist/eventbridge.js.map +1 -0
  84. package/dist/events.d.ts +2 -2
  85. package/dist/events.d.ts.map +1 -1
  86. package/dist/events.js +1 -1
  87. package/dist/events.js.map +1 -1
  88. package/dist/execution-queue.d.ts.map +1 -1
  89. package/dist/execution-queue.js +4 -5
  90. package/dist/execution-queue.js.map +1 -1
  91. package/dist/index.d.ts +35 -8
  92. package/dist/index.d.ts.map +1 -1
  93. package/dist/index.js +106 -6
  94. package/dist/index.js.map +1 -1
  95. package/dist/linguistic.d.ts +3 -108
  96. package/dist/linguistic.d.ts.map +1 -1
  97. package/dist/linguistic.js +3 -372
  98. package/dist/linguistic.js.map +1 -1
  99. package/dist/logger.d.ts +132 -0
  100. package/dist/logger.d.ts.map +1 -0
  101. package/dist/logger.js +137 -0
  102. package/dist/logger.js.map +1 -0
  103. package/dist/memory-provider.d.ts +128 -0
  104. package/dist/memory-provider.d.ts.map +1 -1
  105. package/dist/memory-provider.js +592 -257
  106. package/dist/memory-provider.js.map +1 -1
  107. package/dist/pg-adapter.d.ts +424 -0
  108. package/dist/pg-adapter.d.ts.map +1 -0
  109. package/dist/pg-adapter.js +921 -0
  110. package/dist/pg-adapter.js.map +1 -0
  111. package/dist/pipelines-iceberg-emitter.d.ts +327 -0
  112. package/dist/pipelines-iceberg-emitter.d.ts.map +1 -0
  113. package/dist/pipelines-iceberg-emitter.js +351 -0
  114. package/dist/pipelines-iceberg-emitter.js.map +1 -0
  115. package/dist/provider-capabilities.d.ts +146 -0
  116. package/dist/provider-capabilities.d.ts.map +1 -0
  117. package/dist/provider-capabilities.js +214 -0
  118. package/dist/provider-capabilities.js.map +1 -0
  119. package/dist/rdb-provider-adapter.d.ts +195 -0
  120. package/dist/rdb-provider-adapter.d.ts.map +1 -0
  121. package/dist/rdb-provider-adapter.js +291 -0
  122. package/dist/rdb-provider-adapter.js.map +1 -0
  123. package/dist/schema/cascade.d.ts +48 -17
  124. package/dist/schema/cascade.d.ts.map +1 -1
  125. package/dist/schema/cascade.js +477 -278
  126. package/dist/schema/cascade.js.map +1 -1
  127. package/dist/schema/definition-caches.d.ts +24 -0
  128. package/dist/schema/definition-caches.d.ts.map +1 -0
  129. package/dist/schema/definition-caches.js +26 -0
  130. package/dist/schema/definition-caches.js.map +1 -0
  131. package/dist/schema/dependency-graph.d.ts +21 -109
  132. package/dist/schema/dependency-graph.d.ts.map +1 -1
  133. package/dist/schema/dependency-graph.js +25 -333
  134. package/dist/schema/dependency-graph.js.map +1 -1
  135. package/dist/schema/diff.d.ts +103 -0
  136. package/dist/schema/diff.d.ts.map +1 -0
  137. package/dist/schema/diff.js +329 -0
  138. package/dist/schema/diff.js.map +1 -0
  139. package/dist/schema/entity-operations.d.ts +99 -0
  140. package/dist/schema/entity-operations.d.ts.map +1 -0
  141. package/dist/schema/entity-operations.js +818 -0
  142. package/dist/schema/entity-operations.js.map +1 -0
  143. package/dist/schema/index.d.ts +28 -34
  144. package/dist/schema/index.d.ts.map +1 -1
  145. package/dist/schema/index.js +454 -521
  146. package/dist/schema/index.js.map +1 -1
  147. package/dist/schema/migration.d.ts +205 -0
  148. package/dist/schema/migration.d.ts.map +1 -0
  149. package/dist/schema/migration.js +327 -0
  150. package/dist/schema/migration.js.map +1 -0
  151. package/dist/schema/nl-query-generator.d.ts +68 -0
  152. package/dist/schema/nl-query-generator.d.ts.map +1 -0
  153. package/dist/schema/nl-query-generator.js +362 -0
  154. package/dist/schema/nl-query-generator.js.map +1 -0
  155. package/dist/schema/nl-query.d.ts +65 -0
  156. package/dist/schema/nl-query.d.ts.map +1 -0
  157. package/dist/schema/nl-query.js +178 -0
  158. package/dist/schema/nl-query.js.map +1 -0
  159. package/dist/schema/parse.d.ts.map +1 -1
  160. package/dist/schema/parse.js +144 -89
  161. package/dist/schema/parse.js.map +1 -1
  162. package/dist/schema/provider.d.ts +37 -0
  163. package/dist/schema/provider.d.ts.map +1 -1
  164. package/dist/schema/provider.js +15 -7
  165. package/dist/schema/provider.js.map +1 -1
  166. package/dist/schema/resolve.d.ts +46 -5
  167. package/dist/schema/resolve.d.ts.map +1 -1
  168. package/dist/schema/resolve.js +237 -95
  169. package/dist/schema/resolve.js.map +1 -1
  170. package/dist/schema/search-utils.d.ts +76 -0
  171. package/dist/schema/search-utils.d.ts.map +1 -0
  172. package/dist/schema/search-utils.js +86 -0
  173. package/dist/schema/search-utils.js.map +1 -0
  174. package/dist/schema/seed.d.ts +53 -0
  175. package/dist/schema/seed.d.ts.map +1 -0
  176. package/dist/schema/seed.js +94 -0
  177. package/dist/schema/seed.js.map +1 -0
  178. package/dist/schema/semantic.d.ts +10 -0
  179. package/dist/schema/semantic.d.ts.map +1 -1
  180. package/dist/schema/semantic.js +192 -86
  181. package/dist/schema/semantic.js.map +1 -1
  182. package/dist/schema/sub-apis.d.ts +52 -0
  183. package/dist/schema/sub-apis.d.ts.map +1 -0
  184. package/dist/schema/sub-apis.js +216 -0
  185. package/dist/schema/sub-apis.js.map +1 -0
  186. package/dist/schema/system-entities.d.ts +42 -0
  187. package/dist/schema/system-entities.d.ts.map +1 -0
  188. package/dist/schema/system-entities.js +101 -0
  189. package/dist/schema/system-entities.js.map +1 -0
  190. package/dist/schema/types.d.ts +91 -9
  191. package/dist/schema/types.d.ts.map +1 -1
  192. package/dist/schema/union-fallback.d.ts.map +1 -1
  193. package/dist/schema/union-fallback.js +21 -15
  194. package/dist/schema/union-fallback.js.map +1 -1
  195. package/dist/schema/value-generators/ai.d.ts +54 -0
  196. package/dist/schema/value-generators/ai.d.ts.map +1 -0
  197. package/dist/schema/value-generators/ai.js +136 -0
  198. package/dist/schema/value-generators/ai.js.map +1 -0
  199. package/dist/schema/value-generators/index.d.ts +126 -0
  200. package/dist/schema/value-generators/index.d.ts.map +1 -0
  201. package/dist/schema/value-generators/index.js +219 -0
  202. package/dist/schema/value-generators/index.js.map +1 -0
  203. package/dist/schema/value-generators/placeholder.d.ts +52 -0
  204. package/dist/schema/value-generators/placeholder.d.ts.map +1 -0
  205. package/dist/schema/value-generators/placeholder.js +328 -0
  206. package/dist/schema/value-generators/placeholder.js.map +1 -0
  207. package/dist/schema/value-generators/types.d.ts +116 -0
  208. package/dist/schema/value-generators/types.d.ts.map +1 -0
  209. package/dist/schema/value-generators/types.js +11 -0
  210. package/dist/schema/value-generators/types.js.map +1 -0
  211. package/dist/schema/version.d.ts +111 -0
  212. package/dist/schema/version.d.ts.map +1 -0
  213. package/dist/schema/version.js +190 -0
  214. package/dist/schema/version.js.map +1 -0
  215. package/dist/schema.d.ts +1095 -24
  216. package/dist/schema.d.ts.map +1 -1
  217. package/dist/schema.js +2852 -40
  218. package/dist/schema.js.map +1 -1
  219. package/dist/semantic-vectors.d.ts +39 -0
  220. package/dist/semantic-vectors.d.ts.map +1 -0
  221. package/dist/semantic-vectors.js +334 -0
  222. package/dist/semantic-vectors.js.map +1 -0
  223. package/dist/semantic.d.ts +29 -1
  224. package/dist/semantic.d.ts.map +1 -1
  225. package/dist/semantic.js +26 -16
  226. package/dist/semantic.js.map +1 -1
  227. package/dist/telemetry.d.ts +128 -0
  228. package/dist/telemetry.d.ts.map +1 -0
  229. package/dist/telemetry.js +305 -0
  230. package/dist/telemetry.js.map +1 -0
  231. package/dist/tests.d.ts.map +1 -1
  232. package/dist/tests.js +30 -22
  233. package/dist/tests.js.map +1 -1
  234. package/dist/type-guards.d.ts +50 -5
  235. package/dist/type-guards.d.ts.map +1 -1
  236. package/dist/type-guards.js +87 -16
  237. package/dist/type-guards.js.map +1 -1
  238. package/dist/types.d.ts +33 -245
  239. package/dist/types.d.ts.map +1 -1
  240. package/dist/types.js +62 -72
  241. package/dist/types.js.map +1 -1
  242. package/dist/validation.d.ts +2 -5
  243. package/dist/validation.d.ts.map +1 -1
  244. package/dist/validation.js +65 -93
  245. package/dist/validation.js.map +1 -1
  246. package/dist/worker/db-provider.d.ts +168 -0
  247. package/dist/worker/db-provider.d.ts.map +1 -0
  248. package/dist/worker/db-provider.js +277 -0
  249. package/dist/worker/db-provider.js.map +1 -0
  250. package/dist/worker/index.d.ts +35 -0
  251. package/dist/worker/index.d.ts.map +1 -0
  252. package/dist/worker/index.js +37 -0
  253. package/dist/worker/index.js.map +1 -0
  254. package/dist/worker.d.ts +779 -0
  255. package/dist/worker.d.ts.map +1 -0
  256. package/dist/worker.js +2786 -0
  257. package/dist/worker.js.map +1 -0
  258. package/package.json +46 -16
  259. package/src/docs-rels/migrations/0001-init.sql +125 -0
  260. package/LICENSE +0 -21
@@ -0,0 +1,351 @@
1
+ /**
2
+ * Pipelines → Iceberg analytical fan-out emitter — Phase 2 final, bead `aip-0ypt`.
3
+ *
4
+ * Implements the {@link AnalyticalEmitter} contract surfaced by
5
+ * {@link CascadeWriteStrategy} so cascade writes can dual-write into
6
+ * Iceberg via Cloudflare Pipelines without changing the strategy or
7
+ * orchestrator surface. Per
8
+ * [ADR-0003](../../../docs/adr/0003-storage-strategy-pg-clickhouse-default.md),
9
+ * Stack B's storage shape is:
10
+ *
11
+ * ```text
12
+ * cascade write
13
+ * │
14
+ * ▼
15
+ * DO SQLite (per-cascade, transactional, source of truth for traversal)
16
+ * │
17
+ * └──► CascadeWriteStrategy.analyticalEmitter ──► Cloudflare Pipelines ──► R2 Iceberg
18
+ * (analytical SOR; ClickHouse reads from here)
19
+ * ```
20
+ *
21
+ * The transactional path through DO SQLite is the source of truth for
22
+ * cascade correctness. The analytical fan-out is **fire-and-forget** on
23
+ * the hot path: emitter failures MUST NOT fail the cascade write. The
24
+ * `CascadeWriteStrategy` already swallows thrown errors from the
25
+ * emitter; this module additionally never throws — even on completely
26
+ * misconfigured bindings — so callers get the same shape regardless of
27
+ * runtime.
28
+ *
29
+ * ## Schema mapping
30
+ *
31
+ * Iceberg tables for `things` and `actions` mirror the SVO surface used
32
+ * by the PG/CH/DO SQLite adapters. Columns are kept in lowercase
33
+ * snake_case (Iceberg is case-insensitive but tooling typically
34
+ * normalises this way):
35
+ *
36
+ * **things table**
37
+ * - `id` STRING (Thing id; content-hashed by the orchestrator)
38
+ * - `type` STRING (Thing `$type`)
39
+ * - `data` STRING (jsonb-style — emitted as a stringified JSON blob;
40
+ * downstream readers (CH `JSONExtract`, DataFusion `arrow_cast`) parse
41
+ * on read. Iceberg has STRUCT columns but cascade Things are
42
+ * open-shape so we keep the column STRING)
43
+ * - `cascade_id` STRING (the cascade this row belongs to; partition key)
44
+ * - `tenant_id` STRING NULL (when sharded by tenant)
45
+ * - `shard_key` STRING (the strategy's routing key, e.g. `cascade:abc`)
46
+ * - `created_at` TIMESTAMP (emit time; stable)
47
+ * - `updated_at` TIMESTAMP (emit time; bumped on re-emit)
48
+ *
49
+ * **actions table** — wire-compatible with `SVOAction`
50
+ * - `id` STRING (Action id; orchestrator-supplied or adapter-generated)
51
+ * - `verb` STRING
52
+ * - `subject` STRING NULL
53
+ * - `object` STRING NULL
54
+ * - `roles` STRING (JSON-stringified Frame role map)
55
+ * - `data` STRING (JSON-stringified payload)
56
+ * - `status` STRING (`pending` | `completed` | `failed` | `cancelled`)
57
+ * - `cascade_id` STRING (partition key)
58
+ * - `tenant_id` STRING NULL
59
+ * - `shard_key` STRING
60
+ * - `timestamp` TIMESTAMP (emit time)
61
+ *
62
+ * Schema bootstrap (creating the Iceberg tables) is a deployment-time
63
+ * concern; this emitter only writes records into an existing table
64
+ * via the Pipelines binding's `send()`.
65
+ *
66
+ * ## Bindings
67
+ *
68
+ * The emitter accepts a structurally-typed
69
+ * {@link PipelinesStreamBindingLike} so the module compiles in plain
70
+ * Node tests without `@cloudflare/workers-types`. Real Pipelines
71
+ * bindings produced by `wrangler.toml` satisfy this shape at runtime.
72
+ * For non-Workers callers (Node / dev / batch jobs) an
73
+ * {@link HttpPipelinesEmitterOptions} HTTP fallback is supported,
74
+ * issuing `POST` requests against the Pipelines stream endpoint.
75
+ *
76
+ * ## Exactly-once / dedup
77
+ *
78
+ * Cloudflare Pipelines is at-least-once by default. Cascade entity
79
+ * ids are content-hashed by the orchestrator (same inputs → same id),
80
+ * so re-emits of the same cascade re-use the same `id` field — Iceberg
81
+ * MERGE-on-read jobs (or the Pipelines binding's optional dedup key)
82
+ * collapse duplicates downstream. Callers wanting strict
83
+ * exactly-once semantics should configure dedup on the Pipelines
84
+ * stream itself; this emitter exposes `dedupKey?: 'id' | null` to
85
+ * indicate which field to use.
86
+ *
87
+ * @see {@link ../../../docs/adr/0003-storage-strategy-pg-clickhouse-default.md}
88
+ * @see {@link ./cascade-write-strategy.ts}
89
+ * @packageDocumentation
90
+ */
91
+ // =============================================================================
92
+ // Public API
93
+ // =============================================================================
94
+ /**
95
+ * Create an {@link AnalyticalEmitter} that fans out cascade writes
96
+ * into Iceberg via Cloudflare Pipelines.
97
+ *
98
+ * The returned emitter satisfies the
99
+ * {@link CascadeWriteStrategy.analyticalEmitter} contract — pass it
100
+ * directly to {@link CascadeWriteStrategy} or
101
+ * {@link generateCascade} via the `analyticalEmitter` option.
102
+ *
103
+ * @example Workers binding mode
104
+ * ```ts
105
+ * import { createPipelinesIcebergEmitter, generateCascade } from 'ai-database'
106
+ *
107
+ * const emitter = createPipelinesIcebergEmitter({
108
+ * binding: env.ANALYTICAL_PIPE,
109
+ * thingsTable: 'aidb.things',
110
+ * actionsTable: 'aidb.actions',
111
+ * tenantId: 'acme',
112
+ * })
113
+ *
114
+ * await generateCascade({
115
+ * adapter,
116
+ * rootNoun: 'Customer',
117
+ * analyticalEmitter: emitter,
118
+ * // ...
119
+ * })
120
+ * ```
121
+ *
122
+ * @example Node HTTP fallback (dev / batch)
123
+ * ```ts
124
+ * import { createHttpPipelinesIcebergEmitter } from 'ai-database'
125
+ *
126
+ * const emitter = createHttpPipelinesIcebergEmitter({
127
+ * url: process.env.PIPELINES_URL,
128
+ * authToken: process.env.PIPELINES_TOKEN,
129
+ * })
130
+ * ```
131
+ */
132
+ export function createPipelinesIcebergEmitter(options) {
133
+ const thingsBinding = options.thingsBinding ?? options.binding;
134
+ const actionsBinding = options.actionsBinding ?? options.binding;
135
+ if (!thingsBinding && !actionsBinding) {
136
+ throw new Error('createPipelinesIcebergEmitter: at least one of `binding`, ' +
137
+ '`thingsBinding`, or `actionsBinding` must be provided. For ' +
138
+ 'non-Workers callers, use createHttpPipelinesIcebergEmitter() ' +
139
+ 'with an HTTPS endpoint URL instead.');
140
+ }
141
+ return makeEmitter({
142
+ options,
143
+ sendThings: thingsBinding ? (rows) => Promise.resolve(thingsBinding.send(rows)) : null,
144
+ sendActions: actionsBinding ? (rows) => Promise.resolve(actionsBinding.send(rows)) : null,
145
+ });
146
+ }
147
+ /**
148
+ * Create an {@link AnalyticalEmitter} that fans out cascade writes
149
+ * into Iceberg via the Pipelines HTTPS stream endpoint.
150
+ *
151
+ * Used by non-Workers callers (Node / dev / batch jobs). Workers
152
+ * deployments should prefer {@link createPipelinesIcebergEmitter}
153
+ * for lower latency.
154
+ */
155
+ export function createHttpPipelinesIcebergEmitter(options) {
156
+ const thingsUrl = options.thingsUrl ?? options.url;
157
+ const actionsUrl = options.actionsUrl ?? options.url;
158
+ if (!thingsUrl && !actionsUrl) {
159
+ throw new Error('createHttpPipelinesIcebergEmitter: at least one of `url`, ' +
160
+ '`thingsUrl`, or `actionsUrl` must be provided.');
161
+ }
162
+ const fetchImpl = options.fetch ??
163
+ ((input, init) => {
164
+ // Defer to the runtime's global fetch. Pulled inline so tests can
165
+ // pass a structural fake without monkey-patching globals.
166
+ const g = globalThis;
167
+ if (typeof g.fetch !== 'function') {
168
+ return Promise.reject(new Error('createHttpPipelinesIcebergEmitter: no global `fetch` available. ' +
169
+ 'Pass `fetch` in options for non-Worker / non-Node-18+ environments.'));
170
+ }
171
+ return g.fetch(input, init);
172
+ });
173
+ const headers = { 'Content-Type': 'application/json' };
174
+ if (options.authToken)
175
+ headers['Authorization'] = `Bearer ${options.authToken}`;
176
+ const send = async (url, rows) => {
177
+ const res = await fetchImpl(url, {
178
+ method: 'POST',
179
+ headers,
180
+ body: JSON.stringify(rows),
181
+ });
182
+ if (!res.ok) {
183
+ throw new Error(`Pipelines HTTP send failed: ${res.status} ${res.statusText}`);
184
+ }
185
+ };
186
+ return makeEmitter({
187
+ options,
188
+ sendThings: thingsUrl ? (rows) => send(thingsUrl, rows) : null,
189
+ sendActions: actionsUrl
190
+ ? (rows) => send(actionsUrl, thingsUrl === actionsUrl ? rows : rows /* same payload shape */)
191
+ : null,
192
+ });
193
+ }
194
+ function makeEmitter(args) {
195
+ const thingsTable = args.options.thingsTable ?? 'things';
196
+ const actionsTable = args.options.actionsTable ?? 'actions';
197
+ const dedupKey = args.options.dedupKey === undefined ? 'id' : args.options.dedupKey;
198
+ const nowFn = args.options.now ?? (() => new Date().toISOString());
199
+ const logger = args.options.logger;
200
+ const awaitSend = args.options.awaitSend ?? false;
201
+ const optionTenantId = args.options.tenantId;
202
+ return async (input) => {
203
+ // Resolve cascade-routing columns from the shard ref. The strategy
204
+ // guarantees `shard.context` carries `cascadeId` / `tenantId` when
205
+ // the active strategy needed them.
206
+ const shard = input.shard;
207
+ const cascadeId = resolveCascadeId(shard);
208
+ const tenantId = optionTenantId ?? resolveTenantId(shard);
209
+ const shardKey = shard.key;
210
+ const timestamp = nowFn();
211
+ const thingsRows = buildThingsRows(input.batch, {
212
+ thingsTable,
213
+ cascadeId,
214
+ tenantId,
215
+ shardKey,
216
+ timestamp,
217
+ dedupKey,
218
+ });
219
+ const actionsRows = buildActionsRows(input.batch, {
220
+ actionsTable,
221
+ cascadeId,
222
+ tenantId,
223
+ shardKey,
224
+ timestamp,
225
+ dedupKey,
226
+ });
227
+ const tasks = [];
228
+ if (thingsRows.length > 0 && args.sendThings) {
229
+ const task = Promise.resolve()
230
+ .then(() => args.sendThings(thingsRows))
231
+ .catch((err) => {
232
+ logger?.warn?.('pipelines-iceberg-emitter:things:send-failed', {
233
+ error: errorMessage(err),
234
+ rows: thingsRows.length,
235
+ shardKey,
236
+ });
237
+ });
238
+ tasks.push(task);
239
+ }
240
+ if (actionsRows.length > 0 && args.sendActions) {
241
+ const task = Promise.resolve()
242
+ .then(() => args.sendActions(actionsRows))
243
+ .catch((err) => {
244
+ logger?.warn?.('pipelines-iceberg-emitter:actions:send-failed', {
245
+ error: errorMessage(err),
246
+ rows: actionsRows.length,
247
+ shardKey,
248
+ });
249
+ });
250
+ tasks.push(task);
251
+ }
252
+ if (awaitSend && tasks.length > 0) {
253
+ await Promise.all(tasks);
254
+ }
255
+ };
256
+ }
257
+ function buildThingsRows(batch, ctx) {
258
+ const things = batch.things ?? [];
259
+ if (things.length === 0)
260
+ return [];
261
+ const rows = [];
262
+ for (const t of things) {
263
+ const row = {
264
+ id: t.id,
265
+ type: t.type,
266
+ data: stableJsonStringify(t.data),
267
+ cascade_id: ctx.cascadeId,
268
+ tenant_id: ctx.tenantId,
269
+ shard_key: ctx.shardKey,
270
+ created_at: ctx.timestamp,
271
+ updated_at: ctx.timestamp,
272
+ _table: ctx.thingsTable,
273
+ };
274
+ if (ctx.dedupKey)
275
+ row['_dedup_key'] = row[ctx.dedupKey];
276
+ rows.push(row);
277
+ }
278
+ return rows;
279
+ }
280
+ function buildActionsRows(batch, ctx) {
281
+ const actions = batch.actions ?? [];
282
+ if (actions.length === 0)
283
+ return [];
284
+ const rows = [];
285
+ for (const a of actions) {
286
+ const row = {
287
+ id: a.id ?? generateActionId(ctx.cascadeId, ctx.timestamp, rows.length),
288
+ verb: a.verb,
289
+ subject: a.subject ?? null,
290
+ object: a.object ?? null,
291
+ roles: stableJsonStringify(a.roles ?? {}),
292
+ data: stableJsonStringify(a.data ?? {}),
293
+ status: a.status ?? 'completed',
294
+ cascade_id: ctx.cascadeId,
295
+ tenant_id: ctx.tenantId,
296
+ shard_key: ctx.shardKey,
297
+ timestamp: ctx.timestamp,
298
+ _table: ctx.actionsTable,
299
+ };
300
+ if (ctx.dedupKey)
301
+ row['_dedup_key'] = row[ctx.dedupKey];
302
+ rows.push(row);
303
+ }
304
+ return rows;
305
+ }
306
+ // =============================================================================
307
+ // Internals — utilities
308
+ // =============================================================================
309
+ function resolveCascadeId(shard) {
310
+ const ctxId = shard.context.cascadeId;
311
+ if (typeof ctxId === 'string' && ctxId.length > 0)
312
+ return ctxId;
313
+ // Fall back to the shard key — for `partitioned-by-tenant` and
314
+ // `unsharded` strategies there is no per-cascade id, so the routing
315
+ // key is the best we can do. Iceberg readers can group on it.
316
+ return shard.key;
317
+ }
318
+ function resolveTenantId(shard) {
319
+ const t = shard.context.tenantId;
320
+ return typeof t === 'string' && t.length > 0 ? t : null;
321
+ }
322
+ /**
323
+ * Stable JSON stringify — keys sorted recursively. Iceberg dedup at
324
+ * compaction time depends on identical row bytes for the same logical
325
+ * row; un-sorted key ordering would defeat that.
326
+ */
327
+ function stableJsonStringify(value) {
328
+ return JSON.stringify(value, (_key, val) => {
329
+ if (val === null || typeof val !== 'object' || Array.isArray(val))
330
+ return val;
331
+ const sortedKeys = Object.keys(val).sort();
332
+ const result = {};
333
+ for (const k of sortedKeys) {
334
+ result[k] = val[k];
335
+ }
336
+ return result;
337
+ });
338
+ }
339
+ /**
340
+ * Generate a deterministic-enough Action id when the orchestrator
341
+ * didn't supply one. Production callers always supply Action ids via
342
+ * the orchestrator's content-hash; this is a safety net for ad-hoc
343
+ * `writeBatch` callers.
344
+ */
345
+ function generateActionId(cascadeId, timestamp, index) {
346
+ return `act-${cascadeId.slice(0, 16)}-${timestamp.replace(/[^0-9]/g, '').slice(0, 14)}-${index}`;
347
+ }
348
+ function errorMessage(err) {
349
+ return err instanceof Error ? err.message : String(err);
350
+ }
351
+ //# sourceMappingURL=pipelines-iceberg-emitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipelines-iceberg-emitter.js","sourceRoot":"","sources":["../src/pipelines-iceberg-emitter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Provider Capability Detection and Management
3
+ *
4
+ * This module provides runtime detection of provider capabilities,
5
+ * enabling graceful degradation when advanced features are unavailable.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ import type { DBProvider } from './schema.js';
10
+ /**
11
+ * Capability flags indicating which features a provider supports
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const capabilities: ProviderCapabilities = {
16
+ * hasSemanticSearch: true,
17
+ * hasEvents: true,
18
+ * hasActions: true,
19
+ * hasArtifacts: true,
20
+ * hasBatchOperations: true,
21
+ * }
22
+ * ```
23
+ */
24
+ export interface ProviderCapabilities {
25
+ /** Whether the provider supports semantic/vector search */
26
+ hasSemanticSearch: boolean;
27
+ /** Whether the provider supports event emission and subscription */
28
+ hasEvents: boolean;
29
+ /** Whether the provider supports durable actions (pending/active/completed) */
30
+ hasActions: boolean;
31
+ /** Whether the provider supports artifact storage (embeddings, caches) */
32
+ hasArtifacts: boolean;
33
+ /** Whether the provider supports batch operations with concurrency control */
34
+ hasBatchOperations: boolean;
35
+ }
36
+ /**
37
+ * Detect which capabilities a provider supports by examining its methods
38
+ *
39
+ * Probes the provider for the presence of advanced methods to determine
40
+ * which features are available. Results are cached per-provider.
41
+ *
42
+ * @param provider - The database provider to inspect
43
+ * @returns Detected capabilities
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * const provider = createMemoryProvider()
48
+ * const capabilities = await detectCapabilities(provider)
49
+ *
50
+ * if (capabilities.hasSemanticSearch) {
51
+ * const results = await provider.semanticSearch('Post', 'machine learning')
52
+ * } else {
53
+ * const results = await provider.search('Post', 'machine learning')
54
+ * }
55
+ * ```
56
+ */
57
+ export declare function detectCapabilities(provider: DBProvider): Promise<ProviderCapabilities>;
58
+ /**
59
+ * Clear the capability cache for a specific provider
60
+ *
61
+ * Useful when a provider's capabilities change dynamically.
62
+ *
63
+ * @param provider - The provider to clear from cache
64
+ */
65
+ export declare function clearCapabilityCache(provider: DBProvider): void;
66
+ /**
67
+ * Error thrown when attempting to use a feature that the provider doesn't support
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * try {
72
+ * await provider.semanticSearch('Post', 'query')
73
+ * } catch (e) {
74
+ * if (isCapabilityNotSupportedError(e)) {
75
+ * console.log(`${e.capability} is not supported, using fallback...`)
76
+ * }
77
+ * throw e
78
+ * }
79
+ * ```
80
+ */
81
+ export declare class CapabilityNotSupportedError extends Error {
82
+ /** The capability that was requested but not supported */
83
+ readonly capability: string;
84
+ /** Optional suggested alternative */
85
+ readonly alternative?: string | undefined;
86
+ readonly code = "CAPABILITY_NOT_SUPPORTED";
87
+ readonly name = "CapabilityNotSupportedError";
88
+ constructor(
89
+ /** The capability that was requested but not supported */
90
+ capability: string,
91
+ /** Optional custom error message */
92
+ message?: string,
93
+ /** Optional suggested alternative */
94
+ alternative?: string | undefined);
95
+ }
96
+ /**
97
+ * Type guard to check if an error is a CapabilityNotSupportedError
98
+ *
99
+ * @param error - The error to check
100
+ * @returns True if the error is a CapabilityNotSupportedError
101
+ */
102
+ export declare function isCapabilityNotSupportedError(error: unknown): error is CapabilityNotSupportedError;
103
+ /**
104
+ * Require a capability to be available, throwing if not
105
+ *
106
+ * Use this before calling methods that require specific capabilities.
107
+ *
108
+ * @param capabilities - The detected capabilities
109
+ * @param capability - The capability key to require
110
+ * @param message - Optional custom error message
111
+ * @throws CapabilityNotSupportedError if the capability is not available
112
+ *
113
+ * @example
114
+ * ```ts
115
+ * const capabilities = await detectCapabilities(provider)
116
+ * requireCapability(capabilities, 'hasSemanticSearch')
117
+ * // Safe to call semanticSearch now
118
+ * ```
119
+ */
120
+ export declare function requireCapability(capabilities: ProviderCapabilities, capability: keyof ProviderCapabilities, message?: string): void;
121
+ /**
122
+ * Log a warning if a capability is unavailable (only once per capability)
123
+ *
124
+ * @param capabilities - The detected capabilities
125
+ * @param capability - The capability key to check
126
+ * @param featureName - Human-readable name for the warning message
127
+ *
128
+ * @example
129
+ * ```ts
130
+ * warnIfUnavailable(capabilities, 'hasSemanticSearch', 'semanticSearch')
131
+ * // Logs: "Warning: semanticSearch is not available with this provider"
132
+ * ```
133
+ */
134
+ export declare function warnIfUnavailable(capabilities: ProviderCapabilities, capability: keyof ProviderCapabilities, featureName: string): void;
135
+ /**
136
+ * Clear warning suppression (useful for testing)
137
+ */
138
+ export declare function clearWarningHistory(): void;
139
+ /**
140
+ * Standard capability matrix for known providers
141
+ *
142
+ * This is a reference for documentation purposes. Actual capabilities
143
+ * are detected at runtime using detectCapabilities().
144
+ */
145
+ export declare const PROVIDER_CAPABILITY_MATRIX: Record<string, ProviderCapabilities>;
146
+ //# sourceMappingURL=provider-capabilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-capabilities.d.ts","sourceRoot":"","sources":["../src/provider-capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAO7C;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,oBAAoB;IACnC,2DAA2D;IAC3D,iBAAiB,EAAE,OAAO,CAAA;IAC1B,oEAAoE;IACpE,SAAS,EAAE,OAAO,CAAA;IAClB,+EAA+E;IAC/E,UAAU,EAAE,OAAO,CAAA;IACnB,0EAA0E;IAC1E,YAAY,EAAE,OAAO,CAAA;IACrB,8EAA8E;IAC9E,kBAAkB,EAAE,OAAO,CAAA;CAC5B;AAWD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,UAAU,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAuC5F;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,UAAU,GAAG,IAAI,CAE/D;AAMD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,2BAA4B,SAAQ,KAAK;IAKlD,0DAA0D;aAC1C,UAAU,EAAE,MAAM;IAGlC,qCAAqC;aACrB,WAAW,CAAC,EAAE,MAAM;IATtC,SAAgB,IAAI,8BAA6B;IACjD,SAAyB,IAAI,iCAAgC;;IAG3D,0DAA0D;IAC1C,UAAU,EAAE,MAAM;IAClC,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM;IAChB,qCAAqC;IACrB,WAAW,CAAC,EAAE,MAAM,YAAA;CAKvC;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,2BAA2B,CAQtC;AAMD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,oBAAoB,EAClC,UAAU,EAAE,MAAM,oBAAoB,EACtC,OAAO,CAAC,EAAE,MAAM,GACf,IAAI,CAIN;AAWD;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,oBAAoB,EAClC,UAAU,EAAE,MAAM,oBAAoB,EACtC,WAAW,EAAE,MAAM,GAClB,IAAI,CAKN;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAMD;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAsB3E,CAAA"}