@osdk/client 2.1.0-beta.29 → 2.1.0-beta.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/build/browser/createClient.js +2 -12
- package/build/browser/createClient.js.map +1 -1
- package/build/browser/index.js.map +1 -1
- package/build/browser/objectSet/ObjectSetListenerWebsocket.js.map +1 -1
- package/build/browser/objectSet/ObjectSetListenerWebsocket.test.js.map +1 -1
- package/build/browser/util/UserAgent.js +1 -1
- package/build/cjs/{chunk-JIK7S65P.cjs → chunk-R4DO4ZKB.cjs} +763 -764
- package/build/cjs/chunk-R4DO4ZKB.cjs.map +1 -0
- package/build/cjs/index.cjs +23 -32
- package/build/cjs/index.cjs.map +1 -1
- package/build/cjs/index.d.cts +1 -1
- package/build/cjs/public/internal.cjs +5 -5
- package/build/esm/createClient.js +2 -12
- package/build/esm/createClient.js.map +1 -1
- package/build/esm/index.js.map +1 -1
- package/build/esm/objectSet/ObjectSetListenerWebsocket.js.map +1 -1
- package/build/esm/objectSet/ObjectSetListenerWebsocket.test.js.map +1 -1
- package/build/esm/util/UserAgent.js +1 -1
- package/build/types/index.d.ts +1 -1
- package/package.json +8 -8
- package/build/cjs/chunk-JIK7S65P.cjs.map +0 -1
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
var chunkTCHGLBKJ_cjs = require('./chunk-TCHGLBKJ.cjs');
|
|
4
4
|
var shared_net_errors = require('@osdk/shared.net.errors');
|
|
5
|
-
var
|
|
6
|
-
var invariant = require('tiny-invariant');
|
|
5
|
+
var invariant5 = require('tiny-invariant');
|
|
7
6
|
var api = require('@osdk/api');
|
|
7
|
+
var WebSocket = require('isomorphic-ws');
|
|
8
8
|
|
|
9
9
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
10
|
|
|
11
|
+
var invariant5__default = /*#__PURE__*/_interopDefault(invariant5);
|
|
11
12
|
var WebSocket__default = /*#__PURE__*/_interopDefault(WebSocket);
|
|
12
|
-
var invariant__default = /*#__PURE__*/_interopDefault(invariant);
|
|
13
13
|
|
|
14
14
|
// src/Client.ts
|
|
15
15
|
var additionalContext = Symbol("additionalContext");
|
|
@@ -60,831 +60,831 @@ async function fetchSingleWithErrors(client, objectType, args, objectSet) {
|
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
function extractNamespace(fqApiName) {
|
|
64
|
+
const last = fqApiName.lastIndexOf(".");
|
|
65
|
+
if (last === -1) return [undefined, fqApiName];
|
|
66
|
+
return [fqApiName.slice(0, last), fqApiName.slice(last + 1)];
|
|
65
67
|
}
|
|
66
|
-
function
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
68
|
+
function modernToLegacyWhereClause(whereClause, objectOrInterface) {
|
|
69
|
+
if ("$and" in whereClause) {
|
|
70
|
+
return {
|
|
71
|
+
type: "and",
|
|
72
|
+
value: whereClause.$and.map((clause) => modernToLegacyWhereClause(clause, objectOrInterface))
|
|
73
|
+
};
|
|
74
|
+
} else if ("$or" in whereClause) {
|
|
75
|
+
return {
|
|
76
|
+
type: "or",
|
|
77
|
+
value: whereClause.$or.map((clause) => modernToLegacyWhereClause(clause, objectOrInterface))
|
|
78
|
+
};
|
|
79
|
+
} else if ("$not" in whereClause) {
|
|
80
|
+
return {
|
|
81
|
+
type: "not",
|
|
82
|
+
value: modernToLegacyWhereClause(whereClause.$not, objectOrInterface)
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const parts = Object.entries(whereClause);
|
|
86
|
+
if (parts.length === 1) {
|
|
87
|
+
return handleWherePair(parts[0], objectOrInterface);
|
|
88
|
+
}
|
|
72
89
|
return {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
onOutOfDate,
|
|
76
|
-
onSuccessfulSubscription
|
|
90
|
+
type: "and",
|
|
91
|
+
value: parts.map((v) => handleWherePair(v, objectOrInterface))
|
|
77
92
|
};
|
|
78
93
|
}
|
|
79
|
-
function
|
|
80
|
-
return
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
94
|
+
function makeGeoFilterBbox(bbox, filterType, propertyIdentifier, field) {
|
|
95
|
+
return {
|
|
96
|
+
type: filterType === "$within" ? "withinBoundingBox" : "intersectsBoundingBox",
|
|
97
|
+
/**
|
|
98
|
+
* This is a bit ugly, but did this so that propertyIdentifier only shows up in the return object if its defined,
|
|
99
|
+
* this makes it so we don't need to go update our entire test bed either to include a field which may change in near future.
|
|
100
|
+
* Once we solidify that this is the way forward, I can remove field and clean this up
|
|
101
|
+
*/
|
|
102
|
+
...propertyIdentifier != null && {
|
|
103
|
+
propertyIdentifier
|
|
104
|
+
},
|
|
105
|
+
field,
|
|
106
|
+
value: {
|
|
107
|
+
topLeft: {
|
|
108
|
+
type: "Point",
|
|
109
|
+
coordinates: [bbox[0], bbox[3]]
|
|
110
|
+
},
|
|
111
|
+
bottomRight: {
|
|
112
|
+
type: "Point",
|
|
113
|
+
coordinates: [bbox[2], bbox[1]]
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
84
117
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
118
|
+
function makeGeoFilterPolygon(coordinates, filterType, propertyIdentifier, field) {
|
|
119
|
+
return {
|
|
120
|
+
type: filterType,
|
|
121
|
+
...propertyIdentifier != null && {
|
|
122
|
+
propertyIdentifier
|
|
123
|
+
},
|
|
124
|
+
field,
|
|
125
|
+
value: {
|
|
126
|
+
type: "Polygon",
|
|
127
|
+
coordinates
|
|
93
128
|
}
|
|
94
|
-
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function handleWherePair([fieldName, filter], objectOrInterface, structFieldSelector) {
|
|
132
|
+
!(filter != null) ? process.env.NODE_ENV !== "production" ? invariant5__default.default(false, "Defined key values are only allowed when they are not undefined.") : invariant5__default.default(false) : undefined;
|
|
133
|
+
const propertyIdentifier = structFieldSelector != null ? {
|
|
134
|
+
type: "structField",
|
|
135
|
+
...structFieldSelector,
|
|
136
|
+
propertyApiName: fullyQualifyPropName(structFieldSelector.propertyApiName, objectOrInterface)
|
|
137
|
+
} : undefined;
|
|
138
|
+
const field = structFieldSelector == null ? fullyQualifyPropName(fieldName, objectOrInterface) : undefined;
|
|
139
|
+
if (typeof filter === "string" || typeof filter === "number" || typeof filter === "boolean") {
|
|
140
|
+
return {
|
|
141
|
+
type: "eq",
|
|
142
|
+
...propertyIdentifier != null && {
|
|
143
|
+
propertyIdentifier
|
|
144
|
+
},
|
|
145
|
+
field,
|
|
146
|
+
value: filter
|
|
147
|
+
};
|
|
95
148
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
* temporary and not the actual subscriptionId from the server.
|
|
107
|
-
*/
|
|
108
|
-
#subscriptions = /* @__PURE__ */ new Map();
|
|
109
|
-
#endedSubscriptions = /* @__PURE__ */ new Set();
|
|
110
|
-
#maybeDisconnectTimeout;
|
|
111
|
-
// DO NOT CONSTRUCT DIRECTLY. ONLY EXPOSED AS A TESTING SEAM
|
|
112
|
-
constructor(client, {
|
|
113
|
-
minimumReconnectDelayMs = MINIMUM_RECONNECT_DELAY_MS
|
|
114
|
-
} = {}) {
|
|
115
|
-
this.MINIMUM_RECONNECT_DELAY_MS = minimumReconnectDelayMs;
|
|
116
|
-
this.#client = client;
|
|
117
|
-
this.#logger = client.logger?.child({}, {
|
|
118
|
-
msgPrefix: "<OSW> "
|
|
149
|
+
const keysOfFilter = Object.keys(filter);
|
|
150
|
+
const hasDollarSign = keysOfFilter.some((key) => key.startsWith("$"));
|
|
151
|
+
!(!hasDollarSign || keysOfFilter.length === 1) ? process.env.NODE_ENV !== "production" ? invariant5__default.default(false, "WhereClause Filter with multiple clauses isn't allowed") : invariant5__default.default(false) : undefined;
|
|
152
|
+
if (!hasDollarSign) {
|
|
153
|
+
const structFilter = Object.entries(filter);
|
|
154
|
+
!(structFilter.length === 1) ? process.env.NODE_ENV !== "production" ? invariant5__default.default(false, "Cannot filter on more than one struct field in the same clause, need to use an and clause") : invariant5__default.default(false) : undefined;
|
|
155
|
+
const structFieldApiName = keysOfFilter[0];
|
|
156
|
+
return handleWherePair(Object.entries(filter)[0], objectOrInterface, {
|
|
157
|
+
propertyApiName: fieldName,
|
|
158
|
+
structFieldApiName
|
|
119
159
|
});
|
|
120
|
-
!(client.baseUrl.startsWith("https://") || client.baseUrl.startsWith("http://")) ? process.env.NODE_ENV !== "production" ? invariant__default.default(false, "Stack must be a URL") : invariant__default.default(false) : undefined;
|
|
121
160
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
requestedProperties: objectProperties,
|
|
136
|
-
requestedReferenceProperties: referenceProperties,
|
|
137
|
-
status: "preparing",
|
|
138
|
-
// Since we don't have a real subscription id yet but we need to keep
|
|
139
|
-
// track of this reference, we can just use a random uuid.
|
|
140
|
-
subscriptionId: `TMP-${nextUuid()}}`,
|
|
141
|
-
interfaceApiName: objOrInterfaceDef.type === "object" ? undefined : objOrInterfaceDef.apiName
|
|
142
|
-
};
|
|
143
|
-
this.#subscriptions.set(sub.subscriptionId, sub);
|
|
144
|
-
void this.#initiateSubscribe(sub);
|
|
145
|
-
return () => {
|
|
146
|
-
this.#unsubscribe(sub);
|
|
161
|
+
const firstKey = keysOfFilter[0];
|
|
162
|
+
!(filter[firstKey] != null) ? process.env.NODE_ENV !== "production" ? invariant5__default.default(false) : invariant5__default.default(false) : undefined;
|
|
163
|
+
if (firstKey === "$ne") {
|
|
164
|
+
return {
|
|
165
|
+
type: "not",
|
|
166
|
+
value: {
|
|
167
|
+
type: "eq",
|
|
168
|
+
...propertyIdentifier != null && {
|
|
169
|
+
propertyIdentifier
|
|
170
|
+
},
|
|
171
|
+
field,
|
|
172
|
+
value: filter[firstKey]
|
|
173
|
+
}
|
|
147
174
|
};
|
|
148
175
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
176
|
+
if (firstKey === "$within") {
|
|
177
|
+
const withinBody = filter[firstKey];
|
|
178
|
+
if (Array.isArray(withinBody)) {
|
|
179
|
+
return makeGeoFilterBbox(withinBody, firstKey, propertyIdentifier, field);
|
|
180
|
+
} else if ("$bbox" in withinBody && withinBody.$bbox != null) {
|
|
181
|
+
return makeGeoFilterBbox(withinBody.$bbox, firstKey, propertyIdentifier, field);
|
|
182
|
+
} else if ("$distance" in withinBody && "$of" in withinBody && withinBody.$distance != null && withinBody.$of != null) {
|
|
183
|
+
return {
|
|
184
|
+
type: "withinDistanceOf",
|
|
185
|
+
...propertyIdentifier != null && {
|
|
186
|
+
propertyIdentifier
|
|
187
|
+
},
|
|
188
|
+
field,
|
|
189
|
+
value: {
|
|
190
|
+
center: Array.isArray(withinBody.$of) ? {
|
|
191
|
+
type: "Point",
|
|
192
|
+
coordinates: withinBody.$of
|
|
193
|
+
} : withinBody.$of,
|
|
194
|
+
distance: {
|
|
195
|
+
value: withinBody.$distance[0],
|
|
196
|
+
unit: api.DistanceUnitMapping[withinBody.$distance[1]]
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
} else {
|
|
201
|
+
const coordinates = "$polygon" in withinBody ? withinBody.$polygon : withinBody.coordinates;
|
|
202
|
+
return makeGeoFilterPolygon(coordinates, "withinPolygon", propertyIdentifier, fieldName);
|
|
174
203
|
}
|
|
175
204
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
205
|
+
if (firstKey === "$intersects") {
|
|
206
|
+
const intersectsBody = filter[firstKey];
|
|
207
|
+
if (Array.isArray(intersectsBody)) {
|
|
208
|
+
return makeGeoFilterBbox(intersectsBody, firstKey, propertyIdentifier, field);
|
|
209
|
+
} else if ("$bbox" in intersectsBody && intersectsBody.$bbox != null) {
|
|
210
|
+
return makeGeoFilterBbox(intersectsBody.$bbox, firstKey, propertyIdentifier, field);
|
|
211
|
+
} else {
|
|
212
|
+
const coordinates = "$polygon" in intersectsBody ? intersectsBody.$polygon : intersectsBody.coordinates;
|
|
213
|
+
return makeGeoFilterPolygon(coordinates, "intersectsPolygon", propertyIdentifier, field);
|
|
179
214
|
}
|
|
180
|
-
const readySubs = [...this.#subscriptions.values()].filter(isReady);
|
|
181
|
-
const id = nextUuid();
|
|
182
|
-
this.#pendingSubscriptions.set(id, readySubs);
|
|
183
|
-
const subscribe = {
|
|
184
|
-
id,
|
|
185
|
-
requests: readySubs.map(({
|
|
186
|
-
objectSet,
|
|
187
|
-
requestedProperties,
|
|
188
|
-
requestedReferenceProperties,
|
|
189
|
-
interfaceApiName
|
|
190
|
-
}) => {
|
|
191
|
-
return {
|
|
192
|
-
objectSet,
|
|
193
|
-
propertySet: requestedProperties,
|
|
194
|
-
referenceSet: requestedReferenceProperties
|
|
195
|
-
};
|
|
196
|
-
})
|
|
197
|
-
};
|
|
198
|
-
if (process.env.NODE_ENV !== "production") {
|
|
199
|
-
this.#logger?.trace({
|
|
200
|
-
payload: subscribe
|
|
201
|
-
}, "sending subscribe message");
|
|
202
|
-
}
|
|
203
|
-
this.#ws?.send(JSON.stringify(subscribe));
|
|
204
215
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
sub.listener = fillOutListener({});
|
|
211
|
-
this.#subscriptions.delete(sub.subscriptionId);
|
|
212
|
-
this.#endedSubscriptions.add(sub.subscriptionId);
|
|
213
|
-
this.#sendSubscribeMessage();
|
|
214
|
-
if (this.#maybeDisconnectTimeout) {
|
|
215
|
-
clearTimeout(this.#maybeDisconnectTimeout);
|
|
216
|
-
}
|
|
217
|
-
this.#maybeDisconnectTimeout = setTimeout(
|
|
218
|
-
() => {
|
|
219
|
-
this.#maybeDisconnectTimeout = undefined;
|
|
220
|
-
if (this.#subscriptions.size === 0) {
|
|
221
|
-
this.#cycleWebsocket();
|
|
222
|
-
}
|
|
216
|
+
if (firstKey === "$containsAllTerms" || firstKey === "$containsAnyTerm") {
|
|
217
|
+
return {
|
|
218
|
+
type: firstKey.substring(1),
|
|
219
|
+
...propertyIdentifier != null && {
|
|
220
|
+
propertyIdentifier
|
|
223
221
|
},
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
222
|
+
field,
|
|
223
|
+
value: typeof filter[firstKey] === "string" ? filter[firstKey] : filter[firstKey]["term"],
|
|
224
|
+
fuzzy: typeof filter[firstKey] === "string" ? false : filter[firstKey]["fuzzySearch"] ?? false
|
|
225
|
+
};
|
|
227
226
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
227
|
+
return {
|
|
228
|
+
type: firstKey.substring(1),
|
|
229
|
+
...propertyIdentifier != null && {
|
|
230
|
+
propertyIdentifier
|
|
231
|
+
},
|
|
232
|
+
field,
|
|
233
|
+
value: filter[firstKey]
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
function fullyQualifyPropName(fieldName, objectOrInterface) {
|
|
237
|
+
if (objectOrInterface.type === "interface") {
|
|
238
|
+
const [objApiNamespace] = extractNamespace(objectOrInterface.apiName);
|
|
239
|
+
const [fieldApiNamespace, fieldShortName] = extractNamespace(fieldName);
|
|
240
|
+
return fieldApiNamespace == null && objApiNamespace != null ? `${objApiNamespace}.${fieldShortName}` : fieldName;
|
|
241
|
+
}
|
|
242
|
+
return fieldName;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// src/derivedProperties/createWithPropertiesObjectSet.ts
|
|
246
|
+
function createWithPropertiesObjectSet(objectType, objectSet, definitionMap) {
|
|
247
|
+
const base = {
|
|
248
|
+
pivotTo: (link) => {
|
|
249
|
+
return createWithPropertiesObjectSet(objectType, {
|
|
250
|
+
type: "searchAround",
|
|
251
|
+
objectSet,
|
|
252
|
+
link
|
|
253
|
+
}, definitionMap);
|
|
254
|
+
},
|
|
255
|
+
where: (clause) => {
|
|
256
|
+
return createWithPropertiesObjectSet(objectType, {
|
|
257
|
+
type: "filter",
|
|
258
|
+
objectSet,
|
|
259
|
+
where: modernToLegacyWhereClause(clause, objectType)
|
|
260
|
+
}, definitionMap);
|
|
261
|
+
},
|
|
262
|
+
aggregate: (aggregation, opt) => {
|
|
263
|
+
const splitAggregation = aggregation.split(":");
|
|
264
|
+
!(splitAggregation.length === 2 || splitAggregation[0] === "$count") ? process.env.NODE_ENV !== "production" ? invariant5__default.default(false, "Invalid aggregation format") : invariant5__default.default(false) : undefined;
|
|
265
|
+
const [aggregationPropertyName, aggregationOperation] = splitAggregation;
|
|
266
|
+
let aggregationOperationDefinition;
|
|
267
|
+
switch (aggregationOperation) {
|
|
268
|
+
case "sum":
|
|
269
|
+
case "avg":
|
|
270
|
+
case "min":
|
|
271
|
+
case "max":
|
|
272
|
+
case "exactDistinct":
|
|
273
|
+
case "approximateDistinct":
|
|
274
|
+
aggregationOperationDefinition = {
|
|
275
|
+
type: aggregationOperation,
|
|
276
|
+
selectedPropertyApiName: aggregationPropertyName
|
|
277
|
+
};
|
|
278
|
+
break;
|
|
279
|
+
case "approximatePercentile":
|
|
280
|
+
aggregationOperationDefinition = {
|
|
281
|
+
type: "approximatePercentile",
|
|
282
|
+
selectedPropertyApiName: aggregationPropertyName,
|
|
283
|
+
approximatePercentile: opt?.percentile ?? 0.5
|
|
284
|
+
};
|
|
285
|
+
break;
|
|
286
|
+
case "collectSet":
|
|
287
|
+
case "collectList":
|
|
288
|
+
aggregationOperationDefinition = {
|
|
289
|
+
type: aggregationOperation,
|
|
290
|
+
selectedPropertyApiName: aggregationPropertyName,
|
|
291
|
+
limit: opt?.limit ?? 100
|
|
292
|
+
};
|
|
293
|
+
break;
|
|
294
|
+
case undefined:
|
|
295
|
+
if (aggregationPropertyName === "$count") {
|
|
296
|
+
aggregationOperationDefinition = {
|
|
297
|
+
type: "count"
|
|
298
|
+
};
|
|
299
|
+
break;
|
|
269
300
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
ws.addEventListener("close", cleanup);
|
|
273
|
-
});
|
|
301
|
+
default:
|
|
302
|
+
process.env.NODE_ENV !== "production" ? invariant5__default.default(false, "Invalid aggregation operation " + aggregationOperation) : invariant5__default.default(false) ;
|
|
274
303
|
}
|
|
304
|
+
const selectorResult = {
|
|
305
|
+
type: {}
|
|
306
|
+
};
|
|
307
|
+
definitionMap.set(selectorResult, {
|
|
308
|
+
type: "selection",
|
|
309
|
+
objectSet,
|
|
310
|
+
operation: aggregationOperationDefinition
|
|
311
|
+
});
|
|
312
|
+
return selectorResult;
|
|
313
|
+
},
|
|
314
|
+
selectProperty: (name) => {
|
|
315
|
+
const selectorResult = {
|
|
316
|
+
type: {}
|
|
317
|
+
};
|
|
318
|
+
definitionMap.set(selectorResult, {
|
|
319
|
+
type: "selection",
|
|
320
|
+
objectSet,
|
|
321
|
+
operation: {
|
|
322
|
+
type: "get",
|
|
323
|
+
selectedPropertyApiName: name
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
return selectorResult;
|
|
275
327
|
}
|
|
276
|
-
}
|
|
277
|
-
#onOpen = () => {
|
|
278
|
-
this.#sendSubscribeMessage();
|
|
279
328
|
};
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
329
|
+
return base;
|
|
330
|
+
}
|
|
331
|
+
function legacyToModernSingleAggregationResult(entry) {
|
|
332
|
+
return entry.metrics.reduce((accumulator, curValue) => {
|
|
333
|
+
const parts = curValue.name.split(".");
|
|
334
|
+
if (parts[0] === "count") {
|
|
335
|
+
return accumulator;
|
|
286
336
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
case "subscribeResponses":
|
|
293
|
-
return void this.#handleMessage_subscribeResponses(data);
|
|
294
|
-
case "subscriptionClosed": {
|
|
295
|
-
return void this.#handleMessage_subscriptionClosed(data);
|
|
296
|
-
}
|
|
297
|
-
default:
|
|
298
|
-
process.env.NODE_ENV !== "production" ? invariant__default.default(false, "Unexpected message type") : invariant__default.default(false) ;
|
|
337
|
+
!(parts.length === 2) ? process.env.NODE_ENV !== "production" ? invariant5__default.default(false, "assumed we were getting a `${key}.${type}`") : invariant5__default.default(false) : undefined;
|
|
338
|
+
const property = parts[0];
|
|
339
|
+
const metricType = parts[1];
|
|
340
|
+
if (!(property in accumulator)) {
|
|
341
|
+
accumulator[property] = {};
|
|
299
342
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
object: singleOsdkObject,
|
|
316
|
-
state: "ADDED_OR_UPDATED"
|
|
317
|
-
} : undefined;
|
|
318
|
-
}));
|
|
319
|
-
for (const osdkObject of osdkObjectsWithReferenceUpdates) {
|
|
320
|
-
if (osdkObject != null) {
|
|
321
|
-
try {
|
|
322
|
-
sub.listener.onChange?.(osdkObject);
|
|
323
|
-
} catch (error) {
|
|
324
|
-
this.#logger?.error(error, "Error in onChange callback");
|
|
325
|
-
this.#tryCatchOnError(sub, false, error);
|
|
326
|
-
}
|
|
327
|
-
}
|
|
343
|
+
accumulator[property][metricType] = curValue.value;
|
|
344
|
+
return accumulator;
|
|
345
|
+
}, {});
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// src/internal/conversions/modernToLegacyAggregationClause.ts
|
|
349
|
+
var directionFieldMap = (dir) => dir === "asc" ? "ASC" : dir === "desc" ? "DESC" : undefined;
|
|
350
|
+
function modernToLegacyAggregationClause(select) {
|
|
351
|
+
return Object.entries(select).flatMap(([propAndMetric, aggregationType]) => {
|
|
352
|
+
if (propAndMetric === "$count") {
|
|
353
|
+
return {
|
|
354
|
+
type: "count",
|
|
355
|
+
name: "count",
|
|
356
|
+
direction: directionFieldMap(aggregationType)
|
|
357
|
+
};
|
|
328
358
|
}
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
359
|
+
const colonPos = propAndMetric.lastIndexOf(":");
|
|
360
|
+
const property = propAndMetric.slice(0, colonPos);
|
|
361
|
+
const metric = propAndMetric.slice(colonPos + 1);
|
|
362
|
+
return [{
|
|
363
|
+
type: metric,
|
|
364
|
+
name: `${property}.${metric}`,
|
|
365
|
+
direction: directionFieldMap(aggregationType),
|
|
366
|
+
field: property
|
|
367
|
+
}];
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
function modernToLegacyGroupByClause(groupByClause) {
|
|
371
|
+
if (!groupByClause) return [];
|
|
372
|
+
return Object.entries(groupByClause).flatMap(([field, type]) => {
|
|
373
|
+
if (type === "exact") {
|
|
374
|
+
return [{
|
|
375
|
+
type,
|
|
376
|
+
field
|
|
377
|
+
}];
|
|
378
|
+
} else if ("$exactWithLimit" in type) {
|
|
379
|
+
{
|
|
380
|
+
return [{
|
|
381
|
+
type: "exact",
|
|
382
|
+
field,
|
|
383
|
+
maxGroupCount: type.$exactWithLimit
|
|
384
|
+
}];
|
|
349
385
|
}
|
|
350
|
-
}
|
|
386
|
+
} else if ("$fixedWidth" in type) {
|
|
387
|
+
return [{
|
|
388
|
+
type: "fixedWidth",
|
|
389
|
+
field,
|
|
390
|
+
fixedWidth: type.$fixedWidth
|
|
391
|
+
}];
|
|
392
|
+
} else if ("$ranges" in type) {
|
|
393
|
+
return [{
|
|
394
|
+
type: "ranges",
|
|
395
|
+
field,
|
|
396
|
+
ranges: type.$ranges.map((range) => convertRange(range))
|
|
397
|
+
}];
|
|
398
|
+
} else if ("$duration" in type) {
|
|
399
|
+
return [{
|
|
400
|
+
type: "duration",
|
|
401
|
+
field,
|
|
402
|
+
value: type.$duration[0],
|
|
403
|
+
unit: api.DurationMapping[type.$duration[1]]
|
|
404
|
+
}];
|
|
405
|
+
} else return [];
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
function convertRange(range) {
|
|
409
|
+
return {
|
|
410
|
+
startValue: range[0],
|
|
411
|
+
endValue: range[1]
|
|
351
412
|
};
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// src/object/aggregate.ts
|
|
416
|
+
async function aggregate(clientCtx, objectType, objectSet = chunkTCHGLBKJ_cjs.resolveBaseObjectSetType(objectType), req) {
|
|
417
|
+
chunkTCHGLBKJ_cjs.resolveBaseObjectSetType(objectType);
|
|
418
|
+
const body = {
|
|
419
|
+
aggregation: modernToLegacyAggregationClause(req.$select),
|
|
420
|
+
groupBy: [],
|
|
421
|
+
where: undefined
|
|
422
|
+
};
|
|
423
|
+
if (req.$groupBy) {
|
|
424
|
+
body.groupBy = modernToLegacyGroupByClause(req.$groupBy);
|
|
425
|
+
}
|
|
426
|
+
const result = await chunkTCHGLBKJ_cjs.OntologyObjectSet_exports.aggregate(chunkTCHGLBKJ_cjs.addUserAgentAndRequestContextHeaders(clientCtx, objectType), await clientCtx.ontologyRid, {
|
|
427
|
+
objectSet,
|
|
428
|
+
groupBy: body.groupBy,
|
|
429
|
+
aggregation: body.aggregation
|
|
430
|
+
});
|
|
431
|
+
if (!req.$groupBy) {
|
|
432
|
+
!(result.data.length === 1) ? process.env.NODE_ENV !== "production" ? invariant5__default.default(false, "no group by clause should mean only one data result") : invariant5__default.default(false) : undefined;
|
|
355
433
|
return {
|
|
356
|
-
[
|
|
357
|
-
|
|
358
|
-
}
|
|
434
|
+
...aggregationToCountResult(result.data[0]),
|
|
435
|
+
...legacyToModernSingleAggregationResult(result.data[0])
|
|
359
436
|
};
|
|
360
437
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
|
|
438
|
+
const ret = result.data.map((entry) => {
|
|
439
|
+
return {
|
|
440
|
+
$group: entry.group,
|
|
441
|
+
...aggregationToCountResult(entry),
|
|
442
|
+
...legacyToModernSingleAggregationResult(entry)
|
|
443
|
+
};
|
|
444
|
+
});
|
|
445
|
+
return ret;
|
|
446
|
+
}
|
|
447
|
+
function aggregationToCountResult(entry) {
|
|
448
|
+
for (const aggregateResult of entry.metrics) {
|
|
449
|
+
if (aggregateResult.name === "count") {
|
|
450
|
+
return {
|
|
451
|
+
$count: aggregateResult.value
|
|
452
|
+
};
|
|
369
453
|
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// src/util/augmentRequestContext.ts
|
|
458
|
+
var augmentRequestContext = (client, augment) => ({
|
|
459
|
+
...client,
|
|
460
|
+
requestContext: {
|
|
461
|
+
...client.requestContext,
|
|
462
|
+
...augment(client.requestContext)
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
// src/util/WireObjectSet.ts
|
|
467
|
+
var WIRE_OBJECT_SET_TYPES = /* @__PURE__ */ new Set(["base", "filter", "intersect", "reference", "searchAround", "static", "subtract", "union"]);
|
|
468
|
+
function isWireObjectSet(o) {
|
|
469
|
+
return o != null && typeof o === "object" && WIRE_OBJECT_SET_TYPES.has(o.type);
|
|
470
|
+
}
|
|
471
|
+
var MINIMUM_RECONNECT_DELAY_MS = 5 * 1e3;
|
|
472
|
+
function doNothing() {
|
|
473
|
+
}
|
|
474
|
+
function fillOutListener({
|
|
475
|
+
onChange = doNothing,
|
|
476
|
+
onError = doNothing,
|
|
477
|
+
onOutOfDate = doNothing,
|
|
478
|
+
onSuccessfulSubscription = doNothing
|
|
479
|
+
}) {
|
|
480
|
+
return {
|
|
481
|
+
onChange,
|
|
482
|
+
onError,
|
|
483
|
+
onOutOfDate,
|
|
484
|
+
onSuccessfulSubscription
|
|
370
485
|
};
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
486
|
+
}
|
|
487
|
+
function isReady(sub) {
|
|
488
|
+
return sub.isReady != null;
|
|
489
|
+
}
|
|
490
|
+
function subscriptionIsDone(sub) {
|
|
491
|
+
return sub.status === "done" || sub.status === "error";
|
|
492
|
+
}
|
|
493
|
+
var ObjectSetListenerWebsocket = class _ObjectSetListenerWebsocket {
|
|
494
|
+
static #instances = /* @__PURE__ */ new WeakMap();
|
|
495
|
+
// FIXME
|
|
496
|
+
static getInstance(client) {
|
|
497
|
+
let instance = _ObjectSetListenerWebsocket.#instances.get(client.clientCacheKey);
|
|
498
|
+
if (instance == null) {
|
|
499
|
+
instance = new _ObjectSetListenerWebsocket(client);
|
|
500
|
+
_ObjectSetListenerWebsocket.#instances.set(client.clientCacheKey, instance);
|
|
501
|
+
}
|
|
502
|
+
return instance;
|
|
503
|
+
}
|
|
504
|
+
#ws;
|
|
505
|
+
#lastWsConnect = 0;
|
|
506
|
+
#client;
|
|
507
|
+
#logger;
|
|
508
|
+
/**
|
|
509
|
+
* map of requestId to all active subscriptions at the time of the request
|
|
510
|
+
*/
|
|
511
|
+
#pendingSubscriptions = /* @__PURE__ */ new Map();
|
|
512
|
+
/**
|
|
513
|
+
* Map of subscriptionId to Subscription. Note: the subscriptionId may be
|
|
514
|
+
* temporary and not the actual subscriptionId from the server.
|
|
515
|
+
*/
|
|
516
|
+
#subscriptions = /* @__PURE__ */ new Map();
|
|
517
|
+
#endedSubscriptions = /* @__PURE__ */ new Set();
|
|
518
|
+
#maybeDisconnectTimeout;
|
|
519
|
+
// DO NOT CONSTRUCT DIRECTLY. ONLY EXPOSED AS A TESTING SEAM
|
|
520
|
+
constructor(client, {
|
|
521
|
+
minimumReconnectDelayMs = MINIMUM_RECONNECT_DELAY_MS
|
|
522
|
+
} = {}) {
|
|
523
|
+
this.MINIMUM_RECONNECT_DELAY_MS = minimumReconnectDelayMs;
|
|
524
|
+
this.#client = client;
|
|
525
|
+
this.#logger = client.logger?.child({}, {
|
|
526
|
+
msgPrefix: "<OSW> "
|
|
527
|
+
});
|
|
528
|
+
!(client.baseUrl.startsWith("https://") || client.baseUrl.startsWith("http://")) ? process.env.NODE_ENV !== "production" ? invariant5__default.default(false, "Stack must be a URL") : invariant5__default.default(false) : undefined;
|
|
529
|
+
}
|
|
530
|
+
async subscribe(objectType, objectSet, listener, properties = []) {
|
|
531
|
+
const objOrInterfaceDef = objectType.type === "object" ? await this.#client.ontologyProvider.getObjectDefinition(objectType.apiName) : await this.#client.ontologyProvider.getInterfaceDefinition(objectType.apiName);
|
|
532
|
+
let objectProperties = [];
|
|
533
|
+
let referenceProperties = [];
|
|
534
|
+
if (properties.length === 0) {
|
|
535
|
+
properties = Object.keys(objOrInterfaceDef.properties);
|
|
414
536
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
const sub =
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
537
|
+
objectProperties = properties.filter((p) => objOrInterfaceDef.properties[p].type !== "geotimeSeriesReference");
|
|
538
|
+
referenceProperties = properties.filter((p) => objOrInterfaceDef.properties[p].type === "geotimeSeriesReference");
|
|
539
|
+
const sub = {
|
|
540
|
+
listener: fillOutListener(listener),
|
|
541
|
+
objectSet,
|
|
542
|
+
primaryKeyPropertyName: objOrInterfaceDef.type === "interface" ? undefined : objOrInterfaceDef.primaryKeyApiName,
|
|
543
|
+
requestedProperties: objectProperties,
|
|
544
|
+
requestedReferenceProperties: referenceProperties,
|
|
545
|
+
status: "preparing",
|
|
546
|
+
// Since we don't have a real subscription id yet but we need to keep
|
|
547
|
+
// track of this reference, we can just use a random uuid.
|
|
548
|
+
subscriptionId: `TMP-${nextUuid()}}`,
|
|
549
|
+
interfaceApiName: objOrInterfaceDef.type === "object" ? undefined : objOrInterfaceDef.apiName
|
|
550
|
+
};
|
|
551
|
+
this.#subscriptions.set(sub.subscriptionId, sub);
|
|
552
|
+
void this.#initiateSubscribe(sub);
|
|
553
|
+
return () => {
|
|
554
|
+
this.#unsubscribe(sub);
|
|
555
|
+
};
|
|
422
556
|
}
|
|
423
|
-
|
|
557
|
+
/**
|
|
558
|
+
* Called at least once for every subscription.
|
|
559
|
+
*
|
|
560
|
+
* - Resets pending expiry
|
|
561
|
+
* - Recreates temporary object set
|
|
562
|
+
* - Triggers a full subscribe message
|
|
563
|
+
*
|
|
564
|
+
* @returns
|
|
565
|
+
*/
|
|
566
|
+
async #initiateSubscribe(sub) {
|
|
424
567
|
if (process.env.NODE_ENV !== "production") {
|
|
425
|
-
this.#logger?.trace(
|
|
426
|
-
event
|
|
427
|
-
}, "Received close event from ws", event);
|
|
428
|
-
}
|
|
429
|
-
this.#cycleWebsocket();
|
|
430
|
-
};
|
|
431
|
-
#cycleWebsocket = () => {
|
|
432
|
-
if (this.#ws) {
|
|
433
|
-
this.#ws.removeEventListener("open", this.#onOpen);
|
|
434
|
-
this.#ws.removeEventListener("message", this.#onMessage);
|
|
435
|
-
this.#ws.removeEventListener("close", this.#onClose);
|
|
436
|
-
if (this.#ws.readyState !== WebSocket__default.default.CLOSING && this.#ws.readyState !== WebSocket__default.default.CLOSED) {
|
|
437
|
-
this.#ws.close();
|
|
438
|
-
}
|
|
439
|
-
this.#ws = undefined;
|
|
568
|
+
this.#logger?.trace("#initiateSubscribe()");
|
|
440
569
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
}
|
|
570
|
+
try {
|
|
571
|
+
await this.#ensureWebsocket();
|
|
572
|
+
if (subscriptionIsDone(sub)) {
|
|
573
|
+
return;
|
|
446
574
|
}
|
|
447
|
-
|
|
448
|
-
|
|
575
|
+
sub.isReady = true;
|
|
576
|
+
if (this.#ws?.readyState === WebSocket__default.default.OPEN) {
|
|
577
|
+
this.#sendSubscribeMessage();
|
|
449
578
|
}
|
|
450
|
-
|
|
579
|
+
} catch (error) {
|
|
580
|
+
this.#logger?.error(error, "Error in #initiateSubscribe");
|
|
581
|
+
this.#tryCatchOnError(sub, true, error);
|
|
451
582
|
}
|
|
452
|
-
}
|
|
453
|
-
#
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
subscriptionClosed,
|
|
457
|
-
error
|
|
458
|
-
});
|
|
459
|
-
} catch (onErrorError) {
|
|
460
|
-
console.error(`Error encountered in an onError callback for an OSDK subscription`, onErrorError);
|
|
461
|
-
console.error(`This onError call was triggered by an error in another callback`, error);
|
|
462
|
-
console.error(`The subscription has been closed.`, error);
|
|
463
|
-
if (!subscriptionClosed) {
|
|
464
|
-
this.#logger?.error(error, "Error in onError callback");
|
|
465
|
-
this.#unsubscribe(sub, "error");
|
|
466
|
-
this.#tryCatchOnError(sub, true, onErrorError);
|
|
467
|
-
}
|
|
583
|
+
}
|
|
584
|
+
#sendSubscribeMessage() {
|
|
585
|
+
if (process.env.NODE_ENV !== "production") {
|
|
586
|
+
this.#logger?.trace("#sendSubscribeMessage()");
|
|
468
587
|
}
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
}
|
|
486
|
-
function modernToLegacyWhereClause(whereClause, objectOrInterface) {
|
|
487
|
-
if ("$and" in whereClause) {
|
|
488
|
-
return {
|
|
489
|
-
type: "and",
|
|
490
|
-
value: whereClause.$and.map((clause) => modernToLegacyWhereClause(clause, objectOrInterface))
|
|
491
|
-
};
|
|
492
|
-
} else if ("$or" in whereClause) {
|
|
493
|
-
return {
|
|
494
|
-
type: "or",
|
|
495
|
-
value: whereClause.$or.map((clause) => modernToLegacyWhereClause(clause, objectOrInterface))
|
|
496
|
-
};
|
|
497
|
-
} else if ("$not" in whereClause) {
|
|
498
|
-
return {
|
|
499
|
-
type: "not",
|
|
500
|
-
value: modernToLegacyWhereClause(whereClause.$not, objectOrInterface)
|
|
588
|
+
const readySubs = [...this.#subscriptions.values()].filter(isReady);
|
|
589
|
+
const id = nextUuid();
|
|
590
|
+
this.#pendingSubscriptions.set(id, readySubs);
|
|
591
|
+
const subscribe = {
|
|
592
|
+
id,
|
|
593
|
+
requests: readySubs.map(({
|
|
594
|
+
objectSet,
|
|
595
|
+
requestedProperties,
|
|
596
|
+
requestedReferenceProperties,
|
|
597
|
+
interfaceApiName
|
|
598
|
+
}) => {
|
|
599
|
+
return {
|
|
600
|
+
objectSet,
|
|
601
|
+
propertySet: requestedProperties,
|
|
602
|
+
referenceSet: requestedReferenceProperties
|
|
603
|
+
};
|
|
604
|
+
})
|
|
501
605
|
};
|
|
606
|
+
if (process.env.NODE_ENV !== "production") {
|
|
607
|
+
this.#logger?.trace({
|
|
608
|
+
payload: subscribe
|
|
609
|
+
}, "sending subscribe message");
|
|
610
|
+
}
|
|
611
|
+
this.#ws?.send(JSON.stringify(subscribe));
|
|
502
612
|
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
propertyIdentifier
|
|
522
|
-
},
|
|
523
|
-
field,
|
|
524
|
-
value: {
|
|
525
|
-
topLeft: {
|
|
526
|
-
type: "Point",
|
|
527
|
-
coordinates: [bbox[0], bbox[3]]
|
|
613
|
+
#unsubscribe(sub, newStatus = "done") {
|
|
614
|
+
if (subscriptionIsDone(sub)) {
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
sub.status = newStatus;
|
|
618
|
+
sub.listener = fillOutListener({});
|
|
619
|
+
this.#subscriptions.delete(sub.subscriptionId);
|
|
620
|
+
this.#endedSubscriptions.add(sub.subscriptionId);
|
|
621
|
+
this.#sendSubscribeMessage();
|
|
622
|
+
if (this.#maybeDisconnectTimeout) {
|
|
623
|
+
clearTimeout(this.#maybeDisconnectTimeout);
|
|
624
|
+
}
|
|
625
|
+
this.#maybeDisconnectTimeout = setTimeout(
|
|
626
|
+
() => {
|
|
627
|
+
this.#maybeDisconnectTimeout = undefined;
|
|
628
|
+
if (this.#subscriptions.size === 0) {
|
|
629
|
+
this.#cycleWebsocket();
|
|
630
|
+
}
|
|
528
631
|
},
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
632
|
+
15e3
|
|
633
|
+
/* ms */
|
|
634
|
+
);
|
|
635
|
+
}
|
|
636
|
+
async #ensureWebsocket() {
|
|
637
|
+
if (this.#ws == null) {
|
|
638
|
+
const {
|
|
639
|
+
baseUrl,
|
|
640
|
+
tokenProvider
|
|
641
|
+
} = this.#client;
|
|
642
|
+
const url = constructWebsocketUrl(baseUrl, await this.#client.ontologyRid);
|
|
643
|
+
const token = await tokenProvider();
|
|
644
|
+
if (this.#ws == null) {
|
|
645
|
+
const nextConnectTime = (this.#lastWsConnect ?? 0) + this.MINIMUM_RECONNECT_DELAY_MS;
|
|
646
|
+
if (nextConnectTime > Date.now()) {
|
|
647
|
+
await new Promise((resolve) => {
|
|
648
|
+
setTimeout(resolve, nextConnectTime - Date.now());
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
this.#lastWsConnect = Date.now();
|
|
652
|
+
if (this.#ws == null) {
|
|
653
|
+
if (process.env.NODE_ENV !== "production") {
|
|
654
|
+
this.#logger?.trace("Creating websocket");
|
|
655
|
+
}
|
|
656
|
+
this.#ws = new WebSocket__default.default(url, [`Bearer-${token}`]);
|
|
657
|
+
this.#ws.addEventListener("close", this.#onClose);
|
|
658
|
+
this.#ws.addEventListener("message", this.#onMessage);
|
|
659
|
+
this.#ws.addEventListener("open", this.#onOpen);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
if (this.#ws.readyState === WebSocket__default.default.CONNECTING) {
|
|
663
|
+
const ws = this.#ws;
|
|
664
|
+
return new Promise((resolve, reject) => {
|
|
665
|
+
function cleanup() {
|
|
666
|
+
ws.removeEventListener("open", open);
|
|
667
|
+
ws.removeEventListener("error", error);
|
|
668
|
+
ws.removeEventListener("close", cleanup);
|
|
669
|
+
}
|
|
670
|
+
function open() {
|
|
671
|
+
cleanup();
|
|
672
|
+
resolve();
|
|
673
|
+
}
|
|
674
|
+
function error(evt) {
|
|
675
|
+
cleanup();
|
|
676
|
+
reject(evt);
|
|
677
|
+
}
|
|
678
|
+
ws.addEventListener("open", open);
|
|
679
|
+
ws.addEventListener("error", error);
|
|
680
|
+
ws.addEventListener("close", cleanup);
|
|
681
|
+
});
|
|
532
682
|
}
|
|
533
683
|
}
|
|
684
|
+
}
|
|
685
|
+
#onOpen = () => {
|
|
686
|
+
this.#sendSubscribeMessage();
|
|
534
687
|
};
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
},
|
|
542
|
-
field,
|
|
543
|
-
value: {
|
|
544
|
-
type: "Polygon",
|
|
545
|
-
coordinates
|
|
688
|
+
#onMessage = async (message) => {
|
|
689
|
+
const data = JSON.parse(message.data.toString());
|
|
690
|
+
if (process.env.NODE_ENV !== "production") {
|
|
691
|
+
this.#logger?.trace({
|
|
692
|
+
payload: data
|
|
693
|
+
}, "received message from ws");
|
|
546
694
|
}
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
const field = structFieldSelector == null ? fullyQualifyPropName(fieldName, objectOrInterface) : undefined;
|
|
557
|
-
if (typeof filter === "string" || typeof filter === "number" || typeof filter === "boolean") {
|
|
558
|
-
return {
|
|
559
|
-
type: "eq",
|
|
560
|
-
...propertyIdentifier != null && {
|
|
561
|
-
propertyIdentifier
|
|
562
|
-
},
|
|
563
|
-
field,
|
|
564
|
-
value: filter
|
|
565
|
-
};
|
|
566
|
-
}
|
|
567
|
-
const keysOfFilter = Object.keys(filter);
|
|
568
|
-
const hasDollarSign = keysOfFilter.some((key) => key.startsWith("$"));
|
|
569
|
-
!(!hasDollarSign || keysOfFilter.length === 1) ? process.env.NODE_ENV !== "production" ? invariant__default.default(false, "WhereClause Filter with multiple clauses isn't allowed") : invariant__default.default(false) : undefined;
|
|
570
|
-
if (!hasDollarSign) {
|
|
571
|
-
const structFilter = Object.entries(filter);
|
|
572
|
-
!(structFilter.length === 1) ? process.env.NODE_ENV !== "production" ? invariant__default.default(false, "Cannot filter on more than one struct field in the same clause, need to use an and clause") : invariant__default.default(false) : undefined;
|
|
573
|
-
const structFieldApiName = keysOfFilter[0];
|
|
574
|
-
return handleWherePair(Object.entries(filter)[0], objectOrInterface, {
|
|
575
|
-
propertyApiName: fieldName,
|
|
576
|
-
structFieldApiName
|
|
577
|
-
});
|
|
578
|
-
}
|
|
579
|
-
const firstKey = keysOfFilter[0];
|
|
580
|
-
!(filter[firstKey] != null) ? process.env.NODE_ENV !== "production" ? invariant__default.default(false) : invariant__default.default(false) : undefined;
|
|
581
|
-
if (firstKey === "$ne") {
|
|
582
|
-
return {
|
|
583
|
-
type: "not",
|
|
584
|
-
value: {
|
|
585
|
-
type: "eq",
|
|
586
|
-
...propertyIdentifier != null && {
|
|
587
|
-
propertyIdentifier
|
|
588
|
-
},
|
|
589
|
-
field,
|
|
590
|
-
value: filter[firstKey]
|
|
695
|
+
switch (data.type) {
|
|
696
|
+
case "objectSetChanged":
|
|
697
|
+
return void this.#handleMessage_objectSetChanged(data);
|
|
698
|
+
case "refreshObjectSet":
|
|
699
|
+
return void this.#handleMessage_refreshObjectSet(data);
|
|
700
|
+
case "subscribeResponses":
|
|
701
|
+
return void this.#handleMessage_subscribeResponses(data);
|
|
702
|
+
case "subscriptionClosed": {
|
|
703
|
+
return void this.#handleMessage_subscriptionClosed(data);
|
|
591
704
|
}
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
705
|
+
default:
|
|
706
|
+
process.env.NODE_ENV !== "production" ? invariant5__default.default(false, "Unexpected message type") : invariant5__default.default(false) ;
|
|
707
|
+
}
|
|
708
|
+
};
|
|
709
|
+
#handleMessage_objectSetChanged = async (payload) => {
|
|
710
|
+
const sub = this.#subscriptions.get(payload.id);
|
|
711
|
+
if (sub == null) return;
|
|
712
|
+
const objectUpdates = payload.updates.filter((update) => update.type === "object");
|
|
713
|
+
const referenceUpdates = payload.updates.filter((update) => update.type === "reference");
|
|
714
|
+
const osdkObjectsWithReferenceUpdates = await Promise.all(referenceUpdates.map(async (o) => {
|
|
715
|
+
const osdkObjectArray = await this.#client.objectFactory2(this.#client, [{
|
|
716
|
+
__apiName: o.objectType,
|
|
717
|
+
__primaryKey: sub.primaryKeyPropertyName != null ? o.primaryKey[sub.primaryKeyPropertyName] : undefined,
|
|
718
|
+
...o.primaryKey,
|
|
719
|
+
[o.property]: o.value
|
|
720
|
+
}], sub.interfaceApiName, false, undefined, false, await this.#fetchInterfaceMapping(o.objectType, sub.interfaceApiName));
|
|
721
|
+
const singleOsdkObject = osdkObjectArray[0] ?? undefined;
|
|
722
|
+
return singleOsdkObject != null ? {
|
|
723
|
+
object: singleOsdkObject,
|
|
724
|
+
state: "ADDED_OR_UPDATED"
|
|
725
|
+
} : undefined;
|
|
726
|
+
}));
|
|
727
|
+
for (const osdkObject of osdkObjectsWithReferenceUpdates) {
|
|
728
|
+
if (osdkObject != null) {
|
|
729
|
+
try {
|
|
730
|
+
sub.listener.onChange?.(osdkObject);
|
|
731
|
+
} catch (error) {
|
|
732
|
+
this.#logger?.error(error, "Error in onChange callback");
|
|
733
|
+
this.#tryCatchOnError(sub, false, error);
|
|
616
734
|
}
|
|
617
|
-
}
|
|
618
|
-
} else {
|
|
619
|
-
const coordinates = "$polygon" in withinBody ? withinBody.$polygon : withinBody.coordinates;
|
|
620
|
-
return makeGeoFilterPolygon(coordinates, "withinPolygon", propertyIdentifier, fieldName);
|
|
735
|
+
}
|
|
621
736
|
}
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
737
|
+
const osdkObjects = await Promise.all(objectUpdates.map(async (o) => {
|
|
738
|
+
const keysToDelete = Object.keys(o.object).filter((key) => sub.requestedReferenceProperties.includes(key));
|
|
739
|
+
for (const key of keysToDelete) {
|
|
740
|
+
delete o.object[key];
|
|
741
|
+
}
|
|
742
|
+
const osdkObjectArray = await this.#client.objectFactory2(this.#client, [o.object], sub.interfaceApiName, false, undefined, false, await this.#fetchInterfaceMapping(o.object.__apiName, sub.interfaceApiName));
|
|
743
|
+
const singleOsdkObject = osdkObjectArray[0] ?? undefined;
|
|
744
|
+
return singleOsdkObject != null ? {
|
|
745
|
+
object: singleOsdkObject,
|
|
746
|
+
state: o.state
|
|
747
|
+
} : undefined;
|
|
748
|
+
}));
|
|
749
|
+
for (const osdkObject of osdkObjects) {
|
|
750
|
+
if (osdkObject != null) {
|
|
751
|
+
try {
|
|
752
|
+
sub.listener.onChange?.(osdkObject);
|
|
753
|
+
} catch (error) {
|
|
754
|
+
this.#logger?.error(error, "Error in onChange callback");
|
|
755
|
+
this.#tryCatchOnError(sub, false, error);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
632
758
|
}
|
|
633
|
-
}
|
|
634
|
-
|
|
759
|
+
};
|
|
760
|
+
async #fetchInterfaceMapping(objectTypeApiName, interfaceApiName) {
|
|
761
|
+
if (interfaceApiName == null) return {};
|
|
762
|
+
const interfaceMap = (await this.#client.ontologyProvider.getObjectDefinition(objectTypeApiName)).interfaceMap;
|
|
635
763
|
return {
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
},
|
|
640
|
-
field,
|
|
641
|
-
value: typeof filter[firstKey] === "string" ? filter[firstKey] : filter[firstKey]["term"],
|
|
642
|
-
fuzzy: typeof filter[firstKey] === "string" ? false : filter[firstKey]["fuzzySearch"] ?? false
|
|
764
|
+
[interfaceApiName]: {
|
|
765
|
+
[objectTypeApiName]: interfaceMap[interfaceApiName]
|
|
766
|
+
}
|
|
643
767
|
};
|
|
644
768
|
}
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
769
|
+
#handleMessage_refreshObjectSet = (payload) => {
|
|
770
|
+
const sub = this.#subscriptions.get(payload.id);
|
|
771
|
+
!sub ? process.env.NODE_ENV !== "production" ? invariant5__default.default(false, `Expected subscription id ${payload.id}`) : invariant5__default.default(false) : undefined;
|
|
772
|
+
try {
|
|
773
|
+
sub.listener.onOutOfDate();
|
|
774
|
+
} catch (error) {
|
|
775
|
+
this.#logger?.error(error, "Error in onOutOfDate callback");
|
|
776
|
+
this.#tryCatchOnError(sub, false, error);
|
|
777
|
+
}
|
|
652
778
|
};
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
type: "searchAround",
|
|
669
|
-
objectSet,
|
|
670
|
-
link
|
|
671
|
-
}, definitionMap);
|
|
672
|
-
},
|
|
673
|
-
where: (clause) => {
|
|
674
|
-
return createWithPropertiesObjectSet(objectType, {
|
|
675
|
-
type: "filter",
|
|
676
|
-
objectSet,
|
|
677
|
-
where: modernToLegacyWhereClause(clause, objectType)
|
|
678
|
-
}, definitionMap);
|
|
679
|
-
},
|
|
680
|
-
aggregate: (aggregation, opt) => {
|
|
681
|
-
const splitAggregation = aggregation.split(":");
|
|
682
|
-
!(splitAggregation.length === 2 || splitAggregation[0] === "$count") ? process.env.NODE_ENV !== "production" ? invariant__default.default(false, "Invalid aggregation format") : invariant__default.default(false) : undefined;
|
|
683
|
-
const [aggregationPropertyName, aggregationOperation] = splitAggregation;
|
|
684
|
-
let aggregationOperationDefinition;
|
|
685
|
-
switch (aggregationOperation) {
|
|
686
|
-
case "sum":
|
|
687
|
-
case "avg":
|
|
688
|
-
case "min":
|
|
689
|
-
case "max":
|
|
690
|
-
case "exactDistinct":
|
|
691
|
-
case "approximateDistinct":
|
|
692
|
-
aggregationOperationDefinition = {
|
|
693
|
-
type: aggregationOperation,
|
|
694
|
-
selectedPropertyApiName: aggregationPropertyName
|
|
695
|
-
};
|
|
696
|
-
break;
|
|
697
|
-
case "approximatePercentile":
|
|
698
|
-
aggregationOperationDefinition = {
|
|
699
|
-
type: "approximatePercentile",
|
|
700
|
-
selectedPropertyApiName: aggregationPropertyName,
|
|
701
|
-
approximatePercentile: opt?.percentile ?? 0.5
|
|
702
|
-
};
|
|
779
|
+
#handleMessage_subscribeResponses = (payload) => {
|
|
780
|
+
const {
|
|
781
|
+
id,
|
|
782
|
+
responses
|
|
783
|
+
} = payload;
|
|
784
|
+
const subs = this.#pendingSubscriptions.get(id);
|
|
785
|
+
!subs ? process.env.NODE_ENV !== "production" ? invariant5__default.default(false, `should have a pending subscription for ${id}`) : invariant5__default.default(false) : undefined;
|
|
786
|
+
this.#pendingSubscriptions.delete(id);
|
|
787
|
+
for (let i = 0; i < responses.length; i++) {
|
|
788
|
+
const sub = subs[i];
|
|
789
|
+
const response = responses[i];
|
|
790
|
+
switch (response.type) {
|
|
791
|
+
case "error":
|
|
792
|
+
this.#tryCatchOnError(sub, true, response.errors);
|
|
793
|
+
this.#unsubscribe(sub, "error");
|
|
703
794
|
break;
|
|
704
|
-
case "
|
|
705
|
-
|
|
706
|
-
aggregationOperationDefinition = {
|
|
707
|
-
type: aggregationOperation,
|
|
708
|
-
selectedPropertyApiName: aggregationPropertyName,
|
|
709
|
-
limit: opt?.limit ?? 100
|
|
710
|
-
};
|
|
795
|
+
case "qos":
|
|
796
|
+
this.#cycleWebsocket();
|
|
711
797
|
break;
|
|
712
|
-
case
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
798
|
+
case "success":
|
|
799
|
+
const shouldFireOutOfDate = sub.status === "expired" || sub.status === "reconnecting";
|
|
800
|
+
if (process.env.NODE_ENV !== "production") {
|
|
801
|
+
this.#logger?.trace({
|
|
802
|
+
shouldFireOutOfDate
|
|
803
|
+
}, "success");
|
|
804
|
+
}
|
|
805
|
+
sub.status = "subscribed";
|
|
806
|
+
if (sub.subscriptionId !== response.id) {
|
|
807
|
+
this.#subscriptions.delete(sub.subscriptionId);
|
|
808
|
+
sub.subscriptionId = response.id;
|
|
809
|
+
this.#subscriptions.set(sub.subscriptionId, sub);
|
|
810
|
+
}
|
|
811
|
+
try {
|
|
812
|
+
if (shouldFireOutOfDate) sub.listener.onOutOfDate();
|
|
813
|
+
else sub.listener.onSuccessfulSubscription();
|
|
814
|
+
} catch (error) {
|
|
815
|
+
this.#logger?.error(error, "Error in onOutOfDate or onSuccessfulSubscription callback");
|
|
816
|
+
this.#tryCatchOnError(sub, false, error);
|
|
718
817
|
}
|
|
818
|
+
break;
|
|
719
819
|
default:
|
|
720
|
-
|
|
820
|
+
this.#tryCatchOnError(sub, true, response);
|
|
721
821
|
}
|
|
722
|
-
const selectorResult = {
|
|
723
|
-
type: {}
|
|
724
|
-
};
|
|
725
|
-
definitionMap.set(selectorResult, {
|
|
726
|
-
type: "selection",
|
|
727
|
-
objectSet,
|
|
728
|
-
operation: aggregationOperationDefinition
|
|
729
|
-
});
|
|
730
|
-
return selectorResult;
|
|
731
|
-
},
|
|
732
|
-
selectProperty: (name) => {
|
|
733
|
-
const selectorResult = {
|
|
734
|
-
type: {}
|
|
735
|
-
};
|
|
736
|
-
definitionMap.set(selectorResult, {
|
|
737
|
-
type: "selection",
|
|
738
|
-
objectSet,
|
|
739
|
-
operation: {
|
|
740
|
-
type: "get",
|
|
741
|
-
selectedPropertyApiName: name
|
|
742
|
-
}
|
|
743
|
-
});
|
|
744
|
-
return selectorResult;
|
|
745
822
|
}
|
|
746
823
|
};
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
accumulator[property] = {};
|
|
824
|
+
#handleMessage_subscriptionClosed(payload) {
|
|
825
|
+
const sub = this.#subscriptions.get(payload.id);
|
|
826
|
+
if (sub == null && this.#endedSubscriptions.has(payload.id)) return;
|
|
827
|
+
!sub ? process.env.NODE_ENV !== "production" ? invariant5__default.default(false, `Expected subscription id ${payload.id}`) : invariant5__default.default(false) : undefined;
|
|
828
|
+
this.#tryCatchOnError(sub, true, payload.cause);
|
|
829
|
+
this.#unsubscribe(sub, "error");
|
|
830
|
+
}
|
|
831
|
+
#onClose = (event) => {
|
|
832
|
+
if (process.env.NODE_ENV !== "production") {
|
|
833
|
+
this.#logger?.trace({
|
|
834
|
+
event
|
|
835
|
+
}, "Received close event from ws", event);
|
|
760
836
|
}
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
type: "count",
|
|
773
|
-
name: "count",
|
|
774
|
-
direction: directionFieldMap(aggregationType)
|
|
775
|
-
};
|
|
837
|
+
this.#cycleWebsocket();
|
|
838
|
+
};
|
|
839
|
+
#cycleWebsocket = () => {
|
|
840
|
+
if (this.#ws) {
|
|
841
|
+
this.#ws.removeEventListener("open", this.#onOpen);
|
|
842
|
+
this.#ws.removeEventListener("message", this.#onMessage);
|
|
843
|
+
this.#ws.removeEventListener("close", this.#onClose);
|
|
844
|
+
if (this.#ws.readyState !== WebSocket__default.default.CLOSING && this.#ws.readyState !== WebSocket__default.default.CLOSED) {
|
|
845
|
+
this.#ws.close();
|
|
846
|
+
}
|
|
847
|
+
this.#ws = undefined;
|
|
776
848
|
}
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
name: `${property}.${metric}`,
|
|
783
|
-
direction: directionFieldMap(aggregationType),
|
|
784
|
-
field: property
|
|
785
|
-
}];
|
|
786
|
-
});
|
|
787
|
-
}
|
|
788
|
-
function modernToLegacyGroupByClause(groupByClause) {
|
|
789
|
-
if (!groupByClause) return [];
|
|
790
|
-
return Object.entries(groupByClause).flatMap(([field, type]) => {
|
|
791
|
-
if (type === "exact") {
|
|
792
|
-
return [{
|
|
793
|
-
type,
|
|
794
|
-
field
|
|
795
|
-
}];
|
|
796
|
-
} else if ("$exactWithLimit" in type) {
|
|
797
|
-
{
|
|
798
|
-
return [{
|
|
799
|
-
type: "exact",
|
|
800
|
-
field,
|
|
801
|
-
maxGroupCount: type.$exactWithLimit
|
|
802
|
-
}];
|
|
849
|
+
if (this.#subscriptions.size > 0) {
|
|
850
|
+
if (process.env.NODE_ENV !== "production") {
|
|
851
|
+
for (const s of this.#subscriptions.values()) {
|
|
852
|
+
!(s.status !== "done" && s.status !== "error") ? process.env.NODE_ENV !== "production" ? invariant5__default.default(false, "should not have done/error subscriptions still") : invariant5__default.default(false) : undefined;
|
|
853
|
+
}
|
|
803
854
|
}
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
}];
|
|
810
|
-
} else if ("$ranges" in type) {
|
|
811
|
-
return [{
|
|
812
|
-
type: "ranges",
|
|
813
|
-
field,
|
|
814
|
-
ranges: type.$ranges.map((range) => convertRange(range))
|
|
815
|
-
}];
|
|
816
|
-
} else if ("$duration" in type) {
|
|
817
|
-
return [{
|
|
818
|
-
type: "duration",
|
|
819
|
-
field,
|
|
820
|
-
value: type.$duration[0],
|
|
821
|
-
unit: api.DurationMapping[type.$duration[1]]
|
|
822
|
-
}];
|
|
823
|
-
} else return [];
|
|
824
|
-
});
|
|
825
|
-
}
|
|
826
|
-
function convertRange(range) {
|
|
827
|
-
return {
|
|
828
|
-
startValue: range[0],
|
|
829
|
-
endValue: range[1]
|
|
830
|
-
};
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
// src/object/aggregate.ts
|
|
834
|
-
async function aggregate(clientCtx, objectType, objectSet = chunkTCHGLBKJ_cjs.resolveBaseObjectSetType(objectType), req) {
|
|
835
|
-
chunkTCHGLBKJ_cjs.resolveBaseObjectSetType(objectType);
|
|
836
|
-
const body = {
|
|
837
|
-
aggregation: modernToLegacyAggregationClause(req.$select),
|
|
838
|
-
groupBy: [],
|
|
839
|
-
where: undefined
|
|
855
|
+
for (const s of this.#subscriptions.values()) {
|
|
856
|
+
if (s.status === "subscribed") s.status = "reconnecting";
|
|
857
|
+
}
|
|
858
|
+
void this.#ensureWebsocket();
|
|
859
|
+
}
|
|
840
860
|
};
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
const ret = result.data.map((entry) => {
|
|
857
|
-
return {
|
|
858
|
-
$group: entry.group,
|
|
859
|
-
...aggregationToCountResult(entry),
|
|
860
|
-
...legacyToModernSingleAggregationResult(entry)
|
|
861
|
-
};
|
|
862
|
-
});
|
|
863
|
-
return ret;
|
|
864
|
-
}
|
|
865
|
-
function aggregationToCountResult(entry) {
|
|
866
|
-
for (const aggregateResult of entry.metrics) {
|
|
867
|
-
if (aggregateResult.name === "count") {
|
|
868
|
-
return {
|
|
869
|
-
$count: aggregateResult.value
|
|
870
|
-
};
|
|
861
|
+
#tryCatchOnError = (sub, subscriptionClosed, error) => {
|
|
862
|
+
try {
|
|
863
|
+
sub.listener.onError({
|
|
864
|
+
subscriptionClosed,
|
|
865
|
+
error
|
|
866
|
+
});
|
|
867
|
+
} catch (onErrorError) {
|
|
868
|
+
console.error(`Error encountered in an onError callback for an OSDK subscription`, onErrorError);
|
|
869
|
+
console.error(`This onError call was triggered by an error in another callback`, error);
|
|
870
|
+
console.error(`The subscription has been closed.`, error);
|
|
871
|
+
if (!subscriptionClosed) {
|
|
872
|
+
this.#logger?.error(error, "Error in onError callback");
|
|
873
|
+
this.#unsubscribe(sub, "error");
|
|
874
|
+
this.#tryCatchOnError(sub, true, onErrorError);
|
|
875
|
+
}
|
|
871
876
|
}
|
|
872
|
-
}
|
|
877
|
+
};
|
|
878
|
+
};
|
|
879
|
+
function constructWebsocketUrl(baseUrl, ontologyRid) {
|
|
880
|
+
const base = new URL(baseUrl);
|
|
881
|
+
const url = new URL(`api/v2/ontologySubscriptions/ontologies/${ontologyRid}/streamSubscriptions`, base);
|
|
882
|
+
url.protocol = url.protocol.replace("https", "wss");
|
|
883
|
+
return url;
|
|
873
884
|
}
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
...client,
|
|
878
|
-
requestContext: {
|
|
879
|
-
...client.requestContext,
|
|
880
|
-
...augment(client.requestContext)
|
|
881
|
-
}
|
|
882
|
-
});
|
|
883
|
-
|
|
884
|
-
// src/util/WireObjectSet.ts
|
|
885
|
-
var WIRE_OBJECT_SET_TYPES = /* @__PURE__ */ new Set(["base", "filter", "intersect", "reference", "searchAround", "static", "subtract", "union"]);
|
|
886
|
-
function isWireObjectSet(o) {
|
|
887
|
-
return o != null && typeof o === "object" && WIRE_OBJECT_SET_TYPES.has(o.type);
|
|
885
|
+
var uuidCounter = 0;
|
|
886
|
+
function nextUuid() {
|
|
887
|
+
return `00000000-0000-0000-0000-${(uuidCounter++).toString().padStart(12, "0")}`;
|
|
888
888
|
}
|
|
889
889
|
|
|
890
890
|
// src/objectSet/createObjectSet.ts
|
|
@@ -1013,7 +1013,6 @@ async function createWithPk(clientCtx, objectType, objectSet, primaryKey) {
|
|
|
1013
1013
|
return withPk;
|
|
1014
1014
|
}
|
|
1015
1015
|
|
|
1016
|
-
exports.ObjectSetListenerWebsocket = ObjectSetListenerWebsocket;
|
|
1017
1016
|
exports.additionalContext = additionalContext;
|
|
1018
1017
|
exports.augmentRequestContext = augmentRequestContext;
|
|
1019
1018
|
exports.createObjectSet = createObjectSet;
|
|
@@ -1025,5 +1024,5 @@ exports.hydrateAttachmentFromRid = hydrateAttachmentFromRid;
|
|
|
1025
1024
|
exports.hydrateAttachmentFromRidInternal = hydrateAttachmentFromRidInternal;
|
|
1026
1025
|
exports.isObjectSet = isObjectSet;
|
|
1027
1026
|
exports.isWireObjectSet = isWireObjectSet;
|
|
1028
|
-
//# sourceMappingURL=chunk-
|
|
1029
|
-
//# sourceMappingURL=chunk-
|
|
1027
|
+
//# sourceMappingURL=chunk-R4DO4ZKB.cjs.map
|
|
1028
|
+
//# sourceMappingURL=chunk-R4DO4ZKB.cjs.map
|