@fabriktor/fx 0.0.38 → 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 +41 -2
  6. package/dist/src/chat/chat.js +293 -28
  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
@@ -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
+ }
package/dist/src/fx.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- import type { BillableOperator, CallsOperator, ChatOperator, ConnectionsOperator, ContactsOperator, FeedOperator, JobsOperator, MarketplaceOperator, MemosOperator, NotificationsOperator, PaymentsOperator, PayrollsOperator, PreferencesOperator, PrivacyOperator, RoutesOperator, StorageOperator, TimesheetsOperator, TmpPhonesOperator, TmpUsernamesOperator, UsersOperator } from "@fabriktor/client";
1
+ import type { BillableOperator, CallsOperator, ChatOperator, ConnectionsOperator, ContactsOperator, FeedOperator, FulfillmentsOperator, JobsOperator, MarketplaceOperator, MemosOperator, NotificationsOperator, PaymentsOperator, PayrollsOperator, PreferencesOperator, PrivacyOperator, RoutesOperator, StorageOperator, TimesheetsOperator, TmpPhonesOperator, TmpUsernamesOperator, UsersOperator } from "@fabriktor/client";
2
2
  import type { AuthOperator } from "./auth/auth.js";
3
3
  import type { BillableFX, BillableFXOperator } from "./billable/billable.js";
4
4
  import type { CallsFX, CallsFXOperator } from "./calls/calls.js";
5
5
  import type { ChatFX, ChatFXOperator } from "./chat/chat.js";
6
6
  import type { ContactsFX, ContactsFXOperator } from "./contacts/contacts.js";
7
7
  import type { FeedFX, FeedFXOperator } from "./feed/feed.js";
8
+ import type { FulfillmentsFX, FulfillmentsFXOperator } from "./fulfillments/fulfillments.js";
8
9
  import type { JobsFX, JobsFXOperator } from "./jobs/jobs.js";
9
10
  import type { MarketplaceFX, MarketplaceFXOperator } from "./marketplace/marketplace.js";
10
11
  import type { MemosFX, MemosFXOperator } from "./memos/memos.js";
