@bjornpagen/bumbledb 0.20.3 → 1.0.1

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 (192) hide show
  1. package/COOKBOOK.md +283 -1611
  2. package/README.md +156 -118
  3. package/dist/capacity.d.ts +16 -12
  4. package/dist/capacity.d.ts.map +1 -1
  5. package/dist/capacity.js +16 -48
  6. package/dist/capacity.js.map +1 -1
  7. package/dist/changes.d.ts +54 -0
  8. package/dist/changes.d.ts.map +1 -0
  9. package/dist/changes.js +245 -0
  10. package/dist/changes.js.map +1 -0
  11. package/dist/close.d.ts +24 -0
  12. package/dist/close.d.ts.map +1 -0
  13. package/dist/close.js +34 -0
  14. package/dist/close.js.map +1 -0
  15. package/dist/closed.d.ts +1 -3
  16. package/dist/closed.d.ts.map +1 -1
  17. package/dist/closed.js +24 -12
  18. package/dist/closed.js.map +1 -1
  19. package/dist/codec.d.ts +56 -0
  20. package/dist/codec.d.ts.map +1 -0
  21. package/dist/codec.js +289 -0
  22. package/dist/codec.js.map +1 -0
  23. package/dist/compile.d.ts +67 -0
  24. package/dist/compile.d.ts.map +1 -0
  25. package/dist/compile.js +75 -0
  26. package/dist/compile.js.map +1 -0
  27. package/dist/db-native.d.ts +161 -0
  28. package/dist/db-native.d.ts.map +1 -0
  29. package/dist/db-native.js +5 -0
  30. package/dist/db-native.js.map +1 -0
  31. package/dist/db.d.ts +101 -233
  32. package/dist/db.d.ts.map +1 -1
  33. package/dist/db.js +232 -1084
  34. package/dist/db.js.map +1 -1
  35. package/dist/errors.d.ts +53 -0
  36. package/dist/errors.d.ts.map +1 -0
  37. package/dist/errors.js +28 -0
  38. package/dist/errors.js.map +1 -0
  39. package/dist/face.d.ts.map +1 -1
  40. package/dist/face.js +2 -2
  41. package/dist/face.js.map +1 -1
  42. package/dist/fields.d.ts +64 -24
  43. package/dist/fields.d.ts.map +1 -1
  44. package/dist/fields.js +94 -24
  45. package/dist/fields.js.map +1 -1
  46. package/dist/index.d.ts +37 -32
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +17 -21
  49. package/dist/index.js.map +1 -1
  50. package/dist/internal/log.d.ts +24 -0
  51. package/dist/internal/log.d.ts.map +1 -0
  52. package/dist/internal/log.js +10 -0
  53. package/dist/internal/log.js.map +1 -0
  54. package/dist/law.d.ts +8 -13
  55. package/dist/law.d.ts.map +1 -1
  56. package/dist/law.js +6 -59
  57. package/dist/law.js.map +1 -1
  58. package/dist/lower.d.ts +0 -13
  59. package/dist/lower.d.ts.map +1 -1
  60. package/dist/lower.js +9 -17
  61. package/dist/lower.js.map +1 -1
  62. package/dist/migration.d.ts +32 -0
  63. package/dist/migration.d.ts.map +1 -0
  64. package/dist/migration.js +47 -0
  65. package/dist/migration.js.map +1 -0
  66. package/dist/native.d.ts +256 -301
  67. package/dist/native.d.ts.map +1 -1
  68. package/dist/native.js +65 -108
  69. package/dist/native.js.map +1 -1
  70. package/dist/query/atom.d.ts +24 -13
  71. package/dist/query/atom.d.ts.map +1 -1
  72. package/dist/query/atom.js +7 -3
  73. package/dist/query/atom.js.map +1 -1
  74. package/dist/query/compute.d.ts +68 -0
  75. package/dist/query/compute.d.ts.map +1 -0
  76. package/dist/query/compute.js +141 -0
  77. package/dist/query/compute.js.map +1 -0
  78. package/dist/query/find.d.ts +15 -8
  79. package/dist/query/find.d.ts.map +1 -1
  80. package/dist/query/find.js +6 -2
  81. package/dist/query/find.js.map +1 -1
  82. package/dist/query/lower.d.ts +23 -2
  83. package/dist/query/lower.d.ts.map +1 -1
  84. package/dist/query/lower.js +433 -80
  85. package/dist/query/lower.js.map +1 -1
  86. package/dist/query/parse-ir.d.ts.map +1 -1
  87. package/dist/query/parse-ir.js +17 -8
  88. package/dist/query/parse-ir.js.map +1 -1
  89. package/dist/query/run.d.ts +12 -2
  90. package/dist/query/run.d.ts.map +1 -1
  91. package/dist/query/run.js +26 -9
  92. package/dist/query/run.js.map +1 -1
  93. package/dist/query/scope.d.ts +47 -3
  94. package/dist/query/scope.d.ts.map +1 -1
  95. package/dist/query/scope.js +83 -19
  96. package/dist/query/scope.js.map +1 -1
  97. package/dist/relation.d.ts +3 -8
  98. package/dist/relation.d.ts.map +1 -1
  99. package/dist/relation.js +16 -10
  100. package/dist/relation.js.map +1 -1
  101. package/dist/result.d.ts +47 -0
  102. package/dist/result.d.ts.map +1 -0
  103. package/dist/result.js +50 -0
  104. package/dist/result.js.map +1 -0
  105. package/dist/rows.d.ts +69 -0
  106. package/dist/rows.d.ts.map +1 -0
  107. package/dist/rows.js +325 -0
  108. package/dist/rows.js.map +1 -0
  109. package/dist/runtime-codes.d.ts +2 -0
  110. package/dist/runtime-codes.d.ts.map +1 -0
  111. package/dist/runtime-codes.js +19 -0
  112. package/dist/runtime-codes.js.map +1 -0
  113. package/dist/runtime-errors.d.ts +106 -0
  114. package/dist/runtime-errors.d.ts.map +1 -0
  115. package/dist/runtime-errors.js +62 -0
  116. package/dist/runtime-errors.js.map +1 -0
  117. package/dist/runtime-native.d.ts +159 -0
  118. package/dist/runtime-native.d.ts.map +1 -0
  119. package/dist/runtime-native.js +5 -0
  120. package/dist/runtime-native.js.map +1 -0
  121. package/dist/runtime.d.ts +73 -0
  122. package/dist/runtime.d.ts.map +1 -0
  123. package/dist/runtime.js +292 -0
  124. package/dist/runtime.js.map +1 -0
  125. package/dist/scalar.d.ts +165 -0
  126. package/dist/scalar.d.ts.map +1 -0
  127. package/dist/scalar.js +344 -0
  128. package/dist/scalar.js.map +1 -0
  129. package/dist/schema.d.ts +1 -1
  130. package/dist/schema.d.ts.map +1 -1
  131. package/dist/schema.js +34 -37
  132. package/dist/schema.js.map +1 -1
  133. package/dist/shape.d.ts +27 -0
  134. package/dist/shape.d.ts.map +1 -0
  135. package/dist/shape.js +2 -0
  136. package/dist/shape.js.map +1 -0
  137. package/dist/spec.d.ts +27 -3
  138. package/dist/spec.d.ts.map +1 -1
  139. package/dist/spec.js +22 -1
  140. package/dist/spec.js.map +1 -1
  141. package/dist/statements.d.ts +16 -3
  142. package/dist/statements.d.ts.map +1 -1
  143. package/dist/statements.js +54 -28
  144. package/dist/statements.js.map +1 -1
  145. package/dist/uuid.d.ts +23 -0
  146. package/dist/uuid.d.ts.map +1 -0
  147. package/dist/uuid.js +54 -0
  148. package/dist/uuid.js.map +1 -0
  149. package/pack-provenance.json +7 -0
  150. package/package.json +12 -16
  151. package/src/capacity.ts +34 -54
  152. package/src/changes.ts +361 -0
  153. package/src/close.ts +53 -0
  154. package/src/closed.ts +25 -19
  155. package/src/codec.ts +379 -0
  156. package/src/compile.ts +148 -0
  157. package/src/db-native.ts +238 -0
  158. package/src/db.ts +461 -1632
  159. package/src/errors.ts +46 -0
  160. package/src/face.ts +2 -2
  161. package/src/fields.ts +181 -55
  162. package/src/index.ts +62 -126
  163. package/src/internal/log.ts +49 -0
  164. package/src/law.ts +13 -28
  165. package/src/lower.ts +9 -4
  166. package/src/migration.ts +68 -0
  167. package/src/native.ts +326 -487
  168. package/src/query/atom.ts +61 -25
  169. package/src/query/compute.ts +237 -0
  170. package/src/query/find.ts +31 -12
  171. package/src/query/lower.ts +531 -143
  172. package/src/query/parse-ir.ts +18 -13
  173. package/src/query/run.ts +32 -16
  174. package/src/query/scope.ts +140 -8
  175. package/src/relation.ts +17 -21
  176. package/src/result.ts +130 -0
  177. package/src/rows.ts +401 -0
  178. package/src/runtime-codes.ts +18 -0
  179. package/src/runtime-errors.ts +69 -0
  180. package/src/runtime-native.ts +222 -0
  181. package/src/runtime.ts +439 -0
  182. package/src/scalar.ts +560 -0
  183. package/src/schema.ts +35 -37
  184. package/src/shape.ts +30 -0
  185. package/src/spec.ts +33 -3
  186. package/src/statements.ts +75 -68
  187. package/src/uuid.ts +69 -0
  188. package/dist/marshal.d.ts +0 -44
  189. package/dist/marshal.d.ts.map +0 -1
  190. package/dist/marshal.js +0 -165
  191. package/dist/marshal.js.map +0 -1
  192. package/src/marshal.ts +0 -200
