@libredb/libredb 0.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/LICENSE +21 -0
- package/README.md +259 -0
- package/dist/adapter/store.d.ts +32 -0
- package/dist/adapter/store.d.ts.map +1 -0
- package/dist/adapter/store.js +2 -0
- package/dist/adapter/store.js.map +1 -0
- package/dist/core.d.ts +111 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +343 -0
- package/dist/core.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/lens/document.d.ts +104 -0
- package/dist/lens/document.d.ts.map +1 -0
- package/dist/lens/document.js +152 -0
- package/dist/lens/document.js.map +1 -0
- package/dist/lens/kv.d.ts +59 -0
- package/dist/lens/kv.d.ts.map +1 -0
- package/dist/lens/kv.js +87 -0
- package/dist/lens/kv.js.map +1 -0
- package/dist/lens/relational.d.ts +119 -0
- package/dist/lens/relational.d.ts.map +1 -0
- package/dist/lens/relational.js +213 -0
- package/dist/lens/relational.js.map +1 -0
- package/dist/lens/types.d.ts +58 -0
- package/dist/lens/types.d.ts.map +1 -0
- package/dist/lens/types.js +35 -0
- package/dist/lens/types.js.map +1 -0
- package/dist/query/range.d.ts +44 -0
- package/dist/query/range.d.ts.map +1 -0
- package/dist/query/range.js +60 -0
- package/dist/query/range.js.map +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* query/range.ts — the minimal query surface for the key-value lens.
|
|
3
|
+
*
|
|
4
|
+
* This is an edge, not the kernel (DESIGN.md section 5): the open,
|
|
5
|
+
* fast-contribution tier, holding no durability logic. It is deliberately thin
|
|
6
|
+
* — one inspectable value and the single piece of query logic the KV lens lacks.
|
|
7
|
+
*
|
|
8
|
+
* The kernel's native query is a range scan over its ordered keyspace, and the
|
|
9
|
+
* lens already exposes an explicit `[start, end)`. The one ordered-KV query that
|
|
10
|
+
* is both ubiquitous and easy to get wrong is the PREFIX scan ("every key under
|
|
11
|
+
* `user:`"). Its only subtlety is the exclusive upper bound, and the naive
|
|
12
|
+
* string trick (`prefix + ""`) is unsound here: the kernel sorts by
|
|
13
|
+
* unsigned BYTE order, not UTF-16 code units, and the two disagree above U+FFFF.
|
|
14
|
+
* So this module computes the bound on raw bytes, where it agrees with the
|
|
15
|
+
* kernel by construction. Working in bytes also keeps the surface shared: the
|
|
16
|
+
* document and relational lenses plan ranges over the same byte keyspace.
|
|
17
|
+
*
|
|
18
|
+
* A {@link KeyRange} is a plain value, not a builder: the query is visible
|
|
19
|
+
* (DESIGN.md principle 2 — query visible by default), so a caller can inspect
|
|
20
|
+
* the exact bounds a scan will use before running it.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* A half-open key range `[start, end)`: `start` is included, `end` is excluded
|
|
24
|
+
* — the exact contract of the kernel's
|
|
25
|
+
* {@link import("../core.ts").Transaction.getRange}. Bounds are raw bytes, the
|
|
26
|
+
* unit the kernel orders on.
|
|
27
|
+
*/
|
|
28
|
+
export interface KeyRange {
|
|
29
|
+
readonly start: Uint8Array;
|
|
30
|
+
readonly end: Uint8Array;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The half-open byte range that selects exactly the keys beginning with
|
|
34
|
+
* `prefix`: `[prefix, upperBound(prefix))`. The start is the prefix itself; the
|
|
35
|
+
* end is the smallest key that no longer carries the prefix (see
|
|
36
|
+
* {@link upperBound}).
|
|
37
|
+
*
|
|
38
|
+
* Throws if `prefix` has no finite upper bound — it is empty, or every byte is
|
|
39
|
+
* already `0xFF`. In that case no `end` key can exclude the next sibling, so a
|
|
40
|
+
* half-open range cannot express the scan; rejecting it loudly is honest
|
|
41
|
+
* (DESIGN.md principle 2) where silently scanning the wrong range would not be.
|
|
42
|
+
*/
|
|
43
|
+
export declare function prefixRange(prefix: Uint8Array): KeyRange;
|
|
44
|
+
//# sourceMappingURL=range.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"range.d.ts","sourceRoot":"","sources":["../../src/query/range.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;CAC1B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,QAAQ,CAMxD"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* query/range.ts — the minimal query surface for the key-value lens.
|
|
3
|
+
*
|
|
4
|
+
* This is an edge, not the kernel (DESIGN.md section 5): the open,
|
|
5
|
+
* fast-contribution tier, holding no durability logic. It is deliberately thin
|
|
6
|
+
* — one inspectable value and the single piece of query logic the KV lens lacks.
|
|
7
|
+
*
|
|
8
|
+
* The kernel's native query is a range scan over its ordered keyspace, and the
|
|
9
|
+
* lens already exposes an explicit `[start, end)`. The one ordered-KV query that
|
|
10
|
+
* is both ubiquitous and easy to get wrong is the PREFIX scan ("every key under
|
|
11
|
+
* `user:`"). Its only subtlety is the exclusive upper bound, and the naive
|
|
12
|
+
* string trick (`prefix + ""`) is unsound here: the kernel sorts by
|
|
13
|
+
* unsigned BYTE order, not UTF-16 code units, and the two disagree above U+FFFF.
|
|
14
|
+
* So this module computes the bound on raw bytes, where it agrees with the
|
|
15
|
+
* kernel by construction. Working in bytes also keeps the surface shared: the
|
|
16
|
+
* document and relational lenses plan ranges over the same byte keyspace.
|
|
17
|
+
*
|
|
18
|
+
* A {@link KeyRange} is a plain value, not a builder: the query is visible
|
|
19
|
+
* (DESIGN.md principle 2 — query visible by default), so a caller can inspect
|
|
20
|
+
* the exact bounds a scan will use before running it.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* The half-open byte range that selects exactly the keys beginning with
|
|
24
|
+
* `prefix`: `[prefix, upperBound(prefix))`. The start is the prefix itself; the
|
|
25
|
+
* end is the smallest key that no longer carries the prefix (see
|
|
26
|
+
* {@link upperBound}).
|
|
27
|
+
*
|
|
28
|
+
* Throws if `prefix` has no finite upper bound — it is empty, or every byte is
|
|
29
|
+
* already `0xFF`. In that case no `end` key can exclude the next sibling, so a
|
|
30
|
+
* half-open range cannot express the scan; rejecting it loudly is honest
|
|
31
|
+
* (DESIGN.md principle 2) where silently scanning the wrong range would not be.
|
|
32
|
+
*/
|
|
33
|
+
export function prefixRange(prefix) {
|
|
34
|
+
const end = upperBound(prefix);
|
|
35
|
+
if (end === undefined) {
|
|
36
|
+
throw new Error("libredb: prefix has no finite upper bound (empty or all-0xFF)");
|
|
37
|
+
}
|
|
38
|
+
return { start: prefix, end };
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The smallest key strictly greater than every key beginning with `prefix`:
|
|
42
|
+
* drop the trailing `0xFF` bytes (they are already maximal and cannot be
|
|
43
|
+
* incremented), then add one to the last remaining byte. Returns `undefined`
|
|
44
|
+
* when no such key exists — the prefix is empty, or all of its bytes are `0xFF`.
|
|
45
|
+
*
|
|
46
|
+
* Computed on raw bytes so the result agrees with the kernel's unsigned
|
|
47
|
+
* byte-lexicographic order. A dropped trailing `0xFF` is why the bound can be
|
|
48
|
+
* shorter than the prefix (e.g. `[0x61, 0xFF]` yields `[0x62]`).
|
|
49
|
+
*/
|
|
50
|
+
function upperBound(prefix) {
|
|
51
|
+
let length = prefix.length;
|
|
52
|
+
while (length > 0 && prefix[length - 1] === 0xff)
|
|
53
|
+
length--;
|
|
54
|
+
if (length === 0)
|
|
55
|
+
return undefined;
|
|
56
|
+
const bound = prefix.slice(0, length);
|
|
57
|
+
bound[length - 1] = bound[length - 1] + 1;
|
|
58
|
+
return bound;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=range.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"range.js","sourceRoot":"","sources":["../../src/query/range.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAaH;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CAAC,MAAkB;IAC5C,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAC/B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACnF,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AAChC,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,UAAU,CAAC,MAAkB;IACpC,IAAI,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC3B,OAAO,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,IAAI;QAAE,MAAM,EAAE,CAAC;IAC3D,IAAI,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACnC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACtC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAY,GAAG,CAAC,CAAC;IACtD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@libredb/libredb",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "A small, readable, embeddable, multi-model database. One ordered key-value core, thin model lenses on top.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"main": "./dist/index.js",
|
|
14
|
+
"module": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"import": "./dist/index.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"engines": {
|
|
23
|
+
"bun": ">=1.3.0"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"typecheck": "tsc --noEmit",
|
|
27
|
+
"lint": "eslint .",
|
|
28
|
+
"test": "bun test --coverage",
|
|
29
|
+
"build": "tsc --project tsconfig.build.json",
|
|
30
|
+
"gate": "bun run typecheck && bun run lint && bun run test && bun run build"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@eslint/js": "^9.0.0",
|
|
34
|
+
"@types/bun": "latest",
|
|
35
|
+
"eslint": "^9.0.0",
|
|
36
|
+
"typescript": "^5.4.0",
|
|
37
|
+
"typescript-eslint": "^8.0.0"
|
|
38
|
+
}
|
|
39
|
+
}
|