@bjornpagen/bumbledb 1.3.1 → 2.0.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 (290) hide show
  1. package/COOKBOOK.md +153 -77
  2. package/README.md +107 -41
  3. package/dist/alternatives.d.ts +5 -6
  4. package/dist/alternatives.d.ts.map +1 -1
  5. package/dist/alternatives.js +5 -6
  6. package/dist/alternatives.js.map +1 -1
  7. package/dist/bin.d.ts +3 -0
  8. package/dist/bin.d.ts.map +1 -0
  9. package/dist/bin.js +85 -0
  10. package/dist/bin.js.map +1 -0
  11. package/dist/capacity.d.ts +14 -17
  12. package/dist/capacity.d.ts.map +1 -1
  13. package/dist/capacity.js +7 -7
  14. package/dist/capacity.js.map +1 -1
  15. package/dist/changes.d.ts +32 -40
  16. package/dist/changes.d.ts.map +1 -1
  17. package/dist/changes.js +86 -104
  18. package/dist/changes.js.map +1 -1
  19. package/dist/closed.d.ts +2 -2
  20. package/dist/closed.d.ts.map +1 -1
  21. package/dist/closed.js +5 -5
  22. package/dist/closed.js.map +1 -1
  23. package/dist/codec.d.ts +13 -27
  24. package/dist/codec.d.ts.map +1 -1
  25. package/dist/codec.js +20 -21
  26. package/dist/codec.js.map +1 -1
  27. package/dist/compile.d.ts +26 -50
  28. package/dist/compile.d.ts.map +1 -1
  29. package/dist/compile.js +75 -64
  30. package/dist/compile.js.map +1 -1
  31. package/dist/database/database.d.ts +98 -0
  32. package/dist/database/database.d.ts.map +1 -0
  33. package/dist/database/database.js +249 -0
  34. package/dist/database/database.js.map +1 -0
  35. package/dist/database/driver.d.ts +40 -0
  36. package/dist/database/driver.d.ts.map +1 -0
  37. package/dist/database/driver.js +68 -0
  38. package/dist/database/driver.js.map +1 -0
  39. package/dist/database/fs.d.ts +12 -0
  40. package/dist/database/fs.d.ts.map +1 -0
  41. package/dist/database/fs.js +120 -0
  42. package/dist/database/fs.js.map +1 -0
  43. package/dist/database/generate.d.ts +26 -0
  44. package/dist/database/generate.d.ts.map +1 -0
  45. package/dist/database/generate.js +102 -0
  46. package/dist/database/generate.js.map +1 -0
  47. package/dist/database/hosted.d.ts +32 -0
  48. package/dist/database/hosted.d.ts.map +1 -0
  49. package/dist/database/hosted.js +44 -0
  50. package/dist/database/hosted.js.map +1 -0
  51. package/dist/database/io.d.ts +94 -0
  52. package/dist/database/io.d.ts.map +1 -0
  53. package/dist/database/io.js +35 -0
  54. package/dist/database/io.js.map +1 -0
  55. package/dist/database/mem.d.ts +26 -0
  56. package/dist/database/mem.d.ts.map +1 -0
  57. package/dist/database/mem.js +67 -0
  58. package/dist/database/mem.js.map +1 -0
  59. package/dist/database/migration.d.ts +55 -0
  60. package/dist/database/migration.d.ts.map +1 -0
  61. package/dist/database/migration.js +46 -0
  62. package/dist/database/migration.js.map +1 -0
  63. package/dist/database/s3.d.ts +36 -0
  64. package/dist/database/s3.d.ts.map +1 -0
  65. package/dist/database/s3.js +141 -0
  66. package/dist/database/s3.js.map +1 -0
  67. package/dist/db.d.ts +44 -128
  68. package/dist/db.d.ts.map +1 -1
  69. package/dist/db.js +163 -287
  70. package/dist/db.js.map +1 -1
  71. package/dist/engine.d.ts +7 -0
  72. package/dist/engine.d.ts.map +1 -0
  73. package/dist/engine.js +2 -0
  74. package/dist/engine.js.map +1 -0
  75. package/dist/errors.d.ts +152 -46
  76. package/dist/errors.d.ts.map +1 -1
  77. package/dist/errors.js +107 -19
  78. package/dist/errors.js.map +1 -1
  79. package/dist/face.d.ts +5 -5
  80. package/dist/face.d.ts.map +1 -1
  81. package/dist/face.js +6 -6
  82. package/dist/face.js.map +1 -1
  83. package/dist/fields.d.ts +4 -5
  84. package/dist/fields.d.ts.map +1 -1
  85. package/dist/fields.js +3 -3
  86. package/dist/fields.js.map +1 -1
  87. package/dist/index.d.ts +60 -57
  88. package/dist/index.d.ts.map +1 -1
  89. package/dist/index.js +27 -28
  90. package/dist/index.js.map +1 -1
  91. package/dist/judgment.d.ts +1 -1
  92. package/dist/judgment.js +1 -1
  93. package/dist/law.d.ts +16 -68
  94. package/dist/law.d.ts.map +1 -1
  95. package/dist/law.js +3 -3
  96. package/dist/law.js.map +1 -1
  97. package/dist/lower.d.ts +3 -3
  98. package/dist/lower.d.ts.map +1 -1
  99. package/dist/lower.js +35 -39
  100. package/dist/lower.js.map +1 -1
  101. package/dist/native/addon.d.ts +23 -0
  102. package/dist/native/addon.d.ts.map +1 -0
  103. package/dist/native/addon.js +15 -0
  104. package/dist/native/addon.js.map +1 -0
  105. package/dist/native/binding.d.ts +996 -0
  106. package/dist/native/json.d.ts +14 -0
  107. package/dist/native/json.d.ts.map +1 -0
  108. package/dist/native/json.js +73 -0
  109. package/dist/native/json.js.map +1 -0
  110. package/dist/native/load.d.ts +9 -0
  111. package/dist/native/load.d.ts.map +1 -0
  112. package/dist/native/load.js +30 -0
  113. package/dist/native/load.js.map +1 -0
  114. package/dist/native/op.d.ts +29 -0
  115. package/dist/native/op.d.ts.map +1 -0
  116. package/dist/native/op.js +50 -0
  117. package/dist/native/op.js.map +1 -0
  118. package/dist/query/atom.d.ts +13 -14
  119. package/dist/query/atom.d.ts.map +1 -1
  120. package/dist/query/atom.js +2 -2
  121. package/dist/query/atom.js.map +1 -1
  122. package/dist/query/compute.d.ts +4 -4
  123. package/dist/query/compute.d.ts.map +1 -1
  124. package/dist/query/compute.js +4 -4
  125. package/dist/query/compute.js.map +1 -1
  126. package/dist/query/find.d.ts +8 -8
  127. package/dist/query/find.d.ts.map +1 -1
  128. package/dist/query/find.js +1 -1
  129. package/dist/query/lower.d.ts +22 -17
  130. package/dist/query/lower.d.ts.map +1 -1
  131. package/dist/query/lower.js +230 -343
  132. package/dist/query/lower.js.map +1 -1
  133. package/dist/query/run.d.ts +5 -5
  134. package/dist/query/run.d.ts.map +1 -1
  135. package/dist/query/run.js +32 -15
  136. package/dist/query/run.js.map +1 -1
  137. package/dist/query/scope.d.ts +20 -28
  138. package/dist/query/scope.d.ts.map +1 -1
  139. package/dist/query/scope.js +7 -7
  140. package/dist/query/scope.js.map +1 -1
  141. package/dist/query/segments.d.ts +2 -2
  142. package/dist/query/segments.d.ts.map +1 -1
  143. package/dist/query/segments.js +3 -3
  144. package/dist/query/segments.js.map +1 -1
  145. package/dist/relation.d.ts +1 -1
  146. package/dist/relation.d.ts.map +1 -1
  147. package/dist/relation.js +4 -4
  148. package/dist/relation.js.map +1 -1
  149. package/dist/result.d.ts +15 -22
  150. package/dist/result.d.ts.map +1 -1
  151. package/dist/result.js +30 -39
  152. package/dist/result.js.map +1 -1
  153. package/dist/rows.d.ts +9 -33
  154. package/dist/rows.d.ts.map +1 -1
  155. package/dist/rows.js +8 -12
  156. package/dist/rows.js.map +1 -1
  157. package/dist/runtime.d.ts +17 -20
  158. package/dist/runtime.d.ts.map +1 -1
  159. package/dist/runtime.js +41 -205
  160. package/dist/runtime.js.map +1 -1
  161. package/dist/scalar.d.ts +4 -4
  162. package/dist/scalar.d.ts.map +1 -1
  163. package/dist/scalar.js +24 -8
  164. package/dist/scalar.js.map +1 -1
  165. package/dist/schema.d.ts +7 -18
  166. package/dist/schema.d.ts.map +1 -1
  167. package/dist/schema.js +18 -228
  168. package/dist/schema.js.map +1 -1
  169. package/dist/selection.d.ts +4 -4
  170. package/dist/selection.d.ts.map +1 -1
  171. package/dist/selection.js +5 -5
  172. package/dist/selection.js.map +1 -1
  173. package/dist/shape.d.ts +5 -5
  174. package/dist/shape.d.ts.map +1 -1
  175. package/dist/spec.d.ts +7 -79
  176. package/dist/spec.d.ts.map +1 -1
  177. package/dist/spec.js.map +1 -1
  178. package/dist/statements.d.ts +3 -3
  179. package/dist/statements.d.ts.map +1 -1
  180. package/dist/statements.js +10 -10
  181. package/dist/statements.js.map +1 -1
  182. package/dist/uuid.d.ts +1 -1
  183. package/dist/uuid.d.ts.map +1 -1
  184. package/dist/uuid.js +1 -1
  185. package/dist/uuid.js.map +1 -1
  186. package/dist/values.d.ts +2 -2
  187. package/dist/values.d.ts.map +1 -1
  188. package/dist/values.js +2 -2
  189. package/dist/values.js.map +1 -1
  190. package/package.json +18 -18
  191. package/src/alternatives.ts +7 -8
  192. package/src/bin.ts +82 -0
  193. package/src/capacity.ts +20 -23
  194. package/src/changes.ts +134 -191
  195. package/src/closed.ts +5 -5
  196. package/src/codec.ts +35 -49
  197. package/src/compile.ts +91 -113
  198. package/src/database/database.ts +413 -0
  199. package/src/database/driver.ts +134 -0
  200. package/src/database/fs.ts +119 -0
  201. package/src/database/generate.ts +116 -0
  202. package/src/database/hosted.ts +102 -0
  203. package/src/database/io.ts +134 -0
  204. package/src/database/mem.ts +113 -0
  205. package/src/database/migration.ts +107 -0
  206. package/src/database/s3.ts +231 -0
  207. package/src/db.ts +290 -547
  208. package/src/engine.ts +14 -0
  209. package/src/errors.ts +118 -39
  210. package/src/face.ts +9 -9
  211. package/src/fields.ts +6 -7
  212. package/src/index.ts +92 -105
  213. package/src/judgment.ts +1 -1
  214. package/src/law.ts +18 -70
  215. package/src/lower.ts +61 -72
  216. package/src/native/addon.ts +54 -0
  217. package/src/native/binding.d.ts +996 -0
  218. package/src/native/json.ts +100 -0
  219. package/src/native/load.ts +31 -0
  220. package/src/native/op.ts +73 -0
  221. package/src/query/atom.ts +15 -16
  222. package/src/query/compute.ts +7 -7
  223. package/src/query/find.ts +8 -8
  224. package/src/query/lower.ts +270 -392
  225. package/src/query/run.ts +42 -21
  226. package/src/query/scope.ts +29 -37
  227. package/src/query/segments.ts +4 -4
  228. package/src/relation.ts +4 -4
  229. package/src/result.ts +53 -80
  230. package/src/rows.ts +18 -46
  231. package/src/runtime.ts +50 -277
  232. package/src/scalar.ts +32 -12
  233. package/src/schema.ts +23 -284
  234. package/src/selection.ts +6 -6
  235. package/src/shape.ts +5 -5
  236. package/src/spec.ts +7 -85
  237. package/src/statements.ts +11 -11
  238. package/src/uuid.ts +1 -1
  239. package/src/values.ts +4 -4
  240. package/dist/close.d.ts +0 -24
  241. package/dist/close.d.ts.map +0 -1
  242. package/dist/close.js +0 -34
  243. package/dist/close.js.map +0 -1
  244. package/dist/db-native.d.ts +0 -189
  245. package/dist/db-native.d.ts.map +0 -1
  246. package/dist/db-native.js +0 -13
  247. package/dist/db-native.js.map +0 -1
  248. package/dist/internal/log.d.ts +0 -26
  249. package/dist/internal/log.d.ts.map +0 -1
  250. package/dist/internal/log.js +0 -12
  251. package/dist/internal/log.js.map +0 -1
  252. package/dist/native.d.ts +0 -562
  253. package/dist/native.d.ts.map +0 -1
  254. package/dist/native.js +0 -123
  255. package/dist/native.js.map +0 -1
  256. package/dist/query/description.d.ts +0 -41
  257. package/dist/query/description.d.ts.map +0 -1
  258. package/dist/query/description.js +0 -311
  259. package/dist/query/description.js.map +0 -1
  260. package/dist/query/parse-ir.d.ts +0 -10
  261. package/dist/query/parse-ir.d.ts.map +0 -1
  262. package/dist/query/parse-ir.js +0 -280
  263. package/dist/query/parse-ir.js.map +0 -1
  264. package/dist/runtime-codes.d.ts +0 -2
  265. package/dist/runtime-codes.d.ts.map +0 -1
  266. package/dist/runtime-codes.js +0 -19
  267. package/dist/runtime-codes.js.map +0 -1
  268. package/dist/runtime-errors.d.ts +0 -138
  269. package/dist/runtime-errors.d.ts.map +0 -1
  270. package/dist/runtime-errors.js +0 -111
  271. package/dist/runtime-errors.js.map +0 -1
  272. package/dist/runtime-native.d.ts +0 -136
  273. package/dist/runtime-native.d.ts.map +0 -1
  274. package/dist/runtime-native.js +0 -5
  275. package/dist/runtime-native.js.map +0 -1
  276. package/dist/schema-file.d.ts +0 -7
  277. package/dist/schema-file.d.ts.map +0 -1
  278. package/dist/schema-file.js +0 -24
  279. package/dist/schema-file.js.map +0 -1
  280. package/pack-provenance.json +0 -7
  281. package/src/close.ts +0 -53
  282. package/src/db-native.ts +0 -235
  283. package/src/internal/log.ts +0 -46
  284. package/src/native.ts +0 -736
  285. package/src/query/description.ts +0 -424
  286. package/src/query/parse-ir.ts +0 -293
  287. package/src/runtime-codes.ts +0 -18
  288. package/src/runtime-errors.ts +0 -122
  289. package/src/runtime-native.ts +0 -181
  290. package/src/schema-file.ts +0 -38
