@bjornpagen/bumbledb 0.20.3 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/COOKBOOK.md +283 -1611
- package/README.md +156 -118
- package/dist/capacity.d.ts +16 -12
- package/dist/capacity.d.ts.map +1 -1
- package/dist/capacity.js +16 -48
- package/dist/capacity.js.map +1 -1
- package/dist/changes.d.ts +54 -0
- package/dist/changes.d.ts.map +1 -0
- package/dist/changes.js +245 -0
- package/dist/changes.js.map +1 -0
- package/dist/close.d.ts +24 -0
- package/dist/close.d.ts.map +1 -0
- package/dist/close.js +34 -0
- package/dist/close.js.map +1 -0
- package/dist/closed.d.ts +1 -3
- package/dist/closed.d.ts.map +1 -1
- package/dist/closed.js +24 -12
- package/dist/closed.js.map +1 -1
- package/dist/codec.d.ts +56 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +289 -0
- package/dist/codec.js.map +1 -0
- package/dist/compile.d.ts +67 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +75 -0
- package/dist/compile.js.map +1 -0
- package/dist/db-native.d.ts +161 -0
- package/dist/db-native.d.ts.map +1 -0
- package/dist/db-native.js +5 -0
- package/dist/db-native.js.map +1 -0
- package/dist/db.d.ts +101 -233
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +232 -1084
- package/dist/db.js.map +1 -1
- package/dist/errors.d.ts +53 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +28 -0
- package/dist/errors.js.map +1 -0
- package/dist/face.d.ts.map +1 -1
- package/dist/face.js +2 -2
- package/dist/face.js.map +1 -1
- package/dist/fields.d.ts +64 -24
- package/dist/fields.d.ts.map +1 -1
- package/dist/fields.js +94 -24
- package/dist/fields.js.map +1 -1
- package/dist/index.d.ts +37 -32
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -21
- package/dist/index.js.map +1 -1
- package/dist/internal/log.d.ts +24 -0
- package/dist/internal/log.d.ts.map +1 -0
- package/dist/internal/log.js +10 -0
- package/dist/internal/log.js.map +1 -0
- package/dist/law.d.ts +8 -13
- package/dist/law.d.ts.map +1 -1
- package/dist/law.js +6 -59
- package/dist/law.js.map +1 -1
- package/dist/lower.d.ts +0 -13
- package/dist/lower.d.ts.map +1 -1
- package/dist/lower.js +9 -17
- package/dist/lower.js.map +1 -1
- package/dist/migration.d.ts +32 -0
- package/dist/migration.d.ts.map +1 -0
- package/dist/migration.js +47 -0
- package/dist/migration.js.map +1 -0
- package/dist/native.d.ts +256 -301
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js +65 -108
- package/dist/native.js.map +1 -1
- package/dist/query/atom.d.ts +24 -13
- package/dist/query/atom.d.ts.map +1 -1
- package/dist/query/atom.js +7 -3
- package/dist/query/atom.js.map +1 -1
- package/dist/query/compute.d.ts +68 -0
- package/dist/query/compute.d.ts.map +1 -0
- package/dist/query/compute.js +141 -0
- package/dist/query/compute.js.map +1 -0
- package/dist/query/find.d.ts +15 -8
- package/dist/query/find.d.ts.map +1 -1
- package/dist/query/find.js +6 -2
- package/dist/query/find.js.map +1 -1
- package/dist/query/lower.d.ts +23 -2
- package/dist/query/lower.d.ts.map +1 -1
- package/dist/query/lower.js +433 -80
- package/dist/query/lower.js.map +1 -1
- package/dist/query/parse-ir.d.ts.map +1 -1
- package/dist/query/parse-ir.js +17 -8
- package/dist/query/parse-ir.js.map +1 -1
- package/dist/query/run.d.ts +12 -2
- package/dist/query/run.d.ts.map +1 -1
- package/dist/query/run.js +26 -9
- package/dist/query/run.js.map +1 -1
- package/dist/query/scope.d.ts +47 -3
- package/dist/query/scope.d.ts.map +1 -1
- package/dist/query/scope.js +83 -19
- package/dist/query/scope.js.map +1 -1
- package/dist/relation.d.ts +3 -8
- package/dist/relation.d.ts.map +1 -1
- package/dist/relation.js +16 -10
- package/dist/relation.js.map +1 -1
- package/dist/result.d.ts +47 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/result.js +50 -0
- package/dist/result.js.map +1 -0
- package/dist/rows.d.ts +69 -0
- package/dist/rows.d.ts.map +1 -0
- package/dist/rows.js +325 -0
- package/dist/rows.js.map +1 -0
- package/dist/runtime-codes.d.ts +2 -0
- package/dist/runtime-codes.d.ts.map +1 -0
- package/dist/runtime-codes.js +19 -0
- package/dist/runtime-codes.js.map +1 -0
- package/dist/runtime-errors.d.ts +106 -0
- package/dist/runtime-errors.d.ts.map +1 -0
- package/dist/runtime-errors.js +62 -0
- package/dist/runtime-errors.js.map +1 -0
- package/dist/runtime-native.d.ts +159 -0
- package/dist/runtime-native.d.ts.map +1 -0
- package/dist/runtime-native.js +5 -0
- package/dist/runtime-native.js.map +1 -0
- package/dist/runtime.d.ts +73 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +292 -0
- package/dist/runtime.js.map +1 -0
- package/dist/scalar.d.ts +165 -0
- package/dist/scalar.d.ts.map +1 -0
- package/dist/scalar.js +344 -0
- package/dist/scalar.js.map +1 -0
- package/dist/schema.d.ts +1 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +34 -37
- package/dist/schema.js.map +1 -1
- package/dist/shape.d.ts +27 -0
- package/dist/shape.d.ts.map +1 -0
- package/dist/shape.js +2 -0
- package/dist/shape.js.map +1 -0
- package/dist/spec.d.ts +27 -3
- package/dist/spec.d.ts.map +1 -1
- package/dist/spec.js +22 -1
- package/dist/spec.js.map +1 -1
- package/dist/statements.d.ts +16 -3
- package/dist/statements.d.ts.map +1 -1
- package/dist/statements.js +54 -28
- package/dist/statements.js.map +1 -1
- package/dist/uuid.d.ts +23 -0
- package/dist/uuid.d.ts.map +1 -0
- package/dist/uuid.js +54 -0
- package/dist/uuid.js.map +1 -0
- package/pack-provenance.json +7 -0
- package/package.json +12 -16
- package/src/capacity.ts +34 -54
- package/src/changes.ts +361 -0
- package/src/close.ts +53 -0
- package/src/closed.ts +25 -19
- package/src/codec.ts +379 -0
- package/src/compile.ts +148 -0
- package/src/db-native.ts +238 -0
- package/src/db.ts +461 -1632
- package/src/errors.ts +46 -0
- package/src/face.ts +2 -2
- package/src/fields.ts +181 -55
- package/src/index.ts +62 -126
- package/src/internal/log.ts +49 -0
- package/src/law.ts +13 -28
- package/src/lower.ts +9 -4
- package/src/migration.ts +68 -0
- package/src/native.ts +326 -487
- package/src/query/atom.ts +61 -25
- package/src/query/compute.ts +237 -0
- package/src/query/find.ts +31 -12
- package/src/query/lower.ts +531 -143
- package/src/query/parse-ir.ts +18 -13
- package/src/query/run.ts +32 -16
- package/src/query/scope.ts +140 -8
- package/src/relation.ts +17 -21
- package/src/result.ts +130 -0
- package/src/rows.ts +401 -0
- package/src/runtime-codes.ts +18 -0
- package/src/runtime-errors.ts +69 -0
- package/src/runtime-native.ts +222 -0
- package/src/runtime.ts +439 -0
- package/src/scalar.ts +560 -0
- package/src/schema.ts +35 -37
- package/src/shape.ts +30 -0
- package/src/spec.ts +33 -3
- package/src/statements.ts +75 -68
- package/src/uuid.ts +69 -0
- package/dist/marshal.d.ts +0 -44
- package/dist/marshal.d.ts.map +0 -1
- package/dist/marshal.js +0 -165
- package/dist/marshal.js.map +0 -1
- package/src/marshal.ts +0 -200
package/src/errors.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Data } from "effect"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pure authoring failures, SDK-invariant defects and internal native-boundary
|
|
5
|
+
* diagnostics. AST misuse can throw synchronously without I/O. Runtime
|
|
6
|
+
* adapters translate operational failures into the public `DbError` class
|
|
7
|
+
* in `#runtime-errors.ts`; contradictions in SDK/native state remain defects.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** A pure schema, query, parameter, or value-authoring refusal. */
|
|
11
|
+
export class AuthoringError extends Data.TaggedError("AuthoringError")<{
|
|
12
|
+
readonly message: string
|
|
13
|
+
}> {}
|
|
14
|
+
|
|
15
|
+
/** A contradiction in an SDK/native result, not an application refusal. */
|
|
16
|
+
export class SdkInvariantError extends Data.TaggedError("SdkInvariantError")<{
|
|
17
|
+
readonly message: string
|
|
18
|
+
}> {}
|
|
19
|
+
|
|
20
|
+
export class NativeLoadError extends Data.TaggedError("NativeLoadError")<{
|
|
21
|
+
readonly package: string
|
|
22
|
+
readonly operation: "resolve" | "load"
|
|
23
|
+
readonly message: string
|
|
24
|
+
readonly cause: unknown
|
|
25
|
+
}> {}
|
|
26
|
+
|
|
27
|
+
/** A native bridge call's contextual failure; the exact thrown value is retained. */
|
|
28
|
+
export class NativeOperationError extends Data.TaggedError("NativeOperationError")<{
|
|
29
|
+
readonly operation: string
|
|
30
|
+
readonly cause: unknown
|
|
31
|
+
}> {
|
|
32
|
+
override get message(): string {
|
|
33
|
+
const cause = this.cause
|
|
34
|
+
const detail =
|
|
35
|
+
typeof cause === "object" && cause !== null && "message" in cause && typeof cause.message === "string"
|
|
36
|
+
? cause.message
|
|
37
|
+
: String(cause)
|
|
38
|
+
return `${this.operation}: ${detail}`
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class NativeReportedError extends Data.TaggedError("NativeReportedError")<{
|
|
43
|
+
readonly kind: string
|
|
44
|
+
readonly message: string
|
|
45
|
+
readonly cause: unknown
|
|
46
|
+
}> {}
|
package/src/face.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as errors from "@superbuilders/errors"
|
|
2
1
|
import type { AnyClosed, AnySelectedClosed, PayloadField } from "#closed.ts"
|
|
2
|
+
import { AuthoringError } from "#errors.ts"
|
|
3
3
|
import type { AnyField, SignatureOf } from "#fields.ts"
|
|
4
4
|
import type { Same } from "#judgment.ts"
|
|
5
5
|
import type { AnyRelation, AnySelected, FieldsShape, RelationFields, SelectionBinding } from "#relation.ts"
|
|
@@ -121,7 +121,7 @@ function on<S extends FaceSource>(source: S, fields: string | readonly string[])
|
|
|
121
121
|
})
|
|
122
122
|
const value = Object.freeze({ source, projection, data })
|
|
123
123
|
if (!faceMinted<S, readonly string[]>(value, source, projection)) {
|
|
124
|
-
throw
|
|
124
|
+
throw new AuthoringError({ message: `face over ${parts.owner.name}: face construction incomplete` })
|
|
125
125
|
}
|
|
126
126
|
return value
|
|
127
127
|
}
|
package/src/fields.ts
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
import * as errors from "@superbuilders/errors"
|
|
2
1
|
import { regex } from "arkregex"
|
|
2
|
+
import { Result } from "effect"
|
|
3
|
+
import { AuthoringError } from "#errors.ts"
|
|
4
|
+
import { DbError } from "#runtime-errors.ts"
|
|
3
5
|
import type { LiteralSpec } from "#spec.ts"
|
|
6
|
+
import { Uuid } from "#uuid.ts"
|
|
4
7
|
|
|
5
8
|
const INTEGER_INDEX_NAME = regex("^(?:0|[1-9][0-9]*)$")
|
|
6
9
|
|
|
7
10
|
/**
|
|
8
|
-
* A half-open interval `[start, end)` as a plain value object —
|
|
9
|
-
* interval value type, whatever the field's element type
|
|
10
|
-
* The ray is representable (`end` = the element type's
|
|
11
|
-
* and signedness are NOT modeled on the value — they are
|
|
12
|
-
* labels the engine judges at the typed write boundary.
|
|
13
|
-
* derive no order
|
|
14
|
-
* so no comparators exist on the value type.
|
|
11
|
+
* A half-open integer interval `[start, end)` as a plain value object —
|
|
12
|
+
* the ONE discrete interval value type, whatever the field's element type
|
|
13
|
+
* or width label. The ray is representable (`end` = the element type's
|
|
14
|
+
* MAX_END); widths and signedness are NOT modeled on the value — they are
|
|
15
|
+
* descriptor-type labels the engine judges at the typed write boundary.
|
|
16
|
+
* Interval fields derive no order, so no comparators exist on the value.
|
|
15
17
|
*/
|
|
16
18
|
interface IntervalValue {
|
|
17
19
|
readonly start: bigint
|
|
@@ -19,17 +21,54 @@ interface IntervalValue {
|
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
24
|
+
* A half-open dense float interval `[start, end)` as a plain value object:
|
|
25
|
+
* two canonical binary64 bounds on the dense numeric line.
|
|
26
|
+
* NaN is never an endpoint, signed zero is normalized at the checked
|
|
27
|
+
* constructor and again by the native boundary, and strict `start < end`
|
|
28
|
+
* makes empty spans unrepresentable through {@link span}. Infinite bounds
|
|
29
|
+
* denote a missing bound, not a member point.
|
|
27
30
|
*/
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
interface FloatIntervalValue {
|
|
32
|
+
readonly start: number
|
|
33
|
+
readonly end: number
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Constructs a checked interval literal — the `start..end` spelling.
|
|
38
|
+
* Half-open and nonempty by construction. Fallible pure parsing
|
|
39
|
+
* returns `Result` (use `Effect.fromResult(span(...))` inside a generator),
|
|
40
|
+
* never hidden I/O and never a thrown domain outcome.
|
|
41
|
+
*
|
|
42
|
+
* Two element domains, selected by argument type: `span(0n, 60n)` is a
|
|
43
|
+
* discrete integer interval; `span(0.5, 1.5)` is a dense float interval
|
|
44
|
+
* with canonical endpoints (NaN refused, `-0` normalized to `+0`,
|
|
45
|
+
* `-Infinity` legal only as the lower bound and `+Infinity` only as the
|
|
46
|
+
* upper bound — both enforced by strict numeric `start < end`).
|
|
47
|
+
*/
|
|
48
|
+
function span(start: bigint, end: bigint): Result.Result<IntervalValue, DbError>
|
|
49
|
+
function span(start: number, end: number): Result.Result<FloatIntervalValue, DbError>
|
|
50
|
+
function span(
|
|
51
|
+
start: bigint | number,
|
|
52
|
+
end: bigint | number
|
|
53
|
+
): Result.Result<IntervalValue, DbError> | Result.Result<FloatIntervalValue, DbError> {
|
|
54
|
+
if (typeof start === "bigint" && typeof end === "bigint") {
|
|
55
|
+
if (start >= end) {
|
|
56
|
+
return Result.fail(new DbError({ operation: "span", reason: { _tag: "InvalidArgument" } }))
|
|
57
|
+
}
|
|
58
|
+
return Result.succeed(Object.freeze({ start, end }))
|
|
59
|
+
}
|
|
60
|
+
if (typeof start === "number" && typeof end === "number") {
|
|
61
|
+
if (Number.isNaN(start) || Number.isNaN(end)) {
|
|
62
|
+
return Result.fail(new DbError({ operation: "span", reason: { _tag: "InvalidArgument" } }))
|
|
63
|
+
}
|
|
64
|
+
const lo = Object.is(start, -0) ? 0 : start
|
|
65
|
+
const hi = Object.is(end, -0) ? 0 : end
|
|
66
|
+
if (!(lo < hi)) {
|
|
67
|
+
return Result.fail(new DbError({ operation: "span", reason: { _tag: "InvalidArgument" } }))
|
|
68
|
+
}
|
|
69
|
+
return Result.succeed(Object.freeze({ start: lo, end: hi }))
|
|
31
70
|
}
|
|
32
|
-
return
|
|
71
|
+
return Result.fail(new DbError({ operation: "span", reason: { _tag: "InvalidArgument" } }))
|
|
33
72
|
}
|
|
34
73
|
|
|
35
74
|
/**
|
|
@@ -56,27 +95,37 @@ interface StrField {
|
|
|
56
95
|
readonly kind: "str"
|
|
57
96
|
}
|
|
58
97
|
|
|
59
|
-
interface FreshU64Field {
|
|
60
|
-
readonly kind: "u64"
|
|
61
|
-
readonly fresh: true
|
|
62
|
-
}
|
|
63
|
-
|
|
64
98
|
interface U64Field {
|
|
65
99
|
readonly kind: "u64"
|
|
66
|
-
readonly fresh: FreshU64Field
|
|
67
100
|
}
|
|
68
101
|
|
|
69
102
|
interface I64Field {
|
|
70
103
|
readonly kind: "i64"
|
|
71
104
|
}
|
|
72
105
|
|
|
106
|
+
interface F64Field {
|
|
107
|
+
readonly kind: "f64"
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* The application-owned 128-bit identity scalar: sixteen
|
|
112
|
+
* exact bytes, spelled as the canonical hyphenated UUID {@link Uuid}
|
|
113
|
+
* host value. There is no `fresh` mark anywhere: the database issues no
|
|
114
|
+
* identity, and key laws are declared statements.
|
|
115
|
+
*/
|
|
116
|
+
interface UuidField {
|
|
117
|
+
readonly kind: "uuid"
|
|
118
|
+
}
|
|
119
|
+
|
|
73
120
|
interface BytesField<Width extends number = number> {
|
|
74
121
|
readonly kind: "bytes"
|
|
75
122
|
readonly width: Width
|
|
76
123
|
}
|
|
77
124
|
|
|
125
|
+
type IntervalElementKind = "u64" | "i64" | "f64"
|
|
126
|
+
|
|
78
127
|
interface IntervalField<
|
|
79
|
-
Element extends
|
|
128
|
+
Element extends IntervalElementKind = IntervalElementKind,
|
|
80
129
|
Width extends bigint | undefined = bigint | undefined
|
|
81
130
|
> {
|
|
82
131
|
readonly kind: "interval"
|
|
@@ -96,8 +145,9 @@ type AnyField =
|
|
|
96
145
|
| BoolField
|
|
97
146
|
| StrField
|
|
98
147
|
| U64Field
|
|
99
|
-
| FreshU64Field
|
|
100
148
|
| I64Field
|
|
149
|
+
| F64Field
|
|
150
|
+
| UuidField
|
|
101
151
|
| BytesField
|
|
102
152
|
| IntervalField
|
|
103
153
|
| AnyClosedIdField
|
|
@@ -131,20 +181,26 @@ type Infer<F extends AnyField> = F extends { readonly kind: "bool" }
|
|
|
131
181
|
? bigint
|
|
132
182
|
: F extends { readonly kind: "i64" }
|
|
133
183
|
? bigint
|
|
134
|
-
: F extends { readonly kind: "
|
|
135
|
-
?
|
|
136
|
-
: F extends { readonly kind: "
|
|
137
|
-
?
|
|
138
|
-
:
|
|
184
|
+
: F extends { readonly kind: "f64" }
|
|
185
|
+
? number
|
|
186
|
+
: F extends { readonly kind: "uuid" }
|
|
187
|
+
? Uuid
|
|
188
|
+
: F extends { readonly kind: "bytes" }
|
|
189
|
+
? Uint8Array
|
|
190
|
+
: F extends { readonly kind: "interval"; readonly element: "f64" }
|
|
191
|
+
? FloatIntervalValue
|
|
192
|
+
: F extends { readonly kind: "interval" }
|
|
193
|
+
? IntervalValue
|
|
194
|
+
: never
|
|
139
195
|
|
|
140
196
|
/**
|
|
141
197
|
* The typed shape refusal shared by every literal machine — the selection
|
|
142
|
-
* lowering here, the row
|
|
198
|
+
* lowering here, the row codec (`rows.ts`), and the query-literal
|
|
143
199
|
* tagger (`query/lower.ts`) all throw through this ONE voice; reached only
|
|
144
200
|
* through ill-typed input (the well-typed surfaces make it unrepresentable).
|
|
145
201
|
*/
|
|
146
202
|
function literalShapeError(context: string, expected: string, value: unknown): Error {
|
|
147
|
-
return
|
|
203
|
+
return new AuthoringError({ message: `${context}: expected ${expected}, got ${typeof value}` })
|
|
148
204
|
}
|
|
149
205
|
|
|
150
206
|
function rosterOf(field: AnyField | undefined): AnyClosedRoster | undefined {
|
|
@@ -196,17 +252,48 @@ function isIntervalValue(value: unknown): value is IntervalValue {
|
|
|
196
252
|
)
|
|
197
253
|
}
|
|
198
254
|
|
|
255
|
+
function isFloatIntervalValue(value: unknown): value is FloatIntervalValue {
|
|
256
|
+
return (
|
|
257
|
+
typeof value === "object" &&
|
|
258
|
+
value !== null &&
|
|
259
|
+
"start" in value &&
|
|
260
|
+
"end" in value &&
|
|
261
|
+
typeof value.start === "number" &&
|
|
262
|
+
typeof value.end === "number"
|
|
263
|
+
)
|
|
264
|
+
}
|
|
265
|
+
|
|
199
266
|
function handleLiteral(closed: AnyClosedRoster, value: unknown): LiteralSpec {
|
|
200
267
|
if (typeof value !== "string") {
|
|
201
268
|
throw literalShapeError("selection literal", `a ${closed.name} handle name (string)`, value)
|
|
202
269
|
}
|
|
203
270
|
if (!closed.handles.includes(value)) {
|
|
204
|
-
throw
|
|
271
|
+
throw new AuthoringError({
|
|
272
|
+
message: `"${value}" is not a handle of ${closed.name} — the roster is ${closed.handles.join(", ")}`
|
|
273
|
+
})
|
|
205
274
|
}
|
|
206
275
|
return { kind: "handle", handle: value }
|
|
207
276
|
}
|
|
208
277
|
|
|
209
|
-
function intervalLiteral(element:
|
|
278
|
+
function intervalLiteral(element: IntervalElementKind, value: unknown): LiteralSpec {
|
|
279
|
+
if (element === "f64") {
|
|
280
|
+
if (!isFloatIntervalValue(value)) {
|
|
281
|
+
throw literalShapeError("selection literal", "float interval ({ start, end } numbers)", value)
|
|
282
|
+
}
|
|
283
|
+
if (Number.isNaN(value.start) || Number.isNaN(value.end) || !(value.start < value.end)) {
|
|
284
|
+
throw new AuthoringError({
|
|
285
|
+
message: "selection literal: a float interval is half-open and nonempty with non-NaN canonical endpoints"
|
|
286
|
+
})
|
|
287
|
+
}
|
|
288
|
+
return {
|
|
289
|
+
kind: "value",
|
|
290
|
+
value: {
|
|
291
|
+
kind: "intervalF64",
|
|
292
|
+
start: Object.is(value.start, -0) ? 0 : value.start,
|
|
293
|
+
end: Object.is(value.end, -0) ? 0 : value.end
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
210
297
|
if (!isIntervalValue(value)) {
|
|
211
298
|
throw literalShapeError("selection literal", "interval ({ start, end } bigints)", value)
|
|
212
299
|
}
|
|
@@ -218,55 +305,76 @@ function intervalLiteral(element: "u64" | "i64", value: unknown): LiteralSpec {
|
|
|
218
305
|
|
|
219
306
|
function assertDeclarationOrderKey(where: string, name: string): void {
|
|
220
307
|
if (INTEGER_INDEX_NAME.test(name)) {
|
|
221
|
-
throw
|
|
222
|
-
`${where}: name ${name} is an integer index — JavaScript object keys re-order integer indices, breaking the declaration-order law; use a non-numeric name`
|
|
223
|
-
)
|
|
308
|
+
throw new AuthoringError({
|
|
309
|
+
message: `${where}: name ${name} is an integer index — JavaScript object keys re-order integer indices, breaking the declaration-order law; use a non-numeric name`
|
|
310
|
+
})
|
|
224
311
|
}
|
|
225
312
|
if (name.includes(".")) {
|
|
226
|
-
throw
|
|
227
|
-
`${where}: name ${name} contains a dot — the law classes key on the \`relation.field\` coordinate, so a dotted name would alias unrelated slots (macro parity: Rust identifiers cannot contain dots); use a dot-free name`
|
|
228
|
-
)
|
|
313
|
+
throw new AuthoringError({
|
|
314
|
+
message: `${where}: name ${name} contains a dot — the law classes key on the \`relation.field\` coordinate, so a dotted name would alias unrelated slots (macro parity: Rust identifiers cannot contain dots); use a dot-free name`
|
|
315
|
+
})
|
|
229
316
|
}
|
|
230
317
|
}
|
|
231
318
|
|
|
232
319
|
function assertDeclarationRecord(where: string, record: object): void {
|
|
233
320
|
const proto = Object.getPrototypeOf(record)
|
|
234
321
|
if (proto !== Object.prototype && proto !== null) {
|
|
235
|
-
throw
|
|
236
|
-
`${where}: the declaration record's prototype was replaced — a plain \`__proto__: {...}\` entry is the prototype setter, so its key silently vanishes from the declaration; spell it computed (["__proto__"]: {...}) to declare it as data`
|
|
237
|
-
)
|
|
322
|
+
throw new AuthoringError({
|
|
323
|
+
message: `${where}: the declaration record's prototype was replaced — a plain \`__proto__: {...}\` entry is the prototype setter, so its key silently vanishes from the declaration; spell it computed (["__proto__"]: {...}) to declare it as data`
|
|
324
|
+
})
|
|
238
325
|
}
|
|
239
326
|
}
|
|
240
327
|
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
const u64: U64Field = Object.freeze({ kind: "u64", fresh: freshU64 })
|
|
328
|
+
const u64: U64Field = Object.freeze({ kind: "u64" })
|
|
244
329
|
|
|
245
330
|
const i64: I64Field = Object.freeze({ kind: "i64" })
|
|
246
331
|
|
|
332
|
+
/** Binary64. The native value boundary canonicalizes NaN and signed zero. */
|
|
333
|
+
const f64: F64Field = Object.freeze({ kind: "f64" })
|
|
334
|
+
|
|
335
|
+
/** The application-owned 128-bit identity scalar; no fresh mark exists. */
|
|
336
|
+
const uuid: UuidField = Object.freeze({ kind: "uuid" })
|
|
337
|
+
|
|
247
338
|
const bool: BoolField = Object.freeze({ kind: "bool" })
|
|
248
339
|
|
|
249
340
|
const str: StrField = Object.freeze({ kind: "str" })
|
|
250
341
|
|
|
251
342
|
function bytes<const Width extends number>(width: Width): BytesField<Width> {
|
|
252
343
|
if (!Number.isInteger(width) || width < 1 || width > 64) {
|
|
253
|
-
throw
|
|
344
|
+
throw new AuthoringError({
|
|
345
|
+
message: `bytes width must be an integer in 1..=64 (got ${width}) — the range is pinned at declaration`
|
|
346
|
+
})
|
|
254
347
|
}
|
|
255
348
|
return Object.freeze({ kind: "bytes", width })
|
|
256
349
|
}
|
|
257
350
|
|
|
258
|
-
function interval<Element extends U64Field | I64Field
|
|
351
|
+
function interval<Element extends U64Field | I64Field | F64Field>(
|
|
352
|
+
element: Element
|
|
353
|
+
): IntervalField<Element["kind"], undefined>
|
|
259
354
|
function interval<Element extends U64Field | I64Field, const Width extends bigint>(
|
|
260
355
|
element: Element,
|
|
261
356
|
width: Width
|
|
262
357
|
): IntervalField<Element["kind"], Width>
|
|
263
|
-
function interval(
|
|
358
|
+
function interval(
|
|
359
|
+
element: U64Field | I64Field | F64Field,
|
|
360
|
+
width?: bigint
|
|
361
|
+
): IntervalField<IntervalElementKind, bigint | undefined> {
|
|
264
362
|
const elementKind = element.kind
|
|
265
|
-
if (elementKind !== "u64" && elementKind !== "i64") {
|
|
266
|
-
throw
|
|
363
|
+
if (elementKind !== "u64" && elementKind !== "i64" && elementKind !== "f64") {
|
|
364
|
+
throw new AuthoringError({
|
|
365
|
+
message: `interval element must be the u64, i64 or f64 field constructor (got ${elementKind})`
|
|
366
|
+
})
|
|
367
|
+
}
|
|
368
|
+
if (width !== undefined && elementKind === "f64") {
|
|
369
|
+
throw new AuthoringError({
|
|
370
|
+
message:
|
|
371
|
+
"interval(f64) takes no width — a fixed-width float interval is unrepresentable (rounded start + width is not an exact fixed length on the dense line); applications supply two checked bounds"
|
|
372
|
+
})
|
|
267
373
|
}
|
|
268
374
|
if (width !== undefined && width < 1n) {
|
|
269
|
-
throw
|
|
375
|
+
throw new AuthoringError({
|
|
376
|
+
message: `interval width must be >= 1 (got ${width}) — w >= 1 is pinned at declaration`
|
|
377
|
+
})
|
|
270
378
|
}
|
|
271
379
|
return Object.freeze({ kind: "interval", element: elementKind, width })
|
|
272
380
|
}
|
|
@@ -305,6 +413,18 @@ function literalOf(field: AnyField, value: unknown): LiteralSpec {
|
|
|
305
413
|
}
|
|
306
414
|
return { kind: "value", value: { kind: "string", value } }
|
|
307
415
|
}
|
|
416
|
+
case "f64": {
|
|
417
|
+
if (typeof value !== "number") {
|
|
418
|
+
throw literalShapeError("selection literal", "number", value)
|
|
419
|
+
}
|
|
420
|
+
return { kind: "value", value: { kind: "f64", value } }
|
|
421
|
+
}
|
|
422
|
+
case "uuid": {
|
|
423
|
+
if (!Uuid.isUuid(value)) {
|
|
424
|
+
throw literalShapeError("selection literal", "a UUID (canonical UUID text)", value)
|
|
425
|
+
}
|
|
426
|
+
return { kind: "value", value: { kind: "uuid", value } }
|
|
427
|
+
}
|
|
308
428
|
case "bytes": {
|
|
309
429
|
if (!(value instanceof Uint8Array)) {
|
|
310
430
|
throw literalShapeError("selection literal", "Uint8Array", value)
|
|
@@ -325,22 +445,27 @@ export type {
|
|
|
325
445
|
ClosedHandleTuple,
|
|
326
446
|
ClosedIdField,
|
|
327
447
|
ClosedRoster,
|
|
328
|
-
|
|
448
|
+
F64Field,
|
|
449
|
+
FloatIntervalValue,
|
|
329
450
|
I64Field,
|
|
330
451
|
Infer,
|
|
452
|
+
IntervalElementKind,
|
|
331
453
|
IntervalField,
|
|
332
454
|
IntervalValue,
|
|
333
455
|
SignatureOf,
|
|
334
456
|
StrField,
|
|
335
|
-
U64Field
|
|
457
|
+
U64Field,
|
|
458
|
+
UuidField
|
|
336
459
|
}
|
|
337
460
|
export {
|
|
338
461
|
assertDeclarationOrderKey,
|
|
339
462
|
assertDeclarationRecord,
|
|
340
463
|
bool,
|
|
341
464
|
bytes,
|
|
465
|
+
f64,
|
|
342
466
|
i64,
|
|
343
467
|
interval,
|
|
468
|
+
isFloatIntervalValue,
|
|
344
469
|
isIntervalValue,
|
|
345
470
|
literalOf,
|
|
346
471
|
literalShapeError,
|
|
@@ -349,5 +474,6 @@ export {
|
|
|
349
474
|
signaturesAgree,
|
|
350
475
|
span,
|
|
351
476
|
str,
|
|
352
|
-
u64
|
|
477
|
+
u64,
|
|
478
|
+
uuid
|
|
353
479
|
}
|