@tensorix/metahub 0.1.9 → 0.1.11
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 +19 -6
- package/README.zh-CN.md +7 -2
- package/dist/cli.js +4130 -2200
- package/dist/cli.js.map +54 -46
- package/dist/core/compact.d.ts +42 -0
- package/dist/core/compact.d.ts.map +1 -0
- package/dist/core/config.d.ts +3 -3
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/context.d.ts +4 -4
- package/dist/core/context.d.ts.map +1 -1
- package/dist/core/crdt.d.ts +30 -7
- package/dist/core/crdt.d.ts.map +1 -1
- package/dist/core/databases.d.ts +22 -8
- package/dist/core/databases.d.ts.map +1 -1
- package/dist/core/db.d.ts +1 -27
- package/dist/core/db.d.ts.map +1 -1
- package/dist/core/documents.d.ts +30 -15
- package/dist/core/documents.d.ts.map +1 -1
- package/dist/core/driver.d.ts +25 -0
- package/dist/core/driver.d.ts.map +1 -0
- package/dist/core/errors.d.ts +32 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/history.d.ts +174 -0
- package/dist/core/history.d.ts.map +1 -0
- package/dist/core/hlc.d.ts +3 -3
- package/dist/core/hlc.d.ts.map +1 -1
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/indexing.d.ts +4 -4
- package/dist/core/indexing.d.ts.map +1 -1
- package/dist/core/integrity.d.ts +1 -1
- package/dist/core/integrity.d.ts.map +1 -1
- package/dist/core/node.d.ts +2 -2
- package/dist/core/node.d.ts.map +1 -1
- package/dist/core/properties.d.ts +10 -9
- package/dist/core/properties.d.ts.map +1 -1
- package/dist/core/records.d.ts +13 -8
- package/dist/core/records.d.ts.map +1 -1
- package/dist/core/resolve.d.ts +4 -4
- package/dist/core/resolve.d.ts.map +1 -1
- package/dist/core/schema-init.d.ts +37 -0
- package/dist/core/schema-init.d.ts.map +1 -0
- package/dist/core/schema.d.ts +1 -1
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/search.d.ts +3 -3
- package/dist/core/search.d.ts.map +1 -1
- package/dist/core/sites-core.d.ts +60 -0
- package/dist/core/sites-core.d.ts.map +1 -0
- package/dist/core/sites.d.ts +11 -52
- package/dist/core/sites.d.ts.map +1 -1
- package/dist/core/snapshot.d.ts.map +1 -1
- package/dist/core/sqlcols.d.ts +4 -0
- package/dist/core/sqlcols.d.ts.map +1 -0
- package/dist/core/sync/auth.d.ts +5 -3
- package/dist/core/sync/auth.d.ts.map +1 -1
- package/dist/core/sync/client.d.ts +11 -3
- package/dist/core/sync/client.d.ts.map +1 -1
- package/dist/core/sync/files.d.ts.map +1 -1
- package/dist/core/sync/openapi.d.ts +5 -2
- package/dist/core/sync/openapi.d.ts.map +1 -1
- package/dist/core/sync/pairing.d.ts.map +1 -1
- package/dist/core/sync/peers-routes.d.ts +1 -1
- package/dist/core/sync/peers-routes.d.ts.map +1 -1
- package/dist/core/sync/peers.d.ts +10 -10
- package/dist/core/sync/peers.d.ts.map +1 -1
- package/dist/core/sync/protocol.d.ts +5 -0
- package/dist/core/sync/protocol.d.ts.map +1 -1
- package/dist/core/sync/routes.d.ts +4 -0
- package/dist/core/sync/routes.d.ts.map +1 -1
- package/dist/core/sync/server.d.ts +24 -1
- package/dist/core/sync/server.d.ts.map +1 -1
- package/dist/core/sync/sites-routes.d.ts +1 -1
- package/dist/core/sync/sites-routes.d.ts.map +1 -1
- package/dist/db-worker.js +268 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3254 -1865
- package/dist/index.js.map +36 -31
- package/dist/metahub-sdk.js +1 -0
- package/dist/mh-runtime.js +1 -0
- package/dist/sqlite3.wasm +0 -0
- package/dist/sw.js +1 -0
- package/dist/{core/sync/webui.d.ts → webui/server/assets.d.ts} +9 -6
- package/dist/webui/server/assets.d.ts.map +1 -0
- package/dist/webui/server/icons.d.ts +4 -0
- package/dist/webui/server/icons.d.ts.map +1 -0
- package/dist/webui/server/routes.d.ts +3 -0
- package/dist/webui/server/routes.d.ts.map +1 -0
- package/dist/webui.js +57 -57
- package/package.json +3 -1
- package/dist/core/sync/webui-routes.d.ts +0 -3
- package/dist/core/sync/webui-routes.d.ts.map +0 -1
- package/dist/core/sync/webui.d.ts.map +0 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite";
|
|
2
|
+
export interface CompactResult {
|
|
3
|
+
/** HLC cutoff actually used — history at or before this collapses to a baseline. */
|
|
4
|
+
cutoff: string;
|
|
5
|
+
deleted_changes: number;
|
|
6
|
+
kept_changes: number;
|
|
7
|
+
blobs_deleted: number;
|
|
8
|
+
blob_bytes_freed: number;
|
|
9
|
+
db_bytes_before: number;
|
|
10
|
+
db_bytes_after: number;
|
|
11
|
+
dry_run: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface CompactOptions {
|
|
14
|
+
/** Keep full history for this many days; 0 keeps only the head state. */
|
|
15
|
+
keepDays: number;
|
|
16
|
+
/** Report what would be removed without changing anything. */
|
|
17
|
+
dryRun?: boolean;
|
|
18
|
+
/** Run VACUUM afterwards to return the freed pages to the filesystem. */
|
|
19
|
+
vacuum?: boolean;
|
|
20
|
+
/** Test hook: "now" in epoch millis. */
|
|
21
|
+
now?: number;
|
|
22
|
+
}
|
|
23
|
+
export declare function compactOplog(db: Database, opts: CompactOptions): CompactResult;
|
|
24
|
+
/**
|
|
25
|
+
* Delete cache blobs no longer referenced by any remaining oplog value or
|
|
26
|
+
* materialized site file. Conservative: only files named like a sha256 hash
|
|
27
|
+
* are candidates; anything else in the cache dir is left alone.
|
|
28
|
+
*/
|
|
29
|
+
export declare function gcBlobs(db: Database, opts?: {
|
|
30
|
+
dryRun?: boolean;
|
|
31
|
+
}): {
|
|
32
|
+
deleted: number;
|
|
33
|
+
bytes: number;
|
|
34
|
+
};
|
|
35
|
+
/** Dry-run quick stats for doctor: total oplog rows and how many compaction
|
|
36
|
+
* with the given window would remove. */
|
|
37
|
+
export declare function compactEstimate(db: Database, keepDays: number, now?: number): {
|
|
38
|
+
total_changes: number;
|
|
39
|
+
compactable_changes: number;
|
|
40
|
+
db_bytes: number;
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=compact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compact.d.ts","sourceRoot":"","sources":["../../src/core/compact.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAsB3C,MAAM,WAAW,aAAa;IAC5B,oFAAoF;IACpF,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,yEAAyE;IACzE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAqBD,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,GAAG,aAAa,CAkD9E;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CACrB,EAAE,EAAE,QAAQ,EACZ,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAC9B;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CA0CpC;AAED;0CAC0C;AAC1C,wBAAgB,eAAe,CAC7B,EAAE,EAAE,QAAQ,EACZ,QAAQ,EAAE,MAAM,EAChB,GAAG,SAAa,GACf;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAa1E"}
|
package/dist/core/config.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DbDriver } from "./driver.ts";
|
|
2
2
|
export interface ServerConfig {
|
|
3
3
|
host: string;
|
|
4
4
|
port: number;
|
|
@@ -8,7 +8,7 @@ export interface ServerConfig {
|
|
|
8
8
|
}
|
|
9
9
|
export declare const DEFAULT_CONFIG: ServerConfig;
|
|
10
10
|
/** Persisted server config, falling back to DEFAULT_CONFIG per field. */
|
|
11
|
-
export declare function getServerConfig(db:
|
|
11
|
+
export declare function getServerConfig(db: DbDriver): ServerConfig;
|
|
12
12
|
/** Persist a partial config update. Only provided fields are written. */
|
|
13
|
-
export declare function setServerConfig(db:
|
|
13
|
+
export declare function setServerConfig(db: DbDriver, partial: Partial<ServerConfig>): ServerConfig;
|
|
14
14
|
//# sourceMappingURL=config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAQ5C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,cAAc,EAAE,YAK5B,CAAC;AAeF,yEAAyE;AACzE,wBAAgB,eAAe,CAAC,EAAE,EAAE,QAAQ,GAAG,YAAY,CAW1D;AAED,yEAAyE;AACzE,wBAAgB,eAAe,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAO1F"}
|
package/dist/core/context.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DbDriver } from "./driver.ts";
|
|
2
2
|
import { type DatabaseRow } from "./databases.ts";
|
|
3
3
|
/**
|
|
4
4
|
* The current database, or null. Validated on read: if it points at a database
|
|
5
5
|
* that no longer exists (deleted, or gone after a snapshot restore), the stale
|
|
6
6
|
* pointer is cleared and null returned — no coupling to delete/restore paths.
|
|
7
7
|
*/
|
|
8
|
-
export declare function getCurrentDatabase(db:
|
|
9
|
-
export declare function setCurrentDatabase(db:
|
|
10
|
-
export declare function clearCurrentDatabase(db:
|
|
8
|
+
export declare function getCurrentDatabase(db: DbDriver): DatabaseRow | null;
|
|
9
|
+
export declare function setCurrentDatabase(db: DbDriver, id: string): void;
|
|
10
|
+
export declare function clearCurrentDatabase(db: DbDriver): void;
|
|
11
11
|
//# sourceMappingURL=context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/core/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/core/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAO/D;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,GAAG,WAAW,GAAG,IAAI,CAWnE;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAIjE;AAED,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CAEvD"}
|
package/dist/core/crdt.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DbDriver } from "./driver.ts";
|
|
2
2
|
export interface Change {
|
|
3
3
|
hlc: string;
|
|
4
4
|
node_id: string;
|
|
@@ -6,30 +6,53 @@ export interface Change {
|
|
|
6
6
|
row_id: string;
|
|
7
7
|
col: string;
|
|
8
8
|
value: string | null;
|
|
9
|
+
txn?: string | null;
|
|
9
10
|
}
|
|
11
|
+
/** Oplog SELECT list, locked to the Change interface (also reused by history). */
|
|
12
|
+
export declare const CHANGE_COLS: readonly ["hlc", "node_id", "dataset", "row_id", "col", "value", "txn"];
|
|
13
|
+
export declare const CHANGE_SELECT: string;
|
|
14
|
+
/**
|
|
15
|
+
* Run `fn` with all emits stamped with one shared txn id. Nested calls keep the
|
|
16
|
+
* outermost group (a revert that calls updateDocument is ONE revision). `label`
|
|
17
|
+
* prefixes the id ("repair:", "revert:") so history can classify the source.
|
|
18
|
+
*/
|
|
19
|
+
export declare function withChangeGroup<T>(label: string | null, fn: () => T): T;
|
|
20
|
+
/** Wrap a mutator so its body runs inside one change group. */
|
|
21
|
+
export declare function grouped<A extends unknown[], R>(fn: (...args: A) => R, label?: string | null): (...args: A) => R;
|
|
10
22
|
/**
|
|
11
23
|
* Record a change in the oplog (idempotent) and, if it is the latest write for
|
|
12
24
|
* its register, materialize it. Order-independent: convergence holds regardless
|
|
13
25
|
* of the order changes are applied, because the winner is recomputed as the max
|
|
14
26
|
* HLC over the full oplog for that register.
|
|
15
27
|
*/
|
|
16
|
-
export declare function applyChange(db:
|
|
28
|
+
export declare function applyChange(db: DbDriver, c: Change): boolean;
|
|
17
29
|
/** Apply a local write: assign a fresh HLC, append to oplog, materialize. */
|
|
18
|
-
export declare function emit(db:
|
|
30
|
+
export declare function emit(db: DbDriver, dataset: string, rowId: string, col: string, value: unknown): Change;
|
|
19
31
|
/** Apply multiple local field writes to the same row. */
|
|
20
|
-
export declare function emitFields(db:
|
|
32
|
+
export declare function emitFields(db: DbDriver, dataset: string, rowId: string, fields: Record<string, unknown>): Change[];
|
|
21
33
|
/** Apply remote changes from a sync peer (advances clock, then merges). */
|
|
22
|
-
export declare function ingest(db:
|
|
34
|
+
export declare function ingest(db: DbDriver, changes: Change[]): number;
|
|
23
35
|
/** All oplog changes with HLC strictly greater than `since` (test/debug helper). */
|
|
24
|
-
export declare function changesSince(db:
|
|
36
|
+
export declare function changesSince(db: DbDriver, since: string): Change[];
|
|
25
37
|
export interface ChangeBatch {
|
|
26
38
|
changes: Change[];
|
|
27
39
|
cursor: number;
|
|
28
40
|
}
|
|
41
|
+
export interface ChangesAfterOpts {
|
|
42
|
+
/** Max rows to return — pagination for large pulls (initial hydration). */
|
|
43
|
+
limit?: number;
|
|
44
|
+
/** Datasets to omit (partial replicas, e.g. a phone skipping site_files). */
|
|
45
|
+
excludeDatasets?: string[];
|
|
46
|
+
}
|
|
29
47
|
/**
|
|
30
48
|
* Changes inserted after `seq` (a local rowid), in insertion order, plus the
|
|
31
49
|
* new high-water cursor. Used for replication: insertion order never skips a
|
|
32
50
|
* change even when clocks are skewed.
|
|
51
|
+
*
|
|
52
|
+
* With `limit`, the cursor stops at the last returned row so the next pull
|
|
53
|
+
* resumes there; when the scan is exhausted (fewer rows than the limit, or no
|
|
54
|
+
* limit) the cursor jumps to the table's high-water rowid so excluded-dataset
|
|
55
|
+
* tails aren't rescanned every round.
|
|
33
56
|
*/
|
|
34
|
-
export declare function changesAfterSeq(db:
|
|
57
|
+
export declare function changesAfterSeq(db: DbDriver, seq: number, opts?: ChangesAfterOpts): ChangeBatch;
|
|
35
58
|
//# sourceMappingURL=crdt.d.ts.map
|
package/dist/core/crdt.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crdt.d.ts","sourceRoot":"","sources":["../../src/core/crdt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"crdt.d.ts","sourceRoot":"","sources":["../../src/core/crdt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAW5C,MAAM,WAAW,MAAM;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,kFAAkF;AAClF,eAAO,MAAM,WAAW,yEAA0E,CAAC;AAEnG,eAAO,MAAM,aAAa,QAAyB,CAAC;AAMpD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAQvE;AAED,+DAA+D;AAC/D,wBAAgB,OAAO,CAAC,CAAC,SAAS,OAAO,EAAE,EAAE,CAAC,EAC5C,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,EACrB,KAAK,GAAE,MAAM,GAAG,IAAW,GAC1B,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,CAEnB;AA0ID;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAc5D;AAED,6EAA6E;AAC7E,wBAAgB,IAAI,CAClB,EAAE,EAAE,QAAQ,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,OAAO,GACb,MAAM,CAaR;AAED,yDAAyD;AACzD,wBAAgB,UAAU,CACxB,EAAE,EAAE,QAAQ,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,EAAE,CAMV;AAED,2EAA2E;AAC3E,wBAAgB,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAW9D;AAED,oFAAoF;AACpF,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAIlE;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,QAAQ,EACZ,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,gBAAqB,GAC1B,WAAW,CAuBb"}
|
package/dist/core/databases.d.ts
CHANGED
|
@@ -1,19 +1,33 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DbDriver } from "./driver.ts";
|
|
2
2
|
export interface DatabaseRow {
|
|
3
3
|
id: string;
|
|
4
4
|
name: string;
|
|
5
5
|
icon: string | null;
|
|
6
6
|
created_hlc: string;
|
|
7
7
|
}
|
|
8
|
-
export declare
|
|
8
|
+
export declare const DATABASE_COLS: readonly ["id", "name", "icon", "created_hlc"];
|
|
9
|
+
export declare const createDatabase: (db: DbDriver, opts: {
|
|
9
10
|
name: string;
|
|
10
11
|
icon?: string;
|
|
11
|
-
})
|
|
12
|
-
export declare
|
|
12
|
+
}) => DatabaseRow;
|
|
13
|
+
export declare const updateDatabase: (db: DbDriver, id: string, fields: {
|
|
13
14
|
name?: string;
|
|
14
15
|
icon?: string | null;
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
}) => DatabaseRow;
|
|
17
|
+
/**
|
|
18
|
+
* Copy a database whole — name, icon, every property (type/config/position
|
|
19
|
+
* preserved) and every record (in order, cells carried via an old→new property
|
|
20
|
+
* id map, so duplicate property names copy losslessly). A relation column
|
|
21
|
+
* pointing back at the *source* database is remapped to the copy so it stays
|
|
22
|
+
* self-referential; relations to other databases keep their target.
|
|
23
|
+
* `name`/`icon` override the defaults; the locale "copy" suffix is the
|
|
24
|
+
* caller's job. All emits share one txn, so the copy syncs as one revision.
|
|
25
|
+
*/
|
|
26
|
+
export declare const duplicateDatabase: (db: DbDriver, id: string, opts?: {
|
|
27
|
+
name?: string;
|
|
28
|
+
icon?: string;
|
|
29
|
+
} | undefined) => DatabaseRow;
|
|
30
|
+
export declare function getDatabase(db: DbDriver, id: string): DatabaseRow | null;
|
|
31
|
+
export declare function listDatabases(db: DbDriver): DatabaseRow[];
|
|
32
|
+
export declare const deleteDatabase: (db: DbDriver, id: string) => boolean;
|
|
19
33
|
//# sourceMappingURL=databases.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"databases.d.ts","sourceRoot":"","sources":["../../src/core/databases.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"databases.d.ts","sourceRoot":"","sources":["../../src/core/databases.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAQ5C,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,aAAa,gDAAiD,CAAC;AAI5E,eAAO,MAAM,cAAc;UAEX,MAAM;WAAS,MAAM;iBAOnC,CAAC;AAEH,eAAO,MAAM,cAAc;WAGR,MAAM;WAAS,MAAM,GAAG,IAAI;iBAM7C,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB;WAGb,MAAM;WAAS,MAAM;6BAwBpC,CAAC;AAEH,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAIxE;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,GAAG,WAAW,EAAE,CAIzD;AAED,eAAO,MAAM,cAAc,uCAqBzB,CAAC"}
|
package/dist/core/db.d.ts
CHANGED
|
@@ -1,32 +1,6 @@
|
|
|
1
1
|
import { Database } from "bun:sqlite";
|
|
2
|
+
export { runSchema, ftsAvailable, migrateRecords, migratePeers, migrateDocBlocks, migrateDocuments, migrateOplog, initSchema, } from "./schema-init.ts";
|
|
2
3
|
export declare function ensureDirs(): void;
|
|
3
|
-
export declare function runSchema(db: Database): void;
|
|
4
|
-
export declare function ftsAvailable(db: Database): boolean;
|
|
5
|
-
/**
|
|
6
|
-
* Migrate legacy EAV records (record_values: one row per cell) to the JSON
|
|
7
|
-
* layout (records.data: one row per record). Idempotent — keyed off schema
|
|
8
|
-
* shape, no version flag. A no-op for fresh databases.
|
|
9
|
-
*/
|
|
10
|
-
export declare function migrateRecords(db: Database): void;
|
|
11
|
-
/**
|
|
12
|
-
* Add the peer-pairing columns to a legacy `peers` table (token/label/node_id/
|
|
13
|
-
* enabled/last_sync_at/last_status/last_error). Idempotent — guarded per column,
|
|
14
|
-
* never drops the table so existing replication cursors survive.
|
|
15
|
-
*/
|
|
16
|
-
export declare function migratePeers(db: Database): void;
|
|
17
|
-
/**
|
|
18
|
-
* Add the `blank_after` column to a legacy `doc_blocks` table. Idempotent —
|
|
19
|
-
* guarded by hasColumn; existing blocks default to 0 (canonical single-blank-line
|
|
20
|
-
* separators), so the migration never changes an existing document's body.
|
|
21
|
-
*/
|
|
22
|
-
export declare function migrateDocBlocks(db: Database): void;
|
|
23
|
-
/**
|
|
24
|
-
* Add the `order_key` column to a legacy `documents` table and backfill it.
|
|
25
|
-
* Idempotent — guarded by hasColumn; backfill only touches rows with a NULL key,
|
|
26
|
-
* assigning per-parent fractional indices in current created_hlc order, so the
|
|
27
|
-
* displayed document order is unchanged until the user first drags something.
|
|
28
|
-
*/
|
|
29
|
-
export declare function migrateDocuments(db: Database): void;
|
|
30
4
|
/** Open (and migrate) the on-disk metahub database for the resolved home. */
|
|
31
5
|
export declare function openMetahub(): Database;
|
|
32
6
|
//# sourceMappingURL=db.d.ts.map
|
package/dist/core/db.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/core/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAOtC,
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/core/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAOtC,OAAO,EACL,SAAS,EACT,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,UAAU,GACX,MAAM,kBAAkB,CAAC;AAE1B,wBAAgB,UAAU,IAAI,IAAI,CAGjC;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,IAAI,QAAQ,CAMtC"}
|
package/dist/core/documents.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DbDriver } from "./driver.ts";
|
|
2
2
|
export interface DocumentRow {
|
|
3
3
|
id: string;
|
|
4
4
|
title: string;
|
|
@@ -9,33 +9,48 @@ export interface DocumentRow {
|
|
|
9
9
|
order_key: string | null;
|
|
10
10
|
}
|
|
11
11
|
export type DocumentSummary = Omit<DocumentRow, "body">;
|
|
12
|
+
export declare const DOCUMENT_COLS: readonly ["id", "title", "body", "database_id", "parent_id", "created_hlc", "order_key"];
|
|
12
13
|
/** Max HLC over a document's own register and all its blocks — a read/edit token. */
|
|
13
|
-
export declare function documentVersion(db:
|
|
14
|
-
export declare
|
|
14
|
+
export declare function documentVersion(db: DbDriver, id: string): string;
|
|
15
|
+
export declare const createDocument: (db: DbDriver, opts: {
|
|
15
16
|
title: string;
|
|
16
17
|
body?: string;
|
|
17
18
|
database_id?: string;
|
|
18
19
|
parent_id?: string;
|
|
19
|
-
})
|
|
20
|
-
export declare function getDocument(db:
|
|
21
|
-
export declare function listDocuments(db:
|
|
20
|
+
}) => DocumentRow;
|
|
21
|
+
export declare function getDocument(db: DbDriver, id: string): DocumentRow | null;
|
|
22
|
+
export declare function listDocuments(db: DbDriver, opts?: {
|
|
22
23
|
database_id?: string;
|
|
23
24
|
parent_id?: string;
|
|
24
25
|
}): DocumentSummary[];
|
|
25
26
|
/** Backfill order_key for every parent group that has un-keyed live documents. */
|
|
26
|
-
export declare
|
|
27
|
+
export declare const backfillDocumentOrderKeys: (db: DbDriver) => void;
|
|
27
28
|
/**
|
|
28
29
|
* Move a document next to / into another, atomically updating both its parent
|
|
29
30
|
* and its order_key. `into` nests it as the last child of `targetId`;
|
|
30
31
|
* `before`/`after` re-orders (and reparents if needed) among the target's siblings.
|
|
31
32
|
*/
|
|
32
|
-
export declare
|
|
33
|
-
|
|
33
|
+
export declare const moveDocument: (db: DbDriver, id: string, targetId: string, where: "before" | "after" | "into") => DocumentRow;
|
|
34
|
+
/**
|
|
35
|
+
* Copy a document — title, every block (verbatim, with fresh block ids so the
|
|
36
|
+
* copy edits independently) and its `database_id`/`parent_id`. The copy lands
|
|
37
|
+
* right after its source in the same sibling scope. Blocks are cloned at the
|
|
38
|
+
* block level (not via a markdown round-trip) so empty list items / blank-line
|
|
39
|
+
* runs survive losslessly. `title`/`parentId` override the defaults; the locale
|
|
40
|
+
* "copy" suffix is the caller's job. `created_hlc` is the copy's own birth time.
|
|
41
|
+
*/
|
|
42
|
+
export declare const duplicateDocument: (db: DbDriver, id: string, opts?: {
|
|
43
|
+
title?: string;
|
|
44
|
+
parentId?: string | null;
|
|
45
|
+
} | undefined) => DocumentRow;
|
|
46
|
+
export declare const updateDocument: (db: DbDriver, id: string, fields: {
|
|
34
47
|
title?: string;
|
|
35
48
|
body?: string;
|
|
36
49
|
database_id?: string;
|
|
37
50
|
parent_id?: string | null;
|
|
38
|
-
}
|
|
51
|
+
}, opts?: {
|
|
52
|
+
ifMatch?: string;
|
|
53
|
+
} | undefined) => DocumentRow;
|
|
39
54
|
export interface EditDocResult {
|
|
40
55
|
id: string;
|
|
41
56
|
changed: boolean;
|
|
@@ -48,13 +63,13 @@ export interface EditDocResult {
|
|
|
48
63
|
* cannot author it without current content, and drift surfaces as "not found".
|
|
49
64
|
* `ifMatch` is an optional staleness backstop (a version from documentVersion).
|
|
50
65
|
*/
|
|
51
|
-
export declare
|
|
66
|
+
export declare const editDocument: (db: DbDriver, id: string, opts: {
|
|
52
67
|
old: string;
|
|
53
68
|
new: string;
|
|
54
69
|
replaceAll?: boolean;
|
|
55
70
|
ifMatch?: string;
|
|
56
|
-
})
|
|
57
|
-
export declare
|
|
58
|
-
export declare
|
|
59
|
-
export declare
|
|
71
|
+
}) => EditDocResult;
|
|
72
|
+
export declare const appendDocument: (db: DbDriver, id: string, body: string) => EditDocResult;
|
|
73
|
+
export declare const prependDocument: (db: DbDriver, id: string, body: string) => EditDocResult;
|
|
74
|
+
export declare const deleteDocument: (db: DbDriver, id: string) => boolean;
|
|
60
75
|
//# sourceMappingURL=documents.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/core/documents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/core/documents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAQ5C,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;AAExD,eAAO,MAAM,aAAa,0FAEhB,CAAC;AAqGX,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAShE;AAID,eAAO,MAAM,cAAc;WAEV,MAAM;WAAS,MAAM;kBAAgB,MAAM;gBAAc,MAAM;iBAa9E,CAAC;AAEH,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAIxE;AAMD,wBAAgB,aAAa,CAC3B,EAAE,EAAE,QAAQ,EACZ,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACtD,eAAe,EAAE,CAWnB;AAgFD,kFAAkF;AAClF,eAAO,MAAM,yBAAyB,wBAOpC,CAAC;AAgDH;;;;GAIG;AACH,eAAO,MAAM,YAAY,iGAevB,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB;YAGZ,MAAM;eAAa,MAAM,GAAG,IAAI;6BAuBhD,CAAC;AAEH,eAAO,MAAM,cAAc;YAGP,MAAM;WAAS,MAAM;kBAAgB,MAAM;gBAAc,MAAM,GAAG,IAAI;;cACtE,MAAM;6BAsBxB,CAAC;AAEH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY;SAGV,MAAM;SAAO,MAAM;iBAAe,OAAO;cAAY,MAAM;mBAqCxE,CAAC;AAEH,eAAO,MAAM,cAAc,2DAczB,CAAC;AAEH,eAAO,MAAM,eAAe,2DAc1B,CAAC;AAEH,eAAO,MAAM,cAAc,uCAUzB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal synchronous SQLite driver surface that every runtime hosting a
|
|
3
|
+
* metahub database must provide. The portable core modules type against this
|
|
4
|
+
* instead of bun:sqlite so the same code can run on Bun (bun:sqlite's
|
|
5
|
+
* `Database` satisfies it structurally — no adapter needed) and in a browser
|
|
6
|
+
* worker (sqlite-wasm behind a small adapter).
|
|
7
|
+
*
|
|
8
|
+
* Keep this surface to what bun:sqlite and sqlite-wasm can both serve
|
|
9
|
+
* synchronously: positional `?` binds, `get`/`all`/`run` on prepared
|
|
10
|
+
* statements, `exec` for scripts, and re-entrant `transaction` wrappers.
|
|
11
|
+
*/
|
|
12
|
+
export type SqlBindable = string | number | bigint | boolean | null | Uint8Array;
|
|
13
|
+
export interface Stmt {
|
|
14
|
+
get(...params: SqlBindable[]): unknown;
|
|
15
|
+
all(...params: SqlBindable[]): unknown[];
|
|
16
|
+
run(...params: SqlBindable[]): {
|
|
17
|
+
changes: number;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export interface DbDriver {
|
|
21
|
+
query(sql: string): Stmt;
|
|
22
|
+
exec(sql: string): void;
|
|
23
|
+
transaction<A extends unknown[], R>(fn: (...args: A) => R): (...args: A) => R;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=driver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/core/driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,UAAU,CAAC;AAEjF,MAAM,WAAW,IAAI;IACnB,GAAG,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IACvC,GAAG,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,EAAE,CAAC;IACzC,GAAG,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACpD;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,CAAC,CAAC,SAAS,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC;CAC/E"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Machine-readable error taxonomy — the contract between core and its callers.
|
|
3
|
+
*
|
|
4
|
+
* Agents and scripts dispatch on `code`, never on message text (messages may
|
|
5
|
+
* be reworded freely). The CLI maps codes to exit codes (src/cli/output.ts)
|
|
6
|
+
* and the HTTP layer maps them to status codes (src/webui/server/routes.ts),
|
|
7
|
+
* so adding a code here is enough for both surfaces to pick it up.
|
|
8
|
+
*/
|
|
9
|
+
export type MhErrorCode =
|
|
10
|
+
/** Bad arguments / refusing a request as stated (HTTP 400, exit 2). */
|
|
11
|
+
"invalid_input"
|
|
12
|
+
/** Referenced entity does not exist (HTTP 404, exit 3). */
|
|
13
|
+
| "not_found"
|
|
14
|
+
/** A ref matched more than one entity — disambiguate and retry (exit 4). */
|
|
15
|
+
| "ambiguous"
|
|
16
|
+
/** Optimistic-concurrency failure: re-read, then retry (HTTP 409, exit 5). */
|
|
17
|
+
| "stale"
|
|
18
|
+
/** State conflict, e.g. a name that already exists (HTTP 409, exit 5). */
|
|
19
|
+
| "conflict"
|
|
20
|
+
/** Missing/invalid credentials (HTTP 401, exit 6). */
|
|
21
|
+
| "auth"
|
|
22
|
+
/** A remote peer was unreachable or replied non-OK — retryable (exit 7). */
|
|
23
|
+
| "network"
|
|
24
|
+
/** The requested listen port is taken (exit 98, historical). */
|
|
25
|
+
| "port_in_use";
|
|
26
|
+
export declare class MhError extends Error {
|
|
27
|
+
readonly code: MhErrorCode;
|
|
28
|
+
constructor(code: MhErrorCode, message: string);
|
|
29
|
+
}
|
|
30
|
+
/** The error's code, for errors that carry one (anything else → undefined). */
|
|
31
|
+
export declare function errorCode(e: unknown): MhErrorCode | undefined;
|
|
32
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW;AACrB,uEAAuE;AACrE,eAAe;AACjB,2DAA2D;GACzD,WAAW;AACb,4EAA4E;GAC1E,WAAW;AACb,8EAA8E;GAC5E,OAAO;AACT,0EAA0E;GACxE,UAAU;AACZ,sDAAsD;GACpD,MAAM;AACR,4EAA4E;GAC1E,SAAS;AACX,gEAAgE;GAC9D,aAAa,CAAC;AAElB,qBAAa,OAAQ,SAAQ,KAAK;IAE9B,QAAQ,CAAC,IAAI,EAAE,WAAW;gBAAjB,IAAI,EAAE,WAAW,EAC1B,OAAO,EAAE,MAAM;CAKlB;AAED,+EAA+E;AAC/E,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,GAAG,WAAW,GAAG,SAAS,CAE7D"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import type { DbDriver } from "./driver.ts";
|
|
2
|
+
/** Where a revision came from, derived from its change-group label. */
|
|
3
|
+
export type RevisionKind = "user" | "repair" | "revert";
|
|
4
|
+
export interface DocRevision {
|
|
5
|
+
/** Version token (max HLC of the revision) — pass to documentAtVersion/revertDocument. */
|
|
6
|
+
version: string;
|
|
7
|
+
/** Wall-clock time derived from the version HLC (ISO 8601). */
|
|
8
|
+
at: string;
|
|
9
|
+
node_id: string;
|
|
10
|
+
/** Source of the revision: a user edit, a repairHub fix, or a revert. */
|
|
11
|
+
kind: RevisionKind;
|
|
12
|
+
changes: number;
|
|
13
|
+
created: boolean;
|
|
14
|
+
deleted: boolean;
|
|
15
|
+
title_changed: boolean;
|
|
16
|
+
blocks_changed: number;
|
|
17
|
+
blocks_deleted: number;
|
|
18
|
+
}
|
|
19
|
+
/** A document's edit history, newest first, clustered into save-sized revisions. */
|
|
20
|
+
export declare function listDocumentRevisions(db: DbDriver, id: string): DocRevision[];
|
|
21
|
+
export interface DocumentVersionState {
|
|
22
|
+
id: string;
|
|
23
|
+
title: string;
|
|
24
|
+
body: string;
|
|
25
|
+
deleted: boolean;
|
|
26
|
+
/** Exact version (max HLC <= the requested cutoff) this state corresponds to. */
|
|
27
|
+
version: string;
|
|
28
|
+
}
|
|
29
|
+
/** Reconstruct a document as of version cutoff `at` (state at hlc <= at). */
|
|
30
|
+
export declare function documentAtVersion(db: DbDriver, id: string, at: string): DocumentVersionState;
|
|
31
|
+
export interface RevertDocResult {
|
|
32
|
+
id: string;
|
|
33
|
+
changed: boolean;
|
|
34
|
+
/** The version token the document was restored to. */
|
|
35
|
+
restored: string;
|
|
36
|
+
/** The document's version after the revert (a new head — revert is a forward write). */
|
|
37
|
+
version: string;
|
|
38
|
+
/** True when the revert resurrected a tombstoned document. */
|
|
39
|
+
undeleted: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Restore a document's title/body to a past version, as a new forward edit
|
|
43
|
+
* (reuses updateDocument's block reconcile, so unchanged blocks keep identity).
|
|
44
|
+
* Reverting a tombstoned document resurrects it; children unparented by the
|
|
45
|
+
* delete stay where they are. One change group, so history shows ONE revision.
|
|
46
|
+
*/
|
|
47
|
+
export declare const revertDocument: (db: DbDriver, id: string, to: string, opts?: {
|
|
48
|
+
ifMatch?: string;
|
|
49
|
+
} | undefined) => RevertDocResult;
|
|
50
|
+
export interface RecordRevision {
|
|
51
|
+
version: string;
|
|
52
|
+
at: string;
|
|
53
|
+
node_id: string;
|
|
54
|
+
kind: RevisionKind;
|
|
55
|
+
changes: number;
|
|
56
|
+
created: boolean;
|
|
57
|
+
deleted: boolean;
|
|
58
|
+
/** Property ids of the cells written in this revision. */
|
|
59
|
+
fields: string[];
|
|
60
|
+
moved: boolean;
|
|
61
|
+
}
|
|
62
|
+
/** A record's edit history, newest first, clustered into save-sized revisions. */
|
|
63
|
+
export declare function listRecordRevisions(db: DbDriver, id: string): RecordRevision[];
|
|
64
|
+
/** One cell's value change inside a revision. A missing `before`/`after` key
|
|
65
|
+
* means the cell did not exist on that side (distinct from an explicit null). */
|
|
66
|
+
export interface FieldChange {
|
|
67
|
+
prop: string;
|
|
68
|
+
before?: unknown;
|
|
69
|
+
after?: unknown;
|
|
70
|
+
}
|
|
71
|
+
export interface DatabaseActivityEntry extends RecordRevision {
|
|
72
|
+
record_id: string;
|
|
73
|
+
/** Title-property value as of this revision — deleted records keep their last title. */
|
|
74
|
+
record_title: string | null;
|
|
75
|
+
/** Value-level changes of the touched cells. */
|
|
76
|
+
diffs: FieldChange[];
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* "What happened in this table lately": every record's revisions, merged and
|
|
80
|
+
* sorted newest first. Includes tombstoned records (so deletions show up) — a
|
|
81
|
+
* read-only aggregation, same clustering as listRecordRevisions per record.
|
|
82
|
+
* Walking each record's change stream oldest-first lets us carry a running
|
|
83
|
+
* cell-state map, so every entry ships its old→new values and a title snapshot
|
|
84
|
+
* for free (no extra queries). After compaction, `before` at the window edge
|
|
85
|
+
* may be missing (the superseded write was pruned) — it reads as "was empty".
|
|
86
|
+
*/
|
|
87
|
+
export declare function listDatabaseActivity(db: DbDriver, databaseId: string, opts?: {
|
|
88
|
+
limit?: number;
|
|
89
|
+
}): DatabaseActivityEntry[];
|
|
90
|
+
export interface RecordVersionState {
|
|
91
|
+
id: string;
|
|
92
|
+
database_id: string | null;
|
|
93
|
+
deleted: boolean;
|
|
94
|
+
/** Cells present at that version, keyed by property id (raw, no name mapping). */
|
|
95
|
+
data: Record<string, unknown>;
|
|
96
|
+
version: string;
|
|
97
|
+
}
|
|
98
|
+
/** Reconstruct a record as of version cutoff `at` (state at hlc <= at). */
|
|
99
|
+
export declare function recordAtVersion(db: DbDriver, id: string, at: string): RecordVersionState;
|
|
100
|
+
export interface RevertRecordResult {
|
|
101
|
+
id: string;
|
|
102
|
+
changed: boolean;
|
|
103
|
+
/** Property ids whose cells were written by the revert. */
|
|
104
|
+
fields: string[];
|
|
105
|
+
/** True when the revert resurrected a tombstoned record. */
|
|
106
|
+
undeleted: boolean;
|
|
107
|
+
restored: string;
|
|
108
|
+
}
|
|
109
|
+
/** Restore a record's cells to a past version as a new forward edit. Only cells
|
|
110
|
+
* of currently-live properties are touched, so no orphan cells are recreated
|
|
111
|
+
* (the repairHub invariant). Reverting a tombstoned record resurrects it. */
|
|
112
|
+
export declare const revertRecord: (db: DbDriver, id: string, to: string) => RevertRecordResult;
|
|
113
|
+
export interface PropertyRevision {
|
|
114
|
+
version: string;
|
|
115
|
+
at: string;
|
|
116
|
+
node_id: string;
|
|
117
|
+
kind: RevisionKind;
|
|
118
|
+
changes: number;
|
|
119
|
+
created: boolean;
|
|
120
|
+
deleted: boolean;
|
|
121
|
+
/** Definition columns touched in this revision (name/type/config/position). */
|
|
122
|
+
fields: string[];
|
|
123
|
+
/** Record cells the same change group cleared (a type change / removal cascade). */
|
|
124
|
+
cells_cleared: number;
|
|
125
|
+
}
|
|
126
|
+
/** A property's definition history, newest first. Cascaded cell clears are
|
|
127
|
+
* counted via the shared txn so a type change reads as one revision. */
|
|
128
|
+
export declare function listPropertyRevisions(db: DbDriver, id: string): PropertyRevision[];
|
|
129
|
+
export interface PropertyVersionState {
|
|
130
|
+
id: string;
|
|
131
|
+
database_id: string | null;
|
|
132
|
+
name: string;
|
|
133
|
+
type: string;
|
|
134
|
+
config: unknown;
|
|
135
|
+
position: number | null;
|
|
136
|
+
deleted: boolean;
|
|
137
|
+
version: string;
|
|
138
|
+
}
|
|
139
|
+
/** Reconstruct a property definition as of version cutoff `at`. */
|
|
140
|
+
export declare function propertyAtVersion(db: DbDriver, id: string, at: string): PropertyVersionState;
|
|
141
|
+
export interface RevertPropertyResult {
|
|
142
|
+
id: string;
|
|
143
|
+
changed: boolean;
|
|
144
|
+
/** Definition columns the revert wrote. */
|
|
145
|
+
fields: string[];
|
|
146
|
+
/** Record cells restored to their value at the target version. */
|
|
147
|
+
restored_cells: number;
|
|
148
|
+
/** Cells left alone because a user wrote them after the target version. */
|
|
149
|
+
skipped_cells: number;
|
|
150
|
+
undeleted: boolean;
|
|
151
|
+
restored: string;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Schema-level rollback: restore a property's definition AND the record cells
|
|
155
|
+
* its later type-change/removal cascades cleared. Definition registers are
|
|
156
|
+
* emitted directly (never via updateProperty — its type-change cascade would
|
|
157
|
+
* re-clear the cells being restored). A cell is only touched when its current
|
|
158
|
+
* winner IS the cascade (or a repair); it is restored to the last value before
|
|
159
|
+
* that cascade, so user data — written before or after the target version —
|
|
160
|
+
* always survives. Cells whose winner is a user write are kept (skipped_cells).
|
|
161
|
+
* Pre-txn legacy writes can't be attributed, so they count as user writes.
|
|
162
|
+
*/
|
|
163
|
+
export declare const revertProperty: (db: DbDriver, id: string, to: string) => RevertPropertyResult;
|
|
164
|
+
export interface FieldHistoryEntry {
|
|
165
|
+
version: string;
|
|
166
|
+
at: string;
|
|
167
|
+
node_id: string;
|
|
168
|
+
/** The value written; undefined when the write cleared the cell. */
|
|
169
|
+
value: unknown;
|
|
170
|
+
cleared: boolean;
|
|
171
|
+
}
|
|
172
|
+
/** The full write trail of one record cell (property id), newest first. */
|
|
173
|
+
export declare function recordFieldHistory(db: DbDriver, id: string, propId: string): FieldHistoryEntry[];
|
|
174
|
+
//# sourceMappingURL=history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/core/history.ts"],"names":[],"mappings":"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"}
|
package/dist/core/hlc.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DbDriver } from "./driver.ts";
|
|
2
2
|
export interface Hlc {
|
|
3
3
|
millis: number;
|
|
4
4
|
counter: number;
|
|
@@ -7,7 +7,7 @@ export interface Hlc {
|
|
|
7
7
|
export declare function formatHlc(h: Hlc): string;
|
|
8
8
|
export declare function parseHlc(s: string): Hlc;
|
|
9
9
|
/** Issue a new timestamp for a local event, advancing the persisted clock. */
|
|
10
|
-
export declare function nextHlc(db:
|
|
10
|
+
export declare function nextHlc(db: DbDriver, node: string, now?: number): string;
|
|
11
11
|
/** Advance the local clock to account for an observed remote timestamp. */
|
|
12
|
-
export declare function observeHlc(db:
|
|
12
|
+
export declare function observeHlc(db: DbDriver, node: string, remote: string, now?: number): void;
|
|
13
13
|
//# sourceMappingURL=hlc.d.ts.map
|
package/dist/core/hlc.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hlc.d.ts","sourceRoot":"","sources":["../../src/core/hlc.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"hlc.d.ts","sourceRoot":"","sources":["../../src/core/hlc.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAK5C,MAAM,WAAW,GAAG;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,GAAG,GAAG,MAAM,CAIxC;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,GAAG,CAQvC;AAeD,8EAA8E;AAC9E,wBAAgB,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,MAAM,CAO5E;AAED,2EAA2E;AAC3E,wBAAgB,UAAU,CACxB,EAAE,EAAE,QAAQ,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,GAAG,SAAa,GACf,IAAI,CAWN"}
|