package/src/query/run.ts CHANGED
@@ -1,11 +1,34 @@
1
- import { AuthoringError, SdkInvariantError } from "#errors.ts"
2
- import type { QueryParam, TaggedValue } from "#native.ts"
3
- import type { FindColumn } from "#query/atom.ts"
4
- import { taggedCmpLiteral } from "#query/lower.ts"
5
- import type { ParamEntry } from "#query/scope.ts"
6
- import type { CellValue } from "#rows.ts"
7
- import { decodeCell, handleOf, setOwnField } from "#rows.ts"
8
- import { arrayValue, recordValue } from "#values.ts"
1
+ import { AuthoringError, internalError } from "../errors.ts"
2
+ import type { CellIn, ParamIn } from "../native/binding.d.ts"
3
+ import type { CellValue } from "../rows.ts"
4
+ import { decodeCell, handleOf, setOwnField } from "../rows.ts"
5
+ import type { QueryParam, TaggedValue } from "../spec.ts"
6
+ import { arrayValue, recordValue } from "../values.ts"
7
+ import type { FindColumn } from "./atom.ts"
8
+ import { taggedCmpLiteral } from "./lower.ts"
9
+ import type { ParamEntry } from "./scope.ts"
10
+
11
+ const CELL = {
12
+ bool: "Bool",
13
+ u64: "U64",
14
+ i64: "I64",
15
+ f64: "F64",
16
+ string: "String",
17
+ uuid: "Uuid",
18
+ fixedBytes: "FixedBytes",
19
+ intervalU64: "IntervalU64",
20
+ intervalI64: "IntervalI64",
21
+ intervalF64: "IntervalF64"
22
+ } as const
23
+
24
+ /** One tagged value as the addon's data-plane `CellIn`. */
25
+ function cellIn(value: TaggedValue): CellIn {
26
+ return { ...value, kind: CELL[value.kind] } as CellIn
27
+ }
28
+
29
+ function paramIn(param: QueryParam): ParamIn {
30
+ return param.kind === "set" ? { kind: "Set", values: param.values.map(cellIn) } : cellIn(param)
31
+ }
9
32
 
