@libredb/libredb 0.0.2 → 0.0.3

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/README.md CHANGED
@@ -272,6 +272,18 @@ registry.get("logs");
272
272
 
273
273
  The catalog lives under a reserved key prefix that sorts below all user data, so its entries never appear in a `kv`, `doc`, or `table` scan — and no user row leaks into the registry. `kv` namespaces are deliberately not cataloged: `kv` is the raw layer with full keyspace access.
274
274
 
275
+ A tool that renders the raw `kv` layer (so it sees everything, including the catalog) should hide those engine-internal keys. Rather than hardcode the byte layout, import the contract: `isReservedKey(key)` is true for any key in the reserved namespace, and `RESERVED_MARKER` / `CATALOG_PREFIX` are the underlying constants if you need to build a range.
276
+
277
+ ```ts
278
+ import { open, kv, isReservedKey } from "libredb";
279
+
280
+ const db = open();
281
+ // ... user writes through doc/table, which also write catalog entries ...
282
+
283
+ const visible = kv(db).range("", "￿").toArray().filter((e) => !isReservedKey(e.key));
284
+ // only user keys; catalog entries (under the reserved marker) are filtered out
285
+ ```
286
+
275
287
  ## Reliability — deterministic simulation testing
276
288
 
277
289
  Durability is the trust-critical promise: a transaction that returns has been fsync'd, and a crash can only ever damage the last, un-fsync'd record. LibreDB proves this with **deterministic simulation testing (DST)** — the WAL's crash/recovery path is tortured under a seeded, in-memory simulated filesystem. The kernel reaches the disk only through an injectable FS seam (`open({ path, fs })`), so a test can run the real engine on a `SimFS` that crashes on command, tears the un-fsync'd tail at a seeded point, and injects CRC corruption or short reads.
package/dist/core.d.ts CHANGED
@@ -20,7 +20,7 @@
20
20
  * and discards any record a crash left half-written.
21
21
  */
22
22
  /** The LibreDB package version. Kept in sync with package.json. */
23
- export declare const version = "0.0.2";
23
+ export declare const version = "0.0.3";
24
24
  /**
25
25
  * A key in the kernel: an immutable sequence of bytes.
26
26
  *
package/dist/core.js CHANGED
@@ -21,7 +21,7 @@
21
21
  */
22
22
  import { closeSync, fsyncSync, openSync, readFileSync, statSync, truncateSync, writeSync, } from "node:fs";
23
23
  /** The LibreDB package version. Kept in sync with package.json. */
24
- export const version = "0.0.2";
24
+ export const version = "0.0.3";
25
25
  /**
26
26
  * Compare two keys by unsigned byte-lexicographic order: the first differing
27
27
  * byte decides, and if one key is a prefix of the other the shorter sorts
package/dist/index.d.ts CHANGED
@@ -6,7 +6,9 @@
6
6
  * documents). The kernel's byte-level internals (and each lens's private codec)
7
7
  * stay unexported on purpose — the lens is the usable face. The relational lens
8
8
  * ({@link table}) completes the trio. {@link catalog} reads the registry of
9
- * namespaces a database holds, so a tool can render faithful per-kind views.
9
+ * namespaces a database holds, so a tool can render faithful per-kind views;
10
+ * {@link isReservedKey} (with {@link RESERVED_MARKER} / {@link CATALOG_PREFIX})
11
+ * lets a raw-KV tool hide engine-internal keys instead of hardcoding the layout.
10
12
  */
11
13
  export { version, open } from "./core.ts";
12
14
  export type { Database, OpenOptions } from "./core.ts";
@@ -16,6 +18,6 @@ export { doc } from "./lens/document.ts";
16
18
  export type { DocCollection, Doc, DocEntry, JsonValue } from "./lens/document.ts";
17
19
  export { table } from "./lens/relational.ts";
18
20
  export type { Table, TableSchema, Row, ColumnType, Query } from "./lens/relational.ts";
19
- export { catalog } from "./lens/catalog.ts";
21
+ export { catalog, isReservedKey, CATALOG_PREFIX, RESERVED_MARKER } from "./lens/catalog.ts";
20
22
  export type { CatalogEntry, CatalogRegistry } from "./lens/catalog.ts";
