@bjornpagen/bumbledb 1.3.0 → 2.0.0-rc.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.
- package/COOKBOOK.md +224 -95
- package/README.md +114 -45
- 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 -41
- package/dist/changes.d.ts.map +1 -1
- package/dist/changes.js +86 -110
- 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 +20 -27
- package/dist/codec.d.ts.map +1 -1
- package/dist/codec.js +48 -22
- 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 -58
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +27 -29
- 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 +7 -7
- package/dist/query/compute.d.ts.map +1 -1
- package/dist/query/compute.js +7 -16
- 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 +31 -17
- package/dist/query/lower.d.ts.map +1 -1
- package/dist/query/lower.js +260 -368
- 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 +13 -8
- 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 -43
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +41 -241
- package/dist/runtime.js.map +1 -1
- package/dist/scalar.d.ts +36 -106
- package/dist/scalar.d.ts.map +1 -1
- package/dist/scalar.js +36 -185
- 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 -197
- package/src/closed.ts +5 -5
- package/src/codec.ts +77 -51
- 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 +102 -109
- 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 +13 -22
- package/src/query/find.ts +8 -8
- package/src/query/lower.ts +323 -414
- package/src/query/run.ts +42 -21
- package/src/query/scope.ts +37 -38
- 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 -346
- package/src/scalar.ts +76 -336
- 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 -196
- 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/migration.d.ts +0 -31
- package/dist/migration.d.ts.map +0 -1
- package/dist/migration.js +0 -47
- package/dist/migration.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 -18
- package/dist/runtime-codes.js.map +0 -1
- package/dist/runtime-errors.d.ts +0 -118
- package/dist/runtime-errors.d.ts.map +0 -1
- package/dist/runtime-errors.js +0 -98
- package/dist/runtime-errors.js.map +0 -1
- package/dist/runtime-native.d.ts +0 -141
- 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/pack-provenance.json +0 -7
- package/src/close.ts +0 -53
- package/src/db-native.ts +0 -243
- package/src/internal/log.ts +0 -48
- package/src/migration.ts +0 -61
- package/src/native.ts +0 -736
- package/src/query/description.ts +0 -424
- package/src/query/parse-ir.ts +0 -291
- package/src/runtime-codes.ts +0 -17
- package/src/runtime-errors.ts +0 -109
- package/src/runtime-native.ts +0 -189
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 {
|
|
@@ -141,7 +126,8 @@ function decodeTaggedF64(value: unknown): number | undefined {
|
|
|
141
126
|
}
|
|
142
127
|
|
|
143
128
|
/** Decode representation, then judge the value through the shared interpreter. */
|
|
144
|
-
function decodeBoundaryValue(context: string, field:
|
|
129
|
+
function decodeBoundaryValue<F extends AnyField>(context: string, field: F, input: unknown): Infer<F>
|
|
130
|
+
function decodeBoundaryValue(context: string, field: AnyField, input: unknown): Infer<AnyField> {
|
|
145
131
|
if ("closed" in field) return fieldValue(context, field, input)
|
|
146
132
|
let decoded: unknown = input
|
|
147
133
|
switch (field.kind) {
|
|
@@ -167,6 +153,35 @@ function decodeBoundaryValue(context: string, field: AnyField, input: unknown):
|
|
|
167
153
|
return fieldValue(context, field, decoded)
|
|
168
154
|
}
|
|
169
155
|
|
|
156
|
+
/** The host-value schema, using the same interpreter as facts and row codecs. */
|
|
157
|
+
function fieldSchema<F extends AnyField>(field: F) {
|
|
158
|
+
const descriptor = fieldDescriptor("fieldSchema", field)
|
|
159
|
+
return EffectSchema.declare((value: unknown): value is Infer<F> => {
|
|
160
|
+
try {
|
|
161
|
+
fieldValue("fieldSchema", descriptor, value)
|
|
162
|
+
return true
|
|
163
|
+
} catch {
|
|
164
|
+
return false
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** Encode one field's host value in the canonical JSON-boundary form. */
|
|
170
|
+
function encodeBoundaryField<F extends AnyField>(field: F, value: Infer<F>): Result.Result<unknown, DbError> {
|
|
171
|
+
return Result.try({
|
|
172
|
+
try: () => encodeBoundaryValue("encodeBoundaryField", fieldDescriptor("encodeBoundaryField", field), value),
|
|
173
|
+
catch: (cause) => argumentError("encodeBoundaryField", cause)
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** Strict JSON-boundary decoding, returning the field's canonical host value. */
|
|
178
|
+
function decodeBoundaryField<F extends AnyField>(field: F, input: unknown): Result.Result<Infer<F>, DbError> {
|
|
179
|
+
return Result.try({
|
|
180
|
+
try: () => decodeBoundaryValue("decodeBoundaryField", fieldDescriptor("decodeBoundaryField", field), input),
|
|
181
|
+
catch: (cause) => argumentError("decodeBoundaryField", cause)
|
|
182
|
+
})
|
|
183
|
+
}
|
|
184
|
+
|
|
170
185
|
/** Pure schema-tagged JSON encoding of complete rows. */
|
|
171
186
|
function encodeBoundaryRows<R extends AnyRelation>(
|
|
172
187
|
relation: R,
|
|
@@ -241,7 +256,7 @@ function rowSchema<R extends AnyRelation>(relation: R) {
|
|
|
241
256
|
}
|
|
242
257
|
|
|
243
258
|
/**
|
|
244
|
-
* The canonical native row codec
|
|
259
|
+
* The canonical native row codec: owned bytes
|
|
245
260
|
* out, owned typed rows back in — the same implementation log sealing and
|
|
246
261
|
* migrations use. Binding parameters is ingestion: input must stay stable
|
|
247
262
|
* through execution, and no native work starts before the checked owned
|
|
@@ -251,8 +266,8 @@ const encodeRows = Effect.fn("encodeRows")(function* <R extends AnyRelation>(
|
|
|
251
266
|
shape: RowShape<R>,
|
|
252
267
|
rows: Iterable<Fact<R>>
|
|
253
268
|
) {
|
|
254
|
-
const runtime = yield* runtimeHandle
|
|
255
|
-
const { relation, relationId,
|
|
269
|
+
const runtime = yield* runtimeHandle
|
|
270
|
+
const { relation, relationId, schema } = yield* Effect.try({
|
|
256
271
|
try: () => checkedRowShape("encodeRows", shape),
|
|
257
272
|
catch: (cause) => argumentError("encodeRows", cause)
|
|
258
273
|
})
|
|
@@ -260,30 +275,41 @@ const encodeRows = Effect.fn("encodeRows")(function* <R extends AnyRelation>(
|
|
|
260
275
|
try: () => flatRowsOf(relation, rows as Iterable<object>),
|
|
261
276
|
catch: (cause) => argumentError("encodeRows", cause)
|
|
262
277
|
})
|
|
263
|
-
return yield*
|
|
278
|
+
return yield* call(
|
|
264
279
|
"encodeRows",
|
|
265
|
-
(callback) =>
|
|
266
|
-
|
|
267
|
-
(bytes) => bytes
|
|
280
|
+
(callback) => addon.runtimeEncodeRows(runtime, schema, relationId, flat.rows, flat.cells, callback),
|
|
281
|
+
addon.runtimeBytesTake
|
|
268
282
|
)
|
|
269
283
|
})
|
|
270
284
|
|
|
271
285
|
const decodeRows = Effect.fn("decodeRows")(function* <R extends AnyRelation>(shape: RowShape<R>, input: Uint8Array) {
|
|
272
|
-
const runtime = yield* runtimeHandle
|
|
273
|
-
const { relation, relationId,
|
|
286
|
+
const runtime = yield* runtimeHandle
|
|
287
|
+
const { relation, relationId, schema } = yield* Effect.try({
|
|
274
288
|
try: () => checkedRowShape("decodeRows", shape),
|
|
275
289
|
catch: (cause) => argumentError("decodeRows", cause)
|
|
276
290
|
})
|
|
277
291
|
if (!(input instanceof Uint8Array) || !(input.buffer instanceof ArrayBuffer)) {
|
|
278
292
|
return yield* Effect.fail(invalid("decodeRows"))
|
|
279
293
|
}
|
|
280
|
-
return yield*
|
|
294
|
+
return yield* call(
|
|
281
295
|
"decodeRows",
|
|
282
|
-
(callback) =>
|
|
283
|
-
|
|
284
|
-
|
|
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
|
+
)
|
|
285
301
|
)
|
|
286
302
|
})
|
|
287
303
|
|
|
288
304
|
export type { RowShape }
|
|
289
|
-
export {
|
|
305
|
+
export {
|
|
306
|
+
decodeBoundaryField,
|
|
307
|
+
decodeBoundaryRows,
|
|
308
|
+
decodeRows,
|
|
309
|
+
encodeBoundaryField,
|
|
310
|
+
encodeBoundaryRows,
|
|
311
|
+
encodeRows,
|
|
312
|
+
fieldSchema,
|
|
313
|
+
rowSchema,
|
|
314
|
+
rowShape
|
|
315
|
+
}
|
package/src/compile.ts
CHANGED
|
@@ -1,88 +1,67 @@
|
|
|
1
|
-
import { Effect } from "effect"
|
|
2
|
-
import { isClosedMember, membersAgree } from "#closed.ts"
|
|
3
|
-
import { dbNative } from "#db-native.ts"
|
|
4
|
-
import { SdkInvariantError } from "#errors.ts"
|
|
5
|
-
import { isImmutable, snapshotData } from "#immutable.ts"
|
|
6
|
-
import type { SchemaClasses } from "#law.ts"
|
|
7
|
-
import { lower } from "#lower.ts"
|
|
8
|
-
import type { SealedDescriptor } from "#native.ts"
|
|
9
|
-
import type { AnyRelation } from "#relation.ts"
|
|
10
|
-
import { nativeOperationWith, runtimeHandle } from "#runtime.ts"
|
|
11
|
-
import { argumentError } from "#runtime-errors.ts"
|
|
12
|
-
import type { AnySchema, Schema as SchemaDeclaration, SchemaRelations } from "#schema.ts"
|
|
13
|
-
import { schemaDescriptor } from "#schema.ts"
|
|
14
|
-
import { type KeyStatement, type Statement, statementDescriptor } from "#statements.ts"
|
|
15
|
-
|
|
16
1
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
2
|
+
* A schema is compiled by the engine when it is defined. The compiled handle, descriptor and
|
|
3
|
+
* fingerprint ride with the schema value; the engine's diagnostics come back as authoring errors
|
|
4
|
+
* that name the schema's own relations and statements.
|
|
20
5
|
*/
|
|
21
|
-
|
|
6
|
+
import { Schema as EffectSchema } from "effect"
|
|
7
|
+
import { isClosedMember, membersAgree } from "./closed.ts"
|
|
8
|
+
import { AuthoringError, internalError } from "./errors.ts"
|
|
9
|
+
import { isImmutable } from "./immutable.ts"
|
|
10
|
+
import { lower } from "./lower.ts"
|
|
11
|
+
import type { SchemaRef } from "./native/addon.ts"
|
|
12
|
+
import { addon } from "./native/addon.ts"
|
|
13
|
+
import type { SchemaDescriptorOut, SchemaDiagnostic } from "./native/binding.d.ts"
|
|
14
|
+
import type { AnyRelation } from "./relation.ts"
|
|
15
|
+
import type { AnySchema } from "./schema.ts"
|
|
16
|
+
import { type KeyStatement, renderStatement, type Statement, statementDescriptor } from "./statements.ts"
|
|
22
17
|
|
|
23
|
-
/**
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
readonly
|
|
18
|
+
/** The engine's schema fingerprint: 64 lowercase hex digits, independent of any database. */
|
|
19
|
+
const SchemaId = EffectSchema.String.check(EffectSchema.isPattern(/^[0-9a-f]{64}$/)).pipe(
|
|
20
|
+
EffectSchema.brand("SchemaId")
|
|
21
|
+
)
|
|
22
|
+
type SchemaId = typeof SchemaId.Type
|
|
23
|
+
|
|
24
|
+
interface Compiled {
|
|
25
|
+
readonly handle: SchemaRef
|
|
26
|
+
readonly descriptor: SchemaDescriptorOut
|
|
32
27
|
readonly schemaId: SchemaId
|
|
33
|
-
readonly descriptor: SealedDescriptor
|
|
34
28
|
}
|
|
35
29
|
|
|
36
30
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* relations' auto-handle keys FIRST in relation-declaration order, then
|
|
40
|
-
* declared statements in declaration order with `mirrors` occupying two
|
|
41
|
-
* consecutive slots, source-first — the theory's `StatementId` law).
|
|
42
|
-
* Every declared statement retains its own native identity; no key is
|
|
43
|
-
* privileged by its position in the declaration.
|
|
31
|
+
* Declaration-order tables: relation ids, and each declared statement's first materialized
|
|
32
|
+
* statement id (closed relations' id keys come first; `mirrors` takes two consecutive ids).
|
|
44
33
|
*/
|
|
45
34
|
interface SchemaTables {
|
|
46
35
|
readonly relationIds: ReadonlyMap<string, number>
|
|
47
36
|
readonly statementIds: ReadonlyMap<Statement, number>
|
|
48
37
|
}
|
|
49
38
|
|
|
50
|
-
function declaredWidth(statement: Statement): number {
|
|
51
|
-
return statement.kind === "mirrors" ? 2 : 1
|
|
52
|
-
}
|
|
53
|
-
|
|
54
39
|
function tablesOf(theory: AnySchema): SchemaTables {
|
|
55
40
|
const relationIds = new Map<string, number>()
|
|
56
41
|
const statementIds = new Map<Statement, number>()
|
|
57
|
-
let
|
|
58
|
-
Object.entries(theory.relations).forEach(
|
|
42
|
+
let offset = 0
|
|
43
|
+
Object.entries(theory.relations).forEach(([name, member], ordinal) => {
|
|
59
44
|
relationIds.set(name, ordinal)
|
|
60
|
-
if (isClosedMember(member))
|
|
61
|
-
autoKeys += 1
|
|
62
|
-
}
|
|
45
|
+
if (isClosedMember(member)) offset += 1
|
|
63
46
|
})
|
|
64
|
-
let offset = autoKeys
|
|
65
47
|
for (const statement of theory.statements) {
|
|
66
48
|
statementIds.set(statement, offset)
|
|
67
|
-
offset +=
|
|
49
|
+
offset += statement.kind === "mirrors" ? 2 : 1
|
|
68
50
|
}
|
|
69
51
|
return Object.freeze({ relationIds, statementIds })
|
|
70
52
|
}
|
|
71
53
|
|
|
72
|
-
const
|
|
54
|
+
const tablesCache = new WeakMap<AnySchema, SchemaTables>()
|
|
73
55
|
|
|
74
|
-
/** Memoized pure tables (per schema value identity; no native work). */
|
|
75
56
|
function schemaTables(theory: AnySchema): SchemaTables {
|
|
76
|
-
const cached =
|
|
77
|
-
if (cached !== undefined)
|
|
78
|
-
return cached
|
|
79
|
-
}
|
|
57
|
+
const cached = tablesCache.get(theory)
|
|
58
|
+
if (cached !== undefined) return cached
|
|
80
59
|
const built = tablesOf(theory)
|
|
81
|
-
if (isImmutable(theory))
|
|
60
|
+
if (isImmutable(theory)) tablesCache.set(theory, built)
|
|
82
61
|
return built
|
|
83
62
|
}
|
|
84
63
|
|
|
85
|
-
/**
|
|
64
|
+
/** Resolves a key declaration to the schema's own statement and its statement id. */
|
|
86
65
|
function declaredKey<R extends AnyRelation>(
|
|
87
66
|
theory: AnySchema,
|
|
88
67
|
input: KeyStatement<R>
|
|
@@ -104,68 +83,67 @@ function declaredKey(
|
|
|
104
83
|
return undefined
|
|
105
84
|
}
|
|
106
85
|
|
|
107
|
-
function
|
|
108
|
-
if (
|
|
109
|
-
|
|
86
|
+
function explain(theory: AnySchema, diagnostic: SchemaDiagnostic): string {
|
|
87
|
+
if (diagnostic._tag === "Schema") {
|
|
88
|
+
const cited = [diagnostic.statement, diagnostic.conflict].flatMap((cite) =>
|
|
89
|
+
cite === undefined ? [] : [cite.spelling]
|
|
90
|
+
)
|
|
91
|
+
return cited.length === 0 ? diagnostic.message : `${diagnostic.message} — ${cited.join("; ")}`
|
|
110
92
|
}
|
|
111
|
-
|
|
93
|
+
const relations = Object.keys(theory.relations)
|
|
94
|
+
return diagnostic.issues
|
|
95
|
+
.map((issue) => {
|
|
96
|
+
const at = [
|
|
97
|
+
issue.relation === undefined ? undefined : `relation ${relations[issue.relation] ?? issue.relation}`,
|
|
98
|
+
issue.row === undefined ? undefined : `row ${issue.row}`,
|
|
99
|
+
issue.statement === undefined
|
|
100
|
+
? undefined
|
|
101
|
+
: (() => {
|
|
102
|
+
const statement = theory.statements[issue.statement]
|
|
103
|
+
return statement === undefined ? `statement ${issue.statement}` : renderStatement(statement)
|
|
104
|
+
})()
|
|
105
|
+
].filter((part) => part !== undefined)
|
|
106
|
+
return at.length === 0 ? issue.message : `${issue.message} — ${at.join(", ")}`
|
|
107
|
+
})
|
|
108
|
+
.join("; ")
|
|
112
109
|
}
|
|
113
110
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
try: () => schemaDescriptor(schema),
|
|
125
|
-
catch: (cause) => argumentError("Schema.compile", cause)
|
|
126
|
-
})
|
|
127
|
-
const spec = yield* Effect.try({ try: () => lower(owned), catch: (cause) => argumentError("Schema.compile", cause) })
|
|
128
|
-
const handle = yield* runtimeHandle()
|
|
129
|
-
const descriptor = yield* nativeOperationWith(
|
|
130
|
-
"Schema.compile",
|
|
131
|
-
(callback) => dbNative.runtimeSchemaCompile(handle, spec, callback),
|
|
132
|
-
dbNative.runtimeSchemaTake,
|
|
133
|
-
(value) => value
|
|
134
|
-
)
|
|
135
|
-
const ownedDescriptor = snapshotData(descriptor)
|
|
136
|
-
const compiled: CompiledSchema<S> = Object.freeze({
|
|
137
|
-
get schema() {
|
|
138
|
-
return snapshotData(owned)
|
|
139
|
-
},
|
|
140
|
-
schemaId: admitSchemaId(descriptor.fingerprint),
|
|
141
|
-
get descriptor() {
|
|
142
|
-
return snapshotData(ownedDescriptor)
|
|
111
|
+
const decodeSchemaId = EffectSchema.decodeUnknownOption(SchemaId)
|
|
112
|
+
|
|
113
|
+
/** Compiles `theory` with the engine; an engine refusal throws `AuthoringError`. */
|
|
114
|
+
function compileSchema(theory: AnySchema): Compiled {
|
|
115
|
+
const compiled = addon.compileSchema(JSON.stringify(lower(theory)))
|
|
116
|
+
switch (compiled._tag) {
|
|
117
|
+
case "Compiled": {
|
|
118
|
+
const schemaId = decodeSchemaId(compiled.descriptor.fingerprint)
|
|
119
|
+
if (schemaId._tag === "None") throw internalError("compileSchema: the engine returned no fingerprint")
|
|
120
|
+
return Object.freeze({ handle: compiled.schema, descriptor: compiled.descriptor, schemaId: schemaId.value })
|
|
143
121
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
122
|
+
case "Invalid":
|
|
123
|
+
throw new AuthoringError({ message: `schema ${theory.name}: ${explain(theory, compiled.diagnostic)}` })
|
|
124
|
+
case "Malformed":
|
|
125
|
+
throw internalError(`compileSchema: ${compiled.path}: ${compiled.message}`)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
147
128
|
|
|
148
|
-
|
|
149
|
-
* The declaration-tier `Schema<Rels, Classes>` TYPE (from `#schema.ts`),
|
|
150
|
-
* re-aliased LOCALLY so the one name carries both meanings through a
|
|
151
|
-
* SINGLE export specifier below — a local `type` + `const` merge is the
|
|
152
|
-
* plain TypeScript type/value merge, with no same-name pair of export
|
|
153
|
-
* declarations for any checker to refuse (the earlier
|
|
154
|
-
* `export type { Schema } from "#schema.ts"` beside `export { Schema }`
|
|
155
|
-
* spelled the type meaning twice at the barrel; this spelling cannot).
|
|
156
|
-
*/
|
|
157
|
-
type Schema<Rels extends SchemaRelations, Classes extends SchemaClasses = SchemaClasses> = SchemaDeclaration<
|
|
158
|
-
Rels,
|
|
159
|
-
Classes
|
|
160
|
-
>
|
|
129
|
+
const compiledSchemas = new WeakMap<AnySchema, Compiled>()
|
|
161
130
|
|
|
162
|
-
/**
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
*/
|
|
168
|
-
|
|
131
|
+
/** Records the compiled form of a schema value `schema()` produced. */
|
|
132
|
+
function registerCompiled(theory: AnySchema): void {
|
|
133
|
+
compiledSchemas.set(theory, compileSchema(theory))
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Whether `value` is a schema value `schema()` produced (and so has a compiled form). */
|
|
137
|
+
function isCompiledSchema(value: unknown): value is AnySchema {
|
|
138
|
+
return typeof value === "object" && value !== null && compiledSchemas.has(value as AnySchema)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** The engine's compiled form of `theory`; every schema value `schema()` produced has one. */
|
|
142
|
+
function compiledOf(theory: AnySchema): Compiled {
|
|
143
|
+
const compiled = compiledSchemas.get(theory)
|
|
144
|
+
if (compiled === undefined) throw internalError("compiledOf: the schema was not produced by schema()")
|
|
145
|
+
return compiled
|
|
146
|
+
}
|
|
169
147
|
|
|
170
|
-
export type {
|
|
171
|
-
export { declaredKey,
|
|
148
|
+
export type { Compiled, SchemaTables }
|
|
149
|
+
export { compiledOf, declaredKey, isCompiledSchema, registerCompiled, SchemaId, schemaTables }
|