@q9labsai/chalk-client 5.1.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +125 -0
- package/dist/chat-files/types.d.ts +3 -0
- package/dist/{chunk-RJRSLXVT.js → chunk-BCO3AZUB.js} +647 -221
- package/dist/{chunk-K7PNW3KI.js → chunk-D2GXPX2P.js} +143 -13
- package/dist/{chunk-KHHULLBZ.js → chunk-DHGAKJXP.js} +1 -1
- package/dist/{chunk-3ZN7IXOZ.js → chunk-HO4745TX.js} +250 -2
- package/dist/client.d.ts +201 -0
- package/dist/connection/dependencies.d.ts +3 -0
- package/dist/connection/diagnostics.d.ts +3 -2
- package/dist/connection/lifecycle.d.ts +1 -0
- package/dist/connection/types.d.ts +2 -0
- package/dist/effect.js +62 -4
- package/dist/generated/http-api.d.ts +197 -0
- package/dist/generated/schemas.d.ts +366 -0
- package/dist/generated/sync.d.ts +74 -3
- package/dist/generated/whiteboard-v1.d.ts +71 -9
- package/dist/index.d.ts +1 -0
- package/dist/index.js +18 -14
- package/dist/public-invites/index.js +2 -2
- package/dist/space-client/reload-rejoin.d.ts +1 -1
- package/dist/space-client/types.d.ts +8 -1
- package/dist/sync/connect-diagnostics.d.ts +10 -0
- package/dist/sync/index.js +1 -1
- package/dist/sync/types.d.ts +1 -0
- package/dist/sync/v1-client.d.ts +2 -0
- package/dist/sync/v1-types.d.ts +4 -0
- package/dist/whiteboard/index.d.ts +2 -5
- package/dist/whiteboard/types.d.ts +26 -3
- package/dist/whiteboard/v1-client.d.ts +3 -1
- package/dist/whiteboard/v1-codec.d.ts +5 -1
- package/dist/whiteboard/v1-multipart.d.ts +1 -1
- package/dist/whiteboard/view-bounds.d.ts +5 -0
- package/dist/whiteboard/view-versions.d.ts +9 -0
- package/package.json +1 -1
|
@@ -120,7 +120,7 @@ var BrowserSyncSocket = class {
|
|
|
120
120
|
this.#socket = socket;
|
|
121
121
|
this.#socket.addEventListener("open", () => this.onopen?.());
|
|
122
122
|
this.#socket.addEventListener("message", (event) => this.onmessage?.({ data: event.data }));
|
|
123
|
-
this.#socket.addEventListener("close", (event) => this.onclose?.({ code: event.code }));
|
|
123
|
+
this.#socket.addEventListener("close", (event) => this.onclose?.({ code: event.code, reason: event.reason }));
|
|
124
124
|
this.#socket.addEventListener("error", () => this.onerror?.());
|
|
125
125
|
}
|
|
126
126
|
send(data) {
|
|
@@ -176,7 +176,7 @@ var ReactNativeSyncSocket = class {
|
|
|
176
176
|
this.#socket = socket;
|
|
177
177
|
this.#socket.onopen = () => this.onopen?.();
|
|
178
178
|
this.#socket.onmessage = (event) => this.onmessage?.({ data: event.data });
|
|
179
|
-
this.#socket.onclose = (event) => this.onclose?.({ code: typeof event.code === "number" ? event.code : 1006 });
|
|
179
|
+
this.#socket.onclose = (event) => this.onclose?.({ code: typeof event.code === "number" ? event.code : 1006, reason: typeof event.reason === "string" ? event.reason : void 0 });
|
|
180
180
|
this.#socket.onerror = () => this.onerror?.();
|
|
181
181
|
}
|
|
182
182
|
send(data) {
|
|
@@ -196,7 +196,7 @@ var BrowserFallbackSyncSocket = class {
|
|
|
196
196
|
this.#socket = socket;
|
|
197
197
|
this.#socket.addEventListener("open", () => this.onopen?.());
|
|
198
198
|
this.#socket.addEventListener("message", (event) => this.onmessage?.({ data: event.data }));
|
|
199
|
-
this.#socket.addEventListener("close", (event) => this.onclose?.({ code: event.code }));
|
|
199
|
+
this.#socket.addEventListener("close", (event) => this.onclose?.({ code: event.code, reason: event.reason }));
|
|
200
200
|
this.#socket.addEventListener("error", () => this.onerror?.());
|
|
201
201
|
}
|
|
202
202
|
send(data) {
|
|
@@ -217,6 +217,40 @@ function unsubscribe(subscription) {
|
|
|
217
217
|
}
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
+
// src/sync/connect-diagnostics.ts
|
|
221
|
+
var SAFE_REASONS = /* @__PURE__ */ new Set([
|
|
222
|
+
"hello timeout",
|
|
223
|
+
"invalid token",
|
|
224
|
+
"policy violation",
|
|
225
|
+
"dependency unavailable",
|
|
226
|
+
"server draining",
|
|
227
|
+
"heartbeat timeout",
|
|
228
|
+
"normal",
|
|
229
|
+
"transport error",
|
|
230
|
+
"authentication failed",
|
|
231
|
+
"delivery recovery required",
|
|
232
|
+
"space action delivery recovery required",
|
|
233
|
+
"text frames only",
|
|
234
|
+
"unsupported protocol",
|
|
235
|
+
"invalid frame",
|
|
236
|
+
"WebSocket dial timeout",
|
|
237
|
+
"lifecycle transport deadline",
|
|
238
|
+
"lifecycle unavailable",
|
|
239
|
+
"invalid_frame",
|
|
240
|
+
"state_digest_mismatch",
|
|
241
|
+
"state_digest_recovery_failed",
|
|
242
|
+
"terminal event acknowledged",
|
|
243
|
+
"client stopped",
|
|
244
|
+
"participant inactive",
|
|
245
|
+
"terminal recovery"
|
|
246
|
+
]);
|
|
247
|
+
function safeSyncCloseReason(reason) {
|
|
248
|
+
return reason ? SAFE_REASONS.has(reason) ? reason : "redacted" : null;
|
|
249
|
+
}
|
|
250
|
+
function formatSyncConnectDiagnostic(diagnostic) {
|
|
251
|
+
return `[${diagnostic.stage}; open=${diagnostic.opened ? 1 : 0}; close=${diagnostic.closeCode ?? "none"}; reason=${safeSyncCloseReason(diagnostic.closeReason ?? void 0) ?? "none"}; ${Math.round(diagnostic.durationMs)}ms]`;
|
|
252
|
+
}
|
|
253
|
+
|
|
220
254
|
// src/sync/v1-health.ts
|
|
221
255
|
var SYNC_HEALTH_BUDGET = {
|
|
222
256
|
probeIntervalMs: 500,
|
|
@@ -266,7 +300,14 @@ var SyncProtocolMetadata = {
|
|
|
266
300
|
field: "protocol",
|
|
267
301
|
value: 1,
|
|
268
302
|
transport: "websocket-json-text",
|
|
269
|
-
route: "/v1/sync"
|
|
303
|
+
route: "/v1/sync",
|
|
304
|
+
entryGeneration: {
|
|
305
|
+
queryParameter: "entry_generation",
|
|
306
|
+
newEntry: "new",
|
|
307
|
+
resume: "previous welcome entry_generation",
|
|
308
|
+
confirmation: "monotonic compare-and-set",
|
|
309
|
+
scope: "participant"
|
|
310
|
+
}
|
|
270
311
|
},
|
|
271
312
|
directions: {
|
|
272
313
|
clientToServer: "client-to-server",
|
|
@@ -290,7 +331,7 @@ var SyncProtocolMetadata = {
|
|
|
290
331
|
},
|
|
291
332
|
{
|
|
292
333
|
id: "live",
|
|
293
|
-
accepts: ["command", "live_target", "directed_request", "delivery_ack", "request_ack", "reaction_send", "chat_send", "chat_page_request", "chat_read_set", "chat_reaction_set", "ping"],
|
|
334
|
+
accepts: ["entered", "command", "live_target", "directed_request", "delivery_ack", "request_ack", "reaction_send", "chat_send", "chat_page_request", "chat_read_set", "chat_reaction_set", "ping"],
|
|
294
335
|
heartbeat: {
|
|
295
336
|
intervalMs: 2e4,
|
|
296
337
|
missedDeadlinesBeforeClose: 2
|
|
@@ -570,7 +611,7 @@ var SyncProtocolMetadata = {
|
|
|
570
611
|
{
|
|
571
612
|
code: 1008,
|
|
572
613
|
connection: "closed",
|
|
573
|
-
reasons: ["invalid token", "policy violation"]
|
|
614
|
+
reasons: ["invalid token", "policy violation", "entry timeout"]
|
|
574
615
|
},
|
|
575
616
|
{
|
|
576
617
|
code: 1009,
|
|
@@ -742,6 +783,8 @@ function strictClientFrame(value) {
|
|
|
742
783
|
return exactObject(value, ["type", "stream", "revision", "state_digest"]);
|
|
743
784
|
case "recovery_ack":
|
|
744
785
|
return exactObject(value, ["type", "recovery_id", "revision", "state_digest"]);
|
|
786
|
+
case "entered":
|
|
787
|
+
return exactObject(value, ["type"]);
|
|
745
788
|
case "ping":
|
|
746
789
|
return exactObject(value, ["type"]);
|
|
747
790
|
default:
|
|
@@ -824,7 +867,8 @@ function strictWelcome(value) {
|
|
|
824
867
|
const base = ["type", "protocol", "participant_id", "participant_generation", "recovery_id", "head", "mode"];
|
|
825
868
|
const extension = Array.isArray(value.extensions) && value.extensions.length === 1 ? value.extensions[0] : void 0;
|
|
826
869
|
const extensionValid = isObject(extension) && ["collaboration_v1", "collaboration_v2"].includes(String(extension.name)) && exactObject(extension, ["name", "capabilities", "participant_capabilities", "chat_head_sequence", "retained_floor_sequence", "read_receipts"]) && Array.isArray(extension.read_receipts);
|
|
827
|
-
|
|
870
|
+
if (Object.hasOwn(value, "entry_confirmation") && value.entry_confirmation !== true) return false;
|
|
871
|
+
const fields = [...base, ...extensionValid ? ["extensions"] : [], ...Object.hasOwn(value, "entry_confirmation") ? ["entry_confirmation"] : [], ...Object.hasOwn(value, "entry_generation") ? ["entry_generation"] : []];
|
|
828
872
|
if (!strictCursor(value.head)) return false;
|
|
829
873
|
if (value.mode === "snapshot") return exactObjectWithCorrelation(value, [...fields, "snapshot"]) && strictSnapshot(value.snapshot);
|
|
830
874
|
if (value.mode === "terminal") return exactObjectWithCorrelation(value, [...fields, "reason"]);
|
|
@@ -883,6 +927,8 @@ function strictServerFrame(value) {
|
|
|
883
927
|
return exactObjectWithCorrelation(value, ["type", "command_id", "code"]);
|
|
884
928
|
case "error":
|
|
885
929
|
return exactObjectWithCorrelation(value, ["type", "code", "detail"]);
|
|
930
|
+
case "entered_ack":
|
|
931
|
+
return exactObjectWithCorrelation(value, ["type"]);
|
|
886
932
|
case "pong":
|
|
887
933
|
return exactObjectWithCorrelation(value, ["type"]);
|
|
888
934
|
default:
|
|
@@ -1423,7 +1469,16 @@ var CollaborationWelcomeExtensionSchema = Schema.Struct({
|
|
|
1423
1469
|
retained_floor_sequence: Schema.NullOr(UnsignedDecimalSchema),
|
|
1424
1470
|
read_receipts: Schema.Array(ChatReadReceiptSchema).check(Schema.isMaxLength(500))
|
|
1425
1471
|
}).check(exactKeys(["name", "capabilities", "participant_capabilities", "chat_head_sequence", "retained_floor_sequence", "read_receipts"]));
|
|
1426
|
-
var WelcomeBase = {
|
|
1472
|
+
var WelcomeBase = {
|
|
1473
|
+
type: Schema.Literal("welcome"),
|
|
1474
|
+
protocol: Schema.Literal(1),
|
|
1475
|
+
participant_id: UuidSchema,
|
|
1476
|
+
participant_generation: PositiveIntegerSchema,
|
|
1477
|
+
recovery_id: UuidSchema,
|
|
1478
|
+
head: ControlCursorSchema,
|
|
1479
|
+
entry_confirmation: Schema.optionalKey(Schema.Literal(true)),
|
|
1480
|
+
entry_generation: Schema.optionalKey(PositiveIntegerSchema.check(Schema.isLessThanOrEqualTo(9007199254740991)))
|
|
1481
|
+
};
|
|
1427
1482
|
var ExtendedWelcomeBase = { ...WelcomeBase, extensions: Schema.Tuple([CollaborationWelcomeExtensionSchema]) };
|
|
1428
1483
|
var WelcomeSnapshotFrameSchema = Schema.Struct({ ...WelcomeBase, mode: Schema.Literal("snapshot"), snapshot: SnapshotSchema, ...ServerCorrelationFields }).check(boundedServerFrame(SyncProtocolLimits.snapshotEncodedBytes));
|
|
1429
1484
|
var WelcomeReplayFrameSchema = Schema.Struct({ ...WelcomeBase, mode: Schema.Literal("replay"), ...ServerCorrelationFields });
|
|
@@ -1599,6 +1654,8 @@ var RejectedChatReadResultFrameSchema = Schema.Struct({ type: Schema.Literal("ch
|
|
|
1599
1654
|
var ChatReadResultFrameSchema = Schema.Union([AcceptedChatReadResultFrameSchema, RejectedChatReadResultFrameSchema]);
|
|
1600
1655
|
var RetryableErrorFrameSchema = Schema.Struct({ type: Schema.Literal("retryable_error"), command_id: CommandIdSchema, code: RetryableErrorCodeSchema, ...ServerCorrelationFields });
|
|
1601
1656
|
var ErrorFrameSchema = Schema.Struct({ type: Schema.Literal("error"), code: ProtocolErrorCodeSchema, detail: boundedUtf8String(1024), ...ServerCorrelationFields });
|
|
1657
|
+
var EnteredFrameSchema = Schema.Struct({ type: Schema.Literal("entered") });
|
|
1658
|
+
var EnteredAckFrameSchema = Schema.Struct({ type: Schema.Literal("entered_ack"), ...ServerCorrelationFields });
|
|
1602
1659
|
var PingFrameSchema = Schema.Struct({ type: Schema.Literal("ping") });
|
|
1603
1660
|
var PongFrameSchema = Schema.Struct({ type: Schema.Literal("pong"), ...ServerCorrelationFields });
|
|
1604
1661
|
var SyncV1ClientFrameSchema = Schema.Unknown.check(Schema.makeFilter((frame) => strictClientFrame(frame) ? void 0 : { path: [], issue: "must not contain unknown or missing fields" })).pipe(
|
|
@@ -1632,6 +1689,7 @@ var SyncV1ClientFrameSchema = Schema.Unknown.check(Schema.makeFilter((frame) =>
|
|
|
1632
1689
|
ChatReactionSetFrameSchema,
|
|
1633
1690
|
DeliveryAckFrameSchema,
|
|
1634
1691
|
RecoveryAckFrameSchema,
|
|
1692
|
+
EnteredFrameSchema,
|
|
1635
1693
|
PingFrameSchema
|
|
1636
1694
|
])
|
|
1637
1695
|
)
|
|
@@ -1663,6 +1721,7 @@ var SyncV1ServerFrameSchema = Schema.Unknown.check(Schema.makeFilter((frame) =>
|
|
|
1663
1721
|
ChatReactionResultFrameSchema,
|
|
1664
1722
|
RetryableErrorFrameSchema,
|
|
1665
1723
|
ErrorFrameSchema,
|
|
1724
|
+
EnteredAckFrameSchema,
|
|
1666
1725
|
PongFrameSchema
|
|
1667
1726
|
])
|
|
1668
1727
|
)
|
|
@@ -2939,6 +2998,9 @@ var V1SyncClient = class {
|
|
|
2939
2998
|
#snapshotRevision = null;
|
|
2940
2999
|
#controlEvents = /* @__PURE__ */ new Map();
|
|
2941
3000
|
#liveTargets;
|
|
3001
|
+
#entryPending = false;
|
|
3002
|
+
// Older Sync rejects new hello fields, so entry confirmation is requested on the URL and granted in welcome.
|
|
3003
|
+
#entryNegotiated = false;
|
|
2942
3004
|
#requests = /* @__PURE__ */ new Map();
|
|
2943
3005
|
#mediaEventEvidence = /* @__PURE__ */ new Map();
|
|
2944
3006
|
#presenceEventEvidence = /* @__PURE__ */ new Map();
|
|
@@ -2949,6 +3011,7 @@ var V1SyncClient = class {
|
|
|
2949
3011
|
#presence = null;
|
|
2950
3012
|
#participantId = null;
|
|
2951
3013
|
#participantGeneration = null;
|
|
3014
|
+
#entryGeneration = null;
|
|
2952
3015
|
#recovery = null;
|
|
2953
3016
|
#snapshotRecoveryRequested = false;
|
|
2954
3017
|
#lastDigestRecoveryAt = null;
|
|
@@ -2958,6 +3021,12 @@ var V1SyncClient = class {
|
|
|
2958
3021
|
#reconnectTimer;
|
|
2959
3022
|
#cancelDial;
|
|
2960
3023
|
#dialTimeoutCount = 0;
|
|
3024
|
+
#connectStartedAt = null;
|
|
3025
|
+
#opened = false;
|
|
3026
|
+
#connectFailure;
|
|
3027
|
+
#connectDiagnostic() {
|
|
3028
|
+
return { stage: this.#opened ? "hello" : "upgrade", opened: this.#opened, closeCode: null, closeReason: null, durationMs: Math.max(0, this.#clock().now() - (this.#connectStartedAt ?? this.#clock().now())) };
|
|
3029
|
+
}
|
|
2961
3030
|
#reconnectAttempt = 0;
|
|
2962
3031
|
#heartbeatTimer;
|
|
2963
3032
|
#missedHeartbeats = 0;
|
|
@@ -3036,6 +3105,8 @@ var V1SyncClient = class {
|
|
|
3036
3105
|
}
|
|
3037
3106
|
stop() {
|
|
3038
3107
|
this.#started = false;
|
|
3108
|
+
this.#entryPending = false;
|
|
3109
|
+
this.#entryGeneration = null;
|
|
3039
3110
|
this.#startupGeneration += 1;
|
|
3040
3111
|
this.#unsubscribeLifecycle?.();
|
|
3041
3112
|
this.#unsubscribeLifecycle = void 0;
|
|
@@ -3055,11 +3126,24 @@ var V1SyncClient = class {
|
|
|
3055
3126
|
this.#liveTargets.resetLocalMedia();
|
|
3056
3127
|
this.#emit();
|
|
3057
3128
|
}
|
|
3129
|
+
/** Announces completed startup; transport recovery resends until acknowledged. */
|
|
3130
|
+
async confirmEntered() {
|
|
3131
|
+
this.#requireLive();
|
|
3132
|
+
this.#entryPending = true;
|
|
3133
|
+
if (!this.#entryNegotiated) return;
|
|
3134
|
+
this.#send({ type: "entered" });
|
|
3135
|
+
}
|
|
3058
3136
|
getSnapshot() {
|
|
3059
3137
|
const pendingCommands = this.#commandScheduler.pendingCommands;
|
|
3060
3138
|
const optimisticControl = this.#control && this.#participantId ? optimisticV1Control(this.#control, this.#participantId, pendingCommands) : this.#control;
|
|
3061
3139
|
return {
|
|
3062
|
-
connection: {
|
|
3140
|
+
connection: {
|
|
3141
|
+
...this.#phase,
|
|
3142
|
+
...this.#connectStartedAt !== null && (this.#phase.phase === "connecting" || this.#phase.phase === "recovering") ? { connectAttempt: this.#connectDiagnostic() } : {},
|
|
3143
|
+
...this.#connectFailure && (this.#phase.phase === "connecting" || this.#phase.phase === "recovering") ? { connectFailure: this.#connectFailure } : {},
|
|
3144
|
+
...this.#phase.phase === "live" ? { noticeUnresponsive: this.#health.health === "recovering", health: this.#health.health } : {},
|
|
3145
|
+
...this.#dialTimeoutCount ? { dialTimeoutCount: this.#dialTimeoutCount } : {}
|
|
3146
|
+
},
|
|
3063
3147
|
participantId: this.#participantId,
|
|
3064
3148
|
participantGeneration: this.#participantGeneration,
|
|
3065
3149
|
control: this.#control,
|
|
@@ -3199,8 +3283,19 @@ var V1SyncClient = class {
|
|
|
3199
3283
|
#connect() {
|
|
3200
3284
|
if (!this.#started || !this.#transportAvailable || this.#socket || this.#phase.phase === "terminal") return;
|
|
3201
3285
|
this.#phase = { phase: "connecting" };
|
|
3286
|
+
this.#connectStartedAt = this.#clock().now();
|
|
3287
|
+
this.#opened = false;
|
|
3288
|
+
this.#connectFailure = void 0;
|
|
3202
3289
|
this.#emit();
|
|
3203
|
-
|
|
3290
|
+
this.#entryNegotiated = false;
|
|
3291
|
+
let socket;
|
|
3292
|
+
try {
|
|
3293
|
+
socket = this.#options.webSocket.connect(entryUrl(this.#options.url, this.#entryGeneration, this.#options.entryConfirmation === true));
|
|
3294
|
+
} catch {
|
|
3295
|
+
this.#connectFailure = this.#connectDiagnostic();
|
|
3296
|
+
this.#emit();
|
|
3297
|
+
throw new V1SyncError("Sync WebSocket could not be created", "sync_hello_timeout");
|
|
3298
|
+
}
|
|
3204
3299
|
const connectionGeneration = ++this.#connectionGeneration;
|
|
3205
3300
|
this.#socket = socket;
|
|
3206
3301
|
this.#cancelDial = scheduleSyncDialDeadline(
|
|
@@ -3208,6 +3303,7 @@ var V1SyncClient = class {
|
|
|
3208
3303
|
() => {
|
|
3209
3304
|
this.#cancelDial = void 0;
|
|
3210
3305
|
this.#dialTimeoutCount += 1;
|
|
3306
|
+
this.#connectFailure = this.#connectDiagnostic();
|
|
3211
3307
|
this.#recover("WebSocket dial timeout");
|
|
3212
3308
|
},
|
|
3213
3309
|
this.#options.dialTimeoutMs
|
|
@@ -3215,18 +3311,36 @@ var V1SyncClient = class {
|
|
|
3215
3311
|
socket.onopen = () => {
|
|
3216
3312
|
if (socket !== this.#socket) return;
|
|
3217
3313
|
this.#clearDial();
|
|
3314
|
+
this.#opened = true;
|
|
3315
|
+
this.#connectFailure = void 0;
|
|
3218
3316
|
void this.#authenticate(socket);
|
|
3219
3317
|
};
|
|
3220
3318
|
socket.onmessage = (event) => {
|
|
3221
3319
|
this.#inbound = this.#inbound.then(() => this.#receive(socket, event.data));
|
|
3222
3320
|
};
|
|
3223
|
-
socket.onclose = () => {
|
|
3321
|
+
socket.onclose = (event) => {
|
|
3322
|
+
if (socket === this.#socket && (this.#phase.phase === "connecting" || this.#phase.phase === "recovering")) {
|
|
3323
|
+
this.#connectFailure = { ...this.#connectDiagnostic(), closeCode: event.code, closeReason: safeSyncCloseReason(event.reason) };
|
|
3324
|
+
this.#emit();
|
|
3325
|
+
}
|
|
3224
3326
|
this.#clock().setTimeout(() => {
|
|
3225
3327
|
if (connectionGeneration !== this.#connectionGeneration) return;
|
|
3226
|
-
this.#inbound = this.#inbound.then(() =>
|
|
3328
|
+
this.#inbound = this.#inbound.then(() => {
|
|
3329
|
+
if (socket === this.#socket && event.code === 1008 && (event.reason === "" || event.reason === "invalid token" || event.reason === "policy violation" || event.reason === "entry timeout")) {
|
|
3330
|
+
this.#phase = { phase: "terminal", terminalReason: event.reason === "entry timeout" ? "entry_timeout" : "access_rejected" };
|
|
3331
|
+
this.#emit();
|
|
3332
|
+
}
|
|
3333
|
+
this.#disconnected(socket);
|
|
3334
|
+
});
|
|
3227
3335
|
}, 0);
|
|
3228
3336
|
};
|
|
3229
|
-
socket.onerror = () =>
|
|
3337
|
+
socket.onerror = () => {
|
|
3338
|
+
if (socket === this.#socket && (this.#phase.phase === "connecting" || this.#phase.phase === "recovering")) {
|
|
3339
|
+
this.#connectFailure = this.#connectDiagnostic();
|
|
3340
|
+
this.#emit();
|
|
3341
|
+
}
|
|
3342
|
+
socket.close(CLIENT_RESTART_CLOSE_CODE, "transport error");
|
|
3343
|
+
};
|
|
3230
3344
|
}
|
|
3231
3345
|
async #authenticate(socket) {
|
|
3232
3346
|
try {
|
|
@@ -3355,6 +3469,10 @@ var V1SyncClient = class {
|
|
|
3355
3469
|
return;
|
|
3356
3470
|
case "error":
|
|
3357
3471
|
throw new V1ReplicaError(frame.code);
|
|
3472
|
+
case "entered_ack":
|
|
3473
|
+
this.#requireLive();
|
|
3474
|
+
this.#entryPending = false;
|
|
3475
|
+
return;
|
|
3358
3476
|
case "pong": {
|
|
3359
3477
|
this.#requireLive();
|
|
3360
3478
|
this.#missedHeartbeats = 0;
|
|
@@ -3368,6 +3486,8 @@ var V1SyncClient = class {
|
|
|
3368
3486
|
async #welcome(frame) {
|
|
3369
3487
|
if (this.#phase.phase !== "recovering" || this.#recovery) throw new V1ReplicaError("unexpected welcome");
|
|
3370
3488
|
this.#collaborationState.acceptWelcome(frame);
|
|
3489
|
+
this.#entryNegotiated = frame.entry_confirmation === true;
|
|
3490
|
+
this.#entryGeneration = frame.entry_generation ?? this.#entryGeneration;
|
|
3371
3491
|
this.#participantId = frame.participant_id;
|
|
3372
3492
|
this.#participantGeneration = frame.participant_generation;
|
|
3373
3493
|
this.#updateLocalMediaStates();
|
|
@@ -3486,8 +3606,11 @@ var V1SyncClient = class {
|
|
|
3486
3606
|
if (!this.#recovery?.controlComplete || !this.#media || !this.#presence) return;
|
|
3487
3607
|
this.#recovery = null;
|
|
3488
3608
|
this.#phase = { phase: "live" };
|
|
3609
|
+
this.#connectStartedAt = null;
|
|
3610
|
+
this.#connectFailure = void 0;
|
|
3489
3611
|
this.#reconnectAttempt = 0;
|
|
3490
3612
|
this.#missedHeartbeats = 0;
|
|
3613
|
+
if (this.#entryPending && this.#entryNegotiated) this.#send({ type: "entered" });
|
|
3491
3614
|
this.#commandScheduler.enterLive();
|
|
3492
3615
|
this.#liveTargets.enterLive();
|
|
3493
3616
|
this.#startHeartbeat();
|
|
@@ -3746,6 +3869,12 @@ function copyPublication(publication) {
|
|
|
3746
3869
|
function validMediaPublication(publication) {
|
|
3747
3870
|
return typeof publication.participantId === "string" && publication.participantId.length > 0 && (publication.source === "microphone" || publication.source === "camera" || publication.source === "screen" || publication.source === "screen_audio") && typeof publication.enabled === "boolean" && (publication.publicationId === null || typeof publication.publicationId === "string") && (!publication.enabled || publication.publicationId !== null);
|
|
3748
3871
|
}
|
|
3872
|
+
function entryUrl(value, generation, confirmation) {
|
|
3873
|
+
const url = new URL(value);
|
|
3874
|
+
url.searchParams.set("entry_generation", generation === null ? "new" : String(generation));
|
|
3875
|
+
if (confirmation) url.searchParams.set("entry_confirmation", "1");
|
|
3876
|
+
return url.toString();
|
|
3877
|
+
}
|
|
3749
3878
|
function assertV1Url(value) {
|
|
3750
3879
|
const url = new URL(value);
|
|
3751
3880
|
if (url.pathname !== "/v1/sync") throw new V1SyncError("SyncEngine v1 websocket URL must use /v1/sync", "invalid_url");
|
|
@@ -3893,6 +4022,7 @@ function createV1SyncClient(options) {
|
|
|
3893
4022
|
}
|
|
3894
4023
|
|
|
3895
4024
|
export {
|
|
4025
|
+
formatSyncConnectDiagnostic,
|
|
3896
4026
|
UuidSchema,
|
|
3897
4027
|
ReactionValues,
|
|
3898
4028
|
ReactionSchema,
|