@joai/sdk 4.7.0 → 4.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -220,6 +220,7 @@ type CheckoutSnapshot = {
220
220
  type GuestBuyer = {
221
221
  name: string;
222
222
  email: string;
223
+ phone?: string;
223
224
  };
224
225
  type CheckoutSnapshotRequest = {
225
226
  fulfillmentMethod: FulfillmentMethod;
@@ -290,6 +291,7 @@ type SubscriptionDelivery = {
290
291
  fulfillmentLocation?: {
291
292
  name: string;
292
293
  instructions: string | null;
294
+ address?: AddressSnapshot | null;
293
295
  } | null;
294
296
  }; //#endregion
295
297
  //#region src/wallet/types.d.ts
@@ -614,6 +616,7 @@ declare const NativeApps: {
614
616
  readonly Heartbeats: "heartbeats";
615
617
  readonly Wallets: "wallets";
616
618
  readonly Campaigns: "campaigns";
619
+ readonly Automations: "automations";
617
620
  readonly News: "news";
618
621
  readonly Sites: "sites";
619
622
  readonly Contracts: "contracts";
@@ -824,9 +827,10 @@ type AiCostsResponse = {
824
827
  }; //#endregion
825
828
  //#region src/billing/types.d.ts
826
829
  type TranslatableValue = Partial<Record<WarpLocale, string>>;
827
- type OrderStatus = 'pending' | 'completed' | 'delivered' | 'canceled';
830
+ type OrderStatus = 'pending' | 'confirmed' | 'processing' | 'shipped' | 'completed' | 'delivered' | 'canceled' | 'returned';
828
831
  type OrderSource = 'auto' | 'manual' | 'kiosk';
829
832
  type OrderType = 'order' | 'quote';
833
+ type OrderPriceMode = 'net' | 'gross';
830
834
  type SubscriptionStatus = 'active' | 'canceled' | 'past_due' | 'pending';
831
835
  type SubscriptionInterval = 'weekly' | 'biweekly' | 'monthly' | 'quarterly' | 'yearly';
832
836
  type PricingModel = 'free' | 'one-time' | 'weekly' | 'biweekly' | 'monthly' | 'quarterly' | 'yearly' | 'per-run';
@@ -1037,6 +1041,7 @@ type Order = {
1037
1041
  source: OrderSource | null;
1038
1042
  context: OrderContext | null;
1039
1043
  paymentMode: string | null;
1044
+ priceMode?: OrderPriceMode | null;
1040
1045
  linkVariationId: string | null;
1041
1046
  notes: string | null;
1042
1047
  fulfillmentMethod?: FulfillmentMethod | null;
@@ -1046,6 +1051,7 @@ type Order = {
1046
1051
  fulfillmentLocation?: {
1047
1052
  name: string;
1048
1053
  instructions?: string | null;
1054
+ address?: AddressSnapshot | null;
1049
1055
  } | null;
1050
1056
  shippingFee?: number;
1051
1057
  fulfillments?: Fulfillment[];
@@ -1899,24 +1905,37 @@ type AppointmentRequest = {
1899
1905
  createdAt: string;
1900
1906
  }; //#endregion
1901
1907
  //#region src/automation/types.d.ts
1902
- type AutomationTriggerType = 'prop' | 'segment' | 'manual';
1903
- type AutomationActionType = 'wait' | 'send_email' | 'halt';
1904
- type AutomationSendMode = 'direct' | 'campaign';
1908
+ type AutomationTriggerType = 'prop' | 'segment' | 'manual' | 'webhook';
1909
+ type AutomationActionType = 'wait' | 'halt' | 'warp' | 'branch';
1905
1910
  type AutomationEnrollmentStatus = 'active' | 'completed' | 'skipped';
1906
1911
  type AutomationSkipReason = 'pending_consent' | 'opted_out' | 'missing_channel' | 'automation_disabled' | 'already_completed';
1907
1912
  type AutomationTriggerConfig = {
1908
1913
  propKey?: string;
1909
1914
  propValue?: string | number | boolean;
1910
1915
  segmentId?: string;
1916
+ source?: string;
1917
+ trigger?: {
1918
+ event?: string;
1919
+ when?: Array<{
1920
+ path: string;
1921
+ operator: string;
1922
+ value?: unknown;
1923
+ }>;
1924
+ inputs?: Record<string, unknown>;
1925
+ };
1926
+ hookId?: string;
1911
1927
  };
1912
1928
  type AutomationActionConfig = {
1913
1929
  delayMinutes?: number;
1914
- sendMode?: AutomationSendMode;
1915
- campaignId?: string;
1916
- subject?: string;
1917
- body?: string;
1918
- contentHtml?: boolean;
1919
- sentPropKey?: string;
1930
+ warpId?: string;
1931
+ inputs?: Record<string, unknown>;
1932
+ when?: Array<{
1933
+ path: string;
1934
+ operator: string;
1935
+ value?: unknown;
1936
+ }>;
1937
+ thenPosition?: number;
1938
+ elsePosition?: number;
1920
1939
  [key: string]: unknown;
1921
1940
  };
1922
1941
  type AutomationAction = {
@@ -1933,6 +1952,10 @@ type Automation = {
1933
1952
  enabled: boolean;
1934
1953
  agent: AgentSimple | null;
1935
1954
  actions?: AutomationAction[];
1955
+ activeEnrollmentsCount?: number;
1956
+ completedEnrollmentsCount?: number;
1957
+ skippedEnrollmentsCount?: number;
1958
+ erroredEnrollmentsCount?: number;
1936
1959
  createdAt: string;
1937
1960
  updatedAt: string;
1938
1961
  };
@@ -1978,8 +2001,23 @@ type AutomationUpdatePayload = {
1978
2001
  };
1979
2002
  type AutomationAudiencePreview = {
1980
2003
  count: number;
2004
+ total: number;
2005
+ sendable: number;
2006
+ willSkip: number;
2007
+ reasons: Record<'pending_consent' | 'opted_out' | 'missing_channel', number>;
1981
2008
  sampleContactIds: string[];
1982
- }; //#endregion
2009
+ channel: string | null;
2010
+ };
2011
+ type AutomationStats = {
2012
+ totalAutomations: number;
2013
+ enabledAutomations: number;
2014
+ activeEnrollments: number;
2015
+ emailsSent: number;
2016
+ completedEnrollments: number;
2017
+ erroredEnrollments: number;
2018
+ };
2019
+ type CampaignChannelId = 'email' | 'whatsapp' | 'sms' | 'push';
2020
+ //#endregion
1983
2021
  //#region src/content/types.d.ts
1984
2022
  type ContentStatus = 'draft' | 'published' | 'archived';
1985
2023
  type ContentFieldType = 'text' | 'richText' | 'number' | 'boolean' | 'url' | 'image' | 'media' | 'list' | 'object' | 'reference';
@@ -2039,7 +2077,7 @@ type PatchContentInput = {
2039
2077
  patches: ContentPatch[];
2040
2078
  origin?: 'api' | 'inlineEditor' | 'joai' | 'mcp';
2041
2079
  }; //#endregion
2042
- //#region src/commerce/helpers.d.ts
2080
+ //#region src/address/formatAddressSnapshot.d.ts
2043
2081
  //#endregion
2044
2082
  //#region src/card/types.d.ts
2045
2083
  type Card = {
@@ -2875,6 +2913,8 @@ type SiteAgent = {
2875
2913
  type Site = {
2876
2914
  id: number;
2877
2915
  slug: string;
2916
+ name: string | null;
2917
+ url: string | null;
2878
2918
  brandSlug: string | null;
2879
2919
  customDomain: string | null;
2880
2920
  enabled: boolean;
@@ -3101,7 +3141,7 @@ type SegmentCountResult = {
3101
3141
  reachable: number | null;
3102
3142
  }; //#endregion
3103
3143
  //#region src/campaign/types.d.ts
3104
- type CampaignChannel = 'email' | 'whatsapp' | 'sms' | 'push';
3144
+ type CampaignChannel = CampaignChannelId;
3105
3145
  type CampaignStatus = 'draft' | 'pending' | 'approved' | 'rejected' | 'scheduled' | 'sending' | 'completed' | 'failed';
3106
3146
  type CampaignCategory = 'MARKETING' | 'UTILITY' | 'AUTHENTICATION';
3107
3147
  type CampaignSkipReason = 'pending_consent' | 'opted_out' | 'missing_channel' | 'approval_skipped';
@@ -3322,10 +3362,10 @@ type HookTriggerCondition = {
3322
3362
  value?: unknown;
3323
3363
  };
3324
3364
  type HookTriggerInput = string | {
3325
- source: 'payload';
3365
+ source: 'payload' | 'contact' | 'enrollment';
3326
3366
  path: string;
3327
3367
  } | {
3328
- source: 'literal';
3368
+ source: 'literal' | 'static';
3329
3369
  value: unknown;
3330
3370
  };
3331
3371
  type HookTrigger = {
@@ -3607,6 +3647,103 @@ declare function createGuestCommerceStorage(options: GuestCommerceStorageOptions
3607
3647
  listOrderAccess(): GuestOrderAccess[];
3608
3648
  };
3609
3649
  //#endregion
3650
+ //#region src/commerce/guestCheckout.d.ts
3651
+ type GuestCheckoutCartItem = {
3652
+ id: string;
3653
+ type: 'product' | 'service' | 'coupon';
3654
+ quantity: number;
3655
+ };
3656
+ type GuestCheckoutState<TCart = GuestCheckoutCartItem[]> = GuestCheckoutDraft<TCart> & {
3657
+ identity: GuestBuyer;
3658
+ address: AddressInput;
3659
+ };
3660
+ type GuestCheckoutErrorCode = 'empty_cart' | 'missing_identity' | 'missing_pickup_phone' | 'incomplete_shipping_address' | 'pickup_unavailable' | 'missing_shipping_rate' | 'rates_failed' | 'snapshot_failed' | 'review_required' | 'terms_required' | 'review_expired' | 'order_failed' | 'payment_failed';
3661
+ declare class GuestCheckoutError extends Error {
3662
+ readonly code: GuestCheckoutErrorCode;
3663
+ constructor(code: GuestCheckoutErrorCode);
3664
+ }
3665
+ type GuestCheckoutClient = {
3666
+ commerce: {
3667
+ checkout: {
3668
+ shippingRates(team: string, data: {
3669
+ address: {
3670
+ country: string;
3671
+ zipCode?: string;
3672
+ };
3673
+ items: GuestCheckoutCartItem[];
3674
+ }): Promise<IAppResponse<ShippingRate[]>>;
3675
+ snapshot(team: string, data: CheckoutSnapshotRequest): Promise<IAppResponse<CheckoutSnapshot>>;
3676
+ };
3677
+ };
3678
+ orders: {
3679
+ create(data: {
3680
+ team: string;
3681
+ snapshotId?: string;
3682
+ snapshotAccessToken?: string;
3683
+ guest?: GuestBuyer;
3684
+ idempotencyKey?: string;
3685
+ notes?: string;
3686
+ sendConfirmation?: boolean;
3687
+ }): Promise<IAppResponse<Order>>;
3688
+ pay(id: string, provider?: PaymentProvider, accessToken?: string): Promise<IAppResponse<{
3689
+ url: string;
3690
+ }>>;
3691
+ };
3692
+ };
3693
+ type CreateEmptyGuestCheckoutOptions = {
3694
+ country?: string;
3695
+ fulfillmentMethod?: FulfillmentMethod;
3696
+ };
3697
+ declare const createEmptyGuestCheckoutState: <TCart = GuestCheckoutCartItem[]>(options?: CreateEmptyGuestCheckoutOptions) => GuestCheckoutState<TCart>;
3698
+ declare const toGuestCheckoutDraft: <TCart>(state: GuestCheckoutState<TCart>) => GuestCheckoutDraft<TCart>;
3699
+ declare const assertGuestCheckoutReady: (state: GuestCheckoutState, pickupLocationIds?: number[]) => void;
3700
+ declare const buildGuestCheckoutSnapshotRequest: (state: GuestCheckoutState, options?: {
3701
+ shippingRates?: ShippingRate[];
3702
+ pickupLocationIds?: number[];
3703
+ }) => CheckoutSnapshotRequest;
3704
+ type GuestCheckoutSnapshotResult = {
3705
+ snapshot: CheckoutSnapshot & {
3706
+ accessToken: string;
3707
+ };
3708
+ shippingRates: ShippingRate[];
3709
+ shippingRateId: number | null;
3710
+ };
3711
+ declare function createGuestCheckoutSnapshot(options: {
3712
+ client: GuestCheckoutClient;
3713
+ team: string;
3714
+ state: GuestCheckoutState;
3715
+ pickupLocationIds?: number[];
3716
+ shippingRates?: ShippingRate[];
3717
+ }): Promise<GuestCheckoutSnapshotResult>;
3718
+ type PlaceGuestCheckoutOrderResult = {
3719
+ order: Order;
3720
+ accessToken: string | null; /** Payment provider redirect URL from `orders.pay`. Never the JoAi thank-you page. */
3721
+ paymentUrl: string | null;
3722
+ };
3723
+ /**
3724
+ * Places a guest order from a checkout snapshot and optionally starts payment.
3725
+ *
3726
+ * The client must already carry team context (e.g. `createClient({ team })` → `X-Team`).
3727
+ * Body `team` alone is not enough for `orders.create`.
3728
+ *
3729
+ * When `pay` is enabled (default), `paymentUrl` is only set from a successful `orders.pay`
3730
+ * response. `order.paymentUrl` from create is the JoAi thank-you URL and must not be used
3731
+ * as a gateway redirect.
3732
+ */
3733
+ declare function placeGuestCheckoutOrder(options: {
3734
+ client: GuestCheckoutClient;
3735
+ team: string;
3736
+ snapshot: Pick<CheckoutSnapshot, 'id' | 'expiresAt'> & {
3737
+ accessToken: string;
3738
+ };
3739
+ guest: GuestBuyer;
3740
+ acceptedTerms?: boolean;
3741
+ notes?: string;
3742
+ idempotencyKey?: string;
3743
+ pay?: boolean;
3744
+ }): Promise<PlaceGuestCheckoutOrderResult>;
3745
+ declare const isGuestCheckoutError: (error: unknown) => error is GuestCheckoutError;
3746
+ //#endregion
3610
3747
  //#region src/commerce/index.d.ts
3611
3748
  declare class CommerceResource {
3612
3749
  readonly checkout: CheckoutResource;
@@ -4563,7 +4700,7 @@ declare class OrdersResource {
4563
4700
  source?: 'kiosk';
4564
4701
  context?: OrderContext;
4565
4702
  linkVariationId?: string;
4566
- priceMode?: string;
4703
+ priceMode?: OrderPriceMode;
4567
4704
  type?: OrderType;
4568
4705
  sendConfirmation?: boolean;
4569
4706
  invoiceDate?: string;
@@ -4589,6 +4726,7 @@ declare class OrdersResource {
4589
4726
  guest?: {
4590
4727
  name: string;
4591
4728
  email: string;
4729
+ phone?: string;
4592
4730
  };
4593
4731
  }): Promise<IAppResponse<Order>>;
4594
4732
  update(id: string, data: {
@@ -4597,6 +4735,7 @@ declare class OrdersResource {
4597
4735
  serviceDate?: string;
4598
4736
  type?: OrderType;
4599
4737
  invoiceContactId?: string | null;
4738
+ priceMode?: OrderPriceMode;
4600
4739
  }): Promise<IAppResponse<Order>>;
4601
4740
  convertToOrder(id: string): Promise<IAppResponse<Order>>;
4602
4741
  delete(id: string): Promise<IAppResponse<void>>;
@@ -4801,10 +4940,13 @@ declare class SitesResource {
4801
4940
  constructor(http: IHttpService);
4802
4941
  brands(): Promise<IAppResponse<SiteBrand[]>>;
4803
4942
  listMine(teamSlug: string): Promise<IAppResponse<Site[]>>;
4804
- create(teamSlug: string, slug: string, data?: {
4943
+ create(teamSlug: string, data: {
4944
+ name: string;
4945
+ url?: string | null;
4805
4946
  contactId?: string | null;
4806
4947
  metricsSource?: string | null;
4807
4948
  metricsResource?: string | null;
4949
+ monthlyReport?: boolean;
4808
4950
  }): Promise<IAppResponse<Site>>;
4809
4951
  provision(teamSlug: string, brandSlug: string, data?: {
4810
4952
  settings?: Record<string, unknown>;
@@ -4815,6 +4957,8 @@ declare class SitesResource {
4815
4957
  customDomain?: string | null;
4816
4958
  enabled?: boolean;
4817
4959
  modules?: string[];
4960
+ name?: string | null;
4961
+ url?: string | null;
4818
4962
  contactId?: string | null;
4819
4963
  metricsSource?: string | null;
4820
4964
  metricsResource?: string | null;
@@ -5077,6 +5221,7 @@ declare class AutomationsResource {
5077
5221
  private readonly http;
5078
5222
  constructor(http: IHttpService);
5079
5223
  list(): Promise<IAppResponse<Automation[]>>;
5224
+ stats(): Promise<IAppResponse<AutomationStats>>;
5080
5225
  get(id: string): Promise<IAppResponse<Automation>>;
5081
5226
  create(payload: AutomationCreatePayload): Promise<IAppResponse<Automation>>;
5082
5227
  update(id: string, payload: AutomationUpdatePayload): Promise<IAppResponse<Automation>>;
@@ -5508,4 +5653,4 @@ declare class DistributionResource {
5508
5653
  private fetchDistribution;
5509
5654
  }
5510
5655
  //#endregion
5511
- export { AddressesResource, AgentsResource, AlertsResource, ApiTokensResource, AppointmentsResource, type AttachedMedia, type AuthConfirmCodeRequest, type AuthConfirmCodeResponse, type AuthNativeSessionResponse, type AuthPortalSessionResponse, AuthResource, type AuthSendCodeRequest, AutomationsResource, type BackendWarp, type BackendWarpBrand, BillingResource, BlueprintsResource, type CacheConfig, CachedHttpService, CampaignsResource, CardsResource, CartsResource, ChangelogResource, CharactersResource, CheckoutResource, CommerceResource, ContactsResource, ContentResource, ContractsResource, type CreateHookPayload, type CreateInboundHookPayload, type CreateInternalHookPayload, type CreateWarpLinkedHookPayload, type CreateWebHookPayload, DeskResource, DistributionResource, DocumentsResource, ElementsResource, EntitiesResource, FlowsResource, type FulfillmentLocationInput, FulfillmentsResource, GoalsResource, type GuestBuyer, type GuestCheckoutDraft, type GuestCommerceStorageOptions, type GuestOrderAccess, type Hook, type HookSample, type HookTrigger, type HookTriggerCondition, type HookTriggerInput, HooksResource, IngestionsResource, InquiriesResource, IntegrationsResource, IntentsResource, ItemsResource, JoAiClient, type JoAiClientConfig, KvResource, LinksResource, LoyaltyResource, McpResource, type MediaUploadType, MeetingsResource, MemoriesResource, MessagesResource, MetricsResource, MissionsResource, NotificationsResource, OfficeResource, type OpenPortalSessionOptions, type OpeningHoursEntry, type OpeningHoursFormatOptions, OrdersResource, PersonaResource, type PlaceCheckoutOrderRequest, type Product, type ProductVariation, ProductsResource, ProjectsResource, RemindersResource, ReturnsResource, SegmentsResource, ServicesResource, type ShippingRateInput, ShippingResource, type ShippingZoneInput, ShortcutsResource, SitesResource, SkillsResource, StatsResource, StoreResource, SubscriptionsResource, SwarmsResource, TagsResource, TasksResource, type TeamInviteInfo, TeamsResource, UpdatesResource, UpgradesResource, UsersResource, VoiceResource, WalletsResource, WarpsResource, type WebHookTriggerEvent, WorkspaceResource, completePortalSession, createClient, createGuestCommerceStorage, formatOpeningHours, getAuthFragmentToken, isAllowedRedirectUrl, isPortalCallbackUrl, openPortalSession, sanitizePortalCallbackUrl };
5656
+ export { AddressesResource, AgentsResource, AlertsResource, ApiTokensResource, AppointmentsResource, type AttachedMedia, type AuthConfirmCodeRequest, type AuthConfirmCodeResponse, type AuthNativeSessionResponse, type AuthPortalSessionResponse, AuthResource, type AuthSendCodeRequest, AutomationsResource, type BackendWarp, type BackendWarpBrand, BillingResource, BlueprintsResource, type CacheConfig, CachedHttpService, CampaignsResource, CardsResource, CartsResource, ChangelogResource, CharactersResource, CheckoutResource, CommerceResource, ContactsResource, ContentResource, ContractsResource, type CreateEmptyGuestCheckoutOptions, type CreateHookPayload, type CreateInboundHookPayload, type CreateInternalHookPayload, type CreateWarpLinkedHookPayload, type CreateWebHookPayload, DeskResource, DistributionResource, DocumentsResource, ElementsResource, EntitiesResource, FlowsResource, type FulfillmentLocationInput, FulfillmentsResource, GoalsResource, type GuestBuyer, type GuestCheckoutCartItem, type GuestCheckoutClient, type GuestCheckoutDraft, GuestCheckoutError, type GuestCheckoutErrorCode, type GuestCheckoutSnapshotResult, type GuestCheckoutState, type GuestCommerceStorageOptions, type GuestOrderAccess, type Hook, type HookSample, type HookTrigger, type HookTriggerCondition, type HookTriggerInput, HooksResource, IngestionsResource, InquiriesResource, IntegrationsResource, IntentsResource, ItemsResource, JoAiClient, type JoAiClientConfig, KvResource, LinksResource, LoyaltyResource, McpResource, type MediaUploadType, MeetingsResource, MemoriesResource, MessagesResource, MetricsResource, MissionsResource, NotificationsResource, OfficeResource, type OpenPortalSessionOptions, type OpeningHoursEntry, type OpeningHoursFormatOptions, OrdersResource, PersonaResource, type PlaceCheckoutOrderRequest, type PlaceGuestCheckoutOrderResult, type Product, type ProductVariation, ProductsResource, ProjectsResource, RemindersResource, ReturnsResource, SegmentsResource, ServicesResource, type ShippingRateInput, ShippingResource, type ShippingZoneInput, ShortcutsResource, SitesResource, SkillsResource, StatsResource, StoreResource, SubscriptionsResource, SwarmsResource, TagsResource, TasksResource, type TeamInviteInfo, TeamsResource, UpdatesResource, UpgradesResource, UsersResource, VoiceResource, WalletsResource, WarpsResource, type WebHookTriggerEvent, WorkspaceResource, assertGuestCheckoutReady, buildGuestCheckoutSnapshotRequest, completePortalSession, createClient, createEmptyGuestCheckoutState, createGuestCheckoutSnapshot, createGuestCommerceStorage, formatOpeningHours, getAuthFragmentToken, isAllowedRedirectUrl, isGuestCheckoutError, isPortalCallbackUrl, openPortalSession, placeGuestCheckoutOrder, sanitizePortalCallbackUrl, toGuestCheckoutDraft };
package/dist/index.mjs CHANGED
@@ -110,6 +110,37 @@ var HttpService = class {
110
110
  };
111
111
  }
112
112
  };
113
+ const OUTBOUND_CHANNELS = [
114
+ {
115
+ id: "email",
116
+ supportsHtml: true,
117
+ requiresSubject: true,
118
+ settingsKey: "email_provider"
119
+ },
120
+ {
121
+ id: "whatsapp",
122
+ supportsHtml: false,
123
+ requiresSubject: false
124
+ },
125
+ {
126
+ id: "whatsapp-personal",
127
+ supportsHtml: false,
128
+ requiresSubject: false
129
+ },
130
+ {
131
+ id: "sms",
132
+ supportsHtml: false,
133
+ requiresSubject: false
134
+ },
135
+ {
136
+ id: "push",
137
+ supportsHtml: false,
138
+ requiresSubject: true
139
+ }
140
+ ];
141
+ const AUTOMATION_SEND_CHANNELS = OUTBOUND_CHANNELS.filter((channel) => channel.id === "email" || channel.id === "whatsapp-personal");
142
+ OUTBOUND_CHANNELS.map((channel) => channel.id).filter((id) => id !== "whatsapp-personal");
143
+ AUTOMATION_SEND_CHANNELS[0];
113
144
  Object.values({
114
145
  Billing: "billing",
115
146
  Shipping: "shipping"
@@ -138,6 +169,7 @@ Object.values({
138
169
  Received: "received",
139
170
  Closed: "closed"
140
171
  });
172
+ const isCompleteAddressInput = (address) => Boolean(address.name.trim() && address.addressOne.trim() && address.city.trim() && address.zipCode.trim() && address.country.trim());
141
173
  Object.values({
142
174
  Board: "board",
143
175
  Shop: "shop",
@@ -151,6 +183,7 @@ Object.values({
151
183
  Heartbeats: "heartbeats",
152
184
  Wallets: "wallets",
153
185
  Campaigns: "campaigns",
186
+ Automations: "automations",
154
187
  News: "news",
155
188
  Sites: "sites",
156
189
  Contracts: "contracts",
@@ -505,6 +538,171 @@ function createGuestCommerceStorage(options) {
505
538
  };
506
539
  }
507
540
  //#endregion
541
+ //#region src/commerce/guestCheckout.ts
542
+ var GuestCheckoutError = class extends Error {
543
+ constructor(code) {
544
+ super(code);
545
+ this.code = code;
546
+ this.name = "GuestCheckoutError";
547
+ }
548
+ };
549
+ const createEmptyGuestCheckoutState = (options = {}) => ({
550
+ cart: [],
551
+ identity: {
552
+ name: "",
553
+ email: "",
554
+ phone: ""
555
+ },
556
+ fulfillmentMethod: options.fulfillmentMethod ?? "shipping",
557
+ address: {
558
+ name: "",
559
+ addressOne: "",
560
+ city: "",
561
+ zipCode: "",
562
+ country: options.country ?? "AT",
563
+ phone: ""
564
+ },
565
+ shippingRateId: null,
566
+ fulfillmentLocationId: null
567
+ });
568
+ const toGuestCheckoutDraft = (state) => ({
569
+ cart: state.cart,
570
+ fulfillmentMethod: state.fulfillmentMethod,
571
+ shippingRateId: state.shippingRateId,
572
+ fulfillmentLocationId: state.fulfillmentLocationId
573
+ });
574
+ const assertGuestCheckoutReady = (state, pickupLocationIds = []) => {
575
+ if (!state.cart.length) throw new GuestCheckoutError("empty_cart");
576
+ if (!state.identity.name.trim() || !state.identity.email.trim()) throw new GuestCheckoutError("missing_identity");
577
+ if (state.fulfillmentMethod === "pickup" && !state.identity.phone?.trim()) throw new GuestCheckoutError("missing_pickup_phone");
578
+ const address = {
579
+ ...state.address,
580
+ name: state.identity.name
581
+ };
582
+ if (state.fulfillmentMethod === "shipping" && !isCompleteAddressInput(address)) throw new GuestCheckoutError("incomplete_shipping_address");
583
+ if (state.fulfillmentMethod === "pickup" && !state.fulfillmentLocationId && !pickupLocationIds[0]) throw new GuestCheckoutError("pickup_unavailable");
584
+ };
585
+ const buildGuestCheckoutSnapshotRequest = (state, options = {}) => {
586
+ assertGuestCheckoutReady(state, options.pickupLocationIds ?? []);
587
+ const items = state.cart.map(({ id, type, quantity }) => ({
588
+ id,
589
+ type,
590
+ quantity
591
+ }));
592
+ const address = {
593
+ ...state.address,
594
+ name: state.identity.name
595
+ };
596
+ if (state.fulfillmentMethod === "shipping") {
597
+ const rates = options.shippingRates ?? [];
598
+ const rate = state.shippingRateId == null ? rates[0] : rates.find((item) => item.id === state.shippingRateId);
599
+ if (!rate) throw new GuestCheckoutError("missing_shipping_rate");
600
+ return {
601
+ fulfillmentMethod: "shipping",
602
+ items,
603
+ billingAddress: {
604
+ ...address,
605
+ type: "billing"
606
+ },
607
+ shippingAddress: {
608
+ ...address,
609
+ type: "shipping"
610
+ },
611
+ shippingRateId: rate.id
612
+ };
613
+ }
614
+ return {
615
+ fulfillmentMethod: "pickup",
616
+ items,
617
+ fulfillmentLocationId: state.fulfillmentLocationId || options.pickupLocationIds?.[0] || null
618
+ };
619
+ };
620
+ async function createGuestCheckoutSnapshot(options) {
621
+ const { client, team, state } = options;
622
+ const items = state.cart.map(({ id, type, quantity }) => ({
623
+ id,
624
+ type,
625
+ quantity
626
+ }));
627
+ let shippingRates = options.shippingRates ?? [];
628
+ if (state.fulfillmentMethod === "shipping" && !options.shippingRates) {
629
+ const address = {
630
+ ...state.address,
631
+ name: state.identity.name
632
+ };
633
+ const ratesResponse = await client.commerce.checkout.shippingRates(team, {
634
+ address: {
635
+ country: address.country,
636
+ zipCode: address.zipCode
637
+ },
638
+ items
639
+ });
640
+ if (!ratesResponse.ok || !Array.isArray(ratesResponse.data)) throw new GuestCheckoutError("rates_failed");
641
+ shippingRates = ratesResponse.data;
642
+ }
643
+ const snapshotRequest = buildGuestCheckoutSnapshotRequest(state, {
644
+ shippingRates,
645
+ pickupLocationIds: options.pickupLocationIds
646
+ });
647
+ const snapshot = await client.commerce.checkout.snapshot(team, snapshotRequest);
648
+ if (!snapshot.ok || !snapshot.data?.id || !snapshot.data.accessToken) throw new GuestCheckoutError("snapshot_failed");
649
+ return {
650
+ snapshot: {
651
+ ...snapshot.data,
652
+ accessToken: snapshot.data.accessToken
653
+ },
654
+ shippingRates,
655
+ shippingRateId: typeof snapshotRequest.shippingRateId === "number" ? snapshotRequest.shippingRateId : null
656
+ };
657
+ }
658
+ /**
659
+ * Places a guest order from a checkout snapshot and optionally starts payment.
660
+ *
661
+ * The client must already carry team context (e.g. `createClient({ team })` → `X-Team`).
662
+ * Body `team` alone is not enough for `orders.create`.
663
+ *
664
+ * When `pay` is enabled (default), `paymentUrl` is only set from a successful `orders.pay`
665
+ * response. `order.paymentUrl` from create is the JoAi thank-you URL and must not be used
666
+ * as a gateway redirect.
667
+ */
668
+ async function placeGuestCheckoutOrder(options) {
669
+ if (!options.acceptedTerms) throw new GuestCheckoutError("terms_required");
670
+ const expiresAt = new Date(options.snapshot.expiresAt).getTime();
671
+ if (!Number.isFinite(expiresAt) || expiresAt <= Date.now()) throw new GuestCheckoutError("review_expired");
672
+ const order = await options.client.orders.create({
673
+ team: options.team,
674
+ snapshotId: options.snapshot.id,
675
+ snapshotAccessToken: options.snapshot.accessToken,
676
+ guest: options.guest,
677
+ idempotencyKey: options.idempotencyKey ?? crypto.randomUUID(),
678
+ notes: options.notes,
679
+ sendConfirmation: true
680
+ });
681
+ if (!order.ok || !order.data?.id) throw new GuestCheckoutError("order_failed");
682
+ const accessToken = typeof order.meta?.orderAccessToken === "string" ? order.meta.orderAccessToken : null;
683
+ if (options.pay === false) return {
684
+ order: order.data,
685
+ accessToken,
686
+ paymentUrl: null
687
+ };
688
+ if (!accessToken) throw new GuestCheckoutError("payment_failed");
689
+ const payment = await options.client.orders.pay(order.data.id, void 0, accessToken);
690
+ if (!payment.ok || !payment.data?.url) return {
691
+ order: order.data,
692
+ accessToken,
693
+ paymentUrl: null
694
+ };
695
+ return {
696
+ order: order.data,
697
+ accessToken,
698
+ paymentUrl: payment.data.url
699
+ };
700
+ }
701
+ const isGuestCheckoutError = (error) => {
702
+ if (error instanceof GuestCheckoutError) return true;
703
+ return typeof error === "object" && error !== null && error.name === "GuestCheckoutError" && typeof error.code === "string";
704
+ };
705
+ //#endregion
508
706
  //#region src/commerce/index.ts
509
707
  var CommerceResource = class {
510
708
  constructor(http) {
@@ -1921,7 +2119,7 @@ var OrdersResource = class {
1921
2119
  return this.http.get(`orders/${id}`, orderAccessHeaders(accessToken));
1922
2120
  }
1923
2121
  create(data) {
1924
- return this.http.post("orders", data);
2122
+ return this.http.post("orders", data, { headers: { "X-Team": data.team } });
1925
2123
  }
1926
2124
  update(id, data) {
1927
2125
  return this.http.put(`orders/${id}`, data);
@@ -2175,10 +2373,9 @@ var SitesResource = class {
2175
2373
  listMine(teamSlug) {
2176
2374
  return this.http.get(`sites/mine?team=${encodeURIComponent(teamSlug)}`);
2177
2375
  }
2178
- create(teamSlug, slug, data) {
2376
+ create(teamSlug, data) {
2179
2377
  return this.http.post("sites", {
2180
2378
  team: teamSlug,
2181
- slug,
2182
2379
  ...data
2183
2380
  });
2184
2381
  }
@@ -2611,6 +2808,9 @@ var AutomationsResource = class {
2611
2808
  list() {
2612
2809
  return this.http.get("automations");
2613
2810
  }
2811
+ stats() {
2812
+ return this.http.get("automations/stats");
2813
+ }
2614
2814
  get(id) {
2615
2815
  return this.http.get(`automations/${id}`);
2616
2816
  }
@@ -3355,4 +3555,4 @@ var DistributionResource = class {
3355
3555
  }
3356
3556
  };
3357
3557
  //#endregion
3358
- export { AddressesResource, AgentsResource, AlertsResource, ApiTokensResource, AppointmentsResource, AuthResource, AutomationsResource, BillingResource, BlueprintsResource, CachedHttpService, CampaignsResource, CardsResource, CartsResource, ChangelogResource, CharactersResource, CheckoutResource, CommerceResource, ContactsResource, ContentResource, ContractsResource, DeskResource, DistributionResource, DocumentsResource, ElementsResource, EntitiesResource, FlowsResource, FulfillmentsResource, GoalsResource, HooksResource, IngestionsResource, InquiriesResource, IntegrationsResource, IntentsResource, ItemsResource, JoAiClient, KvResource, LinksResource, LoyaltyResource, McpResource, MeetingsResource, MemoriesResource, MessagesResource, MetricsResource, MissionsResource, NotificationsResource, OfficeResource, OrdersResource, PersonaResource, ProductsResource, ProjectsResource, RemindersResource, ReturnsResource, SegmentsResource, ServicesResource, ShippingResource, ShortcutsResource, SitesResource, SkillsResource, StatsResource, StoreResource, SubscriptionsResource, SwarmsResource, TagsResource, TasksResource, TeamsResource, UpdatesResource, UpgradesResource, UsersResource, VoiceResource, WalletsResource, WarpsResource, WorkspaceResource, completePortalSession, createClient, createGuestCommerceStorage, formatOpeningHours, getAuthFragmentToken, isAllowedRedirectUrl, isPortalCallbackUrl, openPortalSession, sanitizePortalCallbackUrl };
3558
+ export { AddressesResource, AgentsResource, AlertsResource, ApiTokensResource, AppointmentsResource, AuthResource, AutomationsResource, BillingResource, BlueprintsResource, CachedHttpService, CampaignsResource, CardsResource, CartsResource, ChangelogResource, CharactersResource, CheckoutResource, CommerceResource, ContactsResource, ContentResource, ContractsResource, DeskResource, DistributionResource, DocumentsResource, ElementsResource, EntitiesResource, FlowsResource, FulfillmentsResource, GoalsResource, GuestCheckoutError, HooksResource, IngestionsResource, InquiriesResource, IntegrationsResource, IntentsResource, ItemsResource, JoAiClient, KvResource, LinksResource, LoyaltyResource, McpResource, MeetingsResource, MemoriesResource, MessagesResource, MetricsResource, MissionsResource, NotificationsResource, OfficeResource, OrdersResource, PersonaResource, ProductsResource, ProjectsResource, RemindersResource, ReturnsResource, SegmentsResource, ServicesResource, ShippingResource, ShortcutsResource, SitesResource, SkillsResource, StatsResource, StoreResource, SubscriptionsResource, SwarmsResource, TagsResource, TasksResource, TeamsResource, UpdatesResource, UpgradesResource, UsersResource, VoiceResource, WalletsResource, WarpsResource, WorkspaceResource, assertGuestCheckoutReady, buildGuestCheckoutSnapshotRequest, completePortalSession, createClient, createEmptyGuestCheckoutState, createGuestCheckoutSnapshot, createGuestCommerceStorage, formatOpeningHours, getAuthFragmentToken, isAllowedRedirectUrl, isGuestCheckoutError, isPortalCallbackUrl, openPortalSession, placeGuestCheckoutOrder, sanitizePortalCallbackUrl, toGuestCheckoutDraft };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@joai/sdk",
3
- "version": "4.7.0",
3
+ "version": "4.8.0",
4
4
  "description": "JoAi public API SDK — build with your AI agents",
5
5
  "license": "MIT",
6
6
  "type": "module",