@tensorix/metahub 0.1.11 → 0.2.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/dist/cli.js +21342 -17813
- package/dist/cli.js.map +76 -60
- package/dist/core/blobs-core.d.ts +106 -0
- package/dist/core/blobs-core.d.ts.map +1 -0
- package/dist/core/blobs.d.ts +100 -0
- package/dist/core/blobs.d.ts.map +1 -0
- package/dist/core/cache.d.ts +18 -1
- package/dist/core/cache.d.ts.map +1 -1
- package/dist/core/compact.d.ts +4 -3
- package/dist/core/compact.d.ts.map +1 -1
- package/dist/core/config.d.ts +3 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/crdt.d.ts +25 -2
- package/dist/core/crdt.d.ts.map +1 -1
- package/dist/core/schema-init.d.ts +33 -2
- package/dist/core/schema-init.d.ts.map +1 -1
- package/dist/core/schema.d.ts +1 -1
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/sites-core.d.ts +35 -0
- package/dist/core/sites-core.d.ts.map +1 -1
- package/dist/core/sites.d.ts +4 -13
- package/dist/core/sites.d.ts.map +1 -1
- package/dist/core/sync/blob-routes.d.ts +12 -0
- package/dist/core/sync/blob-routes.d.ts.map +1 -0
- package/dist/core/sync/client.d.ts +2 -0
- package/dist/core/sync/client.d.ts.map +1 -1
- package/dist/core/sync/e2ee.d.ts +24 -0
- package/dist/core/sync/e2ee.d.ts.map +1 -0
- package/dist/core/sync/enroll.d.ts +21 -0
- package/dist/core/sync/enroll.d.ts.map +1 -0
- package/dist/core/sync/peers-routes.d.ts.map +1 -1
- package/dist/core/sync/peers.d.ts +75 -2
- package/dist/core/sync/peers.d.ts.map +1 -1
- package/dist/core/sync/publisher-lease.d.ts +8 -0
- package/dist/core/sync/publisher-lease.d.ts.map +1 -0
- package/dist/core/sync/routes.d.ts.map +1 -1
- package/dist/core/sync/server.d.ts +1 -0
- package/dist/core/sync/server.d.ts.map +1 -1
- package/dist/core/sync/sites-serve.d.ts.map +1 -1
- package/dist/core/sync/storage-s3-bun.d.ts +26 -0
- package/dist/core/sync/storage-s3-bun.d.ts.map +1 -0
- package/dist/core/sync/storage.d.ts +170 -0
- package/dist/core/sync/storage.d.ts.map +1 -0
- package/dist/db-worker.js +181 -65
- package/dist/index.js +16519 -13910
- package/dist/index.js.map +40 -28
- package/dist/sw.js +1 -1
- package/dist/webui/server/routes.d.ts.map +1 -1
- package/dist/webui.js +67 -61
- package/package.json +4 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2ee.d.ts","sourceRoot":"","sources":["../../../src/core/sync/e2ee.ts"],"names":[],"mappings":"AAkCA,iFAAiF;AACjF,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE,CAAC,CAAC;IACL,GAAG,EAAE,eAAe,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;CACrB;AAID,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAI/C;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAK/C;AAID,qDAAqD;AACrD,wBAAgB,iBAAiB,IAAI,UAAU,CAE9C;AAmBD,kFAAkF;AAClF,wBAAsB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAkBhG;AAED;2EAC2E;AAC3E,wBAAsB,eAAe,CAAC,GAAG,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAc/F;AAWD,iFAAiF;AACjF,wBAAsB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAUjG;AAED,mFAAmF;AACnF,wBAAsB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAU/F"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** The slim bucket descriptor an enroll token carries. Mirrors the access-only
|
|
2
|
+
* subset of S3Config — no passphrase, no master key, no node-role hints. */
|
|
3
|
+
export interface EnrollPayload {
|
|
4
|
+
endpoint: string;
|
|
5
|
+
region?: string;
|
|
6
|
+
bucket: string;
|
|
7
|
+
prefix?: string;
|
|
8
|
+
accessKeyId: string;
|
|
9
|
+
secretAccessKey: string;
|
|
10
|
+
encrypt?: boolean;
|
|
11
|
+
virtualHostedStyle?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/** Encode the bucket descriptor into a base64url enroll token. Keys are emitted
|
|
14
|
+
* in a fixed order (and undefined fields omitted) so the token is stable. */
|
|
15
|
+
export declare function encodeEnroll(p: EnrollPayload): string;
|
|
16
|
+
/** Decode an enroll token back into a bucket descriptor. Accepts the bare token,
|
|
17
|
+
* an `enroll=<token>` fragment, or a full `…/#enroll=<token>` deep link, so a
|
|
18
|
+
* user can paste whatever they copied. Throws MhError("invalid_input") on a
|
|
19
|
+
* malformed token or a payload missing the fields needed to reach the bucket. */
|
|
20
|
+
export declare function decodeEnroll(tokenOrUrl: string): EnrollPayload;
|
|
21
|
+
//# sourceMappingURL=enroll.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enroll.d.ts","sourceRoot":"","sources":["../../../src/core/sync/enroll.ts"],"names":[],"mappings":"AAaA;6EAC6E;AAC7E,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAmBD;8EAC8E;AAC9E,wBAAgB,YAAY,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,CAYrD;AAED;;;kFAGkF;AAClF,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAoC9D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"peers-routes.d.ts","sourceRoot":"","sources":["../../../src/core/sync/peers-routes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,KAAK,EAAiB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"peers-routes.d.ts","sourceRoot":"","sources":["../../../src/core/sync/peers-routes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,KAAK,EAAiB,MAAM,aAAa,CAAC;AA6KvE,eAAO,MAAM,WAAW,EAAE,KAAK,EA+H9B,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { DbDriver } from "../driver.ts";
|
|
2
|
+
import { type S3Config, type StorageSyncOpts } from "./storage.ts";
|
|
2
3
|
export interface PeerRow {
|
|
3
4
|
url: string;
|
|
4
5
|
pull_cursor: number;
|
|
@@ -7,9 +8,16 @@ export interface PeerRow {
|
|
|
7
8
|
label: string | null;
|
|
8
9
|
node_id: string | null;
|
|
9
10
|
enabled: number;
|
|
11
|
+
/** Last sync attempt, successful or failed. */
|
|
10
12
|
last_sync_at: number | null;
|
|
13
|
+
/** Last successful sync. Freshness gates must use this, not last_sync_at. */
|
|
14
|
+
last_success_at: number | null;
|
|
11
15
|
last_status: string | null;
|
|
12
16
|
last_error: string | null;
|
|
17
|
+
/** Transport: 'http' (POST /sync) or 's3' (bucket store-and-forward). */
|
|
18
|
+
kind: string;
|
|
19
|
+
/** JSON S3Config for 's3' peers; null for 'http'. */
|
|
20
|
+
config: string | null;
|
|
13
21
|
}
|
|
14
22
|
export declare function listPeers(db: DbDriver): PeerRow[];
|
|
15
23
|
export declare function getPeer(db: DbDriver, url: string): PeerRow | null;
|
|
@@ -21,6 +29,47 @@ export interface AddPeerInput {
|
|
|
21
29
|
}
|
|
22
30
|
/** Upsert a peer, preserving replication cursors on conflict. */
|
|
23
31
|
export declare function addPeer(db: DbDriver, input: AddPeerInput): void;
|
|
32
|
+
export interface AddStoragePeerInput {
|
|
33
|
+
/** Synthetic peer key, by convention s3://<bucket>/<prefix>. */
|
|
34
|
+
url: string;
|
|
35
|
+
config: S3Config;
|
|
36
|
+
label?: string | null;
|
|
37
|
+
}
|
|
38
|
+
/** Upsert an 's3' (bucket store-and-forward) peer, preserving cursors on conflict. */
|
|
39
|
+
export declare function addStoragePeer(db: DbDriver, input: AddStoragePeerInput): void;
|
|
40
|
+
/** Synthetic peer key for a storage peer: one per bucket+prefix. */
|
|
41
|
+
export declare const storageUrl: (bucket: string, prefix: string) => string;
|
|
42
|
+
export interface StoragePeerSpec {
|
|
43
|
+
endpoint: string;
|
|
44
|
+
region?: string;
|
|
45
|
+
bucket: string;
|
|
46
|
+
prefix?: string;
|
|
47
|
+
accessKeyId: string;
|
|
48
|
+
secretAccessKey: string;
|
|
49
|
+
/** Virtual-hosted (COS) vs path-style addressing; undefined → auto-detect.
|
|
50
|
+
* Carried by enroll codes so COS buckets join correctly. */
|
|
51
|
+
virtualHostedStyle?: boolean;
|
|
52
|
+
/** Default true; pass false for `--no-encrypt` plaintext buckets. */
|
|
53
|
+
encrypt?: boolean;
|
|
54
|
+
/** Required when encrypt — provisions/adopts the bucket's wrapped master key. */
|
|
55
|
+
passphrase?: string;
|
|
56
|
+
/** Mark this node the bucket's publisher (writes whole-hub snapshots). */
|
|
57
|
+
publish?: boolean;
|
|
58
|
+
priority?: number;
|
|
59
|
+
label?: string | null;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Resolve + persist an S3 storage peer and run one sync so a bad endpoint /
|
|
63
|
+
* credentials / missing CORS fail fast at the call site. Shared by the CLI
|
|
64
|
+
* (`mh config peer add --s3`) and the WebUI server endpoint (`POST /api/peer/s3`)
|
|
65
|
+
* so both go through the exact same provisioning + first-sync path. Returns the
|
|
66
|
+
* resolved config (incl. the wrapped master key) and the first sync outcome.
|
|
67
|
+
*/
|
|
68
|
+
export declare function addAndSyncStoragePeer(db: DbDriver, spec: StoragePeerSpec): Promise<{
|
|
69
|
+
url: string;
|
|
70
|
+
config: S3Config;
|
|
71
|
+
sync: PeerSyncOutcome;
|
|
72
|
+
}>;
|
|
24
73
|
/**
|
|
25
74
|
* Remove a peer AND revoke the credential we issued to it during pairing, so
|
|
26
75
|
* disconnecting is mutual: we stop syncing out to it (peers row) and it can no
|
|
@@ -36,10 +85,34 @@ export interface PeerSyncOutcome {
|
|
|
36
85
|
ok: boolean;
|
|
37
86
|
pushed?: number;
|
|
38
87
|
pulled?: number;
|
|
88
|
+
pendingPush?: boolean;
|
|
39
89
|
error?: string;
|
|
40
90
|
}
|
|
41
|
-
/** Sync once with a single peer, recording status. Errors are captured, not
|
|
42
|
-
|
|
91
|
+
/** Sync once with a single peer, recording status. Errors are captured, not
|
|
92
|
+
* thrown. Dispatches on transport: 's3' peers go through the bucket
|
|
93
|
+
* store-and-forward client, everything else POSTs /sync. */
|
|
94
|
+
export declare function syncPeer(db: DbDriver, url: string, opts?: {
|
|
95
|
+
storage?: StorageSyncOpts;
|
|
96
|
+
}): Promise<PeerSyncOutcome>;
|
|
43
97
|
/** Sync once with every enabled peer. Used by the auto-sync timer. */
|
|
44
98
|
export declare function syncAllPeers(db: DbDriver): Promise<PeerSyncOutcome[]>;
|
|
99
|
+
/**
|
|
100
|
+
* Freshness gate for *non-reactive* consumers — CLI reads and the PWA's served
|
|
101
|
+
* site pages (②b). Their local DB is only as fresh as the last sync, and unlike
|
|
102
|
+
* the reactive WebUI they have no background poll and no `synced` revalidate. So
|
|
103
|
+
* if the newest successful peer sync is older than `maxAgeMs`, block on one
|
|
104
|
+
* bounded sync round before the caller reads; otherwise return immediately
|
|
105
|
+
* (read local).
|
|
106
|
+
*
|
|
107
|
+
* No enabled peers → no-op. A running daemon keeps `last_success_at` recent, so
|
|
108
|
+
* this is a near-instant no-op there and only does real work on a daemon-less node
|
|
109
|
+
* that hasn't synced successfully in a while. Failed attempts update
|
|
110
|
+
* `last_sync_at`, but never make local data fresh. Env overrides: MH_OFFLINE=1
|
|
111
|
+
* skips; MH_FRESH=1 forces; MH_SYNC_MAX_AGE=<ms> tunes the threshold.
|
|
112
|
+
*/
|
|
113
|
+
export declare function ensureFresh(db: DbDriver, opts?: {
|
|
114
|
+
maxAgeMs?: number;
|
|
115
|
+
force?: boolean;
|
|
116
|
+
offline?: boolean;
|
|
117
|
+
}): Promise<void>;
|
|
45
118
|
//# sourceMappingURL=peers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"peers.d.ts","sourceRoot":"","sources":["../../../src/core/sync/peers.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAG7C,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"peers.d.ts","sourceRoot":"","sources":["../../../src/core/sync/peers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { StorageClient } from "./storage.ts";
|
|
2
|
+
/**
|
|
3
|
+
* Refresh this node's heartbeat (throttled) and return whether it is the elected
|
|
4
|
+
* publisher among currently-live candidates. Call only when a snapshot is
|
|
5
|
+
* actually due, so the lease LIST/GETs aren't paid on idle rounds.
|
|
6
|
+
*/
|
|
7
|
+
export declare function isElectedPublisher(client: StorageClient, base: string, node: string, priority: number, now?: number): Promise<boolean>;
|
|
8
|
+
//# sourceMappingURL=publisher-lease.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publisher-lease.d.ts","sourceRoot":"","sources":["../../../src/core/sync/publisher-lease.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAmBlD;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,GAAG,GAAE,MAAmB,GACvB,OAAO,CAAC,OAAO,CAAC,CAgDlB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/core/sync/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACnC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/core/sync/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACnC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAe3C,yEAAyE;AACzE,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,QAAQ,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAeD;;8BAE8B;AAC9B,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,QAAQ,CAMlD;AAED;;;;GAIG;AACH,MAAM,WAAW,KAAK;IACpB,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;CACxE;AAiCD,eAAO,MAAM,MAAM,EAAE,KAAK,EAAmE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/core/sync/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/core/sync/server.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAE7B,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAIvC,OAAO,EAAU,KAAK,KAAK,EAAiB,MAAM,aAAa,CAAC;AAmBhE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,UAAU,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,qFAAqF;IACrF,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,wFAAwF;IACxF,QAAQ,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,CAAC;IAC5C,oEAAoE;IACpE,GAAG,EAAE,OAAO,CAAC;IACb,8CAA8C;IAC9C,QAAQ,EAAE,OAAO,CAAC;IAClB,qEAAqE;IACrE,cAAc,EAAE,MAAM,CAAC;IACvB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,6EAA6E;AAC7E,qBAAa,cAAe,SAAQ,OAAO;IAEvC,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM;gBADZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM;CASxB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;kDAE8C;IAC9C,EAAE,CAAC,EAAE,SAAS,CAAC;IACf;;;mEAG+D;IAC/D,GAAG,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAED,oEAAoE;AACpE,MAAM,WAAW,SAAS;IACxB,8EAA8E;IAC9E,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IACpD,4EAA4E;IAC5E,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB;AAYD,gFAAgF;AAChF,wBAAgB,WAAW,CAAC,IAAI,GAAE,aAAkB,GAAG,aAAa,CA+NnE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sites-serve.d.ts","sourceRoot":"","sources":["../../../src/core/sync/sites-serve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAQ5C,wBAAsB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"sites-serve.d.ts","sourceRoot":"","sources":["../../../src/core/sync/sites-serve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAQ5C,wBAAsB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAyBrF"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type S3Config } from "./storage.ts";
|
|
2
|
+
/** Read the bucket's current CORS config (raw XML), or null if none is set. */
|
|
3
|
+
export declare function getBucketCors(config: S3Config): Promise<string | null>;
|
|
4
|
+
/**
|
|
5
|
+
* Build the PutBucketCors XML body from the bucket's current config. PutBucketCors
|
|
6
|
+
* replaces the whole config, so we keep every rule that isn't ours and re-emit our
|
|
7
|
+
* managed rule (id=metahub-pwa). `merge` decides our rule's origins:
|
|
8
|
+
* - false (CLI `peer cors`): SET — exactly `origins` (lets the user shrink/reset).
|
|
9
|
+
* - true (auto-open on bucket-attach): UNION with the managed rule's existing
|
|
10
|
+
* origins, so attaching the same bucket from a second shell/origin (a homelab
|
|
11
|
+
* server origin alongside the official PWA shell) adds to the allow-list
|
|
12
|
+
* instead of clobbering it.
|
|
13
|
+
* A wildcard `*` collapses the set. Pure (no I/O) so it's unit-testable.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildCorsXml(existing: string | null, origins: string[], merge: boolean): string;
|
|
16
|
+
/**
|
|
17
|
+
* Allow a browser shell served from `origins` to talk to the bucket directly
|
|
18
|
+
* (GET/PUT/HEAD/DELETE) via GET-merge-PUT (see buildCorsXml). `opts.merge` unions
|
|
19
|
+
* with existing managed origins instead of replacing them — used when a second
|
|
20
|
+
* origin attaches the same bucket. Content-MD5 is required by the CORS API
|
|
21
|
+
* (S3 and COS both).
|
|
22
|
+
*/
|
|
23
|
+
export declare function putBucketCors(config: S3Config, origins: string[], opts?: {
|
|
24
|
+
merge?: boolean;
|
|
25
|
+
}): Promise<void>;
|
|
26
|
+
//# sourceMappingURL=storage-s3-bun.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-s3-bun.d.ts","sourceRoot":"","sources":["../../../src/core/sync/storage-s3-bun.ts"],"names":[],"mappings":"AAUA,OAAO,EAML,KAAK,QAAQ,EACd,MAAM,cAAc,CAAC;AAiHtB,+EAA+E;AAC/E,wBAAsB,aAAa,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAS5E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAoB/F;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,QAAQ,EAChB,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAC7B,OAAO,CAAC,IAAI,CAAC,CAmBf"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import type { DbDriver } from "../driver.ts";
|
|
2
|
+
import type { SyncResult } from "./client.ts";
|
|
3
|
+
/** An 's3' peer's bucket settings, stored as JSON in peers.config (local-only). */
|
|
4
|
+
export interface S3Config {
|
|
5
|
+
endpoint: string;
|
|
6
|
+
region: string;
|
|
7
|
+
bucket: string;
|
|
8
|
+
prefix: string;
|
|
9
|
+
accessKeyId: string;
|
|
10
|
+
secretAccessKey: string;
|
|
11
|
+
/** When false (`--no-encrypt`) segments are gzip-only plaintext. */
|
|
12
|
+
encrypt: boolean;
|
|
13
|
+
/** base64 raw 32-byte master key; present iff encrypt. Resolved at peer-add. */
|
|
14
|
+
masterKey?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Address objects as `<bucket>.<host>/<key>` (virtual-hosted) instead of
|
|
17
|
+
* `<host>/<bucket>/<key>` (path-style). Some providers (Tencent COS) reject
|
|
18
|
+
* path-style outright. When undefined, the clients auto-detect: virtual-hosted
|
|
19
|
+
* iff the endpoint host already starts with `<bucket>.` (see
|
|
20
|
+
* isVirtualHostedStyle). R2/MinIO keep using path-style.
|
|
21
|
+
*/
|
|
22
|
+
virtualHostedStyle?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Node-role hints for this bucket (not bucket settings — safe to omit from
|
|
25
|
+
* shared enroll links). `publish` marks this node as the bucket's publisher
|
|
26
|
+
* (writes whole-hub snapshots; see StorageSyncOpts.publish): true for the data
|
|
27
|
+
* home (a server, or a no-origin PWA which IS the home), false for a replica
|
|
28
|
+
* that only attaches the bucket for its own away-sync. `priority` ranks
|
|
29
|
+
* publisher candidates when several are eligible (higher wins; see
|
|
30
|
+
* publisher-lease.ts) — server > desktop > laptop > phone.
|
|
31
|
+
*/
|
|
32
|
+
publish?: boolean;
|
|
33
|
+
priority?: number;
|
|
34
|
+
}
|
|
35
|
+
/** Whether to use virtual-hosted addressing for this bucket: the explicit flag,
|
|
36
|
+
* or — when unset — auto-detected from an endpoint whose host already carries
|
|
37
|
+
* the bucket (e.g. COS's `<bucket>.cos.<region>.myqcloud.com`). */
|
|
38
|
+
export declare function isVirtualHostedStyle(config: S3Config): boolean;
|
|
39
|
+
export interface StorageObject {
|
|
40
|
+
key: string;
|
|
41
|
+
etag?: string;
|
|
42
|
+
}
|
|
43
|
+
/** Options for a conditional/typed put. */
|
|
44
|
+
export interface StoragePutOpts {
|
|
45
|
+
contentType?: string;
|
|
46
|
+
/** Conditional create (S3 `If-None-Match: *`): fail with an MhError("conflict")
|
|
47
|
+
* if the object already exists. Used to make first-time key provisioning a
|
|
48
|
+
* compare-and-set so two devices initializing the same empty bucket can't
|
|
49
|
+
* clobber each other's master key. */
|
|
50
|
+
ifNoneMatch?: boolean;
|
|
51
|
+
}
|
|
52
|
+
/** The minimal object-store surface storage-sync needs. Implemented per runtime:
|
|
53
|
+
* Bun.S3Client on the CLI/desktop (storage-s3-bun.ts), aws4fetch SigV4 + fetch
|
|
54
|
+
* in the browser worker (webui/data/storage-s3-browser.ts). */
|
|
55
|
+
export interface StorageClient {
|
|
56
|
+
/** Keys under `prefix`, ascending, optionally only those strictly after
|
|
57
|
+
* `startAfter`. With `delimiter` ("/"), collapse one level into common
|
|
58
|
+
* prefixes (their keys end in the delimiter) to discover child "folders"
|
|
59
|
+
* cheaply — callers must tolerate a backend that ignores it and returns full
|
|
60
|
+
* keys instead. */
|
|
61
|
+
list(prefix: string, startAfter?: string, delimiter?: string): Promise<StorageObject[]>;
|
|
62
|
+
get(key: string): Promise<Uint8Array | null>;
|
|
63
|
+
put(key: string, body: Uint8Array, opts?: StoragePutOpts): Promise<void>;
|
|
64
|
+
del(key: string): Promise<void>;
|
|
65
|
+
}
|
|
66
|
+
type StorageClientFactory = (config: S3Config) => StorageClient;
|
|
67
|
+
/** Register this runtime's S3 client builder (see the per-runtime impls). */
|
|
68
|
+
export declare function setStorageClientFactory(f: StorageClientFactory): void;
|
|
69
|
+
export declare function storageClientFor(config: S3Config): StorageClient;
|
|
70
|
+
/** Upload a blob's bytes to the bucket (idempotent via If-None-Match). Returns
|
|
71
|
+
* true when actually written, false when the object already existed. */
|
|
72
|
+
export declare function putBucketBlob(config: S3Config, hash: string, bytes: Uint8Array): Promise<boolean>;
|
|
73
|
+
/** Every blob hash the bucket durably holds — one paginated LIST of the `blobs/`
|
|
74
|
+
* namespace (the client loops continuation tokens internally). Used by the
|
|
75
|
+
* on-demand clear-presence verify; keeps the `<base>/blobs/<hash>` key layout
|
|
76
|
+
* encapsulated here. Throws if the bucket is unreachable (caller treats the
|
|
77
|
+
* anchor as unverified). */
|
|
78
|
+
export declare function listBucketBlobHashes(config: S3Config): Promise<Set<string>>;
|
|
79
|
+
/** Fetch a blob's bytes from the bucket, or null if absent. */
|
|
80
|
+
export declare function getBucketBlob(config: S3Config, hash: string): Promise<Uint8Array | null>;
|
|
81
|
+
/**
|
|
82
|
+
* Resolve the master key for a bucket at setup: read keys/main.json and unwrap
|
|
83
|
+
* with the passphrase, or — when absent — generate a key, wrap it, and upload
|
|
84
|
+
* it with `If-None-Match` so a concurrent first-time init can't clobber it.
|
|
85
|
+
* Returns base64(K) to store in peers.config, or null when encryption is off.
|
|
86
|
+
* Wrong passphrase throws `auth` (from unwrapMasterKey).
|
|
87
|
+
*/
|
|
88
|
+
export declare function provisionMasterKey(client: StorageClient, config: S3Config, passphrase: string): Promise<string | null>;
|
|
89
|
+
/**
|
|
90
|
+
* Publish a winners-only snapshot and truncate this node's own segments. Every
|
|
91
|
+
* op we've uploaded so far is in the local oplog now, so the snapshot (winners
|
|
92
|
+
* as-of the current max HLC) supersedes all of them — they're safe to delete
|
|
93
|
+
* (compact.ts invariant #1). Ops produced afterwards go into fresh, higher-keyed
|
|
94
|
+
* segments; consumers reach our pre-snapshot state via the snapshot itself.
|
|
95
|
+
*
|
|
96
|
+
* The key is `<maxHlc>~<hash>.snap`: the hash (over the canonical winner set)
|
|
97
|
+
* makes converged nodes collide on one key (deduped) while two nodes that are
|
|
98
|
+
* NOT converged — same max HLC but different extra winners — get distinct keys,
|
|
99
|
+
* so neither overwrites the other. Then old snapshots (strictly lower max-HLC)
|
|
100
|
+
* are GC'd so the bucket stays bounded.
|
|
101
|
+
*
|
|
102
|
+
* Returns the snapshot key + change count, or null when the oplog is empty.
|
|
103
|
+
*/
|
|
104
|
+
export declare function publishSnapshot(db: DbDriver, client: StorageClient, config: S3Config, retainSegments?: number): Promise<{
|
|
105
|
+
key: string;
|
|
106
|
+
changes: number;
|
|
107
|
+
} | null>;
|
|
108
|
+
export interface StorageSyncOpts {
|
|
109
|
+
/** Publisher-only: publish a snapshot + truncate once this node's own segment
|
|
110
|
+
* count reaches this. Default 200 — high enough that typical use rarely hits
|
|
111
|
+
* it, low enough to keep the bucket bounded under heavy publisher use. */
|
|
112
|
+
snapshotEverySegments?: number;
|
|
113
|
+
/** Push-batching: defer uploading our pending own ops until there are at least
|
|
114
|
+
* this many (default 1 → push every round). Coalesces a burst of edits into
|
|
115
|
+
* one segment instead of many tiny ones (each is a billed request + a GET for
|
|
116
|
+
* every puller). */
|
|
117
|
+
minPushChanges?: number;
|
|
118
|
+
/** …or until the oldest pending op is at least this old (ms; default 0 → no
|
|
119
|
+
* age bound). Bounds how long a small trailing edit waits. */
|
|
120
|
+
maxPushAgeMs?: number;
|
|
121
|
+
/** Push regardless of the batching thresholds — use on explicit "sync now" and
|
|
122
|
+
* when the app is backgrounding, so edits are never stranded unsynced. */
|
|
123
|
+
forcePush?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* This node is the bucket's *publisher*: keep the bucket a complete, fresh
|
|
126
|
+
* whole-hub mirror by writing a winners-only snapshot (publishSnapshot) when
|
|
127
|
+
* the bucket has none yet, or when the hub has advanced past the newest
|
|
128
|
+
* snapshot. The snapshot spans the WHOLE db, so it captures data authored by
|
|
129
|
+
* nodes that never push to this bucket themselves (e.g. a server holding the
|
|
130
|
+
* canonical hub while browsers only window onto it) — fixing the "attached a
|
|
131
|
+
* bucket but it stays empty" footgun. Any node holding the full hub can be the
|
|
132
|
+
* publisher; who is one is decided above storage.ts (server by default, else a
|
|
133
|
+
* lease — see publisher-lease.ts). Correctness never depends on a single
|
|
134
|
+
* publisher: concurrent snapshots are content-addressed and idempotent. */
|
|
135
|
+
publish?: boolean;
|
|
136
|
+
/** ⑤d snapshot trigger: publish once the whole-hub delta since the newest
|
|
137
|
+
* snapshot reaches max(`snapshotMinDelta` ops, hub_size × `snapshotDeltaRatio`),
|
|
138
|
+
* or `snapshotMaxIntervalMs` elapsed (safety). Replaces the old 60s timer that
|
|
139
|
+
* re-checkpointed constantly and forced full re-downloads. Defaults:
|
|
140
|
+
* DEFAULT_SNAPSHOT_MIN_DELTA / _DELTA_RATIO / _MAX_INTERVAL_MS. */
|
|
141
|
+
snapshotMinDelta?: number;
|
|
142
|
+
snapshotDeltaRatio?: number;
|
|
143
|
+
snapshotMaxIntervalMs?: number;
|
|
144
|
+
/** ⑤c: keep this many of our most recent own segments alive past a snapshot so
|
|
145
|
+
* slightly-behind consumers catch up incrementally (default DEFAULT_RETAIN_SEGMENTS). */
|
|
146
|
+
snapshotRetainSegments?: number;
|
|
147
|
+
/** This node's publisher priority when contending for the lease (higher wins;
|
|
148
|
+
* see publisher-lease.ts). Only consulted when `publish` is set. */
|
|
149
|
+
priority?: number;
|
|
150
|
+
/**
|
|
151
|
+
* Run the PULL half of the round (snapshots + other nodes' segments). Default
|
|
152
|
+
* true. Set false for *push-only* rounds: an origin-backed replica gets a
|
|
153
|
+
* superset of bucket contents from its origin (HTTP), so it never needs to PULL
|
|
154
|
+
* the bucket — it only PUSHes its own segments here for independent durability
|
|
155
|
+
* (Path B). Skipping PULL drops the two unconditional LISTs (snapshot/, oplog/)
|
|
156
|
+
* that dominate idle bucket cost. A *publisher* must always PULL (it needs the
|
|
157
|
+
* snapshot list to decide what to publish), so callers never combine
|
|
158
|
+
* `publish:true` with `pull:false`.
|
|
159
|
+
*/
|
|
160
|
+
pull?: boolean;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* One push/pull round against a storage peer. Push uploads this node's pending
|
|
164
|
+
* own ops as a new segment (subject to batching); pull hydrates from snapshots
|
|
165
|
+
* (any not yet ingested) then drains each other node's new segments. Returns
|
|
166
|
+
* { pushed, pulled } like syncWithPeer so peers.ts status writeback is shared.
|
|
167
|
+
*/
|
|
168
|
+
export declare function syncWithStorage(db: DbDriver, peerUrl: string, client: StorageClient, config: S3Config, opts?: StorageSyncOpts): Promise<SyncResult>;
|
|
169
|
+
export {};
|
|
170
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/core/sync/storage.ts"],"names":[],"mappings":"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"}
|