@fabriktor/fx 0.0.32 → 0.0.33

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 (35) hide show
  1. package/dist/src/billable/billable.d.ts +12 -10
  2. package/dist/src/billable/billable.js +1 -2
  3. package/dist/src/calls/calls.d.ts +5 -5
  4. package/dist/src/chat/chat.d.ts +3 -2
  5. package/dist/src/core/pull.d.ts +39 -0
  6. package/dist/src/core/pull.js +101 -0
  7. package/dist/src/feed/feed.d.ts +167 -0
  8. package/dist/src/feed/feed.js +642 -0
  9. package/dist/src/fx.d.ts +42 -1
  10. package/dist/src/fx.js +94 -2
  11. package/dist/src/index.d.ts +10 -0
  12. package/dist/src/index.js +10 -0
  13. package/dist/src/jobs/jobs.d.ts +74 -0
  14. package/dist/src/jobs/jobs.js +375 -0
  15. package/dist/src/marketplace/marketplace.d.ts +35 -0
  16. package/dist/src/marketplace/marketplace.js +159 -0
  17. package/dist/src/notifications/notifications.d.ts +20 -0
  18. package/dist/src/notifications/notifications.js +45 -0
  19. package/dist/src/payments/payments.d.ts +59 -0
  20. package/dist/src/payments/payments.js +266 -0
  21. package/dist/src/payrolls/payrolls.d.ts +52 -0
  22. package/dist/src/payrolls/payrolls.js +54 -0
  23. package/dist/src/privacy/privacy.d.ts +21 -0
  24. package/dist/src/privacy/privacy.js +78 -0
  25. package/dist/src/routes/routes.d.ts +22 -0
  26. package/dist/src/routes/routes.js +134 -0
  27. package/dist/src/session/session.d.ts +17 -11
  28. package/dist/src/session/session.js +6 -12
  29. package/dist/src/storage/storage.d.ts +22 -13
  30. package/dist/src/storage/storage.js +56 -41
  31. package/dist/src/timesheets/timesheets.d.ts +91 -0
  32. package/dist/src/timesheets/timesheets.js +407 -0
  33. package/dist/src/users/users.d.ts +15 -11
  34. package/dist/src/users/users.js +2 -2
  35. package/package.json +3 -3
