cross-tab-worker-databus 0.20.71 → 0.20.86
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 +216 -2
- package/README.md +8 -0
- package/README.zh.md +4 -0
- package/dist/centrifuge-protocol.d.ts +59 -26
- package/dist/centrifuge-protocol.d.ts.map +1 -1
- package/dist/centrifuge-session.d.ts +9 -0
- package/dist/centrifuge-session.d.ts.map +1 -1
- package/dist/centrifuge.d.ts +12 -2
- package/dist/centrifuge.d.ts.map +1 -1
- package/dist/centrifuge.js +168 -88
- package/dist/centrifuge.js.map +3 -3
- package/dist/centrifuge.shared.worker.js +146 -38
- package/dist/centrifuge.shared.worker.js.map +3 -3
- package/dist/centrifuge.worker.js +140 -33
- package/dist/centrifuge.worker.js.map +3 -3
- package/dist/{chunk-D2SIT473.js → chunk-SDOV3UHG.js} +1304 -515
- package/dist/chunk-SDOV3UHG.js.map +7 -0
- package/dist/chunk-TZ7ZP7YD.js +175 -0
- package/dist/chunk-TZ7ZP7YD.js.map +7 -0
- package/dist/cjs/centrifuge.cjs +1608 -650
- package/dist/cjs/centrifuge.cjs.map +4 -4
- package/dist/cjs/hooks.cjs +37 -2
- package/dist/cjs/hooks.cjs.map +3 -3
- package/dist/cjs/index.cjs +1692 -747
- package/dist/cjs/index.cjs.map +4 -4
- package/dist/cjs/vue.cjs +45 -2
- package/dist/cjs/vue.cjs.map +3 -3
- package/dist/core/cluster.d.ts +40 -4
- package/dist/core/cluster.d.ts.map +1 -1
- package/dist/core/data-bus.d.ts +134 -77
- package/dist/core/data-bus.d.ts.map +1 -1
- package/dist/core/dedup-manager.d.ts +98 -0
- package/dist/core/dedup-manager.d.ts.map +1 -0
- package/dist/core/environment.d.ts +43 -3
- package/dist/core/environment.d.ts.map +1 -1
- package/dist/core/replay-manager.d.ts +129 -0
- package/dist/core/replay-manager.d.ts.map +1 -0
- package/dist/core/replay-persistence.d.ts +2 -1
- package/dist/core/replay-persistence.d.ts.map +1 -1
- package/dist/core/replay-pruning.d.ts +21 -0
- package/dist/core/replay-pruning.d.ts.map +1 -0
- package/dist/core/routing.d.ts +22 -3
- package/dist/core/routing.d.ts.map +1 -1
- package/dist/core/storage-batch.d.ts +0 -4
- package/dist/core/storage-batch.d.ts.map +1 -1
- package/dist/core/trace.d.ts +55 -15
- package/dist/core/trace.d.ts.map +1 -1
- package/dist/core/types.d.ts +58 -9
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/version.d.ts +2 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/hooks.d.ts +12 -1
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +28 -2
- package/dist/hooks.js.map +2 -2
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +263 -166
- package/dist/index.js.map +3 -3
- package/dist/utils/constants.d.ts +170 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/error-utils.d.ts +28 -0
- package/dist/utils/error-utils.d.ts.map +1 -0
- package/dist/utils/metadata.d.ts +16 -0
- package/dist/utils/metadata.d.ts.map +1 -0
- package/dist/utils/storage-utils.d.ts +24 -0
- package/dist/utils/storage-utils.d.ts.map +1 -0
- package/dist/utils/validation.d.ts +76 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/vue.d.ts +13 -1
- package/dist/vue.d.ts.map +1 -1
- package/dist/vue.js +36 -2
- package/dist/vue.js.map +2 -2
- package/dist/websocket.d.ts +6 -1
- package/dist/websocket.d.ts.map +1 -1
- package/dist/worker-mode.d.ts +6 -2
- package/dist/worker-mode.d.ts.map +1 -1
- package/docs/README.md +1 -0
- package/docs/api.md +135 -4
- package/docs/architecture.md +92 -1
- package/docs/benchmarks.md +24 -0
- package/docs/capabilities.md +24 -3
- package/docs/configuration.md +58 -0
- package/docs/getting-started.md +35 -0
- package/docs/release-checklist.md +28 -5
- package/docs/roadmap.md +81 -5
- package/docs/zh/README.md +2 -1
- package/docs/zh/api.md +134 -4
- package/docs/zh/architecture.md +61 -1
- package/docs/zh/benchmarks.md +24 -0
- package/docs/zh/capabilities.md +21 -3
- package/docs/zh/configuration.md +53 -0
- package/docs/zh/getting-started.md +35 -0
- package/docs/zh/release-checklist.md +29 -6
- package/docs/zh/roadmap.md +93 -5
- package/package.json +39 -16
- package/dist/chunk-D2SIT473.js.map +0 -7
|
@@ -5003,50 +5003,140 @@ function parseDataBusPublication(value, fallbackTopic) {
|
|
|
5003
5003
|
};
|
|
5004
5004
|
}
|
|
5005
5005
|
|
|
5006
|
+
// src/utils/constants.ts
|
|
5007
|
+
var WORKER_STATUS = {
|
|
5008
|
+
CONNECTING: "connecting",
|
|
5009
|
+
CONNECTED: "connected",
|
|
5010
|
+
DISCONNECTED: "disconnected",
|
|
5011
|
+
ERROR: "error"
|
|
5012
|
+
};
|
|
5013
|
+
var DEFAULT_STORAGE_PREFIX = "cross-tab-worker-databus";
|
|
5014
|
+
var STORAGE_CHANNEL_PREFIX = `${DEFAULT_STORAGE_PREFIX}:channel:`;
|
|
5015
|
+
var TAB_ID_STORAGE_KEY = `${DEFAULT_STORAGE_PREFIX}:tab-id`;
|
|
5016
|
+
var CENTRIFUGE_INPUT_TYPE = {
|
|
5017
|
+
INIT: "INIT",
|
|
5018
|
+
SUBSCRIBE: "SUBSCRIBE",
|
|
5019
|
+
UNSUBSCRIBE: "UNSUBSCRIBE",
|
|
5020
|
+
PUBLISH: "PUBLISH",
|
|
5021
|
+
PUBLISH_BIN: "PUBLISH_BIN",
|
|
5022
|
+
PING: "PING",
|
|
5023
|
+
STOP: "STOP",
|
|
5024
|
+
TOKEN_RESPONSE: "TOKEN_RESPONSE",
|
|
5025
|
+
TOKEN_ERROR: "TOKEN_ERROR"
|
|
5026
|
+
};
|
|
5027
|
+
var CENTRIFUGE_OUTPUT_TYPE = {
|
|
5028
|
+
STATUS: "STATUS",
|
|
5029
|
+
MESSAGE: "MESSAGE",
|
|
5030
|
+
MESSAGE_BIN: "MESSAGE_BIN",
|
|
5031
|
+
ERROR: "ERROR",
|
|
5032
|
+
TOKEN_REQUEST: "TOKEN_REQUEST"
|
|
5033
|
+
};
|
|
5034
|
+
|
|
5035
|
+
// src/utils/metadata.ts
|
|
5036
|
+
function publicationMetadata(messageId, timestamp) {
|
|
5037
|
+
if (messageId === void 0 && timestamp === void 0) return void 0;
|
|
5038
|
+
return {
|
|
5039
|
+
...messageId === void 0 ? {} : { messageId },
|
|
5040
|
+
...timestamp === void 0 ? {} : { timestamp }
|
|
5041
|
+
};
|
|
5042
|
+
}
|
|
5043
|
+
|
|
5044
|
+
// src/utils/error-utils.ts
|
|
5045
|
+
function serializeError(error) {
|
|
5046
|
+
if (error instanceof Error) {
|
|
5047
|
+
return {
|
|
5048
|
+
name: error.name,
|
|
5049
|
+
message: error.message,
|
|
5050
|
+
...error.stack ? { stack: error.stack } : {}
|
|
5051
|
+
};
|
|
5052
|
+
}
|
|
5053
|
+
const context = error === void 0 ? void 0 : error;
|
|
5054
|
+
return {
|
|
5055
|
+
name: "CentrifugeError",
|
|
5056
|
+
message: typeof error === "string" ? error : "Centrifuge worker operation failed.",
|
|
5057
|
+
...context === void 0 || !isStructuredCloneable(context) ? {} : { context }
|
|
5058
|
+
};
|
|
5059
|
+
}
|
|
5060
|
+
function isStructuredCloneable(value) {
|
|
5061
|
+
if (typeof structuredClone !== "function") return true;
|
|
5062
|
+
try {
|
|
5063
|
+
structuredClone(value);
|
|
5064
|
+
return true;
|
|
5065
|
+
} catch {
|
|
5066
|
+
return false;
|
|
5067
|
+
}
|
|
5068
|
+
}
|
|
5069
|
+
function deserializeWorkerError(error) {
|
|
5070
|
+
const result = new Error(error.message);
|
|
5071
|
+
result.name = error.name;
|
|
5072
|
+
if (error.stack) result.stack = error.stack;
|
|
5073
|
+
if (error.context !== void 0) Object.assign(result, { context: error.context });
|
|
5074
|
+
return result;
|
|
5075
|
+
}
|
|
5076
|
+
|
|
5006
5077
|
// src/centrifuge-session.ts
|
|
5007
5078
|
var CentrifugeSession = class {
|
|
5008
5079
|
constructor(sink) {
|
|
5009
5080
|
this.sink = sink;
|
|
5010
5081
|
}
|
|
5082
|
+
sink;
|
|
5011
5083
|
client = null;
|
|
5012
5084
|
subscriptions = /* @__PURE__ */ new Map();
|
|
5013
5085
|
transferable = false;
|
|
5086
|
+
tokenBridge = false;
|
|
5087
|
+
nextRequestId = 1;
|
|
5088
|
+
pendingTokenRequests = /* @__PURE__ */ new Map();
|
|
5014
5089
|
/** Dispatch an incoming Worker message to the matching operation.
|
|
5015
5090
|
* Unknown message types are ignored rather than thrown, so a future protocol
|
|
5016
5091
|
* extension adding a new variant cannot crash an older session. */
|
|
5017
5092
|
handle(message) {
|
|
5018
5093
|
switch (message.type) {
|
|
5019
|
-
case
|
|
5020
|
-
this.initialize(message.url, message.config, message.transferable === true);
|
|
5094
|
+
case CENTRIFUGE_INPUT_TYPE.INIT:
|
|
5095
|
+
this.initialize(message.url, message.config, message.transferable === true, message.tokenBridge === true);
|
|
5021
5096
|
return;
|
|
5022
|
-
case
|
|
5097
|
+
case CENTRIFUGE_INPUT_TYPE.SUBSCRIBE:
|
|
5023
5098
|
this.subscribe(message.topic);
|
|
5024
5099
|
return;
|
|
5025
|
-
case
|
|
5100
|
+
case CENTRIFUGE_INPUT_TYPE.UNSUBSCRIBE:
|
|
5026
5101
|
this.unsubscribe(message.topic);
|
|
5027
5102
|
return;
|
|
5028
|
-
case
|
|
5029
|
-
case
|
|
5103
|
+
case CENTRIFUGE_INPUT_TYPE.PUBLISH:
|
|
5104
|
+
case CENTRIFUGE_INPUT_TYPE.PUBLISH_BIN:
|
|
5030
5105
|
this.publish(message.topic, message.data, message.messageId, message.timestamp);
|
|
5031
5106
|
return;
|
|
5032
|
-
case
|
|
5107
|
+
case CENTRIFUGE_INPUT_TYPE.STOP:
|
|
5033
5108
|
this.stop();
|
|
5034
5109
|
return;
|
|
5110
|
+
case CENTRIFUGE_INPUT_TYPE.TOKEN_RESPONSE:
|
|
5111
|
+
this.resolveToken(message.requestId, message.token);
|
|
5112
|
+
return;
|
|
5113
|
+
case CENTRIFUGE_INPUT_TYPE.TOKEN_ERROR:
|
|
5114
|
+
this.rejectToken(message.requestId, deserializeWorkerError(message.error));
|
|
5115
|
+
return;
|
|
5035
5116
|
default:
|
|
5036
5117
|
return;
|
|
5037
5118
|
}
|
|
5038
5119
|
}
|
|
5039
5120
|
/** Create the Centrifuge client, wire up lifecycle listeners, and connect. */
|
|
5040
|
-
initialize(url, config, transferable) {
|
|
5121
|
+
initialize(url, config, transferable, tokenBridge) {
|
|
5041
5122
|
if (this.client) return;
|
|
5042
5123
|
this.transferable = transferable;
|
|
5043
|
-
|
|
5124
|
+
this.tokenBridge = tokenBridge;
|
|
5125
|
+
const clientOptions = tokenBridge ? {
|
|
5126
|
+
...config,
|
|
5127
|
+
// Route credential fetches back to the main thread, where the
|
|
5128
|
+
// application's credentialProvider lives (config must stay
|
|
5129
|
+
// structured-cloneable, so functions cannot cross the boundary).
|
|
5130
|
+
getToken: () => this.requestToken("token"),
|
|
5131
|
+
getChannelToken: (channel) => this.requestToken("channelToken", channel)
|
|
5132
|
+
} : config;
|
|
5133
|
+
const client = new Centrifuge(url, clientOptions);
|
|
5044
5134
|
this.client = client;
|
|
5045
5135
|
client.on("state", (context) => {
|
|
5046
|
-
this.post({ type:
|
|
5136
|
+
this.post({ type: CENTRIFUGE_OUTPUT_TYPE.STATUS, status: normalizeStatus(context.newState) });
|
|
5047
5137
|
});
|
|
5048
|
-
client.on("connected", () => this.post({ type:
|
|
5049
|
-
client.on("disconnected", () => this.post({ type:
|
|
5138
|
+
client.on("connected", () => this.post({ type: CENTRIFUGE_OUTPUT_TYPE.STATUS, status: WORKER_STATUS.CONNECTED }));
|
|
5139
|
+
client.on("disconnected", () => this.post({ type: CENTRIFUGE_OUTPUT_TYPE.STATUS, status: WORKER_STATUS.DISCONNECTED }));
|
|
5050
5140
|
client.on("error", (context) => this.postError(context));
|
|
5051
5141
|
client.on("publication", (context) => {
|
|
5052
5142
|
const topic = context.channel || getPayloadTopic(context.data);
|
|
@@ -5109,25 +5199,56 @@ var CentrifugeSession = class {
|
|
|
5109
5199
|
postPublication(topic, data) {
|
|
5110
5200
|
if (!topic) return;
|
|
5111
5201
|
if (this.transferable && data instanceof ArrayBuffer) {
|
|
5112
|
-
this.post({ type:
|
|
5202
|
+
this.post({ type: CENTRIFUGE_OUTPUT_TYPE.MESSAGE_BIN, topic, data }, [data]);
|
|
5113
5203
|
return;
|
|
5114
5204
|
}
|
|
5115
5205
|
const publication = parseDataBusPublication(data, topic);
|
|
5116
5206
|
if (!publication) return;
|
|
5117
5207
|
this.post({
|
|
5118
|
-
type:
|
|
5208
|
+
type: CENTRIFUGE_OUTPUT_TYPE.MESSAGE,
|
|
5119
5209
|
topic: publication.topic,
|
|
5120
5210
|
data: publication.data,
|
|
5121
|
-
...publication.messageId
|
|
5122
|
-
...publication.timestamp === void 0 ? {} : { timestamp: publication.timestamp }
|
|
5211
|
+
...publicationMetadata(publication.messageId, publication.timestamp)
|
|
5123
5212
|
});
|
|
5124
5213
|
}
|
|
5125
5214
|
/** Disconnect the client and clear all subscriptions. */
|
|
5126
5215
|
stop() {
|
|
5216
|
+
for (const [, pending] of this.pendingTokenRequests) {
|
|
5217
|
+
pending.reject(new Error("Centrifuge session stopped before the credential was resolved."));
|
|
5218
|
+
}
|
|
5219
|
+
this.pendingTokenRequests.clear();
|
|
5127
5220
|
this.client?.disconnect();
|
|
5128
5221
|
this.subscriptions.clear();
|
|
5129
5222
|
this.client = null;
|
|
5130
|
-
this.post({ type:
|
|
5223
|
+
this.post({ type: CENTRIFUGE_OUTPUT_TYPE.STATUS, status: WORKER_STATUS.DISCONNECTED });
|
|
5224
|
+
}
|
|
5225
|
+
/** Issue a credential request to the main thread and await the response.
|
|
5226
|
+
* Used as Centrifuge's `getToken` / `getChannelToken` when token bridging is
|
|
5227
|
+
* enabled; resolved or rejected by a matching TOKEN_RESPONSE / TOKEN_ERROR. */
|
|
5228
|
+
requestToken(kind, channel) {
|
|
5229
|
+
const requestId = this.nextRequestId;
|
|
5230
|
+
this.nextRequestId += 1;
|
|
5231
|
+
return new Promise((resolve, reject) => {
|
|
5232
|
+
this.pendingTokenRequests.set(requestId, { resolve, reject });
|
|
5233
|
+
this.post({
|
|
5234
|
+
type: CENTRIFUGE_OUTPUT_TYPE.TOKEN_REQUEST,
|
|
5235
|
+
requestId,
|
|
5236
|
+
kind,
|
|
5237
|
+
...channel === void 0 ? {} : { channel }
|
|
5238
|
+
});
|
|
5239
|
+
});
|
|
5240
|
+
}
|
|
5241
|
+
resolveToken(requestId, token) {
|
|
5242
|
+
const pending = this.pendingTokenRequests.get(requestId);
|
|
5243
|
+
if (!pending) return;
|
|
5244
|
+
this.pendingTokenRequests.delete(requestId);
|
|
5245
|
+
pending.resolve(token);
|
|
5246
|
+
}
|
|
5247
|
+
rejectToken(requestId, error) {
|
|
5248
|
+
const pending = this.pendingTokenRequests.get(requestId);
|
|
5249
|
+
if (!pending) return;
|
|
5250
|
+
this.pendingTokenRequests.delete(requestId);
|
|
5251
|
+
pending.reject(error);
|
|
5131
5252
|
}
|
|
5132
5253
|
/** Forward a message to the sink (the transport layer). */
|
|
5133
5254
|
post(message, transfer) {
|
|
@@ -5139,7 +5260,7 @@ var CentrifugeSession = class {
|
|
|
5139
5260
|
* Fatal errors are distinguished by the client eventually emitting
|
|
5140
5261
|
* `disconnected` without a subsequent `connected`. */
|
|
5141
5262
|
postError(error) {
|
|
5142
|
-
this.post({ type:
|
|
5263
|
+
this.post({ type: CENTRIFUGE_OUTPUT_TYPE.ERROR, error: serializeError(error) });
|
|
5143
5264
|
}
|
|
5144
5265
|
};
|
|
5145
5266
|
function getPayloadTopic(data) {
|
|
@@ -5150,24 +5271,10 @@ function getPayloadTopic(data) {
|
|
|
5150
5271
|
const topic = nested ?? payload.channel;
|
|
5151
5272
|
return typeof topic === "string" ? topic : "";
|
|
5152
5273
|
}
|
|
5153
|
-
var LIVE_STATES = /* @__PURE__ */ new Set([
|
|
5274
|
+
var LIVE_STATES = /* @__PURE__ */ new Set([WORKER_STATUS.CONNECTING, WORKER_STATUS.CONNECTED]);
|
|
5154
5275
|
function normalizeStatus(status) {
|
|
5155
5276
|
return LIVE_STATES.has(status) ? status : "disconnected";
|
|
5156
5277
|
}
|
|
5157
|
-
function serializeError(error) {
|
|
5158
|
-
if (error instanceof Error) {
|
|
5159
|
-
return {
|
|
5160
|
-
name: error.name,
|
|
5161
|
-
message: error.message,
|
|
5162
|
-
...error.stack ? { stack: error.stack } : {}
|
|
5163
|
-
};
|
|
5164
|
-
}
|
|
5165
|
-
return {
|
|
5166
|
-
name: "CentrifugeError",
|
|
5167
|
-
message: typeof error === "string" ? error : "Centrifuge worker operation failed.",
|
|
5168
|
-
...error === void 0 ? {} : { context: error }
|
|
5169
|
-
};
|
|
5170
|
-
}
|
|
5171
5278
|
|
|
5172
5279
|
// src/workers/centrifuge.worker.ts
|
|
5173
5280
|
var workerScope = self;
|