@fabriktor/fx 0.0.39 → 0.0.40

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 (36) hide show
  1. package/dist/src/billable/billable.d.ts +164 -1
  2. package/dist/src/billable/billable.js +436 -0
  3. package/dist/src/calls/calls.d.ts +11 -0
  4. package/dist/src/calls/calls.js +26 -0
  5. package/dist/src/chat/chat.d.ts +22 -1
  6. package/dist/src/chat/chat.js +33 -25
  7. package/dist/src/contacts/contacts.d.ts +12 -2
  8. package/dist/src/contacts/contacts.js +33 -7
  9. package/dist/src/core/id.d.ts +3 -0
  10. package/dist/src/core/id.js +24 -0
  11. package/dist/src/feed/feed.d.ts +39 -3
  12. package/dist/src/feed/feed.js +85 -7
  13. package/dist/src/fulfillments/fulfillments.d.ts +32 -0
  14. package/dist/src/fulfillments/fulfillments.js +54 -0
  15. package/dist/src/fx.d.ts +5 -1
  16. package/dist/src/fx.js +11 -1
  17. package/dist/src/index.d.ts +2 -0
  18. package/dist/src/index.js +2 -0
  19. package/dist/src/jobs/jobs.d.ts +52 -4
  20. package/dist/src/jobs/jobs.js +120 -9
  21. package/dist/src/marketplace/marketplace.d.ts +29 -1
  22. package/dist/src/marketplace/marketplace.js +64 -1
  23. package/dist/src/memos/memos.js +4 -28
  24. package/dist/src/payments/payments.d.ts +112 -1
  25. package/dist/src/payments/payments.js +291 -15
  26. package/dist/src/payrolls/payrolls.d.ts +134 -1
  27. package/dist/src/payrolls/payrolls.js +364 -0
  28. package/dist/src/preferences/preferences.d.ts +83 -1
  29. package/dist/src/preferences/preferences.js +227 -0
  30. package/dist/src/privacy/privacy.d.ts +21 -2
  31. package/dist/src/privacy/privacy.js +56 -5
  32. package/dist/src/routes/routes.d.ts +63 -3
  33. package/dist/src/routes/routes.js +151 -1
  34. package/dist/src/timesheets/timesheets.d.ts +11 -1
  35. package/dist/src/timesheets/timesheets.js +39 -1
  36. package/package.json +2 -2
@@ -4,7 +4,11 @@
4
4
  // not use this file except in compliance with the License. You may obtain
5
5
  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
6
  import { errResolveFailed } from "../core/err.js";
7
+ import { requiredOperationID } from "../core/id.js";
8
+ const resourceEvent = "event";
7
9
  const resourceVideoToken = "video_token";
10
+ const msgCreatedEventIDMissing = "Created event response did not contain an ID.";
11
+ const msgEventMissing = "Event could not be resolved after the mutation.";
8
12
  const msgUnableToMintVideoToken = "Unable to mint video token.";
