@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.
- package/COOKBOOK.md +153 -77
- package/README.md +107 -41
- package/dist/alternatives.d.ts +5 -6
- package/dist/alternatives.d.ts.map +1 -1
- package/dist/alternatives.js +5 -6
- package/dist/alternatives.js.map +1 -1
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +85 -0
- package/dist/bin.js.map +1 -0
- package/dist/capacity.d.ts +14 -17
- package/dist/capacity.d.ts.map +1 -1
- package/dist/capacity.js +7 -7
- package/dist/capacity.js.map +1 -1
- package/dist/changes.d.ts +32 -40
- package/dist/changes.d.ts.map +1 -1
- package/dist/changes.js +86 -104
- package/dist/changes.js.map +1 -1
- package/dist/closed.d.ts +2 -2
- package/dist/closed.d.ts.map +1 -1
- package/dist/closed.js +5 -5
- package/dist/closed.js.map +1 -1
- package/dist/codec.d.ts +13 -27
- package/dist/codec.d.ts.map +1 -1
- package/dist/codec.js +20 -21
- package/dist/codec.js.map +1 -1
- package/dist/compile.d.ts +26 -50
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +75 -64
- package/dist/compile.js.map +1 -1
- package/dist/database/database.d.ts +98 -0
- package/dist/database/database.d.ts.map +1 -0
- package/dist/database/database.js +249 -0
- package/dist/database/database.js.map +1 -0
- package/dist/database/driver.d.ts +40 -0
- package/dist/database/driver.d.ts.map +1 -0
- package/dist/database/driver.js +68 -0
- package/dist/database/driver.js.map +1 -0
- package/dist/database/fs.d.ts +12 -0
- package/dist/database/fs.d.ts.map +1 -0
- package/dist/database/fs.js +120 -0
- package/dist/database/fs.js.map +1 -0
- package/dist/database/generate.d.ts +26 -0
- package/dist/database/generate.d.ts.map +1 -0
- package/dist/database/generate.js +102 -0
- package/dist/database/generate.js.map +1 -0
- package/dist/database/hosted.d.ts +32 -0
- package/dist/database/hosted.d.ts.map +1 -0
- package/dist/database/hosted.js +44 -0
- package/dist/database/hosted.js.map +1 -0
- package/dist/database/io.d.ts +94 -0
- package/dist/database/io.d.ts.map +1 -0
- package/dist/database/io.js +35 -0
- package/dist/database/io.js.map +1 -0
- package/dist/database/mem.d.ts +26 -0
- package/dist/database/mem.d.ts.map +1 -0
- package/dist/database/mem.js +67 -0
- package/dist/database/mem.js.map +1 -0
- package/dist/database/migration.d.ts +55 -0
- package/dist/database/migration.d.ts.map +1 -0
- package/dist/database/migration.js +46 -0
- package/dist/database/migration.js.map +1 -0
- package/dist/database/s3.d.ts +36 -0
- package/dist/database/s3.d.ts.map +1 -0
- package/dist/database/s3.js +141 -0
- package/dist/database/s3.js.map +1 -0
- package/dist/db.d.ts +44 -128
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +163 -287
- package/dist/db.js.map +1 -1
- package/dist/engine.d.ts +7 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +2 -0
- package/dist/engine.js.map +1 -0
- package/dist/errors.d.ts +152 -46
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +107 -19
- package/dist/errors.js.map +1 -1
- package/dist/face.d.ts +5 -5
- package/dist/face.d.ts.map +1 -1
- package/dist/face.js +6 -6
- package/dist/face.js.map +1 -1
- package/dist/fields.d.ts +4 -5
- package/dist/fields.d.ts.map +1 -1
- package/dist/fields.js +3 -3
- package/dist/fields.js.map +1 -1
- package/dist/index.d.ts +60 -57
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +27 -28
- package/dist/index.js.map +1 -1
- package/dist/judgment.d.ts +1 -1
- package/dist/judgment.js +1 -1
- package/dist/law.d.ts +16 -68
- package/dist/law.d.ts.map +1 -1
- package/dist/law.js +3 -3
- package/dist/law.js.map +1 -1
- package/dist/lower.d.ts +3 -3
- package/dist/lower.d.ts.map +1 -1
- package/dist/lower.js +35 -39
- package/dist/lower.js.map +1 -1
- package/dist/native/addon.d.ts +23 -0
- package/dist/native/addon.d.ts.map +1 -0
- package/dist/native/addon.js +15 -0
- package/dist/native/addon.js.map +1 -0
- package/dist/native/binding.d.ts +996 -0
- package/dist/native/json.d.ts +14 -0
- package/dist/native/json.d.ts.map +1 -0
- package/dist/native/json.js +73 -0
- package/dist/native/json.js.map +1 -0
- package/dist/native/load.d.ts +9 -0
- package/dist/native/load.d.ts.map +1 -0
- package/dist/native/load.js +30 -0
- package/dist/native/load.js.map +1 -0
- package/dist/native/op.d.ts +29 -0
- package/dist/native/op.d.ts.map +1 -0
- package/dist/native/op.js +50 -0
- package/dist/native/op.js.map +1 -0
- package/dist/query/atom.d.ts +13 -14
- package/dist/query/atom.d.ts.map +1 -1
- package/dist/query/atom.js +2 -2
- package/dist/query/atom.js.map +1 -1
- package/dist/query/compute.d.ts +4 -4
- package/dist/query/compute.d.ts.map +1 -1
- package/dist/query/compute.js +4 -4
- package/dist/query/compute.js.map +1 -1
- package/dist/query/find.d.ts +8 -8
- package/dist/query/find.d.ts.map +1 -1
- package/dist/query/find.js +1 -1
- package/dist/query/lower.d.ts +22 -17
- package/dist/query/lower.d.ts.map +1 -1
- package/dist/query/lower.js +230 -343
- package/dist/query/lower.js.map +1 -1
- package/dist/query/run.d.ts +5 -5
- package/dist/query/run.d.ts.map +1 -1
- package/dist/query/run.js +32 -15
- package/dist/query/run.js.map +1 -1
- package/dist/query/scope.d.ts +20 -28
- package/dist/query/scope.d.ts.map +1 -1
- package/dist/query/scope.js +7 -7
- package/dist/query/scope.js.map +1 -1
- package/dist/query/segments.d.ts +2 -2
- package/dist/query/segments.d.ts.map +1 -1
- package/dist/query/segments.js +3 -3
- package/dist/query/segments.js.map +1 -1
- package/dist/relation.d.ts +1 -1
- package/dist/relation.d.ts.map +1 -1
- package/dist/relation.js +4 -4
- package/dist/relation.js.map +1 -1
- package/dist/result.d.ts +15 -22
- package/dist/result.d.ts.map +1 -1
- package/dist/result.js +30 -39
- package/dist/result.js.map +1 -1
- package/dist/rows.d.ts +9 -33
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +8 -12
- package/dist/rows.js.map +1 -1
- package/dist/runtime.d.ts +17 -20
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +41 -205
- package/dist/runtime.js.map +1 -1
- package/dist/scalar.d.ts +4 -4
- package/dist/scalar.d.ts.map +1 -1
- package/dist/scalar.js +24 -8
- package/dist/scalar.js.map +1 -1
- package/dist/schema.d.ts +7 -18
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +18 -228
- package/dist/schema.js.map +1 -1
- package/dist/selection.d.ts +4 -4
- package/dist/selection.d.ts.map +1 -1
- package/dist/selection.js +5 -5
- package/dist/selection.js.map +1 -1
- package/dist/shape.d.ts +5 -5
- package/dist/shape.d.ts.map +1 -1
- package/dist/spec.d.ts +7 -79
- package/dist/spec.d.ts.map +1 -1
- package/dist/spec.js.map +1 -1
- package/dist/statements.d.ts +3 -3
- package/dist/statements.d.ts.map +1 -1
- package/dist/statements.js +10 -10
- package/dist/statements.js.map +1 -1
- package/dist/uuid.d.ts +1 -1
- package/dist/uuid.d.ts.map +1 -1
- package/dist/uuid.js +1 -1
- package/dist/uuid.js.map +1 -1
- package/dist/values.d.ts +2 -2
- package/dist/values.d.ts.map +1 -1
- package/dist/values.js +2 -2
- package/dist/values.js.map +1 -1
- package/package.json +18 -18
- package/src/alternatives.ts +7 -8
- package/src/bin.ts +82 -0
- package/src/capacity.ts +20 -23
- package/src/changes.ts +134 -191
- package/src/closed.ts +5 -5
- package/src/codec.ts +35 -49
- package/src/compile.ts +91 -113
- package/src/database/database.ts +413 -0
- package/src/database/driver.ts +134 -0
- package/src/database/fs.ts +119 -0
- package/src/database/generate.ts +116 -0
- package/src/database/hosted.ts +102 -0
- package/src/database/io.ts +134 -0
- package/src/database/mem.ts +113 -0
- package/src/database/migration.ts +107 -0
- package/src/database/s3.ts +231 -0
- package/src/db.ts +290 -547
- package/src/engine.ts +14 -0
- package/src/errors.ts +118 -39
- package/src/face.ts +9 -9
- package/src/fields.ts +6 -7
- package/src/index.ts +92 -105
- package/src/judgment.ts +1 -1
- package/src/law.ts +18 -70
- package/src/lower.ts +61 -72
- package/src/native/addon.ts +54 -0
- package/src/native/binding.d.ts +996 -0
- package/src/native/json.ts +100 -0
- package/src/native/load.ts +31 -0
- package/src/native/op.ts +73 -0
- package/src/query/atom.ts +15 -16
- package/src/query/compute.ts +7 -7
- package/src/query/find.ts +8 -8
- package/src/query/lower.ts +270 -392
- package/src/query/run.ts +42 -21
- package/src/query/scope.ts +29 -37
- package/src/query/segments.ts +4 -4
- package/src/relation.ts +4 -4
- package/src/result.ts +53 -80
- package/src/rows.ts +18 -46
- package/src/runtime.ts +50 -277
- package/src/scalar.ts +32 -12
- package/src/schema.ts +23 -284
- package/src/selection.ts +6 -6
- package/src/shape.ts +5 -5
- package/src/spec.ts +7 -85
- package/src/statements.ts +11 -11
- package/src/uuid.ts +1 -1
- package/src/values.ts +4 -4
- package/dist/close.d.ts +0 -24
- package/dist/close.d.ts.map +0 -1
- package/dist/close.js +0 -34
- package/dist/close.js.map +0 -1
- package/dist/db-native.d.ts +0 -189
- package/dist/db-native.d.ts.map +0 -1
- package/dist/db-native.js +0 -13
- package/dist/db-native.js.map +0 -1
- package/dist/internal/log.d.ts +0 -26
- package/dist/internal/log.d.ts.map +0 -1
- package/dist/internal/log.js +0 -12
- package/dist/internal/log.js.map +0 -1
- package/dist/native.d.ts +0 -562
- package/dist/native.d.ts.map +0 -1
- package/dist/native.js +0 -123
- package/dist/native.js.map +0 -1
- package/dist/query/description.d.ts +0 -41
- package/dist/query/description.d.ts.map +0 -1
- package/dist/query/description.js +0 -311
- package/dist/query/description.js.map +0 -1
- package/dist/query/parse-ir.d.ts +0 -10
- package/dist/query/parse-ir.d.ts.map +0 -1
- package/dist/query/parse-ir.js +0 -280
- package/dist/query/parse-ir.js.map +0 -1
- package/dist/runtime-codes.d.ts +0 -2
- package/dist/runtime-codes.d.ts.map +0 -1
- package/dist/runtime-codes.js +0 -19
- package/dist/runtime-codes.js.map +0 -1
- package/dist/runtime-errors.d.ts +0 -138
- package/dist/runtime-errors.d.ts.map +0 -1
- package/dist/runtime-errors.js +0 -111
- package/dist/runtime-errors.js.map +0 -1
- package/dist/runtime-native.d.ts +0 -136
- package/dist/runtime-native.d.ts.map +0 -1
- package/dist/runtime-native.js +0 -5
- package/dist/runtime-native.js.map +0 -1
- package/dist/schema-file.d.ts +0 -7
- package/dist/schema-file.d.ts.map +0 -1
- package/dist/schema-file.js +0 -24
- package/dist/schema-file.js.map +0 -1
- package/pack-provenance.json +0 -7
- package/src/close.ts +0 -53
- package/src/db-native.ts +0 -235
- package/src/internal/log.ts +0 -46
- package/src/native.ts +0 -736
- package/src/query/description.ts +0 -424
- package/src/query/parse-ir.ts +0 -293
- package/src/runtime-codes.ts +0 -18
- package/src/runtime-errors.ts +0 -122
- package/src/runtime-native.ts +0 -181
- package/src/schema-file.ts +0 -38
package/src/changes.ts
CHANGED
|
@@ -1,43 +1,34 @@
|
|
|
1
1
|
import type { Scope } from "effect"
|
|
2
2
|
import { Effect, Exit, Option, Stream } from "effect"
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import type {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { type AnyRelation, type Fact, relationFields } from "
|
|
12
|
-
import type { CellValue } from "
|
|
13
|
-
import { factCellsOf, factOfCells, hostCellCharge } from "
|
|
14
|
-
import {
|
|
15
|
-
import type {
|
|
16
|
-
import {
|
|
17
|
-
import type {
|
|
18
|
-
import
|
|
19
|
-
import { bytesValue, recordValue } from "#values.ts"
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* `ChangeSet` — the engine's checked immutable delta:
|
|
23
|
-
* schema-fingerprint-bound canonical native bytes with
|
|
24
|
-
* one-command `(add, remove ∖ add)` normalization and exact same-fact
|
|
25
|
-
* add-wins. Immutable and reusable while open; sealing/submitting it later
|
|
26
|
-
* retains the SAME native value — no second JS row walk ever happens.
|
|
27
|
-
*/
|
|
28
|
-
/** Counts of distinct fact additions and removals, never input events. */
|
|
29
|
-
interface ChangeCounts {
|
|
30
|
-
readonly added: bigint
|
|
31
|
-
readonly removed: bigint
|
|
32
|
-
}
|
|
3
|
+
import { isClosedMember, membersAgree } from "./closed.ts"
|
|
4
|
+
import type { SchemaId } from "./compile.ts"
|
|
5
|
+
import { compiledOf, schemaTables } from "./compile.ts"
|
|
6
|
+
import { argumentError, DbError, dbError, internalError } from "./errors.ts"
|
|
7
|
+
import type { ChangesRef, DraftRef } from "./native/addon.ts"
|
|
8
|
+
import { addon } from "./native/addon.ts"
|
|
9
|
+
import type { ChangeCounts, ChangeKindOut, ChangeRecordOut, ChangesOut } from "./native/binding.d.ts"
|
|
10
|
+
import { call, drain, release, scoped } from "./native/op.ts"
|
|
11
|
+
import { type AnyRelation, type Fact, relationFields } from "./relation.ts"
|
|
12
|
+
import type { CellValue } from "./rows.ts"
|
|
13
|
+
import { factCellsOf, factOfCells, hostCellCharge } from "./rows.ts"
|
|
14
|
+
import { runtimeHandle } from "./runtime.ts"
|
|
15
|
+
import type { AnySchema, SchemaRelation } from "./schema.ts"
|
|
16
|
+
import { schemaDescriptor } from "./schema.ts"
|
|
17
|
+
import type { Rel } from "./shape.ts"
|
|
18
|
+
import { bytesValue, recordValue } from "./values.ts"
|
|
33
19
|
|
|
34
20
|
/** A relation-name-discriminated union of plain, fully typed facts. */
|
|
35
21
|
type ChangeRecord<S extends AnySchema> = {
|
|
36
22
|
[N in keyof S["relations"]]: S["relations"][N] extends AnyRelation
|
|
37
|
-
? { readonly relation: N; readonly kind:
|
|
23
|
+
? { readonly relation: N; readonly kind: ChangeKindOut; readonly fact: Fact<S["relations"][N]> }
|
|
38
24
|
: never
|
|
39
25
|
}[keyof S["relations"]]
|
|
40
26
|
|
|
27
|
+
/**
|
|
28
|
+
* The engine's checked immutable delta: schema-fingerprint-bound canonical native bytes with
|
|
29
|
+
* one-command `(add, remove ∖ add)` normalization and exact same-fact add-wins. Reusable while
|
|
30
|
+
* open; submitting it retains the same native value, so no second row walk happens.
|
|
31
|
+
*/
|
|
41
32
|
interface ChangeSet<S extends AnySchema> {
|
|
42
33
|
readonly schemaId: SchemaId
|
|
43
34
|
/** Distinct requested actions; use judge for effective counts against a store. */
|
|
@@ -51,26 +42,18 @@ interface ChangeSet<S extends AnySchema> {
|
|
|
51
42
|
toBytes(): Effect.Effect<Uint8Array, DbError>
|
|
52
43
|
/** Commutative add-wins composition into one command, not sequential replay. */
|
|
53
44
|
compose(other: ChangeSet<S>): Effect.Effect<ChangeSet<S>, DbError, Scope.Scope>
|
|
54
|
-
close(): Effect.Effect<CloseReport>
|
|
55
45
|
}
|
|
56
46
|
|
|
57
47
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* stable from an ingestion effect's execution start through its Exit;
|
|
63
|
-
* after successful ingestion the accepted native bytes are independent.
|
|
64
|
-
* Failure/interruption SPENDS the draft and initiates tracked drain.
|
|
65
|
-
* Concurrent/reentrant construction refuses and spends/drains the draft.
|
|
66
|
-
* `finish` consumes the draft; later ingestion or a second finish refuses
|
|
67
|
-
* through the spent capability state.
|
|
48
|
+
* A scoped, database-free change draft. Each method returns a lazy effect that reads its iterable
|
|
49
|
+
* when it runs (every rerun reads it again); accepted rows are copied, so later mutation of the
|
|
50
|
+
* input changes nothing. A failure, an interruption or concurrent use spends the draft; `finish`
|
|
51
|
+
* consumes it.
|
|
68
52
|
*/
|
|
69
53
|
interface ChangeDraft<S extends AnySchema> {
|
|
70
54
|
insert<R extends Rel<S>>(relation: R, rows: Iterable<Fact<R>>): Effect.Effect<void, DbError>
|
|
71
55
|
delete<R extends Rel<S>>(relation: R, rows: Iterable<Fact<R>>): Effect.Effect<void, DbError>
|
|
72
56
|
finish(): Effect.Effect<ChangeSet<S>, DbError, Scope.Scope>
|
|
73
|
-
close(): Effect.Effect<CloseReport>
|
|
74
57
|
}
|
|
75
58
|
|
|
76
59
|
/**
|
|
@@ -84,31 +67,19 @@ const CHUNK_BYTES = 65536n
|
|
|
84
67
|
const CHUNK_ROWS = 4096
|
|
85
68
|
|
|
86
69
|
interface DraftState {
|
|
87
|
-
readonly handle:
|
|
70
|
+
readonly handle: DraftRef
|
|
88
71
|
readonly theory: AnySchema
|
|
89
72
|
spent: boolean
|
|
90
73
|
inFlight: boolean
|
|
91
74
|
}
|
|
92
75
|
|
|
93
|
-
interface ChangesInternal {
|
|
94
|
-
readonly handle: ChangesHandle
|
|
95
|
-
readonly schemaId: SchemaId
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const changesInternals = new WeakMap<object, ChangesInternal>()
|
|
99
|
-
|
|
100
|
-
/** Private cross-module accessor (db.apply retains the native ChangeSet). */
|
|
101
|
-
function internalChanges(value: object): ChangesInternal | undefined {
|
|
102
|
-
return changesInternals.get(value)
|
|
103
|
-
}
|
|
104
|
-
|
|
105
76
|
function refusal(operation: string, reason: "SpentHandle" | "ClosedHandle" | "InvalidArgument"): DbError {
|
|
106
77
|
return new DbError({ operation, reason: { _tag: reason } })
|
|
107
78
|
}
|
|
108
79
|
|
|
109
80
|
interface Chunk {
|
|
110
81
|
readonly rows: bigint
|
|
111
|
-
readonly cells:
|
|
82
|
+
readonly cells: CellValue[]
|
|
112
83
|
readonly done: boolean
|
|
113
84
|
readonly leftover: object | undefined
|
|
114
85
|
}
|
|
@@ -167,16 +138,13 @@ function pullChunk(relation: AnyRelation, iterator: Iterator<object>, pending: o
|
|
|
167
138
|
return { rows, cells, done: false, leftover }
|
|
168
139
|
}
|
|
169
140
|
|
|
170
|
-
function spendAndDrain(state: DraftState
|
|
141
|
+
function spendAndDrain(state: DraftState): Effect.Effect<void> {
|
|
171
142
|
return Effect.suspend(() => {
|
|
172
143
|
if (state.spent) {
|
|
173
144
|
return Effect.void
|
|
174
145
|
}
|
|
175
146
|
state.spent = true
|
|
176
|
-
|
|
177
|
-
// diagnostic here (the ingestion failure itself is the caller's
|
|
178
|
-
// error), but native Closing accounting is never dropped.
|
|
179
|
-
return drainClose(operation, (callback) => dbNative.runtimeDraftClose(state.handle, callback)).pipe(Effect.asVoid)
|
|
147
|
+
return drain((done) => addon.runtimeDraftClose(state.handle, done)).pipe(Effect.asVoid)
|
|
180
148
|
})
|
|
181
149
|
}
|
|
182
150
|
|
|
@@ -186,7 +154,7 @@ function ingest(
|
|
|
186
154
|
relation: AnyRelation,
|
|
187
155
|
rows: Iterable<object>
|
|
188
156
|
): Effect.Effect<void, DbError> {
|
|
189
|
-
const verb = operation === "ChangeDraft.insert" ?
|
|
157
|
+
const verb = operation === "ChangeDraft.insert" ? addon.runtimeDraftInsert : addon.runtimeDraftDelete
|
|
190
158
|
return Effect.gen(function* () {
|
|
191
159
|
if (state.spent) {
|
|
192
160
|
return yield* Effect.fail(refusal(operation, "SpentHandle"))
|
|
@@ -194,7 +162,7 @@ function ingest(
|
|
|
194
162
|
if (state.inFlight) {
|
|
195
163
|
// Reentrant construction refuses AND spends/drains — there is
|
|
196
164
|
// no implicit queue.
|
|
197
|
-
yield* spendAndDrain(state
|
|
165
|
+
yield* spendAndDrain(state)
|
|
198
166
|
return yield* Effect.fail(refusal(operation, "SpentHandle"))
|
|
199
167
|
}
|
|
200
168
|
if (!membersAgree(state.theory.relations[relation.name], relation)) {
|
|
@@ -218,18 +186,19 @@ function ingest(
|
|
|
218
186
|
const chunk = yield* Effect.try({
|
|
219
187
|
try: () => pullChunk(relation, iterator, leftover),
|
|
220
188
|
catch: (cause) => argumentError(operation, cause)
|
|
221
|
-
}).pipe(Effect.catch((error) => spendAndDrain(state
|
|
189
|
+
}).pipe(Effect.catch((error) => spendAndDrain(state).pipe(Effect.andThen(Effect.fail(error)))))
|
|
222
190
|
leftover = chunk.leftover
|
|
223
191
|
done = chunk.done && leftover === undefined
|
|
224
192
|
if (chunk.rows === 0n) {
|
|
225
193
|
continue
|
|
226
194
|
}
|
|
227
195
|
yield* eventLoopTurn()
|
|
228
|
-
yield*
|
|
196
|
+
yield* call(
|
|
229
197
|
operation,
|
|
230
198
|
(callback) => verb(state.handle, relationId, chunk.rows, chunk.cells, callback),
|
|
231
|
-
|
|
232
|
-
|
|
199
|
+
(lease) => {
|
|
200
|
+
addon.runtimeStagedTake(lease)
|
|
201
|
+
}
|
|
233
202
|
).pipe(
|
|
234
203
|
Effect.catch((error) =>
|
|
235
204
|
Effect.sync(() => {
|
|
@@ -251,18 +220,18 @@ function ingest(
|
|
|
251
220
|
if (state.spent || Exit.isSuccess(exit)) {
|
|
252
221
|
return Effect.void
|
|
253
222
|
}
|
|
254
|
-
return spendAndDrain(state
|
|
223
|
+
return spendAndDrain(state)
|
|
255
224
|
})
|
|
256
225
|
})
|
|
257
226
|
}
|
|
258
227
|
|
|
259
228
|
function decodeChangeRecord<S extends AnySchema>(
|
|
260
229
|
relations: readonly SchemaRelation[],
|
|
261
|
-
record:
|
|
230
|
+
record: ChangeRecordOut
|
|
262
231
|
): ChangeRecord<S> {
|
|
263
232
|
const relation = relations[record.relation]
|
|
264
|
-
if (relation === undefined || isClosedMember(relation)
|
|
265
|
-
throw
|
|
233
|
+
if (relation === undefined || isClosedMember(relation)) {
|
|
234
|
+
throw internalError("ChangeSet.records: invalid native record descriptor")
|
|
266
235
|
}
|
|
267
236
|
// Relation id resolves through this schema's own ordered roster. The
|
|
268
237
|
// shared projector validates all field values before this union seam.
|
|
@@ -274,28 +243,25 @@ function decodeChangeRecord<S extends AnySchema>(
|
|
|
274
243
|
}
|
|
275
244
|
|
|
276
245
|
function changeRecords<S extends AnySchema>(
|
|
277
|
-
handle:
|
|
246
|
+
handle: ChangesRef,
|
|
278
247
|
relations: readonly SchemaRelation[]
|
|
279
248
|
): Stream.Stream<ChangeRecord<S>, DbError> {
|
|
280
249
|
return Stream.unwrap(
|
|
281
250
|
Effect.gen(function* () {
|
|
282
251
|
const cursor = yield* Effect.acquireRelease(
|
|
283
|
-
|
|
252
|
+
call(
|
|
284
253
|
"ChangeSet.records",
|
|
285
|
-
(callback) =>
|
|
286
|
-
|
|
287
|
-
(value) => value
|
|
254
|
+
(callback) => addon.runtimeChangesCursor(handle, callback),
|
|
255
|
+
addon.runtimeChangesCursorTake
|
|
288
256
|
),
|
|
289
|
-
(value) =>
|
|
290
|
-
releaseOwner("ChangeCursor.close", (callback) => dbNative.runtimeChangesCursorClose(value, callback)),
|
|
257
|
+
(value) => release("ChangeCursor.close", (callback) => addon.runtimeChangesCursorClose(value, callback)),
|
|
291
258
|
{ interruptible: true }
|
|
292
259
|
)
|
|
293
260
|
return Stream.paginate(undefined, () =>
|
|
294
|
-
|
|
261
|
+
call(
|
|
295
262
|
"ChangeSet.records",
|
|
296
|
-
(callback) =>
|
|
297
|
-
|
|
298
|
-
(page) => page
|
|
263
|
+
(callback) => addon.runtimeChangesCursorNext(cursor, callback),
|
|
264
|
+
addon.runtimeChangePageTake
|
|
299
265
|
).pipe(
|
|
300
266
|
Effect.map((page) =>
|
|
301
267
|
page === null
|
|
@@ -311,63 +277,59 @@ function changeRecords<S extends AnySchema>(
|
|
|
311
277
|
function acquireChanges<S extends AnySchema>(
|
|
312
278
|
theory: S,
|
|
313
279
|
schemaId: SchemaId,
|
|
314
|
-
acquire: Effect.Effect<
|
|
280
|
+
acquire: Effect.Effect<ChangesOut, DbError>
|
|
315
281
|
): Effect.Effect<ChangeSet<S>, DbError, Scope.Scope> {
|
|
316
|
-
return Effect.
|
|
317
|
-
|
|
318
|
-
(
|
|
319
|
-
Effect.suspend(() => {
|
|
320
|
-
const internal = changesInternals.get(changes)
|
|
321
|
-
if (internal === undefined) return Effect.void
|
|
322
|
-
return releaseOwner("ChangeSet.close", (callback) => dbNative.runtimeChangesClose(internal.handle, callback))
|
|
323
|
-
}),
|
|
324
|
-
{ interruptible: true }
|
|
282
|
+
return Effect.map(
|
|
283
|
+
scoped("ChangeSet.release", acquire, (wire) => (done) => addon.runtimeChangesClose(wire.changes, done)),
|
|
284
|
+
(wire): ChangeSet<S> => new ChangeSetLive(theory, wire, schemaId)
|
|
325
285
|
)
|
|
326
286
|
}
|
|
327
287
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
)
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
288
|
+
class ChangeSetLive<S extends AnySchema> implements ChangeSet<S> {
|
|
289
|
+
readonly #theory: S
|
|
290
|
+
readonly #handle: ChangesRef
|
|
291
|
+
readonly schemaId: SchemaId
|
|
292
|
+
readonly counts: ChangeCounts
|
|
293
|
+
readonly byteLength: bigint
|
|
294
|
+
|
|
295
|
+
constructor(theory: S, wire: ChangesOut, schemaId: SchemaId) {
|
|
296
|
+
this.#theory = theory
|
|
297
|
+
this.#handle = wire.changes
|
|
298
|
+
this.schemaId = schemaId
|
|
299
|
+
this.counts = Object.freeze({ ...wire.counts })
|
|
300
|
+
this.byteLength = wire.byteLength
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
records(): Stream.Stream<ChangeRecord<S>, DbError> {
|
|
304
|
+
return changeRecords<S>(this.#handle, Object.values(this.#theory.relations)).pipe(
|
|
305
|
+
Stream.withSpan("ChangeSet.records")
|
|
306
|
+
)
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
toBytes(): Effect.Effect<Uint8Array, DbError> {
|
|
310
|
+
const handle = this.#handle
|
|
311
|
+
return call("ChangeSet.toBytes", (done) => addon.runtimeChangesBytes(handle, done), addon.runtimeBytesTake).pipe(
|
|
312
|
+
Effect.withSpan("ChangeSet.toBytes")
|
|
313
|
+
)
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
compose(other: ChangeSet<S>): Effect.Effect<ChangeSet<S>, DbError, Scope.Scope> {
|
|
317
|
+
const left = this.#handle
|
|
318
|
+
const right = ChangeSetLive.handle(other, this.schemaId)
|
|
319
|
+
if (right === undefined) return Effect.fail(refusal("ChangeSet.compose", "InvalidArgument"))
|
|
320
|
+
return acquireChanges(
|
|
321
|
+
this.#theory,
|
|
322
|
+
this.schemaId,
|
|
323
|
+
call("ChangeSet.compose", (done) => addon.runtimeChangesCompose(left, right, done), addon.runtimeChangesTake)
|
|
324
|
+
).pipe(Effect.withSpan("ChangeSet.compose"))
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/** The native change set behind `value`, when `value` is one this SDK made for `schemaId`. */
|
|
328
|
+
static handle(value: object, schemaId: SchemaId): ChangesRef | undefined {
|
|
329
|
+
if (!(#handle in value)) return undefined
|
|
330
|
+
const changes = value as unknown as ChangeSetLive<AnySchema>
|
|
331
|
+
return changes.schemaId === schemaId ? changes.#handle : undefined
|
|
367
332
|
}
|
|
368
|
-
Object.freeze(value)
|
|
369
|
-
changesInternals.set(value, internal)
|
|
370
|
-
return value
|
|
371
333
|
}
|
|
372
334
|
|
|
373
335
|
function makeDraft<S extends AnySchema>(theory: S, state: DraftState, schemaId: SchemaId): ChangeDraft<S> {
|
|
@@ -387,25 +349,18 @@ function makeDraft<S extends AnySchema>(theory: S, state: DraftState, schemaId:
|
|
|
387
349
|
return yield* Effect.fail(refusal("ChangeDraft.finish", "SpentHandle"))
|
|
388
350
|
}
|
|
389
351
|
if (state.inFlight) {
|
|
390
|
-
yield* spendAndDrain(state
|
|
352
|
+
yield* spendAndDrain(state)
|
|
391
353
|
return yield* Effect.fail(refusal("ChangeDraft.finish", "SpentHandle"))
|
|
392
354
|
}
|
|
393
355
|
// Finish CONSUMES the draft, success or failure.
|
|
394
356
|
state.spent = true
|
|
395
|
-
return yield*
|
|
357
|
+
return yield* call(
|
|
396
358
|
"ChangeDraft.finish",
|
|
397
|
-
(callback) =>
|
|
398
|
-
|
|
399
|
-
(value) => value
|
|
359
|
+
(callback) => addon.runtimeDraftFinish(state.handle, callback),
|
|
360
|
+
addon.runtimeChangesTake
|
|
400
361
|
)
|
|
401
362
|
})
|
|
402
363
|
)
|
|
403
|
-
},
|
|
404
|
-
close() {
|
|
405
|
-
return Effect.suspend(() => {
|
|
406
|
-
state.spent = true
|
|
407
|
-
return drainClose("ChangeDraft.close", (callback) => dbNative.runtimeDraftClose(state.handle, callback))
|
|
408
|
-
})
|
|
409
364
|
}
|
|
410
365
|
}
|
|
411
366
|
return Object.freeze(draft)
|
|
@@ -414,73 +369,61 @@ function makeDraft<S extends AnySchema>(theory: S, state: DraftState, schemaId:
|
|
|
414
369
|
/**
|
|
415
370
|
* `ChangeSet.builder(schema)` — lazy scoped acquisition of a
|
|
416
371
|
* database-free draft. Requires the acquired
|
|
417
|
-
* `
|
|
372
|
+
* `Bumble`; the draft's native resources release with its scope, and
|
|
418
373
|
* the scope finalizer surfaces incomplete/failed teardown as a
|
|
419
374
|
* `CloseFailure` defect.
|
|
420
375
|
*/
|
|
421
376
|
const builder = Effect.fn("ChangeSet.builder")(function* <S extends AnySchema>(schema: S) {
|
|
422
|
-
const handle = yield* runtimeHandle
|
|
423
|
-
const
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
handle: draftHandle,
|
|
435
|
-
theory: compiled.schema,
|
|
377
|
+
const handle = yield* runtimeHandle
|
|
378
|
+
const theory = yield* Effect.try({
|
|
379
|
+
try: () => schemaDescriptor(schema),
|
|
380
|
+
catch: (cause) => argumentError("ChangeSet.builder", cause)
|
|
381
|
+
})
|
|
382
|
+
const compiled = compiledOf(theory)
|
|
383
|
+
const state = yield* scoped(
|
|
384
|
+
"ChangeDraft.release",
|
|
385
|
+
Effect.try({
|
|
386
|
+
try: (): DraftState => ({
|
|
387
|
+
handle: addon.runtimeDraftOpen(handle, compiled.handle),
|
|
388
|
+
theory,
|
|
436
389
|
spent: false,
|
|
437
390
|
inFlight: false
|
|
438
|
-
}
|
|
439
|
-
const draft = makeDraft(compiled.schema, state, compiled.schemaId)
|
|
440
|
-
draftStates.set(draft, state)
|
|
441
|
-
return draft
|
|
442
|
-
}),
|
|
443
|
-
(draft) =>
|
|
444
|
-
Effect.suspend(() => {
|
|
445
|
-
const state = draftStates.get(draft)
|
|
446
|
-
if (state === undefined) {
|
|
447
|
-
return Effect.void
|
|
448
|
-
}
|
|
449
|
-
// Idempotent: repeated close joins the same native
|
|
450
|
-
// transition; the finalizer runs it unconditionally so an
|
|
451
|
-
// abandoned draft is always drained.
|
|
452
|
-
state.spent = true
|
|
453
|
-
return releaseOwner("ChangeDraft.close", (callback) => dbNative.runtimeDraftClose(state.handle, callback))
|
|
454
391
|
}),
|
|
455
|
-
|
|
392
|
+
catch: (cause) => dbError("ChangeSet.builder", cause)
|
|
393
|
+
}),
|
|
394
|
+
(owned) => (done) => {
|
|
395
|
+
owned.spent = true
|
|
396
|
+
addon.runtimeDraftClose(owned.handle, done)
|
|
397
|
+
}
|
|
456
398
|
)
|
|
399
|
+
return makeDraft(theory as S, state, compiled.schemaId)
|
|
457
400
|
})
|
|
458
401
|
|
|
459
|
-
// The draft value → state registry lets the scope finalizer reach the
|
|
460
|
-
// native handle without exposing it on the public capability.
|
|
461
|
-
const draftStates = new WeakMap<object, DraftState>()
|
|
462
|
-
|
|
463
402
|
/** Parse canonical native bytes, owning the input when the Effect starts. */
|
|
464
403
|
const fromBytes = Effect.fn("ChangeSet.fromBytes")(function* <S extends AnySchema>(schema: S, bytes: Uint8Array) {
|
|
465
404
|
const ownedBytes = yield* Effect.try({
|
|
466
405
|
try: () => bytesValue("ChangeSet.fromBytes", bytes),
|
|
467
406
|
catch: (cause) => argumentError("ChangeSet.fromBytes", cause)
|
|
468
407
|
})
|
|
469
|
-
const handle = yield* runtimeHandle
|
|
470
|
-
const
|
|
408
|
+
const handle = yield* runtimeHandle
|
|
409
|
+
const theory = yield* Effect.try({
|
|
410
|
+
try: () => schemaDescriptor(schema),
|
|
411
|
+
catch: (cause) => argumentError("ChangeSet.fromBytes", cause)
|
|
412
|
+
})
|
|
413
|
+
const compiled = compiledOf(theory)
|
|
471
414
|
return yield* acquireChanges(
|
|
472
|
-
|
|
415
|
+
theory as S,
|
|
473
416
|
compiled.schemaId,
|
|
474
|
-
|
|
417
|
+
call(
|
|
475
418
|
"ChangeSet.fromBytes",
|
|
476
|
-
(
|
|
477
|
-
|
|
478
|
-
(wire) => wire
|
|
419
|
+
(done) => addon.runtimeChangesParse(handle, compiled.handle, ownedBytes, done),
|
|
420
|
+
addon.runtimeChangesTake
|
|
479
421
|
)
|
|
480
422
|
)
|
|
481
423
|
})
|
|
482
424
|
|
|
483
425
|
const ChangeSet = Object.freeze({ builder, fromBytes })
|
|
484
426
|
|
|
485
|
-
export type { ChangeCounts
|
|
486
|
-
export {
|
|
427
|
+
export type { ChangeCounts } from "./native/binding.d.ts"
|
|
428
|
+
export type { ChangeDraft, ChangeRecord }
|
|
429
|
+
export { ChangeSet, ChangeSetLive }
|
package/src/closed.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AuthoringError } from "
|
|
1
|
+
import { AuthoringError } from "./errors.ts"
|
|
2
2
|
import {
|
|
3
3
|
type AnyField,
|
|
4
4
|
assertDeclarationOrderKey,
|
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
type Infer,
|
|
9
9
|
ownHandles,
|
|
10
10
|
signaturesAgree
|
|
11
|
-
} from "
|
|
12
|
-
import { descriptorCache } from "
|
|
11
|
+
} from "./fields.ts"
|
|
12
|
+
import { descriptorCache } from "./immutable.ts"
|
|
13
13
|
import {
|
|
14
14
|
type AnyRelation,
|
|
15
15
|
type FieldsShape,
|
|
@@ -17,8 +17,8 @@ import {
|
|
|
17
17
|
type RelationField,
|
|
18
18
|
relationDescriptor,
|
|
19
19
|
relationFields
|
|
20
|
-
} from "
|
|
21
|
-
import { fieldValue, recordValue } from "
|
|
20
|
+
} from "./relation.ts"
|
|
21
|
+
import { fieldValue, recordValue } from "./values.ts"
|
|
22
22
|
|
|
23
23
|
type PayloadField = AnyField
|
|
24
24
|
type PayloadColumns = FieldsShape & { readonly id?: never }
|
package/src/codec.ts
CHANGED
|
@@ -1,41 +1,26 @@
|
|
|
1
1
|
import { Effect, Schema as EffectSchema, Result } from "effect"
|
|
2
|
-
import { membersAgree } from "
|
|
3
|
-
import { schemaTables } from "
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { type AnyRelation, type Fact, relationDescriptor, relationFields } from "
|
|
9
|
-
import type { CellValue } from "
|
|
10
|
-
import { factOfCells, flatRowsOf } from "
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
import {
|
|
15
|
-
import
|
|
16
|
-
import {
|
|
17
|
-
import { fieldValue, recordValue } from "#values.ts"
|
|
2
|
+
import { membersAgree } from "./closed.ts"
|
|
3
|
+
import { compiledOf, schemaTables } from "./compile.ts"
|
|
4
|
+
import { AuthoringError, argumentError, DbError } from "./errors.ts"
|
|
5
|
+
import { type AnyField, fieldDescriptor, type Infer } from "./fields.ts"
|
|
6
|
+
import { addon } from "./native/addon.ts"
|
|
7
|
+
import { call } from "./native/op.ts"
|
|
8
|
+
import { type AnyRelation, type Fact, relationDescriptor, relationFields } from "./relation.ts"
|
|
9
|
+
import type { CellValue } from "./rows.ts"
|
|
10
|
+
import { factOfCells, flatRowsOf } from "./rows.ts"
|
|
11
|
+
import { runtimeHandle } from "./runtime.ts"
|
|
12
|
+
import type { AnySchema } from "./schema.ts"
|
|
13
|
+
import { schemaDescriptor } from "./schema.ts"
|
|
14
|
+
import type { Rel } from "./shape.ts"
|
|
15
|
+
import { f64BitsHex } from "./spec.ts"
|
|
16
|
+
import { fieldValue, recordValue } from "./values.ts"
|
|
18
17
|
|
|
19
18
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* 1. The CANONICAL native row codec: `encodeRows`/`decodeRows` run the
|
|
26
|
-
* same native implementation the engine, log and migrations
|
|
27
|
-
* share (owned bytes in, owned typed rows out; untrusted input cannot
|
|
28
|
-
* inject native capabilities). Effect-only, `NativeRuntime` required.
|
|
29
|
-
* 2. The schema-tagged JSON VALUE form for HTTP/export boundaries
|
|
30
|
-
* (chapter 30): every `f64` — finite included — is
|
|
31
|
-
* `{"$f64":"<16 lowercase hex digits>"}` of canonical binary64 bits;
|
|
32
|
-
* integers are canonical decimal strings; `Uuid` is canonical UUID;
|
|
33
|
-
* bytes use ONE strict lowercase-hex encoding; intervals are
|
|
34
|
-
* `{start,end}` in their element encoding; closed references are handle
|
|
35
|
-
* names. `JSON.stringify` of raw numbers is NOT the database value
|
|
36
|
-
* wire codec — it loses infinities/NaN and cannot encode BigInt.
|
|
37
|
-
* Decoders reject malformed widths, unknown tags and noncanonical
|
|
38
|
-
* representations. These are pure bounded per-row functions.
|
|
19
|
+
* Row codecs derived from the relation descriptors: the canonical native row codec
|
|
20
|
+
* (`encodeRows`/`decodeRows`, the engine's own bytes) and the schema-tagged JSON value form for
|
|
21
|
+
* HTTP/export boundaries, where an `f64` is `{"$f64":"<16 hex>"}` of its canonical bits (raw JSON
|
|
22
|
+
* numbers lose infinities and NaN), integers are decimal strings, bytes are lowercase hex and
|
|
23
|
+
* closed references are handle names. Decoders reject anything noncanonical.
|
|
39
24
|
*/
|
|
40
25
|
|
|
41
26
|
/** The typed row shape: a schema plus one of its relations. */
|
|
@@ -58,7 +43,7 @@ function checkedRowShape<R extends AnyRelation>(operation: string, input: RowSha
|
|
|
58
43
|
if (relationId === undefined || !membersAgree(schema.relations[relation.name], relation)) {
|
|
59
44
|
throw new AuthoringError({ message: `${operation}: relation is not declared in the schema` })
|
|
60
45
|
}
|
|
61
|
-
return { relation, relationId,
|
|
46
|
+
return { relation, relationId, schema: compiledOf(schema).handle }
|
|
62
47
|
}
|
|
63
48
|
|
|
64
49
|
function invalid(operation: string): DbError {
|
|
@@ -271,7 +256,7 @@ function rowSchema<R extends AnyRelation>(relation: R) {
|
|
|
271
256
|
}
|
|
272
257
|
|
|
273
258
|
/**
|
|
274
|
-
* The canonical native row codec
|
|
259
|
+
* The canonical native row codec: owned bytes
|
|
275
260
|
* out, owned typed rows back in — the same implementation log sealing and
|
|
276
261
|
* migrations use. Binding parameters is ingestion: input must stay stable
|
|
277
262
|
* through execution, and no native work starts before the checked owned
|
|
@@ -281,8 +266,8 @@ const encodeRows = Effect.fn("encodeRows")(function* <R extends AnyRelation>(
|
|
|
281
266
|
shape: RowShape<R>,
|
|
282
267
|
rows: Iterable<Fact<R>>
|
|
283
268
|
) {
|
|
284
|
-
const runtime = yield* runtimeHandle
|
|
285
|
-
const { relation, relationId,
|
|
269
|
+
const runtime = yield* runtimeHandle
|
|
270
|
+
const { relation, relationId, schema } = yield* Effect.try({
|
|
286
271
|
try: () => checkedRowShape("encodeRows", shape),
|
|
287
272
|
catch: (cause) => argumentError("encodeRows", cause)
|
|
288
273
|
})
|
|
@@ -290,28 +275,29 @@ const encodeRows = Effect.fn("encodeRows")(function* <R extends AnyRelation>(
|
|
|
290
275
|
try: () => flatRowsOf(relation, rows as Iterable<object>),
|
|
291
276
|
catch: (cause) => argumentError("encodeRows", cause)
|
|
292
277
|
})
|
|
293
|
-
return yield*
|
|
278
|
+
return yield* call(
|
|
294
279
|
"encodeRows",
|
|
295
|
-
(callback) =>
|
|
296
|
-
|
|
297
|
-
(bytes) => bytes
|
|
280
|
+
(callback) => addon.runtimeEncodeRows(runtime, schema, relationId, flat.rows, flat.cells, callback),
|
|
281
|
+
addon.runtimeBytesTake
|
|
298
282
|
)
|
|
299
283
|
})
|
|
300
284
|
|
|
301
285
|
const decodeRows = Effect.fn("decodeRows")(function* <R extends AnyRelation>(shape: RowShape<R>, input: Uint8Array) {
|
|
302
|
-
const runtime = yield* runtimeHandle
|
|
303
|
-
const { relation, relationId,
|
|
286
|
+
const runtime = yield* runtimeHandle
|
|
287
|
+
const { relation, relationId, schema } = yield* Effect.try({
|
|
304
288
|
try: () => checkedRowShape("decodeRows", shape),
|
|
305
289
|
catch: (cause) => argumentError("decodeRows", cause)
|
|
306
290
|
})
|
|
307
291
|
if (!(input instanceof Uint8Array) || !(input.buffer instanceof ArrayBuffer)) {
|
|
308
292
|
return yield* Effect.fail(invalid("decodeRows"))
|
|
309
293
|
}
|
|
310
|
-
return yield*
|
|
294
|
+
return yield* call(
|
|
311
295
|
"decodeRows",
|
|
312
|
-
(callback) =>
|
|
313
|
-
|
|
314
|
-
|
|
296
|
+
(callback) => addon.runtimeDecodeRows(runtime, schema, relationId, input, callback),
|
|
297
|
+
(lease) =>
|
|
298
|
+
((rows) => Object.freeze(rows.map((row) => factOfCells(relation, row as readonly CellValue[]))))(
|
|
299
|
+
addon.runtimeRowsTake(lease)
|
|
300
|
+
)
|
|
315
301
|
)
|
|
316
302
|
})
|
|
317
303
|
|