10
33
  function wireValue(entry: ParamEntry, context: string, value: unknown): TaggedValue {
11
34
  if (entry.anchor === undefined) {
@@ -16,15 +39,15 @@ function wireValue(entry: ParamEntry, context: string, value: unknown): TaggedVa
16
39
  return taggedCmpLiteral(context, entry.anchor, value, entry.op)
17
40
  }
18
41
 
19
- function wireParams(entries: readonly ParamEntry[], supplied: Readonly<Record<string, unknown>>): QueryParam[] {
42
+ function wireParams(entries: readonly ParamEntry[], supplied: Readonly<Record<string, unknown>>): ParamIn[] {
20
43
  const input = recordValue(
21
44
  "query parameters",
22
45
  supplied,
23
46
  entries.filter((entry) => entry.membership === undefined).map((entry) => entry.name)
24
47
  )
25
- return entries.map(function wireOne(entry): QueryParam {
48
+ return entries.map(function wireOne(entry): ParamIn {
26
49
  if (entry.membership !== undefined) {
27
- return entry.membership
50
+ return paramIn(entry.membership)
28
51
  }
29
52
  const value = input[entry.name]
30
53
  if (value === undefined) {
@@ -32,13 +55,13 @@ function wireParams(entries: readonly ParamEntry[], supplied: Readonly<Record<st
32
55
  }
33
56
  if (entry.shape === "set") {
34
57
  return {
35
- kind: "set",
36
- values: arrayValue(`param ${entry.name}`, value, function wireElement(context, element) {
37
- return wireValue(entry, context, element)
38
- })
58
+ kind: "Set",
59
+ values: [
60
+ ...arrayValue(`param ${entry.name}`, value, (context, element) => cellIn(wireValue(entry, context, element)))
61
+ ]
39
62
  }
40
63
  }
41
- return wireValue(entry, `param ${entry.name}`, value)
64
+ return cellIn(wireValue(entry, `param ${entry.name}`, value))
42
65
  })
43
66
  }
44
67
 
@@ -63,15 +86,13 @@ function isAnswerRow<Row>(
63
86
  function decodeAnswers<Row>(finds: readonly FindColumn[], rows: readonly (readonly CellValue[])[]): Row[] {
64
87
  return rows.map(function decodeRow(row) {
65
88
  if (row.length !== finds.length) {
66
- throw new SdkInvariantError({
67
- message: `query answer arity ${row.length} does not match the ${finds.length} find columns`
68
- })
89
+ throw internalError(`query answer arity ${row.length} does not match the ${finds.length} find columns`)
69
90
  }
70
91
  const decoded: Record<string, unknown> = {}
71
92
  finds.forEach(function decodeColumn(column, ordinal) {
72
93
  const cell = row[ordinal]
73
94
  if (cell === undefined) {
74
- throw new SdkInvariantError({ message: `query answer cell ${ordinal} (${column.name}) is absent` })
95
+ throw internalError(`query answer cell ${ordinal} (${column.name}) is absent`)
75
96
  }
76
97
  if (column.slot !== undefined) {
77
98
  setOwnField(decoded, column.name, decodeCell(`query answer column ${column.name}`, column.slot.field, cell))
@@ -85,7 +106,7 @@ function decodeAnswers<Row>(finds: readonly FindColumn[], rows: readonly (readon
85
106
  })
86
107
  Object.freeze(decoded)
87
108
  if (!isAnswerRow<Row>(finds, decoded)) {
88
- throw new SdkInvariantError({ message: "query answer row is not a complete find record" })
109
+ throw internalError("query answer row is not a complete find record")
89
110
  }
90
111
  return decoded
91
112
  })
@@ -1,18 +1,18 @@
1
- import type { AnyClosed } from "#closed.ts"
2
- import { memberDescriptor, sealedFieldsOf } from "#closed.ts"
3
- import { AuthoringError, SdkInvariantError } from "#errors.ts"
4
- import type { AnyField, Infer, SignatureOf } from "#fields.ts"
5
- import { rosterOf, signaturesAgree } from "#fields.ts"
6
- import type { Same, SameLen } from "#judgment.ts"
7
- import type { ClassLookup, ClassRecordOf, SchemaClasses } from "#law.ts"
8
- import type { QueryParam } from "#native.ts"
9
- import type { FindColumn } from "#query/atom.ts"
10
- import type { AnyRelation } from "#relation.ts"
11
- import type { FieldsOf } from "#selection.ts"
12
-
13
- const term: unique symbol = Symbol("bumbledb.query.term")
14
-
15
- const inferred: unique symbol = Symbol("bumbledb.query.inferred")
1
+ import type { AnyClosed } from "../closed.ts"
2
+ import { memberDescriptor, sealedFieldsOf } from "../closed.ts"
3
+ import { AuthoringError, internalError } from "../errors.ts"
4
+ import type { AnyField, Infer, SignatureOf } from "../fields.ts"
5
+ import { rosterOf, signaturesAgree } from "../fields.ts"
6
+ import type { Same, SameLen } from "../judgment.ts"
7
+ import type { ClassLookup, ClassRecordOf, SchemaClasses } from "../law.ts"
8
+ import type { AnyRelation } from "../relation.ts"
9
+ import type { FieldsOf } from "../selection.ts"
10
+ import type { QueryParam } from "../spec.ts"
11
+ import type { FindColumn } from "./atom.ts"
12
+
13
+ const term: unique symbol = Symbol("bdb.query.term")
14
+
15
+ const inferred: unique symbol = Symbol("bdb.query.inferred")
16
16
 
17
17
  type MatchOwner = AnyRelation | AnyClosed
18
18
 
@@ -58,11 +58,10 @@ type VarsOf<R extends MatchOwner> = {
58
58
  * mintable variable inhabits. So an aliased or function-returned record
59
59
  * carrying an extra key (`{...v(Account), extra: otherVar }` — shapes
60
60
  * excess-property checking never sees, it covers inline literals only)
61
- * fails the intersection and falls to the general form's judgment: the
62
- * pre-0.16.0 compile refusal, restored. The identity record `v(rel)` still
63
- * unifies for GENERIC `R` — the judgment is intersections and index
64
- * constraints only, no deferred conditional anywhere, so the full-binding
65
- * law (50-generic-binding.md, "The ruling") stands untouched.
61
+ * fails the intersection and falls to the general form's compile refusal.
62
+ * The identity record `v(rel)` still unifies for GENERIC `R`: the judgment
63
+ * is intersections and index constraints only, with no deferred
64
+ * conditional, so the full-binding law holds.
66
65
  */
67
66
  type ExactVars<R extends MatchOwner, B> = {
68
67
  readonly [K in keyof B]: Var<AnyField, R["name"], K & keyof MatchFields<R> & string>
@@ -80,21 +79,9 @@ function varsMinted<R extends MatchOwner>(owner: R, record: Readonly<Record<stri
80
79
  })
81
80
  }
82
81
 
83
- /**
84
- * Mints a FRESH batch of query variables over an atom owner's
85
- * statically-known columns — one variable per sealed column
86
- * (`sealedFieldsOf`: a closed owner mints `id` first, then payload columns),
87
- * each frozen and each defined by OWN-property definition (object-protocol
88
- * column names must work, the `closed` precedent). Every `v` call mints
89
- * new objects, so two batches are two variables; property access within one
90
- * batch is stable by construction (the record is an eager frozen record,
91
- * never a Proxy). Variable identity is the object reference: destructure
92
- * what you need (`const { id, holder } = v(Account)`) and reuse a value
93
- * across binding positions to join.
94
- */
95
82
  /**
96
83
  * A schema-bound query template used as a relation-expression source
97
- * (chapter 34's nonrecursive composition): structurally, the query value's
84
+ * (nonrecursive composition): structurally, the query value's
98
85
  * own frozen data. Detection is structural so `scope.ts` needs no runtime
99
86
  * import of the query module.
100
87
  */
@@ -194,6 +181,11 @@ function importFacadeOfOwner(owner: object): ImportFacade | undefined {
194
181
  return facadeByOwner.get(owner)
195
182
  }
196
183
 
184
+ /**
185
+ * Mints fresh query variables, one per column of a relation, closed roster or imported query
186
+ * (a closed owner's `id` first). Each call mints new variables; reusing one across binding
187
+ * positions joins, so destructure what you need: `const { id, holder } = v(Account)`.
188
+ */
197
189
  function v<R extends MatchOwner>(owner: R): VarsOf<R>
198
190
  function v<Q extends ImportedSource>(imported: Q): ImportVars<Q>
199
191
  function v(owner: MatchOwner | ImportedSource): Readonly<Record<string, AnyVar>> {
@@ -203,7 +195,7 @@ function v(owner: MatchOwner | ImportedSource): Readonly<Record<string, AnyVar>>
203
195
  for (const [columnName, column] of facade.columns) {
204
196
  const slot = column.slot
205
197
  if (slot === undefined) {
206
- throw new SdkInvariantError({ message: `v(query): facade column ${columnName} lost its slot` })
198
+ throw internalError(`v(query): facade column ${columnName} lost its slot`)
207
199
  }
208
200
  const variable: AnyVar = Object.freeze({
209
201
  [term]: "var" as const,
@@ -230,7 +222,7 @@ function v(owner: MatchOwner | ImportedSource): Readonly<Record<string, AnyVar>>
230
222
  }
231
223
  Object.freeze(record)
232
224
  if (!varsMinted(member, record)) {
233
- throw new SdkInvariantError({ message: `v(${member.name}): variable-record minting incomplete` })
225
+ throw internalError(`v(${member.name}): variable-record minting incomplete`)
234
226
  }
235
227
  return record
236
228
  }
@@ -305,8 +297,8 @@ type ClosedHandles<F extends AnyField> = F extends {
305
297
 
306
298
  /**
307
299
  * Two closed ids anti-join when their handle vectors carry the same Peano
308
- * length ({@link SameLen}: zero equals zero, successor recurses on
309
- * successor). A bare field has no vector and proves nothing.
300
+ * length ({@link SameLen}: zero equals zero, n + 1 recurses on n). A bare
301
+ * field has no vector and proves nothing.
310
302
  */
311
303
  type ClosedIdOk<A extends AnyField, B extends AnyField> = [ClosedHandles<A>] extends [never]
312
304
  ? false
@@ -1,7 +1,7 @@
1
- import { AuthoringError } from "#errors.ts"
2
- import type { IntervalElementKind, IntervalField } from "#fields.ts"
3
- import { type AnyVar, isTerm, term } from "#query/scope.ts"
4
- import { recordValue } from "#values.ts"
1
+ import { AuthoringError } from "../errors.ts"
2
+ import type { IntervalElementKind, IntervalField } from "../fields.ts"
3
+ import { recordValue } from "../values.ts"
4
+ import { type AnyVar, isTerm, term } from "./scope.ts"
5
5
 
6
6
  type IntervalVar<E extends IntervalElementKind = IntervalElementKind> = AnyVar & { readonly field: IntervalField<E> }
7
7
  type SegmentOp = "intersection" | "difference"
package/src/relation.ts CHANGED
@@ -1,13 +1,13 @@
1
- import { AuthoringError } from "#errors.ts"
1
+ import { AuthoringError } from "./errors.ts"
2
2
  import {
3
3
  type AnyField,
4
4
  assertDeclarationOrderKey,
5
5
  assertDeclarationRecord,
6
6
  fieldDescriptor,
7
7
  type Infer
8
- } from "#fields.ts"
9
- import { descriptorCache } from "#immutable.ts"
10
- import { recordValue } from "#values.ts"
8
+ } from "./fields.ts"
9
+ import { descriptorCache } from "./immutable.ts"
10
+ import { recordValue } from "./values.ts"
11
11
 
12
12
  /** Ordinary relations are structural declarations. Field order defines native ordinals. */
13
13
  interface Relation<Name extends string = string, Fields extends FieldsShape = FieldsShape> {
package/src/result.ts CHANGED
@@ -1,101 +1,74 @@
1
1
  import { Effect, Option, Stream } from "effect"
2
- import { drainClose, releaseOwner } from "#close.ts"
3
- import type { CursorHandle, ResultHandle } from "#db-native.ts"
4
- import { dbNative } from "#db-native.ts"
5
- import type { FindColumn } from "#query/atom.ts"
6
- import { decodeAnswers } from "#query/run.ts"
7
- import type { CellValue } from "#rows.ts"
8
- import { nativeOperationWith } from "#runtime.ts"
9
- import type { CloseReport, DbError } from "#runtime-errors.ts"
2
+ import type { DbError } from "./errors.ts"
3
+ import type { CursorRef, ResultRef } from "./native/addon.ts"
4
+ import { addon } from "./native/addon.ts"
5
+ import { call, scoped } from "./native/op.ts"
6
+ import type { FindColumn } from "./query/atom.ts"
7
+ import { decodeAnswers } from "./query/run.ts"
8
+ import type { CellValue } from "./rows.ts"
10
9
 
11
10
  /**
12
- * One complete answer set, sealed after evaluation and independent of its
13
- * source snapshot. collect() explicitly materializes all rows into JS and
14
- * leaves the result available. pages() consumes it once through bounded
15
- * delivery batches; it does not stream query execution.
16
- *
17
- * The stream owns its cursor through Effect scope. Early termination,
18
- * failure, interruption and EOF close/drain it. Creating the stream does
19
- * not spend the result; running it twice fails with SpentHandle.
11
+ * One complete answer set, sealed after evaluation and independent of its snapshot. `collect`
12
+ * reads every row and leaves the result readable. `pages` spends the result once through
13
+ * bounded batches; the stream owns its cursor, so ending it early releases the cursor, and
14
+ * running it a second time fails with `SpentHandle`.
20
15
  */
21
16
  interface CompleteResult<A> {
22
17
  collect(): Effect.Effect<ReadonlyArray<A>, DbError>
23
18
  pages(): Stream.Stream<ReadonlyArray<A>, DbError>
24
- close(): Effect.Effect<CloseReport>
25
19
  }
26
20
 
27
- interface ResultInternal {
28
- readonly handle: ResultHandle
21
+ function decodePage<A>(finds: readonly FindColumn[], rows: readonly (readonly CellValue[])[]): ReadonlyArray<A> {
22
+ return Object.freeze(decodeAnswers<A>(finds, rows))
29
23
  }
30
24
 
31
- const resultInternals = new WeakMap<object, ResultInternal>()
25
+ class CompleteResultLive<A> implements CompleteResult<A> {
26
+ readonly #handle: ResultRef
27
+ readonly #finds: readonly FindColumn[]
32
28
 
33
- /** Private cross-module accessor (scope finalizers in db.ts reach the handle). */
34
- function internalResult(value: object): ResultInternal | undefined {
35
- return resultInternals.get(value)
36
- }
29
+ constructor(handle: ResultRef, finds: readonly FindColumn[]) {
30
+ this.#handle = handle
31
+ this.#finds = finds
32
+ }
37
33
 
38
- function decodePage<A>(finds: readonly FindColumn[], rows: readonly (readonly CellValue[])[]): ReadonlyArray<A> {
39
- // Owned ordinary records in declared column order — the same fields and
40
- // shapes on every page (stable row shape; no Proxy, no per-row fiber).
41
- return Object.freeze(decodeAnswers<A>(finds, rows))
42
- }
34
+ collect(): Effect.Effect<ReadonlyArray<A>, DbError> {
35
+ const handle = this.#handle
36
+ const finds = this.#finds
37
+ return call(
38
+ "CompleteResult.collect",
39
+ (done) => addon.runtimeResultCollect(handle, done),
40
+ (lease) => decodePage<A>(finds, addon.runtimeRowsTake(lease))
41
+ ).pipe(Effect.withSpan("CompleteResult.collect"))
42
+ }
43
43
 
44
- /**
45
- * Internal constructor: `db.ts` publishes results through this after
46
- * execution completes. Each delivery has independent cooperative cancellation.
47
- */
48
- function makeCompleteResult<A>(handle: ResultHandle, finds: readonly FindColumn[]): CompleteResult<A> {
49
- const value: CompleteResult<A> = {
50
- collect() {
51
- return Effect.suspend(() =>
52
- nativeOperationWith(
53
- "CompleteResult.collect",
54
- (callback) => dbNative.runtimeResultCollect(handle, callback),
55
- dbNative.runtimeRowsTake,
56
- (rows) => decodePage<A>(finds, rows)
44
+ pages(): Stream.Stream<ReadonlyArray<A>, DbError> {
45
+ const handle = this.#handle
46
+ const finds = this.#finds
47
+ return Stream.unwrap(
48
+ Effect.gen(function* () {
49
+ const cursor: CursorRef = yield* scoped(
50
+ "ResultCursor.release",
51
+ call("CompleteResult.pages", (done) => addon.runtimeResultCursor(handle, done), addon.runtimeCursorTake),
52
+ (owned) => (done) => addon.runtimeCursorClose(owned, done)
57
53
  )
58
- )
59
- },
60
- pages() {
61
- return Stream.unwrap(
62
- Effect.gen(function* () {
63
- const cursor: CursorHandle = yield* Effect.acquireRelease(
64
- nativeOperationWith(
65
- "CompleteResult.pages",
66
- (callback) => dbNative.runtimeResultCursor(handle, callback),
67
- dbNative.runtimeCursorTake,
68
- (taken) => taken
69
- ),
70
- (taken) => releaseOwner("ResultCursor.close", (callback) => dbNative.runtimeCursorClose(taken, callback)),
71
- { interruptible: true }
72
- )
73
- return Stream.paginate(undefined, () =>
74
- nativeOperationWith(
75
- "CompleteResult.page",
76
- (callback) => dbNative.runtimeCursorNext(cursor, callback),
77
- dbNative.runtimePageTake,
78
- (page) => page
79
- ).pipe(
80
- Effect.map((page) => {
81
- if (page === null) {
82
- return [[], Option.none<undefined>()] as const
83
- }
84
- return [[decodePage<A>(finds, page)], Option.some(undefined)] as const
85
- })
54
+ return Stream.paginate(undefined, () =>
55
+ call("CompleteResult.page", (done) => addon.runtimeCursorNext(cursor, done), addon.runtimePageTake).pipe(
56
+ Effect.map((page) =>
57
+ page === null
58
+ ? ([[], Option.none<undefined>()] as const)
59
+ : ([[decodePage<A>(finds, page)], Option.some(undefined)] as const)
86
60
  )
87
61
  )
88
- })
89
- )
90
- },
91
- close() {
92
- return drainClose("CompleteResult.close", (callback) => dbNative.runtimeResultClose(handle, callback))
93
- }
62
+ )
63
+ })
64
+ ).pipe(Stream.withSpan("CompleteResult.pages"))
65
+ }
66
+
67
+ /** The native result behind `value`, when `value` is a result this SDK made. */
68
+ static handle(value: object): ResultRef | undefined {
69
+ return #handle in value ? (value as CompleteResultLive<unknown>).#handle : undefined
94
70
  }
95
- Object.freeze(value)
96
- resultInternals.set(value, { handle })
97
- return value
98
71
  }
99
72
 
100
73
  export type { CompleteResult }
101
- export { internalResult, makeCompleteResult }
74
+ export { CompleteResultLive }
package/src/rows.ts CHANGED
@@ -1,46 +1,20 @@
1
- import { AuthoringError, SdkInvariantError } from "#errors.ts"
1
+ import { AuthoringError, internalError } from "./errors.ts"
2
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.
3
+ * The one fact ⇄ row projector: named host objects to positional cells in field-declaration order
4
+ * and back, for every value type plus the closed-handle bijection (name ⇄ declaration-order id).
5
+ * Cells are owned host values that the native boundary checks again; shape misuse throws
6
+ * `AuthoringError`. SharedArrayBuffer-backed views are refused before any copy.
18
7
  */
19
- import type { AnyClosedRoster, AnyField } from "#fields.ts"
20
- import { literalShapeError, rosterOf } from "#fields.ts"
21
- import { type AnyRelation, type Fact, relationFields } from "#relation.ts"
22
- import { fieldValue, recordValue } from "#values.ts"
23
-
24
- /**
25
- * One owned cell at the private bridge boundary. The declared sealed field
26
- * type disambiguates the union: `string` is text, an `uuid` in its
27
- * canonical hyphenated UUID spelling, or a closed handle
28
- * before lowering (closed handles cross as `bigint` row ids),
29
- * `Uint8Array` is `bytes<N>`, `{ start, end }` bigints are a discrete
30
- * interval and numbers a dense float interval.
31
- */
32
- type CellValue =
33
- | boolean
34
- | bigint
35
- | number
36
- | string
37
- | Uint8Array
38
- | { readonly start: bigint; readonly end: bigint }
39
- | { readonly start: number; readonly end: number }
8
+ import type { AnyClosedRoster, AnyField } from "./fields.ts"
9
+ import { literalShapeError, rosterOf } from "./fields.ts"
10
+ import type { CellValue } from "./native/binding.d.ts"
11
+ import { type AnyRelation, type Fact, relationFields } from "./relation.ts"
12
+ import { fieldValue, recordValue } from "./values.ts"
40
13
 
14
+ /** Row-major cells for `rows` rows, in sealed field order. */
41
15
  interface FlatRows {
42
16
  readonly rows: bigint
43
- readonly cells: readonly CellValue[]
17
+ readonly cells: CellValue[]
44
18
  }
45
19
 
46
20
  function recordOf(fact: object): Readonly<Record<string, unknown>> {
@@ -141,7 +115,7 @@ function decodeCell(context: string, field: AnyField, cell: unknown): unknown {
141
115
  try {
142
116
  return fieldValue(context, field, cell)
143
117
  } catch (cause) {
144
- if (cause instanceof AuthoringError) throw new SdkInvariantError({ message: cause.message })
118
+ if (cause instanceof AuthoringError) throw internalError(cause.message)
145
119
  throw cause
146
120
  }
147
121
  }
@@ -162,24 +136,22 @@ function isCompleteFact<R extends AnyRelation>(
162
136
  function factOfCells<R extends AnyRelation>(relation: R, row: readonly unknown[]): Fact<R> {
163
137
  const data = relation
164
138
  if (row.length !== relationFields(data).length) {
165
- throw new SdkInvariantError({
166
- message: `relation ${data.name}: row arity ${row.length} does not match the ${relationFields(data).length} declared fields`
167
- })
139
+ throw internalError(
140
+ `relation ${data.name}: row arity ${row.length} does not match the ${relationFields(data).length} declared fields`
141
+ )
168
142
  }
169
143
  const decoded: Record<string, unknown> = {}
170
144
  relationFields(data).forEach(function decodeOne(declared, ordinal) {
171
145
  const cell = row[ordinal]
172
146
  if (cell === undefined) {
173
- throw new SdkInvariantError({
174
- message: `relation ${data.name}: row cell ${ordinal} (${declared.name}) is absent`
175
- })
147
+ throw internalError(`relation ${data.name}: row cell ${ordinal} (${declared.name}) is absent`)
176
148
  }
177
149
  const value = decodeCell(`relation ${data.name} field ${declared.name}`, declared.field, cell)
178
150
  setOwnField(decoded, declared.name, value)
179
151
  })
180
152
  Object.freeze(decoded)
181
153
  if (!isCompleteFact(relation, decoded)) {
182
- throw new SdkInvariantError({ message: `relation ${data.name}: decoded row is not a complete fact` })
154
+ throw internalError(`relation ${data.name}: decoded row is not a complete fact`)
183
155
  }
184
156
  return decoded
185
157
  }