@@ -26,6 +27,7 @@ export type FXOptions = {
26
27
  connections: ConnectionsOperator;
27
28
  contacts: ContactsOperator;
28
29
  feed: FeedOperator;
30
+ fulfillments: FulfillmentsOperator;
29
31
  jobs: JobsOperator;
30
32
  marketplace: MarketplaceOperator;
31
33
  memos: MemosOperator;
@@ -57,6 +59,7 @@ export interface FXOperator {
57
59
  chat: ChatFXOperator;
58
60
  contacts: ContactsFXOperator;
59
61
  feed: FeedFXOperator;
62
+ fulfillments: FulfillmentsFXOperator;
60
63
  jobs: JobsFXOperator;
61
64
  marketplace: MarketplaceFXOperator;
62
65
  memos: MemosFXOperator;
@@ -77,6 +80,7 @@ export declare class FX implements FXOperator {
77
80
  chat: ChatFX;
78
81
  contacts: ContactsFX;
79
82
  feed: FeedFX;
83
+ fulfillments: FulfillmentsFX;
80
84
  jobs: JobsFX;
81
85
  marketplace: MarketplaceFX;
82
86
  memos: MemosFX;
package/dist/src/fx.js CHANGED
@@ -3,12 +3,13 @@
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 { newBillableClient, newCallsClient, newChatClient, newConnectionsClient, newContactsClient, newFeedClient, newHTTPClient, newJobsClient, newMarketplaceClient, newMemosClient, newNotificationsClient, newPaymentsClient, newPayrollsClient, newPreferencesClient, newPrivacyClient, newRoutesClient, newStorageClient, newTimesheetsClient, newTmpPhonesClient, newTmpUsernamesClient, newUsersClient, } from "@fabriktor/client";
6
+ import { newBillableClient, newCallsClient, newChatClient, newConnectionsClient, newContactsClient, newFeedClient, newFulfillmentsClient, newHTTPClient, newJobsClient, newMarketplaceClient, newMemosClient, newNotificationsClient, newPaymentsClient, newPayrollsClient, newPreferencesClient, newPrivacyClient, newRoutesClient, newStorageClient, newTimesheetsClient, newTmpPhonesClient, newTmpUsernamesClient, newUsersClient, } from "@fabriktor/client";
7
7
  import { newBillableFX } from "./billable/billable.js";
8
8
  import { newCallsFX } from "./calls/calls.js";
9
9
  import { newChatFX } from "./chat/chat.js";
10
10
  import { newContactsFX } from "./contacts/contacts.js";
11
11
  import { newFeedFX } from "./feed/feed.js";
12
+ import { newFulfillmentsFX } from "./fulfillments/fulfillments.js";
12
13
  import { newJobsFX } from "./jobs/jobs.js";
13
14
  import { newMarketplaceFX } from "./marketplace/marketplace.js";
14
15
  import { newMemosFX } from "./memos/memos.js";
@@ -28,6 +29,7 @@ export class FX {
28
29
  chat;
29
30
  contacts;
30
31
  feed;
32
+ fulfillments;
31
33
  jobs;
32
34
  marketplace;
33
35
  memos;
@@ -55,6 +57,9 @@ export class FX {
55
57
  this.contacts = newContactsFX({
56
58
  contacts: opts.contacts,
57
59
  });
60
+ this.fulfillments = newFulfillmentsFX({
61
+ fulfillments: opts.fulfillments,
62
+ });
58
63
  this.jobs = newJobsFX({
59
64
  jobs: opts.jobs,
60
65
  });
@@ -146,6 +151,11 @@ export function newDefaultFX(opts) {
146
151
  base_url: opts.base_url,
147
152
  get_token,
148
153
  }),
154
+ fulfillments: newFulfillmentsClient({
155
+ http,
156
+ base_url: opts.base_url,
157
+ get_token,
158
+ }),
149
159
  jobs: newJobsClient({
150
160
  http,
151
161
  base_url: opts.base_url,
@@ -4,9 +4,11 @@ export * from "./calls/calls.js";
4
4
  export * from "./chat/chat.js";
5
5
  export * from "./contacts/contacts.js";
6
6
  export * from "./core/err.js";
7
+ export * from "./core/id.js";
7
8
  export * from "./core/pull.js";
8
9
  export * from "./core/search.js";
9
10
  export * from "./feed/feed.js";
11
+ export * from "./fulfillments/fulfillments.js";
10
12
  export * from "./fx.js";
11
13
  export * from "./jobs/jobs.js";
12
14
  export * from "./marketplace/marketplace.js";
package/dist/src/index.js CHANGED
@@ -4,9 +4,11 @@ export * from "./calls/calls.js";
4
4
  export * from "./chat/chat.js";
5
5
  export * from "./contacts/contacts.js";
6
6
  export * from "./core/err.js";
7
+ export * from "./core/id.js";
7
8
  export * from "./core/pull.js";
8
9
  export * from "./core/search.js";
9
10
  export * from "./feed/feed.js";
11
+ export * from "./fulfillments/fulfillments.js";
10
12
  export * from "./fx.js";
11
13
  export * from "./jobs/jobs.js";
12
14
  export * from "./marketplace/marketplace.js";
@@ -1,13 +1,34 @@
1
- import { type Job, type Location, type OperationResult, type RPJobsFindOverlaps } from "@fabriktor/schema";
1
+ import { type Job, type JobProgram, type Location, type OperationResult, type RPJobsFindOverlaps } from "@fabriktor/schema";
2
2
  import type { JobsOperator, OperationResultOf } from "@fabriktor/client";
3
+ import { type SearchPage } from "../core/search.js";
3
4
  type JobInsert = Parameters<JobsOperator["insertOneJob"]>[0]["in"];
4
5
  type JobProgramInsert = Parameters<JobsOperator["insertOneJobProgram"]>[0]["in"];
5
6
  type LocationInsert = Parameters<JobsOperator["insertOneLocation"]>[0]["in"];
7
+ type LocationInsertOptions = Parameters<JobsOperator["insertOneLocation"]>[0];
8
+ type LocationReplaceOptions = Parameters<JobsOperator["replaceOneLocation"]>[0];
9
+ type JobProgramReplaceOptions = Parameters<JobsOperator["replaceOneJobProgram"]>[0];
10
+ type JobReplaceOptions = Parameters<JobsOperator["replaceOneJob"]>[0];
11
+ type SearchJobRecordsOptions = {
12
+ owner_id: string;
13
+ q?: string;
14
+ page?: number;
15
+ per_page?: number;
16
+ };
6
17
  export declare const JobProgramCreateMode: {
7
18
  readonly Scheduled: "scheduled";
8
19
  readonly Immediate: "immediate";
9
20
  };
10
21
  export type JobProgramCreateMode = (typeof JobProgramCreateMode)[keyof typeof JobProgramCreateMode];
22
+ export type CreateLocationOptions = LocationInsertOptions;
23
+ export type ReplaceLocationOptions = LocationReplaceOptions;
24
+ export type ReplaceJobProgramOptions = JobProgramReplaceOptions;
25
+ export type ReplaceJobOptions = JobReplaceOptions;
26
+ export type SearchLocationsOptions = SearchJobRecordsOptions;
27
+ export type SearchJobProgramsOptions = SearchJobRecordsOptions;
28
+ export type SearchJobsOptions = SearchJobRecordsOptions;
29
+ export type SearchLocationsPage = SearchPage<Location>;
30
+ export type SearchJobProgramsPage = SearchPage<JobProgram>;
31
+ export type SearchJobsPage = SearchPage<Job>;
11
32
  export type JobsFXOptions = {
12
33
  jobs: JobsOperator;
13
34
  now?: () => globalThis.Date;
@@ -24,12 +45,18 @@ export type CreateJobProgramOptions = {
24
45
  in: CreateJobProgramInput;
25
46
  location: Location;
26
47
  };
27
- export type CreateJobProgramResult = {
48
+ export type CreateLocationJobProgramResult = {
28
49
  mode: typeof JobProgramCreateMode.Scheduled;
29
50
  create: OperationResult;
30
51
  } | {
31
52
  mode: typeof JobProgramCreateMode.Immediate;
32
53
  };
54
+ export type CreateJobProgramResult = {
55
+ mode: typeof JobProgramCreateMode.Scheduled;
56
+ job_program: JobProgram;
57
+ } | {
58
+ mode: typeof JobProgramCreateMode.Immediate;
59
+ };
33
60
  export type FindLocationOverlapsInput = Pick<LocationInsert, "y" | "m" | "d" | "h" | "min" | "tz" | "end_date">;
34
61
  export type FindLocationOverlapsOptions = {
35
62
  in: FindLocationOverlapsInput;
@@ -52,8 +79,17 @@ export type SetLocationMembersOptions = {
52
79
  current_members: string[];
53
80
  };
54
81
  export interface JobsFXOperator {
55
- createJob(opts: CreateJobOptions): Promise<OperationResult>;
82
+ createLocation(opts: CreateLocationOptions): Promise<Location>;
83
+ replaceLocation(opts: ReplaceLocationOptions): Promise<Location>;
84
+ searchLocations(opts: SearchLocationsOptions): Promise<SearchLocationsPage>;
85
+ replaceJobProgram(opts: ReplaceJobProgramOptions): Promise<JobProgram>;
86
+ searchJobPrograms(opts: SearchJobProgramsOptions): Promise<SearchJobProgramsPage>;
87
+ replaceJob(opts: ReplaceJobOptions): Promise<Job>;
88
+ searchJobs(opts: SearchJobsOptions): Promise<SearchJobsPage>;
89
+ createJob(opts: CreateJobOptions): Promise<Job>;
90
+ createLocationJob(opts: CreateJobOptions): Promise<OperationResult>;
56
91
  createJobProgram(opts: CreateJobProgramOptions): Promise<CreateJobProgramResult>;
92
+ createLocationJobProgram(opts: CreateJobProgramOptions): Promise<CreateLocationJobProgramResult>;
57
93
  findLocationOverlaps(opts: FindLocationOverlapsOptions): Promise<OperationResultOf<RPJobsFindOverlaps>>;
58
94
  addJobForeman(opts: AddJobForemanOptions): Promise<OperationResult>;
59
95
  removeJobMember(opts: RemoveJobMemberOptions): Promise<OperationResult>;
@@ -63,12 +99,24 @@ export declare class JobsFX implements JobsFXOperator {
63
99
  private jobs;
64
100
  private now;
65
101
  constructor(opts: JobsFXOptions);
66
- createJob(opts: CreateJobOptions): Promise<OperationResult>;
102
+ createLocation(opts: CreateLocationOptions): Promise<Location>;
103
+ replaceLocation(opts: ReplaceLocationOptions): Promise<Location>;
104
+ searchLocations(opts: SearchLocationsOptions): Promise<SearchLocationsPage>;
105
+ replaceJobProgram(opts: ReplaceJobProgramOptions): Promise<JobProgram>;
106
+ searchJobPrograms(opts: SearchJobProgramsOptions): Promise<SearchJobProgramsPage>;
107
+ replaceJob(opts: ReplaceJobOptions): Promise<Job>;
108
+ searchJobs(opts: SearchJobsOptions): Promise<SearchJobsPage>;
109
+ createJob(opts: CreateJobOptions): Promise<Job>;
110
+ createLocationJob(opts: CreateJobOptions): Promise<OperationResult>;
67
111
  createJobProgram(opts: CreateJobProgramOptions): Promise<CreateJobProgramResult>;
112
+ createLocationJobProgram(opts: CreateJobProgramOptions): Promise<CreateLocationJobProgramResult>;
68
113
  findLocationOverlaps(opts: FindLocationOverlapsOptions): Promise<OperationResultOf<RPJobsFindOverlaps>>;
69
114
  addJobForeman(opts: AddJobForemanOptions): Promise<OperationResult>;
70
115
  removeJobMember(opts: RemoveJobMemberOptions): Promise<OperationResult>;
71
116
  setLocationMembers(opts: SetLocationMembersOptions): Promise<OperationResult>;
117
+ private findLocation;
118
+ private findJobProgram;
119
+ private findJob;
72
120
  }
73
121
  export declare function newJobsFX(opts: JobsFXOptions): JobsFX;
74
122
  export {};
@@ -3,8 +3,10 @@
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 { LocationTypePersistent, Pending, Started, Terminated, ZeroID, } from "@fabriktor/schema";
7
- import { errRequired, errValidation } from "../core/err.js";
6
+ import { LocationTypePersistent, Pending, Started, OwnerIDKey, Terminated, ZeroID, } from "@fabriktor/schema";
7
+ import { errRequired, errResolveFailed, errValidation, } from "../core/err.js";
8
+ import { requiredOperationID, resolvedID } from "../core/id.js";
9
+ import { runSearch } from "../core/search.js";
8
10
  const msgJobIDRequired = "Job ID is required.";
9
11
  const msgLocationIDRequired = "Location ID is required.";
10
12
  const msgMemberIDRequired = "Member ID is required.";
@@ -20,6 +22,15 @@ const msgLocationMemberAssigned = "Cannot remove a location member while they ar
20
22
  const msgDateInvalid = "Date contains an invalid UTC value.";
21
23
  const msgLocationRangeInvalid = "Location contains an invalid scheduled time span.";
22
24
  const msgTimezoneInvalid = "Program timezone is invalid.";
25
+ const resourceLocation = "location";
26
+ const resourceJobProgram = "job_program";
27
+ const resourceJob = "job";
28
+ const msgCreatedLocationIDMissing = "Created location response did not contain an ID.";
29
+ const msgCreatedJobProgramIDMissing = "Created job program response did not contain an ID.";
30
+ const msgCreatedJobIDMissing = "Created job response did not contain an ID.";
31
+ const msgLocationMissing = "Location could not be resolved after the mutation.";
32
+ const msgJobProgramMissing = "Job program could not be resolved after the mutation.";
33
+ const msgJobMissing = "Job could not be resolved after the mutation.";
23
34
  export const JobProgramCreateMode = {
24
35
  Scheduled: "scheduled",
25
36
  Immediate: "immediate",
@@ -31,7 +42,62 @@ export class JobsFX {
31
42
  this.jobs = opts.jobs;
32
43
  this.now = opts.now ?? (() => new globalThis.Date());
33
44
  }
45
+ async createLocation(opts) {
46
+ const out = await this.jobs.insertOneLocation(opts);
47
+ const id = requiredOperationID(out, msgCreatedLocationIDMissing);
48
+ return await this.findLocation(id);
49
+ }
50
+ async replaceLocation(opts) {
51
+ await this.jobs.replaceOneLocation(opts);
52
+ return await this.findLocation(opts.id);
53
+ }
54
+ async searchLocations(opts) {
55
+ return await runSearch({
56
+ search: (searchOpts) => this.jobs.searchManyLocations(searchOpts),
57
+ query: {
58
+ [OwnerIDKey]: opts.owner_id,
59
+ },
60
+ q: opts.q,
61
+ page: opts.page,
62
+ per_page: opts.per_page,
63
+ });
64
+ }
65
+ async replaceJobProgram(opts) {
66
+ await this.jobs.replaceOneJobProgram(opts);
67
+ return await this.findJobProgram(opts.id);
68
+ }
69
+ async searchJobPrograms(opts) {
70
+ return await runSearch({
71
+ search: (searchOpts) => this.jobs.searchManyJobPrograms(searchOpts),
72
+ query: {
73
+ [OwnerIDKey]: opts.owner_id,
74
+ },
75
+ q: opts.q,
76
+ page: opts.page,
77
+ per_page: opts.per_page,
78
+ });
79
+ }
80
+ async replaceJob(opts) {
81
+ await this.jobs.replaceOneJob(opts);
82
+ return await this.findJob(opts.id);
83
+ }
84
+ async searchJobs(opts) {
85
+ return await runSearch({
86
+ search: (searchOpts) => this.jobs.searchManyJobs(searchOpts),
87
+ query: {
88
+ [OwnerIDKey]: opts.owner_id,
89
+ },
90
+ q: opts.q,
91
+ page: opts.page,
92
+ per_page: opts.per_page,
93
+ });
94
+ }
34
95
  async createJob(opts) {
96
+ const out = await this.createLocationJob(opts);
97
+ const id = requiredOperationID(out, msgCreatedJobIDMissing);
98
+ return await this.findJob(id);
99
+ }
100
+ async createLocationJob(opts) {
35
101
  const location_id = requiredID(opts.location.id, "location", msgLocationIDRequired);
36
102
  const foremen = normalizeIDs(opts.in.foremen);
37
103
  const current_members = unionIDs(opts.in.current_members, foremen);
@@ -58,6 +124,19 @@ export class JobsFX {
58
124
  });
59
125
  }
60
126
  async createJobProgram(opts) {
127
+ const out = await this.createLocationJobProgram(opts);
128
+ if (out.mode === JobProgramCreateMode.Immediate) {
129
+ return {
130
+ mode: JobProgramCreateMode.Immediate,
131
+ };
132
+ }
133
+ const id = requiredOperationID(out.create, msgCreatedJobProgramIDMissing);
134
+ return {
135
+ mode: JobProgramCreateMode.Scheduled,
136
+ job_program: await this.findJobProgram(id),
137
+ };
138
+ }
139
+ async createLocationJobProgram(opts) {
61
140
  const job_location_id = requiredID(opts.location.id, "location", msgLocationIDRequired);
62
141
  const job_foremen = normalizeIDs(opts.in.job_foremen);
63
142
  const job_current_members = unionIDs(opts.in.job_current_members, job_foremen);
@@ -200,6 +279,45 @@ export class JobsFX {
200
279
  },
201
280
  });
202
281
  }
282
+ async findLocation(id) {
283
+ const out = await this.jobs.findOneLocation({
284
+ id,
285
+ });
286
+ const location = out.value;
287
+ if (location === undefined) {
288
+ throw errResolveFailed({
289
+ resource: resourceLocation,
290
+ msg: msgLocationMissing,
291
+ });
292
+ }
293
+ return location;
294
+ }
295
+ async findJobProgram(id) {
296
+ const out = await this.jobs.findOneJobProgram({
297
+ id,
298
+ });
299
+ const job_program = out.value;
300
+ if (job_program === undefined) {
301
+ throw errResolveFailed({
302
+ resource: resourceJobProgram,
303
+ msg: msgJobProgramMissing,
304
+ });
305
+ }
306
+ return job_program;
307
+ }
308
+ async findJob(id) {
309
+ const out = await this.jobs.findOneJob({
310
+ id,
311
+ });
312
+ const job = out.value;
313
+ if (job === undefined) {
314
+ throw errResolveFailed({
315
+ resource: resourceJob,
316
+ msg: msgJobMissing,
317
+ });
318
+ }
319
+ return job;
320
+ }
203
321
  }
204
322
  export function newJobsFX(opts) {
205
323
  return new JobsFX(opts);
@@ -347,13 +465,6 @@ function requiredID(v, field, msg) {
347
465
  }
348
466
  return out;
349
467
  }
350
- function resolvedID(v) {
351
- const out = v?.trim();
352
- if (out === undefined || out === "" || out === ZeroID) {
353
- return undefined;
354
- }
355
- return out;
356
- }
357
468
  function normalizeIDs(ids) {
358
469
  const seen = new Set();
359
470
  const out = [];