@abraca/dabra 0.1.6 → 0.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.
@@ -1381,10 +1381,15 @@ var HocuspocusProviderWebsocket = class extends EventEmitter {
1381
1381
  if (this.connectionAttempt) this.rejectConnectionAttempt();
1382
1382
  this.status = WebSocketStatus.Disconnected;
1383
1383
  this.emit("status", { status: WebSocketStatus.Disconnected });
1384
+ const isRateLimited = event?.code === 4429;
1384
1385
  this.emit("disconnect", { event });
1385
- if (!this.cancelWebsocketRetry && this.shouldConnect) setTimeout(() => {
1386
- this.connect();
1387
- }, this.configuration.delay);
1386
+ if (isRateLimited) this.emit("rateLimited");
1387
+ if (!this.cancelWebsocketRetry && this.shouldConnect) {
1388
+ const delay = isRateLimited ? 6e4 : this.configuration.delay;
1389
+ setTimeout(() => {
1390
+ this.connect();
1391
+ }, delay);
1392
+ }
1388
1393
  }
1389
1394
  destroy() {
1390
1395
  this.emit("destroy");
@@ -1707,6 +1712,7 @@ var HocuspocusProvider = class extends EventEmitter {
1707
1712
  forceSyncInterval: false,
1708
1713
  onAuthenticated: () => null,
1709
1714
  onAuthenticationFailed: () => null,
1715
+ onRateLimited: () => null,
1710
1716
  onOpen: () => null,
1711
1717
  onConnect: () => null,
1712
1718
  onMessage: () => null,
@@ -1738,6 +1744,7 @@ var HocuspocusProvider = class extends EventEmitter {
1738
1744
  this.forwardClose = (e) => this.emit("close", e);
1739
1745
  this.forwardDisconnect = (e) => this.emit("disconnect", e);
1740
1746
  this.forwardDestroy = () => this.emit("destroy");
1747
+ this.forwardRateLimited = () => this.emit("rateLimited");
1741
1748
  this.setConfiguration(configuration);
1742
1749
  this.configuration.document = configuration.document ? configuration.document : new yjs.Doc();
1743
1750
  this.configuration.awareness = configuration.awareness !== void 0 ? configuration.awareness : new Awareness(this.document);
@@ -1752,6 +1759,7 @@ var HocuspocusProvider = class extends EventEmitter {
1752
1759
  this.on("unsyncedChanges", this.configuration.onUnsyncedChanges);
1753
1760
  this.on("authenticated", this.configuration.onAuthenticated);
1754
1761
  this.on("authenticationFailed", this.configuration.onAuthenticationFailed);
1762
+ this.on("rateLimited", this.configuration.onRateLimited);
1755
1763
  this.awareness?.on("update", () => {
1756
1764
  this.emit("awarenessUpdate", { states: (0, _abraca_dabra_common.awarenessStatesToArray)(this.awareness.getStates()) });
1757
1765
  });
@@ -1944,6 +1952,7 @@ var HocuspocusProvider = class extends EventEmitter {
1944
1952
  this.configuration.websocketProvider.off("disconnect", this.forwardDisconnect);
1945
1953
  this.configuration.websocketProvider.off("destroy", this.configuration.onDestroy);
1946
1954
  this.configuration.websocketProvider.off("destroy", this.forwardDestroy);
1955
+ this.configuration.websocketProvider.off("rateLimited", this.forwardRateLimited);
1947
1956
  this.configuration.websocketProvider.detach(this);
1948
1957
  this._isAttached = false;
1949
1958
  }
@@ -1961,6 +1970,7 @@ var HocuspocusProvider = class extends EventEmitter {
1961
1970
  this.configuration.websocketProvider.on("disconnect", this.forwardDisconnect);
1962
1971
  this.configuration.websocketProvider.on("destroy", this.configuration.onDestroy);
1963
1972
  this.configuration.websocketProvider.on("destroy", this.forwardDestroy);
1973
+ this.configuration.websocketProvider.on("rateLimited", this.forwardRateLimited);
1964
1974
  this.configuration.websocketProvider.attach(this);
1965
1975
  this._isAttached = true;
1966
1976
  }
@@ -2116,6 +2126,10 @@ var SubdocMessage = class extends OutgoingMessage {
2116
2126
 
2117
2127
  //#endregion
2118
2128
  //#region packages/provider/src/AbracadabraProvider.ts
2129
+ /** Validate that a string is a UUID acceptable by the server's DocId parser. */
2130
+ function isValidDocId(id) {
2131
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id);
2132
+ }
2119
2133
  /**
2120
2134
  * AbracadabraProvider extends HocuspocusProvider with:
2121
2135
  *
@@ -2142,6 +2156,7 @@ var AbracadabraProvider = class AbracadabraProvider extends HocuspocusProvider {
2142
2156
  super(resolved);
2143
2157
  this.effectiveRole = null;
2144
2158
  this.childProviders = /* @__PURE__ */ new Map();
2159
+ this.pendingLoads = /* @__PURE__ */ new Map();
2145
2160
  this.boundHandleYSubdocsChange = this.handleYSubdocsChange.bind(this);
2146
2161
  this._client = client;
2147
2162
  this.abracadabraConfig = configuration;
@@ -2251,7 +2266,10 @@ var AbracadabraProvider = class AbracadabraProvider extends HocuspocusProvider {
2251
2266
  * We intercept additions to register them with the Abracadabra server.
2252
2267
  */
2253
2268
  handleYSubdocsChange({ added, removed }) {
2254
- for (const subdoc of added) this.registerSubdoc(subdoc);
2269
+ for (const subdoc of added) {
2270
+ if (!isValidDocId(subdoc.guid)) continue;
2271
+ this.registerSubdoc(subdoc);
2272
+ }
2255
2273
  for (const subdoc of removed) this.unloadChild(subdoc.guid);
2256
2274
  }
2257
2275
  /**
@@ -2275,8 +2293,16 @@ var AbracadabraProvider = class AbracadabraProvider extends HocuspocusProvider {
2275
2293
  * child document id. Each child opens its own WebSocket connection because
2276
2294
  * the server is document-scoped (one WebSocket ↔ one document).
2277
2295
  */
2278
- async loadChild(childId) {
2279
- if (this.childProviders.has(childId)) return this.childProviders.get(childId);
2296
+ loadChild(childId) {
2297
+ if (!isValidDocId(childId)) return Promise.reject(/* @__PURE__ */ new Error(`loadChild: "${childId}" is not a valid document ID (must be a UUID). If this node was created with an older version of the app, delete it and recreate it.`));
2298
+ if (this.childProviders.has(childId)) return Promise.resolve(this.childProviders.get(childId));
2299
+ if (this.pendingLoads.has(childId)) return this.pendingLoads.get(childId);
2300
+ const load = this._doLoadChild(childId);
2301
+ this.pendingLoads.set(childId, load);
2302
+ load.finally(() => this.pendingLoads.delete(childId));
2303
+ return load;
2304
+ }
2305
+ async _doLoadChild(childId) {
2280
2306
  const childDoc = new yjs.Doc({ guid: childId });
2281
2307
  await new Promise((resolve) => {
2282
2308
  const onRegistered = ({ childId: cid }) => {
@@ -2292,7 +2318,7 @@ var AbracadabraProvider = class AbracadabraProvider extends HocuspocusProvider {
2292
2318
  const childProvider = new AbracadabraProvider({
2293
2319
  name: childId,
2294
2320
  document: childDoc,
2295
- url: this.abracadabraConfig.url,
2321
+ url: this.abracadabraConfig.url ?? this.configuration.websocketProvider?.url,
2296
2322
  token: this.configuration.token,
2297
2323
  subdocLoading: this.subdocLoading,
2298
2324
  disableOfflineStore: this.abracadabraConfig.disableOfflineStore,