@osdk/client 2.0.5 → 2.1.0-beta.1

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.
Files changed (96) hide show
  1. package/CHANGELOG.md +28 -84
  2. package/build/browser/Client.d.ts +1 -1
  3. package/build/browser/Client.js +1 -1
  4. package/build/browser/Client.js.map +1 -1
  5. package/build/browser/createClient.d.ts.map +1 -1
  6. package/build/browser/createClient.js +11 -0
  7. package/build/browser/createClient.js.map +1 -1
  8. package/build/browser/createGeotimeSeriesProperty.d.ts +14 -0
  9. package/build/browser/createGeotimeSeriesProperty.d.ts.map +1 -0
  10. package/build/browser/createGeotimeSeriesProperty.js +47 -0
  11. package/build/browser/createGeotimeSeriesProperty.js.map +1 -0
  12. package/build/browser/createTimeseriesProperty.d.ts.map +1 -1
  13. package/build/browser/createTimeseriesProperty.js +4 -36
  14. package/build/browser/createTimeseriesProperty.js.map +1 -1
  15. package/build/browser/fetchMetadata.test.js +7 -0
  16. package/build/browser/fetchMetadata.test.js.map +1 -1
  17. package/build/browser/object/Cache.test.js +1 -1
  18. package/build/browser/object/Cache.test.js.map +1 -1
  19. package/build/browser/object/convertWireToOsdkObjects/InternalSymbols.d.ts +1 -0
  20. package/build/browser/object/convertWireToOsdkObjects/InternalSymbols.d.ts.map +1 -1
  21. package/build/browser/object/convertWireToOsdkObjects/InternalSymbols.js +1 -0
  22. package/build/browser/object/convertWireToOsdkObjects/InternalSymbols.js.map +1 -1
  23. package/build/browser/object/convertWireToOsdkObjects/createOsdkObject.js +15 -1
  24. package/build/browser/object/convertWireToOsdkObjects/createOsdkObject.js.map +1 -1
  25. package/build/browser/object/convertWireToOsdkObjects.test.js +3 -3
  26. package/build/browser/object/convertWireToOsdkObjects.test.js.map +1 -1
  27. package/build/browser/object/geotimeseriesreference.test.d.ts +2 -0
  28. package/build/browser/object/geotimeseriesreference.test.d.ts.map +1 -0
  29. package/build/browser/object/geotimeseriesreference.test.js +257 -0
  30. package/build/browser/object/geotimeseriesreference.test.js.map +1 -0
  31. package/build/browser/objectSet/ObjectSet.test.js +6 -3
  32. package/build/browser/objectSet/ObjectSet.test.js.map +1 -1
  33. package/build/browser/objectSet/ObjectSetListenerWebsocket.d.ts +1 -6
  34. package/build/browser/objectSet/ObjectSetListenerWebsocket.d.ts.map +1 -1
  35. package/build/browser/objectSet/ObjectSetListenerWebsocket.js +37 -156
  36. package/build/browser/objectSet/ObjectSetListenerWebsocket.js.map +1 -1
  37. package/build/browser/objectSet/ObjectSetListenerWebsocket.test.js +17 -16
  38. package/build/browser/objectSet/ObjectSetListenerWebsocket.test.js.map +1 -1
  39. package/build/browser/objectSet/createObjectSet.js +2 -2
  40. package/build/browser/objectSet/createObjectSet.js.map +1 -1
  41. package/build/browser/objectSet/toConjureObjectSet.js +7 -0
  42. package/build/browser/objectSet/toConjureObjectSet.js.map +1 -1
  43. package/build/browser/util/UserAgent.js +1 -1
  44. package/build/browser/util/UserAgent.js.map +1 -1
  45. package/build/browser/util/timeseriesUtils.d.ts +8 -0
  46. package/build/browser/util/timeseriesUtils.d.ts.map +1 -0
  47. package/build/browser/util/timeseriesUtils.js +51 -0
  48. package/build/browser/util/timeseriesUtils.js.map +1 -0
  49. package/build/esm/Client.d.ts +1 -1
  50. package/build/esm/Client.js +1 -1
  51. package/build/esm/Client.js.map +1 -1
  52. package/build/esm/createClient.d.ts.map +1 -1
  53. package/build/esm/createClient.js +11 -0
  54. package/build/esm/createClient.js.map +1 -1
  55. package/build/esm/createGeotimeSeriesProperty.d.ts +14 -0
  56. package/build/esm/createGeotimeSeriesProperty.d.ts.map +1 -0
  57. package/build/esm/createGeotimeSeriesProperty.js +47 -0
  58. package/build/esm/createGeotimeSeriesProperty.js.map +1 -0
  59. package/build/esm/createTimeseriesProperty.d.ts.map +1 -1
  60. package/build/esm/createTimeseriesProperty.js +4 -36
  61. package/build/esm/createTimeseriesProperty.js.map +1 -1
  62. package/build/esm/fetchMetadata.test.js +7 -0
  63. package/build/esm/fetchMetadata.test.js.map +1 -1
  64. package/build/esm/object/Cache.test.js +1 -1
  65. package/build/esm/object/Cache.test.js.map +1 -1
  66. package/build/esm/object/convertWireToOsdkObjects/InternalSymbols.d.ts +1 -0
  67. package/build/esm/object/convertWireToOsdkObjects/InternalSymbols.d.ts.map +1 -1
  68. package/build/esm/object/convertWireToOsdkObjects/InternalSymbols.js +1 -0
  69. package/build/esm/object/convertWireToOsdkObjects/InternalSymbols.js.map +1 -1
  70. package/build/esm/object/convertWireToOsdkObjects/createOsdkObject.js +15 -1
  71. package/build/esm/object/convertWireToOsdkObjects/createOsdkObject.js.map +1 -1
  72. package/build/esm/object/convertWireToOsdkObjects.test.js +3 -3
  73. package/build/esm/object/convertWireToOsdkObjects.test.js.map +1 -1
  74. package/build/esm/object/geotimeseriesreference.test.d.ts +2 -0
  75. package/build/esm/object/geotimeseriesreference.test.d.ts.map +1 -0
  76. package/build/esm/object/geotimeseriesreference.test.js +257 -0
  77. package/build/esm/object/geotimeseriesreference.test.js.map +1 -0
  78. package/build/esm/objectSet/ObjectSet.test.js +6 -3
  79. package/build/esm/objectSet/ObjectSet.test.js.map +1 -1
  80. package/build/esm/objectSet/ObjectSetListenerWebsocket.d.ts +1 -6
  81. package/build/esm/objectSet/ObjectSetListenerWebsocket.d.ts.map +1 -1
  82. package/build/esm/objectSet/ObjectSetListenerWebsocket.js +37 -156
  83. package/build/esm/objectSet/ObjectSetListenerWebsocket.js.map +1 -1
  84. package/build/esm/objectSet/ObjectSetListenerWebsocket.test.js +17 -16
  85. package/build/esm/objectSet/ObjectSetListenerWebsocket.test.js.map +1 -1
  86. package/build/esm/objectSet/createObjectSet.js +2 -2
  87. package/build/esm/objectSet/createObjectSet.js.map +1 -1
  88. package/build/esm/objectSet/toConjureObjectSet.js +7 -0
  89. package/build/esm/objectSet/toConjureObjectSet.js.map +1 -1
  90. package/build/esm/util/UserAgent.js +1 -1
  91. package/build/esm/util/UserAgent.js.map +1 -1
  92. package/build/esm/util/timeseriesUtils.d.ts +8 -0
  93. package/build/esm/util/timeseriesUtils.d.ts.map +1 -0
  94. package/build/esm/util/timeseriesUtils.js +51 -0
  95. package/build/esm/util/timeseriesUtils.js.map +1 -0
  96. package/package.json +12 -13
@@ -13,14 +13,9 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { bulkLoadOntologyEntities, createTemporaryObjectSet, loadAllOntologies } from "@osdk/client.unstable";
17
- import { batchEnableWatcher } from "@osdk/client.unstable.osw";
18
- import * as OntologiesV2 from "@osdk/internal.foundry.ontologiesv2";
19
16
  import WebSocket from "isomorphic-ws";
20
17
  import invariant from "tiny-invariant";
21
- import { metadataCacheClient } from "../__unstable/ConjureSupport.js";
22
18
  import { convertWireToOsdkObjects } from "../object/convertWireToOsdkObjects.js";
23
- import { getObjectSetBaseType, toConjureObjectSet } from "./toConjureObjectSet.js";
24
19
  const ONE_DAY_MS = 24 * 60 * 60 * 1000;
25
20
  const MINIMUM_RECONNECT_DELAY_MS = 5 * 1000;
26
21
  /** Noop function to reduce conditional checks */
@@ -40,7 +35,7 @@ function fillOutListener({
40
35
  };
41
36
  }
42
37
  function isReady(sub) {
43
- return sub.temporaryObjectSetId != null;
38
+ return sub.isReady != null;
44
39
  }
45
40
  function subscriptionIsDone(sub) {
46
41
  return sub.status === "done" || sub.status === "error";
@@ -72,9 +67,6 @@ export class ObjectSetListenerWebsocket {
72
67
  * temporary and not the actual subscriptionId from the server.
73
68
  */
74
69
  #subscriptions = new Map();
75
- #oswContext;
76
- #metadataContext;
77
- #ossContext;
78
70
  #maybeDisconnectTimeout;
79
71
  // DO NOT CONSTRUCT DIRECTLY. ONLY EXPOSED AS A TESTING SEAM
80
72
  constructor(client, {
@@ -88,28 +80,15 @@ export class ObjectSetListenerWebsocket {
88
80
  msgPrefix: "<OSW> "
89
81
  });
90
82
  !(client.baseUrl.startsWith("https://") || client.baseUrl.startsWith("http://")) ? invariant(false, "Stack must be a URL") : void 0;
91
- this.#oswContext = {
92
- baseUrl: client.baseUrl,
93
- servicePath: "/object-set-watcher/api",
94
- fetchFn: client.fetch,
95
- tokenProvider: async () => await client.tokenProvider()
96
- };
97
- this.#ossContext = {
98
- ...this.#oswContext,
99
- servicePath: "/object-set-service/api"
100
- };
101
- this.#metadataContext = {
102
- ...this.#oswContext,
103
- servicePath: "/ontology-metadata/api"
104
- };
105
83
  }