21
23
  export type { Result, WriteResult } from "./lens/types.ts";
package/dist/index.js CHANGED
@@ -6,10 +6,12 @@
6
6
  * documents). The kernel's byte-level internals (and each lens's private codec)
7
7
  * stay unexported on purpose — the lens is the usable face. The relational lens
8
8
  * ({@link table}) completes the trio. {@link catalog} reads the registry of
9
- * namespaces a database holds, so a tool can render faithful per-kind views.
9
+ * namespaces a database holds, so a tool can render faithful per-kind views;
10
+ * {@link isReservedKey} (with {@link RESERVED_MARKER} / {@link CATALOG_PREFIX})
11
+ * lets a raw-KV tool hide engine-internal keys instead of hardcoding the layout.
10
12
  */
11
13
  export { version, open } from "./core.js";
12
14
  export { kv } from "./lens/kv.js";
13
15
  export { doc } from "./lens/document.js";
14
16
  export { table } from "./lens/relational.js";
15
- export { catalog } from "./lens/catalog.js";
17
+ export { catalog, isReservedKey, CATALOG_PREFIX, RESERVED_MARKER } from "./lens/catalog.js";
@@ -27,6 +27,19 @@ export declare const CATALOG_PREFIX = "\0libredb:catalog:";
27
27
  * layer with full keyspace access (DESIGN.md section 6.3).
28
28
  */
29
29
  export declare function assertUserName(name: string): void;
30
+ /**
31
+ * Whether `key` lies in LibreDB's reserved internal namespace — that is, whether
32
+ * it begins with the {@link RESERVED_MARKER}. This is the public contract a tool
33
+ * that renders RAW key-value data (e.g. the LibreDB Studio provider) uses to HIDE
34
+ * engine-internal keys: the catalog today, and any further reserved sub-namespace
35
+ * added under the marker later. Testing the marker rather than the specific
36
+ * {@link CATALOG_PREFIX} is deliberate — a tool that depends on this stays correct
37
+ * if the reserved namespace grows, so it never has to track the byte layout.
38
+ *
39
+ * {@link assertUserName} guarantees no user namespace name begins with the marker,
40
+ * so this predicate partitions reserved keys from user keys with no overlap.
41
+ */
42
+ export declare function isReservedKey(key: string): boolean;
30
43
  /**
31
44
  * The lens a cataloged namespace belongs to, plus (for a relational table) its
32
45
  * schema — the otherwise-unrecoverable interpretation a cold-opening tool needs
@@ -52,6 +52,21 @@ export function assertUserName(name) {
52
52
  throw new Error(`libredb: namespace name ${JSON.stringify(name)} may not start with the reserved catalog marker (U+0000)`);
53
53
  }
54
54
  }
55
+ /**
56
+ * Whether `key` lies in LibreDB's reserved internal namespace — that is, whether
57
+ * it begins with the {@link RESERVED_MARKER}. This is the public contract a tool
58
+ * that renders RAW key-value data (e.g. the LibreDB Studio provider) uses to HIDE
59
+ * engine-internal keys: the catalog today, and any further reserved sub-namespace
60
+ * added under the marker later. Testing the marker rather than the specific
61
+ * {@link CATALOG_PREFIX} is deliberate — a tool that depends on this stays correct
62
+ * if the reserved namespace grows, so it never has to track the byte layout.
63
+ *
64
+ * {@link assertUserName} guarantees no user namespace name begins with the marker,
65
+ * so this predicate partitions reserved keys from user keys with no overlap.
66
+ */
67
+ export function isReservedKey(key) {
68
+ return key.startsWith(RESERVED_MARKER);
69
+ }
55
70
  const utf8 = new TextEncoder();
56
71
  const fromUtf8 = new TextDecoder();
57
72
  /** The kernel key for one namespace's catalog entry: the reserved prefix plus
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@libredb/libredb",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "A small, readable, embeddable, multi-model database. One ordered key-value core, thin model lenses on top.",
5
5
  "type": "module",
6
6
  "license": "MIT",