@party-stack/foundry-ontology 0.18.1 → 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.
Files changed (203) hide show
  1. package/README.md +56 -16
  2. package/lib/adapter/backend.d.ts +35 -0
  3. package/lib/adapter/backend.d.ts.map +1 -0
  4. package/lib/adapter/backend.js +210 -0
  5. package/lib/adapter/backend.js.map +1 -0
  6. package/lib/adapter/encrypted.d.ts +12 -0
  7. package/lib/adapter/encrypted.d.ts.map +1 -0
  8. package/lib/adapter/encrypted.js +79 -0
  9. package/lib/adapter/encrypted.js.map +1 -0
  10. package/lib/adapter/foundryActionError.d.ts +7 -0
  11. package/lib/adapter/foundryActionError.d.ts.map +1 -0
  12. package/lib/adapter/foundryActionError.js +61 -0
  13. package/lib/adapter/foundryActionError.js.map +1 -0
  14. package/lib/adapter/foundryActionValidation.d.ts +4 -3
  15. package/lib/adapter/foundryActionValidation.d.ts.map +1 -1
  16. package/lib/adapter/foundryActionValidation.js +71 -25
  17. package/lib/adapter/foundryActionValidation.js.map +1 -1
  18. package/lib/adapter/foundryCodec.d.ts +3 -5
  19. package/lib/adapter/foundryCodec.d.ts.map +1 -1
  20. package/lib/adapter/foundryCodec.js +19 -7
  21. package/lib/adapter/foundryCodec.js.map +1 -1
  22. package/lib/adapter/foundryObjectSearch.d.ts +13 -0
  23. package/lib/adapter/foundryObjectSearch.d.ts.map +1 -0
  24. package/lib/adapter/foundryObjectSearch.js +57 -0
  25. package/lib/adapter/foundryObjectSearch.js.map +1 -0
  26. package/lib/adapter/index.d.ts +3 -4
  27. package/lib/adapter/index.js +3 -4
  28. package/lib/adapter/likeFilter.d.ts +10 -0
  29. package/lib/adapter/likeFilter.d.ts.map +1 -0
  30. package/lib/adapter/likeFilter.js +87 -0
  31. package/lib/adapter/likeFilter.js.map +1 -0
  32. package/lib/adapter/makeFoundryOntologyBackend.d.ts +76 -0
  33. package/lib/adapter/makeFoundryOntologyBackend.d.ts.map +1 -0
  34. package/lib/adapter/makeFoundryOntologyBackend.js +505 -0
  35. package/lib/adapter/makeFoundryOntologyBackend.js.map +1 -0
  36. package/lib/adapter/subsetFilter.d.ts +14 -0
  37. package/lib/adapter/subsetFilter.d.ts.map +1 -0
  38. package/lib/adapter/subsetFilter.js +105 -0
  39. package/lib/adapter/subsetFilter.js.map +1 -0
  40. package/lib/adapter/uploads.d.ts +25 -0
  41. package/lib/adapter/uploads.d.ts.map +1 -0
  42. package/lib/adapter/uploads.js +78 -0
  43. package/lib/adapter/uploads.js.map +1 -0
  44. package/lib/backend.d.ts +80 -0
  45. package/lib/backend.d.ts.map +1 -0
  46. package/lib/backend.js +34 -0
  47. package/lib/backend.js.map +1 -0
  48. package/lib/config/index.d.ts +8 -12
  49. package/lib/config/index.d.ts.map +1 -1
  50. package/lib/config/index.js +49 -52
  51. package/lib/config/index.js.map +1 -1
  52. package/lib/connectionOptions.d.ts +9 -0
  53. package/lib/connectionOptions.d.ts.map +1 -0
  54. package/lib/connectionOptions.js +1 -0
  55. package/lib/context.d.ts +21 -0
  56. package/lib/context.d.ts.map +1 -0
  57. package/lib/context.js +16 -0
  58. package/lib/context.js.map +1 -0
  59. package/lib/index.d.ts +7 -7
  60. package/lib/index.js +6 -7
  61. package/lib/meta/backend.d.ts +10 -0
  62. package/lib/meta/backend.d.ts.map +1 -0
  63. package/lib/meta/backend.js +161 -0
  64. package/lib/meta/backend.js.map +1 -0
  65. package/lib/meta/convertMetaActionType.d.ts +3 -2
  66. package/lib/meta/convertMetaActionType.d.ts.map +1 -1
  67. package/lib/meta/convertMetaActionType.js +3 -3
  68. package/lib/meta/convertMetaActionType.js.map +1 -1
  69. package/lib/meta/convertMetaLinkType.d.ts +2 -2
  70. package/lib/meta/convertMetaLinkType.d.ts.map +1 -1
  71. package/lib/meta/convertMetaLinkType.js +13 -13
  72. package/lib/meta/convertMetaLinkType.js.map +1 -1
  73. package/lib/meta/convertMetaObjectType.d.ts +2 -2
  74. package/lib/meta/convertMetaObjectType.d.ts.map +1 -1
  75. package/lib/meta/convertMetaObjectType.js +5 -1
  76. package/lib/meta/convertMetaObjectType.js.map +1 -1
  77. package/lib/meta/convertMetaQueryFunctionType.d.ts +1 -1
  78. package/lib/meta/convertMetaQueryFunctionType.js.map +1 -1
  79. package/lib/meta/convertMetaTypeDef.d.ts +1 -1
  80. package/lib/meta/convertMetaTypeDef.d.ts.map +1 -1
  81. package/lib/meta/convertMetaTypeDef.js +7 -1
  82. package/lib/meta/convertMetaTypeDef.js.map +1 -1
  83. package/lib/meta/convertMetaValueType.d.ts +2 -2
  84. package/lib/meta/convertMetaValueType.d.ts.map +1 -1
  85. package/lib/meta/convertMetaValueType.js.map +1 -1
  86. package/lib/meta/convertOmsActionParameterMetadata.d.ts +1 -1
  87. package/lib/meta/convertOmsActionParameterMetadata.js +1 -1
  88. package/lib/meta/convertOmsActionParameterMetadata.js.map +1 -1
  89. package/lib/meta/index.d.ts +2 -4
  90. package/lib/meta/index.js +2 -4
  91. package/lib/meta/listObjectTypes.d.ts +6 -0
  92. package/lib/meta/listObjectTypes.d.ts.map +1 -0
  93. package/lib/meta/listObjectTypes.js +13 -0
  94. package/lib/meta/listObjectTypes.js.map +1 -0
  95. package/lib/meta/loadActionTypeOmsMetadata.d.ts +1 -0
  96. package/lib/meta/loadActions.d.ts +7 -0
  97. package/lib/meta/loadActions.d.ts.map +1 -0
  98. package/lib/meta/loadActions.js +20 -0
  99. package/lib/meta/loadActions.js.map +1 -0
  100. package/lib/meta/loadEntities.d.ts +9 -0
  101. package/lib/meta/loadEntities.d.ts.map +1 -0
  102. package/lib/meta/loadEntities.js +73 -0
  103. package/lib/meta/loadEntities.js.map +1 -0
  104. package/lib/meta/loadQueryFunctions.d.ts +11 -0
  105. package/lib/meta/loadQueryFunctions.d.ts.map +1 -0
  106. package/lib/meta/loadQueryFunctions.js +18 -0
  107. package/lib/meta/loadQueryFunctions.js.map +1 -0
  108. package/lib/meta/planMetaLookup.d.ts +12 -0
  109. package/lib/meta/planMetaLookup.d.ts.map +1 -0
  110. package/lib/meta/planMetaLookup.js +44 -0
  111. package/lib/meta/planMetaLookup.js.map +1 -0
  112. package/lib/platform.d.ts +78 -0
  113. package/lib/platform.d.ts.map +1 -0
  114. package/lib/platform.js +116 -0
  115. package/lib/platform.js.map +1 -0
  116. package/lib/platformCollections.d.ts +68 -0
  117. package/lib/platformCollections.d.ts.map +1 -0
  118. package/lib/platformCollections.js +7 -0
  119. package/lib/platformCollections.js.map +1 -0
  120. package/lib/serviceConnector.d.ts +8 -0
  121. package/lib/serviceConnector.d.ts.map +1 -0
  122. package/lib/serviceConnector.js +105 -0
  123. package/lib/serviceConnector.js.map +1 -0
  124. package/lib/stagedWrites.d.ts +3 -2
  125. package/lib/stagedWrites.d.ts.map +1 -1
  126. package/lib/stagedWrites.js +30 -3
  127. package/lib/stagedWrites.js.map +1 -1
  128. package/lib/users/admin.d.ts +105 -0
  129. package/lib/users/admin.d.ts.map +1 -0
  130. package/lib/users/admin.js +35 -0
  131. package/lib/users/admin.js.map +1 -0
  132. package/lib/users/createFoundryUsersIntegration.d.ts +2 -2
  133. package/lib/users/createFoundryUsersIntegration.d.ts.map +1 -1
  134. package/lib/users/createFoundryUsersIntegration.js +4 -6
  135. package/lib/users/createFoundryUsersIntegration.js.map +1 -1
  136. package/lib/users/foundryUser.d.ts +2 -2
  137. package/lib/users/foundryUser.js +1 -1
  138. package/lib/users/foundryUser.js.map +1 -1
  139. package/lib/users/index.d.ts +2 -3
  140. package/lib/users/index.js +2 -3
  141. package/lib/users/loadUserSubset.d.ts +8 -0
  142. package/lib/users/loadUserSubset.d.ts.map +1 -0
  143. package/lib/users/loadUserSubset.js +166 -0
  144. package/lib/users/loadUserSubset.js.map +1 -0
  145. package/lib/utils/AsyncIterable.d.ts +1 -1
  146. package/lib/utils/AsyncIterable.d.ts.map +1 -1
  147. package/lib/utils/AsyncIterable.js +11 -0
  148. package/lib/utils/AsyncIterable.js.map +1 -1
  149. package/package.json +17 -16
  150. package/lib/adapter/convertLoadSubsetOptions.d.ts +0 -8
  151. package/lib/adapter/convertLoadSubsetOptions.d.ts.map +0 -1
  152. package/lib/adapter/convertLoadSubsetOptions.js +0 -178
  153. package/lib/adapter/convertLoadSubsetOptions.js.map +0 -1
  154. package/lib/adapter/createFoundryOntologyBackendAdapter.d.ts +0 -29
  155. package/lib/adapter/createFoundryOntologyBackendAdapter.d.ts.map +0 -1
  156. package/lib/adapter/createFoundryOntologyBackendAdapter.js +0 -311
  157. package/lib/adapter/createFoundryOntologyBackendAdapter.js.map +0 -1
  158. package/lib/adapter/objectCollectionOptions.d.ts +0 -31
  159. package/lib/adapter/objectCollectionOptions.d.ts.map +0 -1
  160. package/lib/adapter/objectCollectionOptions.js +0 -448
  161. package/lib/adapter/objectCollectionOptions.js.map +0 -1
  162. package/lib/config/applyAttachmentConstraintOverrides.d.ts +0 -10
  163. package/lib/config/applyAttachmentConstraintOverrides.d.ts.map +0 -1
  164. package/lib/config/applyAttachmentConstraintOverrides.js +0 -50
  165. package/lib/config/applyAttachmentConstraintOverrides.js.map +0 -1
  166. package/lib/connection.d.ts +0 -38
  167. package/lib/connection.d.ts.map +0 -1
  168. package/lib/connection.js +0 -195
  169. package/lib/connection.js.map +0 -1
  170. package/lib/installation/createFoundryBackendInstallation.d.ts +0 -29
  171. package/lib/installation/createFoundryBackendInstallation.d.ts.map +0 -1
  172. package/lib/installation/createFoundryBackendInstallation.js +0 -60
  173. package/lib/installation/createFoundryBackendInstallation.js.map +0 -1
  174. package/lib/installation/index.d.ts +0 -2
  175. package/lib/installation/index.js +0 -2
  176. package/lib/meta/actionTypeCollectionOptions.d.ts +0 -14
  177. package/lib/meta/actionTypeCollectionOptions.d.ts.map +0 -1
  178. package/lib/meta/actionTypeCollectionOptions.js +0 -58
  179. package/lib/meta/actionTypeCollectionOptions.js.map +0 -1
  180. package/lib/meta/convertActionTypeLoadSubsetOptions.d.ts +0 -7
  181. package/lib/meta/convertActionTypeLoadSubsetOptions.d.ts.map +0 -1
  182. package/lib/meta/convertActionTypeLoadSubsetOptions.js +0 -84
  183. package/lib/meta/convertActionTypeLoadSubsetOptions.js.map +0 -1
  184. package/lib/meta/createFoundryMetaOntologyBackendAdapter.d.ts +0 -11
  185. package/lib/meta/createFoundryMetaOntologyBackendAdapter.d.ts.map +0 -1
  186. package/lib/meta/createFoundryMetaOntologyBackendAdapter.js +0 -43
  187. package/lib/meta/createFoundryMetaOntologyBackendAdapter.js.map +0 -1
  188. package/lib/meta/entityCollectionOptions.d.ts +0 -24
  189. package/lib/meta/entityCollectionOptions.d.ts.map +0 -1
  190. package/lib/meta/entityCollectionOptions.js +0 -69
  191. package/lib/meta/entityCollectionOptions.js.map +0 -1
  192. package/lib/meta/queryFunctionTypeCollectionOptions.d.ts +0 -12
  193. package/lib/meta/queryFunctionTypeCollectionOptions.d.ts.map +0 -1
  194. package/lib/meta/queryFunctionTypeCollectionOptions.js +0 -59
  195. package/lib/meta/queryFunctionTypeCollectionOptions.js.map +0 -1
  196. package/lib/users/createFoundryAdminOntologyRoute.d.ts +0 -55
  197. package/lib/users/createFoundryAdminOntologyRoute.d.ts.map +0 -1
  198. package/lib/users/createFoundryAdminOntologyRoute.js +0 -33
  199. package/lib/users/createFoundryAdminOntologyRoute.js.map +0 -1
  200. package/lib/users/userCollectionOptions.d.ts +0 -24
  201. package/lib/users/userCollectionOptions.d.ts.map +0 -1
  202. package/lib/users/userCollectionOptions.js +0 -94
  203. package/lib/users/userCollectionOptions.js.map +0 -1