package/src/rows.ts ADDED
@@ -0,0 +1,401 @@
1
+ import { AuthoringError, SdkInvariantError } from "#errors.ts"
2
+ /**
3
+ * The row codec: fact object ⇄ positional cell array by field
4
+ * ordinal, schema-directed, in ONE place. The write side lowers named host
5
+ * objects to rows in the relation's field-declaration order (declaration
6
+ * order = ordinal ids); the read side decodes owned rows back to named
7
+ * objects of BARE structural values. This module is the one fact⇄row
8
+ * projector. It covers all value types: bool, u64, i64,
9
+ * f64, uuid, str, bytes<N>, discrete intervals and dense float intervals,
10
+ * plus the closed-handle bijection (name ⇄ declaration-order row id).
11
+ *
12
+ * Cells here are OWNED plain host values; the native boundary re-judges
13
+ * every crossing against its resident sealed roster. Shape misuse throws
14
+ * the pure {@link AuthoringError}; the Effect ingestion boundary catches
15
+ * and types it (never an untracked partial draft). SharedArrayBuffer-backed
16
+ * views are refused before any copy. Host length is judged before string
17
+ * scans and byte copies.
18
+ */
19
+ import type { AnyClosedRoster, AnyField } from "#fields.ts"
20
+ import { isFloatIntervalValue, isIntervalValue, literalShapeError, rosterOf } from "#fields.ts"
21
+ import type { AnyRelation, Fact, RelationData } from "#relation.ts"
22
+ import { Uuid } from "#uuid.ts"
23
+
24
+ /** Converter-granularity host cell wall (64 KiB). One oversize cell refuses. */
25
+ const HOST_CELL_MAX = 65536n
26
+
27
+ /**
28
+ * One owned cell at the private bridge boundary. The declared sealed field
29
+ * type disambiguates the union: `string` is text, an `uuid` in its
30
+ * canonical hyphenated UUID spelling, or a closed handle
31
+ * before lowering (closed handles cross as `bigint` row ids),
32
+ * `Uint8Array` is `bytes<N>`, `{ start, end }` bigints are a discrete
33
+ * interval and numbers a dense float interval.
34
+ */
35
+ type CellValue =
36
+ | boolean
37
+ | bigint
38
+ | number
39
+ | string
40
+ | Uint8Array
41
+ | { readonly start: bigint; readonly end: bigint }
42
+ | { readonly start: number; readonly end: number }
43
+
44
+ interface FlatRows {
45
+ readonly rows: bigint
46
+ readonly cells: readonly CellValue[]
47
+ /** Conservative charged byte size of the owned cells (input accounting). */
48
+ readonly bytes: bigint
49
+ }
50
+
51
+ function recordOf(fact: object): Readonly<Record<string, unknown>> {
52
+ if (typeof fact !== "object" && typeof fact !== "function") {
53
+ throw new AuthoringError({ message: "fact object is not string-indexable" })
54
+ }
55
+ return fact as Readonly<Record<string, unknown>>
56
+ }
57
+
58
+ function refuseShared(context: string, value: Uint8Array): void {
59
+ if (!(value.buffer instanceof ArrayBuffer)) {
60
+ throw new AuthoringError({
61
+ message: `${context}: SharedArrayBuffer-backed views are refused — make a synchronized stable copy into ordinary unshared input first`
62
+ })
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Cheap host charge before any string scan or byte copy. Strings charge
68
+ * two bytes per UTF-16 code unit, not their UTF-8 wire size. Native admission
69
+ * measures and bounds UTF-8 separately; byte views charge their length.
70
+ */
71
+ function hostCellCharge(value: unknown): bigint {
72
+ if (typeof value === "string") {
73
+ return BigInt(value.length) * 2n
74
+ }
75
+ if (value instanceof Uint8Array) {
76
+ return BigInt(value.byteLength)
77
+ }
78
+ if (typeof value === "boolean") {
79
+ return 1n
80
+ }
81
+ if (typeof value === "bigint" || typeof value === "number") {
82
+ return 8n
83
+ }
84
+ if (value !== null && typeof value === "object" && "start" in value && "end" in value) {
85
+ return 16n
86
+ }
87
+ return 0n
88
+ }
89
+
90
+ function assertHostCellFits(context: string, value: unknown, limit: bigint): bigint {
91
+ const charge = hostCellCharge(value)
92
+ if (charge > limit) {
93
+ throw new AuthoringError({
94
+ message: `${context}: host cell of ${charge} bytes exceeds the ${limit}-byte converter bound — refuse before copy or scan`
95
+ })
96
+ }
97
+ return charge
98
+ }
99
+
100
+ /**
101
+ * The write half of the closed bijection: one handle NAME to its u64 row
102
+ * id (declaration order = row ids). An unknown name is a pointed refusal
103
+ * naming the vocabulary and its roster.
104
+ */
105
+ function closedCellOf(context: string, closed: AnyClosedRoster, name: string): CellValue {
106
+ const id = closed.handles.indexOf(name)
107
+ if (id === -1) {
108
+ throw new AuthoringError({
109
+ message: `${context}: "${name}" is not a handle of ${closed.name} — the roster is ${closed.handles.join(", ")}`
110
+ })
111
+ }
112
+ return BigInt(id)
113
+ }
114
+
115
+ function handleOf(context: string, closed: AnyClosedRoster, cell: unknown): string {
116
+ if (typeof cell !== "bigint") {
117
+ throw literalShapeError(context, `a ${closed.name} handle id (bigint)`, cell)
118
+ }
119
+ const handle = closed.handles[Number(cell)]
120
+ if (handle === undefined) {
121
+ throw new AuthoringError({
122
+ message: `${context}: id ${cell} is outside the ${closed.name} roster (${closed.handles.join(", ")})`
123
+ })
124
+ }
125
+ return handle
126
+ }
127
+
128
+ /** Conservative owned-byte charge of one cell (host accounting, not wire). */
129
+ function cellBytes(cell: CellValue): bigint {
130
+ if (typeof cell === "boolean") {
131
+ return 1n
132
+ }
133
+ if (typeof cell === "bigint" || typeof cell === "number") {
134
+ return 8n
135
+ }
136
+ if (typeof cell === "string") {
137
+ // Account for the host string here; native admission separately
138
+ // checks and charges its exact UTF-8 encoding.
139
+ return BigInt(cell.length) * 2n
140
+ }
141
+ if (cell instanceof Uint8Array) {
142
+ return BigInt(cell.byteLength)
143
+ }
144
+ return 16n
145
+ }
146
+
147
+ function cellOf(context: string, field: AnyField, value: unknown): CellValue {
148
+ const roster = rosterOf(field)
149
+ if (roster !== undefined) {
150
+ if (typeof value !== "string") {
151
+ throw literalShapeError(context, `a ${roster.name} handle name (string)`, value)
152
+ }
153
+ return closedCellOf(context, roster, value)
154
+ }
155
+ switch (field.kind) {
156
+ case "bool": {
157
+ if (typeof value !== "boolean") {
158
+ throw literalShapeError(context, "boolean", value)
159
+ }
160
+ return value
161
+ }
162
+ case "u64":
163
+ case "i64": {
164
+ if (typeof value !== "bigint") {
165
+ throw literalShapeError(context, "bigint", value)
166
+ }
167
+ return value
168
+ }
169
+ case "str": {
170
+ if (typeof value !== "string") {
171
+ throw literalShapeError(context, "string", value)
172
+ }
173
+ assertHostCellFits(context, value, HOST_CELL_MAX)
174
+ if (!value.isWellFormed()) {
175
+ throw literalShapeError(context, "well-formed string", value)
176
+ }
177
+ return value
178
+ }
179
+ case "f64": {
180
+ if (typeof value !== "number") {
181
+ throw literalShapeError(context, "number", value)
182
+ }
183
+ return value
184
+ }
185
+ case "uuid": {
186
+ if (!Uuid.isUuid(value)) {
187
+ throw literalShapeError(context, "a UUID (canonical UUID text)", value)
188
+ }
189
+ // UUIDs cross as canonical hyphenated text, not raw bytes.
190
+ return value
191
+ }
192
+ case "bytes": {
193
+ if (!(value instanceof Uint8Array)) {
194
+ throw literalShapeError(context, "Uint8Array", value)
195
+ }
196
+ refuseShared(context, value)
197
+ assertHostCellFits(context, value, HOST_CELL_MAX)
198
+ if (value.byteLength !== field.width) {
199
+ throw new AuthoringError({
200
+ message: `${context}: bytes<${field.width}> takes exactly ${field.width} bytes (got ${value.byteLength})`
201
+ })
202
+ }
203
+ // Owned copy at the ownership boundary: later caller mutation
204
+ // cannot change an accepted cell.
205
+ return Uint8Array.from(value)
206
+ }
207
+ case "interval": {
208
+ if (field.element === "f64") {
209
+ if (!isFloatIntervalValue(value)) {
210
+ throw literalShapeError(context, "float interval ({ start, end } numbers)", value)
211
+ }
212
+ if (Number.isNaN(value.start) || Number.isNaN(value.end)) {
213
+ throw new AuthoringError({ message: `${context}: a float interval endpoint cannot be NaN` })
214
+ }
215
+ const start = Object.is(value.start, -0) ? 0 : value.start
216
+ const end = Object.is(value.end, -0) ? 0 : value.end
217
+ if (!(start < end)) {
218
+ throw new AuthoringError({
219
+ message: `${context}: a float interval is half-open and nonempty (start < end strictly)`
220
+ })
221
+ }
222
+ return { start, end }
223
+ }
224
+ if (!isIntervalValue(value)) {
225
+ throw literalShapeError(context, "interval ({ start, end } bigints)", value)
226
+ }
227
+ return { start: value.start, end: value.end }
228
+ }
229
+ }
230
+ }
231
+
232
+ /**
233
+ * The flat projector: every fact's cells land in ONE row-major cell array
234
+ * (length rows × arity) with the row count and charged byte size counted
235
+ * while projecting. Missing-field refusal and per-cell judgment are
236
+ * {@link cellOf}'s, byte for byte.
237
+ */
238
+ function flatRowsOf(data: RelationData, facts: Iterable<object>): FlatRows {
239
+ const cells: CellValue[] = []
240
+ let rows = 0n
241
+ let bytes = 0n
242
+ for (const fact of facts) {
243
+ rows += 1n
244
+ const record = recordOf(fact)
245
+ for (const declared of data.fields) {
246
+ const value = record[declared.name]
247
+ if (value === undefined) {
248
+ throw new AuthoringError({ message: `relation ${data.name}: fact is missing field ${declared.name}` })
249
+ }
250
+ const cell = cellOf(`relation ${data.name} field ${declared.name}`, declared.field, value)
251
+ bytes += cellBytes(cell)
252
+ cells.push(cell)
253
+ }
254
+ }
255
+ return { rows, cells, bytes }
256
+ }
257
+
258
+ function keyCellsOf(
259
+ data: RelationData,
260
+ projection: readonly string[],
261
+ key: Readonly<Record<string, unknown>>
262
+ ): CellValue[] {
263
+ for (const supplied of Object.keys(key)) {
264
+ if (key[supplied] !== undefined && !projection.includes(supplied)) {
265
+ throw new AuthoringError({
266
+ message: `relation ${data.name}: key object carries field ${supplied} outside the primary key projection (${projection.join(", ")})`
267
+ })
268
+ }
269
+ }
270
+ return projection.map(function marshalKeyCell(fieldName) {
271
+ const declared = data.fields.find(function byName(candidate) {
272
+ return candidate.name === fieldName
273
+ })
274
+ if (declared === undefined) {
275
+ throw new AuthoringError({
276
+ message: `relation ${data.name}: key projection cites unknown field ${fieldName}`
277
+ })
278
+ }
279
+ const value = key[fieldName]
280
+ if (value === undefined) {
281
+ throw new AuthoringError({
282
+ message: `relation ${data.name}: key object is missing field ${fieldName} — get reads through the primary (first-declared) key, whose projection is (${projection.join(", ")})`
283
+ })
284
+ }
285
+ return cellOf(`relation ${data.name} key field ${fieldName}`, declared.field, value)
286
+ })
287
+ }
288
+
289
+ function decodeCell(context: string, field: AnyField, cell: unknown): unknown {
290
+ const roster = rosterOf(field)
291
+ if (roster !== undefined) {
292
+ return handleOf(context, roster, cell)
293
+ }
294
+ switch (field.kind) {
295
+ case "bool": {
296
+ if (typeof cell !== "boolean") {
297
+ throw new SdkInvariantError({ message: `${context}: expected boolean cell` })
298
+ }
299
+ return cell
300
+ }
301
+ case "u64":
302
+ case "i64": {
303
+ if (typeof cell !== "bigint") {
304
+ throw new SdkInvariantError({ message: `${context}: expected bigint cell` })
305
+ }
306
+ return cell
307
+ }
308
+ case "f64": {
309
+ if (typeof cell !== "number") {
310
+ throw new SdkInvariantError({ message: `${context}: expected number cell` })
311
+ }
312
+ return cell
313
+ }
314
+ case "str": {
315
+ if (typeof cell !== "string") {
316
+ throw new SdkInvariantError({ message: `${context}: expected string cell` })
317
+ }
318
+ return cell
319
+ }
320
+ case "uuid": {
321
+ // The native renderer spells uuid as the canonical
322
+ // canonical hyphenated UUID string (marshal.rs `uuid_hex`); the read
323
+ // side revalidates the spelling and keeps the string value.
324
+ if (!Uuid.isUuid(cell)) {
325
+ throw new SdkInvariantError({
326
+ message: `${context}: expected an uuid cell (canonical UUID text)`
327
+ })
328
+ }
329
+ return cell
330
+ }
331
+ case "bytes": {
332
+ if (!(cell instanceof Uint8Array)) {
333
+ throw new SdkInvariantError({ message: `${context}: expected owned bytes` })
334
+ }
335
+ return cell
336
+ }
337
+ case "interval": {
338
+ if (field.element === "f64") {
339
+ if (!isFloatIntervalValue(cell)) {
340
+ throw new SdkInvariantError({ message: `${context}: expected a float interval cell` })
341
+ }
342
+ return Object.freeze({ start: cell.start, end: cell.end })
343
+ }
344
+ if (!isIntervalValue(cell)) {
345
+ throw new SdkInvariantError({ message: `${context}: expected an integer interval cell` })
346
+ }
347
+ return Object.freeze({ start: cell.start, end: cell.end })
348
+ }
349
+ }
350
+ }
351
+
352
+ function isCompleteFact<R extends AnyRelation>(
353
+ relation: R,
354
+ decoded: Readonly<Record<string, unknown>>
355
+ ): decoded is Readonly<Record<string, unknown>> & Fact<R> {
356
+ return relation.data.fields.every(function present(declared) {
357
+ return decoded[declared.name] !== undefined
358
+ })
359
+ }
360
+
361
+ /**
362
+ * The read half: one owned positional row into a plain frozen record in
363
+ * declared field order: stable field names and shapes, no Proxy or per-cell closures.
364
+ */
365
+ function factOfCells<R extends AnyRelation>(relation: R, row: readonly unknown[]): Fact<R> {
366
+ const data = relation.data
367
+ if (row.length !== data.fields.length) {
368
+ throw new SdkInvariantError({
369
+ message: `relation ${data.name}: row arity ${row.length} does not match the ${data.fields.length} declared fields`
370
+ })
371
+ }
372
+ const decoded: Record<string, unknown> = {}
373
+ data.fields.forEach(function decodeOne(declared, ordinal) {
374
+ const cell = row[ordinal]
375
+ if (cell === undefined) {
376
+ throw new SdkInvariantError({
377
+ message: `relation ${data.name}: row cell ${ordinal} (${declared.name}) is absent`
378
+ })
379
+ }
380
+ decoded[declared.name] = decodeCell(`relation ${data.name} field ${declared.name}`, declared.field, cell)
381
+ })
382
+ Object.freeze(decoded)
383
+ if (!isCompleteFact(relation, decoded)) {
384
+ throw new SdkInvariantError({ message: `relation ${data.name}: decoded row is not a complete fact` })
385
+ }
386
+ return decoded
387
+ }
388
+
389
+ export type { CellValue, FlatRows }
390
+ export {
391
+ assertHostCellFits,
392
+ cellBytes,
393
+ cellOf,
394
+ decodeCell,
395
+ factOfCells,
396
+ flatRowsOf,
397
+ handleOf,
398
+ hostCellCharge,
399
+ keyCellsOf,
400
+ recordOf
401
+ }
@@ -0,0 +1,18 @@
1
+ // Generated from the exact native runtimeErrorCodes export; do not edit.
2
+ export const runtimeErrorCodes = [
3
+ "RuntimeAlreadyLive",
4
+ "ForeignRuntime",
5
+ "ClosedHandle",
6
+ "SpentHandle",
7
+ "QueueFull",
8
+ "InvalidArgument",
9
+ "Internal",
10
+ "DirectoryBusy",
11
+ "WriterBusy",
12
+ "InvalidPath",
13
+ "Io",
14
+ "ResourceLimit",
15
+ "Engine",
16
+ "Cancelled",
17
+ "DeadlineExceeded"
18
+ ] as const
@@ -0,0 +1,69 @@
1
+ import { Schema } from "effect"
2
+ import { runtimeErrorCodes } from "#runtime-codes.ts"
3
+
4
+ export { runtimeErrorCodes } from "#runtime-codes.ts"
5
+
6
+ const ResourceLimit = Schema.Struct({
7
+ _tag: Schema.Literal("ResourceLimit"),
8
+ dimension: Schema.String,
9
+ used: Schema.BigInt,
10
+ requested: Schema.BigInt,
11
+ limit: Schema.BigInt
12
+ })
13
+ const PlainReason = Schema.Struct({
14
+ _tag: Schema.Literals(
15
+ runtimeErrorCodes.filter((code) => code !== "ResourceLimit" && code !== "Io" && code !== "Engine")
16
+ )
17
+ })
18
+ const Io = Schema.Struct({
19
+ _tag: Schema.Literal("Io"),
20
+ kind: Schema.String,
21
+ osCode: Schema.optional(Schema.Number)
22
+ })
23
+ /** A typed engine refusal crossing the executor: core family tag + message. */
24
+ const Engine = Schema.Struct({
25
+ _tag: Schema.Literal("Engine"),
26
+ kind: Schema.String,
27
+ message: Schema.String
28
+ })
29
+ export const DbReason = Schema.Union([ResourceLimit, Io, Engine, PlainReason])
30
+ export class DbError extends Schema.TaggedError<DbError>()("DbError", {
31
+ operation: Schema.String,
32
+ reason: DbReason
33
+ }) {
34
+ get code() {
35
+ return this.reason._tag
36
+ }
37
+ }
38
+
39
+ const decodeReason = Schema.decodeUnknownOption(DbReason)
40
+ export function dbError(operation: string, cause: unknown): DbError {
41
+ const decoded = decodeReason(cause)
42
+ return new DbError({ operation, reason: decoded._tag === "Some" ? decoded.value : { _tag: "Internal" } })
43
+ }
44
+
45
+ const Outstanding = Schema.Struct({
46
+ phase: Schema.Literals(["open", "closing", "closed"]),
47
+ queued: Schema.BigInt,
48
+ active: Schema.BigInt,
49
+ retained: Schema.BigInt,
50
+ owners: Schema.BigInt,
51
+ databases: Schema.BigInt,
52
+ natives: Schema.BigInt,
53
+ inputBytes: Schema.BigInt,
54
+ workingBytes: Schema.BigInt,
55
+ scratchBytes: Schema.BigInt,
56
+ resultBytes: Schema.BigInt
57
+ })
58
+ export type OutstandingWork = typeof Outstanding.Type
59
+ const Close = Schema.Union([
60
+ Schema.Struct({ kind: Schema.Literal("closed") }),
61
+ Schema.Struct({ kind: Schema.Literal("incomplete"), outstanding: Outstanding }),
62
+ Schema.Struct({ kind: Schema.Literal("failed"), error: DbError })
63
+ ])
64
+ export type CloseReport = typeof Close.Type
65
+
66
+ export class CloseFailure extends Schema.TaggedError<CloseFailure>()("CloseFailure", {
67
+ operation: Schema.String,
68
+ report: Close
69
+ }) {}
@@ -0,0 +1,222 @@
1
+ /** Exact-version internal bridge, shared by core and log. Not a public API. */
2
+
3
+ import type {
4
+ DbHandle,
5
+ LogChainKind,
6
+ LogCommandKind,
7
+ LogCommandMetadata,
8
+ LogCommandRef,
9
+ LogCondition,
10
+ LogDecisionStamp,
11
+ LogIdentity,
12
+ LogLimits,
13
+ LogOutcomeWire,
14
+ LogSchemaHandle,
15
+ LogStateStamp,
16
+ Violation
17
+ } from "#native.ts"
18
+ import { native } from "#native.ts"
19
+ import type { SchemaSpec } from "#spec.ts"
20
+
21
+ export interface RuntimeHandle {
22
+ readonly __runtime: unique symbol
23
+ }
24
+ export interface OperationHandle {
25
+ readonly __operation: unique symbol
26
+ }
27
+ export interface DirectoryHandle {
28
+ readonly __directory: unique symbol
29
+ }
30
+
31
+ /** Stamped `NativeKind::RepositoryLock` mint — not a directory-owner twin. */
32
+ export interface RepositoryLockHandle {
33
+ readonly __repositoryLock: unique symbol
34
+ }
35
+
36
+ /** Resource kinds installed in native worker tables. */
37
+ export type NativeKind = "snapshot" | "result" | "cursor" | "draft" | "changes" | "repository-lock"
38
+
39
+ /**
40
+ * Checked capability into the native registry. JS tokens validate
41
+ * these five fields; native re-judges kind/generation/owner on every verb.
42
+ */
43
+ export interface Capability {
44
+ readonly runtime: bigint
45
+ readonly worker: number
46
+ readonly kind: NativeKind
47
+ readonly id: bigint
48
+ readonly generation: bigint
49
+ }
50
+
51
+ export type ManagedDbOutcome =
52
+ | { readonly tag: "accepted"; readonly db: DbHandle }
53
+ | { readonly tag: "rejected"; readonly violations: readonly Violation[] }
54
+ | {
55
+ readonly tag: "refused"
56
+ readonly kind: "schemaError" | "newtypeMismatch" | "fingerprintMismatch" | "destinationExists"
57
+ readonly message: string
58
+ }
59
+
60
+ export type LogTakeWire =
61
+ | { readonly ok: false; readonly kind: LogCommandKind | LogChainKind; readonly message: string }
62
+ | {
63
+ /** Command sealed: envelope bytes + reference. */
64
+ readonly ok: true
65
+ readonly bytes: Uint8Array
66
+ readonly ref: LogCommandRef
67
+ }
68
+ | {
69
+ /** Command parsed. */
70
+ readonly ok: true
71
+ readonly identity: LogIdentity
72
+ readonly receiptEpoch: bigint
73
+ readonly requestId: string
74
+ readonly condition: LogCondition
75
+ readonly changes: Uint8Array
76
+ readonly result: Uint8Array
77
+ readonly ref: LogCommandRef
78
+ }
79
+ | {
80
+ /** Decision framed. */
81
+ readonly ok: true
82
+ readonly bytes: Uint8Array
83
+ readonly digest: Uint8Array
84
+ }
85
+ | {
86
+ /** Decision decoded (and chain-verified when a parent was given). */
87
+ readonly ok: true
88
+ readonly identity: LogIdentity
89
+ readonly seq: bigint
90
+ readonly parent: LogDecisionStamp
91
+ readonly beforeState: LogStateStamp
92
+ readonly afterState: LogStateStamp
93
+ readonly commandBytes: Uint8Array
94
+ readonly command: LogCommandRef
95
+ readonly outcome: LogOutcomeWire
96
+ readonly digest: Uint8Array
97
+ }
98
+
99
+ export interface PolicyWire {
100
+ readonly inputBytes: bigint
101
+ readonly workingBytes: bigint
102
+ readonly scratchBytes: bigint
103
+ readonly resultBytes: bigint
104
+ readonly rows: bigint
105
+ readonly workUnits: bigint
106
+ readonly timeoutMs: number
107
+ }
108
+
109
+ export interface OptionsWire {
110
+ readonly workers: number
111
+ readonly queueCapacity: number
112
+ readonly cleanupCapacity: number
113
+ readonly ownerCapacity: number
114
+ readonly nativeHandleCapacity: number
115
+ readonly inputBytes: bigint
116
+ readonly workingBytes: bigint
117
+ readonly scratchBytes: bigint
118
+ readonly resultBytes: bigint
119
+ readonly chunkBytes: bigint
120
+ readonly cleanupTimeoutMs: number
121
+ }
122
+
123
+ export interface InspectionWire {
124
+ readonly phase: "open" | "closing" | "closed"
125
+ readonly queued: bigint
126
+ readonly active: bigint
127
+ readonly retained: bigint
128
+ readonly owners: bigint
129
+ readonly databases: bigint
130
+ readonly natives: bigint
131
+ readonly inputBytes: bigint
132
+ readonly workingBytes: bigint
133
+ readonly scratchBytes: bigint
134
+ readonly resultBytes: bigint
135
+ }
136
+
137
+ export type CloseWire =
138
+ | { readonly kind: "closed" }
139
+ | { readonly kind: "incomplete"; readonly outstanding: InspectionWire }
140
+ | { readonly kind: "failed" }
141
+
142
+ interface RuntimeNative {
143
+ runtimeErrorCodes(): readonly string[]
144
+ runtimeOpen(options: OptionsWire): RuntimeHandle
145
+ runtimeReady(runtime: RuntimeHandle, policy: PolicyWire, callback: () => void): OperationHandle
146
+ runtimeHash(runtime: RuntimeHandle, policy: PolicyWire, bytes: Uint8Array, callback: () => void): OperationHandle
147
+ runtimeTake(operation: OperationHandle): Uint8Array | null
148
+ runtimeCancel(operation: OperationHandle, callback: (report: CloseWire) => void): void
149
+ runtimeClose(runtime: RuntimeHandle, callback: (report: CloseWire) => void): void
150
+ runtimeInspect(runtime: RuntimeHandle): InspectionWire
151
+ /**
152
+ * L12 request (D12/D25): one-shot arm. Next `dispatch_payload_message`
153
+ * must cancel after `work()` returns and the post-work `checkpoint()`
154
+ * (`runtime.rs` ~860–862), before `complete_operation` writes
155
+ * `operation.output`. A local `QueuedOutput` is not registration.
156
+ * Predelivery: no JS take; cursor stays on row1 so retry does not skip.
157
+ */
158
+ runtimeArmPublicationCancel(runtime: RuntimeHandle): void
159
+ runtimeDirectoryAcquire(
160
+ runtime: RuntimeHandle,
161
+ policy: PolicyWire,
162
+ path: string,
163
+ callback: () => void
164
+ ): OperationHandle
165
+ runtimeDirectoryTake(operation: OperationHandle): DirectoryHandle
166
+ runtimeDirectoryBegin(owner: DirectoryHandle, policy: PolicyWire): OperationHandle
167
+ runtimeDirectoryCheck(operation: OperationHandle): void
168
+ runtimeDirectoryEnd(operation: OperationHandle): void
169
+ runtimeDirectoryClose(owner: DirectoryHandle, remove: boolean, callback: (report: CloseWire) => void): void
170
+ runtimeDirectoryDbOpen(
171
+ owner: DirectoryHandle,
172
+ policy: PolicyWire,
173
+ childName: string,
174
+ spec: SchemaSpec,
175
+ create: boolean,
176
+ callback: () => void
177
+ ): OperationHandle
178
+ runtimeDbTake(operation: OperationHandle): ManagedDbOutcome
179
+ runtimeManagedDbClose(db: DbHandle, callback: (report: CloseWire) => void): void
180
+
181
+ // --- successor log grammar on the executor (charged hashing over
182
+ // whole canonical change payloads; C06 through C09) ---
183
+ runtimeLogCommandSeal(
184
+ runtime: RuntimeHandle,
185
+ schema: LogSchemaHandle,
186
+ policy: PolicyWire,
187
+ metadata: LogCommandMetadata,
188
+ changes: Uint8Array,
189
+ result: Uint8Array | null,
190
+ limits: LogLimits,
191
+ callback: () => void
192
+ ): OperationHandle
193
+ runtimeLogCommandParse(
194
+ runtime: RuntimeHandle,
195
+ schema: LogSchemaHandle,
196
+ policy: PolicyWire,
197
+ bytes: Uint8Array,
198
+ limits: LogLimits,
199
+ callback: () => void
200
+ ): OperationHandle
201
+ runtimeLogDecisionDecode(
202
+ runtime: RuntimeHandle,
203
+ policy: PolicyWire,
204
+ bytes: Uint8Array,
205
+ parent: LogDecisionStamp | null,
206
+ limits: LogLimits,
207
+ callback: () => void
208
+ ): OperationHandle
209
+ runtimeLogTake(operation: OperationHandle): LogTakeWire
210
+ /** L14 mint: `Runtime::mint_repository_lock` stamps `NativeKind::RepositoryLock` at take. */
211
+ logRepositoryLockAcquire(
212
+ runtime: RuntimeHandle,
213
+ policy: PolicyWire,
214
+ directory: string,
215
+ callback: () => void
216
+ ): OperationHandle
217
+ logRepositoryLockTake(operation: OperationHandle): RepositoryLockHandle
218
+ logRepositoryLockRelease(owner: RepositoryLockHandle, callback: (report: CloseWire) => void): void
219
+ }
220
+
221
+ // The checked source/fresh-addon roster test pins this private declaration.
222
+ export const runtimeNative = native as typeof native & RuntimeNative