@bjornpagen/bumbledb 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +12 -0
- package/README.md +84 -0
- package/dist/brand.d.ts +59 -0
- package/dist/brand.d.ts.map +1 -0
- package/dist/brand.js +47 -0
- package/dist/brand.js.map +1 -0
- package/dist/closed.d.ts +97 -0
- package/dist/closed.d.ts.map +1 -0
- package/dist/closed.js +107 -0
- package/dist/closed.js.map +1 -0
- package/dist/count.d.ts +55 -0
- package/dist/count.d.ts.map +1 -0
- package/dist/count.js +92 -0
- package/dist/count.js.map +1 -0
- package/dist/db.d.ts +341 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +1016 -0
- package/dist/db.js.map +1 -0
- package/dist/exhume.d.ts +130 -0
- package/dist/exhume.d.ts.map +1 -0
- package/dist/exhume.js +145 -0
- package/dist/exhume.js.map +1 -0
- package/dist/face.d.ts +91 -0
- package/dist/face.d.ts.map +1 -0
- package/dist/face.js +69 -0
- package/dist/face.js.map +1 -0
- package/dist/fields.d.ts +187 -0
- package/dist/fields.d.ts.map +1 -0
- package/dist/fields.js +204 -0
- package/dist/fields.js.map +1 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/lower.d.ts +34 -0
- package/dist/lower.d.ts.map +1 -0
- package/dist/lower.js +105 -0
- package/dist/lower.js.map +1 -0
- package/dist/marshal.d.ts +79 -0
- package/dist/marshal.d.ts.map +1 -0
- package/dist/marshal.js +167 -0
- package/dist/marshal.js.map +1 -0
- package/dist/native.d.ts +532 -0
- package/dist/native.d.ts.map +1 -0
- package/dist/native.js +64 -0
- package/dist/native.js.map +1 -0
- package/dist/query/atom.d.ts +285 -0
- package/dist/query/atom.d.ts.map +1 -0
- package/dist/query/atom.js +281 -0
- package/dist/query/atom.js.map +1 -0
- package/dist/query/lower.d.ts +145 -0
- package/dist/query/lower.d.ts.map +1 -0
- package/dist/query/lower.js +604 -0
- package/dist/query/lower.js.map +1 -0
- package/dist/query/predicate.d.ts +101 -0
- package/dist/query/predicate.d.ts.map +1 -0
- package/dist/query/predicate.js +85 -0
- package/dist/query/predicate.js.map +1 -0
- package/dist/query/run.d.ts +30 -0
- package/dist/query/run.d.ts.map +1 -0
- package/dist/query/run.js +94 -0
- package/dist/query/run.js.map +1 -0
- package/dist/query/scope.d.ts +168 -0
- package/dist/query/scope.d.ts.map +1 -0
- package/dist/query/scope.js +134 -0
- package/dist/query/scope.js.map +1 -0
- package/dist/query/select.d.ts +106 -0
- package/dist/query/select.d.ts.map +1 -0
- package/dist/query/select.js +69 -0
- package/dist/query/select.js.map +1 -0
- package/dist/relation.d.ts +120 -0
- package/dist/relation.d.ts.map +1 -0
- package/dist/relation.js +108 -0
- package/dist/relation.js.map +1 -0
- package/dist/schema.d.ts +50 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +235 -0
- package/dist/schema.js.map +1 -0
- package/dist/spec.d.ts +218 -0
- package/dist/spec.d.ts.map +1 -0
- package/dist/spec.js +154 -0
- package/dist/spec.js.map +1 -0
- package/dist/statements.d.ts +91 -0
- package/dist/statements.d.ts.map +1 -0
- package/dist/statements.js +101 -0
- package/dist/statements.js.map +1 -0
- package/package.json +66 -0
- package/src/brand.ts +82 -0
- package/src/closed.ts +228 -0
- package/src/count.ts +117 -0
- package/src/db.ts +1519 -0
- package/src/exhume.ts +243 -0
- package/src/face.ts +161 -0
- package/src/fields.ts +385 -0
- package/src/index.ts +185 -0
- package/src/lower.ts +118 -0
- package/src/marshal.ts +220 -0
- package/src/native.ts +576 -0
- package/src/query/atom.ts +556 -0
- package/src/query/lower.ts +855 -0
- package/src/query/predicate.ts +195 -0
- package/src/query/run.ts +106 -0
- package/src/query/scope.ts +301 -0
- package/src/query/select.ts +140 -0
- package/src/relation.ts +252 -0
- package/src/schema.ts +297 -0
- package/src/spec.ts +325 -0
- package/src/statements.ts +148 -0
package/src/count.ts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cardinality-window counts — exactly five constructors, and nothing else
|
|
3
|
+
* (`docs/architecture/70-api.md` § the canonical-utterance law). The ban
|
|
4
|
+
* table is enforced REPRESENTATIONALLY, stronger than Rust's expansion
|
|
5
|
+
* errors: `{1..*}`, `{n..n}`, `{0..0}`, `{0..*}`, and inverted windows have
|
|
6
|
+
* NO constructor — the spellings that could produce them are construction
|
|
7
|
+
* errors naming the canonical form, and no other spelling exists at all.
|
|
8
|
+
* Bounds are `bigint` (u64 crosses as bigint always, PRD-04's law).
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import * as errors from "@superbuilders/errors"
|
|
12
|
+
import type { WindowSpec } from "#spec.ts"
|
|
13
|
+
|
|
14
|
+
/** The exclusion's one spelling, shared by `none`. */
|
|
15
|
+
const exclusion: WindowSpec = Object.freeze({ kind: "exact", n: 0n })
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The admission brand — a module-private symbol, deliberately unexported:
|
|
19
|
+
* `WindowSpec` is a public wire type, so without this brand every banned
|
|
20
|
+
* spelling in the ban table would be writable as a plain object literal
|
|
21
|
+
* (`{ window: { kind: "floor", lo: 1n } }` typechecks structurally). The
|
|
22
|
+
* symbol makes the five constructors the ONLY producers of a `Count`
|
|
23
|
+
* value, which is what "the ban table is unwritable" means.
|
|
24
|
+
*/
|
|
25
|
+
const admitted: unique symbol = Symbol("bumbledb.count.admitted")
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* An admitted window count — opaque and inert: a fact about the theory,
|
|
29
|
+
* not a builder. Only the five constructors below produce one (the
|
|
30
|
+
* module-private {@link admitted} brand forecloses structural literals).
|
|
31
|
+
*/
|
|
32
|
+
interface Count {
|
|
33
|
+
readonly window: WindowSpec
|
|
34
|
+
readonly [admitted]: true
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Stamps one admitted window as a frozen `Count` value. */
|
|
38
|
+
function admit(window: WindowSpec): Count {
|
|
39
|
+
return Object.freeze({ window, [admitted]: true as const })
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* `{n}` — THE exact-count spelling, n ≥ 1. `exactly(0)` is the exclusion
|
|
44
|
+
* respelled and rejected naming `none`.
|
|
45
|
+
*/
|
|
46
|
+
function exactly(n: bigint): Count {
|
|
47
|
+
if (n < 0n) {
|
|
48
|
+
throw errors.new(`window counts are u64: exactly(${n}) is out of domain`)
|
|
49
|
+
}
|
|
50
|
+
if (n === 0n) {
|
|
51
|
+
throw errors.new("`{0..0}`-shaped spelling: the exclusion is written `{0}` — use none")
|
|
52
|
+
}
|
|
53
|
+
return admit(Object.freeze({ kind: "exact", n }))
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** `{0}` — the exclusion: no source fact may pair with the target group. */
|
|
57
|
+
const none: Count = admit(exclusion)
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* `{lo..hi}` — both bounds explicit, 0 ≤ lo < hi. `lo === hi` is the exact
|
|
61
|
+
* count respelled (rejected naming `exactly(n)`, or `none` at 0); an
|
|
62
|
+
* inverted window is unsatisfiable and rejected.
|
|
63
|
+
*/
|
|
64
|
+
function between(lo: bigint, hi: bigint): Count {
|
|
65
|
+
if (lo < 0n || hi < 0n) {
|
|
66
|
+
throw errors.new(`window counts are u64: between(${lo}, ${hi}) is out of domain`)
|
|
67
|
+
}
|
|
68
|
+
if (hi < lo) {
|
|
69
|
+
throw errors.new(
|
|
70
|
+
`the window \`{${lo}..${hi}}\` is inverted — no count satisfies it; bounds are \`{lo..hi}\` with lo < hi (an exact count is \`{n}\`: exactly(n))`
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
if (lo === hi) {
|
|
74
|
+
if (lo === 0n) {
|
|
75
|
+
throw errors.new("`{0..0}` — the exclusion is written `{0}`: use none")
|
|
76
|
+
}
|
|
77
|
+
throw errors.new(`\`{${lo}..${lo}}\` — an exact count is written \`{${lo}}\`: use exactly(${lo})`)
|
|
78
|
+
}
|
|
79
|
+
return admit(Object.freeze({ kind: "range", lo, hi }))
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* `{lo..*}` — a floor with no ceiling, lo ≥ 2: `atLeast(1)` says only what
|
|
84
|
+
* the bare containment says (rejected naming `contained`), and
|
|
85
|
+
* `atLeast(0)` is vacuous (rejected naming deletion).
|
|
86
|
+
*/
|
|
87
|
+
function atLeast(lo: bigint): Count {
|
|
88
|
+
if (lo < 0n) {
|
|
89
|
+
throw errors.new(`window counts are u64: atLeast(${lo}) is out of domain`)
|
|
90
|
+
}
|
|
91
|
+
if (lo === 0n) {
|
|
92
|
+
throw errors.new("the `{0..*}` window is vacuous — it provably says nothing; delete the statement")
|
|
93
|
+
}
|
|
94
|
+
if (lo === 1n) {
|
|
95
|
+
throw errors.new(
|
|
96
|
+
"`{1..*}` says only what the bare containment says — drop the annotation and write the containment: contained(source, target)"
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
return admit(Object.freeze({ kind: "floor", lo }))
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* `{0..hi}` — a ceiling, hi ≥ 1: `atMost(0)` is the exclusion respelled
|
|
104
|
+
* and rejected naming `none`.
|
|
105
|
+
*/
|
|
106
|
+
function atMost(hi: bigint): Count {
|
|
107
|
+
if (hi < 0n) {
|
|
108
|
+
throw errors.new(`window counts are u64: atMost(${hi}) is out of domain`)
|
|
109
|
+
}
|
|
110
|
+
if (hi === 0n) {
|
|
111
|
+
throw errors.new("`{0..0}` — the exclusion is written `{0}`: use none")
|
|
112
|
+
}
|
|
113
|
+
return admit(Object.freeze({ kind: "range", lo: 0n, hi }))
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export type { Count }
|
|
117
|
+
export { atLeast, atMost, between, exactly, none }
|