@final-commerce/command-frame 0.12.0 → 0.13.1-preprod.1

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 (91) hide show
  1. package/dist/CommonTypes.d.ts +18 -1
  2. package/dist/actions/assign-order-user/mock.js +9 -9
  3. package/dist/actions/assign-order-user/types.d.ts +14 -3
  4. package/dist/actions/attach-checkout-contact/action.d.ts +6 -0
  5. package/dist/actions/attach-checkout-contact/action.js +8 -0
  6. package/dist/actions/attach-checkout-contact/mock.d.ts +15 -0
  7. package/dist/actions/attach-checkout-contact/mock.js +22 -0
  8. package/dist/actions/attach-checkout-contact/types.d.ts +35 -0
  9. package/dist/actions/attach-checkout-contact/types.js +16 -0
  10. package/dist/actions/get-address-options/action.d.ts +6 -0
  11. package/dist/actions/get-address-options/action.js +8 -0
  12. package/dist/actions/get-address-options/mock.d.ts +3 -0
  13. package/dist/actions/get-address-options/mock.js +15 -0
  14. package/dist/actions/get-address-options/types.d.ts +25 -0
  15. package/dist/actions/get-address-options/types.js +8 -0
  16. package/dist/actions/get-checkout-status/action.d.ts +6 -0
  17. package/dist/actions/get-checkout-status/action.js +8 -0
  18. package/dist/actions/get-checkout-status/mock.d.ts +3 -0
  19. package/dist/actions/get-checkout-status/mock.js +11 -0
  20. package/dist/actions/get-checkout-status/types.d.ts +27 -0
  21. package/dist/actions/get-checkout-status/types.js +12 -0
  22. package/dist/actions/get-orders/mock.js +9 -6
  23. package/dist/actions/get-orders/types.d.ts +8 -2
  24. package/dist/actions/get-outlets/action.js +2 -2
  25. package/dist/actions/get-outlets/mock.d.ts +12 -0
  26. package/dist/actions/get-outlets/mock.js +28 -4
  27. package/dist/actions/get-outlets/types.d.ts +19 -1
  28. package/dist/actions/get-product-modifier-selections/mock.js +7 -0
  29. package/dist/actions/get-product-modifier-selections/types.d.ts +4 -0
  30. package/dist/actions/get-products/types.d.ts +8 -8
  31. package/dist/actions/get-refund-plan/mockRows.js +1 -1
  32. package/dist/actions/get-refund-plan/types.d.ts +9 -6
  33. package/dist/actions/get-remaining-refundable-quantities/mock.js +1 -0
  34. package/dist/actions/get-remaining-refundable-quantities/types.d.ts +5 -0
  35. package/dist/actions/get-shipping-options/action.d.ts +6 -0
  36. package/dist/actions/get-shipping-options/action.js +8 -0
  37. package/dist/actions/get-shipping-options/mock.d.ts +3 -0
  38. package/dist/actions/get-shipping-options/mock.js +15 -0
  39. package/dist/actions/get-shipping-options/types.d.ts +43 -0
  40. package/dist/actions/get-shipping-options/types.js +1 -0
  41. package/dist/actions/process-partial-refund/types.d.ts +1 -1
  42. package/dist/actions/resume-checkout/action.d.ts +6 -0
  43. package/dist/actions/resume-checkout/action.js +8 -0
  44. package/dist/actions/resume-checkout/mock.d.ts +16 -0
  45. package/dist/actions/resume-checkout/mock.js +51 -0
  46. package/dist/actions/resume-checkout/types.d.ts +59 -0
  47. package/dist/actions/resume-checkout/types.js +13 -0
  48. package/dist/actions/select-shipping-option/action.d.ts +6 -0
  49. package/dist/actions/select-shipping-option/action.js +8 -0
  50. package/dist/actions/select-shipping-option/mock.d.ts +3 -0
  51. package/dist/actions/select-shipping-option/mock.js +31 -0
  52. package/dist/actions/select-shipping-option/types.d.ts +15 -0
  53. package/dist/actions/select-shipping-option/types.js +1 -0
  54. package/dist/actions/set-order-address/action.d.ts +6 -0
  55. package/dist/actions/set-order-address/action.js +8 -0
  56. package/dist/actions/set-order-address/mock.d.ts +7 -0
  57. package/dist/actions/set-order-address/mock.js +29 -0
  58. package/dist/actions/set-order-address/types.d.ts +19 -0
  59. package/dist/actions/set-order-address/types.js +1 -0
  60. package/dist/actions/set-outlet/action.d.ts +6 -0
  61. package/dist/actions/set-outlet/action.js +8 -0
  62. package/dist/actions/set-outlet/mock.d.ts +13 -0
  63. package/dist/actions/set-outlet/mock.js +24 -0
  64. package/dist/actions/set-outlet/types.d.ts +31 -0
  65. package/dist/actions/set-outlet/types.js +21 -0
  66. package/dist/actions/start-checkout/action.d.ts +6 -0
  67. package/dist/actions/start-checkout/action.js +8 -0
  68. package/dist/actions/start-checkout/mock.d.ts +16 -0
  69. package/dist/actions/start-checkout/mock.js +80 -0
  70. package/dist/actions/start-checkout/types.d.ts +90 -0
  71. package/dist/actions/start-checkout/types.js +10 -0
  72. package/dist/demo/shipping.d.ts +8 -0
  73. package/dist/demo/shipping.js +69 -0
  74. package/dist/index.d.ts +21 -1
  75. package/dist/index.js +19 -0
  76. package/dist/projects/render/mocks.js +20 -0
  77. package/dist/projects/render/types.d.ts +23 -1
  78. package/dist/pubsub/topics/checkout/checkout-started/types.d.ts +26 -0
  79. package/dist/pubsub/topics/checkout/checkout-started/types.js +1 -0
  80. package/dist/pubsub/topics/checkout/index.d.ts +7 -0
  81. package/dist/pubsub/topics/checkout/index.js +28 -0
  82. package/dist/pubsub/topics/checkout/payment-completed/types.d.ts +31 -0
  83. package/dist/pubsub/topics/checkout/payment-completed/types.js +1 -0
  84. package/dist/pubsub/topics/checkout/payment-failed/types.d.ts +23 -0
  85. package/dist/pubsub/topics/checkout/payment-failed/types.js +1 -0
  86. package/dist/pubsub/topics/checkout/types.d.ts +12 -0
  87. package/dist/pubsub/topics/checkout/types.js +8 -0
  88. package/dist/pubsub/topics/index.d.ts +18 -17
  89. package/dist/pubsub/topics/index.js +18 -17
  90. package/dist/pubsub/topics/types.d.ts +8 -0
  91. package/package.json +2 -2