106
- async subscribe(objectSet, listener) {
84
+ async subscribe(objectSet, listener, properties) {
107
85
  // Node 18 does not expose 'crypto' on globalThis, so we need to do it ourselves. This
108
86
  // will not be needed after our minimum version is 19 or greater.
109
87
  globalThis.crypto ??= (await import("node:crypto")).webcrypto;
110
88
  const sub = {
111
89
  listener: fillOutListener(listener),
112
90
  objectSet,
91
+ requestedProperties: properties,
113
92
  status: "preparing",
114
93
  // Since we don't have a real subscription id yet but we need to keep
115
94
  // track of this reference, we can just use a random uuid.
@@ -142,28 +121,22 @@ export class ObjectSetListenerWebsocket {
142
121
  // expiry is tied to the temporary object set, which is set to `timeToLive: "ONE_DAY"`
143
122
  // in `#createTemporaryObjectSet`. They should be in sync
144
123
  sub.expiry = setTimeout(() => this.#expire(sub), this.OBJECT_SET_EXPIRY_MS);
145
- const ontologyRid = await this.#client.ontologyRid;
124
+ await this.#client.ontologyRid;
146
125
  try {
147
- const [temporaryObjectSet] = await Promise.all([
148
- // create a time-bounded object set representation for watching
149
- this.#createTemporaryObjectSet(sub.objectSet), this.#ensureWebsocket(),
150
- // look up the object type's rid and ensure that we have enabled object set watcher for that rid
151
- // TODO ???
152
- getObjectSetBaseType(sub.objectSet).then(baseType => OntologiesV2.ObjectTypesV2.get(this.#client, ontologyRid, baseType)).then(objectType => this.#enableObjectSetsWatcher([objectType.rid]))]);
126
+ await this.#ensureWebsocket();
153
127
  // the consumer may have already unsubscribed before we are ready to request a subscription
154
128
  // so we have to acquire the pendingSubscription after the await.
155
129
  if (subscriptionIsDone(sub)) {
156
130
  return;
157
131
  }
158
- // Use new temporary object set id
159
- sub.temporaryObjectSetId = temporaryObjectSet.objectSetRid;
132
+ sub.isReady = true;
160
133
  // if we aren't open, then this happens after we #onConnect
161
134
  if (this.#ws?.readyState === WebSocket.OPEN) {
162
135
  this.#sendSubscribeMessage();
163
136
  }
164
137
  } catch (error) {
165
138
  this.#logger?.error(error, "Error in #initiateSubscribe");
166
- sub.listener.onError(error);
139
+ sub.listener.onError([error]);
167
140
  }
168
141
  }
169
142
  #sendSubscribeMessage() {
@@ -189,15 +162,12 @@ export class ObjectSetListenerWebsocket {
189
162
  const subscribe = {
190
163
  id,
191
164
  requests: readySubs.map(({
192
- temporaryObjectSetId
165
+ objectSet,
166
+ requestedProperties
193
167
  }) => ({
194
- objectSet: temporaryObjectSetId,
195
- objectSetContext: {
196
- objectSetFilterContext: {
197
- parameterOverrides: {}
198
- }
199
- },
200
- watchAllLinks: false
168
+ objectSet: objectSet,
169
+ propertySet: requestedProperties,
170
+ referenceSet: []
201
171
  }))
202
172
  };
203
173
  if (process?.env?.NODE_ENV !== "production") {
@@ -261,8 +231,7 @@ export class ObjectSetListenerWebsocket {
261
231
  tokenProvider
262
232
  } = this.#client;
263
233
  const base = new URL(baseUrl);
264
- // TODO: This should be a different endpoint
265
- const url = `wss://${base.host}/object-set-watcher/ws/subscriptions`;
234
+ const url = `wss://${base.host}/api/v2/ontologySubscriptions/ontologies/${this.#client.ontologyRid}/streamSubscriptions`;
266
235
  const token = await tokenProvider();
267
236
  // tokenProvider is async, there could potentially be a race to create the websocket.
268
237
  // Only the first call to reach here will find a null this.#ws, the rest will bail out
@@ -325,15 +294,14 @@ export class ObjectSetListenerWebsocket {
325
294
  }
326
295
  switch (data.type) {
327
296
  case "objectSetChanged":
328
- return this.#handleMessage_objectSetChanged(data.objectSetChanged);
297
+ return this.#handleMessage_objectSetChanged(data);
329
298
  case "refreshObjectSet":
330
- return this.#handleMessage_refreshObjectSet(data.refreshObjectSet);
299
+ return this.#handleMessage_refreshObjectSet(data);
331
300
  case "subscribeResponses":
332
- return this.#handleMessage_subscribeResponses(data.subscribeResponses);
301
+ return this.#handleMessage_subscribeResponses(data);
333
302
  case "subscriptionClosed":
334
303
  {
335
- const payload = data.subscriptionClosed;
336
- return this.#handleMessage_subscriptionClosed(payload);
304
+ return this.#handleMessage_subscriptionClosed(data);
337
305
  }
338
306
  default:
339
307
  invariant(false, "Unexpected message type");
@@ -342,15 +310,21 @@ export class ObjectSetListenerWebsocket {
342
310
  #handleMessage_objectSetChanged = async payload => {
343
311
  const sub = this.#subscriptions.get(payload.id);
344
312
  !sub ? invariant(false, `Expected subscription id ${payload.id}`) : void 0;
345
- if ("confidenceValue" in payload) {
346
- sub.listener.onOutOfDate();
347
- return;
313
+ const objectUpdates = payload.updates.filter(update => update.type === "object");
314
+ payload.updates.filter(update => update.type === "reference");
315
+ const osdkObjects = await Promise.all(objectUpdates.map(async o => {
316
+ const osdkObjectArray = await convertWireToOsdkObjects(this.#client, [o.object], undefined);
317
+ const singleOsdkObject = osdkObjectArray[0] ?? undefined;
318
+ return singleOsdkObject != null ? {
319
+ object: singleOsdkObject,
320
+ state: o.state
321
+ } : undefined;
322
+ }));
323
+ for (const osdkObject of osdkObjects) {
324
+ if (osdkObject != null) {
325
+ return sub.listener.onChange?.(osdkObject);
326
+ }
348
327
  }
349
- const objects = payload.updates.filter(function (a) {
350
- return a.type === "object";
351
- }).map(a => a.object);
352
- !(objects.length === payload.updates.length) ? invariant(false, "currently only support full updates not reference updates") : void 0;
353
- sub.listener.onChange(await convertFoundryToOsdkObjects(this.#client, this.#metadataContext, objects));
354
328
  };
355
329
  #handleMessage_refreshObjectSet = payload => {
356
330
  const sub = this.#subscriptions.get(payload.id);
@@ -370,7 +344,7 @@ export class ObjectSetListenerWebsocket {
370
344
  const response = responses[i];
371
345
  switch (response.type) {
372
346
  case "error":
373
- sub.listener.onError(response.error);
347
+ sub.listener.onError(response.errors);
374
348
  this.#unsubscribe(sub, "error");
375
349
  break;
376
350
  case "qos":
@@ -386,10 +360,10 @@ export class ObjectSetListenerWebsocket {
386
360
  }, "success");
387
361
  }
388
362
  sub.status = "subscribed";
389
- if (sub.subscriptionId !== response.success.id) {
363
+ if (sub.subscriptionId !== response.id) {
390
364
  // might be the temporary one
391
365
  this.#subscriptions.delete(sub.subscriptionId);
392
- sub.subscriptionId = response.success.id;
366
+ sub.subscriptionId = response.id;
393
367
  this.#subscriptions.set(sub.subscriptionId, sub); // future messages come by this subId
394
368
  }
395
369
  if (shouldFireOutOfDate) sub.listener.onOutOfDate();
@@ -402,7 +376,7 @@ export class ObjectSetListenerWebsocket {
402
376
  #handleMessage_subscriptionClosed(payload) {
403
377
  const sub = this.#subscriptions.get(payload.id);
404
378
  !sub ? invariant(false, `Expected subscription id ${payload.id}`) : void 0;
405
- sub.listener.onError(payload.error);
379
+ sub.listener.onError([payload.cause]);
406
380
  this.#unsubscribe(sub, "error");
407
381
  }
408
382
  #onClose = event => {
@@ -414,28 +388,8 @@ export class ObjectSetListenerWebsocket {
414
388
  // TODO we should probably throttle this so we don't abuse the backend
415
389
  this.#cycleWebsocket();
416
390
  };
417
- async #enableObjectSetsWatcher(objectTypeRids) {
418
- return batchEnableWatcher(this.#oswContext, {
419
- requests: objectTypeRids
420
- });
421
- }
422
- async #createTemporaryObjectSet(objectSet) {
423
- const objectSetBaseType = await getObjectSetBaseType(objectSet);
424
- const mcc = await metadataCacheClient(this.#client);
425
- const objectInfo = await mcc.forObjectByApiName(objectSetBaseType);
426
- const propMapping = await objectInfo.getPropertyMapping();
427
- const temporaryObjectSet = await createTemporaryObjectSet(this.#ossContext, {
428
- objectSet: toConjureObjectSet(objectSet, propMapping),
429
- timeToLive: "ONE_DAY",
430
- // MUST keep in sync with the value for expiry in `#initiateSubscribe`.
431
- objectSetFilterContext: {
432
- parameterOverrides: {}
433
- }
434
- });
435
- return {
436
- objectSetRid: temporaryObjectSet.objectSetRid
437
- };
438
- }
391
+ // TODO: Validate if this is needed
392
+ async #enableObjectSetsWatcher() {}
439
393
  #cycleWebsocket = () => {
440
394
  if (this.#ws) {
441
395
  this.#ws.removeEventListener("open", this.#onOpen);
@@ -460,77 +414,4 @@ export class ObjectSetListenerWebsocket {
460
414
  }
461
415
  };
462
416
  }
463
- async function convertFoundryToOsdkObjects(client, ctx, objects) {
464
- const osdkObjects = await Promise.all(objects.map(async object => {
465
- const propertyMapping = await (await (await metadataCacheClient(client)).forObjectByRid(object.type)).getPropertyMapping();
466
- const convertedObject = Object.fromEntries([...Object.entries(object.properties).map(([key, value]) => {
467
- return [propertyMapping?.propertyIdToApiNameMapping[key], value];
468
- }), [propertyMapping?.propertyIdToApiNameMapping[Object.entries(object.key)[0][0]], Object.entries(object.key)[0][1]], ["__apiName", propertyMapping?.apiName], ["$apiName", propertyMapping?.apiName]]);
469
- return convertedObject;
470
- }));
471
- // doesn't care about interfaces
472
- return await convertWireToOsdkObjects(client, osdkObjects, undefined);
473
- }
474
- // Mapping of ObjectRid to Properties
475
- const objectTypeMapping = new WeakMap();
476
- const objectApiNameToRid = new Map();
477
- async function getOntologyPropertyMappingForApiName(client, ctx, objectApiName) {
478
- if (objectApiNameToRid.has(objectApiName)) {
479
- return objectTypeMapping.get(ctx)?.get(objectApiNameToRid.get(objectApiName));
480
- }
481
- const ontologyRid = await client.ontologyRid;
482
- const wireObjectType = await OntologiesV2.ObjectTypesV2.get(client, ontologyRid, objectApiName);
483
- return getOntologyPropertyMappingForRid(ctx, ontologyRid, wireObjectType.rid);
484
- }
485
- let cachedAllOntologies;
486
- async function getOntologyVersionForRid(ctx, ontologyRid) {
487
- cachedAllOntologies ??= await loadAllOntologies(ctx, {});
488
- !cachedAllOntologies.ontologies[ontologyRid] ? invariant(false, "ontology should be loaded") : void 0;
489
- return cachedAllOntologies.ontologies[ontologyRid].currentOntologyVersion;
490
- }
491
- async function getOntologyPropertyMappingForRid(ctx, ontologyRid, objectRid) {
492
- if (!objectTypeMapping.has(ctx)) {
493
- objectTypeMapping.set(ctx, new Map());
494
- }
495
- if (!objectTypeMapping.get(ctx).has(objectRid)) {
496
- const ontologyVersion = await getOntologyVersionForRid(ctx, ontologyRid);
497
- const body = {
498
- datasourceTypes: [],
499
- objectTypes: [{
500
- identifier: {
501
- type: "objectTypeRid",
502
- objectTypeRid: objectRid
503
- },
504
- versionReference: {
505
- type: "ontologyVersion",
506
- ontologyVersion: ontologyVersion
507
- }
508
- }],
509
- linkTypes: [],
510
- sharedPropertyTypes: [],
511
- interfaceTypes: [],
512
- typeGroups: [],
513
- loadRedacted: false,
514
- includeObjectTypeCount: undefined,
515
- includeObjectTypesWithoutSearchableDatasources: true,
516
- includeEntityMetadata: undefined
517
- };
518
- const entities = await bulkLoadOntologyEntities(ctx, undefined, body);
519
- !entities.objectTypes[0]?.objectType ? invariant(false, "object type should be loaded") : void 0;
520
- const propertyIdToApiNameMapping = Object.fromEntries(Object.values(entities.objectTypes[0].objectType.propertyTypes).map(property => {
521
- return [property.id, property.apiName];
522
- }));
523
- const propertyApiNameToIdMapping = Object.fromEntries(Object.values(entities.objectTypes[0].objectType.propertyTypes).map(property => {
524
- return [property.apiName, property.id];
525
- }));
526
- objectTypeMapping.get(ctx)?.set(objectRid, {
527
- apiName: entities.objectTypes[0].objectType.apiName,
528
- id: entities.objectTypes[0].objectType.id,
529
- propertyIdToApiNameMapping,
530
- propertyApiNameToIdMapping
531
- });
532
- objectApiNameToRid.set(entities.objectTypes[0].objectType.apiName, objectRid);
533
- }
534
- return objectTypeMapping.get(ctx)?.get(objectRid);
535
- }
536
417
  //# sourceMappingURL=ObjectSetListenerWebsocket.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ObjectSetListenerWebsocket.js","names":["bulkLoadOntologyEntities","createTemporaryObjectSet","loadAllOntologies","batchEnableWatcher","OntologiesV2","WebSocket","invariant","metadataCacheClient","convertWireToOsdkObjects","getObjectSetBaseType","toConjureObjectSet","ONE_DAY_MS","MINIMUM_RECONNECT_DELAY_MS","doNothing","fillOutListener","onChange","onError","onOutOfDate","isReady","sub","temporaryObjectSetId","subscriptionIsDone","status","ObjectSetListenerWebsocket","instances","WeakMap","OBJECT_SET_EXPIRY_MS","getInstance","client","instance","get","clientCacheKey","set","ws","lastWsConnect","logger","pendingSubscriptions","Map","subscriptions","oswContext","metadataContext","ossContext","maybeDisconnectTimeout","constructor","objectSetExpiryMs","minimumReconnectDelayMs","child","msgPrefix","baseUrl","startsWith","servicePath","fetchFn","fetch","tokenProvider","subscribe","objectSet","listener","globalThis","crypto","webcrypto","subscriptionId","randomUUID","initiateSubscribe","unsubscribe","#initiateSubscribe","process","env","NODE_ENV","trace","expiry","clearTimeout","setTimeout","expire","ontologyRid","temporaryObjectSet","Promise","all","ensureWebsocket","then","baseType","ObjectTypesV2","objectType","enableObjectSetsWatcher","rid","objectSetRid","readyState","OPEN","sendSubscribeMessage","error","#sendSubscribeMessage","readySubs","values","filter","length","id","requests","map","objectSetContext","objectSetFilterContext","parameterOverrides","watchAllLinks","payload","send","JSON","stringify","#expire","subscription","#unsubscribe","newStatus","undefined","delete","size","cycleWebsocket","#ensureWebsocket","base","URL","url","host","token","nextConnectTime","Date","now","resolve","addEventListener","onClose","onMessage","onOpen","CONNECTING","reject","cleanup","removeEventListener","open","evt","#onOpen","message","data","parse","toString","type","handleMessage_objectSetChanged","objectSetChanged","handleMessage_refreshObjectSet","refreshObjectSet","handleMessage_subscribeResponses","subscribeResponses","subscriptionClosed","handleMessage_subscriptionClosed","objects","updates","a","object","convertFoundryToOsdkObjects","responses","subs","i","response","shouldFireOutOfDate","success","#handleMessage_subscriptionClosed","event","#enableObjectSetsWatcher","objectTypeRids","#createTemporaryObjectSet","objectSetBaseType","mcc","objectInfo","forObjectByApiName","propMapping","getPropertyMapping","timeToLive","#cycleWebsocket","CLOSING","CLOSED","close","s","ctx","osdkObjects","propertyMapping","forObjectByRid","convertedObject","Object","fromEntries","entries","properties","key","value","propertyIdToApiNameMapping","apiName","objectTypeMapping","objectApiNameToRid","getOntologyPropertyMappingForApiName","objectApiName","has","wireObjectType","getOntologyPropertyMappingForRid","cachedAllOntologies","getOntologyVersionForRid","ontologies","currentOntologyVersion","objectRid","ontologyVersion","body","datasourceTypes","objectTypes","identifier","objectTypeRid","versionReference","linkTypes","sharedPropertyTypes","interfaceTypes","typeGroups","loadRedacted","includeObjectTypeCount","includeObjectTypesWithoutSearchableDatasources","includeEntityMetadata","entities","propertyTypes","property","propertyApiNameToIdMapping"],"sources":["ObjectSetListenerWebsocket.js"],"sourcesContent":["/*\n * Copyright 2023 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { bulkLoadOntologyEntities, createTemporaryObjectSet, loadAllOntologies, } from \"@osdk/client.unstable\";\nimport { batchEnableWatcher } from \"@osdk/client.unstable.osw\";\nimport * as OntologiesV2 from \"@osdk/internal.foundry.ontologiesv2\";\nimport WebSocket from \"isomorphic-ws\";\nimport invariant from \"tiny-invariant\";\nimport { metadataCacheClient } from \"../__unstable/ConjureSupport.js\";\nimport { convertWireToOsdkObjects } from \"../object/convertWireToOsdkObjects.js\";\nimport { getObjectSetBaseType, toConjureObjectSet, } from \"./toConjureObjectSet.js\";\nconst ONE_DAY_MS = 24 * 60 * 60 * 1000;\nconst MINIMUM_RECONNECT_DELAY_MS = 5 * 1000;\n/** Noop function to reduce conditional checks */\nfunction doNothing() { }\n/**\n * Converts an ObjectSetListener to one where all the functions are defined.\n */\nfunction fillOutListener({ onChange = doNothing, onError = doNothing, onOutOfDate = doNothing }) {\n return { onChange, onError, onOutOfDate };\n}\nfunction isReady(sub) {\n return sub.temporaryObjectSetId != null;\n}\nfunction subscriptionIsDone(sub) {\n return sub.status === \"done\" || sub.status === \"error\";\n}\n/** @internal */\nexport class ObjectSetListenerWebsocket {\n static #instances = new WeakMap();\n OBJECT_SET_EXPIRY_MS;\n MINIMUM_RECONNECT_DELAY_MS;\n // FIXME\n static getInstance(client) {\n let instance = ObjectSetListenerWebsocket.#instances.get(client.clientCacheKey);\n if (instance == null) {\n instance = new ObjectSetListenerWebsocket(client);\n ObjectSetListenerWebsocket.#instances.set(client.clientCacheKey, instance);\n }\n return instance;\n }\n #ws;\n #lastWsConnect = 0;\n #client;\n #logger;\n /**\n * map of requestId to all active subscriptions at the time of the request\n */\n #pendingSubscriptions = new Map();\n /**\n * Map of subscriptionId to Subscription. Note: the subscriptionId may be\n * temporary and not the actual subscriptionId from the server.\n */\n #subscriptions = new Map();\n #oswContext;\n #metadataContext;\n #ossContext;\n #maybeDisconnectTimeout;\n // DO NOT CONSTRUCT DIRECTLY. ONLY EXPOSED AS A TESTING SEAM\n constructor(client, { objectSetExpiryMs = ONE_DAY_MS, minimumReconnectDelayMs = MINIMUM_RECONNECT_DELAY_MS, } = {}) {\n this.OBJECT_SET_EXPIRY_MS = objectSetExpiryMs;\n this.MINIMUM_RECONNECT_DELAY_MS = minimumReconnectDelayMs;\n this.#client = client;\n this.#logger = client.logger?.child({}, {\n msgPrefix: \"<OSW> \",\n });\n invariant(client.baseUrl.startsWith(\"https://\")\n || client.baseUrl.startsWith(\"http://\"), \"Stack must be a URL\");\n this.#oswContext = {\n baseUrl: client.baseUrl,\n servicePath: \"/object-set-watcher/api\",\n fetchFn: client.fetch,\n tokenProvider: async () => await client.tokenProvider(),\n };\n this.#ossContext = {\n ...this.#oswContext,\n servicePath: \"/object-set-service/api\",\n };\n this.#metadataContext = {\n ...this.#oswContext,\n servicePath: \"/ontology-metadata/api\",\n };\n }\n async subscribe(objectSet, listener) {\n if (process.env.TARGET !== \"browser\") {\n // Node 18 does not expose 'crypto' on globalThis, so we need to do it ourselves. This\n // will not be needed after our minimum version is 19 or greater.\n globalThis.crypto ??= (await import(\"node:crypto\")).webcrypto;\n }\n const sub = {\n listener: fillOutListener(listener),\n objectSet,\n status: \"preparing\",\n // Since we don't have a real subscription id yet but we need to keep\n // track of this reference, we can just use a random uuid.\n subscriptionId: `TMP-${crypto.randomUUID()}`,\n };\n this.#subscriptions.set(sub.subscriptionId, sub);\n // actually prepares the subscription, ensures the ws is ready, and sends\n // a subscribe message. We don't want to block on this.\n this.#initiateSubscribe(sub);\n return () => {\n this.#unsubscribe(sub);\n };\n }\n /**\n * Called at least once for every subscription.\n *\n * - Resets pending expiry\n * - Recreates temporary object set\n * - Triggers a full subscribe message\n *\n * @returns\n */\n async #initiateSubscribe(sub) {\n if (process?.env?.NODE_ENV !== \"production\") {\n this.#logger?.trace(\"#initiateSubscribe()\");\n }\n if (sub.expiry) {\n clearTimeout(sub.expiry);\n }\n // expiry is tied to the temporary object set, which is set to `timeToLive: \"ONE_DAY\"`\n // in `#createTemporaryObjectSet`. They should be in sync\n sub.expiry = setTimeout(() => this.#expire(sub), this.OBJECT_SET_EXPIRY_MS);\n const ontologyRid = await this.#client.ontologyRid;\n try {\n const [temporaryObjectSet] = await Promise.all([\n // create a time-bounded object set representation for watching\n this.#createTemporaryObjectSet(sub.objectSet),\n this.#ensureWebsocket(),\n // look up the object type's rid and ensure that we have enabled object set watcher for that rid\n // TODO ???\n getObjectSetBaseType(sub.objectSet).then(baseType => OntologiesV2.ObjectTypesV2.get(this.#client, ontologyRid, baseType)).then(objectType => this.#enableObjectSetsWatcher([objectType.rid])),\n ]);\n // the consumer may have already unsubscribed before we are ready to request a subscription\n // so we have to acquire the pendingSubscription after the await.\n if (subscriptionIsDone(sub)) {\n return;\n }\n // Use new temporary object set id\n sub.temporaryObjectSetId = temporaryObjectSet.objectSetRid;\n // if we aren't open, then this happens after we #onConnect\n if (this.#ws?.readyState === WebSocket.OPEN) {\n this.#sendSubscribeMessage();\n }\n }\n catch (error) {\n this.#logger?.error(error, \"Error in #initiateSubscribe\");\n sub.listener.onError(error);\n }\n }\n #sendSubscribeMessage() {\n if (process?.env?.NODE_ENV !== \"production\") {\n this.#logger?.trace(\"#sendSubscribeMessage()\");\n }\n // If two calls to `.subscribe()` happen at once (or if the connection is reset),\n // we may have multiple subscriptions that don't have a subscriptionId yet,\n // so we filter those out.\n const readySubs = [...this.#subscriptions.values()].filter(isReady);\n if (readySubs.length === 0) {\n if (process?.env?.NODE_ENV !== \"production\") {\n this.#logger?.trace(\"#sendSubscribeMessage(): aborting due to no ready subscriptions\");\n }\n return;\n }\n // Assumes the node 18 crypto fallback to globalThis in `subscribe` has happened.\n const id = crypto.randomUUID();\n // responses come back as an array of subIds, so we need to know the sources\n this.#pendingSubscriptions.set(id, readySubs);\n // every subscribe message \"overwrites\" the previous ones that are not\n // re-included, so we have to reconstitute the entire list of subscriptions\n const subscribe = {\n id,\n requests: readySubs.map(({ temporaryObjectSetId }) => ({\n objectSet: temporaryObjectSetId,\n objectSetContext: {\n objectSetFilterContext: { parameterOverrides: {} },\n },\n watchAllLinks: false,\n })),\n };\n if (process?.env?.NODE_ENV !== \"production\") {\n this.#logger?.trace({ payload: subscribe }, \"sending subscribe message\");\n }\n this.#ws?.send(JSON.stringify(subscribe));\n }\n #expire(sub) {\n if (process?.env?.NODE_ENV !== \"production\") {\n this.#logger?.trace({ subscription: sub }, \"#expire()\");\n }\n // the temporary ObjectSet has expired, we should re-subscribe which will cause the\n // listener to get an onOutOfDate message when it becomes subscribed again\n sub.status = \"expired\";\n this.#initiateSubscribe(sub);\n }\n #unsubscribe(sub, newStatus = \"done\") {\n if (subscriptionIsDone(sub)) {\n // if we are already done, we don't need to do anything\n return;\n }\n sub.status = newStatus;\n // make sure listeners do nothing now\n sub.listener = fillOutListener({});\n if (sub.expiry) {\n clearTimeout(sub.expiry);\n sub.expiry = undefined;\n }\n this.#subscriptions.delete(sub.subscriptionId);\n // If we have no more subscriptions, we can disconnect the websocket\n // however we should wait a bit to see if we get any more subscriptions.\n // For example, when switching between react views, you may unsubscribe\n // in the old view and subscribe in the new view. We don't need to re-establish\n // the websocket connection in that case.\n if (this.#maybeDisconnectTimeout) {\n // We reset the timeout on every unsubscribe so its always at least 15s from\n // the last time we are empty. E.g.:\n // - 0s: Subscribe(A)\n // - 10s: Unsubscribe(A)\n // - 11s: Subscribe(B)\n // - 20s: Unsubscribe(B)\n // If we do not clear out the timeout we would disconnect at 25s but that would only be\n // 5s after the last subscription was removed instead of at 35s for the desired 15s.\n clearTimeout(this.#maybeDisconnectTimeout);\n }\n this.#maybeDisconnectTimeout = setTimeout(() => {\n this.#maybeDisconnectTimeout = undefined;\n if (this.#subscriptions.size === 0) {\n this.#cycleWebsocket();\n }\n }, 15_000 /* ms */);\n }\n async #ensureWebsocket() {\n if (this.#ws == null) {\n const { baseUrl, tokenProvider } = this.#client;\n const base = new URL(baseUrl);\n // TODO: This should be a different endpoint\n const url = `wss://${base.host}/object-set-watcher/ws/subscriptions`;\n const token = await tokenProvider();\n // tokenProvider is async, there could potentially be a race to create the websocket.\n // Only the first call to reach here will find a null this.#ws, the rest will bail out\n if (this.#ws == null) {\n // TODO this can probably be exponential backoff with jitter\n // don't reconnect more quickly than MINIMUM_RECONNECT_DELAY\n const nextConnectTime = (this.#lastWsConnect ?? 0)\n + this.MINIMUM_RECONNECT_DELAY_MS;\n if (nextConnectTime > Date.now()) {\n await new Promise((resolve) => {\n setTimeout(resolve, nextConnectTime - Date.now());\n });\n }\n this.#lastWsConnect = Date.now();\n // we again may have lost the race after our minimum backoff time\n if (this.#ws == null) {\n if (process?.env?.NODE_ENV !== \"production\") {\n this.#logger?.trace(\"Creating websocket\");\n }\n this.#ws = new WebSocket(url, [`Bearer-${token}`]);\n this.#ws.addEventListener(\"close\", this.#onClose);\n this.#ws.addEventListener(\"message\", this.#onMessage);\n this.#ws.addEventListener(\"open\", this.#onOpen);\n }\n }\n // Allow await-ing the websocket open event if it isn't open already.\n // This needs to happen even for callers that didn't just create this.#ws\n if (this.#ws.readyState === WebSocket.CONNECTING) {\n const ws = this.#ws;\n return new Promise((resolve, reject) => {\n function cleanup() {\n ws.removeEventListener(\"open\", open);\n ws.removeEventListener(\"error\", error);\n ws.removeEventListener(\"close\", cleanup);\n }\n function open() {\n cleanup();\n resolve();\n }\n function error(evt) {\n cleanup();\n reject(evt);\n }\n ws.addEventListener(\"open\", open);\n ws.addEventListener(\"error\", error);\n ws.addEventListener(\"close\", cleanup);\n });\n }\n }\n }\n #onOpen = () => {\n // resubscribe all of the listeners\n this.#sendSubscribeMessage();\n };\n #onMessage = async (message) => {\n const data = JSON.parse(message.data.toString());\n if (process?.env?.NODE_ENV !== \"production\") {\n this.#logger?.trace({ payload: data }, \"received message from ws\");\n }\n switch (data.type) {\n case \"objectSetChanged\":\n return this.#handleMessage_objectSetChanged(data.objectSetChanged);\n case \"refreshObjectSet\":\n return this.#handleMessage_refreshObjectSet(data.refreshObjectSet);\n case \"subscribeResponses\":\n return this.#handleMessage_subscribeResponses(data.subscribeResponses);\n case \"subscriptionClosed\": {\n const payload = data.subscriptionClosed;\n return this.#handleMessage_subscriptionClosed(payload);\n }\n default:\n const _ = data;\n invariant(false, \"Unexpected message type\");\n }\n };\n #handleMessage_objectSetChanged = async (payload) => {\n const sub = this.#subscriptions.get(payload.id);\n invariant(sub, `Expected subscription id ${payload.id}`);\n if (\"confidenceValue\" in payload) {\n sub.listener.onOutOfDate();\n return;\n }\n const objects = payload.updates.filter(function (a) {\n return a.type === \"object\";\n }).map(a => a.object);\n invariant(objects.length === payload.updates.length, \"currently only support full updates not reference updates\");\n sub.listener.onChange(await convertFoundryToOsdkObjects(this.#client, this.#metadataContext, objects));\n };\n #handleMessage_refreshObjectSet = (payload) => {\n const sub = this.#subscriptions.get(payload.id);\n invariant(sub, `Expected subscription id ${payload.id}`);\n sub.listener.onOutOfDate();\n };\n #handleMessage_subscribeResponses = (payload) => {\n const { id, responses } = payload;\n const subs = this.#pendingSubscriptions.get(id);\n invariant(subs, `should have a pending subscription for ${id}`);\n this.#pendingSubscriptions.delete(id);\n for (let i = 0; i < responses.length; i++) {\n const sub = subs[i];\n const response = responses[i];\n switch (response.type) {\n case \"error\":\n sub.listener.onError(response.error);\n this.#unsubscribe(sub, \"error\");\n break;\n case \"qos\":\n // the server has requested that we tear down our websocket and reconnect to help load balance\n this.#cycleWebsocket();\n break;\n case \"success\":\n // `\"preparing\"` should only be the status on an initial subscribe.\n const shouldFireOutOfDate = sub.status === \"expired\"\n || sub.status === \"reconnecting\";\n if (process?.env?.NODE_ENV !== \"production\") {\n this.#logger?.trace({ shouldFireOutOfDate }, \"success\");\n }\n sub.status = \"subscribed\";\n if (sub.subscriptionId !== response.success.id) {\n // might be the temporary one\n this.#subscriptions.delete(sub.subscriptionId);\n sub.subscriptionId = response.success.id;\n this.#subscriptions.set(sub.subscriptionId, sub); // future messages come by this subId\n }\n if (shouldFireOutOfDate)\n sub.listener.onOutOfDate();\n break;\n default:\n const _ = response;\n sub.listener.onError(response);\n }\n }\n };\n #handleMessage_subscriptionClosed(payload) {\n const sub = this.#subscriptions.get(payload.id);\n invariant(sub, `Expected subscription id ${payload.id}`);\n sub.listener.onError(payload.error);\n this.#unsubscribe(sub, \"error\");\n }\n #onClose = (event) => {\n if (process?.env?.NODE_ENV !== \"production\") {\n this.#logger?.trace({ event }, \"Received close event from ws\", event);\n }\n // TODO we should probably throttle this so we don't abuse the backend\n this.#cycleWebsocket();\n };\n async #enableObjectSetsWatcher(objectTypeRids) {\n return batchEnableWatcher(this.#oswContext, {\n requests: objectTypeRids,\n });\n }\n async #createTemporaryObjectSet(objectSet) {\n const objectSetBaseType = await getObjectSetBaseType(objectSet);\n const mcc = await metadataCacheClient(this.#client);\n const objectInfo = await mcc.forObjectByApiName(objectSetBaseType);\n const propMapping = await objectInfo.getPropertyMapping();\n const temporaryObjectSet = await createTemporaryObjectSet(this.#ossContext, {\n objectSet: toConjureObjectSet(objectSet, propMapping),\n timeToLive: \"ONE_DAY\", // MUST keep in sync with the value for expiry in `#initiateSubscribe`.\n objectSetFilterContext: { parameterOverrides: {} },\n });\n return { objectSetRid: temporaryObjectSet.objectSetRid };\n }\n #cycleWebsocket = () => {\n if (this.#ws) {\n this.#ws.removeEventListener(\"open\", this.#onOpen);\n this.#ws.removeEventListener(\"message\", this.#onMessage);\n this.#ws.removeEventListener(\"close\", this.#onClose);\n if (this.#ws.readyState !== WebSocket.CLOSING\n && this.#ws.readyState !== WebSocket.CLOSED) {\n this.#ws.close();\n }\n this.#ws = undefined;\n }\n // if we have any listeners that are still depending on us, go ahead and reopen the websocket\n if (this.#subscriptions.size > 0) {\n if (process?.env?.NODE_ENV !== \"production\") {\n for (const s of this.#subscriptions.values()) {\n invariant(s.status !== \"done\" && s.status !== \"error\", \"should not have done/error subscriptions still\");\n }\n }\n for (const s of this.#subscriptions.values()) {\n if (s.status === \"subscribed\")\n s.status = \"reconnecting\";\n }\n this.#ensureWebsocket();\n }\n };\n}\nasync function convertFoundryToOsdkObjects(client, ctx, objects) {\n const osdkObjects = await Promise.all(objects.map(async (object) => {\n const propertyMapping = await (await (await metadataCacheClient(client))\n .forObjectByRid(object.type))\n .getPropertyMapping();\n const convertedObject = Object.fromEntries([\n ...Object.entries(object.properties).map(([key, value]) => {\n return [propertyMapping?.propertyIdToApiNameMapping[key], value];\n }),\n [\n propertyMapping\n ?.propertyIdToApiNameMapping[Object.entries(object.key)[0][0]],\n Object.entries(object.key)[0][1],\n ],\n [\n \"__apiName\",\n propertyMapping?.apiName,\n ],\n [\n \"$apiName\",\n propertyMapping?.apiName,\n ],\n ]);\n return convertedObject;\n }));\n // doesn't care about interfaces\n return await convertWireToOsdkObjects(client, osdkObjects, undefined);\n}\n// Mapping of ObjectRid to Properties\nconst objectTypeMapping = new WeakMap();\nconst objectApiNameToRid = new Map();\nasync function getOntologyPropertyMappingForApiName(client, ctx, objectApiName) {\n if (objectApiNameToRid.has(objectApiName)) {\n return objectTypeMapping.get(ctx)?.get(objectApiNameToRid.get(objectApiName));\n }\n const ontologyRid = await client.ontologyRid;\n const wireObjectType = await OntologiesV2.ObjectTypesV2\n .get(client, ontologyRid, objectApiName);\n return getOntologyPropertyMappingForRid(ctx, ontologyRid, wireObjectType.rid);\n}\nlet cachedAllOntologies;\nasync function getOntologyVersionForRid(ctx, ontologyRid) {\n cachedAllOntologies ??= await loadAllOntologies(ctx, {});\n invariant(cachedAllOntologies.ontologies[ontologyRid], \"ontology should be loaded\");\n return cachedAllOntologies.ontologies[ontologyRid].currentOntologyVersion;\n}\nasync function getOntologyPropertyMappingForRid(ctx, ontologyRid, objectRid) {\n if (!objectTypeMapping.has(ctx)) {\n objectTypeMapping.set(ctx, new Map());\n }\n if (!objectTypeMapping.get(ctx).has(objectRid)) {\n const ontologyVersion = await getOntologyVersionForRid(ctx, ontologyRid);\n const body = {\n datasourceTypes: [],\n objectTypes: [{\n identifier: {\n type: \"objectTypeRid\",\n objectTypeRid: objectRid,\n },\n versionReference: {\n type: \"ontologyVersion\",\n ontologyVersion: ontologyVersion,\n },\n }],\n linkTypes: [],\n sharedPropertyTypes: [],\n interfaceTypes: [],\n typeGroups: [],\n loadRedacted: false,\n includeObjectTypeCount: undefined,\n includeObjectTypesWithoutSearchableDatasources: true,\n includeEntityMetadata: undefined,\n };\n const entities = await bulkLoadOntologyEntities(ctx, undefined, body);\n invariant(entities.objectTypes[0]?.objectType, \"object type should be loaded\");\n const propertyIdToApiNameMapping = Object\n .fromEntries(Object.values(entities.objectTypes[0].objectType.propertyTypes).map(property => {\n return [property.id, property.apiName];\n }));\n const propertyApiNameToIdMapping = Object\n .fromEntries(Object.values(entities.objectTypes[0].objectType.propertyTypes).map(property => {\n return [property.apiName, property.id];\n }));\n objectTypeMapping.get(ctx)?.set(objectRid, {\n apiName: entities.objectTypes[0].objectType.apiName,\n id: entities.objectTypes[0].objectType.id,\n propertyIdToApiNameMapping,\n propertyApiNameToIdMapping,\n });\n objectApiNameToRid.set(entities.objectTypes[0].objectType.apiName, objectRid);\n }\n return objectTypeMapping.get(ctx)?.get(objectRid);\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,wBAAwB,EAAEC,wBAAwB,EAAEC,iBAAiB,QAAS,uBAAuB;AAC9G,SAASC,kBAAkB,QAAQ,2BAA2B;AAC9D,OAAO,KAAKC,YAAY,MAAM,qCAAqC;AACnE,OAAOC,SAAS,MAAM,eAAe;AACrC,OAAOC,SAAS,MAAM,gBAAgB;AACtC,SAASC,mBAAmB,QAAQ,iCAAiC;AACrE,SAASC,wBAAwB,QAAQ,uCAAuC;AAChF,SAASC,oBAAoB,EAAEC,kBAAkB,QAAS,yBAAyB;AACnF,MAAMC,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI;AACtC,MAAMC,0BAA0B,GAAG,CAAC,GAAG,IAAI;AAC3C;AACA,SAASC,SAASA,CAAA,EAAG,CAAE;AACvB;AACA;AACA;AACA,SAASC,eAAeA,CAAC;EAAEC,QAAQ,GAAGF,SAAS;EAAEG,OAAO,GAAGH,SAAS;EAAEI,WAAW,GAAGJ;AAAU,CAAC,EAAE;EAC7F,OAAO;IAAEE,QAAQ;IAAEC,OAAO;IAAEC;EAAY,CAAC;AAC7C;AACA,SAASC,OAAOA,CAACC,GAAG,EAAE;EAClB,OAAOA,GAAG,CAACC,oBAAoB,IAAI,IAAI;AAC3C;AACA,SAASC,kBAAkBA,CAACF,GAAG,EAAE;EAC7B,OAAOA,GAAG,CAACG,MAAM,KAAK,MAAM,IAAIH,GAAG,CAACG,MAAM,KAAK,OAAO;AAC1D;AACA;AACA,OAAO,MAAMC,0BAA0B,CAAC;EACpC,OAAO,CAACC,SAAS,GAAG,IAAIC,OAAO,CAAC,CAAC;EACjCC,oBAAoB;EACpBd,0BAA0B;EAC1B;EACA,OAAOe,WAAWA,CAACC,MAAM,EAAE;IACvB,IAAIC,QAAQ,GAAGN,0BAA0B,CAAC,CAACC,SAAS,CAACM,GAAG,CAACF,MAAM,CAACG,cAAc,CAAC;IAC/E,IAAIF,QAAQ,IAAI,IAAI,EAAE;MAClBA,QAAQ,GAAG,IAAIN,0BAA0B,CAACK,MAAM,CAAC;MACjDL,0BAA0B,CAAC,CAACC,SAAS,CAACQ,GAAG,CAACJ,MAAM,CAACG,cAAc,EAAEF,QAAQ,CAAC;IAC9E;IACA,OAAOA,QAAQ;EACnB;EACA,CAACI,EAAE;EACH,CAACC,aAAa,GAAG,CAAC;EAClB,CAACN,MAAM;EACP,CAACO,MAAM;EACP;AACJ;AACA;EACI,CAACC,oBAAoB,GAAG,IAAIC,GAAG,CAAC,CAAC;EACjC;AACJ;AACA;AACA;EACI,CAACC,aAAa,GAAG,IAAID,GAAG,CAAC,CAAC;EAC1B,CAACE,UAAU;EACX,CAACC,eAAe;EAChB,CAACC,UAAU;EACX,CAACC,sBAAsB;EACvB;EACAC,WAAWA,CAACf,MAAM,EAAE;IAAEgB,iBAAiB,GAAGjC,UAAU;IAAEkC,uBAAuB,GAAGjC;EAA4B,CAAC,GAAG,CAAC,CAAC,EAAE;IAChH,IAAI,CAACc,oBAAoB,GAAGkB,iBAAiB;IAC7C,IAAI,CAAChC,0BAA0B,GAAGiC,uBAAuB;IACzD,IAAI,CAAC,CAACjB,MAAM,GAAGA,MAAM;IACrB,IAAI,CAAC,CAACO,MAAM,GAAGP,MAAM,CAACO,MAAM,EAAEW,KAAK,CAAC,CAAC,CAAC,EAAE;MACpCC,SAAS,EAAE;IACf,CAAC,CAAC;IACF,EAAUnB,MAAM,CAACoB,OAAO,CAACC,UAAU,CAAC,UAAU,CAAC,IACxCrB,MAAM,CAACoB,OAAO,CAACC,UAAU,CAAC,SAAS,CAAC,IAD3C3C,SAAS,QACoC,qBAAqB;IAClE,IAAI,CAAC,CAACiC,UAAU,GAAG;MACfS,OAAO,EAAEpB,MAAM,CAACoB,OAAO;MACvBE,WAAW,EAAE,yBAAyB;MACtCC,OAAO,EAAEvB,MAAM,CAACwB,KAAK;MACrBC,aAAa,EAAE,MAAAA,CAAA,KAAY,MAAMzB,MAAM,CAACyB,aAAa,CAAC;IAC1D,CAAC;IACD,IAAI,CAAC,CAACZ,UAAU,GAAG;MACf,GAAG,IAAI,CAAC,CAACF,UAAU;MACnBW,WAAW,EAAE;IACjB,CAAC;IACD,IAAI,CAAC,CAACV,eAAe,GAAG;MACpB,GAAG,IAAI,CAAC,CAACD,UAAU;MACnBW,WAAW,EAAE;IACjB,CAAC;EACL;EACA,MAAMI,SAASA,CAACC,SAAS,EAAEC,QAAQ,EAAE;IAE7B;IACA;IACAC,UAAU,CAACC,MAAM,KAAK,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC,EAAEC,SAAS;IAEjE,MAAMxC,GAAG,GAAG;MACRqC,QAAQ,EAAE1C,eAAe,CAAC0C,QAAQ,CAAC;MACnCD,SAAS;MACTjC,MAAM,EAAE,WAAW;MACnB;MACA;MACAsC,cAAc,EAAE,OAAOF,MAAM,CAACG,UAAU,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,CAAC,CAACvB,aAAa,CAACN,GAAG,CAACb,GAAG,CAACyC,cAAc,EAAEzC,GAAG,CAAC;IAChD;IACA;IACA,IAAI,CAAC,CAAC2C,iBAAiB,CAAC3C,GAAG,CAAC;IAC5B,OAAO,MAAM;MACT,IAAI,CAAC,CAAC4C,WAAW,CAAC5C,GAAG,CAAC;IAC1B,CAAC;EACL;EACA;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACI,MAAM,CAAC2C,iBAAiBE,CAAC7C,GAAG,EAAE;IAC1B,IAAI8C,OAAO,EAAEC,GAAG,EAAEC,QAAQ,KAAK,YAAY,EAAE;MACzC,IAAI,CAAC,CAAChC,MAAM,EAAEiC,KAAK,CAAC,sBAAsB,CAAC;IAC/C;IACA,IAAIjD,GAAG,CAACkD,MAAM,EAAE;MACZC,YAAY,CAACnD,GAAG,CAACkD,MAAM,CAAC;IAC5B;IACA;IACA;IACAlD,GAAG,CAACkD,MAAM,GAAGE,UAAU,CAAC,MAAM,IAAI,CAAC,CAACC,MAAM,CAACrD,GAAG,CAAC,EAAE,IAAI,CAACO,oBAAoB,CAAC;IAC3E,MAAM+C,WAAW,GAAG,MAAM,IAAI,CAAC,CAAC7C,MAAM,CAAC6C,WAAW;IAClD,IAAI;MACA,MAAM,CAACC,kBAAkB,CAAC,GAAG,MAAMC,OAAO,CAACC,GAAG,CAAC;MAC3C;MACA,IAAI,CAAC,CAAC3E,wBAAwB,CAACkB,GAAG,CAACoC,SAAS,CAAC,EAC7C,IAAI,CAAC,CAACsB,eAAe,CAAC,CAAC;MACvB;MACA;MACApE,oBAAoB,CAACU,GAAG,CAACoC,SAAS,CAAC,CAACuB,IAAI,CAACC,QAAQ,IAAI3E,YAAY,CAAC4E,aAAa,CAAClD,GAAG,CAAC,IAAI,CAAC,CAACF,MAAM,EAAE6C,WAAW,EAAEM,QAAQ,CAAC,CAAC,CAACD,IAAI,CAACG,UAAU,IAAI,IAAI,CAAC,CAACC,uBAAuB,CAAC,CAACD,UAAU,CAACE,GAAG,CAAC,CAAC,CAAC,CAChM,CAAC;MACF;MACA;MACA,IAAI9D,kBAAkB,CAACF,GAAG,CAAC,EAAE;QACzB;MACJ;MACA;MACAA,GAAG,CAACC,oBAAoB,GAAGsD,kBAAkB,CAACU,YAAY;MAC1D;MACA,IAAI,IAAI,CAAC,CAACnD,EAAE,EAAEoD,UAAU,KAAKhF,SAAS,CAACiF,IAAI,EAAE;QACzC,IAAI,CAAC,CAACC,oBAAoB,CAAC,CAAC;MAChC;IACJ,CAAC,CACD,OAAOC,KAAK,EAAE;MACV,IAAI,CAAC,CAACrD,MAAM,EAAEqD,KAAK,CAACA,KAAK,EAAE,6BAA6B,CAAC;MACzDrE,GAAG,CAACqC,QAAQ,CAACxC,OAAO,CAACwE,KAAK,CAAC;IAC/B;EACJ;EACA,CAACD,oBAAoBE,CAAA,EAAG;IACpB,IAAIxB,OAAO,EAAEC,GAAG,EAAEC,QAAQ,KAAK,YAAY,EAAE;MACzC,IAAI,CAAC,CAAChC,MAAM,EAAEiC,KAAK,CAAC,yBAAyB,CAAC;IAClD;IACA;IACA;IACA;IACA,MAAMsB,SAAS,GAAG,CAAC,GAAG,IAAI,CAAC,CAACpD,aAAa,CAACqD,MAAM,CAAC,CAAC,CAAC,CAACC,MAAM,CAAC1E,OAAO,CAAC;IACnE,IAAIwE,SAAS,CAACG,MAAM,KAAK,CAAC,EAAE;MACxB,IAAI5B,OAAO,EAAEC,GAAG,EAAEC,QAAQ,KAAK,YAAY,EAAE;QACzC,IAAI,CAAC,CAAChC,MAAM,EAAEiC,KAAK,CAAC,iEAAiE,CAAC;MAC1F;MACA;IACJ;IACA;IACA,MAAM0B,EAAE,GAAGpC,MAAM,CAACG,UAAU,CAAC,CAAC;IAC9B;IACA,IAAI,CAAC,CAACzB,oBAAoB,CAACJ,GAAG,CAAC8D,EAAE,EAAEJ,SAAS,CAAC;IAC7C;IACA;IACA,MAAMpC,SAAS,GAAG;MACdwC,EAAE;MACFC,QAAQ,EAAEL,SAAS,CAACM,GAAG,CAAC,CAAC;QAAE5E;MAAqB,CAAC,MAAM;QACnDmC,SAAS,EAAEnC,oBAAoB;QAC/B6E,gBAAgB,EAAE;UACdC,sBAAsB,EAAE;YAAEC,kBAAkB,EAAE,CAAC;UAAE;QACrD,CAAC;QACDC,aAAa,EAAE;MACnB,CAAC,CAAC;IACN,CAAC;IACD,IAAInC,OAAO,EAAEC,GAAG,EAAEC,QAAQ,KAAK,YAAY,EAAE;MACzC,IAAI,CAAC,CAAChC,MAAM,EAAEiC,KAAK,CAAC;QAAEiC,OAAO,EAAE/C;MAAU,CAAC,EAAE,2BAA2B,CAAC;IAC5E;IACA,IAAI,CAAC,CAACrB,EAAE,EAAEqE,IAAI,CAACC,IAAI,CAACC,SAAS,CAAClD,SAAS,CAAC,CAAC;EAC7C;EACA,CAACkB,MAAMiC,CAACtF,GAAG,EAAE;IACT,IAAI8C,OAAO,EAAEC,GAAG,EAAEC,QAAQ,KAAK,YAAY,EAAE;MACzC,IAAI,CAAC,CAAChC,MAAM,EAAEiC,KAAK,CAAC;QAAEsC,YAAY,EAAEvF;MAAI,CAAC,EAAE,WAAW,CAAC;IAC3D;IACA;IACA;IACAA,GAAG,CAACG,MAAM,GAAG,SAAS;IACtB,IAAI,CAAC,CAACwC,iBAAiB,CAAC3C,GAAG,CAAC;EAChC;EACA,CAAC4C,WAAW4C,CAACxF,GAAG,EAAEyF,SAAS,GAAG,MAAM,EAAE;IAClC,IAAIvF,kBAAkB,CAACF,GAAG,CAAC,EAAE;MACzB;MACA;IACJ;IACAA,GAAG,CAACG,MAAM,GAAGsF,SAAS;IACtB;IACAzF,GAAG,CAACqC,QAAQ,GAAG1C,eAAe,CAAC,CAAC,CAAC,CAAC;IAClC,IAAIK,GAAG,CAACkD,MAAM,EAAE;MACZC,YAAY,CAACnD,GAAG,CAACkD,MAAM,CAAC;MACxBlD,GAAG,CAACkD,MAAM,GAAGwC,SAAS;IAC1B;IACA,IAAI,CAAC,CAACvE,aAAa,CAACwE,MAAM,CAAC3F,GAAG,CAACyC,cAAc,CAAC;IAC9C;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,CAAClB,sBAAsB,EAAE;MAC9B;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA4B,YAAY,CAAC,IAAI,CAAC,CAAC5B,sBAAsB,CAAC;IAC9C;IACA,IAAI,CAAC,CAACA,sBAAsB,GAAG6B,UAAU,CAAC,MAAM;MAC5C,IAAI,CAAC,CAAC7B,sBAAsB,GAAGmE,SAAS;MACxC,IAAI,IAAI,CAAC,CAACvE,aAAa,CAACyE,IAAI,KAAK,CAAC,EAAE;QAChC,IAAI,CAAC,CAACC,cAAc,CAAC,CAAC;MAC1B;IACJ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;EACvB;EACA,MAAM,CAACnC,eAAeoC,CAAA,EAAG;IACrB,IAAI,IAAI,CAAC,CAAChF,EAAE,IAAI,IAAI,EAAE;MAClB,MAAM;QAAEe,OAAO;QAAEK;MAAc,CAAC,GAAG,IAAI,CAAC,CAACzB,MAAM;MAC/C,MAAMsF,IAAI,GAAG,IAAIC,GAAG,CAACnE,OAAO,CAAC;MAC7B;MACA,MAAMoE,GAAG,GAAG,SAASF,IAAI,CAACG,IAAI,sCAAsC;MACpE,MAAMC,KAAK,GAAG,MAAMjE,aAAa,CAAC,CAAC;MACnC;MACA;MACA,IAAI,IAAI,CAAC,CAACpB,EAAE,IAAI,IAAI,EAAE;QAClB;QACA;QACA,MAAMsF,eAAe,GAAG,CAAC,IAAI,CAAC,CAACrF,aAAa,IAAI,CAAC,IAC3C,IAAI,CAACtB,0BAA0B;QACrC,IAAI2G,eAAe,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC,EAAE;UAC9B,MAAM,IAAI9C,OAAO,CAAE+C,OAAO,IAAK;YAC3BnD,UAAU,CAACmD,OAAO,EAAEH,eAAe,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC,CAAC;UACrD,CAAC,CAAC;QACN;QACA,IAAI,CAAC,CAACvF,aAAa,GAAGsF,IAAI,CAACC,GAAG,CAAC,CAAC;QAChC;QACA,IAAI,IAAI,CAAC,CAACxF,EAAE,IAAI,IAAI,EAAE;UAClB,IAAIgC,OAAO,EAAEC,GAAG,EAAEC,QAAQ,KAAK,YAAY,EAAE;YACzC,IAAI,CAAC,CAAChC,MAAM,EAAEiC,KAAK,CAAC,oBAAoB,CAAC;UAC7C;UACA,IAAI,CAAC,CAACnC,EAAE,GAAG,IAAI5B,SAAS,CAAC+G,GAAG,EAAE,CAAC,UAAUE,KAAK,EAAE,CAAC,CAAC;UAClD,IAAI,CAAC,CAACrF,EAAE,CAAC0F,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,CAACC,OAAO,CAAC;UACjD,IAAI,CAAC,CAAC3F,EAAE,CAAC0F,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,CAACE,SAAS,CAAC;UACrD,IAAI,CAAC,CAAC5F,EAAE,CAAC0F,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAACG,MAAM,CAAC;QACnD;MACJ;MACA;MACA;MACA,IAAI,IAAI,CAAC,CAAC7F,EAAE,CAACoD,UAAU,KAAKhF,SAAS,CAAC0H,UAAU,EAAE;QAC9C,MAAM9F,EAAE,GAAG,IAAI,CAAC,CAACA,EAAE;QACnB,OAAO,IAAI0C,OAAO,CAAC,CAAC+C,OAAO,EAAEM,MAAM,KAAK;UACpC,SAASC,OAAOA,CAAA,EAAG;YACfhG,EAAE,CAACiG,mBAAmB,CAAC,MAAM,EAAEC,IAAI,CAAC;YACpClG,EAAE,CAACiG,mBAAmB,CAAC,OAAO,EAAE1C,KAAK,CAAC;YACtCvD,EAAE,CAACiG,mBAAmB,CAAC,OAAO,EAAED,OAAO,CAAC;UAC5C;UACA,SAASE,IAAIA,CAAA,EAAG;YACZF,OAAO,CAAC,CAAC;YACTP,OAAO,CAAC,CAAC;UACb;UACA,SAASlC,KAAKA,CAAC4C,GAAG,EAAE;YAChBH,OAAO,CAAC,CAAC;YACTD,MAAM,CAACI,GAAG,CAAC;UACf;UACAnG,EAAE,CAAC0F,gBAAgB,CAAC,MAAM,EAAEQ,IAAI,CAAC;UACjClG,EAAE,CAAC0F,gBAAgB,CAAC,OAAO,EAAEnC,KAAK,CAAC;UACnCvD,EAAE,CAAC0F,gBAAgB,CAAC,OAAO,EAAEM,OAAO,CAAC;QACzC,CAAC,CAAC;MACN;IACJ;EACJ;EACA,CAACH,MAAM,GAAGO,CAAA,KAAM;IACZ;IACA,IAAI,CAAC,CAAC9C,oBAAoB,CAAC,CAAC;EAChC,CAAC;EACD,CAACsC,SAAS,GAAG,MAAOS,OAAO,IAAK;IAC5B,MAAMC,IAAI,GAAGhC,IAAI,CAACiC,KAAK,CAACF,OAAO,CAACC,IAAI,CAACE,QAAQ,CAAC,CAAC,CAAC;IAChD,IAAIxE,OAAO,EAAEC,GAAG,EAAEC,QAAQ,KAAK,YAAY,EAAE;MACzC,IAAI,CAAC,CAAChC,MAAM,EAAEiC,KAAK,CAAC;QAAEiC,OAAO,EAAEkC;MAAK,CAAC,EAAE,0BAA0B,CAAC;IACtE;IACA,QAAQA,IAAI,CAACG,IAAI;MACb,KAAK,kBAAkB;QACnB,OAAO,IAAI,CAAC,CAACC,8BAA8B,CAACJ,IAAI,CAACK,gBAAgB,CAAC;MACtE,KAAK,kBAAkB;QACnB,OAAO,IAAI,CAAC,CAACC,8BAA8B,CAACN,IAAI,CAACO,gBAAgB,CAAC;MACtE,KAAK,oBAAoB;QACrB,OAAO,IAAI,CAAC,CAACC,gCAAgC,CAACR,IAAI,CAACS,kBAAkB,CAAC;MAC1E,KAAK,oBAAoB;QAAE;UACvB,MAAM3C,OAAO,GAAGkC,IAAI,CAACU,kBAAkB;UACvC,OAAO,IAAI,CAAC,CAACC,gCAAgC,CAAC7C,OAAO,CAAC;QAC1D;MACA;QAEI/F,SAAS,QAAQ,yBAAyB;IAClD;EACJ,CAAC;EACD,CAACqI,8BAA8B,GAAG,MAAOtC,OAAO,IAAK;IACjD,MAAMlF,GAAG,GAAG,IAAI,CAAC,CAACmB,aAAa,CAACR,GAAG,CAACuE,OAAO,CAACP,EAAE,CAAC;IAC/C,CAAU3E,GAAG,GAAbb,SAAS,QAAM,4BAA4B+F,OAAO,CAACP,EAAE,EAAE;IACvD,IAAI,iBAAiB,IAAIO,OAAO,EAAE;MAC9BlF,GAAG,CAACqC,QAAQ,CAACvC,WAAW,CAAC,CAAC;MAC1B;IACJ;IACA,MAAMkI,OAAO,GAAG9C,OAAO,CAAC+C,OAAO,CAACxD,MAAM,CAAC,UAAUyD,CAAC,EAAE;MAChD,OAAOA,CAAC,CAACX,IAAI,KAAK,QAAQ;IAC9B,CAAC,CAAC,CAAC1C,GAAG,CAACqD,CAAC,IAAIA,CAAC,CAACC,MAAM,CAAC;IACrB,EAAUH,OAAO,CAACtD,MAAM,KAAKQ,OAAO,CAAC+C,OAAO,CAACvD,MAAM,IAAnDvF,SAAS,QAA4C,2DAA2D;IAChHa,GAAG,CAACqC,QAAQ,CAACzC,QAAQ,CAAC,MAAMwI,2BAA2B,CAAC,IAAI,CAAC,CAAC3H,MAAM,EAAE,IAAI,CAAC,CAACY,eAAe,EAAE2G,OAAO,CAAC,CAAC;EAC1G,CAAC;EACD,CAACN,8BAA8B,GAAIxC,OAAO,IAAK;IAC3C,MAAMlF,GAAG,GAAG,IAAI,CAAC,CAACmB,aAAa,CAACR,GAAG,CAACuE,OAAO,CAACP,EAAE,CAAC;IAC/C,CAAU3E,GAAG,GAAbb,SAAS,QAAM,4BAA4B+F,OAAO,CAACP,EAAE,EAAE;IACvD3E,GAAG,CAACqC,QAAQ,CAACvC,WAAW,CAAC,CAAC;EAC9B,CAAC;EACD,CAAC8H,gCAAgC,GAAI1C,OAAO,IAAK;IAC7C,MAAM;MAAEP,EAAE;MAAE0D;IAAU,CAAC,GAAGnD,OAAO;IACjC,MAAMoD,IAAI,GAAG,IAAI,CAAC,CAACrH,oBAAoB,CAACN,GAAG,CAACgE,EAAE,CAAC;IAC/C,CAAU2D,IAAI,GAAdnJ,SAAS,QAAO,0CAA0CwF,EAAE,EAAE;IAC9D,IAAI,CAAC,CAAC1D,oBAAoB,CAAC0E,MAAM,CAAChB,EAAE,CAAC;IACrC,KAAK,IAAI4D,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGF,SAAS,CAAC3D,MAAM,EAAE6D,CAAC,EAAE,EAAE;MACvC,MAAMvI,GAAG,GAAGsI,IAAI,CAACC,CAAC,CAAC;MACnB,MAAMC,QAAQ,GAAGH,SAAS,CAACE,CAAC,CAAC;MAC7B,QAAQC,QAAQ,CAACjB,IAAI;QACjB,KAAK,OAAO;UACRvH,GAAG,CAACqC,QAAQ,CAACxC,OAAO,CAAC2I,QAAQ,CAACnE,KAAK,CAAC;UACpC,IAAI,CAAC,CAACzB,WAAW,CAAC5C,GAAG,EAAE,OAAO,CAAC;UAC/B;QACJ,KAAK,KAAK;UACN;UACA,IAAI,CAAC,CAAC6F,cAAc,CAAC,CAAC;UACtB;QACJ,KAAK,SAAS;UACV;UACA,MAAM4C,mBAAmB,GAAGzI,GAAG,CAACG,MAAM,KAAK,SAAS,IAC7CH,GAAG,CAACG,MAAM,KAAK,cAAc;UACpC,IAAI2C,OAAO,EAAEC,GAAG,EAAEC,QAAQ,KAAK,YAAY,EAAE;YACzC,IAAI,CAAC,CAAChC,MAAM,EAAEiC,KAAK,CAAC;cAAEwF;YAAoB,CAAC,EAAE,SAAS,CAAC;UAC3D;UACAzI,GAAG,CAACG,MAAM,GAAG,YAAY;UACzB,IAAIH,GAAG,CAACyC,cAAc,KAAK+F,QAAQ,CAACE,OAAO,CAAC/D,EAAE,EAAE;YAC5C;YACA,IAAI,CAAC,CAACxD,aAAa,CAACwE,MAAM,CAAC3F,GAAG,CAACyC,cAAc,CAAC;YAC9CzC,GAAG,CAACyC,cAAc,GAAG+F,QAAQ,CAACE,OAAO,CAAC/D,EAAE;YACxC,IAAI,CAAC,CAACxD,aAAa,CAACN,GAAG,CAACb,GAAG,CAACyC,cAAc,EAAEzC,GAAG,CAAC,CAAC,CAAC;UACtD;UACA,IAAIyI,mBAAmB,EACnBzI,GAAG,CAACqC,QAAQ,CAACvC,WAAW,CAAC,CAAC;UAC9B;QACJ;UAEIE,GAAG,CAACqC,QAAQ,CAACxC,OAAO,CAAC2I,QAAQ,CAAC;MACtC;IACJ;EACJ,CAAC;EACD,CAACT,gCAAgCY,CAACzD,OAAO,EAAE;IACvC,MAAMlF,GAAG,GAAG,IAAI,CAAC,CAACmB,aAAa,CAACR,GAAG,CAACuE,OAAO,CAACP,EAAE,CAAC;IAC/C,CAAU3E,GAAG,GAAbb,SAAS,QAAM,4BAA4B+F,OAAO,CAACP,EAAE,EAAE;IACvD3E,GAAG,CAACqC,QAAQ,CAACxC,OAAO,CAACqF,OAAO,CAACb,KAAK,CAAC;IACnC,IAAI,CAAC,CAACzB,WAAW,CAAC5C,GAAG,EAAE,OAAO,CAAC;EACnC;EACA,CAACyG,OAAO,GAAImC,KAAK,IAAK;IAClB,IAAI9F,OAAO,EAAEC,GAAG,EAAEC,QAAQ,KAAK,YAAY,EAAE;MACzC,IAAI,CAAC,CAAChC,MAAM,EAAEiC,KAAK,CAAC;QAAE2F;MAAM,CAAC,EAAE,8BAA8B,EAAEA,KAAK,CAAC;IACzE;IACA;IACA,IAAI,CAAC,CAAC/C,cAAc,CAAC,CAAC;EAC1B,CAAC;EACD,MAAM,CAAC9B,uBAAuB8E,CAACC,cAAc,EAAE;IAC3C,OAAO9J,kBAAkB,CAAC,IAAI,CAAC,CAACoC,UAAU,EAAE;MACxCwD,QAAQ,EAAEkE;IACd,CAAC,CAAC;EACN;EACA,MAAM,CAAChK,wBAAwBiK,CAAC3G,SAAS,EAAE;IACvC,MAAM4G,iBAAiB,GAAG,MAAM1J,oBAAoB,CAAC8C,SAAS,CAAC;IAC/D,MAAM6G,GAAG,GAAG,MAAM7J,mBAAmB,CAAC,IAAI,CAAC,CAACqB,MAAM,CAAC;IACnD,MAAMyI,UAAU,GAAG,MAAMD,GAAG,CAACE,kBAAkB,CAACH,iBAAiB,CAAC;IAClE,MAAMI,WAAW,GAAG,MAAMF,UAAU,CAACG,kBAAkB,CAAC,CAAC;IACzD,MAAM9F,kBAAkB,GAAG,MAAMzE,wBAAwB,CAAC,IAAI,CAAC,CAACwC,UAAU,EAAE;MACxEc,SAAS,EAAE7C,kBAAkB,CAAC6C,SAAS,EAAEgH,WAAW,CAAC;MACrDE,UAAU,EAAE,SAAS;MAAE;MACvBvE,sBAAsB,EAAE;QAAEC,kBAAkB,EAAE,CAAC;MAAE;IACrD,CAAC,CAAC;IACF,OAAO;MAAEf,YAAY,EAAEV,kBAAkB,CAACU;IAAa,CAAC;EAC5D;EACA,CAAC4B,cAAc,GAAG0D,CAAA,KAAM;IACpB,IAAI,IAAI,CAAC,CAACzI,EAAE,EAAE;MACV,IAAI,CAAC,CAACA,EAAE,CAACiG,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,CAACJ,MAAM,CAAC;MAClD,IAAI,CAAC,CAAC7F,EAAE,CAACiG,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,CAACL,SAAS,CAAC;MACxD,IAAI,CAAC,CAAC5F,EAAE,CAACiG,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,CAACN,OAAO,CAAC;MACpD,IAAI,IAAI,CAAC,CAAC3F,EAAE,CAACoD,UAAU,KAAKhF,SAAS,CAACsK,OAAO,IACtC,IAAI,CAAC,CAAC1I,EAAE,CAACoD,UAAU,KAAKhF,SAAS,CAACuK,MAAM,EAAE;QAC7C,IAAI,CAAC,CAAC3I,EAAE,CAAC4I,KAAK,CAAC,CAAC;MACpB;MACA,IAAI,CAAC,CAAC5I,EAAE,GAAG4E,SAAS;IACxB;IACA;IACA,IAAI,IAAI,CAAC,CAACvE,aAAa,CAACyE,IAAI,GAAG,CAAC,EAAE;MAC9B,IAAI9C,OAAO,EAAEC,GAAG,EAAEC,QAAQ,KAAK,YAAY,EAAE;QACzC,KAAK,MAAM2G,CAAC,IAAI,IAAI,CAAC,CAACxI,aAAa,CAACqD,MAAM,CAAC,CAAC,EAAE;UAC1C,EAAUmF,CAAC,CAACxJ,MAAM,KAAK,MAAM,IAAIwJ,CAAC,CAACxJ,MAAM,KAAK,OAAO,IAArDhB,SAAS,QAA8C,gDAAgD;QAC3G;MACJ;MACA,KAAK,MAAMwK,CAAC,IAAI,IAAI,CAAC,CAACxI,aAAa,CAACqD,MAAM,CAAC,CAAC,EAAE;QAC1C,IAAImF,CAAC,CAACxJ,MAAM,KAAK,YAAY,EACzBwJ,CAAC,CAACxJ,MAAM,GAAG,cAAc;MACjC;MACA,IAAI,CAAC,CAACuD,eAAe,CAAC,CAAC;IAC3B;EACJ,CAAC;AACL;AACA,eAAe0E,2BAA2BA,CAAC3H,MAAM,EAAEmJ,GAAG,EAAE5B,OAAO,EAAE;EAC7D,MAAM6B,WAAW,GAAG,MAAMrG,OAAO,CAACC,GAAG,CAACuE,OAAO,CAACnD,GAAG,CAAC,MAAOsD,MAAM,IAAK;IAChE,MAAM2B,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM1K,mBAAmB,CAACqB,MAAM,CAAC,EAClEsJ,cAAc,CAAC5B,MAAM,CAACZ,IAAI,CAAC,EAC3B8B,kBAAkB,CAAC,CAAC;IACzB,MAAMW,eAAe,GAAGC,MAAM,CAACC,WAAW,CAAC,CACvC,GAAGD,MAAM,CAACE,OAAO,CAAChC,MAAM,CAACiC,UAAU,CAAC,CAACvF,GAAG,CAAC,CAAC,CAACwF,GAAG,EAAEC,KAAK,CAAC,KAAK;MACvD,OAAO,CAACR,eAAe,EAAES,0BAA0B,CAACF,GAAG,CAAC,EAAEC,KAAK,CAAC;IACpE,CAAC,CAAC,EACF,CACIR,eAAe,EACTS,0BAA0B,CAACN,MAAM,CAACE,OAAO,CAAChC,MAAM,CAACkC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAClEJ,MAAM,CAACE,OAAO,CAAChC,MAAM,CAACkC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CACnC,EACD,CACI,WAAW,EACXP,eAAe,EAAEU,OAAO,CAC3B,EACD,CACI,UAAU,EACVV,eAAe,EAAEU,OAAO,CAC3B,CACJ,CAAC;IACF,OAAOR,eAAe;EAC1B,CAAC,CAAC,CAAC;EACH;EACA,OAAO,MAAM3K,wBAAwB,CAACoB,MAAM,EAAEoJ,WAAW,EAAEnE,SAAS,CAAC;AACzE;AACA;AACA,MAAM+E,iBAAiB,GAAG,IAAInK,OAAO,CAAC,CAAC;AACvC,MAAMoK,kBAAkB,GAAG,IAAIxJ,GAAG,CAAC,CAAC;AACpC,eAAeyJ,oCAAoCA,CAAClK,MAAM,EAAEmJ,GAAG,EAAEgB,aAAa,EAAE;EAC5E,IAAIF,kBAAkB,CAACG,GAAG,CAACD,aAAa,CAAC,EAAE;IACvC,OAAOH,iBAAiB,CAAC9J,GAAG,CAACiJ,GAAG,CAAC,EAAEjJ,GAAG,CAAC+J,kBAAkB,CAAC/J,GAAG,CAACiK,aAAa,CAAC,CAAC;EACjF;EACA,MAAMtH,WAAW,GAAG,MAAM7C,MAAM,CAAC6C,WAAW;EAC5C,MAAMwH,cAAc,GAAG,MAAM7L,YAAY,CAAC4E,aAAa,CAClDlD,GAAG,CAACF,MAAM,EAAE6C,WAAW,EAAEsH,aAAa,CAAC;EAC5C,OAAOG,gCAAgC,CAACnB,GAAG,EAAEtG,WAAW,EAAEwH,cAAc,CAAC9G,GAAG,CAAC;AACjF;AACA,IAAIgH,mBAAmB;AACvB,eAAeC,wBAAwBA,CAACrB,GAAG,EAAEtG,WAAW,EAAE;EACtD0H,mBAAmB,KAAK,MAAMjM,iBAAiB,CAAC6K,GAAG,EAAE,CAAC,CAAC,CAAC;EACxD,CAAUoB,mBAAmB,CAACE,UAAU,CAAC5H,WAAW,CAAC,GAArDnE,SAAS,QAA8C,2BAA2B;EAClF,OAAO6L,mBAAmB,CAACE,UAAU,CAAC5H,WAAW,CAAC,CAAC6H,sBAAsB;AAC7E;AACA,eAAeJ,gCAAgCA,CAACnB,GAAG,EAAEtG,WAAW,EAAE8H,SAAS,EAAE;EACzE,IAAI,CAACX,iBAAiB,CAACI,GAAG,CAACjB,GAAG,CAAC,EAAE;IAC7Ba,iBAAiB,CAAC5J,GAAG,CAAC+I,GAAG,EAAE,IAAI1I,GAAG,CAAC,CAAC,CAAC;EACzC;EACA,IAAI,CAACuJ,iBAAiB,CAAC9J,GAAG,CAACiJ,GAAG,CAAC,CAACiB,GAAG,CAACO,SAAS,CAAC,EAAE;IAC5C,MAAMC,eAAe,GAAG,MAAMJ,wBAAwB,CAACrB,GAAG,EAAEtG,WAAW,CAAC;IACxE,MAAMgI,IAAI,GAAG;MACTC,eAAe,EAAE,EAAE;MACnBC,WAAW,EAAE,CAAC;QACNC,UAAU,EAAE;UACRlE,IAAI,EAAE,eAAe;UACrBmE,aAAa,EAAEN;QACnB,CAAC;QACDO,gBAAgB,EAAE;UACdpE,IAAI,EAAE,iBAAiB;UACvB8D,eAAe,EAAEA;QACrB;MACJ,CAAC,CAAC;MACNO,SAAS,EAAE,EAAE;MACbC,mBAAmB,EAAE,EAAE;MACvBC,cAAc,EAAE,EAAE;MAClBC,UAAU,EAAE,EAAE;MACdC,YAAY,EAAE,KAAK;MACnBC,sBAAsB,EAAEvG,SAAS;MACjCwG,8CAA8C,EAAE,IAAI;MACpDC,qBAAqB,EAAEzG;IAC3B,CAAC;IACD,MAAM0G,QAAQ,GAAG,MAAMvN,wBAAwB,CAAC+K,GAAG,EAAElE,SAAS,EAAE4F,IAAI,CAAC;IACrE,CAAUc,QAAQ,CAACZ,WAAW,CAAC,CAAC,CAAC,EAAE1H,UAAU,GAA7C3E,SAAS,QAAsC,8BAA8B;IAC7E,MAAMoL,0BAA0B,GAAGN,MAAM,CACpCC,WAAW,CAACD,MAAM,CAACzF,MAAM,CAAC4H,QAAQ,CAACZ,WAAW,CAAC,CAAC,CAAC,CAAC1H,UAAU,CAACuI,aAAa,CAAC,CAACxH,GAAG,CAACyH,QAAQ,IAAI;MAC7F,OAAO,CAACA,QAAQ,CAAC3H,EAAE,EAAE2H,QAAQ,CAAC9B,OAAO,CAAC;IAC1C,CAAC,CAAC,CAAC;IACH,MAAM+B,0BAA0B,GAAGtC,MAAM,CACpCC,WAAW,CAACD,MAAM,CAACzF,MAAM,CAAC4H,QAAQ,CAACZ,WAAW,CAAC,CAAC,CAAC,CAAC1H,UAAU,CAACuI,aAAa,CAAC,CAACxH,GAAG,CAACyH,QAAQ,IAAI;MAC7F,OAAO,CAACA,QAAQ,CAAC9B,OAAO,EAAE8B,QAAQ,CAAC3H,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;IACH8F,iBAAiB,CAAC9J,GAAG,CAACiJ,GAAG,CAAC,EAAE/I,GAAG,CAACuK,SAAS,EAAE;MACvCZ,OAAO,EAAE4B,QAAQ,CAACZ,WAAW,CAAC,CAAC,CAAC,CAAC1H,UAAU,CAAC0G,OAAO;MACnD7F,EAAE,EAAEyH,QAAQ,CAACZ,WAAW,CAAC,CAAC,CAAC,CAAC1H,UAAU,CAACa,EAAE;MACzC4F,0BAA0B;MAC1BgC;IACJ,CAAC,CAAC;IACF7B,kBAAkB,CAAC7J,GAAG,CAACuL,QAAQ,CAACZ,WAAW,CAAC,CAAC,CAAC,CAAC1H,UAAU,CAAC0G,OAAO,EAAEY,SAAS,CAAC;EACjF;EACA,OAAOX,iBAAiB,CAAC9J,GAAG,CAACiJ,GAAG,CAAC,EAAEjJ,GAAG,CAACyK,SAAS,CAAC;AACrD","ignoreList":[]}
1
+ {"version":3,"file":"ObjectSetListenerWebsocket.js","names":["WebSocket","invariant","convertWireToOsdkObjects","ONE_DAY_MS","MINIMUM_RECONNECT_DELAY_MS","doNothing","fillOutListener","onChange","onError","onOutOfDate","isReady","sub","subscriptionIsDone","status","ObjectSetListenerWebsocket","instances","WeakMap","OBJECT_SET_EXPIRY_MS","getInstance","client","instance","get","clientCacheKey","set","ws","lastWsConnect","logger","pendingSubscriptions","Map","subscriptions","maybeDisconnectTimeout","constructor","objectSetExpiryMs","minimumReconnectDelayMs","child","msgPrefix","baseUrl","startsWith","subscribe","objectSet","listener","properties","globalThis","crypto","webcrypto","requestedProperties","subscriptionId","randomUUID","initiateSubscribe","unsubscribe","#initiateSubscribe","process","env","NODE_ENV","trace","expiry","clearTimeout","setTimeout","expire","ontologyRid","ensureWebsocket","readyState","OPEN","sendSubscribeMessage","error","#sendSubscribeMessage","readySubs","values","filter","length","id","requests","map","propertySet","referenceSet","payload","send","JSON","stringify","#expire","subscription","#unsubscribe","newStatus","undefined","delete","size","cycleWebsocket","#ensureWebsocket","tokenProvider","base","URL","url","host","token","nextConnectTime","Date","now","Promise","resolve","addEventListener","onClose","onMessage","onOpen","CONNECTING","reject","cleanup","removeEventListener","open","evt","#onOpen","message","data","parse","toString","type","handleMessage_objectSetChanged","handleMessage_refreshObjectSet","handleMessage_subscribeResponses","handleMessage_subscriptionClosed","objectUpdates","updates","update","osdkObjects","all","o","osdkObjectArray","object","singleOsdkObject","state","osdkObject","responses","subs","i","response","errors","shouldFireOutOfDate","#handleMessage_subscriptionClosed","cause","event","enableObjectSetsWatcher","#enableObjectSetsWatcher","#cycleWebsocket","CLOSING","CLOSED","close","s"],"sources":["ObjectSetListenerWebsocket.js"],"sourcesContent":["/*\n * Copyright 2023 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport WebSocket from \"isomorphic-ws\";\nimport invariant from \"tiny-invariant\";\nimport { convertWireToOsdkObjects } from \"../object/convertWireToOsdkObjects.js\";\nconst ONE_DAY_MS = 24 * 60 * 60 * 1000;\nconst MINIMUM_RECONNECT_DELAY_MS = 5 * 1000;\n/** Noop function to reduce conditional checks */\nfunction doNothing() { }\n/**\n * Converts an ObjectSetListener to one where all the functions are defined.\n */\nfunction fillOutListener({ onChange = doNothing, onError = doNothing, onOutOfDate = doNothing, }) {\n return { onChange, onError, onOutOfDate };\n}\nfunction isReady(sub) {\n return sub.isReady != null;\n}\nfunction subscriptionIsDone(sub) {\n return sub.status === \"done\" || sub.status === \"error\";\n}\n/** @internal */\nexport class ObjectSetListenerWebsocket {\n static #instances = new WeakMap();\n OBJECT_SET_EXPIRY_MS;\n MINIMUM_RECONNECT_DELAY_MS;\n // FIXME\n static getInstance(client) {\n let instance = ObjectSetListenerWebsocket.#instances.get(client.clientCacheKey);\n if (instance == null) {\n instance = new ObjectSetListenerWebsocket(client);\n ObjectSetListenerWebsocket.#instances.set(client.clientCacheKey, instance);\n }\n return instance;\n }\n #ws;\n #lastWsConnect = 0;\n #client;\n #logger;\n /**\n * map of requestId to all active subscriptions at the time of the request\n */\n #pendingSubscriptions = new Map();\n /**\n * Map of subscriptionId to Subscription. Note: the subscriptionId may be\n * temporary and not the actual subscriptionId from the server.\n */\n #subscriptions = new Map();\n #maybeDisconnectTimeout;\n // DO NOT CONSTRUCT DIRECTLY. ONLY EXPOSED AS A TESTING SEAM\n constructor(client, { objectSetExpiryMs = ONE_DAY_MS, minimumReconnectDelayMs = MINIMUM_RECONNECT_DELAY_MS, } = {}) {\n this.OBJECT_SET_EXPIRY_MS = objectSetExpiryMs;\n this.MINIMUM_RECONNECT_DELAY_MS = minimumReconnectDelayMs;\n this.#client = client;\n this.#logger = client.logger?.child({}, {\n msgPrefix: \"<OSW> \",\n });\n invariant(client.baseUrl.startsWith(\"https://\")\n || client.baseUrl.startsWith(\"http://\"), \"Stack must be a URL\");\n }\n async subscribe(objectSet, listener, properties) {\n if (process.env.TARGET !== \"browser\") {\n // Node 18 does not expose 'crypto' on globalThis, so we need to do it ourselves. This\n // will not be needed after our minimum version is 19 or greater.\n globalThis.crypto ??= (await import(\"node:crypto\")).webcrypto;\n }\n const sub = {\n listener: fillOutListener(listener),\n objectSet,\n requestedProperties: properties,\n status: \"preparing\",\n // Since we don't have a real subscription id yet but we need to keep\n // track of this reference, we can just use a random uuid.\n subscriptionId: `TMP-${crypto.randomUUID()}`,\n };\n this.#subscriptions.set(sub.subscriptionId, sub);\n // actually prepares the subscription, ensures the ws is ready, and sends\n // a subscribe message. We don't want to block on this.\n this.#initiateSubscribe(sub);\n return () => {\n this.#unsubscribe(sub);\n };\n }\n /**\n * Called at least once for every subscription.\n *\n * - Resets pending expiry\n * - Recreates temporary object set\n * - Triggers a full subscribe message\n *\n * @returns\n */\n async #initiateSubscribe(sub) {\n if (process?.env?.NODE_ENV !== \"production\") {\n this.#logger?.trace(\"#initiateSubscribe()\");\n }\n if (sub.expiry) {\n clearTimeout(sub.expiry);\n }\n // expiry is tied to the temporary object set, which is set to `timeToLive: \"ONE_DAY\"`\n // in `#createTemporaryObjectSet`. They should be in sync\n sub.expiry = setTimeout(() => this.#expire(sub), this.OBJECT_SET_EXPIRY_MS);\n const ontologyRid = await this.#client.ontologyRid;\n try {\n await this.#ensureWebsocket();\n // the consumer may have already unsubscribed before we are ready to request a subscription\n // so we have to acquire the pendingSubscription after the await.\n if (subscriptionIsDone(sub)) {\n return;\n }\n sub.isReady = true;\n // if we aren't open, then this happens after we #onConnect\n if (this.#ws?.readyState === WebSocket.OPEN) {\n this.#sendSubscribeMessage();\n }\n }\n catch (error) {\n this.#logger?.error(error, \"Error in #initiateSubscribe\");\n sub.listener.onError([error]);\n }\n }\n #sendSubscribeMessage() {\n if (process?.env?.NODE_ENV !== \"production\") {\n this.#logger?.trace(\"#sendSubscribeMessage()\");\n }\n // If two calls to `.subscribe()` happen at once (or if the connection is reset),\n // we may have multiple subscriptions that don't have a subscriptionId yet,\n // so we filter those out.\n const readySubs = [...this.#subscriptions.values()].filter(isReady);\n if (readySubs.length === 0) {\n if (process?.env?.NODE_ENV !== \"production\") {\n this.#logger?.trace(\"#sendSubscribeMessage(): aborting due to no ready subscriptions\");\n }\n return;\n }\n // Assumes the node 18 crypto fallback to globalThis in `subscribe` has happened.\n const id = crypto.randomUUID();\n // responses come back as an array of subIds, so we need to know the sources\n this.#pendingSubscriptions.set(id, readySubs);\n // every subscribe message \"overwrites\" the previous ones that are not\n // re-included, so we have to reconstitute the entire list of subscriptions\n const subscribe = {\n id,\n requests: readySubs.map(({ objectSet, requestedProperties }) => ({\n objectSet: objectSet,\n propertySet: requestedProperties,\n referenceSet: [],\n })),\n };\n if (process?.env?.NODE_ENV !== \"production\") {\n this.#logger?.trace({ payload: subscribe }, \"sending subscribe message\");\n }\n this.#ws?.send(JSON.stringify(subscribe));\n }\n #expire(sub) {\n if (process?.env?.NODE_ENV !== \"production\") {\n this.#logger?.trace({ subscription: sub }, \"#expire()\");\n }\n // the temporary ObjectSet has expired, we should re-subscribe which will cause the\n // listener to get an onOutOfDate message when it becomes subscribed again\n sub.status = \"expired\";\n this.#initiateSubscribe(sub);\n }\n #unsubscribe(sub, newStatus = \"done\") {\n if (subscriptionIsDone(sub)) {\n // if we are already done, we don't need to do anything\n return;\n }\n sub.status = newStatus;\n // make sure listeners do nothing now\n sub.listener = fillOutListener({});\n if (sub.expiry) {\n clearTimeout(sub.expiry);\n sub.expiry = undefined;\n }\n this.#subscriptions.delete(sub.subscriptionId);\n // If we have no more subscriptions, we can disconnect the websocket\n // however we should wait a bit to see if we get any more subscriptions.\n // For example, when switching between react views, you may unsubscribe\n // in the old view and subscribe in the new view. We don't need to re-establish\n // the websocket connection in that case.\n if (this.#maybeDisconnectTimeout) {\n // We reset the timeout on every unsubscribe so its always at least 15s from\n // the last time we are empty. E.g.:\n // - 0s: Subscribe(A)\n // - 10s: Unsubscribe(A)\n // - 11s: Subscribe(B)\n // - 20s: Unsubscribe(B)\n // If we do not clear out the timeout we would disconnect at 25s but that would only be\n // 5s after the last subscription was removed instead of at 35s for the desired 15s.\n clearTimeout(this.#maybeDisconnectTimeout);\n }\n this.#maybeDisconnectTimeout = setTimeout(() => {\n this.#maybeDisconnectTimeout = undefined;\n if (this.#subscriptions.size === 0) {\n this.#cycleWebsocket();\n }\n }, 15_000 /* ms */);\n }\n async #ensureWebsocket() {\n if (this.#ws == null) {\n const { baseUrl, tokenProvider } = this.#client;\n const base = new URL(baseUrl);\n const url = `wss://${base.host}/api/v2/ontologySubscriptions/ontologies/${this.#client.ontologyRid}/streamSubscriptions`;\n const token = await tokenProvider();\n // tokenProvider is async, there could potentially be a race to create the websocket.\n // Only the first call to reach here will find a null this.#ws, the rest will bail out\n if (this.#ws == null) {\n // TODO this can probably be exponential backoff with jitter\n // don't reconnect more quickly than MINIMUM_RECONNECT_DELAY\n const nextConnectTime = (this.#lastWsConnect ?? 0)\n + this.MINIMUM_RECONNECT_DELAY_MS;\n if (nextConnectTime > Date.now()) {\n await new Promise((resolve) => {\n setTimeout(resolve, nextConnectTime - Date.now());\n });\n }\n this.#lastWsConnect = Date.now();\n // we again may have lost the race after our minimum backoff time\n if (this.#ws == null) {\n if (process?.env?.NODE_ENV !== \"production\") {\n this.#logger?.trace(\"Creating websocket\");\n }\n this.#ws = new WebSocket(url, [`Bearer-${token}`]);\n this.#ws.addEventListener(\"close\", this.#onClose);\n this.#ws.addEventListener(\"message\", this.#onMessage);\n this.#ws.addEventListener(\"open\", this.#onOpen);\n }\n }\n // Allow await-ing the websocket open event if it isn't open already.\n // This needs to happen even for callers that didn't just create this.#ws\n if (this.#ws.readyState === WebSocket.CONNECTING) {\n const ws = this.#ws;\n return new Promise((resolve, reject) => {\n function cleanup() {\n ws.removeEventListener(\"open\", open);\n ws.removeEventListener(\"error\", error);\n ws.removeEventListener(\"close\", cleanup);\n }\n function open() {\n cleanup();\n resolve();\n }\n function error(evt) {\n cleanup();\n reject(evt);\n }\n ws.addEventListener(\"open\", open);\n ws.addEventListener(\"error\", error);\n ws.addEventListener(\"close\", cleanup);\n });\n }\n }\n }\n #onOpen = () => {\n // resubscribe all of the listeners\n this.#sendSubscribeMessage();\n };\n #onMessage = async (message) => {\n const data = JSON.parse(message.data.toString());\n if (process?.env?.NODE_ENV !== \"production\") {\n this.#logger?.trace({ payload: data }, \"received message from ws\");\n }\n switch (data.type) {\n case \"objectSetChanged\":\n return this.#handleMessage_objectSetChanged(data);\n case \"refreshObjectSet\":\n return this.#handleMessage_refreshObjectSet(data);\n case \"subscribeResponses\":\n return this.#handleMessage_subscribeResponses(data);\n case \"subscriptionClosed\": {\n return this.#handleMessage_subscriptionClosed(data);\n }\n default:\n const _ = data;\n invariant(false, \"Unexpected message type\");\n }\n };\n #handleMessage_objectSetChanged = async (payload) => {\n const sub = this.#subscriptions.get(payload.id);\n invariant(sub, `Expected subscription id ${payload.id}`);\n const objectUpdates = payload.updates.filter((update) => update.type === \"object\");\n const referenceUpdates = payload.updates.filter((update) => update.type === \"reference\");\n const osdkObjects = await Promise.all(objectUpdates.map(async (o) => {\n const osdkObjectArray = await convertWireToOsdkObjects(this.#client, [o.object], undefined);\n const singleOsdkObject = osdkObjectArray[0] ?? undefined;\n return singleOsdkObject != null\n ? {\n object: singleOsdkObject,\n state: o.state,\n }\n : undefined;\n }));\n for (const osdkObject of osdkObjects) {\n if (osdkObject != null) {\n return sub.listener.onChange?.(osdkObject);\n }\n }\n };\n #handleMessage_refreshObjectSet = (payload) => {\n const sub = this.#subscriptions.get(payload.id);\n invariant(sub, `Expected subscription id ${payload.id}`);\n sub.listener.onOutOfDate();\n };\n #handleMessage_subscribeResponses = (payload) => {\n const { id, responses } = payload;\n const subs = this.#pendingSubscriptions.get(id);\n invariant(subs, `should have a pending subscription for ${id}`);\n this.#pendingSubscriptions.delete(id);\n for (let i = 0; i < responses.length; i++) {\n const sub = subs[i];\n const response = responses[i];\n switch (response.type) {\n case \"error\":\n sub.listener.onError(response.errors);\n this.#unsubscribe(sub, \"error\");\n break;\n case \"qos\":\n // the server has requested that we tear down our websocket and reconnect to help load balance\n this.#cycleWebsocket();\n break;\n case \"success\":\n // `\"preparing\"` should only be the status on an initial subscribe.\n const shouldFireOutOfDate = sub.status === \"expired\"\n || sub.status === \"reconnecting\";\n if (process?.env?.NODE_ENV !== \"production\") {\n this.#logger?.trace({ shouldFireOutOfDate }, \"success\");\n }\n sub.status = \"subscribed\";\n if (sub.subscriptionId !== response.id) {\n // might be the temporary one\n this.#subscriptions.delete(sub.subscriptionId);\n sub.subscriptionId = response.id;\n this.#subscriptions.set(sub.subscriptionId, sub); // future messages come by this subId\n }\n if (shouldFireOutOfDate)\n sub.listener.onOutOfDate();\n break;\n default:\n const _ = response;\n sub.listener.onError(response);\n }\n }\n };\n #handleMessage_subscriptionClosed(payload) {\n const sub = this.#subscriptions.get(payload.id);\n invariant(sub, `Expected subscription id ${payload.id}`);\n sub.listener.onError([payload.cause]);\n this.#unsubscribe(sub, \"error\");\n }\n #onClose = (event) => {\n if (process?.env?.NODE_ENV !== \"production\") {\n this.#logger?.trace({ event }, \"Received close event from ws\", event);\n }\n // TODO we should probably throttle this so we don't abuse the backend\n this.#cycleWebsocket();\n };\n // TODO: Validate if this is needed\n async #enableObjectSetsWatcher(objectTypeRids) {\n // return batchEnableWatcher(this.#oswContext, {\n // requests: objectTypeRids,\n // });\n return;\n }\n #cycleWebsocket = () => {\n if (this.#ws) {\n this.#ws.removeEventListener(\"open\", this.#onOpen);\n this.#ws.removeEventListener(\"message\", this.#onMessage);\n this.#ws.removeEventListener(\"close\", this.#onClose);\n if (this.#ws.readyState !== WebSocket.CLOSING\n && this.#ws.readyState !== WebSocket.CLOSED) {\n this.#ws.close();\n }\n this.#ws = undefined;\n }\n // if we have any listeners that are still depending on us, go ahead and reopen the websocket\n if (this.#subscriptions.size > 0) {\n if (process?.env?.NODE_ENV !== \"production\") {\n for (const s of this.#subscriptions.values()) {\n invariant(s.status !== \"done\" && s.status !== \"error\", \"should not have done/error subscriptions still\");\n }\n }\n for (const s of this.#subscriptions.values()) {\n if (s.status === \"subscribed\")\n s.status = \"reconnecting\";\n }\n this.#ensureWebsocket();\n }\n };\n}\n"],"mappings":"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","ignoreList":[]}
@@ -20,7 +20,6 @@ import { http, HttpResponse } from "msw";
20
20
  import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
21
21
  import { z } from "zod";
22
22
  import { createMinimalClient } from "../createMinimalClient.js";
23
- import { conjureUnionType } from "./conjureUnionType.js";
24
23
  import { ObjectSetListenerWebsocket } from "./ObjectSetListenerWebsocket.js";
25
24
  // it needs to be hoisted because its referenced from our mocked WebSocket
26
25
  // which must be hoisted to work
@@ -95,11 +94,9 @@ describe("ObjectSetListenerWebsocket", async () => {
95
94
  onOutOfDate: vi.fn()
96
95
  };
97
96
  let objectSetRidCounter = 0;
98
- apiServer.use(http.post(`${STACK}/object-set-service/api/objectSets/temporary`, () => HttpResponse.json({
97
+ apiServer.use(http.post(`${STACK}api/v2/ontologySubscriptions/ontologies/${$ontologyRid}/streamSubscriptions`, () => HttpResponse.json({
99
98
  objectSetRid: `rid.hi.${objectSetRidCounter++}`
100
- })), http.post(`${STACK}/object-set-watcher/api/object-set-watcher/batchEnableWatcher`, async () => {
101
- return HttpResponse.json({});
102
- }));
99
+ })));
103
100
  vi.useFakeTimers();
104
101
  });
105
102
  afterEach(() => {
@@ -171,7 +168,7 @@ describe("ObjectSetListenerWebsocket", async () => {
171
168
  [unsubscribe2, subReq2] = await Promise.all([client.subscribe({
172
169
  type: "base",
173
170
  objectType: Office.apiName
174
- }, listener), expectSingleSubscribeMessage(ws)]);
171
+ }, listener, ["employeeStatus"]), expectSingleSubscribeMessage(ws)]);
175
172
  rootLogger.fatal({
176
173
  subReq2
177
174
  });
@@ -226,24 +223,26 @@ describe("ObjectSetListenerWebsocket", async () => {
226
223
  });
227
224
  });
228
225
  function respondSuccessToSubscribe(ws, subReq2) {
229
- sendToClient(ws, conjureUnionType("subscribeResponses", {
226
+ sendToClient(ws, {
230
227
  id: subReq2.id,
231
- responses: subReq2.requests.map((_, i) => conjureUnionType("success", {
232
- id: `id-${i}`
233
- }))
234
- }));
228
+ type: "subscribeResponses",
229
+ responses: [{
230
+ type: "success",
231
+ id: "subId"
232
+ }]
233
+ });
235
234
  }
236
235
  function expectEqualRemoveAndAddListeners(ws) {
237
236
  expect(ws.removeEventListener).toHaveBeenCalledTimes(ws.addEventListener.mock.calls.length);
238
237
  }
239
238
  async function expectSingleSubscribeMessage(ws) {
240
- return SubscribeMessage.parse(await consumeSingleSend(ws));
239
+ return await consumeSingleSend(ws);
241
240
  }
242
241
  async function subscribeAndExpectWebSocket(client, listener) {
243
242
  const [ws, unsubscribe] = await Promise.all([expectWebSocketConstructed(), client.subscribe({
244
243
  type: "base",
245
244
  objectType: Employee.apiName
246
- }, listener)]);
245
+ }, listener, ["employeeStatus"])]);
247
246
  // otherwise the ObjectSetListenerWebSocket is sitting waiting for it to "connect"
248
247
  setWebSocketState(ws, "open");
249
248
  return [ws, unsubscribe];
@@ -320,9 +319,11 @@ function addLoggerToApiServer(logger) {
320
319
  const SubscribeMessage = z.object({
321
320
  id: z.string(),
322
321
  requests: z.array(z.object({
323
- objectSet: z.string(),
324
- objectSetContext: z.any(),
325
- watchAllLinks: z.boolean()
322
+ objectSet: z.object({
323
+ id: z.string()
324
+ }),
325
+ propertySet: z.array(z.string()),
326
+ referenceSet: z.array(z.string())
326
327
  }))
327
328
  });
328
329
  class MessageEvent extends Event {