@rebasepro/server 0.9.1-canary.e2fc7b6 → 0.9.1-canary.e3f810f
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.es.js
CHANGED
|
@@ -3305,7 +3305,7 @@ var BackendCollectionRegistry = class extends CollectionRegistry {
|
|
|
3305
3305
|
//#endregion
|
|
3306
3306
|
//#region src/collections/loader.ts
|
|
3307
3307
|
function isCollectionFile(file) {
|
|
3308
|
-
return (file.endsWith(".ts") || file.endsWith(".js")) && !file.includes(".test.") && !file.endsWith(".d.ts") && file !== "index.ts" && file !== "index.js";
|
|
3308
|
+
return (file.endsWith(".ts") || file.endsWith(".js")) && !file.startsWith(".") && !file.includes(".test.") && !file.endsWith(".d.ts") && file !== "index.ts" && file !== "index.js";
|
|
3309
3309
|
}
|
|
3310
3310
|
async function importModule(filePath) {
|
|
3311
3311
|
return await import(pathToFileURL(filePath).href);
|
|
@@ -14412,7 +14412,7 @@ async function initializeStorage(storageConfig, isProduction) {
|
|
|
14412
14412
|
//#region src/init/docs.ts
|
|
14413
14413
|
async function mountOpenApiDocs(app, basePath, enableSwagger, activeCollections, requireAuth) {
|
|
14414
14414
|
if (enableSwagger === false || activeCollections.length === 0) return;
|
|
14415
|
-
const { generateOpenApiSpec } = await import("./openapi-generator-
|
|
14415
|
+
const { generateOpenApiSpec } = await import("./openapi-generator-DqSIwNLV.js");
|
|
14416
14416
|
app.get(`${basePath}/docs`, (c) => {
|
|
14417
14417
|
const spec = generateOpenApiSpec(activeCollections, {
|
|
14418
14418
|
basePath,
|
|
@@ -15933,9 +15933,11 @@ var ClientStorageSourceRegistry = class ClientStorageSourceRegistry {
|
|
|
15933
15933
|
function extractMessageError(message) {
|
|
15934
15934
|
const payload = message.payload;
|
|
15935
15935
|
const errPayload = payload?.error;
|
|
15936
|
+
const errorMessage = typeof errPayload === "object" ? errPayload.message : payload?.message || (typeof errPayload === "string" ? errPayload : void 0) || message.error || "Unknown error";
|
|
15937
|
+
const errorCode = typeof errPayload === "object" ? errPayload.code : payload?.code;
|
|
15936
15938
|
return {
|
|
15937
|
-
errorMessage: typeof
|
|
15938
|
-
errorCode
|
|
15939
|
+
errorMessage: typeof errorMessage === "string" ? errorMessage : errorMessage == null ? "Unknown error" : JSON.stringify(errorMessage),
|
|
15940
|
+
errorCode
|
|
15939
15941
|
};
|
|
15940
15942
|
}
|
|
15941
15943
|
/**
|
|
@@ -15971,6 +15973,7 @@ var RebaseWebSocketClient = class {
|
|
|
15971
15973
|
isConnected = false;
|
|
15972
15974
|
messageQueue = [];
|
|
15973
15975
|
requestTimeoutMs = 3e4;
|
|
15976
|
+
subscriptionTimeoutMs = 3e4;
|
|
15974
15977
|
reconnectTimeout = null;
|
|
15975
15978
|
isAuthenticated = false;
|
|
15976
15979
|
authPromise = null;
|
|
@@ -16076,6 +16079,7 @@ var RebaseWebSocketClient = class {
|
|
|
16076
16079
|
this.emit(wasReconnect ? "reconnect" : "connect");
|
|
16077
16080
|
this.processMessageQueue();
|
|
16078
16081
|
if (wasReconnect) this.resubscribeAll();
|
|
16082
|
+
this.armPendingSubscribeWatchdogs();
|
|
16079
16083
|
};
|
|
16080
16084
|
this.ws.onmessage = (event) => {
|
|
16081
16085
|
try {
|
|
@@ -16090,6 +16094,7 @@ var RebaseWebSocketClient = class {
|
|
|
16090
16094
|
this.isConnected = false;
|
|
16091
16095
|
this.isAuthenticated = false;
|
|
16092
16096
|
this.authPromise = null;
|
|
16097
|
+
this.suspendSubscribeWatchdogs();
|
|
16093
16098
|
this.emit("disconnect");
|
|
16094
16099
|
for (const [reqId, request] of this.pendingRequests.entries()) {
|
|
16095
16100
|
if (reqId.startsWith("auth_")) request.reject(/* @__PURE__ */ new Error("Connection closed during authentication"));
|
|
@@ -16121,6 +16126,7 @@ var RebaseWebSocketClient = class {
|
|
|
16121
16126
|
attemptReconnect() {
|
|
16122
16127
|
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
16123
16128
|
console.error("Max reconnection attempts reached");
|
|
16129
|
+
this.failAllPendingSubscriptions(new RebaseApiError("Connection lost", { code: "CONNECTION_LOST" }));
|
|
16124
16130
|
return;
|
|
16125
16131
|
}
|
|
16126
16132
|
this.reconnectAttempts++;
|
|
@@ -16175,29 +16181,18 @@ var RebaseWebSocketClient = class {
|
|
|
16175
16181
|
subscription.backendSubscriptionId = newBackendId;
|
|
16176
16182
|
backendKeyMap.delete(oldBackendId);
|
|
16177
16183
|
backendKeyMap.set(newBackendId, subscriptionKey);
|
|
16178
|
-
this.
|
|
16179
|
-
|
|
16180
|
-
|
|
16181
|
-
...subscription.props,
|
|
16182
|
-
subscriptionId: newBackendId
|
|
16183
|
-
}
|
|
16184
|
-
}).catch((error) => {
|
|
16185
|
-
console.error(`[WS] Failed to re-subscribe ${idPrefix} after auth refresh:`, subscriptionKey, error);
|
|
16186
|
-
subscription.callbacks.forEach((callback) => {
|
|
16187
|
-
if (callback.onError) callback.onError(error);
|
|
16188
|
-
});
|
|
16189
|
-
});
|
|
16190
|
-
} else {
|
|
16191
|
-
const { errorMessage, errorCode } = extractMessageError(message);
|
|
16192
|
-
const error = new RebaseApiError(errorMessage, { code: errorCode });
|
|
16193
|
-
subscription.callbacks.forEach((callback) => {
|
|
16194
|
-
if (callback.onError) callback.onError(error);
|
|
16195
|
-
});
|
|
16184
|
+
if (messageType === "subscribe_collection") this.sendCollectionSubscribe(subscriptionKey);
|
|
16185
|
+
else this.sendEntitySubscribe(subscriptionKey);
|
|
16186
|
+
return;
|
|
16196
16187
|
}
|
|
16188
|
+
const { errorMessage, errorCode } = extractMessageError(message);
|
|
16189
|
+
const error = new RebaseApiError(errorMessage, { code: errorCode });
|
|
16190
|
+
if (messageType === "subscribe_collection") this.failCollectionSubscription(subscriptionKey, error);
|
|
16191
|
+
else this.failEntitySubscription(subscriptionKey, error);
|
|
16197
16192
|
}).catch((err) => {
|
|
16198
|
-
|
|
16199
|
-
|
|
16200
|
-
|
|
16193
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
16194
|
+
if (messageType === "subscribe_collection") this.failCollectionSubscription(subscriptionKey, error);
|
|
16195
|
+
else this.failEntitySubscription(subscriptionKey, error);
|
|
16201
16196
|
});
|
|
16202
16197
|
}
|
|
16203
16198
|
handleWebSocketMessage(message) {
|
|
@@ -16238,6 +16233,9 @@ var RebaseWebSocketClient = class {
|
|
|
16238
16233
|
collectionSub.latestData = rows;
|
|
16239
16234
|
collectionSub.lastUpdated = Date.now();
|
|
16240
16235
|
collectionSub.isInitialDataReceived = true;
|
|
16236
|
+
if (collectionSub.subscribeTimeout) clearTimeout(collectionSub.subscribeTimeout);
|
|
16237
|
+
collectionSub.subscribeTimeout = void 0;
|
|
16238
|
+
collectionSub.subscribeInFlight = false;
|
|
16241
16239
|
collectionSub.callbacks.forEach((callback) => {
|
|
16242
16240
|
try {
|
|
16243
16241
|
callback.onUpdate(rows);
|
|
@@ -16293,6 +16291,9 @@ var RebaseWebSocketClient = class {
|
|
|
16293
16291
|
entitySub.latestData = row;
|
|
16294
16292
|
entitySub.lastUpdated = Date.now();
|
|
16295
16293
|
entitySub.isInitialDataReceived = true;
|
|
16294
|
+
if (entitySub.subscribeTimeout) clearTimeout(entitySub.subscribeTimeout);
|
|
16295
|
+
entitySub.subscribeTimeout = void 0;
|
|
16296
|
+
entitySub.subscribeInFlight = false;
|
|
16296
16297
|
entitySub.callbacks.forEach((callback) => {
|
|
16297
16298
|
try {
|
|
16298
16299
|
callback.onUpdate(row);
|
|
@@ -16314,6 +16315,9 @@ var RebaseWebSocketClient = class {
|
|
|
16314
16315
|
this.resubscribeAfterAuthRefresh(message, collectionSub, collectionKey, "collection", this.backendToCollectionKey, "subscribe_collection");
|
|
16315
16316
|
return;
|
|
16316
16317
|
}
|
|
16318
|
+
if (collectionSub.subscribeTimeout) clearTimeout(collectionSub.subscribeTimeout);
|
|
16319
|
+
collectionSub.subscribeTimeout = void 0;
|
|
16320
|
+
collectionSub.subscribeInFlight = false;
|
|
16317
16321
|
const { errorMessage, errorCode } = extractMessageError(message);
|
|
16318
16322
|
const error = new RebaseApiError(errorMessage, { code: errorCode });
|
|
16319
16323
|
collectionSub.callbacks.forEach((callback) => {
|
|
@@ -16330,6 +16334,9 @@ var RebaseWebSocketClient = class {
|
|
|
16330
16334
|
this.resubscribeAfterAuthRefresh(message, entitySub, entityKey, "row", this.backendToEntityKey, "subscribe_one");
|
|
16331
16335
|
return;
|
|
16332
16336
|
}
|
|
16337
|
+
if (entitySub.subscribeTimeout) clearTimeout(entitySub.subscribeTimeout);
|
|
16338
|
+
entitySub.subscribeTimeout = void 0;
|
|
16339
|
+
entitySub.subscribeInFlight = false;
|
|
16333
16340
|
const { errorMessage, errorCode } = extractMessageError(message);
|
|
16334
16341
|
const error = new RebaseApiError(errorMessage, { code: errorCode });
|
|
16335
16342
|
entitySub.callbacks.forEach((callback) => {
|
|
@@ -16678,9 +16685,12 @@ var RebaseWebSocketClient = class {
|
|
|
16678
16685
|
console.error("Error in collection subscription callback:", error);
|
|
16679
16686
|
if (onError) onError(error instanceof Error ? error : new Error(String(error)));
|
|
16680
16687
|
}
|
|
16688
|
+
else if (!existingSubscription.subscribeInFlight) this.sendCollectionSubscribe(subscriptionKey);
|
|
16681
16689
|
return () => {
|
|
16682
16690
|
callbackMap.delete(callbackId);
|
|
16683
16691
|
if (callbackMap.size === 0) {
|
|
16692
|
+
if (this.collectionSubscriptions.get(subscriptionKey) !== existingSubscription) return;
|
|
16693
|
+
if (existingSubscription.subscribeTimeout) clearTimeout(existingSubscription.subscribeTimeout);
|
|
16684
16694
|
this.collectionSubscriptions.delete(subscriptionKey);
|
|
16685
16695
|
this.backendToCollectionKey.delete(existingSubscription.backendSubscriptionId);
|
|
16686
16696
|
if (this.isConnected && this.ws) this.sendMessage({
|
|
@@ -16702,21 +16712,14 @@ var RebaseWebSocketClient = class {
|
|
|
16702
16712
|
props
|
|
16703
16713
|
});
|
|
16704
16714
|
this.backendToCollectionKey.set(backendSubscriptionId, subscriptionKey);
|
|
16705
|
-
this.
|
|
16706
|
-
type: "subscribe_collection",
|
|
16707
|
-
payload: {
|
|
16708
|
-
...props,
|
|
16709
|
-
subscriptionId: backendSubscriptionId
|
|
16710
|
-
}
|
|
16711
|
-
}).catch((error) => {
|
|
16712
|
-
if (onError) onError(error);
|
|
16713
|
-
});
|
|
16715
|
+
this.sendCollectionSubscribe(subscriptionKey);
|
|
16714
16716
|
return () => {
|
|
16715
16717
|
const subscription = this.collectionSubscriptions.get(subscriptionKey);
|
|
16716
16718
|
if (subscription) {
|
|
16717
16719
|
const callbacks = subscription.callbacks;
|
|
16718
16720
|
callbacks.delete(callbackId);
|
|
16719
16721
|
if (callbacks.size === 0) {
|
|
16722
|
+
if (subscription.subscribeTimeout) clearTimeout(subscription.subscribeTimeout);
|
|
16720
16723
|
this.collectionSubscriptions.delete(subscriptionKey);
|
|
16721
16724
|
this.backendToCollectionKey.delete(subscription.backendSubscriptionId);
|
|
16722
16725
|
if (this.isConnected && this.ws) this.sendMessage({
|
|
@@ -16743,9 +16746,12 @@ var RebaseWebSocketClient = class {
|
|
|
16743
16746
|
console.error("Error in row subscription callback:", error);
|
|
16744
16747
|
if (onError) onError(error instanceof Error ? error : new Error(String(error)));
|
|
16745
16748
|
}
|
|
16749
|
+
else if (!existingSubscription.subscribeInFlight) this.sendEntitySubscribe(subscriptionKey);
|
|
16746
16750
|
return () => {
|
|
16747
16751
|
callbackMap.delete(callbackId);
|
|
16748
16752
|
if (callbackMap.size === 0) {
|
|
16753
|
+
if (this.singleSubscriptions.get(subscriptionKey) !== existingSubscription) return;
|
|
16754
|
+
if (existingSubscription.subscribeTimeout) clearTimeout(existingSubscription.subscribeTimeout);
|
|
16749
16755
|
this.singleSubscriptions.delete(subscriptionKey);
|
|
16750
16756
|
this.backendToEntityKey.delete(existingSubscription.backendSubscriptionId);
|
|
16751
16757
|
if (this.isConnected && this.ws) this.sendMessage({
|
|
@@ -16767,15 +16773,7 @@ var RebaseWebSocketClient = class {
|
|
|
16767
16773
|
props
|
|
16768
16774
|
});
|
|
16769
16775
|
this.backendToEntityKey.set(backendSubscriptionId, subscriptionKey);
|
|
16770
|
-
this.
|
|
16771
|
-
type: "subscribe_one",
|
|
16772
|
-
payload: {
|
|
16773
|
-
...props,
|
|
16774
|
-
subscriptionId: backendSubscriptionId
|
|
16775
|
-
}
|
|
16776
|
-
}).catch((error) => {
|
|
16777
|
-
if (onError) onError(error);
|
|
16778
|
-
});
|
|
16776
|
+
this.sendEntitySubscribe(subscriptionKey);
|
|
16779
16777
|
return () => {
|
|
16780
16778
|
const subscription = this.singleSubscriptions.get(subscriptionKey);
|
|
16781
16779
|
if (subscription) {
|
|
@@ -16793,6 +16791,157 @@ var RebaseWebSocketClient = class {
|
|
|
16793
16791
|
};
|
|
16794
16792
|
}
|
|
16795
16793
|
/**
|
|
16794
|
+
* Send a `subscribe_collection` for an already-registered subscription and
|
|
16795
|
+
* arm its watchdog.
|
|
16796
|
+
*
|
|
16797
|
+
* Every path that registers a collection subscription goes through here, so
|
|
16798
|
+
* that a subscribe which never lands — a rejected send, or a server that
|
|
16799
|
+
* never answers — always ends up in `failCollectionSubscription` rather than
|
|
16800
|
+
* leaving the entry parked with `isInitialDataReceived === false` forever.
|
|
16801
|
+
*/
|
|
16802
|
+
sendCollectionSubscribe(subscriptionKey) {
|
|
16803
|
+
const subscription = this.collectionSubscriptions.get(subscriptionKey);
|
|
16804
|
+
if (!subscription) return;
|
|
16805
|
+
const backendSubscriptionId = subscription.backendSubscriptionId;
|
|
16806
|
+
subscription.subscribeInFlight = true;
|
|
16807
|
+
if (subscription.subscribeTimeout) clearTimeout(subscription.subscribeTimeout);
|
|
16808
|
+
subscription.subscribeTimeout = void 0;
|
|
16809
|
+
if (this.isConnected) this.sendCollectionSubscribeWatchdog(subscriptionKey);
|
|
16810
|
+
this.sendMessage({
|
|
16811
|
+
type: "subscribe_collection",
|
|
16812
|
+
payload: {
|
|
16813
|
+
...subscription.props,
|
|
16814
|
+
subscriptionId: backendSubscriptionId
|
|
16815
|
+
}
|
|
16816
|
+
}).catch((error) => {
|
|
16817
|
+
const current = this.collectionSubscriptions.get(subscriptionKey);
|
|
16818
|
+
if (!current || current.backendSubscriptionId !== backendSubscriptionId) return;
|
|
16819
|
+
this.failCollectionSubscription(subscriptionKey, error instanceof Error ? error : new Error(String(error)));
|
|
16820
|
+
});
|
|
16821
|
+
}
|
|
16822
|
+
/** The `listenOne` counterpart of {@link sendCollectionSubscribe}. */
|
|
16823
|
+
sendEntitySubscribe(subscriptionKey) {
|
|
16824
|
+
const subscription = this.singleSubscriptions.get(subscriptionKey);
|
|
16825
|
+
if (!subscription) return;
|
|
16826
|
+
const backendSubscriptionId = subscription.backendSubscriptionId;
|
|
16827
|
+
subscription.subscribeInFlight = true;
|
|
16828
|
+
if (subscription.subscribeTimeout) clearTimeout(subscription.subscribeTimeout);
|
|
16829
|
+
subscription.subscribeTimeout = void 0;
|
|
16830
|
+
if (this.isConnected) this.sendEntitySubscribeWatchdog(subscriptionKey);
|
|
16831
|
+
this.sendMessage({
|
|
16832
|
+
type: "subscribe_one",
|
|
16833
|
+
payload: {
|
|
16834
|
+
...subscription.props,
|
|
16835
|
+
subscriptionId: backendSubscriptionId
|
|
16836
|
+
}
|
|
16837
|
+
}).catch((error) => {
|
|
16838
|
+
const current = this.singleSubscriptions.get(subscriptionKey);
|
|
16839
|
+
if (!current || current.backendSubscriptionId !== backendSubscriptionId) return;
|
|
16840
|
+
this.failEntitySubscription(subscriptionKey, error instanceof Error ? error : new Error(String(error)));
|
|
16841
|
+
});
|
|
16842
|
+
}
|
|
16843
|
+
/**
|
|
16844
|
+
* Report a subscribe failure to every listener and drop the registration.
|
|
16845
|
+
*
|
|
16846
|
+
* Dropping it is the point: the callbacks stay live (their components are
|
|
16847
|
+
* still mounted and have been told), but the next `listenCollection` for
|
|
16848
|
+
* these params finds no entry and issues a fresh subscribe instead of
|
|
16849
|
+
* silently attaching to a dead one.
|
|
16850
|
+
*/
|
|
16851
|
+
failCollectionSubscription(subscriptionKey, error) {
|
|
16852
|
+
const subscription = this.collectionSubscriptions.get(subscriptionKey);
|
|
16853
|
+
if (!subscription) return;
|
|
16854
|
+
if (subscription.subscribeTimeout) clearTimeout(subscription.subscribeTimeout);
|
|
16855
|
+
subscription.subscribeInFlight = false;
|
|
16856
|
+
this.collectionSubscriptions.delete(subscriptionKey);
|
|
16857
|
+
this.backendToCollectionKey.delete(subscription.backendSubscriptionId);
|
|
16858
|
+
subscription.callbacks.forEach((callback) => {
|
|
16859
|
+
if (callback.onError) try {
|
|
16860
|
+
callback.onError(error);
|
|
16861
|
+
} catch (callbackError) {
|
|
16862
|
+
console.error("Error in collection subscription error callback:", callbackError);
|
|
16863
|
+
}
|
|
16864
|
+
});
|
|
16865
|
+
}
|
|
16866
|
+
/** The `listenOne` counterpart of {@link failCollectionSubscription}. */
|
|
16867
|
+
failEntitySubscription(subscriptionKey, error) {
|
|
16868
|
+
const subscription = this.singleSubscriptions.get(subscriptionKey);
|
|
16869
|
+
if (!subscription) return;
|
|
16870
|
+
if (subscription.subscribeTimeout) clearTimeout(subscription.subscribeTimeout);
|
|
16871
|
+
subscription.subscribeInFlight = false;
|
|
16872
|
+
this.singleSubscriptions.delete(subscriptionKey);
|
|
16873
|
+
this.backendToEntityKey.delete(subscription.backendSubscriptionId);
|
|
16874
|
+
subscription.callbacks.forEach((callback) => {
|
|
16875
|
+
if (callback.onError) try {
|
|
16876
|
+
callback.onError(error);
|
|
16877
|
+
} catch (callbackError) {
|
|
16878
|
+
console.error("Error in row subscription error callback:", callbackError);
|
|
16879
|
+
}
|
|
16880
|
+
});
|
|
16881
|
+
}
|
|
16882
|
+
/**
|
|
16883
|
+
* Stop the watchdogs without failing anything — used when the socket drops,
|
|
16884
|
+
* since the reconnect path re-subscribes everything anyway and a watchdog
|
|
16885
|
+
* firing mid-reconnect would tear down healthy subscriptions.
|
|
16886
|
+
*/
|
|
16887
|
+
suspendSubscribeWatchdogs() {
|
|
16888
|
+
for (const sub of this.collectionSubscriptions.values()) {
|
|
16889
|
+
if (sub.subscribeTimeout) clearTimeout(sub.subscribeTimeout);
|
|
16890
|
+
sub.subscribeTimeout = void 0;
|
|
16891
|
+
sub.subscribeInFlight = false;
|
|
16892
|
+
}
|
|
16893
|
+
for (const sub of this.singleSubscriptions.values()) {
|
|
16894
|
+
if (sub.subscribeTimeout) clearTimeout(sub.subscribeTimeout);
|
|
16895
|
+
sub.subscribeTimeout = void 0;
|
|
16896
|
+
sub.subscribeInFlight = false;
|
|
16897
|
+
}
|
|
16898
|
+
}
|
|
16899
|
+
/**
|
|
16900
|
+
* Arm watchdogs for subscribes that were requested while offline and have
|
|
16901
|
+
* just been flushed to the socket. Their timers were deliberately not set at
|
|
16902
|
+
* request time, so without this they would have no timeout at all.
|
|
16903
|
+
*/
|
|
16904
|
+
armPendingSubscribeWatchdogs() {
|
|
16905
|
+
for (const [key, sub] of this.collectionSubscriptions.entries()) if (sub.subscribeInFlight && !sub.subscribeTimeout) this.sendCollectionSubscribeWatchdog(key);
|
|
16906
|
+
for (const [key, sub] of this.singleSubscriptions.entries()) if (sub.subscribeInFlight && !sub.subscribeTimeout) this.sendEntitySubscribeWatchdog(key);
|
|
16907
|
+
}
|
|
16908
|
+
sendCollectionSubscribeWatchdog(subscriptionKey) {
|
|
16909
|
+
const subscription = this.collectionSubscriptions.get(subscriptionKey);
|
|
16910
|
+
if (!subscription) return;
|
|
16911
|
+
const backendSubscriptionId = subscription.backendSubscriptionId;
|
|
16912
|
+
subscription.subscribeTimeout = setTimeout(() => {
|
|
16913
|
+
const current = this.collectionSubscriptions.get(subscriptionKey);
|
|
16914
|
+
if (!current || current.backendSubscriptionId !== backendSubscriptionId) return;
|
|
16915
|
+
if (!current.subscribeInFlight) return;
|
|
16916
|
+
this.failCollectionSubscription(subscriptionKey, new RebaseApiError("Subscription timed out", { code: "SUBSCRIPTION_TIMEOUT" }));
|
|
16917
|
+
}, this.subscriptionTimeoutMs);
|
|
16918
|
+
}
|
|
16919
|
+
sendEntitySubscribeWatchdog(subscriptionKey) {
|
|
16920
|
+
const subscription = this.singleSubscriptions.get(subscriptionKey);
|
|
16921
|
+
if (!subscription) return;
|
|
16922
|
+
const backendSubscriptionId = subscription.backendSubscriptionId;
|
|
16923
|
+
subscription.subscribeTimeout = setTimeout(() => {
|
|
16924
|
+
const current = this.singleSubscriptions.get(subscriptionKey);
|
|
16925
|
+
if (!current || current.backendSubscriptionId !== backendSubscriptionId) return;
|
|
16926
|
+
if (!current.subscribeInFlight) return;
|
|
16927
|
+
this.failEntitySubscription(subscriptionKey, new RebaseApiError("Subscription timed out", { code: "SUBSCRIPTION_TIMEOUT" }));
|
|
16928
|
+
}, this.subscriptionTimeoutMs);
|
|
16929
|
+
}
|
|
16930
|
+
/**
|
|
16931
|
+
* Fail every subscription that never received data. Called when reconnection
|
|
16932
|
+
* is given up on, so views surface an error instead of spinning forever.
|
|
16933
|
+
*/
|
|
16934
|
+
failAllPendingSubscriptions(error) {
|
|
16935
|
+
for (const key of [...this.collectionSubscriptions.keys()]) {
|
|
16936
|
+
const sub = this.collectionSubscriptions.get(key);
|
|
16937
|
+
if (sub && !sub.isInitialDataReceived) this.failCollectionSubscription(key, error);
|
|
16938
|
+
}
|
|
16939
|
+
for (const key of [...this.singleSubscriptions.keys()]) {
|
|
16940
|
+
const sub = this.singleSubscriptions.get(key);
|
|
16941
|
+
if (sub && !sub.isInitialDataReceived) this.failEntitySubscription(key, error);
|
|
16942
|
+
}
|
|
16943
|
+
}
|
|
16944
|
+
/**
|
|
16796
16945
|
* Re-send all active subscriptions to the backend after a reconnect.
|
|
16797
16946
|
* The server wipes subscription state when a client disconnects, so
|
|
16798
16947
|
* we need to re-register everything to resume receiving updates.
|
|
@@ -16805,15 +16954,7 @@ var RebaseWebSocketClient = class {
|
|
|
16805
16954
|
sub.backendSubscriptionId = newBackendId;
|
|
16806
16955
|
this.backendToCollectionKey.delete(oldBackendId);
|
|
16807
16956
|
this.backendToCollectionKey.set(newBackendId, key);
|
|
16808
|
-
this.
|
|
16809
|
-
type: "subscribe_collection",
|
|
16810
|
-
payload: {
|
|
16811
|
-
...sub.props,
|
|
16812
|
-
subscriptionId: newBackendId
|
|
16813
|
-
}
|
|
16814
|
-
}).catch((error) => {
|
|
16815
|
-
console.error("[WS] Failed to re-subscribe collection:", key, error);
|
|
16816
|
-
});
|
|
16957
|
+
this.sendCollectionSubscribe(key);
|
|
16817
16958
|
}
|
|
16818
16959
|
for (const [key, sub] of this.singleSubscriptions.entries()) {
|
|
16819
16960
|
const oldBackendId = sub.backendSubscriptionId;
|
|
@@ -16821,15 +16962,7 @@ var RebaseWebSocketClient = class {
|
|
|
16821
16962
|
sub.backendSubscriptionId = newBackendId;
|
|
16822
16963
|
this.backendToEntityKey.delete(oldBackendId);
|
|
16823
16964
|
this.backendToEntityKey.set(newBackendId, key);
|
|
16824
|
-
this.
|
|
16825
|
-
type: "subscribe_one",
|
|
16826
|
-
payload: {
|
|
16827
|
-
...sub.props,
|
|
16828
|
-
subscriptionId: newBackendId
|
|
16829
|
-
}
|
|
16830
|
-
}).catch((error) => {
|
|
16831
|
-
console.error("[WS] Failed to re-subscribe row:", key, error);
|
|
16832
|
-
});
|
|
16965
|
+
this.sendEntitySubscribe(key);
|
|
16833
16966
|
}
|
|
16834
16967
|
}
|
|
16835
16968
|
createCollectionSubscriptionKey(props) {
|
|
@@ -17932,7 +18065,7 @@ async function loadFunctionsFromDirectory(directory, importModule = nativeDynami
|
|
|
17932
18065
|
const problems = [];
|
|
17933
18066
|
if (!fs$2.existsSync(directory)) return functions;
|
|
17934
18067
|
const files = fs$2.readdirSync(directory);
|
|
17935
|
-
for (const file of files) if ((file.endsWith(".ts") || file.endsWith(".js")) && !file.includes(".test.") && !file.endsWith(".d.ts") && file !== "index.ts" && file !== "index.js") {
|
|
18068
|
+
for (const file of files) if ((file.endsWith(".ts") || file.endsWith(".js")) && !file.startsWith(".") && !file.includes(".test.") && !file.endsWith(".d.ts") && file !== "index.ts" && file !== "index.js") {
|
|
17936
18069
|
const filePath = path$1.join(directory, file);
|
|
17937
18070
|
try {
|
|
17938
18071
|
const fileUrl = pathToFileURL(filePath).href;
|
|
@@ -18061,7 +18194,7 @@ async function loadCronJobsFromDirectory(directory, importModule = nativeDynamic
|
|
|
18061
18194
|
const jobs = [];
|
|
18062
18195
|
if (!fs$2.existsSync(directory)) return jobs;
|
|
18063
18196
|
const files = fs$2.readdirSync(directory);
|
|
18064
|
-
for (const file of files) if ((file.endsWith(".ts") || file.endsWith(".js")) && !file.includes(".test.") && !file.endsWith(".d.ts") && file !== "index.ts" && file !== "index.js") {
|
|
18197
|
+
for (const file of files) if ((file.endsWith(".ts") || file.endsWith(".js")) && !file.startsWith(".") && !file.includes(".test.") && !file.endsWith(".d.ts") && file !== "index.ts" && file !== "index.js") {
|
|
18065
18198
|
const filePath = path$1.join(directory, file);
|
|
18066
18199
|
try {
|
|
18067
18200
|
const fileUrl = pathToFileURL(filePath).href;
|