@spooky-sync/core 0.0.1-canary.155 → 0.0.1-canary.156
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/index.js +25 -14
- package/dist/types.d.ts +7 -0
- package/package.json +3 -3
- package/src/modules/devtools/index.ts +6 -4
- package/src/modules/devtools/storage-info.ts +27 -0
- package/src/sp00ky.ts +21 -9
package/dist/index.js
CHANGED
|
@@ -5694,8 +5694,8 @@ async function walkOpfs(maxEntries = 2e3, maxDepth = 8) {
|
|
|
5694
5694
|
|
|
5695
5695
|
//#endregion
|
|
5696
5696
|
//#region src/modules/devtools/index.ts
|
|
5697
|
-
const CORE_VERSION = "0.0.1-canary.
|
|
5698
|
-
const WASM_VERSION = "0.0.1-canary.
|
|
5697
|
+
const CORE_VERSION = "0.0.1-canary.156";
|
|
5698
|
+
const WASM_VERSION = "0.0.1-canary.156";
|
|
5699
5699
|
const SURREAL_VERSION = "3.0.3";
|
|
5700
5700
|
var DevToolsService = class {
|
|
5701
5701
|
eventsHistory = [];
|
|
@@ -5703,7 +5703,8 @@ var DevToolsService = class {
|
|
|
5703
5703
|
version = CORE_VERSION;
|
|
5704
5704
|
backendInfo = emptyBackendInfo();
|
|
5705
5705
|
enabled = false;
|
|
5706
|
-
/** Shared-tabs snapshot for the panel, wired by Sp00kyClient
|
|
5706
|
+
/** Shared-tabs snapshot for the panel, wired by Sp00kyClient whenever the
|
|
5707
|
+
* feature was REQUESTED (so an inactive/degraded tab still reports why). */
|
|
5707
5708
|
tabsInfoProvider = null;
|
|
5708
5709
|
setTabsInfoProvider(provider) {
|
|
5709
5710
|
this.tabsInfoProvider = provider;
|
|
@@ -5925,6 +5926,7 @@ var DevToolsService = class {
|
|
|
5925
5926
|
status: "unknown",
|
|
5926
5927
|
fallback: false
|
|
5927
5928
|
},
|
|
5929
|
+
tabs: this.tabsInfoProvider?.() ?? null,
|
|
5928
5930
|
browser: {},
|
|
5929
5931
|
opfs: {
|
|
5930
5932
|
supported: false,
|
|
@@ -8784,24 +8786,33 @@ var Sp00kyClient = class {
|
|
|
8784
8786
|
this.devTools = new DevToolsService(this.local, this.remote, logger, this.config.schema, this.auth, this.dataModule);
|
|
8785
8787
|
this.streamProcessor.addReceiver(this.devTools);
|
|
8786
8788
|
this.setupCallbacks();
|
|
8787
|
-
if (tabsSupport.supported)
|
|
8788
|
-
|
|
8789
|
+
if (tabsSupport.supported) this.tabsCoordinator = this.buildTabsCoordinator();
|
|
8790
|
+
else if (this.config.sharedTabs) this.logger.info({
|
|
8791
|
+
reason: tabsSupport.reason,
|
|
8792
|
+
Category: "sp00ky-client::Sp00kyClient::tabs"
|
|
8793
|
+
}, "sharedTabs requested but unsupported here; running solo");
|
|
8794
|
+
if (this.config.sharedTabs) {
|
|
8795
|
+
const unsupportedReason = tabsSupport.supported ? void 0 : tabsSupport.reason;
|
|
8789
8796
|
this.devTools.setTabsInfoProvider(() => {
|
|
8790
|
-
if (!this.sharedActive || !this.tabsCoordinator) return null;
|
|
8791
8797
|
const c = this.tabsCoordinator;
|
|
8798
|
+
if (!this.sharedActive || !c) return {
|
|
8799
|
+
active: false,
|
|
8800
|
+
reason: unsupportedReason ?? "fell-back"
|
|
8801
|
+
};
|
|
8802
|
+
const hub = c.syncHub;
|
|
8792
8803
|
return {
|
|
8804
|
+
active: true,
|
|
8793
8805
|
role: c.role,
|
|
8794
8806
|
tabId: c.tabId,
|
|
8795
8807
|
leadershipId: c.leadershipId,
|
|
8796
|
-
leaderTabId: c.leaderTabId,
|
|
8797
|
-
|
|
8798
|
-
|
|
8808
|
+
leaderTabId: c.role === "leader" ? c.tabId : c.leaderTabId,
|
|
8809
|
+
...hub ? {
|
|
8810
|
+
followers: hub.followerCount,
|
|
8811
|
+
relayedBatches: hub.relayedBatches
|
|
8812
|
+
} : {}
|
|
8799
8813
|
};
|
|
8800
8814
|
});
|
|
8801
|
-
}
|
|
8802
|
-
reason: tabsSupport.reason,
|
|
8803
|
-
Category: "sp00ky-client::Sp00kyClient::tabs"
|
|
8804
|
-
}, "sharedTabs requested but unsupported here; running solo");
|
|
8815
|
+
}
|
|
8805
8816
|
}
|
|
8806
8817
|
/** The shared-tabs role machinery, wired to this client's modules. */
|
|
8807
8818
|
buildTabsCoordinator() {
|
|
@@ -8810,7 +8821,7 @@ var Sp00kyClient = class {
|
|
|
8810
8821
|
return new TabsCoordinator({
|
|
8811
8822
|
tabId,
|
|
8812
8823
|
fingerprint: computeTabsFingerprint({
|
|
8813
|
-
coreVersion: "0.0.1-canary.
|
|
8824
|
+
coreVersion: "0.0.1-canary.156",
|
|
8814
8825
|
schemaHash: hash53(this.config.schemaSurql),
|
|
8815
8826
|
endpoint: this.config.database.endpoint ?? "",
|
|
8816
8827
|
namespace: this.config.database.namespace,
|
package/dist/types.d.ts
CHANGED
|
@@ -199,6 +199,13 @@ interface EngineStorageDiagnostics {
|
|
|
199
199
|
}[];
|
|
200
200
|
error?: string;
|
|
201
201
|
}
|
|
202
|
+
/**
|
|
203
|
+
* Shared-tabs coordination state. Reported ONLY when `sharedTabs: true` was
|
|
204
|
+
* configured (apps that never asked for it get `null`, so the panel shows
|
|
205
|
+
* nothing). `active: false` with a `reason` is itself the useful signal: the
|
|
206
|
+
* app asked to share one store and this tab is not, so it owns or contends for
|
|
207
|
+
* the OPFS pool alone.
|
|
208
|
+
*/
|
|
202
209
|
//#endregion
|
|
203
210
|
//#region src/services/database/cache-engine.d.ts
|
|
204
211
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spooky-sync/core",
|
|
3
|
-
"version": "0.0.1-canary.
|
|
3
|
+
"version": "0.0.1-canary.156",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -60,8 +60,8 @@
|
|
|
60
60
|
}
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@spooky-sync/query-builder": "0.0.1-canary.
|
|
64
|
-
"@spooky-sync/ssp-wasm": "0.0.1-canary.
|
|
63
|
+
"@spooky-sync/query-builder": "0.0.1-canary.156",
|
|
64
|
+
"@spooky-sync/ssp-wasm": "0.0.1-canary.156",
|
|
65
65
|
"@sqlite.org/sqlite-wasm": "3.53.0-build1",
|
|
66
66
|
"@surrealdb/wasm": "^3.0.3",
|
|
67
67
|
"fast-json-patch": "^3.1.1",
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
parseBackendInfo,
|
|
23
23
|
UNAVAILABLE,
|
|
24
24
|
} from './versions';
|
|
25
|
-
import { walkOpfs, type StorageInfo } from './storage-info';
|
|
25
|
+
import { walkOpfs, type SharedTabsInfo, type StorageInfo } from './storage-info';
|
|
26
26
|
|
|
27
27
|
// Real bundled frontend versions, injected at build time by tsdown's
|
|
28
28
|
// version-define plugin (see tsdown.config.ts). The `typeof` guard keeps these
|
|
@@ -51,10 +51,11 @@ export class DevToolsService implements StreamUpdateReceiver {
|
|
|
51
51
|
// (the on-demand GET_STATE pull) still works before the push channel turns on.
|
|
52
52
|
private enabled = false;
|
|
53
53
|
|
|
54
|
-
/** Shared-tabs snapshot for the panel, wired by Sp00kyClient
|
|
55
|
-
|
|
54
|
+
/** Shared-tabs snapshot for the panel, wired by Sp00kyClient whenever the
|
|
55
|
+
* feature was REQUESTED (so an inactive/degraded tab still reports why). */
|
|
56
|
+
private tabsInfoProvider: (() => SharedTabsInfo | null) | null = null;
|
|
56
57
|
|
|
57
|
-
setTabsInfoProvider(provider: () =>
|
|
58
|
+
setTabsInfoProvider(provider: () => SharedTabsInfo | null): void {
|
|
58
59
|
this.tabsInfoProvider = provider;
|
|
59
60
|
}
|
|
60
61
|
|
|
@@ -357,6 +358,7 @@ export class DevToolsService implements StreamUpdateReceiver {
|
|
|
357
358
|
bucketId: this.databaseService.currentBucketId,
|
|
358
359
|
},
|
|
359
360
|
health: this.databaseService.storageHealth ?? { status: 'unknown', fallback: false },
|
|
361
|
+
tabs: this.tabsInfoProvider?.() ?? null,
|
|
360
362
|
browser: {},
|
|
361
363
|
opfs: { supported: false, entries: [], totalBytes: 0, truncated: false },
|
|
362
364
|
};
|
|
@@ -31,10 +31,37 @@ export interface EngineStorageDiagnostics {
|
|
|
31
31
|
error?: string;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Shared-tabs coordination state. Reported ONLY when `sharedTabs: true` was
|
|
36
|
+
* configured (apps that never asked for it get `null`, so the panel shows
|
|
37
|
+
* nothing). `active: false` with a `reason` is itself the useful signal: the
|
|
38
|
+
* app asked to share one store and this tab is not, so it owns or contends for
|
|
39
|
+
* the OPFS pool alone.
|
|
40
|
+
*/
|
|
41
|
+
export interface SharedTabsInfo {
|
|
42
|
+
active: boolean;
|
|
43
|
+
/** Why inactive: a capability gate reason, or 'fell-back' when the broker
|
|
44
|
+
* was reachable but no role landed (election timeout, rejected tab). */
|
|
45
|
+
reason?: string;
|
|
46
|
+
role?: 'solo' | 'leader' | 'follower';
|
|
47
|
+
/** This tab's id (also the suffix of every mutation id it mints). */
|
|
48
|
+
tabId?: string;
|
|
49
|
+
/** Monotonic id of the current leadership term; embedded in the worker lock. */
|
|
50
|
+
leadershipId?: number;
|
|
51
|
+
/** Who owns the store: this tab when leader, else the leader's tab id. */
|
|
52
|
+
leaderTabId?: string | null;
|
|
53
|
+
/** Leader only: attached follower tabs. */
|
|
54
|
+
followers?: number;
|
|
55
|
+
/** Leader only: ingest batches relayed to followers so far. */
|
|
56
|
+
relayedBatches?: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
34
59
|
export interface StorageInfo {
|
|
35
60
|
at: number;
|
|
36
61
|
engine: { kind: 'surrealdb' | 'sqlite' | 'custom'; store: string; bucketId: string };
|
|
37
62
|
health: { status: 'unknown' | 'persistent' | 'memory'; fallback: boolean; error?: string };
|
|
63
|
+
/** Shared-tabs state, or null when the feature was never requested. */
|
|
64
|
+
tabs?: SharedTabsInfo | null;
|
|
38
65
|
browser: {
|
|
39
66
|
/** `navigator.storage.persisted()` — whether the origin's storage is
|
|
40
67
|
* exempt from eviction (unrelated to the OPFS pool lock). */
|
package/src/sp00ky.ts
CHANGED
|
@@ -368,23 +368,35 @@ export class Sp00kyClient<S extends SchemaStructure> {
|
|
|
368
368
|
// every module. Nothing starts until init() calls coordinator.start().
|
|
369
369
|
if (tabsSupport.supported) {
|
|
370
370
|
this.tabsCoordinator = this.buildTabsCoordinator();
|
|
371
|
+
} else if (this.config.sharedTabs) {
|
|
372
|
+
this.logger.info(
|
|
373
|
+
{ reason: (tabsSupport as { reason: string }).reason, Category: 'sp00ky-client::Sp00kyClient::tabs' },
|
|
374
|
+
'sharedTabs requested but unsupported here; running solo'
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
// Report shared-tabs state whenever the feature was REQUESTED, active or
|
|
378
|
+
// not: "asked to share one store, running alone because X" is exactly the
|
|
379
|
+
// thing you need to see in the panel. Apps that never set the flag report
|
|
380
|
+
// null and the panel shows no section at all.
|
|
381
|
+
if (this.config.sharedTabs) {
|
|
382
|
+
const unsupportedReason = tabsSupport.supported
|
|
383
|
+
? undefined
|
|
384
|
+
: (tabsSupport as { reason: string }).reason;
|
|
371
385
|
this.devTools.setTabsInfoProvider(() => {
|
|
372
|
-
if (!this.sharedActive || !this.tabsCoordinator) return null;
|
|
373
386
|
const c = this.tabsCoordinator;
|
|
387
|
+
if (!this.sharedActive || !c) {
|
|
388
|
+
return { active: false, reason: unsupportedReason ?? 'fell-back' };
|
|
389
|
+
}
|
|
390
|
+
const hub = c.syncHub;
|
|
374
391
|
return {
|
|
392
|
+
active: true,
|
|
375
393
|
role: c.role,
|
|
376
394
|
tabId: c.tabId,
|
|
377
395
|
leadershipId: c.leadershipId,
|
|
378
|
-
leaderTabId: c.leaderTabId,
|
|
379
|
-
followers:
|
|
380
|
-
relayedBatches: c.syncHub?.relayedBatches ?? null,
|
|
396
|
+
leaderTabId: c.role === 'leader' ? c.tabId : c.leaderTabId,
|
|
397
|
+
...(hub ? { followers: hub.followerCount, relayedBatches: hub.relayedBatches } : {}),
|
|
381
398
|
};
|
|
382
399
|
});
|
|
383
|
-
} else if (this.config.sharedTabs) {
|
|
384
|
-
this.logger.info(
|
|
385
|
-
{ reason: (tabsSupport as { reason: string }).reason, Category: 'sp00ky-client::Sp00kyClient::tabs' },
|
|
386
|
-
'sharedTabs requested but unsupported here; running solo'
|
|
387
|
-
);
|
|
388
400
|
}
|
|
389
401
|
}
|
|
390
402
|
|