9
13
  export class CallsFX {
10
14
  calls;
@@ -13,6 +17,15 @@ export class CallsFX {
13
17
  this.calls = opts.calls;
14
18
  this.notifications = opts.notifications;
15
19
  }
20
+ async createEvent(opts) {
21
+ const out = await this.calls.insertOneEvent(opts);
22
+ const id = requiredOperationID(out, msgCreatedEventIDMissing);
23
+ return await this.findEvent(id);
24
+ }
25
+ async replaceEvent(opts) {
26
+ await this.calls.replaceOneEvent(opts);
27
+ return await this.findEvent(opts.id);
28
+ }
16
29
  async startCall(opts) {
17
30
  const token = await this.requireVideoToken(opts.mint);
18
31
  await this.notifications.relayNotification(opts.notification);
@@ -26,6 +39,19 @@ export class CallsFX {
26
39
  async cancelCall(opts) {
27
40
  await this.notifications.relayNotification(opts.notification);
28
41
  }
42
+ async findEvent(id) {
43
+ const out = await this.calls.findOneEvent({
44
+ id,
45
+ });
46
+ const event = out.value;
47
+ if (event === undefined) {
48
+ throw errResolveFailed({
49
+ resource: resourceEvent,
50
+ msg: msgEventMissing,
51
+ });
52
+ }
53
+ return event;
54
+ }
29
55
  async requireVideoToken(opts) {
30
56
  const out = await this.calls.mintVideoToken(opts);
31
57
  const token = out.value?.trim();
@@ -1,12 +1,29 @@
1
1
  import type { ChatOperator, WSCloseHandler, WSConnection, WSErrorHandler, WSMessageHandler } from "@fabriktor/client";
2
- import { type Chat, type ChatRoom, type ChatRoomMember } from "@fabriktor/schema";
2
+ import type { Chat, ChatRoom, ChatRoomMember } from "@fabriktor/schema";
3
3
  import { type SearchPage } from "../core/search.js";
4
4
  type ChatInsertOptions = Parameters<ChatOperator["insertOneChat"]>[0];
5
+ type ChatReplaceOptions = Parameters<ChatOperator["replaceOneChat"]>[0];
5
6
  export type CreateChatOptions = ChatInsertOptions;
7
+ export type MarkChatObjectsUploadedOptions = {
8
+ id: ChatReplaceOptions["id"];
9
+ };
6
10
  export type ReactChatOptions = Parameters<ChatOperator["reactChat"]>[0];
7
11
  export type ChatFXOptions = {
8
12
  chat: ChatOperator;
9
13
  };
14
+ type SearchChatsScope = {
15
+ chat_room_id: string;
16
+ owner_id?: string;
17
+ } | {
18
+ chat_room_id?: string;
19
+ owner_id: string;
20
+ };
21
+ export type SearchChatsOptions = SearchChatsScope & {
22
+ q: string;
23
+ page?: number;
24
+ per_page?: number;
25
+ };
26
+ export type SearchChatsPage = SearchPage<Chat>;
10
27
  export type LatestChatsOptions = {
11
28
  chat_room_id: string;
12
29
  page?: number;
@@ -77,6 +94,8 @@ export type GlobalChatRoomsSession = {
77
94
  };
78
95
  export interface ChatFXOperator {
79
96
  createChat(opts: CreateChatOptions): Promise<Chat>;
97
+ markChatObjectsUploaded(opts: MarkChatObjectsUploadedOptions): Promise<Chat>;
98
+ searchChats(opts: SearchChatsOptions): Promise<SearchChatsPage>;
80
99
  newLatestChatsCursor(opts: LatestChatsOptions): LatestChatsCursor;
81
100
  latestChats(opts: LatestChatsOptions): Promise<LatestChatsPage>;
82
101
  nextLatestChats(opts: NextLatestChatsOptions): Promise<LatestChatsPage>;
@@ -91,6 +110,8 @@ export declare class ChatFX implements ChatFXOperator {
91
110
  private chat;
92
111
  constructor(opts: ChatFXOptions);
93
112
  createChat(opts: CreateChatOptions): Promise<Chat>;
113
+ markChatObjectsUploaded(opts: MarkChatObjectsUploadedOptions): Promise<Chat>;
114
+ searchChats(opts: SearchChatsOptions): Promise<SearchChatsPage>;
94
115
  newLatestChatsCursor(opts: LatestChatsOptions): LatestChatsCursor;
95
116
  latestChats(opts: LatestChatsOptions): Promise<LatestChatsPage>;
96
117
  nextLatestChats(opts: NextLatestChatsOptions): Promise<LatestChatsPage>;
@@ -3,17 +3,17 @@
3
3
  // Licensed under the Apache License, Version 2.0 (the "License"); you may
4
4
  // not use this file except in compliance with the License. You may obtain
5
5
  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
- import { ZeroID, } from "@fabriktor/schema";
7
- import { errResolveFailed, errValidation } from "../core/err.js";
8
- import { normalizeSearchPage, normalizeSearchPerPage, runSearch, } from "../core/search.js";
6
+ import { errRequired, errResolveFailed, errValidation } from "../core/err.js";
7
+ import { requiredOperationID } from "../core/id.js";
8
+ import { normalizeSearchPage, normalizeSearchPerPage, normalizeSearchQuery, runSearch, } from "../core/search.js";
9
9
  const closeCodeNormal = 1000;
10
10
  const closeCodeLeavingPage = 1001;
11
11
  const wsRefreshMilliseconds = 40 * 60 * 1000;
12
12
  const wsRefreshRetryMilliseconds = 30 * 1000;
13
- const resourceChatID = "chat_id";
14
13
  const resourceChat = "chat";
15
14
  const msgCreatedChatIDMissing = "Created chat response did not contain an ID.";
16
15
  const msgChatMissing = "Chat could not be resolved after the mutation.";
16
+ const msgSearchQueryRequired = "Search query is required.";
17
17
  const msgChatObjectsUploading = "Cannot react to a chat while objects are still uploading.";
18
18
  export class ChatFX {
19
19
  chat;
@@ -22,12 +22,37 @@ export class ChatFX {
22
22
  }
23
23
  async createChat(opts) {
24
24
  const out = await this.chat.insertOneChat(opts);
25
- const id = requiredOperationID(out, {
26
- resource: resourceChatID,
27
- msg: msgCreatedChatIDMissing,
28
- });
25
+ const id = requiredOperationID(out, msgCreatedChatIDMissing);
29
26
  return await this.findChat(id);
30
27
  }
28
+ async markChatObjectsUploaded(opts) {
29
+ await this.chat.replaceOneChat({
30
+ id: opts.id,
31
+ in: {
32
+ objects_uploaded: true,
33
+ },
34
+ });
35
+ return await this.findChat(opts.id);
36
+ }
37
+ async searchChats(opts) {
38
+ const q = normalizeSearchQuery(opts.q);
39
+ if (q === undefined) {
40
+ throw errRequired({
41
+ field: "q",
42
+ msg: msgSearchQueryRequired,
43
+ });
44
+ }
45
+ return await runSearch({
46
+ search: (searchOpts) => this.chat.searchManyChats(searchOpts),
47
+ query: {
48
+ chat_room_id: opts.chat_room_id,
49
+ owner_id: opts.owner_id,
50
+ },
51
+ q,
52
+ page: opts.page,
53
+ per_page: opts.per_page,
54
+ });
55
+ }
31
56
  newLatestChatsCursor(opts) {
32
57
  return {
33
58
  chat_room_id: opts.chat_room_id,
@@ -395,20 +420,3 @@ function closeWS(conns, code, reason) {
395
420
  conn.close(code, reason);
396
421
  }
397
422
  }
398
- function requiredOperationID(out, opts) {
399
- const id = resolvedID(out.id);
400
- if (id === undefined) {
401
- throw errResolveFailed({
402
- resource: opts.resource,
403
- msg: opts.msg,
404
- });
405
- }
406
- return id;
407
- }
408
- function resolvedID(value) {
409
- const id = value?.trim();
410
- if (id === undefined || id === "" || id === ZeroID) {
411
- return undefined;
412
- }
413
- return id;
414
- }
@@ -1,5 +1,9 @@
1
- import { Friend, Hired, Manager, Na, OldHire, type Contact, type ID, type OperationResult } from "@fabriktor/schema";
2
1
  import type { ContactsOperator } from "@fabriktor/client";
2
+ import { Friend, Hired, Manager, Na, OldHire, type Contact, type ID, type OperationResult } from "@fabriktor/schema";
3
+ type ContactInsertOptions = Parameters<ContactsOperator["insertOneContact"]>[0];
4
+ type ContactReplaceOptions = Parameters<ContactsOperator["replaceOneContact"]>[0];
5
+ export type CreateContactOptions = ContactInsertOptions;
6
+ export type ReplaceContactOptions = ContactReplaceOptions;
3
7
  export type ContactRelation = typeof Na | typeof Friend | typeof OldHire | typeof Hired | typeof Manager;
4
8
  export type ActiveContactRelation = typeof Friend | typeof Hired | typeof Manager;
5
9
  export type ContactsFXOptions = {
@@ -42,6 +46,8 @@ export type EndHireRelationOptions = {
42
46
  contact: Contact;
43
47
  };
44
48
  export interface ContactsFXOperator {
49
+ createContact(opts: CreateContactOptions): Promise<Contact>;
50
+ replaceContact(opts: ReplaceContactOptions): Promise<Contact>;
45
51
  loadContactIndex(opts: LoadContactIndexOptions): Promise<ContactIndex>;
46
52
  startPresence(opts: StartPresenceOptions): Promise<PresenceSession>;
47
53
  sendFriendRequest(opts: SendFriendRequestOptions): Promise<OperationResult>;
@@ -54,6 +60,8 @@ export interface ContactsFXOperator {
54
60
  export declare class ContactsFX implements ContactsFXOperator {
55
61
  private contacts;
56
62
  constructor(opts: ContactsFXOptions);
63
+ createContact(opts: CreateContactOptions): Promise<Contact>;
64
+ replaceContact(opts: ReplaceContactOptions): Promise<Contact>;
57
65
  loadContactIndex(opts: LoadContactIndexOptions): Promise<ContactIndex>;
58
66
  startPresence(opts: StartPresenceOptions): Promise<PresenceSession>;
59
67
  sendFriendRequest(opts: SendFriendRequestOptions): Promise<OperationResult>;
@@ -62,6 +70,8 @@ export declare class ContactsFX implements ContactsFXOperator {
62
70
  acceptContactRequest(opts: AcceptContactRequestOptions): Promise<OperationResult>;
63
71
  rejectContactRequest(opts: RejectContactRequestOptions): Promise<OperationResult>;
64
72
  endHireRelation(opts: EndHireRelationOptions): Promise<OperationResult>;
65
- private replaceContact;
73
+ private replaceContactResult;
74
+ private findContact;
66
75
  }
67
76
  export declare function newContactsFX(opts: ContactsFXOptions): ContactsFX;
77
+ export {};
@@ -4,8 +4,12 @@
4
4
  // not use this file except in compliance with the License. You may obtain
5
5
  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
6
  import { Friend, Na, OldHire, } from "@fabriktor/schema";
7
- import { errRequired, errValidation } from "../core/err.js";
7
+ import { errRequired, errResolveFailed, errValidation } from "../core/err.js";
8
+ import { requiredOperationID } from "../core/id.js";
8
9
  const presenceIntervalMS = 120_000;
10
+ const resourceContact = "contact";
11
+ const msgCreatedContactIDMissing = "Created contact response did not contain an ID.";
12
+ const msgContactMissing = "Contact could not be resolved after the mutation.";
9
13
  const msgOwnerIDRequired = "Owner ID is required.";
10
14
  const msgContactIDRequired = "Contact ID is required.";
11
15
  const msgRelationUpgradeInvalid = "Requested relation must be higher than the current relation.";
@@ -16,6 +20,15 @@ export class ContactsFX {
16
20
  constructor(opts) {
17
21
  this.contacts = opts.contacts;
18
22
  }
23
+ async createContact(opts) {
24
+ const out = await this.contacts.insertOneContact(opts);
25
+ const id = requiredOperationID(out, msgCreatedContactIDMissing);
26
+ return await this.findContact(id);
27
+ }
28
+ async replaceContact(opts) {
29
+ await this.contacts.replaceOneContact(opts);
30
+ return await this.findContact(opts.id);
31
+ }
19
32
  async loadContactIndex(opts) {
20
33
  const owner_id = opts.owner_id.trim();
21
34
  if (owner_id === "") {
@@ -101,7 +114,7 @@ export class ContactsFX {
101
114
  msg: msgRelationUpgradeInvalid,
102
115
  });
103
116
  }
104
- return await this.replaceContact(opts.contact, {
117
+ return await this.replaceContactResult(opts.contact, {
105
118
  is_pending: true,
106
119
  relation: opts.contact.relation,
107
120
  requested_relation: opts.requested_relation,
@@ -115,7 +128,7 @@ export class ContactsFX {
115
128
  msg: msgRelationDowngradeInvalid,
116
129
  });
117
130
  }
118
- return await this.replaceContact(opts.contact, {
131
+ return await this.replaceContactResult(opts.contact, {
119
132
  is_pending: false,
120
133
  relation: opts.relation,
121
134
  requested_relation: Na,
@@ -129,7 +142,7 @@ export class ContactsFX {
129
142
  msg: msgPendingRelationRequired,
130
143
  });
131
144
  }
132
- return await this.replaceContact(opts.contact, {
145
+ return await this.replaceContactResult(opts.contact, {
133
146
  is_pending: false,
134
147
  relation: opts.contact.requested_relation,
135
148
  requested_relation: Na,
@@ -137,19 +150,19 @@ export class ContactsFX {
137
150
  });
138
151
  }
139
152
  async rejectContactRequest(opts) {
140
- return await this.replaceContact(opts.contact, {
153
+ return await this.replaceContactResult(opts.contact, {
141
154
  is_archived: true,
142
155
  });
143
156
  }
144
157
  async endHireRelation(opts) {
145
- return await this.replaceContact(opts.contact, {
158
+ return await this.replaceContactResult(opts.contact, {
146
159
  is_pending: false,
147
160
  relation: OldHire,
148
161
  requested_relation: Na,
149
162
  is_archived: false,
150
163
  });
151
164
  }
152
- async replaceContact(contact, overrides) {
165
+ async replaceContactResult(contact, overrides) {
153
166
  return await this.contacts.replaceOneContact({
154
167
  id: contact.id,
155
168
  in: {
@@ -162,6 +175,19 @@ export class ContactsFX {
162
175
  },
163
176
  });
164
177
  }
178
+ async findContact(id) {
179
+ const out = await this.contacts.findOneContact({
180
+ id,
181
+ });
182
+ const contact = out.value;
183
+ if (contact === undefined) {
184
+ throw errResolveFailed({
185
+ resource: resourceContact,
186
+ msg: msgContactMissing,
187
+ });
188
+ }
189
+ return contact;
190
+ }
165
191
  }
166
192
  export function newContactsFX(opts) {
167
193
  return new ContactsFX(opts);
@@ -0,0 +1,3 @@
1
+ import { type OperationResult } from "@fabriktor/schema";
2
+ export declare function requiredOperationID(out: OperationResult, msg: string): string;
3
+ export declare function resolvedID(value?: string): string | undefined;
@@ -0,0 +1,24 @@
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 { IDKey, ZeroID } from "@fabriktor/schema";
7
+ import { errResolveFailed } from "./err.js";
8
+ export function requiredOperationID(out, msg) {
9
+ const id = resolvedID(out.id);
10
+ if (id === undefined) {
11
+ throw errResolveFailed({
12
+ resource: IDKey,
13
+ msg,
14
+ });
15
+ }
16
+ return id;
17
+ }
18
+ export function resolvedID(value) {
19
+ const id = value?.trim();
20
+ if (id === undefined || id === "" || id === ZeroID) {
21
+ return undefined;
22
+ }
23
+ return id;
24
+ }
@@ -1,10 +1,17 @@
1
- import { type FeedObject, type FeedPost, type OperationResult, type RPFeedPull } from "@fabriktor/schema";
1
+ import { type FeedFavorite, type FeedObject, type FeedPost, type FeedReaction, type OperationResult, type RPFeedPull } from "@fabriktor/schema";
2
2
  import type { FeedOperator, OperationResultOf, StorageUploadFile } from "@fabriktor/client";
3
3
  import { type PullSession, type PullSessionErrorHandler } from "../core/pull.js";
4
+ import { type SearchPage } from "../core/search.js";
4
5
  import { type StorageFXOperator, type StoragePersonalBoxUploadResult } from "../storage/storage.js";
5
6
  type FeedPullOptions = Parameters<FeedOperator["pull"]>[0];
6
- type FeedPostInsert = Parameters<FeedOperator["insertOneFeedPost"]>[0]["in"];
7
- type FeedReactionInsert = Parameters<FeedOperator["insertOneFeedReaction"]>[0]["in"];
7
+ type FeedPostInsertOptions = Parameters<FeedOperator["insertOneFeedPost"]>[0];
8
+ type FeedPostReplaceOptions = Parameters<FeedOperator["replaceOneFeedPost"]>[0];
9
+ type FeedReactionInsertOptions = Parameters<FeedOperator["insertOneFeedReaction"]>[0];
10
+ type FeedReactionReplaceOptions = Parameters<FeedOperator["replaceOneFeedReaction"]>[0];
11
+ type FeedFavoriteInsertOptions = Parameters<FeedOperator["insertOneFeedFavorite"]>[0];
12
+ type FeedFavoriteReplaceOptions = Parameters<FeedOperator["replaceOneFeedFavorite"]>[0];
13
+ type FeedPostInsert = FeedPostInsertOptions["in"];
14
+ type FeedReactionInsert = FeedReactionInsertOptions["in"];
8
15
  export declare const FeedAction: {
9
16
  readonly Reaction: "reaction";
10
17
  readonly Favorite: "favorite";
@@ -23,6 +30,18 @@ export declare const FeedMediaPostStatus: {
23
30
  };
24
31
  export type FeedMediaPostStatus = (typeof FeedMediaPostStatus)[keyof typeof FeedMediaPostStatus];
25
32
  export type FeedReactionType = FeedReactionInsert["reaction_type"];
33
+ export type CreateFeedPostOptions = FeedPostInsertOptions;
34
+ export type ReplaceFeedPostOptions = FeedPostReplaceOptions;
35
+ export type CreateFeedReactionOptions = FeedReactionInsertOptions;
36
+ export type ReplaceFeedReactionOptions = FeedReactionReplaceOptions;
37
+ export type CreateFeedFavoriteOptions = FeedFavoriteInsertOptions;
38
+ export type ReplaceFeedFavoriteOptions = FeedFavoriteReplaceOptions;
39
+ export type SearchFeedPostsOptions = {
40
+ q?: string;
41
+ page?: number;
42
+ per_page?: number;
43
+ };
44
+ export type SearchFeedPostsPage = SearchPage<FeedPost>;
26
45
  export type FeedPullContext = Pick<FeedPullOptions, "contact_ids" | "pull_type" | "entity_id" | "research">;
27
46
  export type FeedTextPostContent = Pick<FeedPostInsert, "text">;
28
47
  export type FeedMediaPostInput = Pick<FeedPostInsert, "text" | "visibility">;
@@ -117,6 +136,13 @@ export type CreateFeedPostWithMediaResult = {
117
136
  error: unknown;
118
137
  };
119
138
  export interface FeedFXOperator {
139
+ createFeedPost(opts: CreateFeedPostOptions): Promise<FeedPost>;
140
+ replaceFeedPost(opts: ReplaceFeedPostOptions): Promise<FeedPost>;
141
+ searchFeedPosts(opts: SearchFeedPostsOptions): Promise<SearchFeedPostsPage>;
142
+ createFeedReaction(opts: CreateFeedReactionOptions): Promise<FeedReaction>;
143
+ replaceFeedReaction(opts: ReplaceFeedReactionOptions): Promise<FeedReaction>;
144
+ createFeedFavorite(opts: CreateFeedFavoriteOptions): Promise<FeedFavorite>;
145
+ replaceFeedFavorite(opts: ReplaceFeedFavoriteOptions): Promise<FeedFavorite>;
120
146
  startSession(opts: StartFeedSessionOptions): Promise<FeedSession>;
121
147
  addReaction(opts: AddFeedReactionOptions): Promise<OperationResult>;
122
148
  removeReaction(opts: RemoveFeedReactionOptions): Promise<OperationResult>;
@@ -139,6 +165,13 @@ export declare class FeedFX implements FeedFXOperator {
139
165
  private removed_actions;
140
166
  private action_ids;
141
167
  constructor(opts: FeedFXOptions);
168
+ createFeedPost(opts: CreateFeedPostOptions): Promise<FeedPost>;
169
+ replaceFeedPost(opts: ReplaceFeedPostOptions): Promise<FeedPost>;
170
+ searchFeedPosts(opts: SearchFeedPostsOptions): Promise<SearchFeedPostsPage>;
171
+ createFeedReaction(opts: CreateFeedReactionOptions): Promise<FeedReaction>;
172
+ replaceFeedReaction(opts: ReplaceFeedReactionOptions): Promise<FeedReaction>;
173
+ createFeedFavorite(opts: CreateFeedFavoriteOptions): Promise<FeedFavorite>;
174
+ replaceFeedFavorite(opts: ReplaceFeedFavoriteOptions): Promise<FeedFavorite>;
142
175
  startSession(opts: StartFeedSessionOptions): Promise<FeedSession>;
143
176
  addReaction(opts: AddFeedReactionOptions): Promise<OperationResult>;
144
177
  removeReaction(opts: RemoveFeedReactionOptions): Promise<OperationResult>;
@@ -152,6 +185,9 @@ export declare class FeedFX implements FeedFXOperator {
152
185
  createReplyWithMedia(opts: CreateFeedReplyWithMediaOptions): Promise<CreateFeedPostWithMediaResult>;
153
186
  createReferenceWithMedia(opts: CreateFeedReferenceWithMediaOptions): Promise<CreateFeedPostWithMediaResult>;
154
187
  private createMediaPost;
188
+ private findFeedPost;
189
+ private findFeedReaction;
190
+ private findFeedFavorite;
155
191
  private runAction;
156
192
  private hasAction;
157
193
  private actionID;
@@ -5,11 +5,16 @@
5
5
  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
6
  import { All, ColStorageFeed, PullTypeKeepAlive, ZeroID, } from "@fabriktor/schema";
7
7
  import { errResolveFailed, errValidation } from "../core/err.js";
8
+ import { requiredOperationID, resolvedID } from "../core/id.js";
8
9
  import { newPullSession, } from "../core/pull.js";
10
+ import { runSearch } from "../core/search.js";
9
11
  import { StorageUploadModeration, } from "../storage/storage.js";
10
12
  const newFeedSessionToken = "";
11
13
  const resourceFeedSessionToken = "feed_session_token";
12
14
  const resourceFeedPostID = "feed_post_id";
15
+ const resourceFeedPost = "feed_post";
16
+ const resourceFeedReaction = "feed_reaction";
17
+ const resourceFeedFavorite = "feed_favorite";
13
18
  const resourceFeedObject = "feed_object";
14
19
  const msgKeepAliveIntervalInvalid = "Keep-alive interval must be a finite number greater than zero.";
15
20
  const msgFeedSessionClosed = "Feed session is closed.";
@@ -17,6 +22,11 @@ const msgFeedPullInProgress = "A feed pull is already in progress.";
17
22
  const msgFeedSessionTokenMissing = "Feed pull response did not contain a session token.";
18
23
  const msgFeedPostIDMissing = "Feed post does not contain an ID.";
19
24
  const msgFeedCreatedPostIDMissing = "Created feed post response did not contain an ID.";
25
+ const msgFeedPostMissing = "Feed post could not be resolved after the mutation.";
26
+ const msgCreatedFeedReactionIDMissing = "Created feed reaction response did not contain an ID.";
27
+ const msgFeedReactionResolveMissing = "Feed reaction could not be resolved after the mutation.";
28
+ const msgCreatedFeedFavoriteIDMissing = "Created feed favorite response did not contain an ID.";
29
+ const msgFeedFavoriteResolveMissing = "Feed favorite could not be resolved after the mutation.";
20
30
  const msgFeedActionInProgress = "This feed action is already in progress for the post.";
21
31
  const msgFeedReactionAlreadyExists = "A reaction already exists for this post.";
22
32
  const msgFeedReactionMissing = "No reaction exists for this post.";
@@ -63,6 +73,42 @@ export class FeedFX {
63
73
  this.removed_actions = new Map();
64
74
  this.action_ids = new Map();
65
75
  }
76
+ async createFeedPost(opts) {
77
+ const out = await this.feed.insertOneFeedPost(opts);
78
+ const id = requiredOperationID(out, msgFeedCreatedPostIDMissing);
79
+ return await this.findFeedPost(id);
80
+ }
81
+ async replaceFeedPost(opts) {
82
+ await this.feed.replaceOneFeedPost(opts);
83
+ return await this.findFeedPost(opts.id);
84
+ }
85
+ async searchFeedPosts(opts) {
86
+ return await runSearch({
87
+ search: (searchOpts) => this.feed.searchManyFeedPosts(searchOpts),
88
+ query: {},
89
+ q: opts.q,
90
+ page: opts.page,
91
+ per_page: opts.per_page,
92
+ });
93
+ }
94
+ async createFeedReaction(opts) {
95
+ const out = await this.feed.insertOneFeedReaction(opts);
96
+ const id = requiredOperationID(out, msgCreatedFeedReactionIDMissing);
97
+ return await this.findFeedReaction(id);
98
+ }
99
+ async replaceFeedReaction(opts) {
100
+ await this.feed.replaceOneFeedReaction(opts);
101
+ return await this.findFeedReaction(opts.id);
102
+ }
103
+ async createFeedFavorite(opts) {
104
+ const out = await this.feed.insertOneFeedFavorite(opts);
105
+ const id = requiredOperationID(out, msgCreatedFeedFavoriteIDMissing);
106
+ return await this.findFeedFavorite(id);
107
+ }
108
+ async replaceFeedFavorite(opts) {
109
+ await this.feed.replaceOneFeedFavorite(opts);
110
+ return await this.findFeedFavorite(opts.id);
111
+ }
66
112
  async startSession(opts) {
67
113
  const { on_error, ...context } = opts;
68
114
  const initial = await this.feed.pull({
@@ -432,6 +478,45 @@ export class FeedFX {
432
478
  objects,
433
479
  };
434
480
  }
481
+ async findFeedPost(id) {
482
+ const out = await this.feed.findOneFeedPost({
483
+ id,
484
+ });
485
+ const post = out.value;
486
+ if (post === undefined) {
487
+ throw errResolveFailed({
488
+ resource: resourceFeedPost,
489
+ msg: msgFeedPostMissing,
490
+ });
491
+ }
492
+ return post;
493
+ }
494
+ async findFeedReaction(id) {
495
+ const out = await this.feed.findOneFeedReaction({
496
+ id,
497
+ });
498
+ const reaction = out.value;
499
+ if (reaction === undefined) {
500
+ throw errResolveFailed({
501
+ resource: resourceFeedReaction,
502
+ msg: msgFeedReactionResolveMissing,
503
+ });
504
+ }
505
+ return reaction;
506
+ }
507
+ async findFeedFavorite(id) {
508
+ const out = await this.feed.findOneFeedFavorite({
509
+ id,
510
+ });
511
+ const favorite = out.value;
512
+ if (favorite === undefined) {
513
+ throw errResolveFailed({
514
+ resource: resourceFeedFavorite,
515
+ msg: msgFeedFavoriteResolveMissing,
516
+ });
517
+ }
518
+ return favorite;
519
+ }
435
520
  async runAction(post_id, action, fn) {
436
521
  if (this.isActionRunning(post_id, action)) {
437
522
  throw errValidation({
@@ -582,13 +667,6 @@ function selfActionID(post, action) {
582
667
  return resolvedID(post.self?.reference_id);
583
668
  }
584
669
  }
585
- function resolvedID(v) {
586
- const out = resolvedValue(v);
587
- if (out === undefined || out === ZeroID) {
588
- return undefined;
589
- }
590
- return out;
591
- }
592
670
  function resolvedValue(v) {
593
671
  const out = v?.trim();
594
672
  if (out === undefined || out.length === 0) {
@@ -0,0 +1,32 @@
1
+ import type { FulfillmentsOperator } from "@fabriktor/client";
2
+ import { type FulfillOrder } from "@fabriktor/schema";
3
+ import { type SearchPage } from "../core/search.js";
4
+ type FulfillOrderInsertOptions = Parameters<FulfillmentsOperator["insertOneFulfillOrder"]>[0];
5
+ type FulfillOrderReplaceOptions = Parameters<FulfillmentsOperator["replaceOneFulfillOrder"]>[0];
6
+ export type CreateFulfillOrderOptions = FulfillOrderInsertOptions;
7
+ export type ReplaceFulfillOrderOptions = FulfillOrderReplaceOptions;
8
+ export type SearchFulfillOrdersOptions = {
9
+ owner_id: string;
10
+ q?: string;
11
+ page?: number;
12
+ per_page?: number;
13
+ };
14
+ export type SearchFulfillOrdersPage = SearchPage<FulfillOrder>;
15
+ export type FulfillmentsFXOptions = {
16
+ fulfillments: FulfillmentsOperator;
17
+ };
18
+ export interface FulfillmentsFXOperator {
19
+ createFulfillOrder(opts: CreateFulfillOrderOptions): Promise<FulfillOrder>;
20
+ replaceFulfillOrder(opts: ReplaceFulfillOrderOptions): Promise<FulfillOrder>;
21
+ searchFulfillOrders(opts: SearchFulfillOrdersOptions): Promise<SearchFulfillOrdersPage>;
22
+ }
23
+ export declare class FulfillmentsFX implements FulfillmentsFXOperator {
24
+ private fulfillments;
25
+ constructor(opts: FulfillmentsFXOptions);
26
+ createFulfillOrder(opts: CreateFulfillOrderOptions): Promise<FulfillOrder>;
27
+ replaceFulfillOrder(opts: ReplaceFulfillOrderOptions): Promise<FulfillOrder>;
28
+ searchFulfillOrders(opts: SearchFulfillOrdersOptions): Promise<SearchFulfillOrdersPage>;
29
+ private findFulfillOrder;
30
+ }
31
+ export declare function newFulfillmentsFX(opts: FulfillmentsFXOptions): FulfillmentsFX;
32
+ export {};
@@ -0,0 +1,54 @@
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 { OwnerIDKey } from "@fabriktor/schema";
7
+ import { errResolveFailed } from "../core/err.js";
8
+ import { requiredOperationID } from "../core/id.js";
9
+ import { runSearch } from "../core/search.js";
10
+ const resourceFulfillOrder = "fulfill_order";
11
+ const msgCreatedFulfillOrderIDMissing = "Created fulfill order response did not contain an ID.";
12
+ const msgFulfillOrderMissing = "Fulfill order could not be resolved after the mutation.";
13
+ export class FulfillmentsFX {
14
+ fulfillments;
15
+ constructor(opts) {
16
+ this.fulfillments = opts.fulfillments;
17
+ }
18
+ async createFulfillOrder(opts) {
19
+ const out = await this.fulfillments.insertOneFulfillOrder(opts);
20
+ const id = requiredOperationID(out, msgCreatedFulfillOrderIDMissing);
21
+ return await this.findFulfillOrder(id);
22
+ }
23
+ async replaceFulfillOrder(opts) {
24
+ await this.fulfillments.replaceOneFulfillOrder(opts);
25
+ return await this.findFulfillOrder(opts.id);
26
+ }
27
+ async searchFulfillOrders(opts) {
28
+ return await runSearch({
29
+ search: (searchOpts) => this.fulfillments.searchManyFulfillOrders(searchOpts),
30
+ query: {
31
+ [OwnerIDKey]: opts.owner_id,
32
+ },
33
+ q: opts.q,
34
+ page: opts.page,
35
+ per_page: opts.per_page,
36
+ });
37
+ }
38
+ async findFulfillOrder(id) {
39
+ const out = await this.fulfillments.findOneFulfillOrder({
40
+ id,
41
+ });
42
+ const fulfill_order = out.value;
43
+ if (fulfill_order === undefined) {
44
+ throw errResolveFailed({
45
+ resource: resourceFulfillOrder,
46
+ msg: msgFulfillOrderMissing,
47
+ });
48
+ }
49
+ return fulfill_order;
50
+ }
51
+ }
52
+ export function newFulfillmentsFX(opts) {
53
+ return new FulfillmentsFX(opts);
54
+ }