@@ -0,0 +1,80 @@
1
+ import { MOCK_CART, MOCK_COMPANY, mockPublishEvent } from '../../demo/database';
2
+ /**
3
+ * Standalone mock of the storefront checkout.
4
+ *
5
+ * It mirrors the REFUSALS of the real command (empty cart,
6
+ * container not on the page) in the same order, because those are what a
7
+ * builder actually hits first — a mock that accepted anything would let a
8
+ * checkout screen look finished and fail on the published site.
9
+ *
10
+ * The mounted box is deliberately labelled as a mock. The real command mounts
11
+ * the provider's hosted card fields (iframes owned by the payment provider);
12
+ * nothing here takes a card number, and the placeholder must never look like
13
+ * it does. Its button publishes `payment-completed` so a flow's subscriber —
14
+ * the only way the outcome ever arrives — can be exercised in preview.
15
+ */
16
+ export const mockStartCheckout = async (params) => {
17
+ console.log('[Mock] startCheckout called', params);
18
+ if (!params)
19
+ throw new Error('Params required');
20
+ // No email check: contact is optional now, because checkout starts on arrival.
21
+ // Refusing here would make "start on arrival" fail in PREVIEW while working on
22
+ // the published site, which is the worst way for this to be wrong.
23
+ if (!params.container || typeof params.container !== 'string') {
24
+ throw new Error('startCheckout: container must be a CSS selector string (e.g. "#card-fields") — a DOM element cannot cross the command boundary');
25
+ }
26
+ const lineCount = (MOCK_CART.products?.length ?? 0) + (MOCK_CART.customSales?.length ?? 0);
27
+ if (!lineCount) {
28
+ throw new Error('startCheckout: cannot check out an empty cart');
29
+ }
30
+ // Resolved BEFORE the order is "created", exactly as the real command does:
31
+ // finding out the selector is wrong after an order exists would leave an
32
+ // unpaid order behind for a typo that cost nothing to catch first.
33
+ const container = typeof document === 'undefined' ? null : document.querySelector(params.container);
34
+ if (!container) {
35
+ throw new Error(`startCheckout: checkout container "${params.container}" was not found on the page`);
36
+ }
37
+ const serverTotal = Math.round(MOCK_CART.amountToBeCharged || MOCK_CART.total);
38
+ const currency = MOCK_COMPANY.settings?.currency ?? 'USD';
39
+ const suffix = String(Date.now()).slice(-6);
40
+ const order = {
41
+ orderId: `mock-order-${suffix}`,
42
+ receiptId: `ON-001-${suffix}`,
43
+ serverTotal,
44
+ currency,
45
+ paymentStatus: 'ready',
46
+ orderPassword: `mock-pw-${suffix}`,
47
+ };
48
+ mockPublishEvent('checkout', 'checkout-started', { ...order });
49
+ container.replaceChildren();
50
+ const box = document.createElement('div');
51
+ box.setAttribute('data-mock-checkout', 'true');
52
+ box.style.cssText =
53
+ 'border:1px dashed #9aa;border-radius:8px;padding:16px;font:14px system-ui,sans-serif;text-align:center;color:#334';
54
+ const label = document.createElement('div');
55
+ label.textContent = 'Mock payment fields — the published site shows the real hosted card fields here.';
56
+ label.style.cssText = 'margin-bottom:12px;opacity:.75';
57
+ const button = document.createElement('button');
58
+ button.type = 'button';
59
+ button.textContent = `Simulate paying ${(serverTotal / 100).toFixed(2)} ${currency}`;
60
+ button.style.cssText =
61
+ 'padding:10px 16px;border:0;border-radius:6px;background:#111;color:#fff;font-size:14px;cursor:pointer';
62
+ button.addEventListener('click', () => {
63
+ button.disabled = true;
64
+ // `Authorised` is what the real provider reports for a successful card
65
+ // entry. It is NOT settlement — see the checkout topic docs.
66
+ mockPublishEvent('checkout', 'payment-completed', {
67
+ orderId: order.orderId,
68
+ receiptId: order.receiptId,
69
+ resultCode: 'Authorised',
70
+ });
71
+ });
72
+ box.appendChild(label);
73
+ box.appendChild(button);
74
+ container.appendChild(box);
75
+ return {
76
+ success: true,
77
+ timestamp: new Date().toISOString(),
78
+ order,
79
+ };
80
+ };
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Guest contact for the order. There is no shopper account, so this is the only
3
+ * way to reach them — `email` is where the receipt goes and is required.
4
+ */
5
+ export interface StartCheckoutContact {
6
+ email: string;
7
+ name?: string;
8
+ phone?: string;
9
+ }
10
+ export interface StartCheckoutParams {
11
+ /**
12
+ * OPTIONAL, because checkout starts when the shopper ARRIVES rather than when
13
+ * they submit a form. The card fields cannot render without a payment session,
14
+ * a session needs a server-priced amount, and an amount needs an order — so the
15
+ * order has to exist before they have typed anything.
16
+ *
17
+ * Supply it afterwards with `attachCheckoutContact`, which re-sends the same
18
+ * idempotency key and so reaches the SAME order.
19
+ */
20
+ contact?: StartCheckoutContact;
21
+ /**
22
+ * CSS SELECTOR for the element the payment fields mount into, e.g.
23
+ * `'#card-fields'`. The element must already be in the DOM when this is
24
+ * called.
25
+ *
26
+ * A SELECTOR, NOT AN ELEMENT — and this is not a style preference. Command
27
+ * params cross a `postMessage` boundary, which serializes them with the
28
+ * structured clone algorithm; a DOM node is not cloneable, so passing
29
+ * `ref.current` throws `DataCloneError: HTMLDivElement object could not be
30
+ * cloned` before the command is ever sent. The string is resolved on the
31
+ * runtime's side against the same document the page rendered.
32
+ */
33
+ container: string;
34
+ /**
35
+ * Where the provider returns the shopper after a redirect payment method
36
+ * (bank apps, wallets). Defaults to the current URL.
37
+ *
38
+ * Must be HTTPS and on the SAME ORIGIN the storefront token was minted for;
39
+ * the server rejects anything else, since this URL is handed to a payment
40
+ * provider and an open redirect on a checkout is a phishing primitive.
41
+ */
42
+ returnUrl?: string;
43
+ /**
44
+ * Overrides the cart-derived idempotency key. Leave unset: the default is
45
+ * derived from the cart, which is what makes a shopper's double-tap on "Pay"
46
+ * return the SAME order instead of creating a second, abandoned one.
47
+ */
48
+ idempotencyKey?: string;
49
+ /** Defaults to the outlet the storefront booted against. */
50
+ outletId?: string;
51
+ /** Forwarded verbatim to the provider's Drop-in (`showPayButton`, `locale`, field styling, …). */
52
+ dropinConfiguration?: Record<string, unknown>;
53
+ }
54
+ /**
55
+ * The created order. Deliberately says nothing about money having moved — see
56
+ * `paymentStatus` and the `checkout` topic.
57
+ */
58
+ export interface StartCheckoutOrder {
59
+ orderId: string;
60
+ receiptId: string;
61
+ /** The SERVER-computed total in integer minor units — the only total that matters. */
62
+ serverTotal: number;
63
+ currency: string;
64
+ /**
65
+ * `ready` — the payment fields are mounted and the shopper can pay.
66
+ * `unavailable` — THE ORDER EXISTS but no payment could be started, so the
67
+ * shopper has NOT been charged. Never report this as a failed order.
68
+ */
69
+ paymentStatus: 'ready' | 'unavailable';
70
+ /**
71
+ * One-time password for reading this order back, returned only on the first
72
+ * create. It is the ONLY route to this order's status — the guest token
73
+ * grants order creation and deliberately not order reads — so a caller that
74
+ * drops it cannot check whether the payment settled.
75
+ */
76
+ orderPassword?: string;
77
+ }
78
+ export interface StartCheckoutResponse {
79
+ success: boolean;
80
+ timestamp: string;
81
+ order: StartCheckoutOrder;
82
+ }
83
+ /**
84
+ * Creates the server-priced order and mounts the provider's hosted card fields.
85
+ *
86
+ * RESOLVES WHEN THE SHOPPER *CAN* PAY, NOT WHEN THEY HAVE. The shopper has not
87
+ * typed a card yet when this returns. The outcome arrives on the `checkout`
88
+ * topic instead.
89
+ */
90
+ export type StartCheckout = (params: StartCheckoutParams) => Promise<StartCheckoutResponse>;
@@ -0,0 +1,10 @@
1
+ // Start Checkout Types
2
+ //
3
+ // The ONLINE counterpart of the POS tenders: a shopper on a published website
4
+ // pays for the current cart with their own card. Mirrors kaching's storefront
5
+ // `startCheckout` input and result. All money is integer MINOR currency units.
6
+ //
7
+ // This command is served ONLY by the storefront runtime (a published website).
8
+ // On a register it does not exist, exactly as the till tenders (`cashPayment`,
9
+ // `terminalPayment`, `tapToPayPayment`, `chargeMoto`) do not exist online.
10
+ export {};
@@ -0,0 +1,8 @@
1
+ import { type ShippingZoneRule } from '@final-commerce/common';
2
+ import type { ShippingOptionView } from '../actions/get-shipping-options/types';
3
+ export declare const MOCK_SHIPPING_ZONES: ShippingZoneRule[];
4
+ /** The demo cart's options, shaped like the runtime's answer. The mock runs as the website. */
5
+ export declare function mockShippingOptions(): {
6
+ resolution: import("@final-commerce/common").ShippingResolution;
7
+ options: ShippingOptionView[];
8
+ };
@@ -0,0 +1,69 @@
1
+ import { resolveShipping } from '@final-commerce/common';
2
+ import { MOCK_CART, MOCK_OUTLET_MAIN } from './database';
3
+ /*
4
+ * The demo store's Settings › Shipping, so a flow previewed against the mocks meets the real rules
5
+ * (common's `resolveShipping`) rather than a canned list: Canada $10 (free over $100) or Express,
6
+ * Quebec at $15, pickup at the demo store, and nowhere else.
7
+ */
8
+ export const MOCK_SHIPPING_ZONES = [
9
+ {
10
+ id: 'zone_canada',
11
+ kind: 'country',
12
+ places: [{ country: 'CA' }],
13
+ ships: true,
14
+ options: [
15
+ {
16
+ id: 'opt_standard',
17
+ type: 'ship',
18
+ name: 'Standard shipping',
19
+ price: 1000,
20
+ freeOver: 10000,
21
+ minDays: 3,
22
+ maxDays: 6,
23
+ channels: ['web', 'pos'],
24
+ },
25
+ { id: 'opt_express', type: 'ship', name: 'Express', price: 2000, minDays: 1, maxDays: 2, channels: ['web'] },
26
+ { id: 'opt_pickup', type: 'pickup', price: 0, channels: ['web'], outletId: MOCK_OUTLET_MAIN.id },
27
+ ],
28
+ },
29
+ {
30
+ id: 'zone_quebec',
31
+ kind: 'province',
32
+ places: [{ country: 'CA', province: 'QC' }],
33
+ ships: true,
34
+ options: [
35
+ {
36
+ id: 'opt_quebec',
37
+ type: 'ship',
38
+ name: 'Standard shipping',
39
+ price: 1500,
40
+ minDays: 4,
41
+ maxDays: 7,
42
+ channels: ['web', 'pos'],
43
+ },
44
+ ],
45
+ },
46
+ ];
47
+ const STORE_NAME = MOCK_OUTLET_MAIN.name ?? 'the store';
48
+ const money = (amount) => (amount === 0 ? 'Free' : `$${(amount / 100).toFixed(2)}`);
49
+ /** The demo cart's options, shaped like the runtime's answer. The mock runs as the website. */
50
+ export function mockShippingOptions() {
51
+ const resolution = resolveShipping({
52
+ zones: MOCK_SHIPPING_ZONES,
53
+ address: MOCK_CART.shippingAddress,
54
+ itemsTotal: MOCK_CART.subtotal,
55
+ channel: 'web',
56
+ });
57
+ const options = resolution.options.map((option) => ({
58
+ optionId: option.optionId,
59
+ type: option.type,
60
+ name: option.type === 'pickup' ? `Pickup at ${STORE_NAME}` : (option.name ?? ''),
61
+ amount: option.amount,
62
+ priceText: money(option.amount),
63
+ freeShippingHint: option.amountToFree ? `Add ${money(option.amountToFree)} more for free shipping` : null,
64
+ arrivalText: option.minDays != null ? `Arrives in ${option.minDays}–${option.maxDays} business days` : null,
65
+ pickup: option.type === 'pickup' ? { outletId: MOCK_OUTLET_MAIN.id, name: STORE_NAME, hours: [] } : null,
66
+ selected: MOCK_CART.shipping?.optionId === option.optionId,
67
+ }));
68
+ return { resolution, options };
69
+ }
package/dist/index.d.ts CHANGED
@@ -65,6 +65,15 @@ export declare const command: {
65
65
  readonly integrationPayment: import(".").IntegrationPayment;
66
66
  readonly createPaymentLink: import(".").CreatePaymentLink;
67
67
  readonly chargeMoto: import(".").ChargeMoto;
68
+ readonly startCheckout: import(".").StartCheckout;
69
+ readonly attachCheckoutContact: import(".").AttachCheckoutContact;
70
+ readonly getAddressOptions: import(".").GetAddressOptions;
71
+ readonly setOrderAddress: import(".").SetOrderAddress;
72
+ readonly getShippingOptions: import(".").GetShippingOptions;
73
+ readonly selectShippingOption: import(".").SelectShippingOption;
74
+ readonly setOutlet: import(".").SetOutlet;
75
+ readonly resumeCheckout: import(".").ResumeCheckout;
76
+ readonly getCheckoutStatus: import(".").GetCheckoutStatus;
68
77
  readonly getMotoConfig: import(".").GetMotoConfig;
69
78
  readonly addCustomerNote: import(".").AddCustomerNote;
70
79
  readonly removeCustomerNote: import(".").RemoveCustomerNote;
@@ -161,7 +170,7 @@ export type { AddProduct, AddProductParams, AddProductResponse } from './actions
161
170
  export type { EditProduct, EditProductParams, EditProductResponse } from './actions/edit-product/types';
162
171
  export type { EditProductVariants, EditProductVariantsParams, EditProductVariantsResponse, } from './actions/edit-product-variants/types';
163
172
  export type { DeleteProduct, DeleteProductParams, DeleteProductResponse } from './actions/delete-product/types';
164
- export type { GetOutlets, GetOutletsResponse } from './actions/get-outlets/types';
173
+ export type { GetOutlets, GetOutletsParams, GetOutletsResponse } from './actions/get-outlets/types';
165
174
  export type { GetStations, GetStationsParams, GetStationsResponse } from './actions/get-stations/types';
166
175
  export type { GetSmartGridLayout, GetSmartGridLayoutParams, GetSmartGridLayoutResponse, } from './actions/get-smart-grid-layout/types';
167
176
  export type { SaveSmartGridLayout, SaveSmartGridLayoutParams, SaveSmartGridLayoutResponse, } from './actions/save-smart-grid-layout/types';
@@ -223,6 +232,15 @@ export type { RedeemPayment, RedeemPaymentParams, RedeemPaymentResponse } from '
223
232
  export type { IntegrationPayment, IntegrationPaymentParams, IntegrationPaymentResponse, IntegrationEmvData, } from './actions/integration-payment/types';
224
233
  export type { CreatePaymentLink, CreatePaymentLinkParams, CreatePaymentLinkResponse, } from './actions/create-payment-link/types';
225
234
  export type { ChargeMoto, ChargeMotoParams, ChargeMotoResponse, ChargeMotoCardFields, } from './actions/charge-moto/types';
235
+ export type { StartCheckout, StartCheckoutParams, StartCheckoutResponse, StartCheckoutContact, StartCheckoutOrder, } from './actions/start-checkout/types';
236
+ export type { AttachCheckoutContact, AttachCheckoutContactParams, AttachCheckoutContactResponse, } from './actions/attach-checkout-contact/types';
237
+ export type { GetAddressOptions, GetAddressOptionsParams, GetAddressOptionsResponse, AddressCountryOption, AddressProvinceOption, } from './actions/get-address-options/types';
238
+ export type { SetOrderAddress, SetOrderAddressParams, SetOrderAddressResponse, OrderAddressType, } from './actions/set-order-address/types';
239
+ export type { GetShippingOptions, GetShippingOptionsResponse, ShippingOptionView, ShippingPickupView, } from './actions/get-shipping-options/types';
240
+ export type { SelectShippingOption, SelectShippingOptionParams, SelectShippingOptionResponse, } from './actions/select-shipping-option/types';
241
+ export type { SetOutlet, SetOutletParams, SetOutletResponse } from './actions/set-outlet/types';
242
+ export type { ResumeCheckout, ResumeCheckoutParams, ResumeCheckoutResponse, ResumeCheckoutResult, } from './actions/resume-checkout/types';
243
+ export type { GetCheckoutStatus, GetCheckoutStatusParams, GetCheckoutStatusResponse, CheckoutOrderStatus, CheckoutCancelReason, } from './actions/get-checkout-status/types';
226
244
  export type { GetMotoConfig, GetMotoConfigResponse, MotoUnavailableReason } from './actions/get-moto-config/types';
227
245
  export type { AddCustomerNote, AddCustomerNoteParams, AddCustomerNoteResponse, } from './actions/add-customer-note/types';
228
246
  export type { RemoveCustomerNote, RemoveCustomerNoteParams, RemoveCustomerNoteResponse, } from './actions/remove-customer-note/types';
@@ -280,6 +298,7 @@ export { refundsTopic } from './pubsub/topics/refunds';
280
298
  export { productsTopic } from './pubsub/topics/products';
281
299
  export { cartTopic } from './pubsub/topics/cart';
282
300
  export { paymentsTopic } from './pubsub/topics/payments';
301
+ export { checkoutTopic } from './pubsub/topics/checkout';
283
302
  export { splitPaymentsTopic } from './pubsub/topics/split-payments';
284
303
  export { customTablesTopic } from './pubsub/topics/custom-tables';
285
304
  export { printTopic } from './pubsub/topics/print';
@@ -307,6 +326,7 @@ export type { CategoryCreatedPayload, CategoryCreatedEvent, CategoryUpdatedPaylo
307
326
  export type { AttributeCreatedPayload, AttributeCreatedEvent, AttributeUpdatedPayload, AttributeUpdatedEvent, AttributesEventType, AttributesEventPayload, } from './pubsub/topics/attributes/types';
308
327
  export type { CartCreatedPayload, CartCustomerAssignedPayload, ProductAddedPayload, ProductDeletedPayload, CartDiscountAddedPayload, CartDiscountRemovedPayload, CartFeeAddedPayload, CartFeeRemovedPayload, ProductDiscountAddedPayload, ProductDiscountRemovedPayload, ProductFeeAddedPayload, ProductFeeRemovedPayload, ProductNoteAddedPayload, ProductNoteRemovedPayload, CartCreatedEvent, CartCustomerAssignedEvent, ProductAddedEvent, ProductDeletedEvent, CartDiscountAddedEvent, CartDiscountRemovedEvent, CartFeeAddedEvent, CartFeeRemovedEvent, ProductDiscountAddedEvent, ProductDiscountRemovedEvent, ProductFeeAddedEvent, ProductFeeRemovedEvent, ProductNoteAddedEvent, ProductNoteRemovedEvent, CartEventType, CartEventPayload, } from './pubsub/topics/cart/types';
309
328
  export type { PaymentDonePayload, PaymentErrPayload, PaymentDoneEvent, PaymentErrEvent, PaymentsEventType, PaymentsEventPayload, } from './pubsub/topics/payments/types';
329
+ export type { CheckoutStartedPayload, PaymentCompletedPayload, PaymentFailedPayload, CheckoutStartedEvent, PaymentCompletedEvent, PaymentFailedEvent, CheckoutEventType, CheckoutEventPayload, } from './pubsub/topics/checkout/types';
310
330
  export type { SplitPaymentUpdatedPayload, SplitPaymentUpdatedEvent, SplitPaymentsEventType, SplitPaymentsEventPayload, } from './pubsub/topics/split-payments/types';
311
331
  export type { RowCreatedPayload, RowUpdatedPayload, RowDeletedPayload, RowCreatedEvent, RowUpdatedEvent, RowDeletedEvent, CustomTablesEventType, CustomTablesEventPayload, } from './pubsub/topics/custom-tables/types';
312
332
  export type { PrintStartedPayload, PrintCompletedPayload, PrintErrorPayload, PrintStartedEvent, PrintCompletedEvent, PrintErrorEvent, PrintEventType, PrintEventPayload, } from './pubsub/topics/print/types';
package/dist/index.js CHANGED
@@ -65,6 +65,15 @@ import { redeemPayment } from './actions/redeem-payment/action';
65
65
  import { integrationPayment } from './actions/integration-payment/action';
66
66
  import { createPaymentLink } from './actions/create-payment-link/action';
67
67
  import { chargeMoto } from './actions/charge-moto/action';
68
+ import { startCheckout } from './actions/start-checkout/action';
69
+ import { attachCheckoutContact } from './actions/attach-checkout-contact/action';
70
+ import { getAddressOptions } from './actions/get-address-options/action';
71
+ import { setOrderAddress } from './actions/set-order-address/action';
72
+ import { getShippingOptions } from './actions/get-shipping-options/action';
73
+ import { selectShippingOption } from './actions/select-shipping-option/action';
74
+ import { setOutlet } from './actions/set-outlet/action';
75
+ import { resumeCheckout } from './actions/resume-checkout/action';
76
+ import { getCheckoutStatus } from './actions/get-checkout-status/action';
68
77
  import { getMotoConfig } from './actions/get-moto-config/action';
69
78
  // Customer Actions
70
79
  import { addCustomerNote } from './actions/add-customer-note/action';
@@ -225,6 +234,15 @@ export const command = {
225
234
  integrationPayment,
226
235
  createPaymentLink,
227
236
  chargeMoto,
237
+ startCheckout,
238
+ attachCheckoutContact,
239
+ getAddressOptions,
240
+ setOrderAddress,
241
+ getShippingOptions,
242
+ selectShippingOption,
243
+ setOutlet,
244
+ resumeCheckout,
245
+ getCheckoutStatus,
228
246
  getMotoConfig,
229
247
  // Customer Actions
230
248
  addCustomerNote,
@@ -336,6 +354,7 @@ export { refundsTopic } from './pubsub/topics/refunds';
336
354
  export { productsTopic } from './pubsub/topics/products';
337
355
  export { cartTopic } from './pubsub/topics/cart';
338
356
  export { paymentsTopic } from './pubsub/topics/payments';
357
+ export { checkoutTopic } from './pubsub/topics/checkout';
339
358
  export { splitPaymentsTopic } from './pubsub/topics/split-payments';
340
359
  export { customTablesTopic } from './pubsub/topics/custom-tables';
341
360
  export { printTopic } from './pubsub/topics/print';
@@ -38,6 +38,16 @@ import { mockRecordExternalPayment } from '../../actions/record-external-payment
38
38
  import { mockGetCashRoundingAmount } from '../../actions/get-cash-rounding-amount/mock';
39
39
  import { mockCreatePaymentLink } from '../../actions/create-payment-link/mock';
40
40
  import { mockChargeMoto } from '../../actions/charge-moto/mock';
41
+ import { mockStartCheckout } from '../../actions/start-checkout/mock';
42
+ import { mockAttachCheckoutContact } from '../../actions/attach-checkout-contact/mock';
43
+ import { mockGetAddressOptions } from '../../actions/get-address-options/mock';
44
+ import { mockSetOrderAddress } from '../../actions/set-order-address/mock';
45
+ import { mockGetShippingOptions } from '../../actions/get-shipping-options/mock';
46
+ import { mockSelectShippingOption } from '../../actions/select-shipping-option/mock';
47
+ import { mockGetOutlets } from '../../actions/get-outlets/mock';
48
+ import { mockSetOutlet } from '../../actions/set-outlet/mock';
49
+ import { mockResumeCheckout } from '../../actions/resume-checkout/mock';
50
+ import { mockGetCheckoutStatus } from '../../actions/get-checkout-status/mock';
41
51
  import { mockGetMotoConfig } from '../../actions/get-moto-config/mock';
42
52
  import { mockGetTimeClockStatus } from '../../actions/get-time-clock-status/mock';
43
53
  import { mockClearCart } from '../../actions/clear-cart/mock';
@@ -158,6 +168,16 @@ export const RENDER_MOCKS = {
158
168
  getCashRoundingAmount: mockGetCashRoundingAmount,
159
169
  createPaymentLink: mockCreatePaymentLink,
160
170
  chargeMoto: mockChargeMoto,
171
+ startCheckout: mockStartCheckout,
172
+ attachCheckoutContact: mockAttachCheckoutContact,
173
+ getAddressOptions: mockGetAddressOptions,
174
+ setOrderAddress: mockSetOrderAddress,
175
+ getShippingOptions: mockGetShippingOptions,
176
+ selectShippingOption: mockSelectShippingOption,
177
+ getOutlets: mockGetOutlets,
178
+ setOutlet: mockSetOutlet,
179
+ resumeCheckout: mockResumeCheckout,
180
+ getCheckoutStatus: mockGetCheckoutStatus,
161
181
  getMotoConfig: mockGetMotoConfig,
162
182
  clearCart: mockClearCart,
163
183
  deleteParkedOrder: mockDeleteParkedOrder,
@@ -1,4 +1,4 @@
1
- import type { ExampleFunction, GetProducts, AddCustomSale, EditCustomSale, GetCustomers, AssignCustomer, AddCustomer, EditCustomer, GetCategories, GetOrders, GetRefunds, GetTaxTables, GetCustomStockActions, AddProductDiscount, AddProductToCart, RemoveProductFromCart, UpdateCartItemQuantity, AddCartDiscount, GetContext, GetFinalContext, AddProductNote, AddProductFee, GetProductModifierSelections, GetCompositePrice, GetCompositeAvailability, SetProductModifierSelections, SetActiveProductFee, SetActiveProductDiscount, GetActiveProduct, SetActiveProduct, AdjustInventory, SetVariantUnavailable, AddOrderNote, AddCartFee, ClearCart, ParkOrder, ResumeParkedOrder, ResumeOrder, SetOrderMetadata, AssignOrderUser, ReleaseFromCart, SetOrderType, SetScheduledFor, SetOrderStatus, GetOrderStatuses, DeleteParkedOrder, VoidOrder, InitiateRefund, CashPayment, RecordExternalPayment, GetCashRoundingAmount, TapToPayPayment, TerminalPayment, ExtensionPayment, RedeemPayment, AddNonRevenueItem, AddCustomerNote, RemoveCustomerNote, RemoveCustomerFromCart, GoToStationHome, OpenCashDrawer, ShowNotification, ShowConfirmation, AuthenticateUser, PartialPayment, SwitchUser, SetRefundStockAction, SelectAllRefundItems, ResetRefundDetails, CalculateRefundTotal, GetRemainingRefundableQuantities, ProcessPartialRefund, RedeemRefund, GetRefundPlan, CheckPermission, GetCurrentCart, Print, SetActiveOrder, GetCustomTables, GetCustomTableData, UpsertCustomTableData, DeleteCustomTableData, GetCustomExtensions, GetCurrentCompanyCustomExtensions, GetCustomExtensionCustomTables, GetCustomTableFields, GetSecretsKeys, GetSecretVal, SetSecretVal, GetUsers, GetRoles, RemoveCartDiscount, GetActiveOrder, GetActiveCustomer, SetActiveCustomer, GetActiveOutlet, GetActiveStation, GetActiveSession, GetActiveUser, SetActiveUser, SetActiveRefund, RemoveProductDiscount, RemoveProductFee, RemoveProductNote, RemoveCartFee, RemoveOrderNote, RemoveCustomSale, RemoveNonRevenueItem, CanTransition, GetAvailableTransitions, ApplyTransition, IntegrationPayment, GetSmartGridLayout, SaveSmartGridLayout, SendEmail, SendSms, GetBookingResources, GetBookingAvailability, GetBookings, HoldBooking, AddBookingToCart, RemoveBookingFromCart, CancelBooking, CreatePaymentLink, ChargeMoto, GetMotoConfig, GetTimeClockStatus } from '../../index';
1
+ import type { ExampleFunction, GetProducts, AddCustomSale, EditCustomSale, GetCustomers, AssignCustomer, AddCustomer, EditCustomer, GetCategories, GetOrders, GetRefunds, GetTaxTables, GetCustomStockActions, AddProductDiscount, AddProductToCart, RemoveProductFromCart, UpdateCartItemQuantity, AddCartDiscount, GetContext, GetFinalContext, AddProductNote, AddProductFee, GetProductModifierSelections, GetCompositePrice, GetCompositeAvailability, SetProductModifierSelections, SetActiveProductFee, SetActiveProductDiscount, GetActiveProduct, SetActiveProduct, AdjustInventory, SetVariantUnavailable, AddOrderNote, AddCartFee, ClearCart, ParkOrder, ResumeParkedOrder, ResumeOrder, SetOrderMetadata, AssignOrderUser, ReleaseFromCart, SetOrderType, SetScheduledFor, SetOrderStatus, GetOrderStatuses, DeleteParkedOrder, VoidOrder, InitiateRefund, CashPayment, RecordExternalPayment, GetCashRoundingAmount, TapToPayPayment, TerminalPayment, ExtensionPayment, RedeemPayment, AddNonRevenueItem, AddCustomerNote, RemoveCustomerNote, RemoveCustomerFromCart, GoToStationHome, OpenCashDrawer, ShowNotification, ShowConfirmation, AuthenticateUser, PartialPayment, SwitchUser, SetRefundStockAction, SelectAllRefundItems, ResetRefundDetails, CalculateRefundTotal, GetRemainingRefundableQuantities, ProcessPartialRefund, RedeemRefund, GetRefundPlan, CheckPermission, GetCurrentCart, Print, SetActiveOrder, GetCustomTables, GetCustomTableData, UpsertCustomTableData, DeleteCustomTableData, GetCustomExtensions, GetCurrentCompanyCustomExtensions, GetCustomExtensionCustomTables, GetCustomTableFields, GetSecretsKeys, GetSecretVal, SetSecretVal, GetUsers, GetRoles, RemoveCartDiscount, GetActiveOrder, GetActiveCustomer, SetActiveCustomer, GetActiveOutlet, GetActiveStation, GetActiveSession, GetActiveUser, SetActiveUser, SetActiveRefund, RemoveProductDiscount, RemoveProductFee, RemoveProductNote, RemoveCartFee, RemoveOrderNote, RemoveCustomSale, RemoveNonRevenueItem, CanTransition, GetAvailableTransitions, ApplyTransition, IntegrationPayment, GetSmartGridLayout, SaveSmartGridLayout, SendEmail, SendSms, GetBookingResources, GetBookingAvailability, GetBookings, HoldBooking, AddBookingToCart, RemoveBookingFromCart, CancelBooking, CreatePaymentLink, ChargeMoto, StartCheckout, AttachCheckoutContact, GetAddressOptions, SetOrderAddress, GetShippingOptions, SelectShippingOption, GetOutlets, SetOutlet, ResumeCheckout, GetCheckoutStatus, GetMotoConfig, GetTimeClockStatus } from '../../index';
2
2
  export interface RenderProviderActions {
3
3
  exampleFunction: ExampleFunction;
4
4
  getProducts: GetProducts;
@@ -65,6 +65,28 @@ export interface RenderProviderActions {
65
65
  integrationPayment: IntegrationPayment;
66
66
  createPaymentLink: CreatePaymentLink;
67
67
  chargeMoto: ChargeMoto;
68
+ /**
69
+ * ONLINE checkout — served only by the storefront runtime (a published
70
+ * website). The till tenders above are refused there, and this is refused on
71
+ * a register, because the two declare different things to the card networks.
72
+ */
73
+ startCheckout: StartCheckout;
74
+ attachCheckoutContact: AttachCheckoutContact;
75
+ /** Shipping, on the till (ship-to) and the website alike. The runtime prices; the flow renders. */
76
+ getAddressOptions: GetAddressOptions;
77
+ setOrderAddress: SetOrderAddress;
78
+ getShippingOptions: GetShippingOptions;
79
+ selectShippingOption: SelectShippingOption;
80
+ getOutlets: GetOutlets;
81
+ setOutlet: SetOutlet;
82
+ /**
83
+ * The RETURN LEG of an online checkout, after a redirect payment method or
84
+ * 3-D Secure sent the shopper away and back. Storefront-only, like
85
+ * `startCheckout`, and safe to call on every page load.
86
+ */
87
+ resumeCheckout: ResumeCheckout;
88
+ /** Where an online order stands now, by its order password. Storefront-only. */
89
+ getCheckoutStatus: GetCheckoutStatus;
68
90
  getMotoConfig: GetMotoConfig;
69
91
  addNonRevenueItem: AddNonRevenueItem;
70
92
  addCustomerNote: AddCustomerNote;
@@ -0,0 +1,26 @@
1
+ import type { TopicEvent } from "../../../types";
2
+ /**
3
+ * Payload for checkout-started event
4
+ *
5
+ * The order EXISTS and is unpaid. `serverTotal` is the server's own price for
6
+ * the cart, in integer minor units — the browser never sends a price, so this
7
+ * is the first and only authoritative total.
8
+ */
9
+ export interface CheckoutStartedPayload {
10
+ orderId: string;
11
+ receiptId: string;
12
+ serverTotal: number;
13
+ currency: string;
14
+ /**
15
+ * `ready` — the payment fields are mounted and the shopper can pay.
16
+ * `unavailable` — the order exists but no payment could be started, so the
17
+ * shopper has NOT been charged.
18
+ */
19
+ paymentStatus: "ready" | "unavailable";
20
+ /** One-time password for reading this order back. Returned only on the first create. */
21
+ orderPassword?: string;
22
+ }
23
+ /**
24
+ * Typed event for checkout-started
25
+ */
26
+ export type CheckoutStartedEvent = TopicEvent<CheckoutStartedPayload>;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Checkout Topic Definition
3
+ * Defines the checkout topic and its available event types
4
+ */
5
+ import type { TopicDefinition } from "../../types";
6
+ export declare const checkoutTopic: TopicDefinition;
7
+ export * from "./types";
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Checkout Topic Definition
3
+ * Defines the checkout topic and its available event types
4
+ */
5
+ export const checkoutTopic = {
6
+ id: "checkout",
7
+ name: "Checkout",
8
+ description: "Topic for online (website) checkout events",
9
+ eventTypes: [
10
+ {
11
+ id: "checkout-started",
12
+ name: "Checkout Started",
13
+ description: "Published when the order has been created and the payment fields are mounted"
14
+ },
15
+ {
16
+ id: "payment-completed",
17
+ name: "Payment Completed",
18
+ description: "Published when the shopper's payment succeeds on their side (authorisation, not settlement)"
19
+ },
20
+ {
21
+ id: "payment-failed",
22
+ name: "Payment Failed",
23
+ description: "Published when a payment attempt is refused or errors; the shopper can retry"
24
+ }
25
+ ]
26
+ };
27
+ // Re-export types
28
+ export * from "./types";
@@ -0,0 +1,31 @@
1
+ import type { TopicEvent } from "../../../types";
2
+ /**
3
+ * Payload for payment-completed event
4
+ *
5
+ * THIS IS NOT SETTLEMENT. It reports that the SHOPPER'S side finished —
6
+ * `resultCode` is the provider's own outcome, typically `Authorised`. The money
7
+ * is confirmed by the provider's capture webhook reaching the backend, out of
8
+ * band and after this page is done, so this event cannot and does not claim it.
9
+ */
10
+ export interface PaymentCompletedPayload {
11
+ orderId: string;
12
+ receiptId: string;
13
+ /** The provider's result code, e.g. `Authorised`. */
14
+ resultCode: string;
15
+ /**
16
+ * OPAQUE PROOF OF THIS PAYMENT, handed to the browser by the provider and to
17
+ * nobody else. Pass it to the order-status read and the server verifies it
18
+ * with the provider before believing a word of it.
19
+ *
20
+ * It is the only evidence of an outcome that exists outside the provider's
21
+ * webhook, so it is what recovers an order whose confirmation never arrived.
22
+ * Treat it as a credential: do not log it, do not put it in a URL you share.
23
+ *
24
+ * Absent when the provider reported no payment (see `resultCode`).
25
+ */
26
+ sessionResult?: string;
27
+ }
28
+ /**
29
+ * Typed event for payment-completed
30
+ */
31
+ export type PaymentCompletedEvent = TopicEvent<PaymentCompletedPayload>;
@@ -0,0 +1,23 @@
1
+ import type { TopicEvent } from '../../../types';
2
+ /**
3
+ * Payload for payment-failed event
4
+ *
5
+ * ONE DECLINED ATTEMPT, NOT A DEAD CHECKOUT. The order and the mounted payment
6
+ * fields both survive, so the shopper can try another card without the page
7
+ * starting a new checkout.
8
+ */
9
+ export interface PaymentFailedPayload {
10
+ orderId: string;
11
+ receiptId: string;
12
+ /**
13
+ * The provider's result code, e.g. `Refused`, or an error name. `SoldOut`: the shopper pressed Pay
14
+ * and something in the cart can no longer be sold, so the card was never sent.
15
+ */
16
+ resultCode: string;
17
+ /** Present when the failure carried a message worth showing. */
18
+ message?: string;
19
+ }
20
+ /**
21
+ * Typed event for payment-failed
22
+ */
23
+ export type PaymentFailedEvent = TopicEvent<PaymentFailedPayload>;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Checkout Topic Types
3
+ * Aggregated types for all online-checkout events
4
+ */
5
+ export * from "./checkout-started/types";
6
+ export * from "./payment-completed/types";
7
+ export * from "./payment-failed/types";
8
+ import type { CheckoutStartedPayload } from "./checkout-started/types";
9
+ import type { PaymentCompletedPayload } from "./payment-completed/types";
10
+ import type { PaymentFailedPayload } from "./payment-failed/types";
11
+ export type CheckoutEventPayload = CheckoutStartedPayload | PaymentCompletedPayload | PaymentFailedPayload;
12
+ export type CheckoutEventType = "checkout-started" | "payment-completed" | "payment-failed";
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Checkout Topic Types
3
+ * Aggregated types for all online-checkout events
4
+ */
5
+ // Re-export all event types
6
+ export * from "./checkout-started/types";
7
+ export * from "./payment-completed/types";
8
+ export * from "./payment-failed/types";
@@ -2,20 +2,21 @@
2
2
  * Pub/Sub Topics
3
3
  * Export all available topics and their types
4
4
  */
5
- export * from './customers';
6
- export * from './orders';
7
- export * from './bookings';
8
- export * from './refunds';
9
- export * from './products';
10
- export * from './cart';
11
- export * from './payments';
12
- export * from './custom-tables';
13
- export * from './print';
14
- export * from './outlet';
15
- export * from './station';
16
- export * from './session';
17
- export * from './users';
18
- export * from './variants';
19
- export * from './transactions';
20
- export * from './categories';
21
- export * from './attributes';
5
+ export * from "./customers";
6
+ export * from "./orders";
7
+ export * from "./bookings";
8
+ export * from "./refunds";
9
+ export * from "./products";
10
+ export * from "./cart";
11
+ export * from "./payments";
12
+ export * from "./checkout";
13
+ export * from "./custom-tables";
14
+ export * from "./print";
15
+ export * from "./outlet";
16
+ export * from "./station";
17
+ export * from "./session";
18
+ export * from "./users";
19
+ export * from "./variants";
20
+ export * from "./transactions";
21
+ export * from "./categories";
22
+ export * from "./attributes";