@@ -0,0 +1,505 @@
1
+ import { FOUNDRY_CURRENT_USER_CONTEXT_FIELD } from "../context.js";
2
+ import { toFoundryActionTypeName } from "../utils/actionTypeName.js";
3
+ import { getFoundryAttachmentKind } from "../meta/foundryAttachmentMetadata.js";
4
+ import { getFoundryActionOverrideParameterMapping } from "../meta/convertMetaActionType.js";
5
+ import { makeFoundryBackend } from "./backend.js";
6
+ import { makeFoundryEncryptedValues } from "./encrypted.js";
7
+ import { foundryActionError } from "./foundryActionError.js";
8
+ import { getFoundryValidationIssues, loadFoundrySubmissionCriteria, validateFoundryActionDraftCriteria } from "./foundryActionValidation.js";
9
+ import { decodeFoundryMediaId, mediaReferenceToFoundryMediaId } from "./foundryMediaId.js";
10
+ import { createFoundryCodec } from "./foundryCodec.js";
11
+ import { uploadFoundryAttachment, uploadFoundryMedia } from "./uploads.js";
12
+ import { Effect, Redacted, Schema, Stream } from "effect";
13
+ import { invariant } from "@bobbyfidz/panic";
14
+ import { MediaSets } from "@osdk/foundry.mediasets";
15
+ import { Actions, Attachments, MediaReferenceProperties, Queries } from "@osdk/foundry.ontologies";
16
+ import { BackendError, classifyBackendFailure } from "@party-stack/ontology-backend";
17
+ import { certain, uncertain } from "@party-stack/ontology-spec";
18
+ import { resolveType, unwrapType } from "@party-stack/ontology-spec/utils";
19
+ import { byteChunks, byteSource, readableByteSource, scopedByteSource, sliceByteSource } from "@party-stack/ontology-storage/blobs";
20
+ import { Temporal } from "temporal-polyfill";
21
+ //#region src/adapter/makeFoundryOntologyBackend.ts
22
+ const attachmentFailure = (kind, message) => new BackendError({
23
+ operation: "foundry.attachment",
24
+ kind,
25
+ message,
26
+ retryable: false
27
+ });
28
+ function isFoundryAttachmentRid(value) {
29
+ return /^ri\.attachments\.[^.]+\.attachment\..+$/.test(value);
30
+ }
31
+ function isFoundryNotFoundError(error) {
32
+ if (typeof error !== "object" || error === null) return false;
33
+ const foundryError = error;
34
+ return foundryError.statusCode === 404 || foundryError.errorCode === "NOT_FOUND";
35
+ }
36
+ function serializeOverrideValue(value) {
37
+ if (typeof value === "string") return value;
38
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return String(value);
39
+ if (value instanceof Date) return value.toISOString();
40
+ if (value instanceof Temporal.Instant) return value.toString();
41
+ if (value instanceof Temporal.PlainDate || value instanceof Temporal.PlainDateTime) return value.toString();
42
+ return JSON.stringify(value) ?? "";
43
+ }
44
+ function serializeActionExecutionTime(value) {
45
+ try {
46
+ const candidate = value instanceof Date ? value.toISOString() : String(value);
47
+ return Temporal.Instant.from(candidate).toString();
48
+ } catch (cause) {
49
+ throw new TypeError("Invalid action execution time: expected a Date or Temporal-like ISO instant.", { cause });
50
+ }
51
+ }
52
+ function getAttachmentName(attachment) {
53
+ if (typeof attachment !== "object" || attachment === null || Array.isArray(attachment)) return;
54
+ const name = attachment.name;
55
+ return typeof name === "string" ? name : void 0;
56
+ }
57
+ function getAttachmentProviderType(target) {
58
+ return getFoundryAttachmentKind(target?.meta);
59
+ }
60
+ function prepareFoundryActionInvocation(options) {
61
+ const actionType = options.ir.actionTypes.find((candidate) => candidate.name === options.name);
62
+ if (!actionType) throw new BackendError({
63
+ operation: "foundry.prepare",
64
+ kind: "InvalidRequest",
65
+ retryable: false,
66
+ actionOutcome: "not-committed",
67
+ message: `Unknown Foundry action type "${options.name}".`
68
+ });
69
+ const overrideMapping = getFoundryActionOverrideParameterMapping(actionType);
70
+ const parameterTypes = new Map(actionType.parameters.map((parameter) => [parameter.name, parameter.type]));
71
+ const parameters = {};
72
+ const uniqueIdentifierLinkIdValues = {};
73
+ let actionExecutionTime;
74
+ try {
75
+ for (const [parameterName, value] of Object.entries(options.parameters)) {
76
+ if (overrideMapping.uuidByParameterName.has(parameterName)) {
77
+ if (value !== void 0) uniqueIdentifierLinkIdValues[overrideMapping.uuidByParameterName.get(parameterName)] = serializeOverrideValue(value);
78
+ continue;
79
+ }
80
+ if (overrideMapping.nowParameterName === parameterName) {
81
+ if (value !== void 0) actionExecutionTime = serializeActionExecutionTime(value);
82
+ continue;
83
+ }
84
+ if (value !== void 0) {
85
+ const parameterType = parameterTypes.get(parameterName);
86
+ parameters[parameterName] = parameterType ? options.codec.encodeValue(parameterType, value) : value;
87
+ }
88
+ }
89
+ } catch (cause) {
90
+ throw new BackendError({
91
+ operation: "foundry.prepare",
92
+ kind: "InvalidRequest",
93
+ retryable: false,
94
+ actionOutcome: "not-committed",
95
+ message: "Invalid action parameters.",
96
+ cause: Redacted.make(cause)
97
+ });
98
+ }
99
+ return {
100
+ parameters,
101
+ overrides: {
102
+ uniqueIdentifierLinkIdValues,
103
+ actionExecutionTime
104
+ }
105
+ };
106
+ }
107
+ function withRequestSignal(client, signal) {
108
+ return signal ? {
109
+ ...client,
110
+ fetch: (input, init) => client.fetch(input, {
111
+ ...init,
112
+ signal: init?.signal ? AbortSignal.any([signal, init.signal]) : signal
113
+ })
114
+ } : client;
115
+ }
116
+ const makeFoundryOntologyBackend = Effect.fn("Foundry.makeBackend")(function* (opts) {
117
+ const context = opts.context ?? {};
118
+ const codec = yield* Effect.try({
119
+ try: () => createFoundryCodec(opts.ir),
120
+ catch: (cause) => new BackendError({
121
+ operation: "foundry.open",
122
+ kind: "InvalidConfiguration",
123
+ retryable: false,
124
+ message: "Invalid Foundry definition.",
125
+ cause: Redacted.make(cause)
126
+ })
127
+ });
128
+ const Validation = Schema.Struct({ result: Schema.Literals(["VALID", "INVALID"]) });
129
+ const ActionResponse = Schema.Struct({ validation: Schema.optional(Validation) });
130
+ const ValidationResponse = Schema.Struct({ validation: Validation });
131
+ const attachments = {
132
+ materializeAttachment: async (attachment, input, { target, signal }, client = opts.client) => {
133
+ invariant(target, "A property target must be passed to materializeAttachment in the Foundry adapter so that we know whether to target attachments or media.");
134
+ invariant(getAttachmentProviderType(target) === "attachment", "Foundry media references must be uploaded during action execution.");
135
+ const filename = byteSource(input).name ?? "";
136
+ if (!isFoundryAttachmentRid(attachment.id)) {
137
+ const uploaded = await uploadFoundryAttachment(client, input, {
138
+ filename,
139
+ signal
140
+ });
141
+ return {
142
+ ...attachment,
143
+ id: uploaded.rid
144
+ };
145
+ }
146
+ try {
147
+ await Attachments.get(client, attachment.id);
148
+ return;
149
+ } catch (error) {
150
+ if (!isFoundryNotFoundError(error)) throw error;
151
+ }
152
+ await uploadFoundryAttachment(client, input, {
153
+ filename,
154
+ rid: attachment.id,
155
+ signal
156
+ });
157
+ },
158
+ getAttachmentContent: async (attachment, readOptions) => {
159
+ const client = withRequestSignal(opts.client, readOptions?.signal);
160
+ const userContent = await opts.users?.getAttachmentContent?.(client, attachment);
161
+ if (userContent) return userContent;
162
+ if (decodeFoundryMediaId(attachment.id)) {
163
+ const source = attachment.source;
164
+ if (!source) throw attachmentFailure("InvalidRequest", "Media reads require an object property source.");
165
+ const response = await MediaReferenceProperties.getMediaContent(client, client.ontologyRid, source.objectType, String(source.primaryKey), source.property, { preview: true });
166
+ if (!response.body) throw attachmentFailure("InvalidResponse", "Foundry returned no media body.");
167
+ return readableByteSource(response.body, { type: response.headers.get("content-type") ?? attachment.type });
168
+ }
169
+ const contents = await Attachments.read(client, attachment.id);
170
+ if (!contents.body) throw attachmentFailure("InvalidResponse", "Foundry returned no attachment body.");
171
+ return readableByteSource(contents.body, { type: contents.headers.get("content-type") ?? attachment.type });
172
+ },
173
+ getAttachmentMetadata: async (attachment, selection, readOptions) => {
174
+ const client = withRequestSignal(opts.client, readOptions?.signal);
175
+ const userMetadata = await opts.users?.getAttachmentMetadata?.(client, attachment, selection);
176
+ if (userMetadata) return userMetadata;
177
+ const media = decodeFoundryMediaId(attachment.id);
178
+ if (media) {
179
+ const result = {};
180
+ if (attachment.type !== void 0) result.type = attachment.type;
181
+ if (selection.includes("dimensions")) {
182
+ const detailed = await MediaSets.metadata(client, media.mediaSetRid, media.mediaItemRid);
183
+ result.size = detailed.sizeBytes;
184
+ if (detailed.type === "imagery" && detailed.dimensions) result.dimensions = {
185
+ width: detailed.dimensions.width,
186
+ height: detailed.dimensions.height
187
+ };
188
+ }
189
+ if (!selection.filter((field) => result[field] === void 0).some((field) => field !== "dimensions")) return result;
190
+ const source = attachment.source;
191
+ if (!source) throw attachmentFailure("InvalidRequest", "Media reads require an object property source.");
192
+ const info = await MediaReferenceProperties.getMediaMetadata(client, client.ontologyRid, source.objectType, String(source.primaryKey), source.property, { preview: true });
193
+ return {
194
+ ...result,
195
+ size: Number(info.sizeBytes),
196
+ type: info.mediaType,
197
+ name: info.path
198
+ };
199
+ }
200
+ const metadata = await Attachments.get(client, attachment.id);
201
+ return {
202
+ size: Number(metadata.sizeBytes),
203
+ type: metadata.mediaType,
204
+ name: metadata.filename
205
+ };
206
+ }
207
+ };
208
+ const submitAction = async (name, parameters, context, client = opts.client) => {
209
+ if (!opts.ir.actionTypes.some((action) => action.name === name)) throw new BackendError({
210
+ operation: "foundry.applyAction",
211
+ kind: "InvalidRequest",
212
+ retryable: false,
213
+ actionOutcome: "not-committed",
214
+ message: "Unknown Foundry action type."
215
+ });
216
+ const mediaReferences = /* @__PURE__ */ new Map();
217
+ const attachmentIdMappings = [];
218
+ const attachmentIds = /* @__PURE__ */ new Map();
219
+ await Promise.all([...new Map((context.attachmentUploads ?? []).map((upload) => [upload.attachment.id, upload])).values()].map(async (upload) => {
220
+ if (getAttachmentProviderType(upload.target) !== "media") {
221
+ const id = (await attachments.materializeAttachment(upload.attachment, upload.blob, {
222
+ target: upload.target,
223
+ signal: context.signal
224
+ }, client))?.id ?? upload.attachment.id;
225
+ attachmentIds.set(upload.attachment.id, id);
226
+ if (id !== upload.attachment.id) attachmentIdMappings.push({
227
+ localId: upload.attachment.id,
228
+ remoteId: id
229
+ });
230
+ return;
231
+ }
232
+ const reference = await uploadFoundryMedia(client, upload.blob, {
233
+ filename: getAttachmentName(upload.blob) ?? upload.attachment.id,
234
+ signal: context.signal
235
+ });
236
+ mediaReferences.set(upload.attachment.id, reference);
237
+ attachmentIdMappings.push({
238
+ localId: upload.attachment.id,
239
+ remoteId: mediaReferenceToFoundryMediaId(reference)
240
+ });
241
+ })).catch((cause) => {
242
+ const error = foundryActionError("foundry.upload", cause, opts.ir, name, parameters);
243
+ throw new BackendError({
244
+ operation: error.operation,
245
+ kind: error.kind,
246
+ message: error.message,
247
+ retryable: error.retryable,
248
+ issues: error.issues,
249
+ cause: error.cause,
250
+ actionOutcome: "not-committed"
251
+ });
252
+ });
253
+ const actionCodec = createFoundryCodec(opts.ir, {
254
+ resolveMediaReference: (id) => mediaReferences.get(id),
255
+ resolveAttachmentId: (id) => attachmentIds.get(id)
256
+ });
257
+ let invocation;
258
+ try {
259
+ invocation = prepareFoundryActionInvocation({
260
+ ir: opts.ir,
261
+ name,
262
+ parameters,
263
+ codec: actionCodec
264
+ });
265
+ } catch (cause) {
266
+ if (cause instanceof BackendError) throw cause;
267
+ throw new BackendError({
268
+ operation: "foundry.prepare",
269
+ kind: "InvalidRequest",
270
+ retryable: false,
271
+ actionOutcome: "not-committed",
272
+ message: "Invalid action parameters.",
273
+ cause: Redacted.make(cause)
274
+ });
275
+ }
276
+ let result;
277
+ try {
278
+ result = await Actions.applyWithOverrides(client, client.ontologyRid, toFoundryActionTypeName(name), {
279
+ request: {
280
+ options: {
281
+ mode: "VALIDATE_AND_EXECUTE",
282
+ returnEdits: "ALL_V2_WITH_DELETIONS"
283
+ },
284
+ parameters: invocation.parameters
285
+ },
286
+ overrides: invocation.overrides
287
+ }, { preview: true });
288
+ } catch (error) {
289
+ throw foundryActionError("foundry.applyAction", error, opts.ir, name, parameters);
290
+ }
291
+ try {
292
+ Schema.decodeUnknownSync(ActionResponse)(result);
293
+ } catch (cause) {
294
+ throw new BackendError({
295
+ operation: "foundry.applyAction",
296
+ kind: "InvalidResponse",
297
+ retryable: false,
298
+ actionOutcome: "unknown",
299
+ message: "Foundry returned an invalid action response.",
300
+ cause: Redacted.make(cause)
301
+ });
302
+ }
303
+ if (result.validation?.result === "INVALID") throw new BackendError({
304
+ operation: "foundry.applyAction",
305
+ kind: "ValidationFailed",
306
+ message: "Submission failed validation.",
307
+ issues: getFoundryValidationIssues(result, parameters),
308
+ retryable: false,
309
+ actionOutcome: "not-committed"
310
+ });
311
+ return {
312
+ result,
313
+ attachmentIdMappings
314
+ };
315
+ };
316
+ const runQueryFunction = async (name, parameters, client = opts.client) => {
317
+ const queryFunctionType = opts.ir.queryFunctionTypes.find((candidate) => candidate.name === name);
318
+ if (!queryFunctionType) throw new BackendError({
319
+ operation: "foundry.queryFunction",
320
+ kind: "InvalidRequest",
321
+ retryable: false,
322
+ message: `Unknown Foundry query function type "${name}".`
323
+ });
324
+ const parameterTypes = new Map(queryFunctionType.parameters.map((parameter) => [parameter.name, parameter.type]));
325
+ const requestParameters = {};
326
+ for (const [parameterName, value] of Object.entries(parameters)) {
327
+ if (value === void 0) continue;
328
+ const parameterType = parameterTypes.get(parameterName);
329
+ requestParameters[parameterName] = parameterType ? codec.encodeValue(parameterType, value) : value;
330
+ }
331
+ const result = await Queries.execute(client, client.ontologyRid, name, { parameters: requestParameters });
332
+ try {
333
+ return codec.decodeValue(queryFunctionType.returnType, result.value);
334
+ } catch (cause) {
335
+ throw new BackendError({
336
+ operation: "foundry.queryFunction",
337
+ kind: "InvalidResponse",
338
+ retryable: false,
339
+ message: "Foundry returned an invalid query result.",
340
+ cause: Redacted.make(cause)
341
+ });
342
+ }
343
+ };
344
+ const attempt = (operation, run) => Effect.tryPromise({
345
+ try: run,
346
+ catch: (cause) => classifyBackendFailure(operation, cause)
347
+ });
348
+ const validateAction = Effect.fn("Foundry.validateAction")(function* (name, parameters) {
349
+ const invocation = yield* Effect.try({
350
+ try: () => prepareFoundryActionInvocation({
351
+ ir: opts.ir,
352
+ name,
353
+ parameters,
354
+ codec
355
+ }),
356
+ catch: (cause) => foundryActionError("foundry.validateAction", cause, opts.ir, name, parameters)
357
+ });
358
+ const result = yield* Effect.tryPromise({
359
+ try: (signal) => Actions.applyWithOverrides(withRequestSignal(opts.client, signal), opts.client.ontologyRid, toFoundryActionTypeName(name), {
360
+ request: {
361
+ options: { mode: "VALIDATE_ONLY" },
362
+ parameters: invocation.parameters
363
+ },
364
+ overrides: invocation.overrides
365
+ }, { preview: true }),
366
+ catch: (cause) => foundryActionError("foundry.validateAction", cause, opts.ir, name, parameters)
367
+ });
368
+ const { validation } = yield* Schema.decodeUnknownEffect(ValidationResponse)(result).pipe(Effect.mapError((cause) => new BackendError({
369
+ operation: "foundry.validateAction",
370
+ kind: "InvalidResponse",
371
+ retryable: false,
372
+ actionOutcome: "not-committed",
373
+ message: "Foundry returned an invalid validation response.",
374
+ cause: Redacted.make(cause)
375
+ })));
376
+ return certain(validation.result === "VALID" ? {
377
+ kind: "ok",
378
+ value: void 0
379
+ } : {
380
+ kind: "err",
381
+ value: getFoundryValidationIssues(result, parameters)
382
+ });
383
+ });
384
+ const validateActionDraft = Effect.fn("Foundry.validateActionDraft")(function* (name, parameters, live) {
385
+ const action = opts.ir.actionTypes.find((candidate) => candidate.name === name);
386
+ if (!action) return yield* new BackendError({
387
+ operation: "foundry.validateActionDraft",
388
+ kind: "InvalidRequest",
389
+ message: "Unknown action type.",
390
+ retryable: false
391
+ });
392
+ const knownParameters = /* @__PURE__ */ new Set([...Object.entries(parameters).flatMap(([key, value]) => value === void 0 ? [] : [key]), ...live.knownParameters]);
393
+ const missing = action.parameters.filter((parameter) => parameters[parameter.name] === void 0 && knownParameters.has(parameter.name) && !unwrapType(resolveType(opts.ir, parameter.type)).isOptional);
394
+ if (missing.length) return certain({
395
+ kind: "err",
396
+ value: missing.map((parameter) => ({
397
+ message: "A value is required.",
398
+ path: [parameter.name],
399
+ code: "required",
400
+ category: "input",
401
+ source: "parameter",
402
+ messageSource: "standard"
403
+ }))
404
+ });
405
+ if (!action.parameters.some((parameter) => parameters[parameter.name] === void 0 && !knownParameters.has(parameter.name))) return yield* validateAction(name, parameters);
406
+ const value = live.context?.[FOUNDRY_CURRENT_USER_CONTEXT_FIELD];
407
+ const userId = typeof value === "string" ? value : void 0;
408
+ if (!userId) return uncertain();
409
+ return yield* Effect.tryPromise({
410
+ try: async (signal) => validateFoundryActionDraftCriteria({
411
+ client: withRequestSignal(opts.client, signal),
412
+ criteria: await loadFoundrySubmissionCriteria({
413
+ client: withRequestSignal(opts.client, signal),
414
+ actionTypeName: name,
415
+ userId
416
+ }),
417
+ userId,
418
+ parameters,
419
+ knownParameters
420
+ }),
421
+ catch: (cause) => foundryActionError("foundry.validateActionDraft", cause, opts.ir, name, parameters)
422
+ });
423
+ });
424
+ return yield* makeFoundryBackend({
425
+ client: opts.client,
426
+ ir: opts.ir,
427
+ context,
428
+ watch: opts.watch,
429
+ encrypted: makeFoundryEncryptedValues(opts.client, opts.ir),
430
+ users: opts.users && {
431
+ objectType: opts.users.objectType,
432
+ loadSubset: (query, signal) => opts.users.loadSubset(opts.client, query, signal)
433
+ },
434
+ submitAction: (invocation, signal) => submitAction(invocation.name, invocation.parameters, {
435
+ signal,
436
+ attachmentUploads: invocation.attachmentUploads ? [...invocation.attachmentUploads] : void 0
437
+ }, withRequestSignal(opts.client, signal)),
438
+ decodeObject: (objectType, value) => codec.decodeObject(objectType, value),
439
+ queryFunction: (name, parameters, signal) => runQueryFunction(name, parameters, withRequestSignal(opts.client, signal)),
440
+ attachments: {
441
+ stage: (value, blob, settings) => attempt("attachment.stage", async (signal) => {
442
+ const target = settings?.target;
443
+ if (!target || getAttachmentProviderType(target) === "media") throw new BackendError({
444
+ operation: "attachment.stage",
445
+ kind: "NotImplemented",
446
+ retryable: false,
447
+ message: "This attachment target must be uploaded during action execution."
448
+ });
449
+ return await attachments.materializeAttachment(value, blob, {
450
+ target,
451
+ signal
452
+ }, withRequestSignal(opts.client, signal)) ?? value;
453
+ }),
454
+ read: (value, range) => scopedByteSource(Effect.gen(function* () {
455
+ if (range && (!Number.isSafeInteger(range.offset ?? 0) || (range.offset ?? 0) < 0 || range.length !== void 0 && (!Number.isSafeInteger(range.length) || range.length < 0))) return yield* new BackendError({
456
+ operation: "attachment.read",
457
+ kind: "InvalidRequest",
458
+ message: "Invalid byte range.",
459
+ retryable: false
460
+ });
461
+ const download = yield* Effect.acquireRelease(Effect.sync(() => new AbortController()), (controller) => Effect.sync(() => controller.abort()));
462
+ const blob = yield* attempt("attachment.read", (signal) => attachments.getAttachmentContent(value, { signal: AbortSignal.any([signal, download.signal]) }));
463
+ return range ? sliceByteSource(blob, range.offset ?? 0, range.length) : byteSource(blob);
464
+ })),
465
+ metadata: (value, settings) => Effect.gen(function* () {
466
+ const meta = yield* attempt("attachment.metadata", async (signal) => await attachments.getAttachmentMetadata?.(value, settings?.select ?? [
467
+ "size",
468
+ "type",
469
+ "name"
470
+ ], { signal }) ?? {});
471
+ if (settings?.select || meta.size !== void 0 && meta.type !== void 0) return {
472
+ size: meta.size,
473
+ type: meta.type,
474
+ name: meta.name,
475
+ dimensions: meta.dimensions ?? void 0
476
+ };
477
+ const download = yield* Effect.acquireRelease(Effect.sync(() => new AbortController()), (controller) => Effect.sync(() => controller.abort()));
478
+ const blob = yield* attempt("attachment.read", (signal) => attachments.getAttachmentContent(value, { signal: AbortSignal.any([signal, download.signal]) }));
479
+ const source = byteSource(blob);
480
+ return {
481
+ size: source.size ?? (yield* byteChunks(source).pipe(Stream.runFold(() => 0, (total, chunk) => total + chunk.length), Effect.mapError((cause) => new BackendError({
482
+ operation: "attachment.metadata",
483
+ kind: "Unavailable",
484
+ message: "Attachment metadata is unavailable.",
485
+ retryable: true,
486
+ cause
487
+ })))),
488
+ type: source.type,
489
+ name: meta.name,
490
+ dimensions: meta.dimensions ?? void 0
491
+ };
492
+ }).pipe(Effect.scoped)
493
+ }
494
+ }).pipe(Effect.map((native) => ({
495
+ ...native,
496
+ validateAction: (name, parameters, settings) => settings?.knownParameters ? validateActionDraft(name, parameters, {
497
+ context,
498
+ knownParameters: settings.knownParameters
499
+ }) : validateAction(name, parameters)
500
+ })));
501
+ });
502
+ //#endregion
503
+ export { isFoundryNotFoundError, makeFoundryOntologyBackend };
504
+
505
+ //# sourceMappingURL=makeFoundryOntologyBackend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"makeFoundryOntologyBackend.js","names":[],"sources":["../../src/adapter/makeFoundryOntologyBackend.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 { BackendError, classifyBackendFailure } from \"@party-stack/ontology-backend\";\nimport { certain, uncertain, type OntologyIR } from \"@party-stack/ontology-spec\";\nimport { resolveType, unwrapType } from \"@party-stack/ontology-spec/utils\";\nimport {\n byteSource,\n byteChunks,\n readableByteSource,\n sliceByteSource,\n scopedByteSource,\n type ByteInput,\n} from \"@party-stack/ontology-storage/blobs\";\nimport { Effect, Stream, Schema, Redacted, type Types } from \"effect\";\nimport { Temporal } from \"temporal-polyfill\";\nimport { FOUNDRY_CURRENT_USER_CONTEXT_FIELD } from \"../context.js\";\nimport { getFoundryActionOverrideParameterMapping } from \"../meta/convertMetaActionType.js\";\nimport { getFoundryAttachmentKind } from \"../meta/foundryAttachmentMetadata.js\";\nimport { toFoundryActionTypeName } from \"../utils/actionTypeName.js\";\nimport { makeFoundryBackend } from \"./backend.js\";\nimport { makeFoundryEncryptedValues } from \"./encrypted.js\";\nimport { foundryActionError } from \"./foundryActionError.js\";\nimport {\n getFoundryValidationIssues,\n loadFoundrySubmissionCriteria,\n validateFoundryActionDraftCriteria,\n} from \"./foundryActionValidation.js\";\nimport { createFoundryCodec } from \"./foundryCodec.js\";\nimport { decodeFoundryMediaId, mediaReferenceToFoundryMediaId } from \"./foundryMediaId.js\";\nimport { uploadFoundryMedia, uploadFoundryAttachment } from \"./uploads.js\";\nimport type { OntologyClient } from \"@party-stack/foundry-client\";\nimport type {\n BackendAttachments,\n BackendSnapshot,\n ValidationReport,\n ActionReceipt,\n} from \"@party-stack/ontology-backend\";\ntype PartialAttachmentMetadata = Types.Mutable<Effect.Success<ReturnType<BackendAttachments[\"metadata\"]>>>;\ntype OntologyAttachmentIdMapping = NonNullable<ActionReceipt[\"attachmentIdMappings\"]>[number];\nimport type { attachment } from \"@party-stack/ontology-spec/values\";\nimport type { Query } from \"@party-stack/ontology-storage\";\n\nconst attachmentFailure = (kind: \"InvalidRequest\" | \"InvalidResponse\", message: string) =>\n new BackendError({\n operation: \"foundry.attachment\",\n kind,\n message,\n retryable: false,\n });\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 loadSubset(client: OntologyClient, query: Query, signal: AbortSignal): Promise<BackendSnapshot>;\n getAttachmentContent?(client: OntologyClient, attachment: attachment): Promise<ByteInput | undefined>;\n getAttachmentMetadata?(\n client: OntologyClient,\n attachment: attachment,\n selection: readonly (keyof PartialAttachmentMetadata)[]\n ): Promise<PartialAttachmentMetadata | undefined>;\n}\n\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 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 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 BackendError({\n operation: \"foundry.prepare\",\n kind: \"InvalidRequest\",\n retryable: false,\n actionOutcome: \"not-committed\",\n message: `Unknown Foundry action type \"${options.name}\".`,\n });\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 try {\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 } catch (cause) {\n throw new BackendError({\n operation: \"foundry.prepare\",\n kind: \"InvalidRequest\",\n retryable: false,\n actionOutcome: \"not-committed\",\n message: \"Invalid action parameters.\",\n cause: Redacted.make(cause),\n });\n }\n\n return {\n parameters,\n overrides: {\n uniqueIdentifierLinkIdValues,\n actionExecutionTime,\n },\n };\n}\n\nexport interface FoundryOntologyBackendOptions {\n client: OntologyClient;\n ir: OntologyIR;\n users?: FoundryUsersIntegration;\n watch?: boolean;\n context?: Record<string, unknown>;\n}\n\nfunction withRequestSignal(client: OntologyClient, signal?: AbortSignal): OntologyClient {\n return signal\n ? {\n ...client,\n fetch: (input, init) =>\n client.fetch(input, {\n ...init,\n signal: init?.signal ? AbortSignal.any([signal, init.signal]) : signal,\n }),\n }\n : client;\n}\n\nexport const makeFoundryOntologyBackend = Effect.fn(\"Foundry.makeBackend\")(function* (\n opts: FoundryOntologyBackendOptions\n) {\n const context = opts.context ?? {};\n const codec = yield* Effect.try({\n try: () => createFoundryCodec(opts.ir),\n catch: (cause) =>\n new BackendError({\n operation: \"foundry.open\",\n kind: \"InvalidConfiguration\",\n retryable: false,\n message: \"Invalid Foundry definition.\",\n cause: Redacted.make(cause),\n }),\n });\n const Validation = Schema.Struct({ result: Schema.Literals([\"VALID\", \"INVALID\"]) });\n const ActionResponse = Schema.Struct({ validation: Schema.optional(Validation) });\n const ValidationResponse = Schema.Struct({ validation: Validation });\n const attachments = {\n materializeAttachment: async (\n attachment: attachment,\n input: ByteInput,\n {\n target,\n signal,\n }: { target?: import(\"@party-stack/ontology-spec\").AttachmentTypeDef; signal?: AbortSignal },\n client = opts.client\n ) => {\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 = byteSource(input).name ?? \"\";\n if (!isFoundryAttachmentRid(attachment.id)) {\n const uploaded = await uploadFoundryAttachment(client, input, { filename, signal });\n return {\n ...attachment,\n id: uploaded.rid,\n };\n }\n try {\n await Attachments.get(client, attachment.id);\n return;\n } catch (error) {\n if (!isFoundryNotFoundError(error)) {\n throw error;\n }\n }\n await uploadFoundryAttachment(client, input, { filename, rid: attachment.id, signal });\n },\n getAttachmentContent: async (attachment: attachment, readOptions?: { signal?: AbortSignal }) => {\n const client = withRequestSignal(opts.client, readOptions?.signal);\n const userContent = await opts.users?.getAttachmentContent?.(client, attachment);\n if (userContent) return userContent;\n const media = decodeFoundryMediaId(attachment.id);\n if (media) {\n const source = attachment.source;\n if (!source)\n throw attachmentFailure(\n \"InvalidRequest\",\n \"Media reads require an object property source.\"\n );\n const response = await MediaReferenceProperties.getMediaContent(\n client,\n client.ontologyRid,\n source.objectType,\n String(source.primaryKey),\n source.property,\n { preview: true }\n );\n if (!response.body)\n throw attachmentFailure(\"InvalidResponse\", \"Foundry returned no media body.\");\n return readableByteSource(response.body, {\n type: response.headers.get(\"content-type\") ?? attachment.type,\n });\n }\n const contents = await Attachments.read(client, attachment.id);\n if (!contents.body)\n throw attachmentFailure(\"InvalidResponse\", \"Foundry returned no attachment body.\");\n return readableByteSource(contents.body, {\n type: contents.headers.get(\"content-type\") ?? attachment.type,\n });\n },\n getAttachmentMetadata: async (\n attachment: attachment,\n selection: readonly (keyof PartialAttachmentMetadata)[],\n readOptions?: { signal?: AbortSignal }\n ): Promise<PartialAttachmentMetadata> => {\n const client = withRequestSignal(opts.client, readOptions?.signal);\n const userMetadata = await opts.users?.getAttachmentMetadata?.(client, attachment, selection);\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(client, media.mediaSetRid, media.mediaItemRid);\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 if (!source)\n throw attachmentFailure(\n \"InvalidRequest\",\n \"Media reads require an object property source.\"\n );\n const info = await MediaReferenceProperties.getMediaMetadata(\n client,\n 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(client, attachment.id);\n return {\n size: Number(metadata.sizeBytes),\n type: metadata.mediaType,\n name: metadata.filename,\n };\n },\n };\n\n // Submission only calls provider APIs; Replica owns read-back and confirmation.\n const submitAction = async (\n name: string,\n parameters: Record<string, unknown>,\n context: {\n attachmentUploads?: readonly import(\"@party-stack/ontology-backend\").AttachmentUpload[];\n signal?: AbortSignal;\n },\n client = opts.client\n ) => {\n if (!opts.ir.actionTypes.some((action) => action.name === name))\n throw new BackendError({\n operation: \"foundry.applyAction\",\n kind: \"InvalidRequest\",\n retryable: false,\n actionOutcome: \"not-committed\",\n message: \"Unknown Foundry action type.\",\n });\n const mediaReferences = new Map<string, Awaited<ReturnType<typeof MediaSets.uploadMedia>>>();\n const attachmentIdMappings: OntologyAttachmentIdMapping[] = [];\n const attachmentIds = new Map<string, string>();\n await Promise.all(\n [\n ...new Map(\n (context.attachmentUploads ?? []).map((upload) => [upload.attachment.id, upload])\n ).values(),\n ].map(async (upload) => {\n if (getAttachmentProviderType(upload.target) !== \"media\") {\n const result = await attachments.materializeAttachment(\n upload.attachment,\n upload.blob,\n {\n target: upload.target,\n signal: context.signal,\n },\n client\n );\n const id = result?.id ?? upload.attachment.id;\n attachmentIds.set(upload.attachment.id, id);\n if (id !== upload.attachment.id)\n attachmentIdMappings.push({ localId: upload.attachment.id, remoteId: id });\n return;\n }\n const reference = await uploadFoundryMedia(client, upload.blob, {\n filename: getAttachmentName(upload.blob) ?? upload.attachment.id,\n signal: context.signal,\n });\n mediaReferences.set(upload.attachment.id, reference);\n attachmentIdMappings.push({\n localId: upload.attachment.id,\n remoteId: mediaReferenceToFoundryMediaId(reference),\n });\n })\n ).catch((cause) => {\n const error = foundryActionError(\"foundry.upload\", cause, opts.ir, name, parameters);\n throw new BackendError({\n operation: error.operation,\n kind: error.kind,\n message: error.message,\n retryable: error.retryable,\n issues: error.issues,\n cause: error.cause,\n actionOutcome: \"not-committed\",\n });\n });\n const actionCodec = createFoundryCodec(opts.ir, {\n resolveMediaReference: (id) => mediaReferences.get(id),\n resolveAttachmentId: (id) => attachmentIds.get(id),\n });\n let invocation: ReturnType<typeof prepareFoundryActionInvocation>;\n try {\n invocation = prepareFoundryActionInvocation({\n ir: opts.ir,\n name,\n parameters,\n codec: actionCodec,\n });\n } catch (cause) {\n if (cause instanceof BackendError) throw cause;\n throw new BackendError({\n operation: \"foundry.prepare\",\n kind: \"InvalidRequest\",\n retryable: false,\n actionOutcome: \"not-committed\",\n message: \"Invalid action parameters.\",\n cause: Redacted.make(cause),\n });\n }\n\n let result: ApplyActionResult;\n try {\n result = await Actions.applyWithOverrides(\n client,\n 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 throw foundryActionError(\"foundry.applyAction\", error, opts.ir, name, parameters);\n }\n try {\n Schema.decodeUnknownSync(ActionResponse)(result);\n } catch (cause) {\n throw new BackendError({\n operation: \"foundry.applyAction\",\n kind: \"InvalidResponse\",\n retryable: false,\n actionOutcome: \"unknown\",\n message: \"Foundry returned an invalid action response.\",\n cause: Redacted.make(cause),\n });\n }\n if (result.validation?.result === \"INVALID\") {\n throw new BackendError({\n operation: \"foundry.applyAction\",\n kind: \"ValidationFailed\",\n message: \"Submission failed validation.\",\n issues: getFoundryValidationIssues(result, parameters),\n retryable: false,\n actionOutcome: \"not-committed\",\n });\n }\n return { result, attachmentIdMappings };\n };\n\n const runQueryFunction = async (\n name: string,\n parameters: Record<string, unknown>,\n client = opts.client\n ) => {\n const queryFunctionType = opts.ir.queryFunctionTypes.find((candidate) => candidate.name === name);\n if (!queryFunctionType) {\n throw new BackendError({\n operation: \"foundry.queryFunction\",\n kind: \"InvalidRequest\",\n retryable: false,\n message: `Unknown Foundry query function type \"${name}\".`,\n });\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(client, client.ontologyRid, name, {\n parameters: requestParameters,\n });\n\n try {\n return codec.decodeValue(queryFunctionType.returnType, result.value);\n } catch (cause) {\n throw new BackendError({\n operation: \"foundry.queryFunction\",\n kind: \"InvalidResponse\",\n retryable: false,\n message: \"Foundry returned an invalid query result.\",\n cause: Redacted.make(cause),\n });\n }\n };\n const attempt = <A>(operation: string, run: (signal: AbortSignal) => Promise<A>) =>\n Effect.tryPromise({\n try: run,\n catch: (cause) => classifyBackendFailure(operation, cause),\n });\n const validateAction = Effect.fn(\"Foundry.validateAction\")(function* (\n name: string,\n parameters: Record<string, unknown>\n ): Effect.fn.Return<ValidationReport, BackendError> {\n const invocation = yield* Effect.try({\n try: () => prepareFoundryActionInvocation({ ir: opts.ir, name, parameters, codec }),\n catch: (cause) => foundryActionError(\"foundry.validateAction\", cause, opts.ir, name, parameters),\n });\n const result = yield* Effect.tryPromise({\n try: (signal) =>\n Actions.applyWithOverrides(\n withRequestSignal(opts.client, signal),\n opts.client.ontologyRid,\n toFoundryActionTypeName(name),\n {\n request: {\n options: { mode: \"VALIDATE_ONLY\" },\n parameters: invocation.parameters,\n },\n overrides: invocation.overrides,\n },\n { preview: true }\n ),\n catch: (cause) => foundryActionError(\"foundry.validateAction\", cause, opts.ir, name, parameters),\n });\n const { validation } = yield* Schema.decodeUnknownEffect(ValidationResponse)(result).pipe(\n Effect.mapError(\n (cause) =>\n new BackendError({\n operation: \"foundry.validateAction\",\n kind: \"InvalidResponse\",\n retryable: false,\n actionOutcome: \"not-committed\",\n message: \"Foundry returned an invalid validation response.\",\n cause: Redacted.make(cause),\n })\n )\n );\n return certain(\n validation.result === \"VALID\"\n ? { kind: \"ok\" as const, value: undefined }\n : { kind: \"err\" as const, value: getFoundryValidationIssues(result, parameters) }\n );\n });\n const validateActionDraft = Effect.fn(\"Foundry.validateActionDraft\")(function* (\n name: string,\n parameters: Record<string, unknown>,\n live: { knownParameters: readonly string[]; context?: Record<string, unknown> }\n ): Effect.fn.Return<ValidationReport, BackendError> {\n const action = opts.ir.actionTypes.find((candidate) => candidate.name === name);\n if (!action)\n return yield* new BackendError({\n operation: \"foundry.validateActionDraft\",\n kind: \"InvalidRequest\",\n message: \"Unknown action type.\",\n retryable: false,\n });\n const knownParameters = new Set([\n ...Object.entries(parameters).flatMap(([key, value]) => (value === undefined ? [] : [key])),\n ...live.knownParameters,\n ]);\n const missing = action.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 (missing.length)\n return certain({\n kind: \"err\" as const,\n value: missing.map((parameter) => ({\n message: \"A value is required.\",\n path: [parameter.name],\n code: \"required\",\n category: \"input\" as const,\n source: \"parameter\" as const,\n messageSource: \"standard\" as const,\n })),\n });\n if (\n !action.parameters.some(\n (parameter) =>\n parameters[parameter.name] === undefined && !knownParameters.has(parameter.name)\n )\n )\n return yield* validateAction(name, parameters);\n const value = live.context?.[FOUNDRY_CURRENT_USER_CONTEXT_FIELD];\n const userId = typeof value === \"string\" ? value : undefined;\n if (!userId) return uncertain();\n return yield* Effect.tryPromise({\n try: async (signal) =>\n validateFoundryActionDraftCriteria({\n client: withRequestSignal(opts.client, signal),\n criteria: await loadFoundrySubmissionCriteria({\n client: withRequestSignal(opts.client, signal),\n actionTypeName: name,\n userId,\n }),\n userId,\n parameters,\n knownParameters,\n }),\n catch: (cause) =>\n foundryActionError(\"foundry.validateActionDraft\", cause, opts.ir, name, parameters),\n });\n });\n return yield* makeFoundryBackend({\n client: opts.client,\n ir: opts.ir,\n context,\n watch: opts.watch,\n encrypted: makeFoundryEncryptedValues(opts.client, opts.ir),\n users: opts.users && {\n objectType: opts.users.objectType,\n loadSubset: (query, signal) => opts.users!.loadSubset(opts.client, query, signal),\n },\n submitAction: (invocation, signal) =>\n submitAction(\n invocation.name,\n invocation.parameters,\n {\n signal,\n attachmentUploads: invocation.attachmentUploads\n ? [...invocation.attachmentUploads]\n : undefined,\n },\n withRequestSignal(opts.client, signal)\n ),\n decodeObject: (objectType, value) => codec.decodeObject(objectType, value),\n queryFunction: (name, parameters, signal) =>\n runQueryFunction(name, parameters, withRequestSignal(opts.client, signal)),\n attachments: {\n stage: (value, blob, settings) =>\n attempt(\"attachment.stage\", async (signal) => {\n const target = settings?.target;\n if (!target || getAttachmentProviderType(target) === \"media\")\n throw new BackendError({\n operation: \"attachment.stage\",\n kind: \"NotImplemented\",\n retryable: false,\n message: \"This attachment target must be uploaded during action execution.\",\n });\n return (\n (await attachments.materializeAttachment(\n value,\n blob,\n { target, signal },\n withRequestSignal(opts.client, signal)\n )) ?? value\n );\n }),\n read: (value, range) =>\n scopedByteSource(\n Effect.gen(function* () {\n if (\n range &&\n (!Number.isSafeInteger(range.offset ?? 0) ||\n (range.offset ?? 0) < 0 ||\n (range.length !== undefined &&\n (!Number.isSafeInteger(range.length) || range.length < 0)))\n )\n return yield* new BackendError({\n operation: \"attachment.read\",\n kind: \"InvalidRequest\",\n message: \"Invalid byte range.\",\n retryable: false,\n });\n // Fetch resolves at headers; retain cancellation through body consumption.\n const download = yield* Effect.acquireRelease(\n Effect.sync(() => new AbortController()),\n (controller) => Effect.sync(() => controller.abort())\n );\n const blob = yield* attempt(\"attachment.read\", (signal) =>\n attachments.getAttachmentContent(value, {\n signal: AbortSignal.any([signal, download.signal]),\n })\n );\n return range\n ? sliceByteSource(blob, range.offset ?? 0, range.length)\n : byteSource(blob);\n })\n ),\n metadata: (value, settings) =>\n Effect.gen(function* () {\n const meta = yield* attempt(\n \"attachment.metadata\",\n async (signal) =>\n (await attachments.getAttachmentMetadata?.(\n value,\n settings?.select ?? [\"size\", \"type\", \"name\"],\n { signal }\n )) ?? {}\n );\n if (settings?.select || (meta.size !== undefined && meta.type !== undefined))\n return {\n size: meta.size,\n type: meta.type,\n name: meta.name,\n dimensions: meta.dimensions ?? undefined,\n };\n // Fetch resolves at headers; retain cancellation through body consumption.\n const download = yield* Effect.acquireRelease(\n Effect.sync(() => new AbortController()),\n (controller) => Effect.sync(() => controller.abort())\n );\n const blob = yield* attempt(\"attachment.read\", (signal) =>\n attachments.getAttachmentContent(value, {\n signal: AbortSignal.any([signal, download.signal]),\n })\n );\n const source = byteSource(blob);\n const size =\n source.size ??\n (yield* byteChunks(source).pipe(\n Stream.runFold(\n () => 0,\n (total, chunk) => total + chunk.length\n ),\n Effect.mapError(\n (cause) =>\n new BackendError({\n operation: \"attachment.metadata\",\n kind: \"Unavailable\",\n message: \"Attachment metadata is unavailable.\",\n retryable: true,\n cause,\n })\n )\n ));\n return {\n size,\n type: source.type,\n name: meta.name,\n dimensions: meta.dimensions ?? undefined,\n };\n }).pipe(Effect.scoped),\n },\n }).pipe(\n Effect.map((native) => ({\n ...native,\n validateAction: (\n name: string,\n parameters: Record<string, unknown>,\n settings?: { readonly knownParameters?: readonly string[] }\n ) =>\n settings?.knownParameters\n ? validateActionDraft(name, parameters, {\n context,\n knownParameters: settings.knownParameters,\n })\n : validateAction(name, parameters),\n }))\n );\n});\n"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { SearchJsonQueryV2 } from "@osdk/foundry.ontologies";
2
+ import { Predicate } from "@party-stack/ontology-storage";
3
+ //#region src/adapter/subsetFilter.d.ts
4
+ export declare const subsetFilter: (predicate: Predicate | undefined) => SearchJsonQueryV2 | undefined;
5
+ /** Report effective placement, including supported OR branches that could not safely be sent. */
6
+ export declare function analyzeSubsetFilter(predicate: Predicate | undefined): {
7
+ query: SearchJsonQueryV2 | undefined;
8
+ predicates: {
9
+ readonly path: readonly number[];
10
+ readonly execution: "adapter" | "candidate" | "engine" | "source";
11
+ }[];
12
+ };
13
+ //#endregion
14
+ //# sourceMappingURL=subsetFilter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subsetFilter.d.ts","names":[],"sources":["../../src/adapter/subsetFilter.ts"],"mappings":";;;qBAkFa,eAAY,WAAe,0BAAwB;;wBAIhD,oBAAoB,WAAW;SAAA"}