@bjornpagen/bumbledb 1.2.1 → 1.3.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 +240 -9
- package/README.md +9 -6
- package/dist/alternatives.d.ts +25 -0
- package/dist/alternatives.d.ts.map +1 -0
- package/dist/alternatives.js +59 -0
- package/dist/alternatives.js.map +1 -0
- package/dist/changes.d.ts +0 -1
- package/dist/changes.d.ts.map +1 -1
- package/dist/changes.js +2 -8
- package/dist/changes.js.map +1 -1
- package/dist/codec.d.ts +8 -1
- package/dist/codec.d.ts.map +1 -1
- package/dist/codec.js +29 -2
- package/dist/codec.js.map +1 -1
- package/dist/db-native.d.ts +2 -9
- package/dist/db-native.d.ts.map +1 -1
- package/dist/db-native.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/internal/log.d.ts +4 -4
- package/dist/internal/log.d.ts.map +1 -1
- package/dist/internal/log.js +2 -2
- package/dist/internal/log.js.map +1 -1
- package/dist/native.d.ts +23 -9
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js.map +1 -1
- package/dist/query/atom.d.ts +2 -1
- package/dist/query/atom.d.ts.map +1 -1
- package/dist/query/atom.js.map +1 -1
- package/dist/query/compute.d.ts +19 -4
- package/dist/query/compute.d.ts.map +1 -1
- package/dist/query/compute.js +17 -13
- package/dist/query/compute.js.map +1 -1
- package/dist/query/description.d.ts +10 -2
- package/dist/query/description.d.ts.map +1 -1
- package/dist/query/description.js +14 -5
- package/dist/query/description.js.map +1 -1
- package/dist/query/find.d.ts +13 -6
- package/dist/query/find.d.ts.map +1 -1
- package/dist/query/find.js +1 -1
- package/dist/query/find.js.map +1 -1
- package/dist/query/lower.d.ts +14 -2
- package/dist/query/lower.d.ts.map +1 -1
- package/dist/query/lower.js +64 -50
- package/dist/query/lower.js.map +1 -1
- package/dist/query/parse-ir.d.ts.map +1 -1
- package/dist/query/parse-ir.js +26 -3
- package/dist/query/parse-ir.js.map +1 -1
- package/dist/query/scope.d.ts.map +1 -1
- package/dist/query/scope.js +6 -1
- package/dist/query/scope.js.map +1 -1
- package/dist/query/segments.d.ts +20 -0
- package/dist/query/segments.d.ts.map +1 -0
- package/dist/query/segments.js +35 -0
- package/dist/query/segments.js.map +1 -0
- package/dist/runtime-codes.d.ts +1 -1
- package/dist/runtime-codes.d.ts.map +1 -1
- package/dist/runtime-codes.js +1 -0
- package/dist/runtime-codes.js.map +1 -1
- package/dist/runtime-errors.d.ts +23 -3
- package/dist/runtime-errors.d.ts.map +1 -1
- package/dist/runtime-errors.js +16 -3
- package/dist/runtime-errors.js.map +1 -1
- package/dist/runtime-native.d.ts +3 -8
- package/dist/runtime-native.d.ts.map +1 -1
- package/dist/runtime-native.js.map +1 -1
- package/dist/runtime.d.ts +0 -23
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +0 -36
- package/dist/runtime.js.map +1 -1
- package/dist/scalar.d.ts +46 -94
- package/dist/scalar.d.ts.map +1 -1
- package/dist/scalar.js +69 -156
- package/dist/scalar.js.map +1 -1
- package/dist/schema-file.d.ts +7 -0
- package/dist/schema-file.d.ts.map +1 -0
- package/dist/schema-file.js +24 -0
- package/dist/schema-file.js.map +1 -0
- package/pack-provenance.json +4 -4
- package/package.json +4 -4
- package/src/alternatives.ts +95 -0
- package/src/changes.ts +2 -8
- package/src/codec.ts +43 -3
- package/src/db-native.ts +2 -10
- package/src/index.ts +23 -6
- package/src/internal/log.ts +2 -4
- package/src/native.ts +21 -7
- package/src/query/atom.ts +2 -0
- package/src/query/compute.ts +46 -16
- package/src/query/description.ts +38 -8
- package/src/query/find.ts +37 -26
- package/src/query/lower.ts +89 -52
- package/src/query/parse-ir.ts +27 -3
- package/src/query/scope.ts +8 -1
- package/src/query/segments.ts +61 -0
- package/src/runtime-codes.ts +1 -0
- package/src/runtime-errors.ts +16 -3
- package/src/runtime-native.ts +1 -9
- package/src/runtime.ts +1 -70
- package/src/scalar.ts +138 -285
- package/src/schema-file.ts +38 -0
- 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/src/migration.ts +0 -61
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-file.d.ts","sourceRoot":"","sources":["../src/schema-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAG/B,OAAO,EAAE,OAAO,EAAW,MAAM,oBAAoB,CAAA;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAS1C,QAAA,MAAM,sBAAsB,2FAQ1B,CAAA;AAEF,QAAA,MAAM,sBAAsB,2FAY1B,CAAA;AAEF,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { dbNative } from "#db-native.ts";
|
|
3
|
+
import { nativeOperationWith, runtimeHandle } from "#runtime.ts";
|
|
4
|
+
import { DbError, dbError } from "#runtime-errors.ts";
|
|
5
|
+
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
6
|
+
function text(operation, bytes) {
|
|
7
|
+
if (bytes === null)
|
|
8
|
+
throw dbError(operation, { _tag: "Internal" });
|
|
9
|
+
return decoder.decode(bytes);
|
|
10
|
+
}
|
|
11
|
+
const internalSchemaSnapshot = Effect.fn("internalSchemaSnapshot")(function* (spec) {
|
|
12
|
+
const runtime = yield* runtimeHandle();
|
|
13
|
+
return yield* nativeOperationWith("internalSchemaSnapshot", (callback) => dbNative.runtimeSchemaSnapshot(runtime, spec, callback), dbNative.runtimeBytesTake, (bytes) => text("internalSchemaSnapshot", bytes));
|
|
14
|
+
});
|
|
15
|
+
const internalSchemaBindings = Effect.fn("internalSchemaBindings")(function* (snapshot) {
|
|
16
|
+
if (typeof snapshot !== "string" || !snapshot.isWellFormed()) {
|
|
17
|
+
return yield* Effect.fail(new DbError({ operation: "internalSchemaBindings", reason: { _tag: "InvalidArgument" } }));
|
|
18
|
+
}
|
|
19
|
+
const runtime = yield* runtimeHandle();
|
|
20
|
+
const bytes = new TextEncoder().encode(snapshot);
|
|
21
|
+
return yield* nativeOperationWith("internalSchemaBindings", (callback) => dbNative.runtimeSchemaBindings(runtime, bytes, callback), dbNative.runtimeBytesTake, (bytes) => text("internalSchemaBindings", bytes));
|
|
22
|
+
});
|
|
23
|
+
export { internalSchemaBindings, internalSchemaSnapshot };
|
|
24
|
+
//# sourceMappingURL=schema-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-file.js","sourceRoot":"","sources":["../src/schema-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAGrD,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;AAEzD,SAAS,IAAI,CAAC,SAAiB,EAAE,KAAwB;IACxD,IAAI,KAAK,KAAK,IAAI;QAAE,MAAM,OAAO,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAA;IAClE,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC7B,CAAC;AAED,MAAM,sBAAsB,GAAG,MAAM,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAgB;IAC7F,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,aAAa,EAAE,CAAA;IACtC,OAAO,KAAK,CAAC,CAAC,mBAAmB,CAChC,wBAAwB,EACxB,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,EACrE,QAAQ,CAAC,gBAAgB,EACzB,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAChD,CAAA;AACF,CAAC,CAAC,CAAA;AAEF,MAAM,sBAAsB,GAAG,MAAM,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,QAAQ,CAAC,EAAE,QAAgB;IAC7F,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,CAAC;QAC9D,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,EAAE,SAAS,EAAE,wBAAwB,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,EAAE,CAAC,CAAC,CAAA;IACrH,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,aAAa,EAAE,CAAA;IACtC,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAChD,OAAO,KAAK,CAAC,CAAC,mBAAmB,CAChC,wBAAwB,EACxB,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,EACtE,QAAQ,CAAC,gBAAgB,EACzB,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAChD,CAAA;AACF,CAAC,CAAC,CAAA;AAEF,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,CAAA"}
|
package/pack-provenance.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"candidateSourceDigest": "
|
|
3
|
-
"specificationRevision": "
|
|
4
|
-
"stagedAt": "2026-09-
|
|
2
|
+
"candidateSourceDigest": "7109ef17978c17a195301260c8b4cd2736ce785646c46c61d61bf7850c4299da",
|
|
3
|
+
"specificationRevision": "91f64ebf5ccf285a072aeff41ca364d1e837259e4273f9be12a0a5959c38a45e",
|
|
4
|
+
"stagedAt": "2026-09-12T00:04:00.990Z",
|
|
5
5
|
"package": "@bjornpagen/bumbledb",
|
|
6
|
-
"version": "1.
|
|
6
|
+
"version": "1.3.1"
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bjornpagen/bumbledb",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Effect-native embedded relational database for TypeScript: typed schemas and queries, exact floats, commit-time constraints",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
},
|
|
58
58
|
"private": false,
|
|
59
59
|
"optionalDependencies": {
|
|
60
|
-
"@bjornpagen/bumbledb-darwin-arm64": "1.
|
|
61
|
-
"@bjornpagen/bumbledb-linux-arm64": "1.
|
|
62
|
-
"@bjornpagen/bumbledb-linux-x64": "1.
|
|
60
|
+
"@bjornpagen/bumbledb-darwin-arm64": "1.3.1",
|
|
61
|
+
"@bjornpagen/bumbledb-linux-arm64": "1.3.1",
|
|
62
|
+
"@bjornpagen/bumbledb-linux-x64": "1.3.1"
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { type AnyClosed, closedDescriptor, closedId, sealedFieldOf } from "#closed.ts"
|
|
2
|
+
import { AuthoringError } from "#errors.ts"
|
|
3
|
+
import type { Face, SameArity, SameShapes } from "#face.ts"
|
|
4
|
+
import { type ClosedIdField, signaturesAgree } from "#fields.ts"
|
|
5
|
+
import type { RelationFields } from "#relation.ts"
|
|
6
|
+
import {
|
|
7
|
+
type ContainmentStatement,
|
|
8
|
+
type KeyStatement,
|
|
9
|
+
type MirrorsStatement,
|
|
10
|
+
statementDescriptor
|
|
11
|
+
} from "#statements.ts"
|
|
12
|
+
import { recordValue } from "#values.ts"
|
|
13
|
+
|
|
14
|
+
type KeyFace<K extends KeyStatement> = Face<K["owner"], K["projection"]>
|
|
15
|
+
type ScalarKey<K extends KeyStatement> =
|
|
16
|
+
Extract<RelationFields<K["owner"]>[K["projection"][number]], { readonly kind: "interval" }> extends never
|
|
17
|
+
? unknown
|
|
18
|
+
: { readonly "alternative identity keys must be scalar": never }
|
|
19
|
+
type Discriminator<P extends KeyStatement, C extends AnyClosed> = {
|
|
20
|
+
[F in keyof RelationFields<P["owner"]>]: RelationFields<P["owner"]>[F] extends ClosedIdField<C["name"], C["handles"]>
|
|
21
|
+
? F
|
|
22
|
+
: never
|
|
23
|
+
}[keyof RelationFields<P["owner"]>] &
|
|
24
|
+
string
|
|
25
|
+
|
|
26
|
+
function scalarKey(input: KeyStatement): KeyStatement {
|
|
27
|
+
const checked = statementDescriptor(input)
|
|
28
|
+
if (checked.kind !== "key") throw new AuthoringError({ message: "alternatives: expected a key statement" })
|
|
29
|
+
for (const name of checked.projection) {
|
|
30
|
+
if (sealedFieldOf(checked.owner, name)?.kind === "interval")
|
|
31
|
+
throw new AuthoringError({
|
|
32
|
+
message: "alternatives: identity keys must be scalar; interval keys prove point coverage"
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
return checked
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Exhaustive closed alternatives, expanded into ordinary laws. Declare the
|
|
40
|
+
* supplied keys in the schema once; this helper emits only the discriminator
|
|
41
|
+
* containment followed by one mirrors statement per handle in roster order.
|
|
42
|
+
* No new statement kind or assembled payload representation is introduced.
|
|
43
|
+
*/
|
|
44
|
+
function alternatives<
|
|
45
|
+
P extends KeyStatement,
|
|
46
|
+
C extends AnyClosed,
|
|
47
|
+
const Arms extends Record<C["handles"][number], KeyStatement>
|
|
48
|
+
>(
|
|
49
|
+
parent: P & ScalarKey<P>,
|
|
50
|
+
discriminator: Discriminator<NoInfer<P>, NoInfer<C>>,
|
|
51
|
+
roster: C,
|
|
52
|
+
arms: Arms &
|
|
53
|
+
Record<Exclude<keyof Arms, C["handles"][number]>, never> & {
|
|
54
|
+
readonly [H in C["handles"][number]]: ScalarKey<Arms[H]> &
|
|
55
|
+
SameArity<KeyFace<P>, KeyFace<Arms[H]>> &
|
|
56
|
+
SameShapes<KeyFace<P>, KeyFace<Arms[H]>>
|
|
57
|
+
}
|
|
58
|
+
): readonly (ContainmentStatement | MirrorsStatement)[] {
|
|
59
|
+
const primary = scalarKey(parent)
|
|
60
|
+
const closed = closedDescriptor(roster)
|
|
61
|
+
const field = sealedFieldOf(primary.owner, discriminator)
|
|
62
|
+
if (field === undefined || !signaturesAgree(field, closedId(closed)))
|
|
63
|
+
throw new AuthoringError({ message: "alternatives: discriminator must reference the supplied closed roster" })
|
|
64
|
+
const payloads = recordValue("alternative arms", arms, closed.handles)
|
|
65
|
+
const statements: (ContainmentStatement | MirrorsStatement)[] = [
|
|
66
|
+
statementDescriptor({
|
|
67
|
+
kind: "containment",
|
|
68
|
+
source: { owner: primary.owner, projection: [discriminator], selection: [] },
|
|
69
|
+
target: { owner: closed, projection: ["id"], selection: [] }
|
|
70
|
+
})
|
|
71
|
+
]
|
|
72
|
+
const children = new Set<string>([primary.owner.name])
|
|
73
|
+
for (const handle of closed.handles) {
|
|
74
|
+
const child = scalarKey(payloads[handle] as KeyStatement)
|
|
75
|
+
if (children.has(child.owner.name))
|
|
76
|
+
throw new AuthoringError({
|
|
77
|
+
message: `alternatives: each arm needs its own payload relation (${child.owner.name})`
|
|
78
|
+
})
|
|
79
|
+
children.add(child.owner.name)
|
|
80
|
+
statements.push(
|
|
81
|
+
statementDescriptor({
|
|
82
|
+
kind: "mirrors",
|
|
83
|
+
source: {
|
|
84
|
+
owner: primary.owner,
|
|
85
|
+
projection: primary.projection,
|
|
86
|
+
selection: [{ field: discriminator, set: { kind: "one", literal: { kind: "handle", handle } } }]
|
|
87
|
+
},
|
|
88
|
+
target: { owner: child.owner, projection: child.projection, selection: [] }
|
|
89
|
+
})
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
return Object.freeze(statements)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export { alternatives }
|
package/src/changes.ts
CHANGED
|
@@ -93,7 +93,6 @@ interface DraftState {
|
|
|
93
93
|
interface ChangesInternal {
|
|
94
94
|
readonly handle: ChangesHandle
|
|
95
95
|
readonly schemaId: SchemaId
|
|
96
|
-
closed: boolean
|
|
97
96
|
}
|
|
98
97
|
|
|
99
98
|
const changesInternals = new WeakMap<object, ChangesInternal>()
|
|
@@ -320,7 +319,6 @@ function acquireChanges<S extends AnySchema>(
|
|
|
320
319
|
Effect.suspend(() => {
|
|
321
320
|
const internal = changesInternals.get(changes)
|
|
322
321
|
if (internal === undefined) return Effect.void
|
|
323
|
-
internal.closed = true
|
|
324
322
|
return releaseOwner("ChangeSet.close", (callback) => dbNative.runtimeChangesClose(internal.handle, callback))
|
|
325
323
|
}),
|
|
326
324
|
{ interruptible: true }
|
|
@@ -330,7 +328,7 @@ function acquireChanges<S extends AnySchema>(
|
|
|
330
328
|
function makeChangeSet<S extends AnySchema>(theory: S, wire: ChangesWire, schemaId: SchemaId): ChangeSet<S> {
|
|
331
329
|
const handle = wire.changes
|
|
332
330
|
const relations = Object.values(theory.relations)
|
|
333
|
-
const internal: ChangesInternal = { handle, schemaId
|
|
331
|
+
const internal: ChangesInternal = { handle, schemaId }
|
|
334
332
|
const value: ChangeSet<S> = {
|
|
335
333
|
schemaId,
|
|
336
334
|
counts: Object.freeze({ ...wire.counts }),
|
|
@@ -351,7 +349,6 @@ function makeChangeSet<S extends AnySchema>(theory: S, wire: ChangesWire, schema
|
|
|
351
349
|
const right = internalChanges(other)
|
|
352
350
|
if (right === undefined || right.schemaId !== schemaId)
|
|
353
351
|
return Effect.fail(refusal("ChangeSet.compose", "InvalidArgument"))
|
|
354
|
-
if (internal.closed || right.closed) return Effect.fail(refusal("ChangeSet.compose", "ClosedHandle"))
|
|
355
352
|
return acquireChanges(
|
|
356
353
|
theory,
|
|
357
354
|
schemaId,
|
|
@@ -365,10 +362,7 @@ function makeChangeSet<S extends AnySchema>(theory: S, wire: ChangesWire, schema
|
|
|
365
362
|
})
|
|
366
363
|
},
|
|
367
364
|
close() {
|
|
368
|
-
return
|
|
369
|
-
internal.closed = true
|
|
370
|
-
return drainClose("ChangeSet.close", (callback) => dbNative.runtimeChangesClose(handle, callback))
|
|
371
|
-
})
|
|
365
|
+
return drainClose("ChangeSet.close", (callback) => dbNative.runtimeChangesClose(handle, callback))
|
|
372
366
|
}
|
|
373
367
|
}
|
|
374
368
|
Object.freeze(value)
|
package/src/codec.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { membersAgree } from "#closed.ts"
|
|
|
3
3
|
import { schemaTables } from "#compile.ts"
|
|
4
4
|
import { dbNative } from "#db-native.ts"
|
|
5
5
|
import { AuthoringError } from "#errors.ts"
|
|
6
|
-
import type
|
|
6
|
+
import { type AnyField, fieldDescriptor, type Infer } from "#fields.ts"
|
|
7
7
|
import { lower } from "#lower.ts"
|
|
8
8
|
import { type AnyRelation, type Fact, relationDescriptor, relationFields } from "#relation.ts"
|
|
9
9
|
import type { CellValue } from "#rows.ts"
|
|
@@ -141,7 +141,8 @@ function decodeTaggedF64(value: unknown): number | undefined {
|
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
/** Decode representation, then judge the value through the shared interpreter. */
|
|
144
|
-
function decodeBoundaryValue(context: string, field:
|
|
144
|
+
function decodeBoundaryValue<F extends AnyField>(context: string, field: F, input: unknown): Infer<F>
|
|
145
|
+
function decodeBoundaryValue(context: string, field: AnyField, input: unknown): Infer<AnyField> {
|
|
145
146
|
if ("closed" in field) return fieldValue(context, field, input)
|
|
146
147
|
let decoded: unknown = input
|
|
147
148
|
switch (field.kind) {
|
|
@@ -167,6 +168,35 @@ function decodeBoundaryValue(context: string, field: AnyField, input: unknown):
|
|
|
167
168
|
return fieldValue(context, field, decoded)
|
|
168
169
|
}
|
|
169
170
|
|
|
171
|
+
/** The host-value schema, using the same interpreter as facts and row codecs. */
|
|
172
|
+
function fieldSchema<F extends AnyField>(field: F) {
|
|
173
|
+
const descriptor = fieldDescriptor("fieldSchema", field)
|
|
174
|
+
return EffectSchema.declare((value: unknown): value is Infer<F> => {
|
|
175
|
+
try {
|
|
176
|
+
fieldValue("fieldSchema", descriptor, value)
|
|
177
|
+
return true
|
|
178
|
+
} catch {
|
|
179
|
+
return false
|
|
180
|
+
}
|
|
181
|
+
})
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** Encode one field's host value in the canonical JSON-boundary form. */
|
|
185
|
+
function encodeBoundaryField<F extends AnyField>(field: F, value: Infer<F>): Result.Result<unknown, DbError> {
|
|
186
|
+
return Result.try({
|
|
187
|
+
try: () => encodeBoundaryValue("encodeBoundaryField", fieldDescriptor("encodeBoundaryField", field), value),
|
|
188
|
+
catch: (cause) => argumentError("encodeBoundaryField", cause)
|
|
189
|
+
})
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** Strict JSON-boundary decoding, returning the field's canonical host value. */
|
|
193
|
+
function decodeBoundaryField<F extends AnyField>(field: F, input: unknown): Result.Result<Infer<F>, DbError> {
|
|
194
|
+
return Result.try({
|
|
195
|
+
try: () => decodeBoundaryValue("decodeBoundaryField", fieldDescriptor("decodeBoundaryField", field), input),
|
|
196
|
+
catch: (cause) => argumentError("decodeBoundaryField", cause)
|
|
197
|
+
})
|
|
198
|
+
}
|
|
199
|
+
|
|
170
200
|
/** Pure schema-tagged JSON encoding of complete rows. */
|
|
171
201
|
function encodeBoundaryRows<R extends AnyRelation>(
|
|
172
202
|
relation: R,
|
|
@@ -286,4 +316,14 @@ const decodeRows = Effect.fn("decodeRows")(function* <R extends AnyRelation>(sha
|
|
|
286
316
|
})
|
|
287
317
|
|
|
288
318
|
export type { RowShape }
|
|
289
|
-
export {
|
|
319
|
+
export {
|
|
320
|
+
decodeBoundaryField,
|
|
321
|
+
decodeBoundaryRows,
|
|
322
|
+
decodeRows,
|
|
323
|
+
encodeBoundaryField,
|
|
324
|
+
encodeBoundaryRows,
|
|
325
|
+
encodeRows,
|
|
326
|
+
fieldSchema,
|
|
327
|
+
rowSchema,
|
|
328
|
+
rowShape
|
|
329
|
+
}
|
package/src/db-native.ts
CHANGED
|
@@ -226,16 +226,8 @@ interface DbBridge {
|
|
|
226
226
|
bytes: Uint8Array,
|
|
227
227
|
callback: () => void
|
|
228
228
|
): OperationHandle
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
* Read-only migration-codec integration over native `schema_file` and
|
|
232
|
-
* `migration::{plan, manifest}` through the shared executor: bounded
|
|
233
|
-
* owned input, bounded owned JSON response bytes, one registered
|
|
234
|
-
* cancellable operation. Neither verb opens, initializes, freezes or
|
|
235
|
-
* migrates a database.
|
|
236
|
-
*/
|
|
237
|
-
runtimeMigrationSchema(runtime: RuntimeHandle, spec: SchemaSpec, callback: () => void): OperationHandle
|
|
238
|
-
runtimeMigrationRead(runtime: RuntimeHandle, request: Uint8Array, callback: () => void): OperationHandle
|
|
229
|
+
runtimeSchemaSnapshot(runtime: RuntimeHandle, spec: SchemaSpec, callback: () => void): OperationHandle
|
|
230
|
+
runtimeSchemaBindings(runtime: RuntimeHandle, snapshot: Uint8Array, callback: () => void): OperationHandle
|
|
239
231
|
}
|
|
240
232
|
|
|
241
233
|
// The fresh-addon roster test pins this private declaration exactly as it
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* or disposal twin. The raw native bridge is not exported from this barrel.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
export { alternatives } from "#alternatives.ts"
|
|
9
10
|
export type {
|
|
10
11
|
BoundsOnTarget,
|
|
11
12
|
CapacityWeight,
|
|
@@ -27,7 +28,17 @@ export type {
|
|
|
27
28
|
} from "#closed.ts"
|
|
28
29
|
export { closed, closedId } from "#closed.ts"
|
|
29
30
|
export type { RowShape } from "#codec.ts"
|
|
30
|
-
export {
|
|
31
|
+
export {
|
|
32
|
+
decodeBoundaryField,
|
|
33
|
+
decodeBoundaryRows,
|
|
34
|
+
decodeRows,
|
|
35
|
+
encodeBoundaryField,
|
|
36
|
+
encodeBoundaryRows,
|
|
37
|
+
encodeRows,
|
|
38
|
+
fieldSchema,
|
|
39
|
+
rowSchema,
|
|
40
|
+
rowShape
|
|
41
|
+
} from "#codec.ts"
|
|
31
42
|
export type { CompiledSchema, SchemaId } from "#compile.ts"
|
|
32
43
|
export { Schema } from "#compile.ts"
|
|
33
44
|
export type {
|
|
@@ -112,7 +123,13 @@ export type { FindColumn } from "#query/atom.ts"
|
|
|
112
123
|
export { ALLEN } from "#query/atom.ts"
|
|
113
124
|
export type { AnyComputeExpr, ComputeExpr, ComputeValue, QueryNode } from "#query/compute.ts"
|
|
114
125
|
export { Compute } from "#query/compute.ts"
|
|
115
|
-
export type {
|
|
126
|
+
export type {
|
|
127
|
+
DescriptionHead,
|
|
128
|
+
DescriptionParameter,
|
|
129
|
+
DescriptionRow,
|
|
130
|
+
DescriptionTable,
|
|
131
|
+
QueryDescription
|
|
132
|
+
} from "#query/description.ts"
|
|
116
133
|
export { describeQuery, queryFromDescription } from "#query/description.ts"
|
|
117
134
|
export type { Agg, HeadRecordOf, RowOfFind } from "#query/find.ts"
|
|
118
135
|
export type {
|
|
@@ -147,6 +164,7 @@ export type {
|
|
|
147
164
|
VarsOf
|
|
148
165
|
} from "#query/scope.ts"
|
|
149
166
|
export { v } from "#query/scope.ts"
|
|
167
|
+
export type { IntervalVar, SegmentOp, Segments } from "#query/segments.ts"
|
|
150
168
|
export type {
|
|
151
169
|
AnyRelation,
|
|
152
170
|
Fact,
|
|
@@ -164,17 +182,16 @@ export { NativeRuntime } from "#runtime.ts"
|
|
|
164
182
|
export type { CloseReport, OutstandingWork } from "#runtime-errors.ts"
|
|
165
183
|
export { CloseFailure, DbError, dbError, runtimeErrorCodes } from "#runtime-errors.ts"
|
|
166
184
|
export type {
|
|
185
|
+
IntervalKind,
|
|
167
186
|
NumericCast,
|
|
168
|
-
|
|
169
|
-
|
|
187
|
+
Rounding,
|
|
188
|
+
ScalarInputKind,
|
|
170
189
|
ScalarKind,
|
|
171
|
-
ScalarLeafScope,
|
|
172
190
|
ScalarLiteral,
|
|
173
191
|
ScalarNode,
|
|
174
192
|
ScalarResultKind,
|
|
175
193
|
ScalarValue
|
|
176
194
|
} from "#scalar.ts"
|
|
177
|
-
export { Scalar } from "#scalar.ts"
|
|
178
195
|
export type { AnySchema, Schema as SchemaDeclaration, SchemaRelation, SchemaRelations } from "#schema.ts"
|
|
179
196
|
export { schema } from "#schema.ts"
|
|
180
197
|
export type { AnySelected, FieldsOf, Selected, SelectionBinding, SelectionInput } from "#selection.ts"
|
package/src/internal/log.ts
CHANGED
|
@@ -12,7 +12,6 @@ export type { PreparedQuery, QueryReader } from "#db.ts"
|
|
|
12
12
|
export { Db, internalPublishedReader } from "#db.ts"
|
|
13
13
|
export type { SnapshotHandle } from "#db-native.ts"
|
|
14
14
|
export { lower } from "#lower.ts"
|
|
15
|
-
export { internalMigrationRead, internalMigrationSchema } from "#migration.ts"
|
|
16
15
|
export {
|
|
17
16
|
internalBlake3,
|
|
18
17
|
internalDescriptor,
|
|
@@ -22,11 +21,10 @@ export {
|
|
|
22
21
|
} from "#native.ts"
|
|
23
22
|
export type { CompleteResult } from "#result.ts"
|
|
24
23
|
export { factCellsOf } from "#rows.ts"
|
|
25
|
-
export type { NativeRuntimeOptions
|
|
24
|
+
export type { NativeRuntimeOptions } from "#runtime.ts"
|
|
26
25
|
export {
|
|
27
26
|
finalizeClose,
|
|
28
27
|
hashChunk,
|
|
29
|
-
internalAcquireRepositoryLock,
|
|
30
28
|
NativeRuntime,
|
|
31
29
|
nativeOperation,
|
|
32
30
|
nativeOperationWith,
|
|
@@ -41,8 +39,8 @@ export type {
|
|
|
41
39
|
InspectionWire,
|
|
42
40
|
NativeKind,
|
|
43
41
|
OperationHandle,
|
|
44
|
-
RepositoryLockHandle,
|
|
45
42
|
RuntimeHandle
|
|
46
43
|
} from "#runtime-native.ts"
|
|
47
44
|
export { runtimeNative } from "#runtime-native.ts"
|
|
48
45
|
export { schemasAgree } from "#schema.ts"
|
|
46
|
+
export { internalSchemaBindings, internalSchemaSnapshot } from "#schema-file.ts"
|
package/src/native.ts
CHANGED
|
@@ -82,13 +82,21 @@ type HeadOpIr = "sum" | "mean" | "min" | "max" | "count" | "pack"
|
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
84
|
* The computed-find scalar expression (C05 `FindTerm::Compute(ScalarExpr)`):
|
|
85
|
-
* exactly the frozen core roster, spelled as the
|
|
85
|
+
* exactly the frozen core roster, spelled as the canonical scalar JSON spells
|
|
86
86
|
* the same expressions (one grammar, no second evaluator). `var` binds a
|
|
87
87
|
* rule variable ordinal on this lane.
|
|
88
88
|
*/
|
|
89
89
|
type NumericCastIr = "toF64" | "toF64Exact" | "toI64Exact" | "toU64Exact"
|
|
90
90
|
|
|
91
91
|
type ScalarExprIr =
|
|
92
|
+
| { readonly kind: "measure"; readonly expr: ScalarExprIr }
|
|
93
|
+
| {
|
|
94
|
+
readonly kind: "mulDiv"
|
|
95
|
+
readonly a: ScalarExprIr
|
|
96
|
+
readonly b: ScalarExprIr
|
|
97
|
+
readonly divisor: ScalarExprIr
|
|
98
|
+
readonly rounding: import("#scalar.ts").Rounding
|
|
99
|
+
}
|
|
92
100
|
| { readonly kind: "var"; readonly var: number }
|
|
93
101
|
| { readonly kind: "literal"; readonly value: TaggedValue }
|
|
94
102
|
| { readonly kind: "negate"; readonly expr: ScalarExprIr }
|
|
@@ -114,6 +122,12 @@ type FoldOpIr =
|
|
|
114
122
|
| { readonly kind: "max" }
|
|
115
123
|
|
|
116
124
|
type FindTermIr =
|
|
125
|
+
| {
|
|
126
|
+
readonly kind: "segments"
|
|
127
|
+
readonly op: import("#query/segments.ts").SegmentOp
|
|
128
|
+
readonly left: number
|
|
129
|
+
readonly right: number
|
|
130
|
+
}
|
|
117
131
|
| { readonly kind: "var"; readonly var: number }
|
|
118
132
|
| { readonly kind: "compute"; readonly expr: ScalarExprIr }
|
|
119
133
|
| { readonly kind: "count" }
|
|
@@ -280,7 +294,7 @@ type LogAccess =
|
|
|
280
294
|
readonly operation: string
|
|
281
295
|
readonly intent:
|
|
282
296
|
| { readonly kind: "erasure" }
|
|
283
|
-
| { readonly kind: "
|
|
297
|
+
| { readonly kind: "transition"; readonly contractDigest: Uint8Array; readonly target: string }
|
|
284
298
|
}
|
|
285
299
|
|
|
286
300
|
type LogLifecycle =
|
|
@@ -297,10 +311,10 @@ type LogLifecycle =
|
|
|
297
311
|
readonly reason:
|
|
298
312
|
| { readonly kind: "erasure" }
|
|
299
313
|
| {
|
|
300
|
-
readonly kind: "
|
|
314
|
+
readonly kind: "transitionAborted"
|
|
301
315
|
readonly sourceDatabase: string
|
|
302
316
|
readonly sourceIncarnation: string
|
|
303
|
-
readonly
|
|
317
|
+
readonly contractDigest: Uint8Array
|
|
304
318
|
}
|
|
305
319
|
}
|
|
306
320
|
|
|
@@ -313,7 +327,7 @@ type LogActivation =
|
|
|
313
327
|
readonly cause:
|
|
314
328
|
| { readonly kind: "create" }
|
|
315
329
|
| { readonly kind: "restore" }
|
|
316
|
-
| { readonly kind: "
|
|
330
|
+
| { readonly kind: "transition"; readonly contractDigest: Uint8Array }
|
|
317
331
|
}
|
|
318
332
|
|
|
319
333
|
interface LogAuthority {
|
|
@@ -327,10 +341,10 @@ type LogGenesisProvenance =
|
|
|
327
341
|
| { readonly kind: "create" }
|
|
328
342
|
| { readonly kind: "restore"; readonly sourceEvidence: Uint8Array }
|
|
329
343
|
| {
|
|
330
|
-
readonly kind: "
|
|
344
|
+
readonly kind: "transition"
|
|
331
345
|
readonly sourceDatabase: string
|
|
332
346
|
readonly sourceIncarnation: string
|
|
333
|
-
readonly
|
|
347
|
+
readonly contractDigest: Uint8Array
|
|
334
348
|
}
|
|
335
349
|
|
|
336
350
|
interface LogGenesis {
|
package/src/query/atom.ts
CHANGED
|
@@ -16,6 +16,7 @@ import type {
|
|
|
16
16
|
ShapeOf
|
|
17
17
|
} from "#query/scope.ts"
|
|
18
18
|
import { isTerm, term } from "#query/scope.ts"
|
|
19
|
+
import type { Segments } from "#query/segments.ts"
|
|
19
20
|
import type { FieldsShape } from "#relation.ts"
|
|
20
21
|
import type { ScalarKind } from "#scalar.ts"
|
|
21
22
|
import type { Uuid } from "#uuid.ts"
|
|
@@ -75,6 +76,7 @@ type AggData =
|
|
|
75
76
|
|
|
76
77
|
/** Compute `expr` is the shared `#scalar.ts` query-var node (one grammar). */
|
|
77
78
|
type FindEntryData =
|
|
79
|
+
| Segments
|
|
78
80
|
| { readonly kind: "var"; readonly over: AnyVar }
|
|
79
81
|
| { readonly kind: "aggregate"; readonly agg: AggData }
|
|
80
82
|
| { readonly kind: "compute"; readonly expr: QueryNode; readonly result: ScalarKind }
|
package/src/query/compute.ts
CHANGED
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* variable-addressed leaf scope over the ONE shared operator roster in
|
|
4
|
-
* `#scalar.ts`. Leaves are bound query variables that lower to `VarId`s.
|
|
5
|
-
* Operators are the shared constructors — this module only admits known
|
|
6
|
-
* schema kinds at query-var leaves.
|
|
7
|
-
*
|
|
8
|
-
* `ComputeExpr<K>` is a `ScalarNode<"query-var", K>`. Distinct I64 and U64
|
|
9
|
-
* survive host inference; they do not collapse to plain `bigint`.
|
|
10
|
-
*/
|
|
1
|
+
/** Query scalar expressions use the same nodes that native preparation reads.
|
|
2
|
+
* Distinct i64 and u64 kinds survive TypeScript's shared bigint carrier. */
|
|
11
3
|
import { AuthoringError } from "#errors.ts"
|
|
12
4
|
import type { AnyField } from "#fields.ts"
|
|
13
5
|
import { bool as boolField, f64 as f64Field, i64 as i64Field, rosterOf, u64 as u64Field } from "#fields.ts"
|
|
14
6
|
import type { AnyVar } from "#query/scope.ts"
|
|
15
7
|
import { isTerm, term } from "#query/scope.ts"
|
|
16
|
-
import type { ScalarKind, ScalarLiteral, ScalarNode } from "#scalar.ts"
|
|
8
|
+
import type { Rounding, ScalarKind, ScalarLiteral, ScalarNode } from "#scalar.ts"
|
|
17
9
|
import {
|
|
18
10
|
checkBool,
|
|
19
11
|
checkF64,
|
|
@@ -27,16 +19,18 @@ import {
|
|
|
27
19
|
scalarCast,
|
|
28
20
|
scalarFloatPredicate,
|
|
29
21
|
scalarLiteral,
|
|
22
|
+
scalarMeasure,
|
|
23
|
+
scalarMulDiv,
|
|
30
24
|
scalarNegate
|
|
31
25
|
} from "#scalar.ts"
|
|
32
26
|
|
|
33
|
-
/** Query
|
|
34
|
-
type QueryNode = ScalarNode
|
|
27
|
+
/** Query expression, including interval leaves consumed by measure. */
|
|
28
|
+
type QueryNode = ScalarNode
|
|
35
29
|
|
|
36
30
|
/** Host value for a derived query compute kind. */
|
|
37
31
|
type ComputeValue<K extends ScalarKind> = K extends "f64" ? number : K extends "bool" ? boolean : bigint
|
|
38
32
|
|
|
39
|
-
type ComputeExpr<K extends ScalarKind> = ScalarNode<
|
|
33
|
+
type ComputeExpr<K extends ScalarKind> = ScalarNode<K>
|
|
40
34
|
|
|
41
35
|
type AnyComputeExpr = ComputeExpr<"u64"> | ComputeExpr<"i64"> | ComputeExpr<"f64"> | ComputeExpr<"bool">
|
|
42
36
|
|
|
@@ -61,7 +55,10 @@ type OperandKind<O> =
|
|
|
61
55
|
: never
|
|
62
56
|
|
|
63
57
|
function isComputeExpr(value: unknown): value is AnyComputeExpr {
|
|
64
|
-
return
|
|
58
|
+
return (
|
|
59
|
+
isScalarNode(value) &&
|
|
60
|
+
(value.result === "u64" || value.result === "i64" || value.result === "f64" || value.result === "bool")
|
|
61
|
+
)
|
|
65
62
|
}
|
|
66
63
|
|
|
67
64
|
function varKindOf(where: string, ref: AnyVar): ScalarKind {
|
|
@@ -93,7 +90,7 @@ function asQueryNode(where: string, operand: Operand): QueryNode {
|
|
|
93
90
|
}
|
|
94
91
|
|
|
95
92
|
function literal<K extends ScalarKind>(value: ScalarLiteral): ComputeExpr<K> {
|
|
96
|
-
return scalarLiteral(
|
|
93
|
+
return scalarLiteral(value) as ComputeExpr<K>
|
|
97
94
|
}
|
|
98
95
|
|
|
99
96
|
function u64(value: bigint): ComputeExpr<"u64"> {
|
|
@@ -167,6 +164,37 @@ function negate<O extends SignedOperand>(operand: O): ComputeExpr<OperandKind<O>
|
|
|
167
164
|
return scalarNegate(where, asQueryNode(where, operand)) as ComputeExpr<OperandKind<O> & ("i64" | "f64")>
|
|
168
165
|
}
|
|
169
166
|
|
|
167
|
+
type IntegerOperand =
|
|
168
|
+
| ComputeExpr<"u64">
|
|
169
|
+
| ComputeExpr<"i64">
|
|
170
|
+
| (AnyVar & { readonly field: { readonly kind: "i64" | "u64" } })
|
|
171
|
+
|
|
172
|
+
function mulDiv<A extends IntegerOperand, B extends IntegerOperand, D extends IntegerOperand>(
|
|
173
|
+
a: A,
|
|
174
|
+
b: B & (OperandKind<A> extends OperandKind<B> ? unknown : never),
|
|
175
|
+
divisor: D & (OperandKind<A> extends OperandKind<D> ? unknown : never),
|
|
176
|
+
rounding: Rounding
|
|
177
|
+
): ComputeExpr<OperandKind<A>> {
|
|
178
|
+
return scalarMulDiv(
|
|
179
|
+
"Compute.mulDiv",
|
|
180
|
+
asQueryNode("Compute.mulDiv", a),
|
|
181
|
+
asQueryNode("Compute.mulDiv", b),
|
|
182
|
+
asQueryNode("Compute.mulDiv", divisor),
|
|
183
|
+
rounding
|
|
184
|
+
) as ComputeExpr<OperandKind<A>>
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function measure<V extends AnyVar & { readonly field: { readonly kind: "interval" } }>(
|
|
188
|
+
interval: V
|
|
189
|
+
): ComputeExpr<V["field"] extends { readonly element: "f64" } ? "f64" : "u64"> {
|
|
190
|
+
if (!isTerm(interval) || interval[term] !== "var" || interval.field.kind !== "interval")
|
|
191
|
+
throw new AuthoringError({ message: "Compute.measure: expected an interval variable" })
|
|
192
|
+
const kind = { u64: "intervalU64", i64: "intervalI64", f64: "intervalF64" } as const
|
|
193
|
+
return scalarMeasure("Compute.measure", queryVarLeaf(interval, kind[interval.field.element])) as ComputeExpr<
|
|
194
|
+
V["field"] extends { readonly element: "f64" } ? "f64" : "u64"
|
|
195
|
+
>
|
|
196
|
+
}
|
|
197
|
+
|
|
170
198
|
function toF64(operand: ArithmeticOperand): ComputeExpr<"f64"> {
|
|
171
199
|
const where = "Compute.toF64"
|
|
172
200
|
return scalarCast(where, "toF64", "f64", asQueryNode(where, operand)) as ComputeExpr<"f64">
|
|
@@ -225,6 +253,8 @@ const Compute = Object.freeze({
|
|
|
225
253
|
subtract,
|
|
226
254
|
multiply,
|
|
227
255
|
divide,
|
|
256
|
+
mulDiv,
|
|
257
|
+
measure,
|
|
228
258
|
toF64,
|
|
229
259
|
toF64Exact,
|
|
230
260
|
toI64Exact,
|