@fairfox/polly 0.57.0 → 0.59.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.
|
@@ -23,6 +23,7 @@ import { Repo, type StorageAdapterInterface } from "@automerge/automerge-repo/sl
|
|
|
23
23
|
import type { KeyringStorage } from "./keyring-storage";
|
|
24
24
|
import { type MeshKeyring, MeshNetworkAdapter } from "./mesh-network-adapter";
|
|
25
25
|
import { MeshSignalingClient, type MeshSignalingClientOptions } from "./mesh-signaling-client";
|
|
26
|
+
import { type MeshStateLoadedRejectionBreadcrumb } from "./mesh-state";
|
|
26
27
|
import { MeshWebRTCAdapter, type MeshWebRTCAdapterOptions } from "./mesh-webrtc-adapter";
|
|
27
28
|
/** Options for {@link createMeshClient}. */
|
|
28
29
|
export interface CreateMeshClientOptions {
|
|
@@ -197,6 +198,64 @@ export interface MeshClientHandleSnapshot {
|
|
|
197
198
|
* asking. */
|
|
198
199
|
lastSyncMessageOutType: string | undefined;
|
|
199
200
|
}
|
|
201
|
+
/** Polly#107 H5 diagnostics: surfaces the `mesh-state` module
|
|
202
|
+
* instance identity so a single snapshot read tells the operator
|
|
203
|
+
* whether the consumer's `$meshState` wrappers are resolving against
|
|
204
|
+
* the same module instance `createMeshClient` configured. A mismatch
|
|
205
|
+
* here IS the bundle-time module duplication bug. */
|
|
206
|
+
export interface MeshStateModuleDiagnostics {
|
|
207
|
+
/** The id stamped at import time on the `mesh-state` module
|
|
208
|
+
* instance THIS mesh client was constructed against. Compare to
|
|
209
|
+
* the id seen at the `$meshState` call site (also importable as
|
|
210
|
+
* `MESH_STATE_MODULE_ID` from `@fairfox/polly/mesh`). Two different
|
|
211
|
+
* ids means the consumer is reaching a duplicated copy of
|
|
212
|
+
* `mesh-state.ts` — wrappers register handles against a Repo this
|
|
213
|
+
* mesh client never saw. */
|
|
214
|
+
moduleId: string;
|
|
215
|
+
/** `true` iff THIS module instance has a configured `defaultRepo`.
|
|
216
|
+
* In the H5 scenario, this is `true` for the mesh-client-side
|
|
217
|
+
* snapshot (because `createMeshClient` always calls
|
|
218
|
+
* `configureMeshState` on the module it imports), but the same
|
|
219
|
+
* field read from the consumer's `$meshState` call site would
|
|
220
|
+
* be `false`. */
|
|
221
|
+
configured: boolean;
|
|
222
|
+
/** `peerId` of the most recent Repo wired through
|
|
223
|
+
* `configureMeshState` against THIS module instance. Compared to
|
|
224
|
+
* `client.repo.peerId` and the consumer's wrappers' resolved Repo
|
|
225
|
+
* tells the full story. */
|
|
226
|
+
lastConfiguredRepoPeerId: string | undefined;
|
|
227
|
+
/** `true` if any `$meshState`-family wrapper has been called
|
|
228
|
+
* against THIS module instance at any point. The polly#107 H5
|
|
229
|
+
* fingerprint pair: `configured: true, wasResolved: false` on
|
|
230
|
+
* the mesh-client-side snapshot (the wrappers never reached us);
|
|
231
|
+
* the consumer's wrapper code reading the same field from THEIR
|
|
232
|
+
* `$meshState` import would see `configured: false, wasResolved:
|
|
233
|
+
* true` (they're using a module instance no mesh client ever
|
|
234
|
+
* configured). */
|
|
235
|
+
wasResolved: boolean;
|
|
236
|
+
/** Polly#107 post-H5 instrumentation. Count of `$meshState`-family
|
|
237
|
+
* lazy factory invocations since module load. Once the consumer's
|
|
238
|
+
* pre-warm pass completes, this equals the number of distinct
|
|
239
|
+
* `$mesh*` wrappers whose handles the loader actually tried to
|
|
240
|
+
* resolve. Compared to {@link lazyReachedRepo}: gap = throws
|
|
241
|
+
* before any Repo work. */
|
|
242
|
+
lazyInvocations: number;
|
|
243
|
+
/** Polly#107 post-H5 instrumentation. Count of factory invocations
|
|
244
|
+
* that reached the Repo subsystem (`repo.handles[...]`, `repo.find`
|
|
245
|
+
* or `repo.import`) before returning or throwing. If
|
|
246
|
+
* {@link lazyInvocations} is N and this is N, every wrapper
|
|
247
|
+
* touched the Repo — any missing handles are downstream of Repo
|
|
248
|
+
* registration. If this is < N, the gap is the call site to
|
|
249
|
+
* instrument next. */
|
|
250
|
+
lazyReachedRepo: number;
|
|
251
|
+
/** Polly#107 post-H5 instrumentation. Breadcrumb for the most
|
|
252
|
+
* recent rejection from a `$meshState`-family `loaded` promise
|
|
253
|
+
* (or its factory). Captured even when the consumer's wrapper
|
|
254
|
+
* never awaits `loaded` and the rejection would otherwise vanish
|
|
255
|
+
* silently. `undefined` means no rejection has escaped any
|
|
256
|
+
* wrapper on THIS module instance since module load. */
|
|
257
|
+
lastLoadedRejection: MeshStateLoadedRejectionBreadcrumb | undefined;
|
|
258
|
+
}
|
|
200
259
|
/** The mesh client's enriched per-peer state snapshot. Mirrors the
|
|
201
260
|
* underlying {@link MeshWebRTCAdapter.getPeerStateSnapshot} shape but
|
|
202
261
|
* replaces the slot's `handles` map with the Repo-enriched view
|
|
@@ -211,6 +270,19 @@ export interface MeshClientPeerStateSnapshot {
|
|
|
211
270
|
handles: Record<string, MeshClientHandleSnapshot>;
|
|
212
271
|
});
|
|
213
272
|
}>;
|
|
273
|
+
/** polly#107 H5 diagnostics. See {@link MeshStateModuleDiagnostics}. */
|
|
274
|
+
meshStateModule: MeshStateModuleDiagnostics;
|
|
275
|
+
/** Count of handles known to the Repo this client owns. Compared
|
|
276
|
+
* to the count the consumer's `$meshState` wrappers should have
|
|
277
|
+
* registered: a mismatch (e.g. consumer pre-warmed 14 wrappers,
|
|
278
|
+
* snapshot reports 1) confirms the H5 module-duplication
|
|
279
|
+
* fingerprint without needing a separate read. */
|
|
280
|
+
repoHandleCount: number;
|
|
281
|
+
/** All handle ids the Repo this client owns currently caches.
|
|
282
|
+
* Together with `repoHandleCount` and `meshStateModule.moduleId`,
|
|
283
|
+
* this answers "did the consumer's wrappers land their handles in
|
|
284
|
+
* THIS Repo?" in one read. */
|
|
285
|
+
repoHandleIds: string[];
|
|
214
286
|
}
|
|
215
287
|
/** Handle returned by {@link createMeshClient}. */
|
|
216
288
|
export interface MeshClient {
|
|
@@ -56,6 +56,41 @@ export interface MeshStateOptions {
|
|
|
56
56
|
* a public-key set used by the signing layer to verify incoming ops. */
|
|
57
57
|
access?: Access;
|
|
58
58
|
}
|
|
59
|
+
/** Per-module-instance identifier stamped at import time. Two distinct
|
|
60
|
+
* module instances (e.g. duplicated under a bundler that hoists
|
|
61
|
+
* differently for the consumer's app code and `@fairfox/polly`'s own
|
|
62
|
+
* imports) produce two different ids — and therefore two different
|
|
63
|
+
* `defaultRepo` globals.
|
|
64
|
+
*
|
|
65
|
+
* The polly#107 fingerprint reading is exactly that: `configureMeshState`
|
|
66
|
+
* runs on one module instance (the one `createMeshClient` imports);
|
|
67
|
+
* the consumer's `$meshState(key, initial)` calls run on a different
|
|
68
|
+
* instance, whose `defaultRepo` was never set. `resolveRepo` either
|
|
69
|
+
* throws (caught silently by consumer wrappers) or returns the
|
|
70
|
+
* unconfigured fallback — either way, the handle that should land
|
|
71
|
+
* in the mesh `Repo` lands somewhere else (or nowhere), Automerge's
|
|
72
|
+
* NetworkSubsystem never sees it, and inbound sync from the daemon
|
|
73
|
+
* has nowhere to go.
|
|
74
|
+
*
|
|
75
|
+
* Exported so consumers can compare the id seen at the `$meshState`
|
|
76
|
+
* call site against the id seen at the `configureMeshState` call
|
|
77
|
+
* site. A mismatch IS the bundle-duplication bug; a match rules it
|
|
78
|
+
* out. The id is also surfaced via {@link getMeshStateModuleId} on
|
|
79
|
+
* every `MeshClient.getPeerStateSnapshot()` so a single one-line
|
|
80
|
+
* read from the failing tab tells the operator which module
|
|
81
|
+
* instance the snapshot is rendered from.
|
|
82
|
+
*
|
|
83
|
+
* Polly issue #107 H5 (mesh-state module duplication). */
|
|
84
|
+
export declare const MESH_STATE_MODULE_ID: string;
|
|
85
|
+
/** Returns the per-module-instance id stamped at import time. See
|
|
86
|
+
* {@link MESH_STATE_MODULE_ID}. */
|
|
87
|
+
export declare function getMeshStateModuleId(): string;
|
|
88
|
+
/** Returns the `peerId` of the most recent Repo wired through
|
|
89
|
+
* {@link configureMeshState} against this module instance. Surfaced
|
|
90
|
+
* via the mesh client snapshot so a consumer can answer "did
|
|
91
|
+
* configureMeshState run on the same module instance the wrappers
|
|
92
|
+
* are using" in one read. */
|
|
93
|
+
export declare function getLastConfiguredRepoPeerId(): string | undefined;
|
|
59
94
|
/**
|
|
60
95
|
* Set the default Repo that the $mesh* primitives use when no `repo` option
|
|
61
96
|
* is supplied. Production code typically calls this once at application
|
|
@@ -68,6 +103,43 @@ export declare function configureMeshState(repo: Repo): void;
|
|
|
68
103
|
* Intended for tests; production code should not call this.
|
|
69
104
|
*/
|
|
70
105
|
export declare function resetMeshState(): void;
|
|
106
|
+
/** Returns whether this module instance's `defaultRepo` was ever
|
|
107
|
+
* set via {@link configureMeshState}. Distinct from "was set and
|
|
108
|
+
* then reset" — `resetMeshState` clears it. The polly#107 H5
|
|
109
|
+
* fingerprint is `false` here on the module instance the consumer's
|
|
110
|
+
* `$meshState` calls resolve from. */
|
|
111
|
+
export declare function isMeshStateConfigured(): boolean;
|
|
112
|
+
/** Returns `true` once any `$meshState`-family wrapper has been
|
|
113
|
+
* called against this module instance. See
|
|
114
|
+
* {@link meshStateEverResolved}. */
|
|
115
|
+
export declare function wasMeshStateResolved(): boolean;
|
|
116
|
+
/** Returns the count of factory invocations since module load. See
|
|
117
|
+
* {@link lazyInvocations}. */
|
|
118
|
+
export declare function getLazyInvocations(): number;
|
|
119
|
+
/** Returns the count of factory invocations that reached
|
|
120
|
+
* `repo.find` / `repo.import` since module load. See
|
|
121
|
+
* {@link lazyReachedRepo}. */
|
|
122
|
+
export declare function getLazyReachedRepo(): number;
|
|
123
|
+
/** Polly#107 post-H5 instrumentation. Records the most recent
|
|
124
|
+
* rejection (or synchronous throw) escaping the factory body — the
|
|
125
|
+
* `loaded` promise's rejection path. Today an unawaited rejection
|
|
126
|
+
* inside a consumer wrapper vanishes without trace; capturing the
|
|
127
|
+
* message + stack here on the module and exposing it via the
|
|
128
|
+
* snapshot leaves a breadcrumb the operator can read in one paste.
|
|
129
|
+
*
|
|
130
|
+
* The format is the JSON-safe `{ name, message, stack, at }` shape
|
|
131
|
+
* so the snapshot read does not have to traffic in `Error`
|
|
132
|
+
* instances. `at` is `Date.now()` at the time the rejection was
|
|
133
|
+
* captured. */
|
|
134
|
+
export interface MeshStateLoadedRejectionBreadcrumb {
|
|
135
|
+
name: string;
|
|
136
|
+
message: string;
|
|
137
|
+
stack: string | undefined;
|
|
138
|
+
at: number;
|
|
139
|
+
}
|
|
140
|
+
/** Returns the most recent rejection escaping a `$meshState` factory
|
|
141
|
+
* invocation since module load. See {@link lastLoadedRejection}. */
|
|
142
|
+
export declare function getLastLoadedRejection(): MeshStateLoadedRejectionBreadcrumb | undefined;
|
|
71
143
|
/**
|
|
72
144
|
* Create a peer-replicated state primitive backed by Automerge with a mesh
|
|
73
145
|
* transport. Every device holds a full replica; no central server holds a
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fairfox/polly",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.59.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Multi-execution-context framework with reactive state and cross-context messaging for Chrome extensions, PWAs, and worker-based applications",
|