cross-tab-worker-databus 0.20.93 → 0.20.95
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/CHANGELOG.md +22 -0
- package/dist/centrifuge.d.ts +4 -4
- package/dist/centrifuge.d.ts.map +1 -1
- package/dist/centrifuge.js +13 -14
- package/dist/centrifuge.js.map +2 -2
- package/dist/centrifuge.shared.worker.js +44 -21
- package/dist/centrifuge.shared.worker.js.map +3 -3
- package/dist/centrifuge.worker.js +44 -21
- package/dist/centrifuge.worker.js.map +3 -3
- package/dist/{chunk-OXEPZGXR.js → chunk-7BPB2Y4E.js} +18 -14
- package/dist/chunk-7BPB2Y4E.js.map +7 -0
- package/dist/cjs/centrifuge.cjs +29 -26
- package/dist/cjs/centrifuge.cjs.map +2 -2
- package/dist/cjs/hooks.cjs +1 -4
- package/dist/cjs/hooks.cjs.map +2 -2
- package/dist/cjs/index.cjs +17 -13
- package/dist/cjs/index.cjs.map +2 -2
- package/dist/cjs/vue.cjs +1 -5
- package/dist/cjs/vue.cjs.map +2 -2
- package/dist/core/cluster.d.ts.map +1 -1
- package/dist/core/environment.d.ts.map +1 -1
- package/dist/core/storage-batch.d.ts.map +1 -1
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +1 -4
- package/dist/hooks.js.map +2 -2
- package/dist/index.js +1 -1
- package/dist/vue.d.ts.map +1 -1
- package/dist/vue.js +1 -5
- package/dist/vue.js.map +2 -2
- package/docs/benchmarks.md +10 -10
- package/docs/configuration.md +3 -1
- package/docs/release-checklist.md +2 -2
- package/docs/roadmap.md +21 -6
- package/docs/zh/benchmarks.md +10 -10
- package/docs/zh/configuration.md +3 -1
- package/docs/zh/release-checklist.md +2 -2
- package/docs/zh/roadmap.md +21 -6
- package/package.json +3 -2
- package/dist/chunk-OXEPZGXR.js.map +0 -7
package/dist/cjs/vue.cjs
CHANGED
|
@@ -73,7 +73,6 @@ function useCrossTabSubscription(bus, topic, handler) {
|
|
|
73
73
|
let currentBus = null;
|
|
74
74
|
let currentTopic = null;
|
|
75
75
|
let cleanup;
|
|
76
|
-
let latestHandler = handler;
|
|
77
76
|
const stop = () => {
|
|
78
77
|
cleanup?.();
|
|
79
78
|
cleanup = void 0;
|
|
@@ -88,13 +87,10 @@ function useCrossTabSubscription(bus, topic, handler) {
|
|
|
88
87
|
if (!nextBus) return;
|
|
89
88
|
currentBus = nextBus;
|
|
90
89
|
currentTopic = nextTopic;
|
|
91
|
-
cleanup = nextBus.subscribe(nextTopic,
|
|
90
|
+
cleanup = nextBus.subscribe(nextTopic, handler);
|
|
92
91
|
};
|
|
93
92
|
(0, import_vue.watch)(bus, sync, { immediate: true });
|
|
94
93
|
if (typeof topic !== "string") (0, import_vue.watch)(topic, sync);
|
|
95
|
-
(0, import_vue.watch)(() => handler, (value) => {
|
|
96
|
-
latestHandler = value;
|
|
97
|
-
});
|
|
98
94
|
(0, import_vue.onBeforeUnmount)(stop);
|
|
99
95
|
}
|
|
100
96
|
function useCrossTabStatus(bus) {
|
package/dist/cjs/vue.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/vue.ts", "../../src/utils/constants.ts"],
|
|
4
|
-
"sourcesContent": ["/** Vue 3 composables adapter for cross-tab-worker-databus.\n * Vue is an optional peer dependency; this module is a separate entry point.\n */\nimport { onBeforeUnmount, onMounted, ref, shallowRef, watch, type Ref } from 'vue';\nimport type { CrossTabDataBus, DataBusHealthSummary } from './core/data-bus';\nimport type { DataBusMessage, WorkerStatus } from './core/types';\nimport { WORKER_STATUS } from './utils/constants';\n\nexport function useCrossTabDataBus<TConfig, TData>(\n create: () => CrossTabDataBus<TConfig, TData>,\n deps: ReadonlyArray<Ref<unknown> | (() => unknown)> = []\n): Ref<CrossTabDataBus<TConfig, TData> | null> {\n const bus = shallowRef<CrossTabDataBus<TConfig, TData> | null>(null);\n let instance: CrossTabDataBus<TConfig, TData> | null = null;\n let lifecycleGeneration = 0;\n const stop = async () => { const current = instance; instance = null; bus.value = null; if (current) await current.stop(); };\n const start = () => {\n const generation = ++lifecycleGeneration;\n void stop().then(() => {\n if (generation !== lifecycleGeneration) return;\n const next = create();\n instance = next;\n bus.value = next;\n void next.ready().catch(() => {});\n });\n };\n onMounted(start);\n onBeforeUnmount(() => {\n // Bump the generation so a start() still awaiting its stop() sees itself\n // superseded. Without this the pending continuation would run create()\n // after the component is gone, leaving a live bus with no owner to stop\n // it (the React adapter has no such window: its create() is synchronous\n // inside useEffect).\n lifecycleGeneration += 1;\n void stop();\n });\n if (deps.length > 0) watch(deps, start);\n return bus as Ref<CrossTabDataBus<TConfig, TData> | null>;\n}\n\nexport function useCrossTabSubscription<TConfig, TData>(\n bus: Ref<CrossTabDataBus<TConfig, TData> | null>, topic: Ref<string> | string,\n handler: (message: DataBusMessage<TData>) => void\n): void {\n let currentBus: CrossTabDataBus<TConfig, TData> | null = null;\n let currentTopic: string | null = null;\n let cleanup: (() => void) | undefined;\n let latestHandler = handler;\n const stop = () => { cleanup?.(); cleanup = undefined; currentBus = null; currentTopic = null; };\n const sync = () => {\n const nextBus = bus.value;\n const nextTopic = typeof topic === 'string' ? topic : topic.value;\n if (nextBus === currentBus && currentTopic === nextTopic && cleanup) return;\n stop();\n if (!nextBus) return;\n currentBus = nextBus;\n currentTopic = nextTopic;\n cleanup = nextBus.subscribe(nextTopic, message => latestHandler(message));\n };\n watch(bus, sync, { immediate: true });\n if (typeof topic !== 'string') watch(topic, sync);\n watch(() => handler, value => { latestHandler = value; });\n onBeforeUnmount(stop);\n}\n\nexport function useCrossTabStatus<TConfig, TData>(\n bus: Ref<CrossTabDataBus<TConfig, TData> | null>\n): Ref<WorkerStatus> {\n const status = ref<WorkerStatus>(WORKER_STATUS.CONNECTING);\n let cleanup: (() => void) | undefined;\n watch(bus, next => {\n cleanup?.(); cleanup = undefined;\n status.value = next?.getStatus() ?? WORKER_STATUS.CONNECTING;\n if (next) cleanup = next.onStatus(value => { status.value = value; });\n }, { immediate: true });\n onBeforeUnmount(() => cleanup?.());\n return status;\n}\n\n/** Options for {@link useCrossTabHealth}. */\nexport interface UseCrossTabHealthOptions {\n /** Polling cadence in ms for the health snapshot. Default 1000; `0` disables\n * polling and relies on status/error events only. */\n intervalMs?: number;\n}\n\n/**\n * Mirror the bus health summary into a Vue ref. `getHealthSummary()` is a\n * snapshot, so the composable polls it on an interval (default 1000 ms) and\n * refreshes on status changes and errors. A reactive interval change replaces\n * the timer without rebuilding the bus. Returns `null` until the bus exists.\n */\nexport function useCrossTabHealth<TConfig, TData>(\n bus: Ref<CrossTabDataBus<TConfig, TData> | null>,\n options?: UseCrossTabHealthOptions\n): Ref<DataBusHealthSummary | null> {\n const health = ref<DataBusHealthSummary | null>(null);\n let timer: ReturnType<typeof setInterval> | null = null;\n let cleanups: Array<() => void> = [];\n const teardown = () => {\n if (timer) clearInterval(timer);\n timer = null;\n for (const cleanup of cleanups) cleanup();\n cleanups = [];\n };\n watch([bus, () => options?.intervalMs], ([next]) => {\n teardown();\n if (!next) {\n health.value = null;\n return;\n }\n const refresh = () => { health.value = next.getHealthSummary(); };\n refresh();\n cleanups.push(next.onStatus(refresh));\n cleanups.push(next.onError(refresh));\n const intervalMs = options?.intervalMs ?? 1_000;\n if (intervalMs > 0) timer = setInterval(refresh, intervalMs);\n }, { immediate: true });\n onBeforeUnmount(teardown);\n return health as Ref<DataBusHealthSummary | null>;\n}\n", "/**\n * \u516C\u5171\u5B57\u7B26\u4E32\u5E38\u91CF \u2014\u2014 \u751F\u547D\u5468\u671F\u72B6\u6001\u3001\u89D2\u8272\u3001\u63A7\u5236\u52A8\u4F5C\u3001\u534F\u8BAE\u6D88\u606F\u7C7B\u578B\u3001\u679A\u4E3E\u4E0E\n * \u547D\u540D\u7A7A\u95F4\u524D\u7F00\u3002\n *\n * \u6240\u6709\u8FD0\u884C\u65F6\u4F7F\u7528\u7684\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\u96C6\u4E2D\u5728\u6B64\u4E00\u4EFD\u503C\uFF0C\u7C7B\u578B\u5B9A\u4E49\uFF08src/core/types.ts\n * \u7B49\uFF09\u901A\u8FC7 `(typeof X)[keyof typeof X]` \u4ECE\u8FD9\u4E9B\u5E38\u91CF\u6D3E\u751F\uFF0C\u6BD4\u8F83/switch \u5904\u5F15\u7528\n * \u540C\u4E00\u5BF9\u8C61\u6210\u5458\u3002\u8FD9\u6837\u65E2\u80FD\u6D88\u9664\u6563\u843D\u5728\u5404\u6587\u4EF6\u91CC\u7684\u91CD\u590D\u5B57\u7B26\u4E32\uFF08\u907F\u514D\u5927\u5C0F\u5199\u4E0D\u7EDF\u4E00\n * \u6216\u7B14\u8BEF\uFF09\uFF0C\u53C8\u4FDD\u8BC1\u7C7B\u578B\u4E0E\u503C\u6C38\u4E0D\u9519\u4F4D\u3002\n *\n * ## \u4F7F\u7528\u7EA6\u5B9A\n *\n * - **\u65B0\u589E\u6216\u4FEE\u6539\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\u65F6\uFF0C\u5148\u5230\u8FD9\u91CC\u67E5\u627E/\u589E\u8865\uFF0C\u4E0D\u8981\u5728\u4E1A\u52A1\u6587\u4EF6\u91CC\u76F4\u63A5\u5199\n * \u9B54\u6CD5\u5B57\u7B26\u4E32\u3002** \u626B\u63CF\u6B8B\u7559\u5B57\u9762\u91CF\uFF1A`rg \"'(['a-z]+)'\" src/`\u3002\n * - **\u53EA\u7528\u4E8E\u7C7B\u578B\u4F4D\u7F6E\u7684\u5E38\u91CF**\uFF08\u5982 `PERSISTENCE_OPERATION`\uFF09\u5728\u8C03\u7528\u65B9\u7528\n * `import type`\uFF1B**\u5728\u8FD0\u884C\u65F6\u6BD4\u8F83/\u6784\u9020\u4E2D\u4F7F\u7528\u7684**\uFF08\u5982 `WORKER_STATUS.ERROR`\u3001\n * `TRACE_EVENT_TYPE.LIFECYCLE`\uFF09\u5FC5\u987B\u7528\u503C\u5BFC\u5165\uFF0C\u5426\u5219\u4F1A\u62A5 \"cannot be used as\n * a value because it was imported using 'import type'\"\u3002\n * - **\u503C\u6D3E\u751F\u7C7B\u578B**\uFF1A`export type WorkerStatus = (typeof WORKER_STATUS)[keyof\n * typeof WORKER_STATUS]`\u3002\u8FD9\u6837\u65B0\u589E\u679A\u4E3E\u5206\u652F\u65F6\u7C7B\u578B\u81EA\u52A8\u6536\u7A84\uFF0C\u7F16\u8BD1\u5668\u4F1A\u6307\u51FA\n * \u6BCF\u4E2A\u9057\u6F0F\u7684 switch \u5206\u652F\u3002\n * - \u5206\u7EC4\u7684\u987A\u5E8F\uFF08\u72B6\u6001 / \u89D2\u8272 / \u540E\u7AEF / \u6D88\u606F\u7C7B\u578B / \u679A\u4E3E / \u524D\u7F00\uFF09\u4FDD\u6301\u7A33\u5B9A\uFF0C\u65B9\u4FBF\n * \u7EF4\u62A4\u8005\u4E00\u773C\u5B9A\u4F4D\u3002\n */\n\n// ---- \u751F\u547D\u5468\u671F\u72B6\u6001 / \u89D2\u8272 / \u53EF\u89C1\u6027 ----\nexport const WORKER_STATUS = {\n CONNECTING: 'connecting',\n CONNECTED: 'connected',\n DISCONNECTED: 'disconnected',\n ERROR: 'error',\n} as const;\n\nexport const WORKER_ROLE = {\n ACTIVE: 'active',\n STANDBY: 'standby',\n} as const;\n\nexport const TAB_VISIBILITY = {\n VISIBLE: 'visible',\n HIDDEN: 'hidden',\n} as const;\n\n// ---- Worker \u540E\u7AEF\u6A21\u5F0F\u4E0E\u89E3\u6790\u7ED3\u679C\uFF08WorkerMode / WorkerBackend\uFF09----\nexport const WORKER_MODE = {\n DEDICATED: 'dedicated',\n SHARED: 'shared',\n AUTO: 'auto',\n} as const;\n\nexport const WORKER_BACKEND = {\n DEDICATED: 'dedicated',\n SHARED: 'shared',\n LOCAL: 'local',\n} as const;\n\n// ---- \u5B58\u50A8\u4E8B\u4EF6\u901A\u9053\u56DE\u9000 ----\nexport const CHANNEL_FALLBACK = {\n NONE: 'none',\n STORAGE_EVENT: 'storage-event',\n} as const;\n\n// ---- Worker / MessagePort / BroadcastChannel \u7684 EventTarget \u4E8B\u4EF6\u540D\u5224\u522B ----\n// MessageEvent.type\uFF08'message' / 'messageerror'\uFF09\u4E0E Worker \u4E0A\u7684 'error' \u4E8B\u4EF6\u540D\uFF0C\n// \u7528\u4E8E\u73AF\u5883\u9002\u914D\u5668\u63A5\u53E3\u7B7E\u540D\u4E0E\u6D4B\u8BD5\u66FF\u8EAB\u7684 addEventListener \u771F\u5047\u5206\u652F\u3002\nexport const EVENT_TYPE = {\n MESSAGE: 'message',\n MESSAGEERROR: 'messageerror',\n ERROR: 'error',\n} as const;\n\n// ---- \u63A7\u5236\u5E73\u9762\u52A8\u4F5C\uFF08WorkerControlAction\uFF09----\nexport const CONTROL_ACTION = {\n SUBSCRIBE: 'SUBSCRIBE',\n UNSUBSCRIBE: 'UNSUBSCRIBE',\n PUBLISH: 'PUBLISH',\n} as const;\n\n// ---- BroadcastChannel \u96C6\u7FA4\u6D88\u606F\u7C7B\u578B ----\nexport const CLUSTER_MESSAGE_TYPE = {\n CONTROL: 'CONTROL',\n EVENT: 'EVENT',\n REGISTRY: 'REGISTRY',\n ROUTE_RELEASED: 'ROUTE_RELEASED',\n} as const;\n\n// ---- \u547D\u540D\u7A7A\u95F4\u524D\u7F00\u4E0E\u4E8B\u4EF6\u540D ----\nexport const DEFAULT_STORAGE_PREFIX = 'cross-tab-worker-databus';\nexport const STORAGE_CHANNEL_PREFIX = `${DEFAULT_STORAGE_PREFIX}:channel:`;\nexport const TAB_ID_STORAGE_KEY = `${DEFAULT_STORAGE_PREFIX}:tab-id`;\nexport const PUBLICATION_EVENT = 'DATABUS_PUBLICATION';\n\n// ---- \u89C4\u8303 JSON \u4FE1\u5C01\u64CD\u4F5C\u7801 ----\nexport const PUBLICATION_ENVELOPE_OP = 'publication';\n\n// ---- trace \u4E8B\u4EF6\u7C7B\u578B ----\nexport const TRACE_EVENT_TYPE = {\n LIFECYCLE: 'lifecycle',\n STATUS: 'status',\n SUBSCRIPTION: 'subscription',\n COORDINATION: 'coordination',\n ERROR: 'error',\n RELIABILITY: 'reliability',\n MESSAGE_METRICS: 'message_metrics',\n} as const;\n\n// ---- trace \u751F\u547D\u5468\u671F\u52A8\u4F5C ----\nexport const TRACE_LIFECYCLE_ACTION = {\n START: 'start',\n STOP: 'stop',\n SUSPEND: 'suspend',\n RESUME: 'resume',\n} as const;\n\n// ---- \u5185\u90E8 handler \u8C03\u7528\u6807\u7B7E\uFF08\u9694\u79BB\u5F02\u5E38\u65F6\u7684\u5206\u7C7B\u6765\u6E90\uFF09----\nexport const INVOKE_LABEL = {\n DISPATCH: 'dispatch',\n STATUS: 'status',\n ERROR_HANDLER: 'error handler',\n} as const;\n\n// ---- trace \u6A21\u5F0F\uFF08DataBusTraceMode\uFF09----\nexport const TRACE_MODE = {\n EVENTS: 'events',\n METRICS: 'metrics',\n ALL: 'all',\n} as const;\n\n// ---- trace \u9519\u8BEF\u6765\u6E90 ----\nexport const TRACE_ERROR_SOURCE = {\n TRANSPORT: 'transport',\n OPERATION: 'operation',\n} as const;\n\n// ---- reliability \u8BCA\u65AD\u64CD\u4F5C ----\nexport const RELIABILITY_OPERATION = {\n TRANSPORT_RECOVERY: 'transport_recovery',\n ROUTE_ACK: 'route_ack',\n ROUTE_MIGRATION: 'route_migration',\n // A re-election that recovered a stranded unconfirmed handoff (previous\n // owner gone, ACK never arrived). Distinct from ROUTE_MIGRATION so trace\n // consumers can tell recoveries apart from routine graceful handoffs.\n ROUTE_MIGRATION_RECOVERY: 'route_migration_recovery',\n PERSISTENCE_CLEANUP: 'persistence_cleanup',\n PERSISTENCE_RETRY: 'persistence_retry',\n DEDUP_SUPPRESSED: 'dedup_suppressed',\n} as const;\n\n// ---- \u81EA\u52A8\u6062\u590D\u5C1D\u8BD5\u7ED3\u679C ----\nexport const RECOVERY_OUTCOME = {\n SCHEDULED: 'scheduled',\n SUCCEEDED: 'succeeded',\n FAILED: 'failed',\n EXHAUSTED: 'exhausted',\n} as const;\n\n// ---- \u8BA2\u9605\u52A8\u4F5C ----\nexport const SUBSCRIPTION_ACTION = {\n SUBSCRIBE: 'subscribe',\n UNSUBSCRIBE: 'unsubscribe',\n} as const;\n\n// ---- \u56DE\u653E\u4FEE\u526A\u7B56\u7565 ----\nexport const PRUNE_STRATEGY = {\n COUNT: 'count',\n AGE: 'age',\n BOTH: 'both',\n} as const;\n\n// ---- \u6301\u4E45\u5316\u64CD\u4F5C ----\nexport const PERSISTENCE_OPERATION = {\n LOAD: 'load',\n APPEND: 'append',\n CLEAR: 'clear',\n CLEAR_TOPIC: 'clearTopic',\n CLEAR_BEFORE: 'clearBefore',\n} as const;\n\n// ---- \u6545\u969C\u6765\u6E90\uFF08DataBusFailureSource\uFF09----\nexport const FAILURE_SOURCE = {\n TRANSPORT: 'transport',\n PERSISTENCE: 'persistence',\n DISPATCH: 'dispatch',\n} as const;\n\n// ---- \u5065\u5EB7\u5224\u5B9A\u72B6\u6001\uFF08DataBusHealthSummary['state']\uFF09----\nexport const HEALTH_STATE = {\n STOPPED: 'stopped',\n STARTING: 'starting',\n HEALTHY: 'healthy',\n RECOVERING: 'recovering',\n SUSPENDED: 'suspended',\n DEGRADED: 'degraded',\n} as const;\n\n// ---- WebSocket wire \u534F\u8BAE\u64CD\u4F5C\u7801 ----\nexport const WS_OP = {\n SUBSCRIBE: 'subscribe',\n UNSUBSCRIBE: 'unsubscribe',\n PUBLISH: 'publish',\n PUBLISH_BATCH: 'publishBatch',\n} as const;\n\n// ---- Centrifuge Worker \u8F93\u5165\u6D88\u606F\u7C7B\u578B ----\nexport const CENTRIFUGE_INPUT_TYPE = {\n INIT: 'INIT',\n SUBSCRIBE: 'SUBSCRIBE',\n UNSUBSCRIBE: 'UNSUBSCRIBE',\n PUBLISH: 'PUBLISH',\n PUBLISH_BIN: 'PUBLISH_BIN',\n PING: 'PING',\n STOP: 'STOP',\n TOKEN_RESPONSE: 'TOKEN_RESPONSE',\n TOKEN_ERROR: 'TOKEN_ERROR',\n} as const;\n\n// ---- Centrifuge Worker \u8F93\u51FA\u6D88\u606F\u7C7B\u578B ----\nexport const CENTRIFUGE_OUTPUT_TYPE = {\n STATUS: 'STATUS',\n MESSAGE: 'MESSAGE',\n MESSAGE_BIN: 'MESSAGE_BIN',\n ERROR: 'ERROR',\n TOKEN_REQUEST: 'TOKEN_REQUEST',\n} as const;\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,iBAA6E;;;ACsBtE,IAAM,gBAAgB;AAAA,EAC3B,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,cAAc;AAAA,EACd,OAAO;AACT;AAwDO,IAAM,yBAAyB;AAC/B,IAAM,yBAAyB,GAAG,sBAAsB;AACxD,IAAM,qBAAqB,GAAG,sBAAsB;;;ADhFpD,SAAS,mBACd,QACA,OAAsD,CAAC,GACV;AAC7C,QAAM,UAAM,uBAAmD,IAAI;AACnE,MAAI,WAAmD;AACvD,MAAI,sBAAsB;AAC1B,QAAM,OAAO,YAAY;AAAE,UAAM,UAAU;AAAU,eAAW;AAAM,QAAI,QAAQ;AAAM,QAAI,QAAS,OAAM,QAAQ,KAAK;AAAA,EAAG;AAC3H,QAAM,QAAQ,MAAM;AAClB,UAAM,aAAa,EAAE;AACrB,SAAK,KAAK,EAAE,KAAK,MAAM;AACrB,UAAI,eAAe,oBAAqB;AACxC,YAAM,OAAO,OAAO;AACpB,iBAAW;AACX,UAAI,QAAQ;AACZ,WAAK,KAAK,MAAM,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IAClC,CAAC;AAAA,EACH;AACA,4BAAU,KAAK;AACf,kCAAgB,MAAM;AAMpB,2BAAuB;AACvB,SAAK,KAAK;AAAA,EACZ,CAAC;AACD,MAAI,KAAK,SAAS,EAAG,uBAAM,MAAM,KAAK;AACtC,SAAO;AACT;AAEO,SAAS,wBACd,KAAkD,OAClD,SACM;AACN,MAAI,aAAqD;AACzD,MAAI,eAA8B;AAClC,MAAI;AACJ,
|
|
4
|
+
"sourcesContent": ["/** Vue 3 composables adapter for cross-tab-worker-databus.\n * Vue is an optional peer dependency; this module is a separate entry point.\n */\nimport { onBeforeUnmount, onMounted, ref, shallowRef, watch, type Ref } from 'vue';\nimport type { CrossTabDataBus, DataBusHealthSummary } from './core/data-bus';\nimport type { DataBusMessage, WorkerStatus } from './core/types';\nimport { WORKER_STATUS } from './utils/constants';\n\nexport function useCrossTabDataBus<TConfig, TData>(\n create: () => CrossTabDataBus<TConfig, TData>,\n deps: ReadonlyArray<Ref<unknown> | (() => unknown)> = []\n): Ref<CrossTabDataBus<TConfig, TData> | null> {\n const bus = shallowRef<CrossTabDataBus<TConfig, TData> | null>(null);\n let instance: CrossTabDataBus<TConfig, TData> | null = null;\n let lifecycleGeneration = 0;\n const stop = async () => { const current = instance; instance = null; bus.value = null; if (current) await current.stop(); };\n const start = () => {\n const generation = ++lifecycleGeneration;\n void stop().then(() => {\n if (generation !== lifecycleGeneration) return;\n const next = create();\n instance = next;\n bus.value = next;\n void next.ready().catch(() => {});\n });\n };\n onMounted(start);\n onBeforeUnmount(() => {\n // Bump the generation so a start() still awaiting its stop() sees itself\n // superseded. Without this the pending continuation would run create()\n // after the component is gone, leaving a live bus with no owner to stop\n // it (the React adapter has no such window: its create() is synchronous\n // inside useEffect).\n lifecycleGeneration += 1;\n void stop();\n });\n if (deps.length > 0) watch(deps, start);\n return bus as Ref<CrossTabDataBus<TConfig, TData> | null>;\n}\n\nexport function useCrossTabSubscription<TConfig, TData>(\n bus: Ref<CrossTabDataBus<TConfig, TData> | null>, topic: Ref<string> | string,\n handler: (message: DataBusMessage<TData>) => void\n): void {\n let currentBus: CrossTabDataBus<TConfig, TData> | null = null;\n let currentTopic: string | null = null;\n let cleanup: (() => void) | undefined;\n const stop = () => { cleanup?.(); cleanup = undefined; currentBus = null; currentTopic = null; };\n const sync = () => {\n const nextBus = bus.value;\n const nextTopic = typeof topic === 'string' ? topic : topic.value;\n if (nextBus === currentBus && currentTopic === nextTopic && cleanup) return;\n stop();\n if (!nextBus) return;\n currentBus = nextBus;\n currentTopic = nextTopic;\n cleanup = nextBus.subscribe(nextTopic, handler);\n };\n watch(bus, sync, { immediate: true });\n if (typeof topic !== 'string') watch(topic, sync);\n onBeforeUnmount(stop);\n}\n\nexport function useCrossTabStatus<TConfig, TData>(\n bus: Ref<CrossTabDataBus<TConfig, TData> | null>\n): Ref<WorkerStatus> {\n const status = ref<WorkerStatus>(WORKER_STATUS.CONNECTING);\n let cleanup: (() => void) | undefined;\n watch(bus, next => {\n cleanup?.(); cleanup = undefined;\n status.value = next?.getStatus() ?? WORKER_STATUS.CONNECTING;\n if (next) cleanup = next.onStatus(value => { status.value = value; });\n }, { immediate: true });\n onBeforeUnmount(() => cleanup?.());\n return status;\n}\n\n/** Options for {@link useCrossTabHealth}. */\nexport interface UseCrossTabHealthOptions {\n /** Polling cadence in ms for the health snapshot. Default 1000; `0` disables\n * polling and relies on status/error events only. */\n intervalMs?: number;\n}\n\n/**\n * Mirror the bus health summary into a Vue ref. `getHealthSummary()` is a\n * snapshot, so the composable polls it on an interval (default 1000 ms) and\n * refreshes on status changes and errors. A reactive interval change replaces\n * the timer without rebuilding the bus. Returns `null` until the bus exists.\n */\nexport function useCrossTabHealth<TConfig, TData>(\n bus: Ref<CrossTabDataBus<TConfig, TData> | null>,\n options?: UseCrossTabHealthOptions\n): Ref<DataBusHealthSummary | null> {\n const health = ref<DataBusHealthSummary | null>(null);\n let timer: ReturnType<typeof setInterval> | null = null;\n let cleanups: Array<() => void> = [];\n const teardown = () => {\n if (timer) clearInterval(timer);\n timer = null;\n for (const cleanup of cleanups) cleanup();\n cleanups = [];\n };\n watch([bus, () => options?.intervalMs], ([next]) => {\n teardown();\n if (!next) {\n health.value = null;\n return;\n }\n const refresh = () => { health.value = next.getHealthSummary(); };\n refresh();\n cleanups.push(next.onStatus(refresh));\n cleanups.push(next.onError(refresh));\n const intervalMs = options?.intervalMs ?? 1_000;\n if (intervalMs > 0) timer = setInterval(refresh, intervalMs);\n }, { immediate: true });\n onBeforeUnmount(teardown);\n return health as Ref<DataBusHealthSummary | null>;\n}\n", "/**\n * \u516C\u5171\u5B57\u7B26\u4E32\u5E38\u91CF \u2014\u2014 \u751F\u547D\u5468\u671F\u72B6\u6001\u3001\u89D2\u8272\u3001\u63A7\u5236\u52A8\u4F5C\u3001\u534F\u8BAE\u6D88\u606F\u7C7B\u578B\u3001\u679A\u4E3E\u4E0E\n * \u547D\u540D\u7A7A\u95F4\u524D\u7F00\u3002\n *\n * \u6240\u6709\u8FD0\u884C\u65F6\u4F7F\u7528\u7684\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\u96C6\u4E2D\u5728\u6B64\u4E00\u4EFD\u503C\uFF0C\u7C7B\u578B\u5B9A\u4E49\uFF08src/core/types.ts\n * \u7B49\uFF09\u901A\u8FC7 `(typeof X)[keyof typeof X]` \u4ECE\u8FD9\u4E9B\u5E38\u91CF\u6D3E\u751F\uFF0C\u6BD4\u8F83/switch \u5904\u5F15\u7528\n * \u540C\u4E00\u5BF9\u8C61\u6210\u5458\u3002\u8FD9\u6837\u65E2\u80FD\u6D88\u9664\u6563\u843D\u5728\u5404\u6587\u4EF6\u91CC\u7684\u91CD\u590D\u5B57\u7B26\u4E32\uFF08\u907F\u514D\u5927\u5C0F\u5199\u4E0D\u7EDF\u4E00\n * \u6216\u7B14\u8BEF\uFF09\uFF0C\u53C8\u4FDD\u8BC1\u7C7B\u578B\u4E0E\u503C\u6C38\u4E0D\u9519\u4F4D\u3002\n *\n * ## \u4F7F\u7528\u7EA6\u5B9A\n *\n * - **\u65B0\u589E\u6216\u4FEE\u6539\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\u65F6\uFF0C\u5148\u5230\u8FD9\u91CC\u67E5\u627E/\u589E\u8865\uFF0C\u4E0D\u8981\u5728\u4E1A\u52A1\u6587\u4EF6\u91CC\u76F4\u63A5\u5199\n * \u9B54\u6CD5\u5B57\u7B26\u4E32\u3002** \u626B\u63CF\u6B8B\u7559\u5B57\u9762\u91CF\uFF1A`rg \"'(['a-z]+)'\" src/`\u3002\n * - **\u53EA\u7528\u4E8E\u7C7B\u578B\u4F4D\u7F6E\u7684\u5E38\u91CF**\uFF08\u5982 `PERSISTENCE_OPERATION`\uFF09\u5728\u8C03\u7528\u65B9\u7528\n * `import type`\uFF1B**\u5728\u8FD0\u884C\u65F6\u6BD4\u8F83/\u6784\u9020\u4E2D\u4F7F\u7528\u7684**\uFF08\u5982 `WORKER_STATUS.ERROR`\u3001\n * `TRACE_EVENT_TYPE.LIFECYCLE`\uFF09\u5FC5\u987B\u7528\u503C\u5BFC\u5165\uFF0C\u5426\u5219\u4F1A\u62A5 \"cannot be used as\n * a value because it was imported using 'import type'\"\u3002\n * - **\u503C\u6D3E\u751F\u7C7B\u578B**\uFF1A`export type WorkerStatus = (typeof WORKER_STATUS)[keyof\n * typeof WORKER_STATUS]`\u3002\u8FD9\u6837\u65B0\u589E\u679A\u4E3E\u5206\u652F\u65F6\u7C7B\u578B\u81EA\u52A8\u6536\u7A84\uFF0C\u7F16\u8BD1\u5668\u4F1A\u6307\u51FA\n * \u6BCF\u4E2A\u9057\u6F0F\u7684 switch \u5206\u652F\u3002\n * - \u5206\u7EC4\u7684\u987A\u5E8F\uFF08\u72B6\u6001 / \u89D2\u8272 / \u540E\u7AEF / \u6D88\u606F\u7C7B\u578B / \u679A\u4E3E / \u524D\u7F00\uFF09\u4FDD\u6301\u7A33\u5B9A\uFF0C\u65B9\u4FBF\n * \u7EF4\u62A4\u8005\u4E00\u773C\u5B9A\u4F4D\u3002\n */\n\n// ---- \u751F\u547D\u5468\u671F\u72B6\u6001 / \u89D2\u8272 / \u53EF\u89C1\u6027 ----\nexport const WORKER_STATUS = {\n CONNECTING: 'connecting',\n CONNECTED: 'connected',\n DISCONNECTED: 'disconnected',\n ERROR: 'error',\n} as const;\n\nexport const WORKER_ROLE = {\n ACTIVE: 'active',\n STANDBY: 'standby',\n} as const;\n\nexport const TAB_VISIBILITY = {\n VISIBLE: 'visible',\n HIDDEN: 'hidden',\n} as const;\n\n// ---- Worker \u540E\u7AEF\u6A21\u5F0F\u4E0E\u89E3\u6790\u7ED3\u679C\uFF08WorkerMode / WorkerBackend\uFF09----\nexport const WORKER_MODE = {\n DEDICATED: 'dedicated',\n SHARED: 'shared',\n AUTO: 'auto',\n} as const;\n\nexport const WORKER_BACKEND = {\n DEDICATED: 'dedicated',\n SHARED: 'shared',\n LOCAL: 'local',\n} as const;\n\n// ---- \u5B58\u50A8\u4E8B\u4EF6\u901A\u9053\u56DE\u9000 ----\nexport const CHANNEL_FALLBACK = {\n NONE: 'none',\n STORAGE_EVENT: 'storage-event',\n} as const;\n\n// ---- Worker / MessagePort / BroadcastChannel \u7684 EventTarget \u4E8B\u4EF6\u540D\u5224\u522B ----\n// MessageEvent.type\uFF08'message' / 'messageerror'\uFF09\u4E0E Worker \u4E0A\u7684 'error' \u4E8B\u4EF6\u540D\uFF0C\n// \u7528\u4E8E\u73AF\u5883\u9002\u914D\u5668\u63A5\u53E3\u7B7E\u540D\u4E0E\u6D4B\u8BD5\u66FF\u8EAB\u7684 addEventListener \u771F\u5047\u5206\u652F\u3002\nexport const EVENT_TYPE = {\n MESSAGE: 'message',\n MESSAGEERROR: 'messageerror',\n ERROR: 'error',\n} as const;\n\n// ---- \u63A7\u5236\u5E73\u9762\u52A8\u4F5C\uFF08WorkerControlAction\uFF09----\nexport const CONTROL_ACTION = {\n SUBSCRIBE: 'SUBSCRIBE',\n UNSUBSCRIBE: 'UNSUBSCRIBE',\n PUBLISH: 'PUBLISH',\n} as const;\n\n// ---- BroadcastChannel \u96C6\u7FA4\u6D88\u606F\u7C7B\u578B ----\nexport const CLUSTER_MESSAGE_TYPE = {\n CONTROL: 'CONTROL',\n EVENT: 'EVENT',\n REGISTRY: 'REGISTRY',\n ROUTE_RELEASED: 'ROUTE_RELEASED',\n} as const;\n\n// ---- \u547D\u540D\u7A7A\u95F4\u524D\u7F00\u4E0E\u4E8B\u4EF6\u540D ----\nexport const DEFAULT_STORAGE_PREFIX = 'cross-tab-worker-databus';\nexport const STORAGE_CHANNEL_PREFIX = `${DEFAULT_STORAGE_PREFIX}:channel:`;\nexport const TAB_ID_STORAGE_KEY = `${DEFAULT_STORAGE_PREFIX}:tab-id`;\nexport const PUBLICATION_EVENT = 'DATABUS_PUBLICATION';\n\n// ---- \u89C4\u8303 JSON \u4FE1\u5C01\u64CD\u4F5C\u7801 ----\nexport const PUBLICATION_ENVELOPE_OP = 'publication';\n\n// ---- trace \u4E8B\u4EF6\u7C7B\u578B ----\nexport const TRACE_EVENT_TYPE = {\n LIFECYCLE: 'lifecycle',\n STATUS: 'status',\n SUBSCRIPTION: 'subscription',\n COORDINATION: 'coordination',\n ERROR: 'error',\n RELIABILITY: 'reliability',\n MESSAGE_METRICS: 'message_metrics',\n} as const;\n\n// ---- trace \u751F\u547D\u5468\u671F\u52A8\u4F5C ----\nexport const TRACE_LIFECYCLE_ACTION = {\n START: 'start',\n STOP: 'stop',\n SUSPEND: 'suspend',\n RESUME: 'resume',\n} as const;\n\n// ---- \u5185\u90E8 handler \u8C03\u7528\u6807\u7B7E\uFF08\u9694\u79BB\u5F02\u5E38\u65F6\u7684\u5206\u7C7B\u6765\u6E90\uFF09----\nexport const INVOKE_LABEL = {\n DISPATCH: 'dispatch',\n STATUS: 'status',\n ERROR_HANDLER: 'error handler',\n} as const;\n\n// ---- trace \u6A21\u5F0F\uFF08DataBusTraceMode\uFF09----\nexport const TRACE_MODE = {\n EVENTS: 'events',\n METRICS: 'metrics',\n ALL: 'all',\n} as const;\n\n// ---- trace \u9519\u8BEF\u6765\u6E90 ----\nexport const TRACE_ERROR_SOURCE = {\n TRANSPORT: 'transport',\n OPERATION: 'operation',\n} as const;\n\n// ---- reliability \u8BCA\u65AD\u64CD\u4F5C ----\nexport const RELIABILITY_OPERATION = {\n TRANSPORT_RECOVERY: 'transport_recovery',\n ROUTE_ACK: 'route_ack',\n ROUTE_MIGRATION: 'route_migration',\n // A re-election that recovered a stranded unconfirmed handoff (previous\n // owner gone, ACK never arrived). Distinct from ROUTE_MIGRATION so trace\n // consumers can tell recoveries apart from routine graceful handoffs.\n ROUTE_MIGRATION_RECOVERY: 'route_migration_recovery',\n PERSISTENCE_CLEANUP: 'persistence_cleanup',\n PERSISTENCE_RETRY: 'persistence_retry',\n DEDUP_SUPPRESSED: 'dedup_suppressed',\n} as const;\n\n// ---- \u81EA\u52A8\u6062\u590D\u5C1D\u8BD5\u7ED3\u679C ----\nexport const RECOVERY_OUTCOME = {\n SCHEDULED: 'scheduled',\n SUCCEEDED: 'succeeded',\n FAILED: 'failed',\n EXHAUSTED: 'exhausted',\n} as const;\n\n// ---- \u8BA2\u9605\u52A8\u4F5C ----\nexport const SUBSCRIPTION_ACTION = {\n SUBSCRIBE: 'subscribe',\n UNSUBSCRIBE: 'unsubscribe',\n} as const;\n\n// ---- \u56DE\u653E\u4FEE\u526A\u7B56\u7565 ----\nexport const PRUNE_STRATEGY = {\n COUNT: 'count',\n AGE: 'age',\n BOTH: 'both',\n} as const;\n\n// ---- \u6301\u4E45\u5316\u64CD\u4F5C ----\nexport const PERSISTENCE_OPERATION = {\n LOAD: 'load',\n APPEND: 'append',\n CLEAR: 'clear',\n CLEAR_TOPIC: 'clearTopic',\n CLEAR_BEFORE: 'clearBefore',\n} as const;\n\n// ---- \u6545\u969C\u6765\u6E90\uFF08DataBusFailureSource\uFF09----\nexport const FAILURE_SOURCE = {\n TRANSPORT: 'transport',\n PERSISTENCE: 'persistence',\n DISPATCH: 'dispatch',\n} as const;\n\n// ---- \u5065\u5EB7\u5224\u5B9A\u72B6\u6001\uFF08DataBusHealthSummary['state']\uFF09----\nexport const HEALTH_STATE = {\n STOPPED: 'stopped',\n STARTING: 'starting',\n HEALTHY: 'healthy',\n RECOVERING: 'recovering',\n SUSPENDED: 'suspended',\n DEGRADED: 'degraded',\n} as const;\n\n// ---- WebSocket wire \u534F\u8BAE\u64CD\u4F5C\u7801 ----\nexport const WS_OP = {\n SUBSCRIBE: 'subscribe',\n UNSUBSCRIBE: 'unsubscribe',\n PUBLISH: 'publish',\n PUBLISH_BATCH: 'publishBatch',\n} as const;\n\n// ---- Centrifuge Worker \u8F93\u5165\u6D88\u606F\u7C7B\u578B ----\nexport const CENTRIFUGE_INPUT_TYPE = {\n INIT: 'INIT',\n SUBSCRIBE: 'SUBSCRIBE',\n UNSUBSCRIBE: 'UNSUBSCRIBE',\n PUBLISH: 'PUBLISH',\n PUBLISH_BIN: 'PUBLISH_BIN',\n PING: 'PING',\n STOP: 'STOP',\n TOKEN_RESPONSE: 'TOKEN_RESPONSE',\n TOKEN_ERROR: 'TOKEN_ERROR',\n} as const;\n\n// ---- Centrifuge Worker \u8F93\u51FA\u6D88\u606F\u7C7B\u578B ----\nexport const CENTRIFUGE_OUTPUT_TYPE = {\n STATUS: 'STATUS',\n MESSAGE: 'MESSAGE',\n MESSAGE_BIN: 'MESSAGE_BIN',\n ERROR: 'ERROR',\n TOKEN_REQUEST: 'TOKEN_REQUEST',\n} as const;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cluster.d.ts","sourceRoot":"","sources":["../../src/core/cluster.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAkB,kBAAkB,EAAe,MAAM,eAAe,CAAC;AASrF,OAAO,KAAK,EACV,0BAA0B,EAC1B,oBAAoB,EAGpB,mBAAmB,EACnB,YAAY,EAEZ,WAAW,EACX,YAAY,EAEb,MAAM,SAAS,CAAC;AAEjB,OAAO,EAIL,qBAAqB,EAItB,MAAM,oBAAoB,CAAC;AAK5B,0EAA0E;AAC1E,MAAM,WAAW,qBAAqB;IACpC,mFAAmF;IACnF,SAAS,EAAE,CACT,MAAM,EAAE,mBAAmB,EAC3B,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,OAAO,EACd,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,KACf,IAAI,CAAC;IACV;;yEAEqE;IACrE,cAAc,CAAC,EAAE,CACf,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,aAAa,CAAC;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,KAC5E,IAAI,CAAC;IACV;;;2DAGuD;IACvD,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C,OAAO,EAAE,CACP,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,MAAM,EACtB,WAAW,CAAC,EAAE,MAAM,KACjB,IAAI,CAAC;IACV,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,qGAAqG;IACrG,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE;QACrB,SAAS,EAAE,CAAC,OAAO,qBAAqB,CAAC,SAAS,GAAG,OAAO,qBAAqB,CAAC,eAAe,GAAG,OAAO,qBAAqB,CAAC,wBAAwB,CAAC,CAAC;QAC3J,KAAK,EAAE,MAAM,CAAC;KACf,KAAK,IAAI,CAAC;CACZ;AAED,MAAM,WAAW,oBAAoB;IACnC;gFAC4E;IAC5E,UAAU,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,QAAQ,EAAE,qBAAqB,CAAC;IAChC,2EAA2E;IAC3E,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,4EAA4E;IAC5E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2DAA2D;IAC3D,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;sEACkE;IAClE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;kFAG8E;IAC9E,aAAa,CAAC,EAAE,oBAAoB,CAAC;CACtC;AAED,2EAA2E;AAC3E,MAAM,WAAW,qBAAqB;IACpC,eAAe,EAAE,MAAM,CAAC;IACxB,2FAA2F;IAC3F,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IACpD,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,YAAY,CAAC;IAC5B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,qFAAqF;IACrF,MAAM,EAAE,KAAK,CAAC,WAAW,GAAG;QAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IACtD,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,0DAA0D;IAC1D,WAAW,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,eAAe,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/E;AAUD;;;;;;;;;;;;GAYG;AACH,qBAAa,oBAAoB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwB;IACjD,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,mFAAmF;IACnF,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmC;IACjE,gFAAgF;IAChF,OAAO,CAAC,gBAAgB,CAItB;IAEF,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqB;IAItD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAC5D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA+D;IAC/F,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAC5C,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,sBAAsB,CAAuB;IACrD,OAAO,CAAC,oBAAoB;
|
|
1
|
+
{"version":3,"file":"cluster.d.ts","sourceRoot":"","sources":["../../src/core/cluster.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/core/environment.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/core/environment.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-batch.d.ts","sourceRoot":"","sources":["../../src/core/storage-batch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAajD;;;;;;;;GAQG;AACH,qBAAa,qBAAsB,YAAW,WAAW;IAS3C,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,uEAAuE;IACvE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAC5D,0DAA0D;IAC1D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA6B;IACxD,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,WAAW,CAA8C;IACjE,OAAO,CAAC,YAAY,CAA0B;gBAEjB,OAAO,EAAE,WAAW;IAEjD;;gCAE4B;IAC5B,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,KAAK,IAAI,IAAI;IAcb;;6EAEyE;IACzE,cAAc,IAAI,IAAI;IAUtB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKnC,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIjC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK7B,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAKzC,KAAK,IAAI,IAAI;IA6Cb,yEAAyE;IACzE,OAAO,CAAC,IAAI;IAiBZ,OAAO,CAAC,aAAa;
|
|
1
|
+
{"version":3,"file":"storage-batch.d.ts","sourceRoot":"","sources":["../../src/core/storage-batch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAajD;;;;;;;;GAQG;AACH,qBAAa,qBAAsB,YAAW,WAAW;IAS3C,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,uEAAuE;IACvE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAC5D,0DAA0D;IAC1D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA6B;IACxD,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,WAAW,CAA8C;IACjE,OAAO,CAAC,YAAY,CAA0B;gBAEjB,OAAO,EAAE,WAAW;IAEjD;;gCAE4B;IAC5B,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,KAAK,IAAI,IAAI;IAcb;;6EAEyE;IACzE,cAAc,IAAI,IAAI;IAUtB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKnC,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIjC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK7B,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAKzC,KAAK,IAAI,IAAI;IA6Cb,yEAAyE;IACzE,OAAO,CAAC,IAAI;IAiBZ,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,WAAW;CAMpB"}
|
package/dist/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC7E,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGjE;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,KAAK,EAC/C,MAAM,EAAE,MAAM,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,EAC7C,IAAI,GAAE,cAAmB,GACxB,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC7E,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGjE;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,KAAK,EAC/C,MAAM,EAAE,MAAM,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,EAC7C,IAAI,GAAE,cAAmB,GACxB,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,IAAI,CAkBxC;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,KAAK,EACpD,GAAG,EAAE,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,IAAI,EAC3C,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,CAAC,KAAK,CAAC,KAAK,IAAI,GAChD,IAAI,CAON;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,KAAK,EAC9C,GAAG,EAAE,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,IAAI,GAC1C,YAAY,CAWd;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,KAAK,EAC9C,GAAG,EAAE,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,IAAI,EAC3C,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAChC,oBAAoB,GAAG,IAAI,CAuB7B"}
|
package/dist/hooks.js
CHANGED
|
@@ -6,16 +6,13 @@ import {
|
|
|
6
6
|
import { useEffect, useRef, useState } from "react";
|
|
7
7
|
function useCrossTabDataBus(create, deps = []) {
|
|
8
8
|
const [bus, setBus] = useState(null);
|
|
9
|
-
const lifecycleGeneration = useRef(0);
|
|
10
9
|
useEffect(() => {
|
|
11
|
-
const generation = ++lifecycleGeneration.current;
|
|
12
10
|
const instance = create();
|
|
13
|
-
if (generation !== lifecycleGeneration.current) return;
|
|
14
11
|
setBus(instance);
|
|
15
12
|
void instance.ready().catch(() => {
|
|
16
13
|
});
|
|
17
14
|
return () => {
|
|
18
|
-
|
|
15
|
+
setBus(null);
|
|
19
16
|
void instance.stop();
|
|
20
17
|
};
|
|
21
18
|
}, deps);
|
package/dist/hooks.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/hooks.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * React hooks adapter for cross-tab-worker-databus.\n *\n * A thin, transport-agnostic bridge between the imperative CrossTabDataBus\n * API and React component lifecycles. React is an optional peer dependency \u2014\n * this module is a separate entry point so consumers who don't use React\n * never load it.\n *\n * - `useCrossTabDataBus` owns the bus lifecycle: created on mount, stopped on\n * unmount. It is StrictMode-safe: the double-invoked effect exercises the\n * same stop/recreate path as BFCache suspend/resume.\n * - `useCrossTabSubscription` attaches a message handler with automatic\n * cleanup; the handler is read through a ref, so you can pass inline\n * closures without resubscribing on every render.\n * - `useCrossTabStatus` mirrors `bus.onStatus()` into React state.\n * - `useCrossTabHealth` polls `bus.getHealthSummary()` into React state,\n * with event-driven refreshes on status changes and errors.\n */\nimport { useEffect, useRef, useState } from 'react';\nimport type { DependencyList } from 'react';\nimport type { CrossTabDataBus, DataBusHealthSummary } from './core/data-bus';\nimport type { DataBusMessage, WorkerStatus } from './core/types';\nimport { WORKER_STATUS } from './utils/constants';\n\n/**\n * Create a CrossTabDataBus for the component's lifetime.\n *\n * @param create Factory invoked once per effect run. Return a fresh bus \u2014\n * do not share a bus instance between effects, or StrictMode's\n * mount \u2192 stop \u2192 mount cycle will stop the shared instance out from\n * under the second mount.\n * @param deps Re-create the bus when these change (default: create once).\n * @returns The active bus, or `null` before the first effect has run (SSR\n * and the initial render).\n */\nexport function useCrossTabDataBus<TConfig, TData>(\n create: () => CrossTabDataBus<TConfig, TData>,\n deps: DependencyList = []\n): CrossTabDataBus<TConfig, TData> | null {\n const [bus, setBus] = useState<CrossTabDataBus<TConfig, TData> | null>(null);\n
|
|
5
|
-
"mappings": ";;;;;AAkBA,SAAS,WAAW,QAAQ,gBAAgB;AAiBrC,SAAS,mBACd,QACA,OAAuB,CAAC,GACgB;AACxC,QAAM,CAAC,KAAK,MAAM,IAAI,SAAiD,IAAI;AAC3E,
|
|
4
|
+
"sourcesContent": ["/**\n * React hooks adapter for cross-tab-worker-databus.\n *\n * A thin, transport-agnostic bridge between the imperative CrossTabDataBus\n * API and React component lifecycles. React is an optional peer dependency \u2014\n * this module is a separate entry point so consumers who don't use React\n * never load it.\n *\n * - `useCrossTabDataBus` owns the bus lifecycle: created on mount, stopped on\n * unmount. It is StrictMode-safe: the double-invoked effect exercises the\n * same stop/recreate path as BFCache suspend/resume.\n * - `useCrossTabSubscription` attaches a message handler with automatic\n * cleanup; the handler is read through a ref, so you can pass inline\n * closures without resubscribing on every render.\n * - `useCrossTabStatus` mirrors `bus.onStatus()` into React state.\n * - `useCrossTabHealth` polls `bus.getHealthSummary()` into React state,\n * with event-driven refreshes on status changes and errors.\n */\nimport { useEffect, useRef, useState } from 'react';\nimport type { DependencyList } from 'react';\nimport type { CrossTabDataBus, DataBusHealthSummary } from './core/data-bus';\nimport type { DataBusMessage, WorkerStatus } from './core/types';\nimport { WORKER_STATUS } from './utils/constants';\n\n/**\n * Create a CrossTabDataBus for the component's lifetime.\n *\n * @param create Factory invoked once per effect run. Return a fresh bus \u2014\n * do not share a bus instance between effects, or StrictMode's\n * mount \u2192 stop \u2192 mount cycle will stop the shared instance out from\n * under the second mount.\n * @param deps Re-create the bus when these change (default: create once).\n * @returns The active bus, or `null` before the first effect has run (SSR\n * and the initial render).\n */\nexport function useCrossTabDataBus<TConfig, TData>(\n create: () => CrossTabDataBus<TConfig, TData>,\n deps: DependencyList = []\n): CrossTabDataBus<TConfig, TData> | null {\n const [bus, setBus] = useState<CrossTabDataBus<TConfig, TData> | null>(null);\n useEffect(() => {\n // No \"is this effect still current?\" check is needed: React runs an\n // effect's cleanup before its next invocation, and nothing between the\n // lines below yields, so `create()` cannot be interleaved with a newer\n // mount and this cleanup always stops the instance its own run created.\n const instance = create();\n setBus(instance);\n void instance.ready().catch(() => {});\n return () => {\n setBus(null);\n void instance.stop();\n };\n // The factory is intentionally not a dependency: callers pass an inline\n // closure and key recreation through `deps` instead.\n }, deps);\n return bus;\n}\n\n/**\n * Subscribe to `topic` for the component's lifetime. The handler is read\n * through a ref on each delivery, so inline closures are safe without\n * unsubscribing/resubscribing on re-renders.\n *\n * When `bus` is null (not yet created) the subscription is queued until the\n * bus appears \u2014 the bus itself queues it until the transport is ready.\n */\nexport function useCrossTabSubscription<TConfig, TData>(\n bus: CrossTabDataBus<TConfig, TData> | null,\n topic: string,\n handler: (message: DataBusMessage<TData>) => void\n): void {\n const handlerRef = useRef(handler);\n handlerRef.current = handler;\n useEffect(() => {\n if (!bus) return;\n return bus.subscribe(topic, message => handlerRef.current(message));\n }, [bus, topic]);\n}\n\n/**\n * Mirror the bus connection status into React state. Reports the live value\n * via `onStatus` and reads the current value synchronously whenever `bus`\n * changes identity.\n */\nexport function useCrossTabStatus<TConfig, TData>(\n bus: CrossTabDataBus<TConfig, TData> | null\n): WorkerStatus {\n const [status, setStatus] = useState<WorkerStatus>(WORKER_STATUS.CONNECTING);\n useEffect(() => {\n if (!bus) {\n setStatus(WORKER_STATUS.CONNECTING);\n return;\n }\n setStatus(bus.getStatus());\n return bus.onStatus(setStatus);\n }, [bus]);\n return status;\n}\n\n/**\n * Mirror the bus health summary into React state.\n *\n * `getHealthSummary()` is a snapshot, not an event stream, so the hook polls\n * it on an interval (default 1000 ms) and refreshes immediately on status\n * changes and errors. Pass `intervalMs: 0` to rely on event-driven refreshes\n * only; changing the interval replaces the timer without recreating the bus.\n * Returns `null` while the bus has not been created yet.\n */\nexport function useCrossTabHealth<TConfig, TData>(\n bus: CrossTabDataBus<TConfig, TData> | null,\n options?: { intervalMs?: number }\n): DataBusHealthSummary | null {\n const [health, setHealth] = useState<DataBusHealthSummary | null>(null);\n const intervalMs = options?.intervalMs ?? 1_000;\n useEffect(() => {\n if (!bus) {\n setHealth(null);\n return;\n }\n const refresh = () => setHealth(bus.getHealthSummary());\n refresh();\n const unsubscribeStatus = bus.onStatus(refresh);\n const unsubscribeError = bus.onError(refresh);\n const timer = intervalMs > 0 ? setInterval(refresh, intervalMs) : null;\n return () => {\n unsubscribeStatus();\n unsubscribeError();\n if (timer) clearInterval(timer);\n };\n // Depend on the normalized cadence rather than the options object so inline\n // option literals do not restart the effect on every render, while a real\n // intervalMs change still replaces the polling timer.\n }, [bus, intervalMs]);\n return health;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;AAkBA,SAAS,WAAW,QAAQ,gBAAgB;AAiBrC,SAAS,mBACd,QACA,OAAuB,CAAC,GACgB;AACxC,QAAM,CAAC,KAAK,MAAM,IAAI,SAAiD,IAAI;AAC3E,YAAU,MAAM;AAKd,UAAM,WAAW,OAAO;AACxB,WAAO,QAAQ;AACf,SAAK,SAAS,MAAM,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AACpC,WAAO,MAAM;AACX,aAAO,IAAI;AACX,WAAK,SAAS,KAAK;AAAA,IACrB;AAAA,EAGF,GAAG,IAAI;AACP,SAAO;AACT;AAUO,SAAS,wBACd,KACA,OACA,SACM;AACN,QAAM,aAAa,OAAO,OAAO;AACjC,aAAW,UAAU;AACrB,YAAU,MAAM;AACd,QAAI,CAAC,IAAK;AACV,WAAO,IAAI,UAAU,OAAO,aAAW,WAAW,QAAQ,OAAO,CAAC;AAAA,EACpE,GAAG,CAAC,KAAK,KAAK,CAAC;AACjB;AAOO,SAAS,kBACd,KACc;AACd,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAuB,cAAc,UAAU;AAC3E,YAAU,MAAM;AACd,QAAI,CAAC,KAAK;AACR,gBAAU,cAAc,UAAU;AAClC;AAAA,IACF;AACA,cAAU,IAAI,UAAU,CAAC;AACzB,WAAO,IAAI,SAAS,SAAS;AAAA,EAC/B,GAAG,CAAC,GAAG,CAAC;AACR,SAAO;AACT;AAWO,SAAS,kBACd,KACA,SAC6B;AAC7B,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAsC,IAAI;AACtE,QAAM,aAAa,SAAS,cAAc;AAC1C,YAAU,MAAM;AACd,QAAI,CAAC,KAAK;AACR,gBAAU,IAAI;AACd;AAAA,IACF;AACA,UAAM,UAAU,MAAM,UAAU,IAAI,iBAAiB,CAAC;AACtD,YAAQ;AACR,UAAM,oBAAoB,IAAI,SAAS,OAAO;AAC9C,UAAM,mBAAmB,IAAI,QAAQ,OAAO;AAC5C,UAAM,QAAQ,aAAa,IAAI,YAAY,SAAS,UAAU,IAAI;AAClE,WAAO,MAAM;AACX,wBAAkB;AAClB,uBAAiB;AACjB,UAAI,MAAO,eAAc,KAAK;AAAA,IAChC;AAAA,EAIF,GAAG,CAAC,KAAK,UAAU,CAAC;AACpB,SAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/index.js
CHANGED
package/dist/vue.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vue.d.ts","sourceRoot":"","sources":["../src/vue.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAsD,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AACnF,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC7E,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGjE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,KAAK,EAC/C,MAAM,EAAE,MAAM,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,EAC7C,IAAI,GAAE,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,CAAM,GACvD,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,CA2B7C;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,KAAK,EACpD,GAAG,EAAE,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,EAC7E,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,CAAC,KAAK,CAAC,KAAK,IAAI,GAChD,IAAI,
|
|
1
|
+
{"version":3,"file":"vue.d.ts","sourceRoot":"","sources":["../src/vue.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAsD,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AACnF,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC7E,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGjE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,KAAK,EAC/C,MAAM,EAAE,MAAM,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,EAC7C,IAAI,GAAE,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,CAAM,GACvD,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,CA2B7C;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,KAAK,EACpD,GAAG,EAAE,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,EAC7E,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,CAAC,KAAK,CAAC,KAAK,IAAI,GAChD,IAAI,CAkBN;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,KAAK,EAC9C,GAAG,EAAE,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,GAC/C,GAAG,CAAC,YAAY,CAAC,CAUnB;AAED,6CAA6C;AAC7C,MAAM,WAAW,wBAAwB;IACvC;yDACqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,KAAK,EAC9C,GAAG,EAAE,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,EAChD,OAAO,CAAC,EAAE,wBAAwB,GACjC,GAAG,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAyBlC"}
|
package/dist/vue.js
CHANGED
|
@@ -37,7 +37,6 @@ function useCrossTabSubscription(bus, topic, handler) {
|
|
|
37
37
|
let currentBus = null;
|
|
38
38
|
let currentTopic = null;
|
|
39
39
|
let cleanup;
|
|
40
|
-
let latestHandler = handler;
|
|
41
40
|
const stop = () => {
|
|
42
41
|
cleanup?.();
|
|
43
42
|
cleanup = void 0;
|
|
@@ -52,13 +51,10 @@ function useCrossTabSubscription(bus, topic, handler) {
|
|
|
52
51
|
if (!nextBus) return;
|
|
53
52
|
currentBus = nextBus;
|
|
54
53
|
currentTopic = nextTopic;
|
|
55
|
-
cleanup = nextBus.subscribe(nextTopic,
|
|
54
|
+
cleanup = nextBus.subscribe(nextTopic, handler);
|
|
56
55
|
};
|
|
57
56
|
watch(bus, sync, { immediate: true });
|
|
58
57
|
if (typeof topic !== "string") watch(topic, sync);
|
|
59
|
-
watch(() => handler, (value) => {
|
|
60
|
-
latestHandler = value;
|
|
61
|
-
});
|
|
62
58
|
onBeforeUnmount(stop);
|
|
63
59
|
}
|
|
64
60
|
function useCrossTabStatus(bus) {
|
package/dist/vue.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/vue.ts"],
|
|
4
|
-
"sourcesContent": ["/** Vue 3 composables adapter for cross-tab-worker-databus.\n * Vue is an optional peer dependency; this module is a separate entry point.\n */\nimport { onBeforeUnmount, onMounted, ref, shallowRef, watch, type Ref } from 'vue';\nimport type { CrossTabDataBus, DataBusHealthSummary } from './core/data-bus';\nimport type { DataBusMessage, WorkerStatus } from './core/types';\nimport { WORKER_STATUS } from './utils/constants';\n\nexport function useCrossTabDataBus<TConfig, TData>(\n create: () => CrossTabDataBus<TConfig, TData>,\n deps: ReadonlyArray<Ref<unknown> | (() => unknown)> = []\n): Ref<CrossTabDataBus<TConfig, TData> | null> {\n const bus = shallowRef<CrossTabDataBus<TConfig, TData> | null>(null);\n let instance: CrossTabDataBus<TConfig, TData> | null = null;\n let lifecycleGeneration = 0;\n const stop = async () => { const current = instance; instance = null; bus.value = null; if (current) await current.stop(); };\n const start = () => {\n const generation = ++lifecycleGeneration;\n void stop().then(() => {\n if (generation !== lifecycleGeneration) return;\n const next = create();\n instance = next;\n bus.value = next;\n void next.ready().catch(() => {});\n });\n };\n onMounted(start);\n onBeforeUnmount(() => {\n // Bump the generation so a start() still awaiting its stop() sees itself\n // superseded. Without this the pending continuation would run create()\n // after the component is gone, leaving a live bus with no owner to stop\n // it (the React adapter has no such window: its create() is synchronous\n // inside useEffect).\n lifecycleGeneration += 1;\n void stop();\n });\n if (deps.length > 0) watch(deps, start);\n return bus as Ref<CrossTabDataBus<TConfig, TData> | null>;\n}\n\nexport function useCrossTabSubscription<TConfig, TData>(\n bus: Ref<CrossTabDataBus<TConfig, TData> | null>, topic: Ref<string> | string,\n handler: (message: DataBusMessage<TData>) => void\n): void {\n let currentBus: CrossTabDataBus<TConfig, TData> | null = null;\n let currentTopic: string | null = null;\n let cleanup: (() => void) | undefined;\n
|
|
5
|
-
"mappings": ";;;;;AAGA,SAAS,iBAAiB,WAAW,KAAK,YAAY,aAAuB;AAKtE,SAAS,mBACd,QACA,OAAsD,CAAC,GACV;AAC7C,QAAM,MAAM,WAAmD,IAAI;AACnE,MAAI,WAAmD;AACvD,MAAI,sBAAsB;AAC1B,QAAM,OAAO,YAAY;AAAE,UAAM,UAAU;AAAU,eAAW;AAAM,QAAI,QAAQ;AAAM,QAAI,QAAS,OAAM,QAAQ,KAAK;AAAA,EAAG;AAC3H,QAAM,QAAQ,MAAM;AAClB,UAAM,aAAa,EAAE;AACrB,SAAK,KAAK,EAAE,KAAK,MAAM;AACrB,UAAI,eAAe,oBAAqB;AACxC,YAAM,OAAO,OAAO;AACpB,iBAAW;AACX,UAAI,QAAQ;AACZ,WAAK,KAAK,MAAM,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IAClC,CAAC;AAAA,EACH;AACA,YAAU,KAAK;AACf,kBAAgB,MAAM;AAMpB,2BAAuB;AACvB,SAAK,KAAK;AAAA,EACZ,CAAC;AACD,MAAI,KAAK,SAAS,EAAG,OAAM,MAAM,KAAK;AACtC,SAAO;AACT;AAEO,SAAS,wBACd,KAAkD,OAClD,SACM;AACN,MAAI,aAAqD;AACzD,MAAI,eAA8B;AAClC,MAAI;AACJ,
|
|
4
|
+
"sourcesContent": ["/** Vue 3 composables adapter for cross-tab-worker-databus.\n * Vue is an optional peer dependency; this module is a separate entry point.\n */\nimport { onBeforeUnmount, onMounted, ref, shallowRef, watch, type Ref } from 'vue';\nimport type { CrossTabDataBus, DataBusHealthSummary } from './core/data-bus';\nimport type { DataBusMessage, WorkerStatus } from './core/types';\nimport { WORKER_STATUS } from './utils/constants';\n\nexport function useCrossTabDataBus<TConfig, TData>(\n create: () => CrossTabDataBus<TConfig, TData>,\n deps: ReadonlyArray<Ref<unknown> | (() => unknown)> = []\n): Ref<CrossTabDataBus<TConfig, TData> | null> {\n const bus = shallowRef<CrossTabDataBus<TConfig, TData> | null>(null);\n let instance: CrossTabDataBus<TConfig, TData> | null = null;\n let lifecycleGeneration = 0;\n const stop = async () => { const current = instance; instance = null; bus.value = null; if (current) await current.stop(); };\n const start = () => {\n const generation = ++lifecycleGeneration;\n void stop().then(() => {\n if (generation !== lifecycleGeneration) return;\n const next = create();\n instance = next;\n bus.value = next;\n void next.ready().catch(() => {});\n });\n };\n onMounted(start);\n onBeforeUnmount(() => {\n // Bump the generation so a start() still awaiting its stop() sees itself\n // superseded. Without this the pending continuation would run create()\n // after the component is gone, leaving a live bus with no owner to stop\n // it (the React adapter has no such window: its create() is synchronous\n // inside useEffect).\n lifecycleGeneration += 1;\n void stop();\n });\n if (deps.length > 0) watch(deps, start);\n return bus as Ref<CrossTabDataBus<TConfig, TData> | null>;\n}\n\nexport function useCrossTabSubscription<TConfig, TData>(\n bus: Ref<CrossTabDataBus<TConfig, TData> | null>, topic: Ref<string> | string,\n handler: (message: DataBusMessage<TData>) => void\n): void {\n let currentBus: CrossTabDataBus<TConfig, TData> | null = null;\n let currentTopic: string | null = null;\n let cleanup: (() => void) | undefined;\n const stop = () => { cleanup?.(); cleanup = undefined; currentBus = null; currentTopic = null; };\n const sync = () => {\n const nextBus = bus.value;\n const nextTopic = typeof topic === 'string' ? topic : topic.value;\n if (nextBus === currentBus && currentTopic === nextTopic && cleanup) return;\n stop();\n if (!nextBus) return;\n currentBus = nextBus;\n currentTopic = nextTopic;\n cleanup = nextBus.subscribe(nextTopic, handler);\n };\n watch(bus, sync, { immediate: true });\n if (typeof topic !== 'string') watch(topic, sync);\n onBeforeUnmount(stop);\n}\n\nexport function useCrossTabStatus<TConfig, TData>(\n bus: Ref<CrossTabDataBus<TConfig, TData> | null>\n): Ref<WorkerStatus> {\n const status = ref<WorkerStatus>(WORKER_STATUS.CONNECTING);\n let cleanup: (() => void) | undefined;\n watch(bus, next => {\n cleanup?.(); cleanup = undefined;\n status.value = next?.getStatus() ?? WORKER_STATUS.CONNECTING;\n if (next) cleanup = next.onStatus(value => { status.value = value; });\n }, { immediate: true });\n onBeforeUnmount(() => cleanup?.());\n return status;\n}\n\n/** Options for {@link useCrossTabHealth}. */\nexport interface UseCrossTabHealthOptions {\n /** Polling cadence in ms for the health snapshot. Default 1000; `0` disables\n * polling and relies on status/error events only. */\n intervalMs?: number;\n}\n\n/**\n * Mirror the bus health summary into a Vue ref. `getHealthSummary()` is a\n * snapshot, so the composable polls it on an interval (default 1000 ms) and\n * refreshes on status changes and errors. A reactive interval change replaces\n * the timer without rebuilding the bus. Returns `null` until the bus exists.\n */\nexport function useCrossTabHealth<TConfig, TData>(\n bus: Ref<CrossTabDataBus<TConfig, TData> | null>,\n options?: UseCrossTabHealthOptions\n): Ref<DataBusHealthSummary | null> {\n const health = ref<DataBusHealthSummary | null>(null);\n let timer: ReturnType<typeof setInterval> | null = null;\n let cleanups: Array<() => void> = [];\n const teardown = () => {\n if (timer) clearInterval(timer);\n timer = null;\n for (const cleanup of cleanups) cleanup();\n cleanups = [];\n };\n watch([bus, () => options?.intervalMs], ([next]) => {\n teardown();\n if (!next) {\n health.value = null;\n return;\n }\n const refresh = () => { health.value = next.getHealthSummary(); };\n refresh();\n cleanups.push(next.onStatus(refresh));\n cleanups.push(next.onError(refresh));\n const intervalMs = options?.intervalMs ?? 1_000;\n if (intervalMs > 0) timer = setInterval(refresh, intervalMs);\n }, { immediate: true });\n onBeforeUnmount(teardown);\n return health as Ref<DataBusHealthSummary | null>;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;AAGA,SAAS,iBAAiB,WAAW,KAAK,YAAY,aAAuB;AAKtE,SAAS,mBACd,QACA,OAAsD,CAAC,GACV;AAC7C,QAAM,MAAM,WAAmD,IAAI;AACnE,MAAI,WAAmD;AACvD,MAAI,sBAAsB;AAC1B,QAAM,OAAO,YAAY;AAAE,UAAM,UAAU;AAAU,eAAW;AAAM,QAAI,QAAQ;AAAM,QAAI,QAAS,OAAM,QAAQ,KAAK;AAAA,EAAG;AAC3H,QAAM,QAAQ,MAAM;AAClB,UAAM,aAAa,EAAE;AACrB,SAAK,KAAK,EAAE,KAAK,MAAM;AACrB,UAAI,eAAe,oBAAqB;AACxC,YAAM,OAAO,OAAO;AACpB,iBAAW;AACX,UAAI,QAAQ;AACZ,WAAK,KAAK,MAAM,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IAClC,CAAC;AAAA,EACH;AACA,YAAU,KAAK;AACf,kBAAgB,MAAM;AAMpB,2BAAuB;AACvB,SAAK,KAAK;AAAA,EACZ,CAAC;AACD,MAAI,KAAK,SAAS,EAAG,OAAM,MAAM,KAAK;AACtC,SAAO;AACT;AAEO,SAAS,wBACd,KAAkD,OAClD,SACM;AACN,MAAI,aAAqD;AACzD,MAAI,eAA8B;AAClC,MAAI;AACJ,QAAM,OAAO,MAAM;AAAE,cAAU;AAAG,cAAU;AAAW,iBAAa;AAAM,mBAAe;AAAA,EAAM;AAC/F,QAAM,OAAO,MAAM;AACjB,UAAM,UAAU,IAAI;AACpB,UAAM,YAAY,OAAO,UAAU,WAAW,QAAQ,MAAM;AAC5D,QAAI,YAAY,cAAc,iBAAiB,aAAa,QAAS;AACrE,SAAK;AACL,QAAI,CAAC,QAAS;AACd,iBAAa;AACb,mBAAe;AACf,cAAU,QAAQ,UAAU,WAAW,OAAO;AAAA,EAChD;AACA,QAAM,KAAK,MAAM,EAAE,WAAW,KAAK,CAAC;AACpC,MAAI,OAAO,UAAU,SAAU,OAAM,OAAO,IAAI;AAChD,kBAAgB,IAAI;AACtB;AAEO,SAAS,kBACd,KACmB;AACnB,QAAM,SAAS,IAAkB,cAAc,UAAU;AACzD,MAAI;AACJ,QAAM,KAAK,UAAQ;AACjB,cAAU;AAAG,cAAU;AACvB,WAAO,QAAQ,MAAM,UAAU,KAAK,cAAc;AAClD,QAAI,KAAM,WAAU,KAAK,SAAS,WAAS;AAAE,aAAO,QAAQ;AAAA,IAAO,CAAC;AAAA,EACtE,GAAG,EAAE,WAAW,KAAK,CAAC;AACtB,kBAAgB,MAAM,UAAU,CAAC;AACjC,SAAO;AACT;AAeO,SAAS,kBACd,KACA,SACkC;AAClC,QAAM,SAAS,IAAiC,IAAI;AACpD,MAAI,QAA+C;AACnD,MAAI,WAA8B,CAAC;AACnC,QAAM,WAAW,MAAM;AACrB,QAAI,MAAO,eAAc,KAAK;AAC9B,YAAQ;AACR,eAAW,WAAW,SAAU,SAAQ;AACxC,eAAW,CAAC;AAAA,EACd;AACA,QAAM,CAAC,KAAK,MAAM,SAAS,UAAU,GAAG,CAAC,CAAC,IAAI,MAAM;AAClD,aAAS;AACT,QAAI,CAAC,MAAM;AACT,aAAO,QAAQ;AACf;AAAA,IACF;AACA,UAAM,UAAU,MAAM;AAAE,aAAO,QAAQ,KAAK,iBAAiB;AAAA,IAAG;AAChE,YAAQ;AACR,aAAS,KAAK,KAAK,SAAS,OAAO,CAAC;AACpC,aAAS,KAAK,KAAK,QAAQ,OAAO,CAAC;AACnC,UAAM,aAAa,SAAS,cAAc;AAC1C,QAAI,aAAa,EAAG,SAAQ,YAAY,SAAS,UAAU;AAAA,EAC7D,GAAG,EAAE,WAAW,KAAK,CAAC;AACtB,kBAAgB,QAAQ;AACxB,SAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/docs/benchmarks.md
CHANGED
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
# Browser Benchmark Trend
|
|
4
4
|
|
|
5
|
-
> Data through 2026-09-
|
|
5
|
+
> Data through 2026-09-21, from the 40 archived `bench-results/browser-*.json` reports (run `pnpm bench:browser` to add one; regenerate this doc with `node scripts/bench-trend.mjs`).
|
|
6
6
|
|
|
7
|
-
The comparison baseline for release gating is `pnpm bench:compare --fail-above-pct 50
|
|
7
|
+
The comparison baseline for release gating is `pnpm bench:compare --fail-above-pct 50`, which compares the newest report against the median of the same metric in the preceding reports (50% ceiling absorbs shared-runner noise; a single previous report was a fragile baseline because the in-page hot-path metrics alternate between a fast and a slow mode on identical code). This doc records the long-run picture: values are per-metric latencies where lower is better, and the last column is the best run inside the most recent 5 reports — not an all-time record, because the in-page matrix changed measurement semantics in early September 2026 and older reports are not comparable.
|
|
8
8
|
|
|
9
9
|
<!-- BENCH-TREND:BEGIN (machine-generated table) -->
|
|
10
|
-
| Metric | Previous (ms) | Latest (ms) | Δ |
|
|
10
|
+
| Metric | Previous (ms) | Latest (ms) | Δ | Best of last 5 runs (ms) |
|
|
11
11
|
|---|---|---|---|---|
|
|
12
|
-
| publish per-message (ms, lower is better) — dedicated |
|
|
13
|
-
| publish per-message (ms, lower is better) — shared | 34.
|
|
14
|
-
| wildcard dispatch ×1000 (ms, lower is better) |
|
|
15
|
-
| publishBatch ×1000 (ms, lower is better) | 4.
|
|
16
|
-
| dedup ×1000 (ms, lower is better) |
|
|
17
|
-
| trace + publish ×1000 (ms, lower is better) |
|
|
18
|
-
| first-packet cold dispatch (ms, lower is better) | 0 | 0 |
|
|
12
|
+
| publish per-message (ms, lower is better) — dedicated | 49.7556 | 49.4012 | -0.35 | 40.4432 |
|
|
13
|
+
| publish per-message (ms, lower is better) — shared | 34.1052 | 33.8616 | -0.24 | 33.8616 |
|
|
14
|
+
| wildcard dispatch ×1000 (ms, lower is better) | 5.4 | 6.8 | +1.40 | 5.4 |
|
|
15
|
+
| publishBatch ×1000 (ms, lower is better) | 4.2 | 3.5 | -0.70 | 3.5 |
|
|
16
|
+
| dedup ×1000 (ms, lower is better) | 11 | 10.6 | -0.40 | 9.8 |
|
|
17
|
+
| trace + publish ×1000 (ms, lower is better) | 4.8 | 4.6 | -0.20 | 4.5 |
|
|
18
|
+
| first-packet cold dispatch (ms, lower is better) | 0.1 | 0 | -0.10 | 0 |
|
|
19
19
|
<!-- BENCH-TREND:END -->
|
|
20
20
|
|
|
21
21
|
Notes:
|
package/docs/configuration.md
CHANGED
|
@@ -87,7 +87,7 @@ Retry waits are lifecycle-aware: `stop()` and pagehide suspension cancel pending
|
|
|
87
87
|
|
|
88
88
|
The Vue adapter serializes bus replacement and ignores stale stop completions when reactive dependencies change rapidly, preserving the newest component lifecycle.
|
|
89
89
|
|
|
90
|
-
The React adapter
|
|
90
|
+
The React adapter relies on React's own effect ordering instead of a generation counter: an effect's cleanup always runs before its next invocation, and nothing inside the effect yields, so each run stops exactly the instance it created.
|
|
91
91
|
|
|
92
92
|
IndexedDB replay persistence closes connections receiving `versionchange` and lazily reopens them for the next operation, which keeps multi-tab schema upgrades recoverable.
|
|
93
93
|
|
|
@@ -204,6 +204,8 @@ When `BroadcastChannel` is unavailable (some WebViews, older browsers), the clus
|
|
|
204
204
|
|
|
205
205
|
`createBrowserEnvironment({ channelFallback: 'storage-event' })` opts into a fallback `ClusterChannel` backed by localStorage `storage` events, preserving cross-tab coordination. It is opt-in because of a security trade-off: BroadcastChannel messages live in memory only, while the fallback writes coordination payloads (which carry plaintext topic names) to localStorage under the `cross-tab-worker-databus:channel:` key namespace — at least transiently, and indefinitely after a tab crash. The key is removed when the channel closes.
|
|
206
206
|
|
|
207
|
+
Storage events are delivered to other documents only. Two bus runtimes in the *same* document that share a `clusterKey` therefore do not exchange channel frames through the fallback; they still converge through the shared localStorage coordination records and the reconcile loop (bounded by the heartbeat interval). Give each runtime a distinct `clusterKey` — or keep BroadcastChannel — when you need same-document coordination.
|
|
208
|
+
|
|
207
209
|
## SharedWorker Session Reaper
|
|
208
210
|
|
|
209
211
|
A `MessagePort` has no `close` event, so the SharedWorker cannot know when a tab has crashed or been closed without sending a `STOP` message. To avoid leaking a `CentrifugeSession` (and its WebSocket) for a dead tab, the transport sends a periodic **PING heartbeat** to the SharedWorker, and the SharedWorker runs a **reaper** that closes any session whose port has been silent for longer than its timeout.
|
|
@@ -11,7 +11,7 @@ Use this checklist for each pre-1.0 release. The repository does not publish fro
|
|
|
11
11
|
|
|
12
12
|
## Automated gates (CI)
|
|
13
13
|
|
|
14
|
-
The `CI` workflow's `verify` job runs `pnpm check`, `pnpm lint`, `pnpm test:coverage` (the `vitest.config.ts` floors:
|
|
14
|
+
The `CI` workflow's `verify` job runs `pnpm check`, `pnpm lint`, `pnpm test:coverage` (the `vitest.config.ts` floors: 96% statements / 92% branches / 96% functions / 97% lines), `pnpm verify:compat`, `pnpm verify:pack`, `pnpm bench`, and `pnpm audit` on every push and pull request; the `browser` job runs the Playwright E2E suite. The `Release` workflow repeats `verify:compat` and `verify:pack` before publishing, then runs the blocking `verify:published` gate. The checkout in both workflows uses `fetch-depth: 0` + `fetch-tags: true` because `verify:compat` resolves its baseline from the most recent release tag.
|
|
15
15
|
|
|
16
16
|
Only `pnpm bench:browser` / `pnpm bench:compare` stay local-only: shared-runner timing noise makes numeric CI gates unreliable.
|
|
17
17
|
|
|
@@ -20,7 +20,7 @@ Only `pnpm bench:browser` / `pnpm bench:compare` stay local-only: shared-runner
|
|
|
20
20
|
1. Update `package.json`, `CHANGELOG.md`, and both roadmap files.
|
|
21
21
|
2. Run `pnpm check`, `pnpm lint`, `pnpm test:coverage`, `pnpm bench`, `pnpm test:e2e`, `pnpm bench:browser`, `pnpm verify:pack`, `pnpm verify:compat`, and `git diff --check`. (`verify:compat` asserts the package `exports` subpaths and type fields present in the `COMPAT_BASE_TAG` baseline still exist; `verify:pack` steam-imports the full root public surface plus every subpath in ESM and CJS from the packed tarball. `verify:compat` resolves its baseline from the most recent release tag, so a shallow or tag-less clone must first run `git fetch --tags` or it fails with "no version tag found".)
|
|
22
22
|
3. Gate dependency security: `pnpm audit --registry=https://registry.npmjs.org` (the configured mirror registry lacks the audit endpoint; CI runs it on the public registry in the verify job). Fail the release on any known-vulnerability advisory; `pnpm-workspace.yaml` overrides pin patched ranges.
|
|
23
|
-
4. Gate browser benchmark regressions: `pnpm bench:compare --fail-above-pct 50
|
|
23
|
+
4. Gate browser benchmark regressions: run `pnpm bench:browser` (twice at minimum; the gate compares the newest report against the median of the same metric in up to the five preceding archived reports) and then `pnpm bench:compare --fail-above-pct 50`. The median baseline exists because the in-page hot-path metrics alternate between a fast and a slow mode on identical code — two consecutive runs of `dedup1000Ms` measured 12.7 ms then 25.6 ms, and a single noisy previous report could fail the documented ceiling with no code change at all. `publish/dedicated/perMessageMs` is noisy the same way: two consecutive runs of identical code measured 49.9 ms then 71.1 ms, failing the gate at +75.7% while `dedup1000Ms` and `traceAndPublish1000Ms` *improved* in the same report — that single-metric-up-everything-else-down shape is the noise signature, and the next run reported 49.4 ms and passed. Before accepting or acting on a failure, re-run and check the spread; if the change touches a hot path, size it directly (a micro-benchmark of the 0.20.95 bounded-map rewrites measured 80–86 ns/op across all three variants, i.e. inside run-to-run variance). A baseline shift (e.g. a metric becoming real instead of a no-op) is an expected one-time failure. Refresh the long-run trend doc with `pnpm bench:trend` and commit it when the tables change.
|
|
24
24
|
5. Confirm the package contains only intended files with `npm pack --dry-run --json`.
|
|
25
25
|
6. Commit on a feature branch, push that branch, and merge its green PR using squash or fast-forward (no merge commit). Fetch the merged commit, tag that exact commit, and push only the specific version tag; never push `main`/`master` directly or force-push. The workflow runs `node scripts/verify-release-version.mjs` to require `RELEASE_TAG` to equal `v` + the package version and to require exactly one non-empty CHANGELOG section.
|
|
26
26
|
|
package/docs/roadmap.md
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
1
|
# Roadmap
|
|
2
2
|
|
|
3
|
-
0.20.
|
|
3
|
+
0.20.95 was released on September 22, 2026. The project is intentionally continuing through reliability-focused releases before a 1.0.0 stability freeze.
|
|
4
4
|
|
|
5
|
-
## 0.20.
|
|
5
|
+
## 0.20.95 delivered scope
|
|
6
|
+
|
|
7
|
+
- Removed unreachable defensive branches instead of leaving them to inflate coverage: the storage writer's already-armed retry guard, the `undefined` breaks in both bounded-map eviction loops, and the Centrifuge transport's three Worker/port generation checks — the last of which could not identify which Worker fired even when reachable.
|
|
8
|
+
- Dropped the React adapter's lifecycle generation ref, which no React effect ordering can reach, and corrected the configuration doc that had been describing it. The Vue adapter's guard is genuinely load-bearing and stays.
|
|
9
|
+
- Closed a Vitest assertion hole that had voided every `reason ?? new Error(...)` fallback-message test in the IndexedDB replay suite: `rejects.toThrow('message')` also passes on a `null` or `undefined` rejection reason. `expectRejectionMessage()` now asserts the `Error` instance as well, and the convention is recorded in `AGENTS.md`.
|
|
10
|
+
- Six more behaviors are pinned by mutation-verified regressions — the storage-event channel's malformed-payload guard, the BroadcastChannel-less fallback wiring documented in the getting-started guide, storage-writer key enumeration, dedup sweep partial expiry, the late credential failure path, and the React hook publishing the newest bus. `environment.ts`, `storage-batch.ts`, `dedup-manager.ts` and `hooks.ts` are now at 100% coverage on all four metrics.
|
|
11
|
+
|
|
12
|
+
## 0.20.94 delivered scope
|
|
13
|
+
|
|
14
|
+
- Fixed the Vue subscription composable's permanently inert watcher on its own handler parameter, and pinned the same-target rebind guard that prevents a torn-down-and-recreated subscription when the bus and topic change in one tick.
|
|
15
|
+
- Made the CI unit gate survivable under runner load: a 15s ceiling for the subprocess-spawning package/compat gates and an explicit 120s budget for the seeded lifecycle fuzzer, which had reached 98% of its own limit under coverage instrumentation.
|
|
16
|
+
- Raised the coverage floors from advisory to enforced, keeping them a few points under the measured values instead of ten.
|
|
17
|
+
- Added mutation-verified regressions for nine behaviors that had no effective test, including a route-owner-cache eviction assertion that passed with the eviction loop deleted, the failed-hydration retry on the next start, the metadata-less item of an unpacked remote batch, and superseded-client status isolation.
|
|
18
|
+
|
|
19
|
+
## 0.20.93 delivered scope
|
|
6
20
|
|
|
7
21
|
- Strengthen package compatibility checks across package metadata, unconditional and fallback-array targets, and recursive nested or custom export conditions.
|
|
8
22
|
- Require a readable storage capability probe, degrade safely when channel construction fails, and preserve a stable in-memory tab identity when session storage is unavailable.
|
|
@@ -534,14 +548,14 @@ The line continues the async-callback isolation audit: every fix below binds a c
|
|
|
534
548
|
1. ~~Publish a peer capability matrix and expose SDK/backend/transport identity in diagnostics.~~ Delivered: `getDiagnostics()` carries protocol version, unknown-message stats, peer protocol versions, and transport identity; `getHealthSummary()`/`getMetrics()` now ship live trace metrics and sink state.
|
|
535
549
|
2. ~~Unify replay, deduplication, trace, recovery, and cluster health counters.~~ Delivered: `getDiagnostics()` + `getMetrics()` + `getHealthSummary()` cover lifecycle, recovery, dedup, replay, persistence, protocol, transport, cluster, trace metrics, and sink back-pressure in single snapshots.
|
|
536
550
|
3. ~~Optimize IndexedDB concurrent append and cleanup paths.~~ Delivered: adjacent `appendBatch` mutations coalesce into one transaction; clear/clearTopic/clearBefore ordering preserved.
|
|
537
|
-
4. ~~Add performance baselines for adaptive dedup, async trace, pruning, and long-running multi-tab workloads.~~
|
|
551
|
+
4. ~~Add performance baselines for adaptive dedup, async trace, pruning, and long-running multi-tab workloads.~~ Delivered: bench covers load-weighting scoring, `getMetrics`, publishBatch batch-size sensitivity, adaptive dedup TTL, age-strategy replay pruning, a two-worker cross-tab fan-out, and the existing dedup/async-sink/persistence cases.
|
|
538
552
|
|
|
539
553
|
## 0.13.0 candidates
|
|
540
554
|
|
|
541
|
-
1. Freeze the public export surface and transport-neutral publication envelope.
|
|
555
|
+
1. ~~Freeze the public export surface and transport-neutral publication envelope.~~ Delivered: the root export surface is pinned by a regression test and the tag-to-tag `verify:compat` gate, and the transport-neutral publication envelope (with legacy/nested frame compatibility) is documented and covered by protocol fixtures.
|
|
542
556
|
2. ~~Document at-least-once delivery and deduplication guarantees precisely.~~ Delivered: architecture/API/capability docs now distinguish at-most-once local fan-out per accepted transport publication from end-to-end delivery, document transport/server loss and redelivery, and describe bounded opt-in `messageId` dedup without claiming at-least-once or exactly-once.
|
|
543
|
-
3. Add long-running browser soak coverage for replay retention, reconnect, BFCache, and owner migration.
|
|
544
|
-
4. Publish a migration guide and deprecation policy for any pre-1.0 protocol aliases.
|
|
557
|
+
3. ~~Add long-running browser soak coverage for replay retention, reconnect, BFCache, and owner migration.~~ Delivered: the real-Chromium multi-tab soak and the repeated BFCache/reload/owner-handoff scenarios exercise one continuous session across the full lifecycle.
|
|
558
|
+
4. ~~Publish a migration guide and deprecation policy for any pre-1.0 protocol aliases.~~ Delivered: the deprecation policy lives in the release checklist, the "Upgrading & Deprecation" guide is published in both getting-started references, and legacy protocol frames are parsed for one minor with the active version surfaced in `getDiagnostics().protocol`.
|
|
545
559
|
|
|
546
560
|
## Longer-term candidates
|
|
547
561
|
|
|
@@ -550,6 +564,7 @@ The line continues the async-callback isolation audit: every fix below binds a c
|
|
|
550
564
|
3. **Publication deduplication** — design and implement an opt-in, bounded message-ID window that works across local dispatch, BroadcastChannel fan-out, WebSocket, and replay without changing the default behavior.
|
|
551
565
|
4. **Adapter and protocol parity** — align React/Vue lifecycle and type contracts, document binary framing and recovery semantics, and add compatibility fixtures for custom transports.
|
|
552
566
|
5. **Operational validation** — extend browser and package-consumption tests, add regression benchmarks for dedup/recovery/replay cleanup, and keep push CI as a release gate.
|
|
567
|
+
6. **TypeScript 7 toolchain migration** — blocked upstream, not here: as of 2026-09-22 `typescript-eslint` is released only up to 8.70.1, whose peer range is `typescript >=4.8.4 <6.1.0`, so installing TypeScript 7 breaks the lint gate before it breaks our own types. Re-check when a typescript-eslint release widens that ceiling, then migrate in an isolated branch (TS 7 still exposes a `tsc` bin, so `pnpm typecheck` itself needs no change).
|
|
553
568
|
|
|
554
569
|
## Release checklist
|
|
555
570
|
|
package/docs/zh/benchmarks.md
CHANGED
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
# 浏览器基准趋势
|
|
4
4
|
|
|
5
|
-
> 数据截至 2026-09-
|
|
5
|
+
> 数据截至 2026-09-21,基于 40 份归档的 `bench-results/browser-*.json` 报告(运行 `pnpm bench:browser` 追加一份;用 `node scripts/bench-trend.mjs` 重新生成本文档)。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
发布门禁的对比基线是 `pnpm bench:compare --fail-above-pct 50`:将最新报告与其之前若干报告中同一指标的中位数比较(50% 上限用于吸收共享 runner 的噪声;此前只看"上一份报告"并不稳定,因为页内热路径指标在同一份代码上会在快/慢两档之间来回跳)。本文记录长期趋势:数值为逐指标延迟,越低越好;最后一列是最近 5 份报告内的最优值,而不是历史纪录——页内基准矩阵在 2026 年 9 月初变更过测量语义,更早的报告不可比。
|
|
8
8
|
|
|
9
9
|
<!-- BENCH-TREND:BEGIN (machine-generated table) -->
|
|
10
|
-
| 指标 | 上次 (ms) | 本次 (ms) | Δ |
|
|
10
|
+
| 指标 | 上次 (ms) | 本次 (ms) | Δ | 近 5 次最优 (ms) |
|
|
11
11
|
|---|---|---|---|---|
|
|
12
|
-
| publish per-message (ms, lower is better) — dedicated |
|
|
13
|
-
| publish per-message (ms, lower is better) — shared | 34.
|
|
14
|
-
| wildcard dispatch ×1000 (ms, lower is better) |
|
|
15
|
-
| publishBatch ×1000 (ms, lower is better) | 4.
|
|
16
|
-
| dedup ×1000 (ms, lower is better) |
|
|
17
|
-
| trace + publish ×1000 (ms, lower is better) |
|
|
18
|
-
| first-packet cold dispatch (ms, lower is better) | 0 | 0 |
|
|
12
|
+
| publish per-message (ms, lower is better) — dedicated | 49.7556 | 49.4012 | -0.35 | 40.4432 |
|
|
13
|
+
| publish per-message (ms, lower is better) — shared | 34.1052 | 33.8616 | -0.24 | 33.8616 |
|
|
14
|
+
| wildcard dispatch ×1000 (ms, lower is better) | 5.4 | 6.8 | +1.40 | 5.4 |
|
|
15
|
+
| publishBatch ×1000 (ms, lower is better) | 4.2 | 3.5 | -0.70 | 3.5 |
|
|
16
|
+
| dedup ×1000 (ms, lower is better) | 11 | 10.6 | -0.40 | 9.8 |
|
|
17
|
+
| trace + publish ×1000 (ms, lower is better) | 4.8 | 4.6 | -0.20 | 4.5 |
|
|
18
|
+
| first-packet cold dispatch (ms, lower is better) | 0.1 | 0 | -0.10 | 0 |
|
|
19
19
|
<!-- BENCH-TREND:END -->
|
|
20
20
|
|
|
21
21
|
说明:
|
package/docs/zh/configuration.md
CHANGED
|
@@ -87,7 +87,7 @@ Retry 等待遵循生命周期:`stop()` 和 pagehide 挂起会取消待执行
|
|
|
87
87
|
|
|
88
88
|
Vue 适配层会串行化 bus 替换,并在 reactive 依赖快速变化时忽略过期的 stop 完成,确保组件始终绑定最新生命周期。
|
|
89
89
|
|
|
90
|
-
React
|
|
90
|
+
React 适配层不再使用 generation 计数,而是依赖 React 自身的 effect 顺序:一个 effect 的清理一定先于它的下一次执行,而且 effect 体内不会让出异步,因此每次运行只会停止它自己创建的那个实例。
|
|
91
91
|
|
|
92
92
|
IndexedDB replay persistence 收到 `versionchange` 时会关闭连接,并在下一次操作时惰性重新打开,从而支持多 tab schema 升级后的恢复。
|
|
93
93
|
|
|
@@ -197,6 +197,8 @@ const bus = createCentrifugeDataBus({
|
|
|
197
197
|
|
|
198
198
|
`createBrowserEnvironment({ channelFallback: 'storage-event' })` 可选择启用基于 localStorage `storage` 事件的降级 `ClusterChannel`,保留跨 Tab 协调能力。该能力为 opt-in,原因是安全权衡:BroadcastChannel 消息仅存在于内存,而降级通道会把协调载荷(含明文 Topic 名称)写入 localStorage 的 `cross-tab-worker-databus:channel:` 键空间——至少短暂落盘,Tab 崩溃后可能长期留存。通道关闭时会清除该键。
|
|
199
199
|
|
|
200
|
+
storage 事件只在其他 document 中派发。因此同一 document 内共享同一 `clusterKey` 的两个 bus runtime 不会通过该降级通道交换 channel 帧;它们仍会通过共享的 localStorage 协调记录与 reconcile 循环收敛(上界为一个心跳间隔)。若需要同 document 内协调,请为每个 runtime 使用不同的 `clusterKey`,或保留 BroadcastChannel。
|
|
201
|
+
|
|
200
202
|
## SharedWorker 会话回收
|
|
201
203
|
|
|
202
204
|
`MessagePort` 没有 `close` 事件,因此 SharedWorker 无法在 Tab 崩溃或关闭时获知(除非收到 `STOP` 消息)。为避免泄漏已死 Tab 的 `CentrifugeSession`(及其 WebSocket),transport 定期向 SharedWorker 发送 **PING 心跳**,SharedWorker 运行一个**回收器**来关闭超过静默超时的端口会话。
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
## 自动化门禁(CI)
|
|
13
13
|
|
|
14
|
-
`CI` 工作流的 `verify` job 在每次 push 与 pull request 上运行 `pnpm check`、`pnpm lint`、`pnpm test:coverage`(`vitest.config.ts` 中的下限:语句
|
|
14
|
+
`CI` 工作流的 `verify` job 在每次 push 与 pull request 上运行 `pnpm check`、`pnpm lint`、`pnpm test:coverage`(`vitest.config.ts` 中的下限:语句 96% / 分支 92% / 函数 96% / 行 97%)、`pnpm verify:compat`、`pnpm verify:pack`、`pnpm bench` 与 `pnpm audit`;`browser` job 运行 Playwright E2E 套件。`Release` 工作流在发布前重跑 `verify:compat` 与 `verify:pack`,随后执行阻塞式 `verify:published` 门禁。两个工作流的 checkout 均使用 `fetch-depth: 0` + `fetch-tags: true`,因为 `verify:compat` 需要从最近的发布 tag 解析基线。
|
|
15
15
|
|
|
16
16
|
只有 `pnpm bench:browser` / `pnpm bench:compare` 保持仅本地执行:共享 runner 的计时噪声会让数值型 CI 门禁不可靠。
|
|
17
17
|
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
1. 更新 `package.json`、`CHANGELOG.md` 和中英文 roadmap。
|
|
21
21
|
2. 运行 `pnpm check`、`pnpm lint`、`pnpm test:coverage`、`pnpm bench`、`pnpm test:e2e`、`pnpm bench:browser`、`pnpm verify:pack`、`pnpm verify:compat` 以及 `git diff --check`(`verify:compat` 断言 `COMPAT_BASE_TAG` 基线中的 package `exports` 子路径与类型字段仍然存在;`verify:pack` 从打包产物冒烟导入完整根公共面与全部子路径的 ESM/CJS。`verify:compat` 从最近的发布 tag 解析基线,因此浅克隆或缺少 tag 的克隆需先执行 `git fetch --tags`,否则会以 "no version tag found" 失败)。
|
|
22
22
|
3. 依赖安全门禁:`pnpm audit --registry=https://registry.npmjs.org`(配置的镜像 registry 缺少 audit 端点;CI 在 verify job 中于公共 registry 运行)。任一已知漏洞公告即视为发布失败;`pnpm-workspace.yaml` overrides 钉住补丁版本。
|
|
23
|
-
4.
|
|
23
|
+
4. 浏览器基准回归门禁:运行 `pnpm bench:browser`(至少两次;门禁将最新报告与之前最多五份归档报告中同一指标的中位数比较),随后执行 `pnpm bench:compare --fail-above-pct 50`。采用中位数基线是因为页内热路径指标在同一份代码上会在快/慢两档之间来回跳——`dedup1000Ms` 相邻两次实测分别为 12.7 ms 与 25.6 ms,只看"上一份报告"时,一次偶发噪声就能在无代码改动的情况下击穿既定上限。`publish/dedicated/perMessageMs` 同样如此:同一份代码相邻两次实测为 49.9 ms 与 71.1 ms,令门禁以 +75.7% 失败,而同一份报告里 `dedup1000Ms` 与 `traceAndPublish1000Ms` 反而*变快*——"单指标上涨、其余下降"正是噪声的特征,第三次实测为 49.4 ms 并通过。因此在采信或处理失败前先复跑并观察离散度;若改动涉及热路径,就直接量化其开销(0.20.95 有界映射改写的微基准显示三种写法均为 80–86 ns/op,落在运行间波动之内)。基线迁移(例如某指标从空操作变为真实路径)属预期内的一次性失败。用 `pnpm bench:trend` 刷新长期趋势文档,表格变化时一并提交。
|
|
24
24
|
5. 用 `npm pack --dry-run --json` 确认发布包只包含预期文件。
|
|
25
25
|
6. 在功能分支提交并推送该分支,PR 验证通过后使用 squash 或 fast-forward 合入(不创建 merge commit)。获取合入后的精确提交并打 tag,只推送该版本 tag;禁止直接推送 `main`/`master` 或 force-push。工作流运行 `node scripts/verify-release-version.mjs`,要求 `RELEASE_TAG` 等于 `v` 加 package 版本,且 CHANGELOG 中恰好有一个非空的对应版本章节。
|
|
26
26
|
|