@party-stack/foundry-ontology 0.19.0 → 0.20.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 +53 -32
- package/lib/adapter/backend.d.ts +35 -0
- package/lib/adapter/backend.d.ts.map +1 -0
- package/lib/adapter/backend.js +210 -0
- package/lib/adapter/backend.js.map +1 -0
- package/lib/adapter/encrypted.d.ts +12 -0
- package/lib/adapter/encrypted.d.ts.map +1 -0
- package/lib/adapter/encrypted.js +79 -0
- package/lib/adapter/encrypted.js.map +1 -0
- package/lib/adapter/foundryActionError.d.ts +7 -0
- package/lib/adapter/foundryActionError.d.ts.map +1 -0
- package/lib/adapter/foundryActionError.js +61 -0
- package/lib/adapter/foundryActionError.js.map +1 -0
- package/lib/adapter/foundryActionValidation.d.ts +4 -3
- package/lib/adapter/foundryActionValidation.d.ts.map +1 -1
- package/lib/adapter/foundryActionValidation.js +71 -25
- package/lib/adapter/foundryActionValidation.js.map +1 -1
- package/lib/adapter/foundryCodec.d.ts +2 -5
- package/lib/adapter/foundryCodec.d.ts.map +1 -1
- package/lib/adapter/foundryCodec.js +19 -7
- package/lib/adapter/foundryCodec.js.map +1 -1
- package/lib/adapter/foundryObjectSearch.d.ts +13 -0
- package/lib/adapter/foundryObjectSearch.d.ts.map +1 -0
- package/lib/adapter/foundryObjectSearch.js +57 -0
- package/lib/adapter/foundryObjectSearch.js.map +1 -0
- package/lib/adapter/index.d.ts +3 -4
- package/lib/adapter/index.js +3 -4
- package/lib/adapter/likeFilter.d.ts +10 -0
- package/lib/adapter/likeFilter.d.ts.map +1 -0
- package/lib/adapter/likeFilter.js +87 -0
- package/lib/adapter/likeFilter.js.map +1 -0
- package/lib/adapter/makeFoundryOntologyBackend.d.ts +76 -0
- package/lib/adapter/makeFoundryOntologyBackend.d.ts.map +1 -0
- package/lib/adapter/makeFoundryOntologyBackend.js +505 -0
- package/lib/adapter/makeFoundryOntologyBackend.js.map +1 -0
- package/lib/adapter/subsetFilter.d.ts +14 -0
- package/lib/adapter/subsetFilter.d.ts.map +1 -0
- package/lib/adapter/subsetFilter.js +105 -0
- package/lib/adapter/subsetFilter.js.map +1 -0
- package/lib/adapter/uploads.d.ts +25 -0
- package/lib/adapter/uploads.d.ts.map +1 -0
- package/lib/adapter/uploads.js +78 -0
- package/lib/adapter/uploads.js.map +1 -0
- package/lib/backend.d.ts +80 -0
- package/lib/backend.d.ts.map +1 -0
- package/lib/backend.js +34 -0
- package/lib/backend.js.map +1 -0
- package/lib/config/index.d.ts +8 -12
- package/lib/config/index.d.ts.map +1 -1
- package/lib/config/index.js +49 -52
- package/lib/config/index.js.map +1 -1
- package/lib/connectionOptions.d.ts +9 -0
- package/lib/connectionOptions.d.ts.map +1 -0
- package/lib/connectionOptions.js +1 -0
- package/lib/context.d.ts +21 -0
- package/lib/context.d.ts.map +1 -0
- package/lib/context.js +16 -0
- package/lib/context.js.map +1 -0
- package/lib/index.d.ts +7 -7
- package/lib/index.js +6 -7
- package/lib/meta/backend.d.ts +10 -0
- package/lib/meta/backend.d.ts.map +1 -0
- package/lib/meta/backend.js +161 -0
- package/lib/meta/backend.js.map +1 -0
- package/lib/meta/convertMetaActionType.d.ts +3 -2
- package/lib/meta/convertMetaActionType.d.ts.map +1 -1
- package/lib/meta/convertMetaActionType.js +3 -3
- package/lib/meta/convertMetaActionType.js.map +1 -1
- package/lib/meta/convertMetaLinkType.d.ts +2 -2
- package/lib/meta/convertMetaLinkType.d.ts.map +1 -1
- package/lib/meta/convertMetaLinkType.js +13 -13
- package/lib/meta/convertMetaLinkType.js.map +1 -1
- package/lib/meta/convertMetaObjectType.d.ts +2 -2
- package/lib/meta/convertMetaObjectType.d.ts.map +1 -1
- package/lib/meta/convertMetaObjectType.js +5 -1
- package/lib/meta/convertMetaObjectType.js.map +1 -1
- package/lib/meta/convertMetaQueryFunctionType.d.ts +1 -1
- package/lib/meta/convertMetaQueryFunctionType.js.map +1 -1
- package/lib/meta/convertMetaTypeDef.d.ts +1 -1
- package/lib/meta/convertMetaTypeDef.d.ts.map +1 -1
- package/lib/meta/convertMetaTypeDef.js +7 -1
- package/lib/meta/convertMetaTypeDef.js.map +1 -1
- package/lib/meta/convertMetaValueType.d.ts +2 -2
- package/lib/meta/convertMetaValueType.d.ts.map +1 -1
- package/lib/meta/convertMetaValueType.js.map +1 -1
- package/lib/meta/convertOmsActionParameterMetadata.d.ts +1 -1
- package/lib/meta/convertOmsActionParameterMetadata.js +1 -1
- package/lib/meta/convertOmsActionParameterMetadata.js.map +1 -1
- package/lib/meta/index.d.ts +2 -4
- package/lib/meta/index.js +2 -4
- package/lib/meta/listObjectTypes.d.ts +6 -0
- package/lib/meta/listObjectTypes.d.ts.map +1 -0
- package/lib/meta/listObjectTypes.js +13 -0
- package/lib/meta/listObjectTypes.js.map +1 -0
- package/lib/meta/loadActions.d.ts +7 -0
- package/lib/meta/loadActions.d.ts.map +1 -0
- package/lib/meta/loadActions.js +20 -0
- package/lib/meta/loadActions.js.map +1 -0
- package/lib/meta/loadEntities.d.ts +9 -0
- package/lib/meta/loadEntities.d.ts.map +1 -0
- package/lib/meta/loadEntities.js +73 -0
- package/lib/meta/loadEntities.js.map +1 -0
- package/lib/meta/loadQueryFunctions.d.ts +11 -0
- package/lib/meta/loadQueryFunctions.d.ts.map +1 -0
- package/lib/meta/loadQueryFunctions.js +18 -0
- package/lib/meta/loadQueryFunctions.js.map +1 -0
- package/lib/meta/planMetaLookup.d.ts +12 -0
- package/lib/meta/planMetaLookup.d.ts.map +1 -0
- package/lib/meta/planMetaLookup.js +44 -0
- package/lib/meta/planMetaLookup.js.map +1 -0
- package/lib/platform.d.ts +78 -0
- package/lib/platform.d.ts.map +1 -0
- package/lib/platform.js +116 -0
- package/lib/platform.js.map +1 -0
- package/lib/platformCollections.d.ts +68 -0
- package/lib/platformCollections.d.ts.map +1 -0
- package/lib/platformCollections.js +7 -0
- package/lib/platformCollections.js.map +1 -0
- package/lib/serviceConnector.d.ts +8 -0
- package/lib/serviceConnector.d.ts.map +1 -0
- package/lib/serviceConnector.js +105 -0
- package/lib/serviceConnector.js.map +1 -0
- package/lib/stagedWrites.d.ts +3 -2
- package/lib/stagedWrites.d.ts.map +1 -1
- package/lib/stagedWrites.js +30 -3
- package/lib/stagedWrites.js.map +1 -1
- package/lib/users/admin.d.ts +105 -0
- package/lib/users/admin.d.ts.map +1 -0
- package/lib/users/admin.js +35 -0
- package/lib/users/admin.js.map +1 -0
- package/lib/users/createFoundryUsersIntegration.d.ts +2 -2
- package/lib/users/createFoundryUsersIntegration.d.ts.map +1 -1
- package/lib/users/createFoundryUsersIntegration.js +4 -6
- package/lib/users/createFoundryUsersIntegration.js.map +1 -1
- package/lib/users/foundryUser.d.ts +2 -2
- package/lib/users/foundryUser.js +1 -1
- package/lib/users/foundryUser.js.map +1 -1
- package/lib/users/index.d.ts +2 -3
- package/lib/users/index.js +2 -3
- package/lib/users/loadUserSubset.d.ts +8 -0
- package/lib/users/loadUserSubset.d.ts.map +1 -0
- package/lib/users/loadUserSubset.js +166 -0
- package/lib/users/loadUserSubset.js.map +1 -0
- package/lib/utils/AsyncIterable.d.ts +1 -1
- package/lib/utils/AsyncIterable.d.ts.map +1 -1
- package/lib/utils/AsyncIterable.js +11 -0
- package/lib/utils/AsyncIterable.js.map +1 -1
- package/package.json +16 -15
- package/lib/adapter/convertLoadSubsetOptions.d.ts +0 -8
- package/lib/adapter/convertLoadSubsetOptions.d.ts.map +0 -1
- package/lib/adapter/convertLoadSubsetOptions.js +0 -178
- package/lib/adapter/convertLoadSubsetOptions.js.map +0 -1
- package/lib/adapter/createFoundryOntologyBackendAdapter.d.ts +0 -29
- package/lib/adapter/createFoundryOntologyBackendAdapter.d.ts.map +0 -1
- package/lib/adapter/createFoundryOntologyBackendAdapter.js +0 -311
- package/lib/adapter/createFoundryOntologyBackendAdapter.js.map +0 -1
- package/lib/adapter/objectCollectionOptions.d.ts +0 -33
- package/lib/adapter/objectCollectionOptions.d.ts.map +0 -1
- package/lib/adapter/objectCollectionOptions.js +0 -482
- package/lib/adapter/objectCollectionOptions.js.map +0 -1
- package/lib/config/applyAttachmentConstraintOverrides.d.ts +0 -10
- package/lib/config/applyAttachmentConstraintOverrides.d.ts.map +0 -1
- package/lib/config/applyAttachmentConstraintOverrides.js +0 -50
- package/lib/config/applyAttachmentConstraintOverrides.js.map +0 -1
- package/lib/connection.d.ts +0 -38
- package/lib/connection.d.ts.map +0 -1
- package/lib/connection.js +0 -195
- package/lib/connection.js.map +0 -1
- package/lib/installation/createFoundryBackendInstallation.d.ts +0 -29
- package/lib/installation/createFoundryBackendInstallation.d.ts.map +0 -1
- package/lib/installation/createFoundryBackendInstallation.js +0 -60
- package/lib/installation/createFoundryBackendInstallation.js.map +0 -1
- package/lib/installation/index.d.ts +0 -2
- package/lib/installation/index.js +0 -1
- package/lib/meta/actionTypeCollectionOptions.d.ts +0 -14
- package/lib/meta/actionTypeCollectionOptions.d.ts.map +0 -1
- package/lib/meta/actionTypeCollectionOptions.js +0 -58
- package/lib/meta/actionTypeCollectionOptions.js.map +0 -1
- package/lib/meta/convertActionTypeLoadSubsetOptions.d.ts +0 -7
- package/lib/meta/convertActionTypeLoadSubsetOptions.d.ts.map +0 -1
- package/lib/meta/convertActionTypeLoadSubsetOptions.js +0 -84
- package/lib/meta/convertActionTypeLoadSubsetOptions.js.map +0 -1
- package/lib/meta/createFoundryMetaOntologyBackendAdapter.d.ts +0 -11
- package/lib/meta/createFoundryMetaOntologyBackendAdapter.d.ts.map +0 -1
- package/lib/meta/createFoundryMetaOntologyBackendAdapter.js +0 -43
- package/lib/meta/createFoundryMetaOntologyBackendAdapter.js.map +0 -1
- package/lib/meta/entityCollectionOptions.d.ts +0 -25
- package/lib/meta/entityCollectionOptions.d.ts.map +0 -1
- package/lib/meta/entityCollectionOptions.js +0 -69
- package/lib/meta/entityCollectionOptions.js.map +0 -1
- package/lib/meta/queryFunctionTypeCollectionOptions.d.ts +0 -12
- package/lib/meta/queryFunctionTypeCollectionOptions.d.ts.map +0 -1
- package/lib/meta/queryFunctionTypeCollectionOptions.js +0 -59
- package/lib/meta/queryFunctionTypeCollectionOptions.js.map +0 -1
- package/lib/users/createFoundryAdminOntologyRoute.d.ts +0 -55
- package/lib/users/createFoundryAdminOntologyRoute.d.ts.map +0 -1
- package/lib/users/createFoundryAdminOntologyRoute.js +0 -33
- package/lib/users/createFoundryAdminOntologyRoute.js.map +0 -1
- package/lib/users/userCollectionOptions.d.ts +0 -25
- package/lib/users/userCollectionOptions.d.ts.map +0 -1
- package/lib/users/userCollectionOptions.js +0 -94
- package/lib/users/userCollectionOptions.js.map +0 -1
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
import { parseOrderByExpression, parseWhereExpression } from "@tanstack/db";
|
|
2
|
-
import { Temporal } from "temporal-polyfill";
|
|
3
|
-
//#region src/adapter/convertLoadSubsetOptions.ts
|
|
4
|
-
const ALWAYS_FALSE_FILTER = {
|
|
5
|
-
type: "or",
|
|
6
|
-
value: []
|
|
7
|
-
};
|
|
8
|
-
const ALWAYS_TRUE_FILTER = {
|
|
9
|
-
type: "and",
|
|
10
|
-
value: []
|
|
11
|
-
};
|
|
12
|
-
function pushdown(query, safeToNegate = true) {
|
|
13
|
-
return {
|
|
14
|
-
query,
|
|
15
|
-
safeToNegate
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
function parseLikePattern(pattern) {
|
|
19
|
-
const parts = [];
|
|
20
|
-
let literal = "";
|
|
21
|
-
const flushLiteral = () => {
|
|
22
|
-
if (literal) {
|
|
23
|
-
parts.push({
|
|
24
|
-
type: "literal",
|
|
25
|
-
value: literal
|
|
26
|
-
});
|
|
27
|
-
literal = "";
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
for (let index = 0; index < pattern.length; index++) {
|
|
31
|
-
const character = pattern[index];
|
|
32
|
-
if (character === "\\") {
|
|
33
|
-
const escaped = pattern[index + 1];
|
|
34
|
-
if (escaped === "%" || escaped === "_" || escaped === "\\") {
|
|
35
|
-
literal += escaped;
|
|
36
|
-
index++;
|
|
37
|
-
} else literal += character;
|
|
38
|
-
} else if (character === "%") {
|
|
39
|
-
flushLiteral();
|
|
40
|
-
parts.push({ type: "many" });
|
|
41
|
-
} else if (character === "_") {
|
|
42
|
-
flushLiteral();
|
|
43
|
-
parts.push({ type: "single" });
|
|
44
|
-
} else literal += character;
|
|
45
|
-
}
|
|
46
|
-
flushLiteral();
|
|
47
|
-
return parts;
|
|
48
|
-
}
|
|
49
|
-
function escapeFoundryWildcardLiteral(value) {
|
|
50
|
-
return value.replace(/[\\*?]/g, "\\$&");
|
|
51
|
-
}
|
|
52
|
-
function convertLikeFilter(field, value) {
|
|
53
|
-
const parts = parseLikePattern(value.toLowerCase());
|
|
54
|
-
const hasLeadingWildcard = parts[0]?.type === "many";
|
|
55
|
-
const hasTrailingWildcard = parts.at(-1)?.type === "many";
|
|
56
|
-
const propertyIdentifier = fieldPathToPropertyIdentifier(field);
|
|
57
|
-
if (hasLeadingWildcard && hasTrailingWildcard) {
|
|
58
|
-
const queries = parts.flatMap((part) => part.type === "literal" && part.value ? [part.value] : []).map((term) => ({
|
|
59
|
-
type: "containsAllTermsInOrder",
|
|
60
|
-
propertyIdentifier,
|
|
61
|
-
value: term
|
|
62
|
-
}));
|
|
63
|
-
return pushdown(queries.length === 0 ? ALWAYS_TRUE_FILTER : queries.length === 1 ? queries[0] : {
|
|
64
|
-
type: "and",
|
|
65
|
-
value: queries
|
|
66
|
-
}, false);
|
|
67
|
-
}
|
|
68
|
-
return pushdown({
|
|
69
|
-
type: "wildcard",
|
|
70
|
-
propertyIdentifier,
|
|
71
|
-
value: parts.map((part) => {
|
|
72
|
-
if (part.type === "many") return "*";
|
|
73
|
-
if (part.type === "single") return "?";
|
|
74
|
-
return escapeFoundryWildcardLiteral(part.value);
|
|
75
|
-
}).join("")
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
function convertQueryValue(value) {
|
|
79
|
-
if (value instanceof Date) return value.toISOString();
|
|
80
|
-
if (value instanceof Temporal.Instant || value instanceof Temporal.PlainDate || value instanceof Temporal.PlainDateTime) return value.toString();
|
|
81
|
-
return value;
|
|
82
|
-
}
|
|
83
|
-
function fieldPathToPropertyIdentifier(fieldPath) {
|
|
84
|
-
if (fieldPath.length === 1) return {
|
|
85
|
-
type: "property",
|
|
86
|
-
apiName: fieldPath[0]
|
|
87
|
-
};
|
|
88
|
-
else if (fieldPath.length === 2) return {
|
|
89
|
-
type: "structField",
|
|
90
|
-
propertyApiName: fieldPath[0],
|
|
91
|
-
structFieldApiName: fieldPath[1]
|
|
92
|
-
};
|
|
93
|
-
throw new Error(`Invalid field path: ${fieldPath.join(".")}`);
|
|
94
|
-
}
|
|
95
|
-
function convertInFilter(fieldOrValue, valuesOrField) {
|
|
96
|
-
if (!Array.isArray(valuesOrField)) throw new Error("Expected the second inArray argument to be an array or field path");
|
|
97
|
-
if (!Array.isArray(fieldOrValue)) return pushdown({
|
|
98
|
-
type: "contains",
|
|
99
|
-
propertyIdentifier: fieldPathToPropertyIdentifier(valuesOrField),
|
|
100
|
-
value: convertQueryValue(fieldOrValue)
|
|
101
|
-
});
|
|
102
|
-
const field = fieldOrValue;
|
|
103
|
-
const values = valuesOrField;
|
|
104
|
-
return pushdown({
|
|
105
|
-
type: "in",
|
|
106
|
-
propertyIdentifier: fieldPathToPropertyIdentifier(field),
|
|
107
|
-
value: values.filter((entry) => entry !== null && entry !== void 0).map(convertQueryValue)
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
function isAlwaysFalseFilter(filter) {
|
|
111
|
-
return filter?.type === "or" && filter.value.length === 0;
|
|
112
|
-
}
|
|
113
|
-
function convertLoadSubsetFilter(filter) {
|
|
114
|
-
return parseWhereExpression(filter, { handlers: {
|
|
115
|
-
and: (...filters) => pushdown({
|
|
116
|
-
type: "and",
|
|
117
|
-
value: filters.map(({ query }) => query)
|
|
118
|
-
}, filters.every(({ safeToNegate }) => safeToNegate)),
|
|
119
|
-
or: (...filters) => pushdown({
|
|
120
|
-
type: "or",
|
|
121
|
-
value: filters.map(({ query }) => query)
|
|
122
|
-
}, filters.every(({ safeToNegate }) => safeToNegate)),
|
|
123
|
-
not: (filter) => filter.safeToNegate ? pushdown({
|
|
124
|
-
type: "not",
|
|
125
|
-
value: filter.query
|
|
126
|
-
}) : pushdown(ALWAYS_TRUE_FILTER, false),
|
|
127
|
-
eq: (field, value) => pushdown(value === null ? ALWAYS_FALSE_FILTER : value === void 0 ? {
|
|
128
|
-
type: "isNull",
|
|
129
|
-
propertyIdentifier: fieldPathToPropertyIdentifier(field),
|
|
130
|
-
value: true
|
|
131
|
-
} : {
|
|
132
|
-
type: "eq",
|
|
133
|
-
propertyIdentifier: fieldPathToPropertyIdentifier(field),
|
|
134
|
-
value: convertQueryValue(value)
|
|
135
|
-
}),
|
|
136
|
-
gt: (field, value) => pushdown(value == null ? ALWAYS_FALSE_FILTER : {
|
|
137
|
-
type: "gt",
|
|
138
|
-
propertyIdentifier: fieldPathToPropertyIdentifier(field),
|
|
139
|
-
value: convertQueryValue(value)
|
|
140
|
-
}),
|
|
141
|
-
gte: (field, value) => pushdown(value == null ? ALWAYS_FALSE_FILTER : {
|
|
142
|
-
type: "gte",
|
|
143
|
-
propertyIdentifier: fieldPathToPropertyIdentifier(field),
|
|
144
|
-
value: convertQueryValue(value)
|
|
145
|
-
}),
|
|
146
|
-
lt: (field, value) => pushdown(value == null ? ALWAYS_FALSE_FILTER : {
|
|
147
|
-
type: "lt",
|
|
148
|
-
propertyIdentifier: fieldPathToPropertyIdentifier(field),
|
|
149
|
-
value: convertQueryValue(value)
|
|
150
|
-
}),
|
|
151
|
-
lte: (field, value) => pushdown(value == null ? ALWAYS_FALSE_FILTER : {
|
|
152
|
-
type: "lte",
|
|
153
|
-
propertyIdentifier: fieldPathToPropertyIdentifier(field),
|
|
154
|
-
value: convertQueryValue(value)
|
|
155
|
-
}),
|
|
156
|
-
isUndefined: (field) => ({
|
|
157
|
-
query: {
|
|
158
|
-
type: "isNull",
|
|
159
|
-
propertyIdentifier: fieldPathToPropertyIdentifier(field),
|
|
160
|
-
value: true
|
|
161
|
-
},
|
|
162
|
-
safeToNegate: true
|
|
163
|
-
}),
|
|
164
|
-
in: convertInFilter,
|
|
165
|
-
ilike: convertLikeFilter,
|
|
166
|
-
like: convertLikeFilter
|
|
167
|
-
} })?.query ?? void 0;
|
|
168
|
-
}
|
|
169
|
-
function convertLoadSubsetOrderBy(orderBy) {
|
|
170
|
-
return orderBy ? { fields: parseOrderByExpression(orderBy).map((ordering) => ({
|
|
171
|
-
field: ordering.field[0],
|
|
172
|
-
direction: ordering.direction
|
|
173
|
-
})) } : void 0;
|
|
174
|
-
}
|
|
175
|
-
//#endregion
|
|
176
|
-
export { convertLoadSubsetFilter, convertLoadSubsetOrderBy, isAlwaysFalseFilter };
|
|
177
|
-
|
|
178
|
-
//# sourceMappingURL=convertLoadSubsetOptions.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"convertLoadSubsetOptions.js","names":[],"sources":["../../src/adapter/convertLoadSubsetOptions.ts"],"sourcesContent":["import {\n PropertyApiName,\n PropertyIdentifier,\n SearchJsonQueryV2,\n SearchOrderByV2,\n StructFieldApiName,\n} from \"@osdk/foundry.ontologies\";\nimport { FieldPath, LoadSubsetOptions, parseOrderByExpression, parseWhereExpression } from \"@tanstack/db\";\nimport { Temporal } from \"temporal-polyfill\";\n\nconst ALWAYS_FALSE_FILTER: SearchJsonQueryV2 = { type: \"or\", value: [] };\nconst ALWAYS_TRUE_FILTER: SearchJsonQueryV2 = { type: \"and\", value: [] };\n\ntype LikePatternPart = { type: \"literal\"; value: string } | { type: \"many\" } | { type: \"single\" };\n\ninterface PushdownFilter {\n query: SearchJsonQueryV2;\n safeToNegate: boolean;\n}\n\nfunction pushdown(query: SearchJsonQueryV2, safeToNegate = true): PushdownFilter {\n return { query, safeToNegate };\n}\n\nfunction parseLikePattern(pattern: string): LikePatternPart[] {\n const parts: LikePatternPart[] = [];\n let literal = \"\";\n\n const flushLiteral = () => {\n if (literal) {\n parts.push({ type: \"literal\", value: literal });\n literal = \"\";\n }\n };\n\n for (let index = 0; index < pattern.length; index++) {\n const character = pattern[index]!;\n if (character === \"\\\\\") {\n const escaped = pattern[index + 1];\n if (escaped === \"%\" || escaped === \"_\" || escaped === \"\\\\\") {\n literal += escaped;\n index++;\n } else {\n literal += character;\n }\n } else if (character === \"%\") {\n flushLiteral();\n parts.push({ type: \"many\" });\n } else if (character === \"_\") {\n flushLiteral();\n parts.push({ type: \"single\" });\n } else {\n literal += character;\n }\n }\n flushLiteral();\n\n return parts;\n}\n\nfunction escapeFoundryWildcardLiteral(value: string): string {\n return value.replace(/[\\\\*?]/g, \"\\\\$&\");\n}\n\nfunction convertLikeFilter(field: FieldPath, value: string): PushdownFilter {\n const parts = parseLikePattern(value.toLowerCase());\n const hasLeadingWildcard = parts[0]?.type === \"many\";\n const hasTrailingWildcard = parts.at(-1)?.type === \"many\";\n const propertyIdentifier = fieldPathToPropertyIdentifier(field);\n\n if (hasLeadingWildcard && hasTrailingWildcard) {\n const terms = parts.flatMap((part) => (part.type === \"literal\" && part.value ? [part.value] : []));\n const queries = terms.map<SearchJsonQueryV2>((term) => ({\n // This is Foundry's substring/phrase query. It can over-fetch because\n // wildcard-delimited terms are not required to be adjacent or ordered.\n type: \"containsAllTermsInOrder\",\n propertyIdentifier,\n value: term,\n }));\n const query: SearchJsonQueryV2 =\n queries.length === 0\n ? ALWAYS_TRUE_FILTER\n : queries.length === 1\n ? queries[0]!\n : { type: \"and\", value: queries };\n\n // Contains is an approximation of SQL LIKE. Negating this superset\n // would produce a subset and could hide exact matches.\n return pushdown(query, false);\n }\n\n const wildcard = parts\n .map((part) => {\n if (part.type === \"many\") return \"*\";\n if (part.type === \"single\") return \"?\";\n return escapeFoundryWildcardLiteral(part.value);\n })\n .join(\"\");\n\n return pushdown({\n type: \"wildcard\",\n propertyIdentifier,\n value: wildcard,\n });\n}\n\nfunction convertQueryValue(value: unknown): unknown {\n if (value instanceof Date) {\n return value.toISOString();\n }\n if (\n value instanceof Temporal.Instant ||\n value instanceof Temporal.PlainDate ||\n value instanceof Temporal.PlainDateTime\n ) {\n return value.toString();\n }\n return value;\n}\n\nfunction fieldPathToPropertyIdentifier(fieldPath: FieldPath): PropertyIdentifier {\n if (fieldPath.length === 1) {\n return {\n type: \"property\",\n apiName: fieldPath[0]! as PropertyApiName,\n };\n } else if (fieldPath.length === 2) {\n return {\n type: \"structField\",\n propertyApiName: fieldPath[0]! as PropertyApiName,\n structFieldApiName: fieldPath[1]! as StructFieldApiName,\n };\n }\n throw new Error(`Invalid field path: ${fieldPath.join(\".\")}`);\n}\n\nfunction convertInFilter(fieldOrValue: unknown, valuesOrField: unknown): PushdownFilter {\n if (!Array.isArray(valuesOrField)) {\n throw new Error(\"Expected the second inArray argument to be an array or field path\");\n }\n\n if (!Array.isArray(fieldOrValue)) {\n return pushdown({\n type: \"contains\",\n propertyIdentifier: fieldPathToPropertyIdentifier(valuesOrField as FieldPath),\n value: convertQueryValue(fieldOrValue),\n });\n }\n\n const field = fieldOrValue as FieldPath;\n const values = valuesOrField as unknown[];\n return pushdown({\n type: \"in\",\n propertyIdentifier: fieldPathToPropertyIdentifier(field),\n value: values.filter((entry) => entry !== null && entry !== undefined).map(convertQueryValue),\n });\n}\n\nexport function isAlwaysFalseFilter(filter: SearchJsonQueryV2 | undefined): boolean {\n return filter?.type === \"or\" && filter.value.length === 0;\n}\n\nexport function convertLoadSubsetFilter(filter: LoadSubsetOptions[\"where\"]): SearchJsonQueryV2 | undefined {\n return (\n parseWhereExpression<PushdownFilter>(filter, {\n handlers: {\n and: (...filters: PushdownFilter[]) =>\n pushdown(\n { type: \"and\", value: filters.map(({ query }) => query) },\n filters.every(({ safeToNegate }) => safeToNegate)\n ),\n or: (...filters: PushdownFilter[]) =>\n pushdown(\n { type: \"or\", value: filters.map(({ query }) => query) },\n filters.every(({ safeToNegate }) => safeToNegate)\n ),\n not: (filter: PushdownFilter) =>\n filter.safeToNegate\n ? pushdown({ type: \"not\", value: filter.query })\n : pushdown(ALWAYS_TRUE_FILTER, false),\n eq: (field: FieldPath, value) =>\n pushdown(\n value === null\n ? ALWAYS_FALSE_FILTER\n : value === undefined\n ? {\n type: \"isNull\",\n propertyIdentifier: fieldPathToPropertyIdentifier(field),\n value: true,\n }\n : {\n type: \"eq\",\n propertyIdentifier: fieldPathToPropertyIdentifier(field),\n value: convertQueryValue(value),\n }\n ),\n gt: (field: FieldPath, value) =>\n pushdown(\n value == null\n ? ALWAYS_FALSE_FILTER\n : {\n type: \"gt\",\n propertyIdentifier: fieldPathToPropertyIdentifier(field),\n value: convertQueryValue(value),\n }\n ),\n gte: (field: FieldPath, value) =>\n pushdown(\n value == null\n ? ALWAYS_FALSE_FILTER\n : {\n type: \"gte\",\n propertyIdentifier: fieldPathToPropertyIdentifier(field),\n value: convertQueryValue(value),\n }\n ),\n lt: (field: FieldPath, value) =>\n pushdown(\n value == null\n ? ALWAYS_FALSE_FILTER\n : {\n type: \"lt\",\n propertyIdentifier: fieldPathToPropertyIdentifier(field),\n value: convertQueryValue(value),\n }\n ),\n lte: (field: FieldPath, value) =>\n pushdown(\n value == null\n ? ALWAYS_FALSE_FILTER\n : {\n type: \"lte\",\n propertyIdentifier: fieldPathToPropertyIdentifier(field),\n value: convertQueryValue(value),\n }\n ),\n isUndefined: (field: FieldPath) => ({\n query: {\n type: \"isNull\",\n propertyIdentifier: fieldPathToPropertyIdentifier(field),\n value: true,\n },\n safeToNegate: true,\n }),\n in: convertInFilter,\n ilike: convertLikeFilter,\n // Foundry wildcard and contains searches are case-insensitive,\n // so LIKE can over-fetch while TanStack applies exact casing.\n like: convertLikeFilter,\n },\n })?.query ?? undefined\n );\n}\n\nexport function convertLoadSubsetOrderBy(orderBy: LoadSubsetOptions[\"orderBy\"]): SearchOrderByV2 | undefined {\n return orderBy\n ? {\n fields: parseOrderByExpression(orderBy).map((ordering) => ({\n field: ordering.field[0]! as PropertyApiName,\n direction: ordering.direction,\n })),\n }\n : undefined;\n}\n"],"mappings":"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"}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { OntologyClient } from "@party-stack/foundry-client";
|
|
2
|
-
import { OntologyBackendAdapter, OntologyBackendAdapterProvider, OntologyCollectionOptions, OntologyIR, PartialAttachmentMetadata } from "@party-stack/ontology";
|
|
3
|
-
import { attachment } from "@party-stack/ontology/values";
|
|
4
|
-
//#region src/adapter/createFoundryOntologyBackendAdapter.d.ts
|
|
5
|
-
export declare function isFoundryNotFoundError(error: unknown): boolean;
|
|
6
|
-
export interface FoundryUsersIntegration {
|
|
7
|
-
objectType: string;
|
|
8
|
-
getCollectionOptions(client: OntologyClient): OntologyCollectionOptions;
|
|
9
|
-
getAttachmentContent?(client: OntologyClient, attachment: attachment): Promise<Blob | undefined>;
|
|
10
|
-
getAttachmentMetadata?(client: OntologyClient, attachment: attachment, selection: readonly (keyof PartialAttachmentMetadata)[]): Promise<PartialAttachmentMetadata | undefined>;
|
|
11
|
-
}
|
|
12
|
-
export interface CreateFoundryOntologyBackendAdapterOptions {
|
|
13
|
-
client: OntologyClient;
|
|
14
|
-
ir: OntologyIR;
|
|
15
|
-
users?: FoundryUsersIntegration;
|
|
16
|
-
live?: boolean;
|
|
17
|
-
}
|
|
18
|
-
export declare function createFoundryOntologyBackendAdapter(opts: CreateFoundryOntologyBackendAdapterOptions): OntologyBackendAdapter;
|
|
19
|
-
export type CreateFoundryOntologyBackendOptions<Context extends Record<string, unknown> = Record<string, unknown>> = ({
|
|
20
|
-
client: OntologyClient;
|
|
21
|
-
} | {
|
|
22
|
-
createClient: (ir: OntologyIR, context: Context) => OntologyClient | Promise<OntologyClient>;
|
|
23
|
-
}) & {
|
|
24
|
-
users?: FoundryUsersIntegration;
|
|
25
|
-
live?: boolean;
|
|
26
|
-
};
|
|
27
|
-
export declare function createFoundryOntologyBackend<Context extends Record<string, unknown> = Record<string, unknown>>(opts: CreateFoundryOntologyBackendOptions<Context>): OntologyBackendAdapterProvider<Context>;
|
|
28
|
-
//#endregion
|
|
29
|
-
//# sourceMappingURL=createFoundryOntologyBackendAdapter.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"createFoundryOntologyBackendAdapter.d.ts","names":[],"sources":["../../src/adapter/createFoundryOntologyBackendAdapter.ts"],"mappings":";;;;wBA2CgB,uBAAuB;iBAWtB;EACb;EACA,qBAAqB,QAAQ,iBAAiB;EAC9C,sBAAsB,QAAQ,gBAAgB,YAAY,aAAa,QAAQ;EAC/E,uBACI,QAAQ,gBACR,YAAY,YACZ,2BAA2B,+BAC5B,QAAQ;;iBAoIE;EACb,QAAQ;EACR,IAAI;EACJ,QAAQ;EACR;;wBAGY,oCACZ,MAAM,6CACP;YAqXS,oCACR,gBAAgB,0BAA0B;EAGpC,QAAQ;;EAGR,eAAe,IAAI,YAAY,SAAS,YAAY,iBAAiB,QAAQ;;EAGnF,QAAQ;EACR;;wBAGY,6BACZ,gBAAgB,0BAA0B,yBAC5C,MAAM,oCAAoC,WAAW,+BAA+B"}
|
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
import { objectCollectionOptions } from "./objectCollectionOptions.js";
|
|
2
|
-
import { toFoundryActionTypeName } from "../utils/actionTypeName.js";
|
|
3
|
-
import { getFoundryAttachmentKind } from "../meta/foundryAttachmentMetadata.js";
|
|
4
|
-
import { getFoundryActionOverrideParameterMapping } from "../meta/convertMetaActionType.js";
|
|
5
|
-
import { getFoundryValidationIssues, loadFoundrySubmissionCriteria, validateFoundryActionDraftCriteria } from "./foundryActionValidation.js";
|
|
6
|
-
import { decodeFoundryMediaId, mediaReferenceToFoundryMediaId } from "./foundryMediaId.js";
|
|
7
|
-
import { createFoundryCodec } from "./foundryCodec.js";
|
|
8
|
-
import { Actions, Attachments, MediaReferenceProperties, Queries } from "@osdk/foundry.ontologies";
|
|
9
|
-
import { Temporal } from "temporal-polyfill";
|
|
10
|
-
import { invariant } from "@bobbyfidz/panic";
|
|
11
|
-
import { MediaSets } from "@osdk/foundry.mediasets";
|
|
12
|
-
import { NonRetryableError, certain, uncertain } from "@party-stack/ontology";
|
|
13
|
-
import { resolveType, unwrapType } from "@party-stack/ontology/utils";
|
|
14
|
-
//#region src/adapter/createFoundryOntologyBackendAdapter.ts
|
|
15
|
-
function isFoundryAttachmentRid(value) {
|
|
16
|
-
return /^ri\.attachments\.[^.]+\.attachment\..+$/.test(value);
|
|
17
|
-
}
|
|
18
|
-
function isFoundryNotFoundError(error) {
|
|
19
|
-
if (typeof error !== "object" || error === null) return false;
|
|
20
|
-
const foundryError = error;
|
|
21
|
-
return foundryError.statusCode === 404 || foundryError.errorCode === "NOT_FOUND";
|
|
22
|
-
}
|
|
23
|
-
function serializeOverrideValue(value) {
|
|
24
|
-
if (typeof value === "string") return value;
|
|
25
|
-
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return String(value);
|
|
26
|
-
if (value instanceof Date) return value.toISOString();
|
|
27
|
-
if (value instanceof Temporal.Instant) return value.toString();
|
|
28
|
-
if (value instanceof Temporal.PlainDate || value instanceof Temporal.PlainDateTime) return value.toString();
|
|
29
|
-
return JSON.stringify(value) ?? "";
|
|
30
|
-
}
|
|
31
|
-
function serializeActionExecutionTime(value) {
|
|
32
|
-
try {
|
|
33
|
-
const candidate = value instanceof Date ? value.toISOString() : String(value);
|
|
34
|
-
return Temporal.Instant.from(candidate).toString();
|
|
35
|
-
} catch (cause) {
|
|
36
|
-
throw new TypeError("Invalid action execution time: expected a Date or Temporal-like ISO instant.", { cause });
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
function getApplyActionOperationId(result) {
|
|
40
|
-
const operationId = result.operationId;
|
|
41
|
-
if (typeof operationId !== "string" || operationId.length === 0) throw new Error("Foundry apply action response did not include an operationId.");
|
|
42
|
-
return operationId;
|
|
43
|
-
}
|
|
44
|
-
function getAttachmentName(attachment) {
|
|
45
|
-
if (typeof attachment !== "object" || attachment === null || Array.isArray(attachment)) return;
|
|
46
|
-
const name = attachment.name;
|
|
47
|
-
return typeof name === "string" ? name : void 0;
|
|
48
|
-
}
|
|
49
|
-
function getAttachmentProviderType(target) {
|
|
50
|
-
return getFoundryAttachmentKind(target?.meta);
|
|
51
|
-
}
|
|
52
|
-
function getEditedObjectTypes(edits) {
|
|
53
|
-
const objectTypes = /* @__PURE__ */ new Set();
|
|
54
|
-
if (!edits || edits.type !== "edits") return objectTypes;
|
|
55
|
-
for (const edit of edits.edits) if (edit.type === "addObject" || edit.type === "modifyObject" || edit.type === "deleteObject") objectTypes.add(edit.objectType);
|
|
56
|
-
return objectTypes;
|
|
57
|
-
}
|
|
58
|
-
function prepareFoundryActionInvocation(options) {
|
|
59
|
-
const actionType = options.ir.actionTypes.find((candidate) => candidate.name === options.name);
|
|
60
|
-
if (!actionType) throw new NonRetryableError(`Unknown Foundry action type "${options.name}".`);
|
|
61
|
-
const overrideMapping = getFoundryActionOverrideParameterMapping(actionType);
|
|
62
|
-
const parameterTypes = new Map(actionType.parameters.map((parameter) => [parameter.name, parameter.type]));
|
|
63
|
-
const parameters = {};
|
|
64
|
-
const uniqueIdentifierLinkIdValues = {};
|
|
65
|
-
let actionExecutionTime;
|
|
66
|
-
for (const [parameterName, value] of Object.entries(options.parameters)) {
|
|
67
|
-
if (overrideMapping.uuidByParameterName.has(parameterName)) {
|
|
68
|
-
if (value !== void 0) uniqueIdentifierLinkIdValues[overrideMapping.uuidByParameterName.get(parameterName)] = serializeOverrideValue(value);
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
if (overrideMapping.nowParameterName === parameterName) {
|
|
72
|
-
if (value !== void 0) actionExecutionTime = serializeActionExecutionTime(value);
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
if (value !== void 0) {
|
|
76
|
-
const parameterType = parameterTypes.get(parameterName);
|
|
77
|
-
parameters[parameterName] = parameterType ? options.codec.encodeValue(parameterType, value) : value;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
return {
|
|
81
|
-
parameters,
|
|
82
|
-
overrides: {
|
|
83
|
-
uniqueIdentifierLinkIdValues,
|
|
84
|
-
actionExecutionTime
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
function createFoundryOntologyBackendAdapter(opts) {
|
|
89
|
-
const codec = createFoundryCodec(opts.ir);
|
|
90
|
-
const adapter = {
|
|
91
|
-
name: "foundry",
|
|
92
|
-
live: opts.live !== false,
|
|
93
|
-
getCollectionOptions: (objectType) => {
|
|
94
|
-
if (opts.users?.objectType === objectType) return opts.users.getCollectionOptions(opts.client);
|
|
95
|
-
const objectTypeDef = opts.ir.objectTypes.find((ot) => ot.name === objectType);
|
|
96
|
-
return objectCollectionOptions({
|
|
97
|
-
client: opts.client,
|
|
98
|
-
objectType,
|
|
99
|
-
primaryKeyProperty: objectTypeDef.primaryKey,
|
|
100
|
-
selectedProperties: objectTypeDef.properties.map((property) => property.name),
|
|
101
|
-
live: opts.live,
|
|
102
|
-
decodeObject: (object) => codec.decodeObject(objectType, object),
|
|
103
|
-
decodeEditObject: (object) => codec.decodeEditObject(objectType, object)
|
|
104
|
-
});
|
|
105
|
-
},
|
|
106
|
-
validateAction: async (name, parameters) => {
|
|
107
|
-
const invocation = prepareFoundryActionInvocation({
|
|
108
|
-
ir: opts.ir,
|
|
109
|
-
name,
|
|
110
|
-
parameters,
|
|
111
|
-
codec
|
|
112
|
-
});
|
|
113
|
-
let result;
|
|
114
|
-
try {
|
|
115
|
-
result = await Actions.applyWithOverrides(opts.client, opts.client.ontologyRid, toFoundryActionTypeName(name), {
|
|
116
|
-
request: {
|
|
117
|
-
options: { mode: "VALIDATE_ONLY" },
|
|
118
|
-
parameters: invocation.parameters
|
|
119
|
-
},
|
|
120
|
-
overrides: invocation.overrides
|
|
121
|
-
}, { preview: true });
|
|
122
|
-
} catch (error) {
|
|
123
|
-
if (isFoundryNotFoundError(error)) throw new NonRetryableError(error instanceof Error ? error.message : "Foundry action target was not found.", { cause: error });
|
|
124
|
-
throw error;
|
|
125
|
-
}
|
|
126
|
-
if (!result.validation) throw new Error("Foundry validate action response did not include a validation result.");
|
|
127
|
-
return {
|
|
128
|
-
certain: true,
|
|
129
|
-
value: result.validation.result === "VALID" ? {
|
|
130
|
-
kind: "ok",
|
|
131
|
-
value: void 0
|
|
132
|
-
} : {
|
|
133
|
-
kind: "err",
|
|
134
|
-
value: getFoundryValidationIssues(result)
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
},
|
|
138
|
-
validateActionDraft: async (name, parameters, live) => {
|
|
139
|
-
const actionType = opts.ir.actionTypes.find((candidate) => candidate.name === name);
|
|
140
|
-
if (!actionType) throw new NonRetryableError(`Unknown Foundry action type "${name}".`);
|
|
141
|
-
const knownParameters = /* @__PURE__ */ new Set([...Object.entries(parameters).flatMap(([parameterName, value]) => value === void 0 ? [] : [parameterName]), ...live.knownParameters]);
|
|
142
|
-
const missingKnownRequiredParameters = actionType.parameters.filter((parameter) => parameters[parameter.name] === void 0 && knownParameters.has(parameter.name) && !unwrapType(resolveType(opts.ir, parameter.type)).isOptional);
|
|
143
|
-
if (missingKnownRequiredParameters.length > 0) return certain({
|
|
144
|
-
kind: "err",
|
|
145
|
-
value: missingKnownRequiredParameters.map((parameter) => ({
|
|
146
|
-
message: `Required action parameter "${parameter.name}" is missing.`,
|
|
147
|
-
path: [parameter.name]
|
|
148
|
-
}))
|
|
149
|
-
});
|
|
150
|
-
if (!actionType.parameters.some((parameter) => parameters[parameter.name] === void 0 && !knownParameters.has(parameter.name))) return adapter.validateAction(name, parameters, live);
|
|
151
|
-
const userId = typeof live.context?.user === "string" ? live.context.user : void 0;
|
|
152
|
-
if (!userId) return uncertain();
|
|
153
|
-
const criteria = await loadFoundrySubmissionCriteria({
|
|
154
|
-
client: opts.client,
|
|
155
|
-
actionTypeName: name,
|
|
156
|
-
userId
|
|
157
|
-
});
|
|
158
|
-
return validateFoundryActionDraftCriteria({
|
|
159
|
-
client: opts.client,
|
|
160
|
-
criteria,
|
|
161
|
-
userId,
|
|
162
|
-
parameters,
|
|
163
|
-
knownParameters
|
|
164
|
-
});
|
|
165
|
-
},
|
|
166
|
-
applyAction: async (name, parameters, context) => {
|
|
167
|
-
const mediaReferences = /* @__PURE__ */ new Map();
|
|
168
|
-
const attachmentIdMappings = [];
|
|
169
|
-
await Promise.all([...new Map((context.attachmentUploads ?? []).map((upload) => [upload.attachment.id, upload])).values()].map(async (upload) => {
|
|
170
|
-
invariant(getAttachmentProviderType(upload.target) === "media", `Foundry attachment "${upload.attachment.id}" was not materialized before action execution.`);
|
|
171
|
-
const reference = await MediaSets.uploadMedia(opts.client, upload.blob, { filename: getAttachmentName(upload.blob) ?? upload.attachment.id });
|
|
172
|
-
mediaReferences.set(upload.attachment.id, reference);
|
|
173
|
-
attachmentIdMappings.push({
|
|
174
|
-
localId: upload.attachment.id,
|
|
175
|
-
remoteId: mediaReferenceToFoundryMediaId(reference)
|
|
176
|
-
});
|
|
177
|
-
}));
|
|
178
|
-
const actionCodec = createFoundryCodec(opts.ir, { resolveMediaReference: (id) => mediaReferences.get(id) });
|
|
179
|
-
const invocation = prepareFoundryActionInvocation({
|
|
180
|
-
ir: opts.ir,
|
|
181
|
-
name,
|
|
182
|
-
parameters,
|
|
183
|
-
codec: actionCodec
|
|
184
|
-
});
|
|
185
|
-
let result;
|
|
186
|
-
try {
|
|
187
|
-
result = await Actions.applyWithOverrides(opts.client, opts.client.ontologyRid, toFoundryActionTypeName(name), {
|
|
188
|
-
request: {
|
|
189
|
-
options: {
|
|
190
|
-
mode: "VALIDATE_AND_EXECUTE",
|
|
191
|
-
returnEdits: "ALL_V2_WITH_DELETIONS"
|
|
192
|
-
},
|
|
193
|
-
parameters: invocation.parameters
|
|
194
|
-
},
|
|
195
|
-
overrides: invocation.overrides
|
|
196
|
-
}, { preview: true });
|
|
197
|
-
} catch (error) {
|
|
198
|
-
if (isFoundryNotFoundError(error)) throw new NonRetryableError(error instanceof Error ? error.message : "Foundry action target was not found.", { cause: error });
|
|
199
|
-
throw error;
|
|
200
|
-
}
|
|
201
|
-
if (result.validation?.result === "INVALID") throw new NonRetryableError("Invalid Action arguments.");
|
|
202
|
-
if (opts.live !== false && context) {
|
|
203
|
-
const operationId = getApplyActionOperationId(result);
|
|
204
|
-
const targetCollections = Array.from(getEditedObjectTypes(result.edits)).map((objectType) => context.objects[objectType]).filter((collection) => Boolean(collection?.utils?.awaitOperationId));
|
|
205
|
-
await Promise.all(targetCollections.map((collection) => collection.utils.awaitOperationId(operationId)));
|
|
206
|
-
}
|
|
207
|
-
if (attachmentIdMappings.length === 0) return;
|
|
208
|
-
return { attachmentIdMappings };
|
|
209
|
-
},
|
|
210
|
-
runQueryFunction: async (name, parameters) => {
|
|
211
|
-
const queryFunctionType = opts.ir.queryFunctionTypes.find((candidate) => candidate.name === name);
|
|
212
|
-
if (!queryFunctionType) throw new Error(`Unknown Foundry query function type "${name}".`);
|
|
213
|
-
const parameterTypes = new Map(queryFunctionType.parameters.map((parameter) => [parameter.name, parameter.type]));
|
|
214
|
-
const requestParameters = {};
|
|
215
|
-
for (const [parameterName, value] of Object.entries(parameters)) {
|
|
216
|
-
if (value === void 0) continue;
|
|
217
|
-
const parameterType = parameterTypes.get(parameterName);
|
|
218
|
-
requestParameters[parameterName] = parameterType ? codec.encodeValue(parameterType, value) : value;
|
|
219
|
-
}
|
|
220
|
-
const result = await Queries.execute(opts.client, opts.client.ontologyRid, name, { parameters: requestParameters });
|
|
221
|
-
return codec.decodeValue(queryFunctionType.returnType, result.value);
|
|
222
|
-
},
|
|
223
|
-
attachments: {
|
|
224
|
-
generateAttachmentId: (_, { target }) => {
|
|
225
|
-
invariant(target, "A property target must be passed to generateAttachmentId in the Foundry adapter so that we know whether to target attachments or media.");
|
|
226
|
-
if (getFoundryAttachmentKind(target.meta) === "attachment") return `ri.attachments.main.attachment.${crypto.randomUUID()}`;
|
|
227
|
-
return crypto.randomUUID();
|
|
228
|
-
},
|
|
229
|
-
canMaterializeAttachment: (_, { target }) => getAttachmentProviderType(target) !== "media",
|
|
230
|
-
materializeAttachment: async (attachment, blob, { target }) => {
|
|
231
|
-
invariant(target, "A property target must be passed to materializeAttachment in the Foundry adapter so that we know whether to target attachments or media.");
|
|
232
|
-
invariant(getAttachmentProviderType(target) === "attachment", "Foundry media references must be uploaded during action execution.");
|
|
233
|
-
const filename = getAttachmentName(blob) ?? "";
|
|
234
|
-
if (!isFoundryAttachmentRid(attachment.id)) {
|
|
235
|
-
const uploaded = await Attachments.upload(opts.client, blob, { filename });
|
|
236
|
-
return {
|
|
237
|
-
...attachment,
|
|
238
|
-
id: uploaded.rid
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
try {
|
|
242
|
-
await Attachments.get(opts.client, attachment.id);
|
|
243
|
-
return;
|
|
244
|
-
} catch (error) {
|
|
245
|
-
if (!isFoundryNotFoundError(error)) throw error;
|
|
246
|
-
}
|
|
247
|
-
await Attachments.uploadWithRid(opts.client, attachment.id, blob, {
|
|
248
|
-
filename,
|
|
249
|
-
preview: true
|
|
250
|
-
});
|
|
251
|
-
},
|
|
252
|
-
getAttachmentContent: async (attachment) => {
|
|
253
|
-
const userContent = await opts.users?.getAttachmentContent?.(opts.client, attachment);
|
|
254
|
-
if (userContent) return userContent;
|
|
255
|
-
if (decodeFoundryMediaId(attachment.id)) {
|
|
256
|
-
const source = attachment.source;
|
|
257
|
-
invariant(source, `Foundry media attachment "${attachment.id}" is missing its object property source.`);
|
|
258
|
-
return (await MediaReferenceProperties.getMediaContent(opts.client, opts.client.ontologyRid, source.objectType, String(source.primaryKey), source.property, { preview: true })).blob();
|
|
259
|
-
}
|
|
260
|
-
return (await Attachments.read(opts.client, attachment.id)).blob();
|
|
261
|
-
},
|
|
262
|
-
getAttachmentMetadata: async (attachment, selection) => {
|
|
263
|
-
const userMetadata = await opts.users?.getAttachmentMetadata?.(opts.client, attachment, selection);
|
|
264
|
-
if (userMetadata) return userMetadata;
|
|
265
|
-
const media = decodeFoundryMediaId(attachment.id);
|
|
266
|
-
if (media) {
|
|
267
|
-
const result = {};
|
|
268
|
-
if (attachment.type !== void 0) result.type = attachment.type;
|
|
269
|
-
if (selection.includes("dimensions")) {
|
|
270
|
-
const detailed = await MediaSets.metadata(opts.client, media.mediaSetRid, media.mediaItemRid);
|
|
271
|
-
result.size = detailed.sizeBytes;
|
|
272
|
-
if (detailed.type === "imagery" && detailed.dimensions) result.dimensions = {
|
|
273
|
-
width: detailed.dimensions.width,
|
|
274
|
-
height: detailed.dimensions.height
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
if (!selection.filter((field) => result[field] === void 0).some((field) => field !== "dimensions")) return result;
|
|
278
|
-
const source = attachment.source;
|
|
279
|
-
invariant(source, `Foundry media attachment "${attachment.id}" is missing its object property source.`);
|
|
280
|
-
const info = await MediaReferenceProperties.getMediaMetadata(opts.client, opts.client.ontologyRid, source.objectType, String(source.primaryKey), source.property, { preview: true });
|
|
281
|
-
return {
|
|
282
|
-
...result,
|
|
283
|
-
size: Number(info.sizeBytes),
|
|
284
|
-
type: info.mediaType,
|
|
285
|
-
name: info.path
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
const metadata = await Attachments.get(opts.client, attachment.id);
|
|
289
|
-
return {
|
|
290
|
-
id: attachment.id,
|
|
291
|
-
size: Number(metadata.sizeBytes),
|
|
292
|
-
type: metadata.mediaType,
|
|
293
|
-
name: metadata.filename
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
};
|
|
298
|
-
return adapter;
|
|
299
|
-
}
|
|
300
|
-
function createFoundryOntologyBackend(opts) {
|
|
301
|
-
return async (ir, context) => createFoundryOntologyBackendAdapter({
|
|
302
|
-
ir,
|
|
303
|
-
client: "client" in opts ? opts.client : await opts.createClient(ir, context),
|
|
304
|
-
users: opts.users,
|
|
305
|
-
live: opts.live
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
//#endregion
|
|
309
|
-
export { createFoundryOntologyBackend, createFoundryOntologyBackendAdapter, isFoundryNotFoundError };
|
|
310
|
-
|
|
311
|
-
//# sourceMappingURL=createFoundryOntologyBackendAdapter.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"createFoundryOntologyBackendAdapter.js","names":[],"sources":["../../src/adapter/createFoundryOntologyBackendAdapter.ts"],"sourcesContent":["import { invariant } from \"@bobbyfidz/panic\";\nimport { MediaSets } from \"@osdk/foundry.mediasets\";\nimport {\n Actions,\n AttachmentRid,\n Attachments,\n MediaReferenceProperties,\n Queries,\n} from \"@osdk/foundry.ontologies\";\nimport {\n certain,\n NonRetryableError,\n uncertain,\n type PartialAttachmentMetadata,\n type OntologyAttachmentIdMapping,\n type OntologyBackendAdapter,\n type OntologyBackendAdapterProvider,\n type OntologyCollectionOptions,\n type OntologyAttachmentsAdapter,\n type OntologyIR,\n type ValidateActionDraftLiveOpts,\n} from \"@party-stack/ontology\";\nimport { resolveType, unwrapType } from \"@party-stack/ontology/utils\";\nimport { Collection } from \"@tanstack/db\";\nimport { Temporal } from \"temporal-polyfill\";\nimport { getFoundryActionOverrideParameterMapping } from \"../meta/convertMetaActionType.js\";\nimport { getFoundryAttachmentKind } from \"../meta/foundryAttachmentMetadata.js\";\nimport { toFoundryActionTypeName } from \"../utils/actionTypeName.js\";\nimport {\n getFoundryValidationIssues,\n loadFoundrySubmissionCriteria,\n validateFoundryActionDraftCriteria,\n} from \"./foundryActionValidation.js\";\nimport { createFoundryCodec } from \"./foundryCodec.js\";\nimport { decodeFoundryMediaId, mediaReferenceToFoundryMediaId } from \"./foundryMediaId.js\";\nimport { objectCollectionOptions, type ObjectCollectionUtils } from \"./objectCollectionOptions.js\";\nimport type { OntologyClient } from \"@party-stack/foundry-client\";\nimport type { attachment } from \"@party-stack/ontology/values\";\n\nfunction isFoundryAttachmentRid(value: string): value is AttachmentRid {\n return /^ri\\.attachments\\.[^.]+\\.attachment\\..+$/.test(value);\n}\n\nexport function isFoundryNotFoundError(error: unknown): boolean {\n if (typeof error !== \"object\" || error === null) {\n return false;\n }\n const foundryError = error as {\n statusCode?: unknown;\n errorCode?: unknown;\n };\n return foundryError.statusCode === 404 || foundryError.errorCode === \"NOT_FOUND\";\n}\n\nexport interface FoundryUsersIntegration {\n objectType: string;\n getCollectionOptions(client: OntologyClient): OntologyCollectionOptions;\n getAttachmentContent?(client: OntologyClient, attachment: attachment): Promise<Blob | undefined>;\n getAttachmentMetadata?(\n client: OntologyClient,\n attachment: attachment,\n selection: readonly (keyof PartialAttachmentMetadata)[]\n ): Promise<PartialAttachmentMetadata | undefined>;\n}\n\ntype CollectionWithUtils = Collection<Record<string, unknown>, string | number, ObjectCollectionUtils>;\ntype ApplyActionResult = Awaited<ReturnType<typeof Actions.applyWithOverrides>> & {\n operationId?: string;\n};\n\nfunction serializeOverrideValue(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n if (typeof value === \"number\" || typeof value === \"boolean\" || typeof value === \"bigint\") {\n return String(value);\n }\n if (value instanceof Date) {\n return value.toISOString();\n }\n if (value instanceof Temporal.Instant) {\n return value.toString();\n }\n if (value instanceof Temporal.PlainDate || value instanceof Temporal.PlainDateTime) {\n return value.toString();\n }\n return JSON.stringify(value) ?? \"\";\n}\n\nfunction serializeActionExecutionTime(value: unknown): string {\n try {\n const candidate = value instanceof Date ? value.toISOString() : String(value);\n return Temporal.Instant.from(candidate).toString();\n } catch (cause) {\n throw new TypeError(\"Invalid action execution time: expected a Date or Temporal-like ISO instant.\", {\n cause,\n });\n }\n}\n\nfunction getApplyActionOperationId(result: ApplyActionResult): string {\n const operationId = result.operationId;\n if (typeof operationId !== \"string\" || operationId.length === 0) {\n throw new Error(\"Foundry apply action response did not include an operationId.\");\n }\n return operationId;\n}\n\nfunction getAttachmentName(attachment: unknown): string | undefined {\n if (typeof attachment !== \"object\" || attachment === null || Array.isArray(attachment)) {\n return undefined;\n }\n const name = (attachment as Record<string, unknown>).name;\n return typeof name === \"string\" ? name : undefined;\n}\n\nfunction getAttachmentProviderType(\n target: { meta?: Record<string, unknown> } | undefined\n): \"attachment\" | \"media\" {\n return getFoundryAttachmentKind(target?.meta);\n}\n\nfunction getEditedObjectTypes(\n edits: Awaited<ReturnType<typeof Actions.applyWithOverrides>>[\"edits\"]\n): Set<string> {\n const objectTypes = new Set<string>();\n if (!edits || edits.type !== \"edits\") {\n return objectTypes;\n }\n\n for (const edit of edits.edits) {\n if (edit.type === \"addObject\" || edit.type === \"modifyObject\" || edit.type === \"deleteObject\") {\n objectTypes.add(edit.objectType);\n }\n }\n\n return objectTypes;\n}\n\nfunction prepareFoundryActionInvocation(options: {\n ir: OntologyIR;\n name: string;\n parameters: Record<string, unknown>;\n codec: ReturnType<typeof createFoundryCodec>;\n}): {\n parameters: Record<string, unknown>;\n overrides: {\n uniqueIdentifierLinkIdValues: Record<string, string>;\n actionExecutionTime?: string;\n };\n} {\n const actionType = options.ir.actionTypes.find((candidate) => candidate.name === options.name);\n if (!actionType) {\n throw new NonRetryableError(`Unknown Foundry action type \"${options.name}\".`);\n }\n const overrideMapping = getFoundryActionOverrideParameterMapping(actionType);\n const parameterTypes = new Map(\n actionType.parameters.map((parameter) => [parameter.name, parameter.type])\n );\n const parameters: Record<string, unknown> = {};\n const uniqueIdentifierLinkIdValues: Record<string, string> = {};\n let actionExecutionTime: string | undefined;\n\n for (const [parameterName, value] of Object.entries(options.parameters)) {\n if (overrideMapping.uuidByParameterName.has(parameterName)) {\n if (value !== undefined) {\n uniqueIdentifierLinkIdValues[overrideMapping.uuidByParameterName.get(parameterName)!] =\n serializeOverrideValue(value);\n }\n continue;\n }\n if (overrideMapping.nowParameterName === parameterName) {\n if (value !== undefined) {\n actionExecutionTime = serializeActionExecutionTime(value);\n }\n continue;\n }\n if (value !== undefined) {\n const parameterType = parameterTypes.get(parameterName);\n parameters[parameterName] = parameterType\n ? options.codec.encodeValue(parameterType, value)\n : value;\n }\n }\n\n return {\n parameters,\n overrides: {\n uniqueIdentifierLinkIdValues,\n actionExecutionTime,\n },\n };\n}\n\nexport interface CreateFoundryOntologyBackendAdapterOptions {\n client: OntologyClient;\n ir: OntologyIR;\n users?: FoundryUsersIntegration;\n live?: boolean;\n}\n\nexport function createFoundryOntologyBackendAdapter(\n opts: CreateFoundryOntologyBackendAdapterOptions\n): OntologyBackendAdapter {\n const codec = createFoundryCodec(opts.ir);\n const attachments: OntologyAttachmentsAdapter = {\n generateAttachmentId: (_, { target }) => {\n invariant(\n target,\n \"A property target must be passed to generateAttachmentId in the Foundry adapter so that we know whether to target attachments or media.\"\n );\n if (getFoundryAttachmentKind(target.meta) === \"attachment\") {\n return `ri.attachments.main.attachment.${crypto.randomUUID()}`;\n }\n return crypto.randomUUID();\n },\n canMaterializeAttachment: (_, { target }) => getAttachmentProviderType(target) !== \"media\",\n materializeAttachment: async (attachment, blob, { target }) => {\n invariant(\n target,\n \"A property target must be passed to materializeAttachment in the Foundry adapter so that we know whether to target attachments or media.\"\n );\n invariant(\n getAttachmentProviderType(target) === \"attachment\",\n \"Foundry media references must be uploaded during action execution.\"\n );\n const filename = getAttachmentName(blob) ?? \"\";\n if (!isFoundryAttachmentRid(attachment.id)) {\n const uploaded = await Attachments.upload(opts.client, blob, { filename });\n return {\n ...attachment,\n id: uploaded.rid,\n };\n }\n try {\n await Attachments.get(opts.client, attachment.id);\n return;\n } catch (error) {\n if (!isFoundryNotFoundError(error)) {\n throw error;\n }\n }\n await Attachments.uploadWithRid(opts.client, attachment.id, blob, {\n filename,\n preview: true,\n });\n },\n getAttachmentContent: async (attachment) => {\n const userContent = await opts.users?.getAttachmentContent?.(opts.client, attachment);\n if (userContent) return userContent;\n const media = decodeFoundryMediaId(attachment.id);\n if (media) {\n const source = attachment.source;\n invariant(\n source,\n `Foundry media attachment \"${attachment.id}\" is missing its object property source.`\n );\n const response = await MediaReferenceProperties.getMediaContent(\n opts.client,\n opts.client.ontologyRid,\n source.objectType,\n String(source.primaryKey),\n source.property,\n { preview: true }\n );\n return response.blob();\n }\n const contents = await Attachments.read(opts.client, attachment.id);\n return contents.blob();\n },\n getAttachmentMetadata: async (attachment, selection) => {\n const userMetadata = await opts.users?.getAttachmentMetadata?.(\n opts.client,\n attachment,\n selection\n );\n if (userMetadata) return userMetadata;\n const media = decodeFoundryMediaId(attachment.id);\n if (media) {\n const result: PartialAttachmentMetadata = {};\n if (attachment.type !== undefined) {\n result.type = attachment.type;\n }\n if (selection.includes(\"dimensions\")) {\n const detailed = await MediaSets.metadata(\n opts.client,\n media.mediaSetRid,\n media.mediaItemRid\n );\n result.size = detailed.sizeBytes;\n if (detailed.type === \"imagery\" && detailed.dimensions) {\n result.dimensions = {\n width: detailed.dimensions.width,\n height: detailed.dimensions.height,\n };\n }\n }\n const missingMetadata = selection.filter((field) => result[field] === undefined);\n const needsBasicMetadata = missingMetadata.some((field) => field !== \"dimensions\");\n if (!needsBasicMetadata) return result;\n\n const source = attachment.source;\n invariant(\n source,\n `Foundry media attachment \"${attachment.id}\" is missing its object property source.`\n );\n const info = await MediaReferenceProperties.getMediaMetadata(\n opts.client,\n opts.client.ontologyRid,\n source.objectType,\n String(source.primaryKey),\n source.property,\n { preview: true }\n );\n return {\n ...result,\n size: Number(info.sizeBytes),\n type: info.mediaType,\n name: info.path,\n };\n }\n const metadata = await Attachments.get(opts.client, attachment.id);\n return {\n id: attachment.id,\n size: Number(metadata.sizeBytes),\n type: metadata.mediaType,\n name: metadata.filename,\n };\n },\n };\n\n const adapter: OntologyBackendAdapter = {\n name: \"foundry\",\n live: opts.live !== false,\n getCollectionOptions: (objectType: string) => {\n if (opts.users?.objectType === objectType) {\n return opts.users.getCollectionOptions(opts.client);\n }\n const objectTypeDef = opts.ir.objectTypes.find((ot) => ot.name === objectType)!;\n return objectCollectionOptions({\n client: opts.client,\n objectType,\n primaryKeyProperty: objectTypeDef.primaryKey,\n selectedProperties: objectTypeDef.properties.map((property) => property.name),\n live: opts.live,\n decodeObject: (object) => codec.decodeObject(objectType, object),\n decodeEditObject: (object) => codec.decodeEditObject(objectType, object),\n });\n },\n validateAction: async (name: string, parameters: Record<string, unknown>) => {\n const invocation = prepareFoundryActionInvocation({\n ir: opts.ir,\n name,\n parameters,\n codec,\n });\n\n let result: ApplyActionResult;\n try {\n result = await Actions.applyWithOverrides(\n opts.client,\n opts.client.ontologyRid,\n toFoundryActionTypeName(name),\n {\n request: {\n options: {\n mode: \"VALIDATE_ONLY\",\n },\n parameters: invocation.parameters,\n },\n overrides: invocation.overrides,\n },\n // oxlint-disable-next-line typescript/no-unsafe-argument\n {\n preview: true,\n // oxlint-disable-next-line typescript/no-explicit-any\n }\n );\n } catch (error) {\n if (isFoundryNotFoundError(error)) {\n throw new NonRetryableError(\n error instanceof Error ? error.message : \"Foundry action target was not found.\",\n { cause: error }\n );\n }\n throw error;\n }\n\n if (!result.validation) {\n throw new Error(\"Foundry validate action response did not include a validation result.\");\n }\n return {\n certain: true,\n value:\n result.validation.result === \"VALID\"\n ? {\n kind: \"ok\",\n value: undefined,\n }\n : {\n kind: \"err\",\n value: getFoundryValidationIssues(result),\n },\n };\n },\n validateActionDraft: async (\n name: string,\n parameters: Record<string, unknown>,\n live: ValidateActionDraftLiveOpts\n ) => {\n const actionType = opts.ir.actionTypes.find((candidate) => candidate.name === name);\n if (!actionType) {\n throw new NonRetryableError(`Unknown Foundry action type \"${name}\".`);\n }\n const knownParameters = new Set([\n ...Object.entries(parameters).flatMap(([parameterName, value]) =>\n value === undefined ? [] : [parameterName]\n ),\n ...live.knownParameters,\n ]);\n const missingKnownRequiredParameters = actionType.parameters.filter(\n (parameter) =>\n parameters[parameter.name] === undefined &&\n knownParameters.has(parameter.name) &&\n !unwrapType(resolveType(opts.ir, parameter.type)).isOptional\n );\n if (missingKnownRequiredParameters.length > 0) {\n return certain({\n kind: \"err\",\n value: missingKnownRequiredParameters.map((parameter) => ({\n message: `Required action parameter \"${parameter.name}\" is missing.`,\n path: [parameter.name],\n })),\n });\n }\n const hasUnknownParameters = actionType.parameters.some(\n (parameter) =>\n parameters[parameter.name] === undefined && !knownParameters.has(parameter.name)\n );\n if (!hasUnknownParameters) {\n return adapter.validateAction!(name, parameters, live);\n }\n\n const userId = typeof live.context?.user === \"string\" ? live.context.user : undefined;\n if (!userId) {\n return uncertain();\n }\n const criteria = await loadFoundrySubmissionCriteria({\n client: opts.client,\n actionTypeName: name,\n userId,\n });\n return validateFoundryActionDraftCriteria({\n client: opts.client,\n criteria,\n userId,\n parameters,\n knownParameters,\n });\n },\n applyAction: async (name, parameters, context) => {\n const mediaReferences = new Map<string, Awaited<ReturnType<typeof MediaSets.uploadMedia>>>();\n const attachmentIdMappings: OntologyAttachmentIdMapping[] = [];\n await Promise.all(\n [\n ...new Map(\n (context.attachmentUploads ?? []).map((upload) => [upload.attachment.id, upload])\n ).values(),\n ].map(async (upload) => {\n invariant(\n getAttachmentProviderType(upload.target) === \"media\",\n `Foundry attachment \"${upload.attachment.id}\" was not materialized before action execution.`\n );\n const reference = await MediaSets.uploadMedia(opts.client, upload.blob, {\n filename: getAttachmentName(upload.blob) ?? upload.attachment.id,\n });\n mediaReferences.set(upload.attachment.id, reference);\n attachmentIdMappings.push({\n localId: upload.attachment.id,\n remoteId: mediaReferenceToFoundryMediaId(reference),\n });\n })\n );\n const actionCodec = createFoundryCodec(opts.ir, {\n resolveMediaReference: (id) => mediaReferences.get(id),\n });\n const invocation = prepareFoundryActionInvocation({\n ir: opts.ir,\n name,\n parameters,\n codec: actionCodec,\n });\n\n let result: ApplyActionResult;\n try {\n result = await Actions.applyWithOverrides(\n opts.client,\n opts.client.ontologyRid,\n toFoundryActionTypeName(name),\n {\n request: {\n options: {\n mode: \"VALIDATE_AND_EXECUTE\",\n returnEdits: \"ALL_V2_WITH_DELETIONS\",\n },\n parameters: invocation.parameters,\n },\n overrides: invocation.overrides,\n },\n // oxlint-disable-next-line typescript/no-unsafe-argument\n {\n preview: true,\n // oxlint-disable-next-line typescript/no-explicit-any\n }\n );\n } catch (error) {\n if (isFoundryNotFoundError(error)) {\n throw new NonRetryableError(\n error instanceof Error ? error.message : \"Foundry action target was not found.\",\n { cause: error }\n );\n }\n throw error;\n }\n if (result.validation?.result === \"INVALID\") {\n throw new NonRetryableError(\"Invalid Action arguments.\");\n }\n if (opts.live !== false && context) {\n const operationId = getApplyActionOperationId(result);\n const editedObjectTypes = Array.from(getEditedObjectTypes(result.edits));\n const targetCollections = editedObjectTypes\n .map((objectType) => context.objects[objectType] as CollectionWithUtils | undefined)\n .filter((collection): collection is CollectionWithUtils =>\n Boolean(collection?.utils?.awaitOperationId)\n );\n\n await Promise.all(\n targetCollections.map((collection) => collection.utils.awaitOperationId(operationId))\n );\n }\n if (attachmentIdMappings.length === 0) {\n return undefined;\n }\n return {\n attachmentIdMappings,\n };\n },\n runQueryFunction: async (name, parameters) => {\n const queryFunctionType = opts.ir.queryFunctionTypes.find((candidate) => candidate.name === name);\n if (!queryFunctionType) {\n throw new Error(`Unknown Foundry query function type \"${name}\".`);\n }\n\n const parameterTypes = new Map(\n queryFunctionType.parameters.map((parameter) => [parameter.name, parameter.type])\n );\n const requestParameters: Record<string, unknown> = {};\n for (const [parameterName, value] of Object.entries(parameters)) {\n if (value === undefined) continue;\n const parameterType = parameterTypes.get(parameterName);\n requestParameters[parameterName] = parameterType\n ? codec.encodeValue(parameterType, value)\n : value;\n }\n\n const result = await Queries.execute(opts.client, opts.client.ontologyRid, name, {\n parameters: requestParameters,\n });\n\n return codec.decodeValue(queryFunctionType.returnType, result.value);\n },\n attachments,\n };\n return adapter;\n}\n\nexport type CreateFoundryOntologyBackendOptions<\n Context extends Record<string, unknown> = Record<string, unknown>,\n> = (\n | {\n client: OntologyClient;\n }\n | {\n createClient: (ir: OntologyIR, context: Context) => OntologyClient | Promise<OntologyClient>;\n }\n) & {\n users?: FoundryUsersIntegration;\n live?: boolean;\n};\n\nexport function createFoundryOntologyBackend<\n Context extends Record<string, unknown> = Record<string, unknown>,\n>(opts: CreateFoundryOntologyBackendOptions<Context>): OntologyBackendAdapterProvider<Context> {\n return async (ir, context) =>\n createFoundryOntologyBackendAdapter({\n ir,\n client: \"client\" in opts ? opts.client : await opts.createClient(ir, context),\n users: opts.users,\n live: opts.live,\n });\n}\n"],"mappings":"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"}
|