@@ -0,0 +1,642 @@
1
+ // Copyright (C) Fabriktor, Inc. 2025-present.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License"); you may
4
+ // not use this file except in compliance with the License. You may obtain
5
+ // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ import { All, ColStorageFeed, PullTypeKeepAlive, ZeroID, } from "@fabriktor/schema";
7
+ import { errResolveFailed, errValidation } from "../core/err.js";
8
+ import { newPullSession, } from "../core/pull.js";
9
+ import { StorageUploadModeration, } from "../storage/storage.js";
10
+ const newFeedSessionToken = "";
11
+ const resourceFeedSessionToken = "feed_session_token";
12
+ const resourceFeedPostID = "feed_post_id";
13
+ const resourceFeedObject = "feed_object";
14
+ const msgKeepAliveIntervalInvalid = "Keep-alive interval must be a finite number greater than zero.";
15
+ const msgFeedSessionClosed = "Feed session is closed.";
16
+ const msgFeedPullInProgress = "A feed pull is already in progress.";
17
+ const msgFeedSessionTokenMissing = "Feed pull response did not contain a session token.";
18
+ const msgFeedPostIDMissing = "Feed post does not contain an ID.";
19
+ const msgFeedCreatedPostIDMissing = "Created feed post response did not contain an ID.";
20
+ const msgFeedActionInProgress = "This feed action is already in progress for the post.";
21
+ const msgFeedReactionAlreadyExists = "A reaction already exists for this post.";
22
+ const msgFeedReactionMissing = "No reaction exists for this post.";
23
+ const msgFeedFavoriteAlreadyExists = "A favorite already exists for this post.";
24
+ const msgFeedFavoriteMissing = "No favorite exists for this post.";
25
+ const msgFeedReplyAlreadyExists = "A reply already exists for this post.";
26
+ const msgFeedReplyMissing = "No reply exists for this post.";
27
+ const msgFeedReferenceAlreadyExists = "A reference already exists for this post.";
28
+ const msgFeedReferenceMissing = "No reference exists for this post.";
29
+ const msgFeedObjectsMissing = "Storage download did not return any feed objects.";
30
+ const msgFeedObjectURLMissing = "Storage object does not contain a permanent signed URL.";
31
+ const msgFeedObjectMIMEMissing = "Storage object does not contain a MIME prefix.";
32
+ const msgFeedObjectCaptionMissing = "Storage object does not contain a caption embedding.";
33
+ export const FeedAction = {
34
+ Reaction: "reaction",
35
+ Favorite: "favorite",
36
+ Reply: "reply",
37
+ Reference: "reference",
38
+ };
39
+ export const FeedMediaPostStatus = {
40
+ Complete: "complete",
41
+ CreateUnresolved: "create_unresolved",
42
+ UploadFailed: "upload_failed",
43
+ AllForbidden: "all_forbidden",
44
+ DownloadFailed: "download_failed",
45
+ ResolveFailed: "resolve_failed",
46
+ PatchFailed: "patch_failed",
47
+ };
48
+ export class FeedFX {
49
+ feed;
50
+ storage_fx;
51
+ keep_alive_interval_ms;
52
+ running_actions;
53
+ completed_actions;
54
+ removed_actions;
55
+ action_ids;
56
+ constructor(opts) {
57
+ validateFeedFXOptions(opts);
58
+ this.feed = opts.feed;
59
+ this.storage_fx = opts.storage_fx;
60
+ this.keep_alive_interval_ms = opts.keep_alive_interval_ms;
61
+ this.running_actions = new Map();
62
+ this.completed_actions = new Map();
63
+ this.removed_actions = new Map();
64
+ this.action_ids = new Map();
65
+ }
66
+ async startSession(opts) {
67
+ const { on_error, ...context } = opts;
68
+ const initial = await this.feed.pull({
69
+ ...context,
70
+ session_token: newFeedSessionToken,
71
+ is_new_session: true,
72
+ });
73
+ const session_token = feedSessionToken(initial);
74
+ return newPullSession({
75
+ initial,
76
+ session_token,
77
+ keep_alive_interval_ms: this.keep_alive_interval_ms,
78
+ pull_next: async (token) => {
79
+ return await this.feed.pull({
80
+ ...context,
81
+ session_token: token,
82
+ is_new_session: false,
83
+ });
84
+ },
85
+ keep_alive: async (token) => {
86
+ return await this.feed.pull({
87
+ contact_ids: [],
88
+ session_token: token,
89
+ is_new_session: false,
90
+ pull_type: PullTypeKeepAlive,
91
+ entity_id: "",
92
+ research: "",
93
+ });
94
+ },
95
+ resolve_session_token: feedSessionToken,
96
+ closed_error: () => errValidation({
97
+ msg: msgFeedSessionClosed,
98
+ }),
99
+ pull_in_progress_error: () => errValidation({
100
+ msg: msgFeedPullInProgress,
101
+ }),
102
+ on_error,
103
+ });
104
+ }
105
+ async addReaction(opts) {
106
+ const post_id = feedPostID(opts.post);
107
+ if (this.hasAction(opts.post, FeedAction.Reaction)) {
108
+ throw errValidation({
109
+ field: "post",
110
+ msg: msgFeedReactionAlreadyExists,
111
+ });
112
+ }
113
+ return await this.runAction(post_id, FeedAction.Reaction, async () => {
114
+ const out = await this.feed.insertOneFeedReaction({
115
+ in: {
116
+ post_id,
117
+ reaction_type: opts.reaction_type,
118
+ },
119
+ });
120
+ this.markAction(post_id, FeedAction.Reaction, operationID(out));
121
+ return out;
122
+ });
123
+ }
124
+ async removeReaction(opts) {
125
+ const post_id = feedPostID(opts.post);
126
+ const id = this.actionID(opts.post, FeedAction.Reaction);
127
+ if (id === undefined) {
128
+ throw errValidation({
129
+ field: "post",
130
+ msg: msgFeedReactionMissing,
131
+ });
132
+ }
133
+ return await this.runAction(post_id, FeedAction.Reaction, async () => {
134
+ const out = await this.feed.deleteOneFeedReaction({
135
+ id,
136
+ });
137
+ this.markActionRemoved(post_id, FeedAction.Reaction);
138
+ return out;
139
+ });
140
+ }
141
+ async addFavorite(opts) {
142
+ const post_id = feedPostID(opts.post);
143
+ if (this.hasAction(opts.post, FeedAction.Favorite)) {
144
+ throw errValidation({
145
+ field: "post",
146
+ msg: msgFeedFavoriteAlreadyExists,
147
+ });
148
+ }
149
+ return await this.runAction(post_id, FeedAction.Favorite, async () => {
150
+ const out = await this.feed.insertOneFeedFavorite({
151
+ in: {
152
+ post_id,
153
+ },
154
+ });
155
+ this.markAction(post_id, FeedAction.Favorite, operationID(out));
156
+ return out;
157
+ });
158
+ }
159
+ async removeFavorite(opts) {
160
+ const post_id = feedPostID(opts.post);
161
+ const id = this.actionID(opts.post, FeedAction.Favorite);
162
+ if (id === undefined) {
163
+ throw errValidation({
164
+ field: "post",
165
+ msg: msgFeedFavoriteMissing,
166
+ });
167
+ }
168
+ return await this.runAction(post_id, FeedAction.Favorite, async () => {
169
+ const out = await this.feed.deleteOneFeedFavorite({
170
+ id,
171
+ });
172
+ this.markActionRemoved(post_id, FeedAction.Favorite);
173
+ return out;
174
+ });
175
+ }
176
+ async createReply(opts) {
177
+ const post_id = feedPostID(opts.post);
178
+ if (this.hasAction(opts.post, FeedAction.Reply)) {
179
+ throw errValidation({
180
+ field: "post",
181
+ msg: msgFeedReplyAlreadyExists,
182
+ });
183
+ }
184
+ return await this.runAction(post_id, FeedAction.Reply, async () => {
185
+ const out = await this.feed.insertOneFeedPost({
186
+ in: {
187
+ objects: [],
188
+ text: opts.in.text,
189
+ is_uploading: false,
190
+ has_media: false,
191
+ visibility: All,
192
+ referenced_post_id: ZeroID,
193
+ reply_to_post_id: post_id,
194
+ },
195
+ });
196
+ this.markAction(post_id, FeedAction.Reply, operationID(out));
197
+ return out;
198
+ });
199
+ }
200
+ async removeReply(opts) {
201
+ const post_id = feedPostID(opts.post);
202
+ const id = this.actionID(opts.post, FeedAction.Reply);
203
+ if (id === undefined) {
204
+ throw errValidation({
205
+ field: "post",
206
+ msg: msgFeedReplyMissing,
207
+ });
208
+ }
209
+ return await this.runAction(post_id, FeedAction.Reply, async () => {
210
+ const out = await this.feed.deleteOneFeedPost({
211
+ id,
212
+ });
213
+ this.markActionRemoved(post_id, FeedAction.Reply);
214
+ return out;
215
+ });
216
+ }
217
+ async createReference(opts) {
218
+ const post_id = feedPostID(opts.post);
219
+ if (this.hasAction(opts.post, FeedAction.Reference)) {
220
+ throw errValidation({
221
+ field: "post",
222
+ msg: msgFeedReferenceAlreadyExists,
223
+ });
224
+ }
225
+ return await this.runAction(post_id, FeedAction.Reference, async () => {
226
+ const out = await this.feed.insertOneFeedPost({
227
+ in: {
228
+ objects: [],
229
+ text: opts.in.text,
230
+ is_uploading: false,
231
+ has_media: false,
232
+ visibility: All,
233
+ referenced_post_id: post_id,
234
+ reply_to_post_id: ZeroID,
235
+ },
236
+ });
237
+ this.markAction(post_id, FeedAction.Reference, operationID(out));
238
+ return out;
239
+ });
240
+ }
241
+ async removeReference(opts) {
242
+ const post_id = feedPostID(opts.post);
243
+ const id = this.actionID(opts.post, FeedAction.Reference);
244
+ if (id === undefined) {
245
+ throw errValidation({
246
+ field: "post",
247
+ msg: msgFeedReferenceMissing,
248
+ });
249
+ }
250
+ return await this.runAction(post_id, FeedAction.Reference, async () => {
251
+ const out = await this.feed.deleteOneFeedPost({
252
+ id,
253
+ });
254
+ this.markActionRemoved(post_id, FeedAction.Reference);
255
+ return out;
256
+ });
257
+ }
258
+ async createPostWithMedia(opts) {
259
+ return await this.createMediaPost({
260
+ in: {
261
+ objects: [],
262
+ text: opts.in.text,
263
+ is_uploading: true,
264
+ has_media: true,
265
+ visibility: opts.in.visibility,
266
+ referenced_post_id: ZeroID,
267
+ reply_to_post_id: ZeroID,
268
+ },
269
+ user_id: opts.user_id,
270
+ uploader_id: opts.uploader_id,
271
+ full_quality: opts.full_quality,
272
+ files: opts.files,
273
+ save_to_personal_box: opts.save_to_personal_box,
274
+ });
275
+ }
276
+ async createReplyWithMedia(opts) {
277
+ const post_id = feedPostID(opts.post);
278
+ if (this.hasAction(opts.post, FeedAction.Reply)) {
279
+ throw errValidation({
280
+ field: "post",
281
+ msg: msgFeedReplyAlreadyExists,
282
+ });
283
+ }
284
+ return await this.runAction(post_id, FeedAction.Reply, async () => {
285
+ const out = await this.createMediaPost({
286
+ in: {
287
+ objects: [],
288
+ text: opts.in.text,
289
+ is_uploading: true,
290
+ has_media: true,
291
+ visibility: All,
292
+ referenced_post_id: ZeroID,
293
+ reply_to_post_id: post_id,
294
+ },
295
+ user_id: opts.user_id,
296
+ uploader_id: opts.uploader_id,
297
+ full_quality: opts.full_quality,
298
+ files: opts.files,
299
+ save_to_personal_box: opts.save_to_personal_box,
300
+ });
301
+ const id = completedMediaPostID(out);
302
+ if (id !== undefined) {
303
+ this.markAction(post_id, FeedAction.Reply, id);
304
+ }
305
+ return out;
306
+ });
307
+ }
308
+ async createReferenceWithMedia(opts) {
309
+ const post_id = feedPostID(opts.post);
310
+ if (this.hasAction(opts.post, FeedAction.Reference)) {
311
+ throw errValidation({
312
+ field: "post",
313
+ msg: msgFeedReferenceAlreadyExists,
314
+ });
315
+ }
316
+ return await this.runAction(post_id, FeedAction.Reference, async () => {
317
+ const out = await this.createMediaPost({
318
+ in: {
319
+ objects: [],
320
+ text: opts.in.text,
321
+ is_uploading: true,
322
+ has_media: true,
323
+ visibility: All,
324
+ referenced_post_id: post_id,
325
+ reply_to_post_id: ZeroID,
326
+ },
327
+ user_id: opts.user_id,
328
+ uploader_id: opts.uploader_id,
329
+ full_quality: opts.full_quality,
330
+ files: opts.files,
331
+ save_to_personal_box: opts.save_to_personal_box,
332
+ });
333
+ const id = completedMediaPostID(out);
334
+ if (id !== undefined) {
335
+ this.markAction(post_id, FeedAction.Reference, id);
336
+ }
337
+ return out;
338
+ });
339
+ }
340
+ async createMediaPost(opts) {
341
+ const create = await this.feed.insertOneFeedPost({
342
+ in: opts.in,
343
+ });
344
+ const post_id = operationID(create);
345
+ if (post_id === undefined) {
346
+ return {
347
+ status: FeedMediaPostStatus.CreateUnresolved,
348
+ create,
349
+ error: errResolveFailed({
350
+ resource: resourceFeedPostID,
351
+ msg: msgFeedCreatedPostIDMissing,
352
+ }),
353
+ };
354
+ }
355
+ let upload;
356
+ try {
357
+ upload = await this.storage_fx.uploadObjectsWithPersonalBox({
358
+ col: ColStorageFeed,
359
+ owner_id: post_id,
360
+ user_id: opts.user_id,
361
+ uploader_id: opts.uploader_id,
362
+ full_quality: opts.full_quality,
363
+ files: opts.files,
364
+ save_to_personal_box: opts.save_to_personal_box,
365
+ });
366
+ }
367
+ catch (err) {
368
+ return {
369
+ status: FeedMediaPostStatus.UploadFailed,
370
+ post_id,
371
+ error: err,
372
+ };
373
+ }
374
+ if (upload.primary.moderation === StorageUploadModeration.AllForbidden) {
375
+ return {
376
+ status: FeedMediaPostStatus.AllForbidden,
377
+ post_id,
378
+ upload,
379
+ };
380
+ }
381
+ let stored;
382
+ try {
383
+ stored = await this.storage_fx.downloadObjects({
384
+ col: ColStorageFeed,
385
+ owner_id: post_id,
386
+ expire: false,
387
+ });
388
+ }
389
+ catch (err) {
390
+ return {
391
+ status: FeedMediaPostStatus.DownloadFailed,
392
+ post_id,
393
+ upload,
394
+ error: err,
395
+ };
396
+ }
397
+ let objects;
398
+ try {
399
+ objects = feedObjects(stored.value ?? []);
400
+ }
401
+ catch (err) {
402
+ return {
403
+ status: FeedMediaPostStatus.ResolveFailed,
404
+ post_id,
405
+ upload,
406
+ error: err,
407
+ };
408
+ }
409
+ try {
410
+ await this.feed.replaceOneFeedPost({
411
+ id: post_id,
412
+ in: {
413
+ ...opts.in,
414
+ objects,
415
+ is_uploading: false,
416
+ },
417
+ });
418
+ }
419
+ catch (err) {
420
+ return {
421
+ status: FeedMediaPostStatus.PatchFailed,
422
+ post_id,
423
+ upload,
424
+ objects,
425
+ error: err,
426
+ };
427
+ }
428
+ return {
429
+ status: FeedMediaPostStatus.Complete,
430
+ post_id,
431
+ upload,
432
+ objects,
433
+ };
434
+ }
435
+ async runAction(post_id, action, fn) {
436
+ if (this.isActionRunning(post_id, action)) {
437
+ throw errValidation({
438
+ msg: msgFeedActionInProgress,
439
+ });
440
+ }
441
+ this.setActionRunning(post_id, action, true);
442
+ try {
443
+ return await fn();
444
+ }
445
+ finally {
446
+ this.setActionRunning(post_id, action, false);
447
+ }
448
+ }
449
+ hasAction(post, action) {
450
+ const post_id = feedPostID(post);
451
+ if (this.isActionCompleted(post_id, action)) {
452
+ return true;
453
+ }
454
+ if (this.isActionRemoved(post_id, action)) {
455
+ return false;
456
+ }
457
+ return selfActionID(post, action) !== undefined;
458
+ }
459
+ actionID(post, action) {
460
+ const post_id = feedPostID(post);
461
+ if (this.isActionCompleted(post_id, action)) {
462
+ return this.action_ids.get(post_id)?.get(action);
463
+ }
464
+ if (this.isActionRemoved(post_id, action)) {
465
+ return undefined;
466
+ }
467
+ return selfActionID(post, action);
468
+ }
469
+ markAction(post_id, action, id) {
470
+ this.clearActionRemoved(post_id, action);
471
+ let completed = this.completed_actions.get(post_id);
472
+ if (completed === undefined) {
473
+ completed = new Set();
474
+ this.completed_actions.set(post_id, completed);
475
+ }
476
+ completed.add(action);
477
+ if (id === undefined) {
478
+ return;
479
+ }
480
+ let ids = this.action_ids.get(post_id);
481
+ if (ids === undefined) {
482
+ ids = new Map();
483
+ this.action_ids.set(post_id, ids);
484
+ }
485
+ ids.set(action, id);
486
+ }
487
+ markActionRemoved(post_id, action) {
488
+ const completed = this.completed_actions.get(post_id);
489
+ completed?.delete(action);
490
+ if (completed?.size === 0) {
491
+ this.completed_actions.delete(post_id);
492
+ }
493
+ const ids = this.action_ids.get(post_id);
494
+ ids?.delete(action);
495
+ if (ids?.size === 0) {
496
+ this.action_ids.delete(post_id);
497
+ }
498
+ let removed = this.removed_actions.get(post_id);
499
+ if (removed === undefined) {
500
+ removed = new Set();
501
+ this.removed_actions.set(post_id, removed);
502
+ }
503
+ removed.add(action);
504
+ }
505
+ clearActionRemoved(post_id, action) {
506
+ const removed = this.removed_actions.get(post_id);
507
+ removed?.delete(action);
508
+ if (removed?.size === 0) {
509
+ this.removed_actions.delete(post_id);
510
+ }
511
+ }
512
+ isActionCompleted(post_id, action) {
513
+ return this.completed_actions.get(post_id)?.has(action) ?? false;
514
+ }
515
+ isActionRemoved(post_id, action) {
516
+ return this.removed_actions.get(post_id)?.has(action) ?? false;
517
+ }
518
+ isActionRunning(post_id, action) {
519
+ return this.running_actions.get(post_id)?.has(action) ?? false;
520
+ }
521
+ setActionRunning(post_id, action, running) {
522
+ if (running) {
523
+ let actions = this.running_actions.get(post_id);
524
+ if (actions === undefined) {
525
+ actions = new Set();
526
+ this.running_actions.set(post_id, actions);
527
+ }
528
+ actions.add(action);
529
+ return;
530
+ }
531
+ const actions = this.running_actions.get(post_id);
532
+ actions?.delete(action);
533
+ if (actions?.size === 0) {
534
+ this.running_actions.delete(post_id);
535
+ }
536
+ }
537
+ }
538
+ export function newFeedFX(opts) {
539
+ return new FeedFX(opts);
540
+ }
541
+ function validateFeedFXOptions(opts) {
542
+ if (!Number.isFinite(opts.keep_alive_interval_ms) ||
543
+ opts.keep_alive_interval_ms <= 0) {
544
+ throw errValidation({
545
+ field: "keep_alive_interval_ms",
546
+ msg: msgKeepAliveIntervalInvalid,
547
+ });
548
+ }
549
+ }
550
+ function feedSessionToken(out) {
551
+ const token = resolvedValue(out.value?.session_token);
552
+ if (token === undefined) {
553
+ throw errResolveFailed({
554
+ resource: resourceFeedSessionToken,
555
+ msg: msgFeedSessionTokenMissing,
556
+ });
557
+ }
558
+ return token;
559
+ }
560
+ function feedPostID(post) {
561
+ const id = resolvedID(post.id);
562
+ if (id === undefined) {
563
+ throw errValidation({
564
+ field: "id",
565
+ msg: msgFeedPostIDMissing,
566
+ });
567
+ }
568
+ return id;
569
+ }
570
+ function operationID(out) {
571
+ return resolvedID(out.id);
572
+ }
573
+ function selfActionID(post, action) {
574
+ switch (action) {
575
+ case FeedAction.Reaction:
576
+ return resolvedID(post.self?.reaction_id);
577
+ case FeedAction.Favorite:
578
+ return resolvedID(post.self?.favorite_id);
579
+ case FeedAction.Reply:
580
+ return resolvedID(post.self?.reply_id);
581
+ case FeedAction.Reference:
582
+ return resolvedID(post.self?.reference_id);
583
+ }
584
+ }
585
+ function resolvedID(v) {
586
+ const out = resolvedValue(v);
587
+ if (out === undefined || out === ZeroID) {
588
+ return undefined;
589
+ }
590
+ return out;
591
+ }
592
+ function resolvedValue(v) {
593
+ const out = v?.trim();
594
+ if (out === undefined || out.length === 0) {
595
+ return undefined;
596
+ }
597
+ return out;
598
+ }
599
+ function completedMediaPostID(out) {
600
+ if (out.status !== FeedMediaPostStatus.Complete) {
601
+ return undefined;
602
+ }
603
+ return out.post_id;
604
+ }
605
+ function feedObjects(objects) {
606
+ if (objects.length === 0) {
607
+ throw errResolveFailed({
608
+ resource: resourceFeedObject,
609
+ msg: msgFeedObjectsMissing,
610
+ });
611
+ }
612
+ const out = [];
613
+ for (const object of objects) {
614
+ const signed_url = resolvedValue(object.signed_url);
615
+ if (signed_url === undefined) {
616
+ throw errResolveFailed({
617
+ resource: resourceFeedObject,
618
+ msg: msgFeedObjectURLMissing,
619
+ });
620
+ }
621
+ const mime_prefix = resolvedValue(object.mime_prefix);
622
+ if (mime_prefix === undefined) {
623
+ throw errResolveFailed({
624
+ resource: resourceFeedObject,
625
+ msg: msgFeedObjectMIMEMissing,
626
+ });
627
+ }
628
+ const embedding = object.caption;
629
+ if (embedding === undefined) {
630
+ throw errResolveFailed({
631
+ resource: resourceFeedObject,
632
+ msg: msgFeedObjectCaptionMissing,
633
+ });
634
+ }
635
+ out.push({
636
+ signed_url,
637
+ mime_prefix,
638
+ embedding,
639
+ });
640
+ }
641
+ return out;
642
+ }