@party-stack/foundry-ontology 0.18.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -0
- package/lib/adapter/convertLoadSubsetOptions.d.ts +2 -0
- package/lib/adapter/convertLoadSubsetOptions.d.ts.map +1 -1
- package/lib/adapter/convertLoadSubsetOptions.js +158 -191
- package/lib/adapter/convertLoadSubsetOptions.js.map +1 -1
- package/lib/adapter/createFoundryOntologyBackendAdapter.d.ts +17 -15
- package/lib/adapter/createFoundryOntologyBackendAdapter.d.ts.map +1 -1
- package/lib/adapter/createFoundryOntologyBackendAdapter.js +288 -400
- package/lib/adapter/createFoundryOntologyBackendAdapter.js.map +1 -1
- package/lib/adapter/foundryActionValidation.d.ts +17 -15
- package/lib/adapter/foundryActionValidation.d.ts.map +1 -1
- package/lib/adapter/foundryActionValidation.js +206 -305
- package/lib/adapter/foundryActionValidation.js.map +1 -1
- package/lib/adapter/foundryCodec.d.ts +10 -8
- package/lib/adapter/foundryCodec.d.ts.map +1 -1
- package/lib/adapter/foundryCodec.js +180 -287
- package/lib/adapter/foundryCodec.js.map +1 -1
- package/lib/adapter/foundryMediaId.d.ts +6 -4
- package/lib/adapter/foundryMediaId.d.ts.map +1 -1
- package/lib/adapter/foundryMediaId.js +31 -32
- package/lib/adapter/foundryMediaId.js.map +1 -1
- package/lib/adapter/index.d.ts +4 -4
- package/lib/adapter/index.js +4 -4
- package/lib/adapter/objectCollectionOptions.d.ts +18 -17
- package/lib/adapter/objectCollectionOptions.d.ts.map +1 -1
- package/lib/adapter/objectCollectionOptions.js +451 -538
- package/lib/adapter/objectCollectionOptions.js.map +1 -1
- package/lib/config/applyAttachmentConstraintOverrides.d.ts +6 -4
- package/lib/config/applyAttachmentConstraintOverrides.d.ts.map +1 -1
- package/lib/config/applyAttachmentConstraintOverrides.js +45 -49
- package/lib/config/applyAttachmentConstraintOverrides.js.map +1 -1
- package/lib/config/index.d.ts +17 -15
- package/lib/config/index.d.ts.map +1 -1
- package/lib/config/index.js +56 -81
- package/lib/config/index.js.map +1 -1
- package/lib/connection.d.ts +28 -26
- package/lib/connection.d.ts.map +1 -1
- package/lib/connection.js +183 -215
- package/lib/connection.js.map +1 -1
- package/lib/index.d.ts +9 -5
- package/lib/index.js +9 -5
- package/lib/installation/createFoundryBackendInstallation.d.ts +21 -20
- package/lib/installation/createFoundryBackendInstallation.d.ts.map +1 -1
- package/lib/installation/createFoundryBackendInstallation.js +52 -62
- package/lib/installation/createFoundryBackendInstallation.js.map +1 -1
- package/lib/installation/index.d.ts +2 -2
- package/lib/installation/index.js +1 -2
- package/lib/meta/actionTypeCollectionOptions.d.ts +8 -6
- package/lib/meta/actionTypeCollectionOptions.d.ts.map +1 -1
- package/lib/meta/actionTypeCollectionOptions.js +49 -49
- package/lib/meta/actionTypeCollectionOptions.js.map +1 -1
- package/lib/meta/convertActionTypeLoadSubsetOptions.d.ts +3 -1
- package/lib/meta/convertActionTypeLoadSubsetOptions.d.ts.map +1 -1
- package/lib/meta/convertActionTypeLoadSubsetOptions.js +69 -75
- package/lib/meta/convertActionTypeLoadSubsetOptions.js.map +1 -1
- package/lib/meta/convertMetaActionType.d.ts +7 -5
- package/lib/meta/convertMetaActionType.d.ts.map +1 -1
- package/lib/meta/convertMetaActionType.js +458 -581
- package/lib/meta/convertMetaActionType.js.map +1 -1
- package/lib/meta/convertMetaLinkType.d.ts +4 -2
- package/lib/meta/convertMetaLinkType.d.ts.map +1 -1
- package/lib/meta/convertMetaLinkType.js +37 -43
- package/lib/meta/convertMetaLinkType.js.map +1 -1
- package/lib/meta/convertMetaObjectType.d.ts +4 -2
- package/lib/meta/convertMetaObjectType.d.ts.map +1 -1
- package/lib/meta/convertMetaObjectType.js +34 -35
- package/lib/meta/convertMetaObjectType.js.map +1 -1
- package/lib/meta/convertMetaQueryFunctionType.d.ts +4 -2
- package/lib/meta/convertMetaQueryFunctionType.d.ts.map +1 -1
- package/lib/meta/convertMetaQueryFunctionType.js +113 -94
- package/lib/meta/convertMetaQueryFunctionType.js.map +1 -1
- package/lib/meta/convertMetaTypeDef.d.ts +4 -2
- package/lib/meta/convertMetaTypeDef.d.ts.map +1 -1
- package/lib/meta/convertMetaTypeDef.js +178 -176
- package/lib/meta/convertMetaTypeDef.js.map +1 -1
- package/lib/meta/convertMetaValueType.d.ts +4 -2
- package/lib/meta/convertMetaValueType.d.ts.map +1 -1
- package/lib/meta/convertMetaValueType.js +11 -7
- package/lib/meta/convertMetaValueType.js.map +1 -1
- package/lib/meta/convertOmsActionParameterMetadata.d.ts +4 -2
- package/lib/meta/convertOmsActionParameterMetadata.d.ts.map +1 -1
- package/lib/meta/convertOmsActionParameterMetadata.js +107 -163
- package/lib/meta/convertOmsActionParameterMetadata.js.map +1 -1
- package/lib/meta/createFoundryMetaOntologyBackendAdapter.d.ts +7 -5
- package/lib/meta/createFoundryMetaOntologyBackendAdapter.d.ts.map +1 -1
- package/lib/meta/createFoundryMetaOntologyBackendAdapter.js +39 -41
- package/lib/meta/createFoundryMetaOntologyBackendAdapter.js.map +1 -1
- package/lib/meta/entityCollectionOptions.d.ts +12 -10
- package/lib/meta/entityCollectionOptions.d.ts.map +1 -1
- package/lib/meta/entityCollectionOptions.js +59 -62
- package/lib/meta/entityCollectionOptions.js.map +1 -1
- package/lib/meta/foundryAttachmentMetadata.d.ts +2 -0
- package/lib/meta/foundryAttachmentMetadata.d.ts.map +1 -1
- package/lib/meta/foundryAttachmentMetadata.js +13 -14
- package/lib/meta/foundryAttachmentMetadata.js.map +1 -1
- package/lib/meta/index.d.ts +5 -5
- package/lib/meta/index.js +5 -5
- package/lib/meta/loadActionTypeOmsMetadata.d.ts +5 -3
- package/lib/meta/loadActionTypeOmsMetadata.d.ts.map +1 -1
- package/lib/meta/loadActionTypeOmsMetadata.js +102 -139
- package/lib/meta/loadActionTypeOmsMetadata.js.map +1 -1
- package/lib/meta/queryFunctionTypeCollectionOptions.d.ts +7 -5
- package/lib/meta/queryFunctionTypeCollectionOptions.d.ts.map +1 -1
- package/lib/meta/queryFunctionTypeCollectionOptions.js +47 -49
- package/lib/meta/queryFunctionTypeCollectionOptions.js.map +1 -1
- package/lib/stagedWrites.d.ts +26 -24
- package/lib/stagedWrites.d.ts.map +1 -1
- package/lib/stagedWrites.js +55 -66
- package/lib/stagedWrites.js.map +1 -1
- package/lib/users/createFoundryAdminOntologyRoute.d.ts +47 -17366
- package/lib/users/createFoundryAdminOntologyRoute.d.ts.map +1 -1
- package/lib/users/createFoundryAdminOntologyRoute.js +29 -37
- package/lib/users/createFoundryAdminOntologyRoute.js.map +1 -1
- package/lib/users/createFoundryUsersIntegration.d.ts +6 -4
- package/lib/users/createFoundryUsersIntegration.d.ts.map +1 -1
- package/lib/users/createFoundryUsersIntegration.js +28 -30
- package/lib/users/createFoundryUsersIntegration.js.map +1 -1
- package/lib/users/foundryUser.d.ts +4 -2
- package/lib/users/foundryUser.d.ts.map +1 -1
- package/lib/users/foundryUser.js +69 -74
- package/lib/users/foundryUser.js.map +1 -1
- package/lib/users/index.d.ts +5 -5
- package/lib/users/index.js +5 -5
- package/lib/users/userCollectionOptions.d.ts +13 -11
- package/lib/users/userCollectionOptions.d.ts.map +1 -1
- package/lib/users/userCollectionOptions.js +82 -100
- package/lib/users/userCollectionOptions.js.map +1 -1
- package/lib/utils/AsyncIterable.d.ts +2 -0
- package/lib/utils/AsyncIterable.d.ts.map +1 -1
- package/lib/utils/AsyncIterable.js +26 -34
- package/lib/utils/AsyncIterable.js.map +1 -1
- package/lib/utils/actionTypeName.d.ts +2 -0
- package/lib/utils/actionTypeName.d.ts.map +1 -1
- package/lib/utils/actionTypeName.js +9 -7
- package/lib/utils/actionTypeName.js.map +1 -1
- package/lib/utils/chunk.d.ts +2 -0
- package/lib/utils/chunk.d.ts.map +1 -1
- package/lib/utils/chunk.js +8 -6
- package/lib/utils/chunk.js.map +1 -1
- package/package.json +21 -27
- package/lib/adapter/convertLoadSubsetOptions.test.d.ts +0 -2
- package/lib/adapter/convertLoadSubsetOptions.test.d.ts.map +0 -1
- package/lib/adapter/convertLoadSubsetOptions.test.js +0 -213
- package/lib/adapter/convertLoadSubsetOptions.test.js.map +0 -1
- package/lib/adapter/createFoundryOntologyBackendAdapter.test.d.ts +0 -2
- package/lib/adapter/createFoundryOntologyBackendAdapter.test.d.ts.map +0 -1
- package/lib/adapter/createFoundryOntologyBackendAdapter.test.js +0 -628
- package/lib/adapter/createFoundryOntologyBackendAdapter.test.js.map +0 -1
- package/lib/adapter/foundryActionValidation.test.d.ts +0 -2
- package/lib/adapter/foundryActionValidation.test.d.ts.map +0 -1
- package/lib/adapter/foundryActionValidation.test.js +0 -243
- package/lib/adapter/foundryActionValidation.test.js.map +0 -1
- package/lib/adapter/foundryCodec.test.d.ts +0 -2
- package/lib/adapter/foundryCodec.test.d.ts.map +0 -1
- package/lib/adapter/foundryCodec.test.js +0 -137
- package/lib/adapter/foundryCodec.test.js.map +0 -1
- package/lib/adapter/foundryMediaId.test.d.ts +0 -2
- package/lib/adapter/foundryMediaId.test.d.ts.map +0 -1
- package/lib/adapter/foundryMediaId.test.js +0 -23
- package/lib/adapter/foundryMediaId.test.js.map +0 -1
- package/lib/adapter/index.d.ts.map +0 -1
- package/lib/adapter/index.js.map +0 -1
- package/lib/adapter/objectCollectionOptions.test.d.ts +0 -2
- package/lib/adapter/objectCollectionOptions.test.d.ts.map +0 -1
- package/lib/adapter/objectCollectionOptions.test.js +0 -1290
- package/lib/adapter/objectCollectionOptions.test.js.map +0 -1
- package/lib/config/connectionPull.test.d.ts +0 -2
- package/lib/config/connectionPull.test.d.ts.map +0 -1
- package/lib/config/connectionPull.test.js +0 -151
- package/lib/config/connectionPull.test.js.map +0 -1
- package/lib/config/index.test.d.ts +0 -2
- package/lib/config/index.test.d.ts.map +0 -1
- package/lib/config/index.test.js +0 -182
- package/lib/config/index.test.js.map +0 -1
- package/lib/connection.test.d.ts +0 -2
- package/lib/connection.test.d.ts.map +0 -1
- package/lib/connection.test.js +0 -162
- package/lib/connection.test.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/installation/createFoundryBackendInstallation.test.d.ts +0 -2
- package/lib/installation/createFoundryBackendInstallation.test.d.ts.map +0 -1
- package/lib/installation/createFoundryBackendInstallation.test.js +0 -83
- package/lib/installation/createFoundryBackendInstallation.test.js.map +0 -1
- package/lib/installation/index.d.ts.map +0 -1
- package/lib/installation/index.js.map +0 -1
- package/lib/meta/actionTypeCollectionOptions.test.d.ts +0 -2
- package/lib/meta/actionTypeCollectionOptions.test.d.ts.map +0 -1
- package/lib/meta/actionTypeCollectionOptions.test.js +0 -24
- package/lib/meta/actionTypeCollectionOptions.test.js.map +0 -1
- package/lib/meta/actionTypeIdQuery.test.d.ts +0 -2
- package/lib/meta/actionTypeIdQuery.test.d.ts.map +0 -1
- package/lib/meta/actionTypeIdQuery.test.js +0 -131
- package/lib/meta/actionTypeIdQuery.test.js.map +0 -1
- package/lib/meta/convertActionTypeLoadSubsetOptions.test.d.ts +0 -2
- package/lib/meta/convertActionTypeLoadSubsetOptions.test.d.ts.map +0 -1
- package/lib/meta/convertActionTypeLoadSubsetOptions.test.js +0 -138
- package/lib/meta/convertActionTypeLoadSubsetOptions.test.js.map +0 -1
- package/lib/meta/convertMetaActionType.test.d.ts +0 -2
- package/lib/meta/convertMetaActionType.test.d.ts.map +0 -1
- package/lib/meta/convertMetaActionType.test.js +0 -1565
- package/lib/meta/convertMetaActionType.test.js.map +0 -1
- package/lib/meta/convertMetaLinkType.test.d.ts +0 -2
- package/lib/meta/convertMetaLinkType.test.d.ts.map +0 -1
- package/lib/meta/convertMetaLinkType.test.js +0 -110
- package/lib/meta/convertMetaLinkType.test.js.map +0 -1
- package/lib/meta/convertMetaObjectType.test.d.ts +0 -2
- package/lib/meta/convertMetaObjectType.test.d.ts.map +0 -1
- package/lib/meta/convertMetaObjectType.test.js +0 -250
- package/lib/meta/convertMetaObjectType.test.js.map +0 -1
- package/lib/meta/convertMetaQueryFunctionType.test.d.ts +0 -2
- package/lib/meta/convertMetaQueryFunctionType.test.d.ts.map +0 -1
- package/lib/meta/convertMetaQueryFunctionType.test.js +0 -134
- package/lib/meta/convertMetaQueryFunctionType.test.js.map +0 -1
- package/lib/meta/createFoundryMetaOntologyBackendAdapter.test.d.ts +0 -2
- package/lib/meta/createFoundryMetaOntologyBackendAdapter.test.d.ts.map +0 -1
- package/lib/meta/createFoundryMetaOntologyBackendAdapter.test.js +0 -49
- package/lib/meta/createFoundryMetaOntologyBackendAdapter.test.js.map +0 -1
- package/lib/meta/entityCollectionOptions.test.d.ts +0 -2
- package/lib/meta/entityCollectionOptions.test.d.ts.map +0 -1
- package/lib/meta/entityCollectionOptions.test.js +0 -98
- package/lib/meta/entityCollectionOptions.test.js.map +0 -1
- package/lib/meta/index.d.ts.map +0 -1
- package/lib/meta/index.js.map +0 -1
- package/lib/meta/loadActionTypeOmsMetadata.test.d.ts +0 -2
- package/lib/meta/loadActionTypeOmsMetadata.test.d.ts.map +0 -1
- package/lib/meta/loadActionTypeOmsMetadata.test.js +0 -218
- package/lib/meta/loadActionTypeOmsMetadata.test.js.map +0 -1
- package/lib/stagedWrites.test.d.ts +0 -2
- package/lib/stagedWrites.test.d.ts.map +0 -1
- package/lib/stagedWrites.test.js +0 -71
- package/lib/stagedWrites.test.js.map +0 -1
- package/lib/users/createFoundryUsersIntegration.test.d.ts +0 -2
- package/lib/users/createFoundryUsersIntegration.test.d.ts.map +0 -1
- package/lib/users/createFoundryUsersIntegration.test.js +0 -32
- package/lib/users/createFoundryUsersIntegration.test.js.map +0 -1
- package/lib/users/foundryUser.test.d.ts +0 -2
- package/lib/users/foundryUser.test.d.ts.map +0 -1
- package/lib/users/foundryUser.test.js +0 -45
- package/lib/users/foundryUser.test.js.map +0 -1
- package/lib/users/index.d.ts.map +0 -1
- package/lib/users/index.js.map +0 -1
- package/lib/users/userCollectionOptions.test.d.ts +0 -2
- package/lib/users/userCollectionOptions.test.d.ts.map +0 -1
- package/lib/users/userCollectionOptions.test.js +0 -18
- package/lib/users/userCollectionOptions.test.js.map +0 -1
- package/lib/utils/AsyncIterable.test.d.ts +0 -2
- package/lib/utils/AsyncIterable.test.d.ts.map +0 -1
- package/lib/utils/AsyncIterable.test.js +0 -17
- package/lib/utils/AsyncIterable.test.js.map +0 -1
- package/lib/utils/actionTypeName.test.d.ts +0 -2
- package/lib/utils/actionTypeName.test.d.ts.map +0 -1
- package/lib/utils/actionTypeName.test.js +0 -30
- package/lib/utils/actionTypeName.test.js.map +0 -1
|
@@ -1,569 +1,482 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { fromPagination, toArray } from "../utils/AsyncIterable.js";
|
|
2
|
+
import { convertLoadSubsetFilter, convertLoadSubsetOrderBy, isAlwaysFalseFilter } from "./convertLoadSubsetOptions.js";
|
|
3
|
+
import { ObjectTypesV2, OntologyObjectsV2 } from "@osdk/foundry.ontologies";
|
|
2
4
|
import { getObjectSetWatcherManager } from "@party-stack/foundry-object-set-watcher";
|
|
3
|
-
import { BasicIndex, DeduplicatedLoadSubset
|
|
5
|
+
import { BasicIndex, DeduplicatedLoadSubset } from "@tanstack/db";
|
|
4
6
|
import { Store } from "@tanstack/store";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
|
-
// Edit history helpers
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
|
-
const EDIT_HISTORY_PAGE_SIZE = 1_000;
|
|
7
|
+
//#region src/adapter/objectCollectionOptions.ts
|
|
8
|
+
const COLLECTION_SYNC_TIMEOUT_MS = 5e3;
|
|
9
|
+
var TimeoutWaitingForOperationIdError = class extends Error {
|
|
10
|
+
constructor(operationId, objectType) {
|
|
11
|
+
super(`Timed out waiting for Foundry operation ${operationId} to sync for ${objectType}.`);
|
|
12
|
+
this.name = "TimeoutWaitingForOperationIdError";
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
var ObjectCollectionSyncAbortedError = class extends Error {
|
|
16
|
+
constructor(objectType) {
|
|
17
|
+
super(`Foundry sync for ${objectType} stopped before the operation was observed.`);
|
|
18
|
+
this.name = "ObjectCollectionSyncAbortedError";
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
const EDIT_HISTORY_PAGE_SIZE = 1e3;
|
|
24
22
|
const EDIT_HISTORY_CURSOR_METADATA_KEY = "foundry.editHistoryCursor";
|
|
25
23
|
const EDIT_HISTORY_CURSOR_VERSION = 1;
|
|
26
|
-
function createEditHistoryCursor(timestamp = new Date().toISOString()) {
|
|
27
|
-
|
|
24
|
+
function createEditHistoryCursor(timestamp = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
25
|
+
return {
|
|
26
|
+
timestamp,
|
|
27
|
+
seenEntryKeysAtTimestamp: /* @__PURE__ */ new Set()
|
|
28
|
+
};
|
|
28
29
|
}
|
|
29
30
|
function cloneEditHistoryCursor(cursor) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
return {
|
|
32
|
+
timestamp: cursor.timestamp,
|
|
33
|
+
seenEntryKeysAtTimestamp: new Set(cursor.seenEntryKeysAtTimestamp)
|
|
34
|
+
};
|
|
34
35
|
}
|
|
35
36
|
function serializeEditHistoryCursor(cursor) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
return {
|
|
38
|
+
version: EDIT_HISTORY_CURSOR_VERSION,
|
|
39
|
+
timestamp: cursor.timestamp,
|
|
40
|
+
seenEntryKeysAtTimestamp: [...cursor.seenEntryKeysAtTimestamp].sort()
|
|
41
|
+
};
|
|
41
42
|
}
|
|
42
43
|
function deserializeEditHistoryCursor(value) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return undefined;
|
|
49
|
-
}
|
|
50
|
-
return {
|
|
51
|
-
timestamp: value.timestamp,
|
|
52
|
-
seenEntryKeysAtTimestamp: new Set(value.seenEntryKeysAtTimestamp),
|
|
53
|
-
};
|
|
44
|
+
if (!isPlainObject(value) || value.version !== EDIT_HISTORY_CURSOR_VERSION || typeof value.timestamp !== "string" || !Array.isArray(value.seenEntryKeysAtTimestamp) || !value.seenEntryKeysAtTimestamp.every((key) => typeof key === "string")) return;
|
|
45
|
+
return {
|
|
46
|
+
timestamp: value.timestamp,
|
|
47
|
+
seenEntryKeysAtTimestamp: new Set(value.seenEntryKeysAtTimestamp)
|
|
48
|
+
};
|
|
54
49
|
}
|
|
55
50
|
function editHistoryCursorsEqual(left, right) {
|
|
56
|
-
|
|
57
|
-
left.seenEntryKeysAtTimestamp.size === right.seenEntryKeysAtTimestamp.size &&
|
|
58
|
-
[...left.seenEntryKeysAtTimestamp].every((key) => right.seenEntryKeysAtTimestamp.has(key)));
|
|
51
|
+
return left.timestamp === right.timestamp && left.seenEntryKeysAtTimestamp.size === right.seenEntryKeysAtTimestamp.size && [...left.seenEntryKeysAtTimestamp].every((key) => right.seenEntryKeysAtTimestamp.has(key));
|
|
59
52
|
}
|
|
60
53
|
function canonicalizeJsonValue(value) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return Object.fromEntries(Object.keys(value)
|
|
65
|
-
.sort()
|
|
66
|
-
.map((key) => [key, canonicalizeJsonValue(value[key])]));
|
|
67
|
-
}
|
|
68
|
-
return value;
|
|
54
|
+
if (Array.isArray(value)) return value.map(canonicalizeJsonValue);
|
|
55
|
+
if (isPlainObject(value)) return Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonicalizeJsonValue(value[key])]));
|
|
56
|
+
return value;
|
|
69
57
|
}
|
|
70
58
|
function getEditHistoryEntryKey(entry) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
59
|
+
return JSON.stringify(canonicalizeJsonValue({
|
|
60
|
+
objectPrimaryKey: entry.objectPrimaryKey,
|
|
61
|
+
operationId: entry.operationId,
|
|
62
|
+
timestamp: entry.timestamp,
|
|
63
|
+
edit: entry.edit
|
|
64
|
+
}));
|
|
77
65
|
}
|
|
78
66
|
function shouldProcessEditHistoryEntry(cursor, entry) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
return !cursor.seenEntryKeysAtTimestamp.has(getEditHistoryEntryKey(entry));
|
|
83
|
-
}
|
|
84
|
-
return true;
|
|
67
|
+
if (entry.timestamp < cursor.timestamp) return false;
|
|
68
|
+
if (entry.timestamp === cursor.timestamp) return !cursor.seenEntryKeysAtTimestamp.has(getEditHistoryEntryKey(entry));
|
|
69
|
+
return true;
|
|
85
70
|
}
|
|
86
71
|
function advanceEditHistoryCursor(cursor, entry) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
72
|
+
const entryKey = getEditHistoryEntryKey(entry);
|
|
73
|
+
if (entry.timestamp > cursor.timestamp) {
|
|
74
|
+
cursor.timestamp = entry.timestamp;
|
|
75
|
+
cursor.seenEntryKeysAtTimestamp.clear();
|
|
76
|
+
}
|
|
77
|
+
cursor.seenEntryKeysAtTimestamp.add(entryKey);
|
|
93
78
|
}
|
|
94
79
|
function getPrimaryKeyValue(primaryKey, primaryKeyProperty, decodeEditObject) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
[primaryKeyProperty]: values[0],
|
|
101
|
-
})[primaryKeyProperty];
|
|
102
|
-
if (typeof value !== "string" && typeof value !== "number") {
|
|
103
|
-
throw new Error("Foundry object collections currently only support string or number primary keys.");
|
|
104
|
-
}
|
|
105
|
-
return value;
|
|
80
|
+
const values = Object.values(primaryKey);
|
|
81
|
+
if (values.length !== 1) throw new Error("Foundry object collections currently only support single-field primary keys.");
|
|
82
|
+
const value = decodeEditObject({ [primaryKeyProperty]: values[0] })[primaryKeyProperty];
|
|
83
|
+
if (typeof value !== "string" && typeof value !== "number") throw new Error("Foundry object collections currently only support string or number primary keys.");
|
|
84
|
+
return value;
|
|
106
85
|
}
|
|
107
86
|
function isPlainObject(value) {
|
|
108
|
-
|
|
87
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
109
88
|
}
|
|
110
|
-
// ---------------------------------------------------------------------------
|
|
111
|
-
// Foundry object fetching
|
|
112
|
-
// ---------------------------------------------------------------------------
|
|
113
89
|
async function fetchFoundryObjects(client, objectType, selectedProperties, opts, decodeObject = (object) => object) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
pageSize,
|
|
148
|
-
pageToken,
|
|
149
|
-
orderBy: convertLoadSubsetOrderBy(opts.orderBy),
|
|
150
|
-
}), (page) => page.nextPageToken, (page) => page.data, 10_000, limit === undefined ? undefined : offset + limit));
|
|
151
|
-
opts.signal?.throwIfAborted();
|
|
152
|
-
return results
|
|
153
|
-
.slice(offset, limit === undefined ? undefined : offset + limit)
|
|
154
|
-
.map(decodeObject);
|
|
90
|
+
opts.signal?.throwIfAborted();
|
|
91
|
+
const offset = Math.max(0, Math.trunc(opts.offset ?? 0));
|
|
92
|
+
const limit = opts.limit === void 0 ? void 0 : Math.max(0, Math.trunc(opts.limit));
|
|
93
|
+
if (limit === 0) return [];
|
|
94
|
+
let where = convertLoadSubsetFilter(opts.where);
|
|
95
|
+
if (isAlwaysFalseFilter(where) || where?.type === "in" && where.value.length === 0) return [];
|
|
96
|
+
if (opts.cursor?.whereFrom) {
|
|
97
|
+
const cursorWhere = convertLoadSubsetFilter(opts.cursor.whereFrom);
|
|
98
|
+
if (isAlwaysFalseFilter(cursorWhere)) return [];
|
|
99
|
+
if (cursorWhere) where = where ? {
|
|
100
|
+
type: "and",
|
|
101
|
+
value: [where, cursorWhere]
|
|
102
|
+
} : cursorWhere;
|
|
103
|
+
}
|
|
104
|
+
const requestClient = opts.signal ? {
|
|
105
|
+
...client,
|
|
106
|
+
fetch: (input, init) => client.fetch(input, {
|
|
107
|
+
...init,
|
|
108
|
+
signal: opts.signal
|
|
109
|
+
})
|
|
110
|
+
} : client;
|
|
111
|
+
const results = await toArray(fromPagination((pageSize, pageToken) => OntologyObjectsV2.search(requestClient, client.ontologyRid, objectType, {
|
|
112
|
+
snapshot: true,
|
|
113
|
+
where,
|
|
114
|
+
excludeRid: true,
|
|
115
|
+
select: selectedProperties,
|
|
116
|
+
selectV2: [],
|
|
117
|
+
pageSize,
|
|
118
|
+
pageToken,
|
|
119
|
+
orderBy: convertLoadSubsetOrderBy(opts.orderBy)
|
|
120
|
+
}), (page) => page.nextPageToken, (page) => page.data, 1e4, limit === void 0 ? void 0 : offset + limit));
|
|
121
|
+
opts.signal?.throwIfAborted();
|
|
122
|
+
return results.slice(offset, limit === void 0 ? void 0 : offset + limit).map(decodeObject);
|
|
155
123
|
}
|
|
156
124
|
function createSyncConfig(client, objectType, primaryKeyProperty, selectedProperties, decodeObject = (object) => object, decodeEditObject = decodeObject, live = true) {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
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
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
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
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
void applyDirectWatcherUpdates(message.updates).catch((error) => {
|
|
492
|
-
console.warn(`Failed to apply direct Foundry updates for ${objectType}.`, error);
|
|
493
|
-
requestFullRefresh?.();
|
|
494
|
-
});
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
else {
|
|
498
|
-
pendingDirectWatcherUpdates.push(...message.updates);
|
|
499
|
-
requestEditHistoryCatchUp?.();
|
|
500
|
-
}
|
|
501
|
-
break;
|
|
502
|
-
}
|
|
503
|
-
case "refresh": {
|
|
504
|
-
if (editHistoryUnavailable) {
|
|
505
|
-
requestFullRefresh?.();
|
|
506
|
-
}
|
|
507
|
-
else {
|
|
508
|
-
requestEditHistoryCatchUp?.();
|
|
509
|
-
}
|
|
510
|
-
break;
|
|
511
|
-
}
|
|
512
|
-
case "state": {
|
|
513
|
-
if (message.status !== "open")
|
|
514
|
-
break;
|
|
515
|
-
if (editHistoryUnavailable) {
|
|
516
|
-
requestFullRefresh?.();
|
|
517
|
-
}
|
|
518
|
-
else {
|
|
519
|
-
requestEditHistoryCatchUp?.();
|
|
520
|
-
}
|
|
521
|
-
break;
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
})
|
|
525
|
-
: () => { };
|
|
526
|
-
// start task here, cleanup can stop it
|
|
527
|
-
// in that task:
|
|
528
|
-
// - spawn object set subscription, which sends messages to catch up
|
|
529
|
-
// - actions sends messages to catch up
|
|
530
|
-
if (initialCommit === true) {
|
|
531
|
-
markReady();
|
|
532
|
-
}
|
|
533
|
-
else {
|
|
534
|
-
void initialCommit.then(markReady, markError);
|
|
535
|
-
}
|
|
536
|
-
return {
|
|
537
|
-
loadSubset: loadSubsetDedupe.loadSubset,
|
|
538
|
-
cleanup: () => {
|
|
539
|
-
disposed = true;
|
|
540
|
-
requestEditHistoryCatchUp = undefined;
|
|
541
|
-
requestFullRefresh = undefined;
|
|
542
|
-
syncDisposed.setState(() => true);
|
|
543
|
-
unsubscribe();
|
|
544
|
-
loadSubsetDedupe.reset();
|
|
545
|
-
},
|
|
546
|
-
};
|
|
547
|
-
},
|
|
548
|
-
};
|
|
549
|
-
return { sync, utils };
|
|
125
|
+
const seenOperationIds = new Store(/* @__PURE__ */ new Set());
|
|
126
|
+
const syncDisposed = new Store(false);
|
|
127
|
+
const fullSourceRefreshVersion = new Store(0);
|
|
128
|
+
let editHistoryUnavailable = false;
|
|
129
|
+
let requestFullRefresh;
|
|
130
|
+
const refresh = async () => {
|
|
131
|
+
if (!requestFullRefresh || syncDisposed.state) throw new ObjectCollectionSyncAbortedError(objectType);
|
|
132
|
+
await requestFullRefresh();
|
|
133
|
+
};
|
|
134
|
+
const refreshInBackground = () => {
|
|
135
|
+
refresh().catch((error) => {
|
|
136
|
+
console.warn(`Failed full Foundry refresh for ${objectType}.`, error);
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
let requestEditHistoryCatchUp;
|
|
140
|
+
const awaitOperationId = async (operationId, timeout = COLLECTION_SYNC_TIMEOUT_MS) => {
|
|
141
|
+
if (typeof operationId !== "string" || operationId.length === 0) throw new Error("Foundry operationId must be a non-empty string.");
|
|
142
|
+
if (seenOperationIds.state.has(operationId)) return;
|
|
143
|
+
if (syncDisposed.state) throw new ObjectCollectionSyncAbortedError(objectType);
|
|
144
|
+
if (!requestEditHistoryCatchUp) return;
|
|
145
|
+
const refreshVersionAtStart = fullSourceRefreshVersion.state;
|
|
146
|
+
const historyUnavailableAtStart = editHistoryUnavailable;
|
|
147
|
+
return new Promise((resolve, reject) => {
|
|
148
|
+
const cleanup = () => {
|
|
149
|
+
clearTimeout(timeoutId);
|
|
150
|
+
seenOperationIdsSubscription.unsubscribe();
|
|
151
|
+
fullSourceRefreshVersionSubscription.unsubscribe();
|
|
152
|
+
disposedSubscription.unsubscribe();
|
|
153
|
+
};
|
|
154
|
+
const timeoutId = setTimeout(() => {
|
|
155
|
+
cleanup();
|
|
156
|
+
reject(new TimeoutWaitingForOperationIdError(operationId, objectType));
|
|
157
|
+
}, timeout);
|
|
158
|
+
const seenOperationIdsSubscription = seenOperationIds.subscribe(() => {
|
|
159
|
+
if (seenOperationIds.state.has(operationId)) {
|
|
160
|
+
cleanup();
|
|
161
|
+
resolve();
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
const fullSourceRefreshVersionSubscription = fullSourceRefreshVersion.subscribe(() => {
|
|
165
|
+
if (!historyUnavailableAtStart && editHistoryUnavailable && fullSourceRefreshVersion.state > refreshVersionAtStart) {
|
|
166
|
+
cleanup();
|
|
167
|
+
resolve();
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
const disposedSubscription = syncDisposed.subscribe(() => {
|
|
171
|
+
if (syncDisposed.state) {
|
|
172
|
+
cleanup();
|
|
173
|
+
reject(new ObjectCollectionSyncAbortedError(objectType));
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
if (editHistoryUnavailable) refresh().then(() => {
|
|
177
|
+
cleanup();
|
|
178
|
+
resolve();
|
|
179
|
+
}, (error) => {
|
|
180
|
+
cleanup();
|
|
181
|
+
reject(error);
|
|
182
|
+
});
|
|
183
|
+
else requestEditHistoryCatchUp?.();
|
|
184
|
+
});
|
|
185
|
+
};
|
|
186
|
+
return {
|
|
187
|
+
sync: { sync: (params) => {
|
|
188
|
+
const { begin, write, commit, markError, markReady, truncate } = params;
|
|
189
|
+
const collectionMetadata = params.metadata?.collection;
|
|
190
|
+
syncDisposed.setState(() => false);
|
|
191
|
+
let disposed = false;
|
|
192
|
+
const restoredEditHistoryCursor = deserializeEditHistoryCursor(collectionMetadata?.get(EDIT_HISTORY_CURSOR_METADATA_KEY));
|
|
193
|
+
let editHistoryCursor = restoredEditHistoryCursor ?? createEditHistoryCursor();
|
|
194
|
+
let initialCommit = true;
|
|
195
|
+
if (!restoredEditHistoryCursor) {
|
|
196
|
+
if (collectionMetadata) {
|
|
197
|
+
begin();
|
|
198
|
+
collectionMetadata.set(EDIT_HISTORY_CURSOR_METADATA_KEY, serializeEditHistoryCursor(editHistoryCursor));
|
|
199
|
+
initialCommit = commit();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
let catchUpRequested = false;
|
|
203
|
+
let catchUpTask;
|
|
204
|
+
let pendingDirectWatcherUpdates = [];
|
|
205
|
+
let fullRefreshRequested = false;
|
|
206
|
+
let fullRefreshTask;
|
|
207
|
+
const getObjectKey = (object) => object[primaryKeyProperty];
|
|
208
|
+
const getWatcherObjectKey = (object) => {
|
|
209
|
+
const key = object[primaryKeyProperty] ?? object.__primaryKey;
|
|
210
|
+
if (typeof key !== "string" && typeof key !== "number") throw new Error(`Foundry websocket update for ${objectType} did not include a supported primary key.`);
|
|
211
|
+
return key;
|
|
212
|
+
};
|
|
213
|
+
const upsertObject = (object) => {
|
|
214
|
+
const key = getObjectKey(object);
|
|
215
|
+
const exists = params.collection.has(key);
|
|
216
|
+
const existing = exists ? params.collection.get(key) : void 0;
|
|
217
|
+
write({
|
|
218
|
+
type: exists ? "update" : "insert",
|
|
219
|
+
value: existing ? {
|
|
220
|
+
...existing,
|
|
221
|
+
...object
|
|
222
|
+
} : object
|
|
223
|
+
});
|
|
224
|
+
};
|
|
225
|
+
const deleteObjectByKey = (key) => {
|
|
226
|
+
write({
|
|
227
|
+
type: "delete",
|
|
228
|
+
key
|
|
229
|
+
});
|
|
230
|
+
return true;
|
|
231
|
+
};
|
|
232
|
+
const fetchEditHistoryPage = (body) => ObjectTypesV2.getEditsHistory(client, client.ontologyRid, objectType, body, { preview: true });
|
|
233
|
+
const decodeEditProperties = (properties, primaryKey) => decodeEditObject({
|
|
234
|
+
...properties,
|
|
235
|
+
[primaryKeyProperty]: primaryKey
|
|
236
|
+
});
|
|
237
|
+
const decodeWatcherObject = (object, primaryKey) => decodeObject({
|
|
238
|
+
...object,
|
|
239
|
+
[primaryKeyProperty]: primaryKey
|
|
240
|
+
});
|
|
241
|
+
const applyDirectWatcherUpdates = async (updates) => {
|
|
242
|
+
const pendingMutations = /* @__PURE__ */ new Map();
|
|
243
|
+
for (const update of updates) {
|
|
244
|
+
if (update.type !== "object") continue;
|
|
245
|
+
const object = update.object;
|
|
246
|
+
const primaryKey = getWatcherObjectKey(object);
|
|
247
|
+
switch (update.state) {
|
|
248
|
+
case "ADDED_OR_UPDATED":
|
|
249
|
+
pendingMutations.set(primaryKey, {
|
|
250
|
+
type: "upsert",
|
|
251
|
+
object: decodeWatcherObject(object, primaryKey)
|
|
252
|
+
});
|
|
253
|
+
break;
|
|
254
|
+
case "REMOVED": pendingMutations.set(primaryKey, { type: "delete" });
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
let transactionStarted = false;
|
|
258
|
+
for (const [primaryKey, mutation] of pendingMutations) {
|
|
259
|
+
if (!transactionStarted) {
|
|
260
|
+
begin();
|
|
261
|
+
transactionStarted = true;
|
|
262
|
+
}
|
|
263
|
+
if (mutation.type === "delete") deleteObjectByKey(primaryKey);
|
|
264
|
+
else upsertObject(mutation.object);
|
|
265
|
+
}
|
|
266
|
+
const receipt = transactionStarted ? commit() : true;
|
|
267
|
+
if (receipt !== true) await receipt;
|
|
268
|
+
};
|
|
269
|
+
const switchToDirectWebsocketMode = (error) => {
|
|
270
|
+
if (!editHistoryUnavailable) {
|
|
271
|
+
const errorMessage = error instanceof Error ? error.message : error;
|
|
272
|
+
console.warn(`Edit history catch-up failed for ${objectType}; falling back to direct websocket updates.`, errorMessage);
|
|
273
|
+
editHistoryUnavailable = true;
|
|
274
|
+
}
|
|
275
|
+
if (pendingDirectWatcherUpdates.length > 0) {
|
|
276
|
+
const updates = pendingDirectWatcherUpdates;
|
|
277
|
+
pendingDirectWatcherUpdates = [];
|
|
278
|
+
applyDirectWatcherUpdates(updates).catch((applyError) => {
|
|
279
|
+
console.warn(`Failed to apply direct Foundry updates for ${objectType}.`, applyError);
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
refreshInBackground();
|
|
283
|
+
};
|
|
284
|
+
const catchUpFromEditHistory = async () => {
|
|
285
|
+
const nextEditHistoryCursor = cloneEditHistoryCursor(editHistoryCursor);
|
|
286
|
+
const pendingMutations = /* @__PURE__ */ new Map();
|
|
287
|
+
const newOperationIds = /* @__PURE__ */ new Set();
|
|
288
|
+
for await (const entry of fromPagination((pageSize, pageToken) => fetchEditHistoryPage({
|
|
289
|
+
filters: {
|
|
290
|
+
type: "timestampFilter",
|
|
291
|
+
startTime: nextEditHistoryCursor.timestamp
|
|
292
|
+
},
|
|
293
|
+
includeAllPreviousProperties: true,
|
|
294
|
+
pageSize,
|
|
295
|
+
pageToken,
|
|
296
|
+
sortOrder: "oldest_first"
|
|
297
|
+
}), (page) => page.nextPageToken, (page) => page.data, EDIT_HISTORY_PAGE_SIZE)) {
|
|
298
|
+
if (disposed) break;
|
|
299
|
+
if (!shouldProcessEditHistoryEntry(nextEditHistoryCursor, entry)) continue;
|
|
300
|
+
advanceEditHistoryCursor(nextEditHistoryCursor, entry);
|
|
301
|
+
newOperationIds.add(entry.operationId);
|
|
302
|
+
const primaryKey = getPrimaryKeyValue(entry.objectPrimaryKey, primaryKeyProperty, decodeEditObject);
|
|
303
|
+
switch (entry.edit.type) {
|
|
304
|
+
case "createEdit":
|
|
305
|
+
case "modifyEdit":
|
|
306
|
+
pendingMutations.set(primaryKey, {
|
|
307
|
+
type: "upsert",
|
|
308
|
+
object: decodeEditProperties(entry.edit.properties, primaryKey)
|
|
309
|
+
});
|
|
310
|
+
break;
|
|
311
|
+
case "deleteEdit": pendingMutations.set(primaryKey, { type: "delete" });
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
if (disposed) return;
|
|
315
|
+
const checkpointChanged = !editHistoryCursorsEqual(editHistoryCursor, nextEditHistoryCursor);
|
|
316
|
+
let transactionStarted = false;
|
|
317
|
+
const ensureTransaction = () => {
|
|
318
|
+
if (transactionStarted) return;
|
|
319
|
+
begin();
|
|
320
|
+
transactionStarted = true;
|
|
321
|
+
};
|
|
322
|
+
for (const [primaryKey, mutation] of pendingMutations) {
|
|
323
|
+
ensureTransaction();
|
|
324
|
+
if (mutation.type === "delete") deleteObjectByKey(primaryKey);
|
|
325
|
+
else upsertObject(mutation.object);
|
|
326
|
+
}
|
|
327
|
+
if (checkpointChanged && collectionMetadata) {
|
|
328
|
+
ensureTransaction();
|
|
329
|
+
collectionMetadata.set(EDIT_HISTORY_CURSOR_METADATA_KEY, serializeEditHistoryCursor(nextEditHistoryCursor));
|
|
330
|
+
}
|
|
331
|
+
const receipt = transactionStarted ? commit() : true;
|
|
332
|
+
if (checkpointChanged) editHistoryCursor = nextEditHistoryCursor;
|
|
333
|
+
if (newOperationIds.size > 0) seenOperationIds.setState((current) => /* @__PURE__ */ new Set([...current, ...newOperationIds]));
|
|
334
|
+
pendingDirectWatcherUpdates = [];
|
|
335
|
+
if (receipt !== true) await receipt;
|
|
336
|
+
};
|
|
337
|
+
const refreshAllFromSource = async () => {
|
|
338
|
+
const objects = await fetchFoundryObjects(client, objectType, selectedProperties, {}, decodeObject);
|
|
339
|
+
if (disposed) throw new ObjectCollectionSyncAbortedError(objectType);
|
|
340
|
+
begin();
|
|
341
|
+
truncate();
|
|
342
|
+
for (const object of objects) write({
|
|
343
|
+
type: "insert",
|
|
344
|
+
value: object
|
|
345
|
+
});
|
|
346
|
+
const receipt = commit();
|
|
347
|
+
if (receipt !== true) await receipt;
|
|
348
|
+
if (disposed) throw new ObjectCollectionSyncAbortedError(objectType);
|
|
349
|
+
while (pendingDirectWatcherUpdates.length > 0 && !disposed) {
|
|
350
|
+
const updates = pendingDirectWatcherUpdates;
|
|
351
|
+
pendingDirectWatcherUpdates = [];
|
|
352
|
+
await applyDirectWatcherUpdates(updates);
|
|
353
|
+
}
|
|
354
|
+
if (disposed) throw new ObjectCollectionSyncAbortedError(objectType);
|
|
355
|
+
fullSourceRefreshVersion.setState((version) => version + 1);
|
|
356
|
+
};
|
|
357
|
+
requestFullRefresh = () => {
|
|
358
|
+
fullRefreshRequested = true;
|
|
359
|
+
if (fullRefreshTask) return fullRefreshTask;
|
|
360
|
+
const priorCatchUp = catchUpTask;
|
|
361
|
+
fullRefreshTask = (async () => {
|
|
362
|
+
if (priorCatchUp) await priorCatchUp;
|
|
363
|
+
if (disposed) throw new ObjectCollectionSyncAbortedError(objectType);
|
|
364
|
+
while (fullRefreshRequested && !disposed) {
|
|
365
|
+
fullRefreshRequested = false;
|
|
366
|
+
await refreshAllFromSource();
|
|
367
|
+
}
|
|
368
|
+
})().catch(async (error) => {
|
|
369
|
+
while (pendingDirectWatcherUpdates.length > 0 && !disposed) {
|
|
370
|
+
const updates = pendingDirectWatcherUpdates;
|
|
371
|
+
pendingDirectWatcherUpdates = [];
|
|
372
|
+
try {
|
|
373
|
+
await applyDirectWatcherUpdates(updates);
|
|
374
|
+
} catch (applyError) {
|
|
375
|
+
console.warn(`Failed to apply queued Foundry updates for ${objectType}.`, applyError);
|
|
376
|
+
break;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
throw error;
|
|
380
|
+
}).finally(() => {
|
|
381
|
+
fullRefreshTask = void 0;
|
|
382
|
+
if (fullRefreshRequested && !disposed) refreshInBackground();
|
|
383
|
+
});
|
|
384
|
+
return fullRefreshTask;
|
|
385
|
+
};
|
|
386
|
+
requestEditHistoryCatchUp = () => {
|
|
387
|
+
if (editHistoryUnavailable) return;
|
|
388
|
+
catchUpRequested = true;
|
|
389
|
+
if (catchUpTask) return;
|
|
390
|
+
const priorRefresh = fullRefreshTask;
|
|
391
|
+
catchUpTask = (async () => {
|
|
392
|
+
if (priorRefresh) await priorRefresh;
|
|
393
|
+
while (catchUpRequested && !disposed) {
|
|
394
|
+
catchUpRequested = false;
|
|
395
|
+
await catchUpFromEditHistory();
|
|
396
|
+
}
|
|
397
|
+
})().catch((error) => {
|
|
398
|
+
switchToDirectWebsocketMode(error);
|
|
399
|
+
}).finally(() => {
|
|
400
|
+
catchUpTask = void 0;
|
|
401
|
+
if (catchUpRequested && !disposed) requestEditHistoryCatchUp?.();
|
|
402
|
+
});
|
|
403
|
+
};
|
|
404
|
+
const loadSubset = async (opts) => {
|
|
405
|
+
const objects = await fetchFoundryObjects(client, objectType, selectedProperties, opts, decodeObject);
|
|
406
|
+
if (objects.length > 0) {
|
|
407
|
+
begin();
|
|
408
|
+
for (const object of objects) upsertObject(object);
|
|
409
|
+
const receipt = commit(opts.signal);
|
|
410
|
+
if (receipt !== true) await receipt;
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
const loadSubsetDedupe = new DeduplicatedLoadSubset({ loadSubset });
|
|
414
|
+
const unsubscribe = live ? getObjectSetWatcherManager(client).subscribe({
|
|
415
|
+
type: "base",
|
|
416
|
+
objectType
|
|
417
|
+
}, (message) => {
|
|
418
|
+
switch (message.type) {
|
|
419
|
+
case "change":
|
|
420
|
+
if (fullRefreshTask) pendingDirectWatcherUpdates.push(...message.updates);
|
|
421
|
+
else if (editHistoryUnavailable) applyDirectWatcherUpdates(message.updates).catch((error) => {
|
|
422
|
+
console.warn(`Failed to apply direct Foundry updates for ${objectType}.`, error);
|
|
423
|
+
refreshInBackground();
|
|
424
|
+
});
|
|
425
|
+
else {
|
|
426
|
+
pendingDirectWatcherUpdates.push(...message.updates);
|
|
427
|
+
requestEditHistoryCatchUp?.();
|
|
428
|
+
}
|
|
429
|
+
break;
|
|
430
|
+
case "refresh":
|
|
431
|
+
if (editHistoryUnavailable) refreshInBackground();
|
|
432
|
+
else requestEditHistoryCatchUp?.();
|
|
433
|
+
break;
|
|
434
|
+
case "state":
|
|
435
|
+
if (message.status !== "open") break;
|
|
436
|
+
if (editHistoryUnavailable) refreshInBackground();
|
|
437
|
+
else requestEditHistoryCatchUp?.();
|
|
438
|
+
}
|
|
439
|
+
}) : () => {};
|
|
440
|
+
if (initialCommit === true) markReady();
|
|
441
|
+
else initialCommit.then(markReady, markError);
|
|
442
|
+
return {
|
|
443
|
+
loadSubset: loadSubsetDedupe.loadSubset,
|
|
444
|
+
cleanup: () => {
|
|
445
|
+
disposed = true;
|
|
446
|
+
requestEditHistoryCatchUp = void 0;
|
|
447
|
+
requestFullRefresh = void 0;
|
|
448
|
+
syncDisposed.setState(() => true);
|
|
449
|
+
unsubscribe();
|
|
450
|
+
loadSubsetDedupe.reset();
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
} },
|
|
454
|
+
utils: {
|
|
455
|
+
awaitOperationId,
|
|
456
|
+
refresh
|
|
457
|
+
}
|
|
458
|
+
};
|
|
550
459
|
}
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
460
|
+
function objectCollectionOptions(config) {
|
|
461
|
+
const { client, objectType, primaryKeyProperty, selectedProperties, live, decodeObject, decodeEditObject, schema, ...rest } = config;
|
|
462
|
+
const { sync, utils } = createSyncConfig(client, objectType, primaryKeyProperty, selectedProperties, decodeObject, decodeEditObject, live);
|
|
463
|
+
if (schema === void 0) return {
|
|
464
|
+
syncMode: "on-demand",
|
|
465
|
+
sync,
|
|
466
|
+
utils
|
|
467
|
+
};
|
|
468
|
+
return {
|
|
469
|
+
...rest,
|
|
470
|
+
schema,
|
|
471
|
+
defaultIndexType: BasicIndex,
|
|
472
|
+
autoIndex: "eager",
|
|
473
|
+
syncMode: "on-demand",
|
|
474
|
+
getKey: (object) => object[primaryKeyProperty],
|
|
475
|
+
sync,
|
|
476
|
+
utils
|
|
477
|
+
};
|
|
568
478
|
}
|
|
479
|
+
//#endregion
|
|
480
|
+
export { objectCollectionOptions };
|
|
481
|
+
|
|
569
482
|
//# sourceMappingURL=objectCollectionOptions.js.map
|