@final-commerce/command-frame 0.11.1-online.1 → 0.12.0-staging.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.
- package/dist/CommonTypes.d.ts +1 -21
- package/dist/actions/get-current-cart/mock.js +0 -3
- package/dist/actions/get-current-cart/types.d.ts +0 -6
- package/dist/actions/get-orders/action.d.ts +1 -1
- package/dist/actions/get-orders/action.js +2 -2
- package/dist/actions/get-orders/mock.d.ts +1 -1
- package/dist/actions/get-orders/mock.js +19 -74
- package/dist/actions/get-orders/types.d.ts +2 -33
- package/dist/actions/get-outlets/action.js +2 -2
- package/dist/actions/get-outlets/mock.d.ts +0 -12
- package/dist/actions/get-outlets/mock.js +4 -28
- package/dist/actions/get-outlets/types.d.ts +1 -19
- package/dist/actions/get-product-modifier-selections/mock.js +0 -7
- package/dist/actions/get-product-modifier-selections/types.d.ts +0 -4
- package/dist/actions/get-products/types.d.ts +8 -8
- package/dist/actions/get-refund-plan/mockRows.js +1 -1
- package/dist/actions/get-refund-plan/types.d.ts +6 -9
- package/dist/actions/get-remaining-refundable-quantities/mock.js +0 -1
- package/dist/actions/get-remaining-refundable-quantities/types.d.ts +0 -5
- package/dist/actions/process-partial-refund/types.d.ts +1 -1
- package/dist/actions/resume-parked-order/mock.d.ts +0 -5
- package/dist/actions/resume-parked-order/mock.js +24 -25
- package/dist/actions/void-order/mock.js +7 -17
- package/dist/actions/void-order/types.d.ts +2 -6
- package/dist/common-types/order-state.d.ts +1 -20
- package/dist/demo/database.d.ts +0 -4
- package/dist/demo/database.js +0 -29
- package/dist/index.d.ts +1 -41
- package/dist/index.js +0 -39
- package/dist/projects/render/mocks.js +0 -40
- package/dist/projects/render/types.d.ts +1 -33
- package/dist/pubsub/topics/index.d.ts +17 -18
- package/dist/pubsub/topics/index.js +17 -18
- package/dist/pubsub/topics/types.d.ts +0 -8
- package/package.json +2 -2
- package/dist/actions/assign-order-user/action.d.ts +0 -6
- package/dist/actions/assign-order-user/action.js +0 -8
- package/dist/actions/assign-order-user/mock.d.ts +0 -2
- package/dist/actions/assign-order-user/mock.js +0 -30
- package/dist/actions/assign-order-user/types.d.ts +0 -15
- package/dist/actions/assign-order-user/types.js +0 -1
- package/dist/actions/attach-checkout-contact/action.d.ts +0 -6
- package/dist/actions/attach-checkout-contact/action.js +0 -8
- package/dist/actions/attach-checkout-contact/mock.d.ts +0 -15
- package/dist/actions/attach-checkout-contact/mock.js +0 -22
- package/dist/actions/attach-checkout-contact/types.d.ts +0 -35
- package/dist/actions/attach-checkout-contact/types.js +0 -16
- package/dist/actions/get-address-options/action.d.ts +0 -6
- package/dist/actions/get-address-options/action.js +0 -8
- package/dist/actions/get-address-options/mock.d.ts +0 -3
- package/dist/actions/get-address-options/mock.js +0 -15
- package/dist/actions/get-address-options/types.d.ts +0 -25
- package/dist/actions/get-address-options/types.js +0 -8
- package/dist/actions/get-checkout-status/action.d.ts +0 -6
- package/dist/actions/get-checkout-status/action.js +0 -8
- package/dist/actions/get-checkout-status/mock.d.ts +0 -3
- package/dist/actions/get-checkout-status/mock.js +0 -11
- package/dist/actions/get-checkout-status/types.d.ts +0 -20
- package/dist/actions/get-checkout-status/types.js +0 -12
- package/dist/actions/get-moto-config/action.d.ts +0 -6
- package/dist/actions/get-moto-config/action.js +0 -8
- package/dist/actions/get-moto-config/mock.d.ts +0 -7
- package/dist/actions/get-moto-config/mock.js +0 -9
- package/dist/actions/get-moto-config/types.d.ts +0 -34
- package/dist/actions/get-moto-config/types.js +0 -5
- package/dist/actions/get-order-statuses/action.d.ts +0 -6
- package/dist/actions/get-order-statuses/action.js +0 -8
- package/dist/actions/get-order-statuses/mock.d.ts +0 -2
- package/dist/actions/get-order-statuses/mock.js +0 -5
- package/dist/actions/get-order-statuses/types.d.ts +0 -8
- package/dist/actions/get-order-statuses/types.js +0 -1
- package/dist/actions/get-shipping-options/action.d.ts +0 -6
- package/dist/actions/get-shipping-options/action.js +0 -8
- package/dist/actions/get-shipping-options/mock.d.ts +0 -3
- package/dist/actions/get-shipping-options/mock.js +0 -15
- package/dist/actions/get-shipping-options/types.d.ts +0 -43
- package/dist/actions/get-shipping-options/types.js +0 -1
- package/dist/actions/record-external-payment/action.d.ts +0 -6
- package/dist/actions/record-external-payment/action.js +0 -8
- package/dist/actions/record-external-payment/mock.d.ts +0 -2
- package/dist/actions/record-external-payment/mock.js +0 -36
- package/dist/actions/record-external-payment/types.d.ts +0 -37
- package/dist/actions/record-external-payment/types.js +0 -1
- package/dist/actions/release-from-cart/action.d.ts +0 -6
- package/dist/actions/release-from-cart/action.js +0 -8
- package/dist/actions/release-from-cart/mock.d.ts +0 -2
- package/dist/actions/release-from-cart/mock.js +0 -26
- package/dist/actions/release-from-cart/types.d.ts +0 -8
- package/dist/actions/release-from-cart/types.js +0 -1
- package/dist/actions/resume-checkout/action.d.ts +0 -6
- package/dist/actions/resume-checkout/action.js +0 -8
- package/dist/actions/resume-checkout/mock.d.ts +0 -16
- package/dist/actions/resume-checkout/mock.js +0 -51
- package/dist/actions/resume-checkout/types.d.ts +0 -59
- package/dist/actions/resume-checkout/types.js +0 -13
- package/dist/actions/resume-order/action.d.ts +0 -6
- package/dist/actions/resume-order/action.js +0 -8
- package/dist/actions/resume-order/mock.d.ts +0 -2
- package/dist/actions/resume-order/mock.js +0 -55
- package/dist/actions/resume-order/types.d.ts +0 -17
- package/dist/actions/resume-order/types.js +0 -1
- package/dist/actions/select-shipping-option/action.d.ts +0 -6
- package/dist/actions/select-shipping-option/action.js +0 -8
- package/dist/actions/select-shipping-option/mock.d.ts +0 -3
- package/dist/actions/select-shipping-option/mock.js +0 -31
- package/dist/actions/select-shipping-option/types.d.ts +0 -15
- package/dist/actions/select-shipping-option/types.js +0 -1
- package/dist/actions/set-order-address/action.d.ts +0 -6
- package/dist/actions/set-order-address/action.js +0 -8
- package/dist/actions/set-order-address/mock.d.ts +0 -7
- package/dist/actions/set-order-address/mock.js +0 -29
- package/dist/actions/set-order-address/types.d.ts +0 -19
- package/dist/actions/set-order-address/types.js +0 -1
- package/dist/actions/set-order-metadata/action.d.ts +0 -6
- package/dist/actions/set-order-metadata/action.js +0 -8
- package/dist/actions/set-order-metadata/mock.d.ts +0 -5
- package/dist/actions/set-order-metadata/mock.js +0 -38
- package/dist/actions/set-order-metadata/types.d.ts +0 -20
- package/dist/actions/set-order-metadata/types.js +0 -1
- package/dist/actions/set-order-status/action.d.ts +0 -6
- package/dist/actions/set-order-status/action.js +0 -8
- package/dist/actions/set-order-status/mock.d.ts +0 -3
- package/dist/actions/set-order-status/mock.js +0 -44
- package/dist/actions/set-order-status/types.d.ts +0 -25
- package/dist/actions/set-order-status/types.js +0 -1
- package/dist/actions/set-order-type/action.d.ts +0 -6
- package/dist/actions/set-order-type/action.js +0 -8
- package/dist/actions/set-order-type/mock.d.ts +0 -3
- package/dist/actions/set-order-type/mock.js +0 -27
- package/dist/actions/set-order-type/types.d.ts +0 -17
- package/dist/actions/set-order-type/types.js +0 -1
- package/dist/actions/set-outlet/action.d.ts +0 -6
- package/dist/actions/set-outlet/action.js +0 -8
- package/dist/actions/set-outlet/mock.d.ts +0 -13
- package/dist/actions/set-outlet/mock.js +0 -24
- package/dist/actions/set-outlet/types.d.ts +0 -31
- package/dist/actions/set-outlet/types.js +0 -21
- package/dist/actions/set-scheduled-for/action.d.ts +0 -6
- package/dist/actions/set-scheduled-for/action.js +0 -8
- package/dist/actions/set-scheduled-for/mock.d.ts +0 -4
- package/dist/actions/set-scheduled-for/mock.js +0 -45
- package/dist/actions/set-scheduled-for/types.d.ts +0 -22
- package/dist/actions/set-scheduled-for/types.js +0 -1
- package/dist/actions/start-checkout/action.d.ts +0 -6
- package/dist/actions/start-checkout/action.js +0 -8
- package/dist/actions/start-checkout/mock.d.ts +0 -16
- package/dist/actions/start-checkout/mock.js +0 -80
- package/dist/actions/start-checkout/types.d.ts +0 -90
- package/dist/actions/start-checkout/types.js +0 -10
- package/dist/demo/shipping.d.ts +0 -8
- package/dist/demo/shipping.js +0 -69
- package/dist/pubsub/topics/checkout/checkout-started/types.d.ts +0 -26
- package/dist/pubsub/topics/checkout/checkout-started/types.js +0 -1
- package/dist/pubsub/topics/checkout/index.d.ts +0 -7
- package/dist/pubsub/topics/checkout/index.js +0 -28
- package/dist/pubsub/topics/checkout/payment-completed/types.d.ts +0 -31
- package/dist/pubsub/topics/checkout/payment-completed/types.js +0 -1
- package/dist/pubsub/topics/checkout/payment-failed/types.d.ts +0 -20
- package/dist/pubsub/topics/checkout/payment-failed/types.js +0 -1
- package/dist/pubsub/topics/checkout/types.d.ts +0 -12
- package/dist/pubsub/topics/checkout/types.js +0 -8
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Set order status action
|
|
3
|
-
* Calls the setOrderStatus action on the parent window
|
|
4
|
-
*/
|
|
5
|
-
import { commandFrameClient } from '../../client';
|
|
6
|
-
export const setOrderStatus = async (params) => {
|
|
7
|
-
return await commandFrameClient.call('setOrderStatus', params);
|
|
8
|
-
};
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { MOCK_ORDERS, MOCK_ORDER_STATUSES, MOCK_PARKED_ORDERS, mockPublishEvent } from '../../demo/database';
|
|
2
|
-
/** Best-effort mock: no state-machine guards beyond the status's payment requirement. */
|
|
3
|
-
export const mockSetOrderStatus = async (params) => {
|
|
4
|
-
console.log('[Mock] setOrderStatus called', params);
|
|
5
|
-
if (!params?.orderId) {
|
|
6
|
-
throw new Error('setOrderStatus: the demo has no live-cart order — pass an orderId');
|
|
7
|
-
}
|
|
8
|
-
const order = [...MOCK_ORDERS, ...MOCK_PARKED_ORDERS].find((o) => o._id === params.orderId);
|
|
9
|
-
if (!order) {
|
|
10
|
-
throw new Error(`Order with ID ${params.orderId} not found`);
|
|
11
|
-
}
|
|
12
|
-
const from = { payment: order.paymentState ?? 'unpaid', fulfillment: order.fulfillmentState ?? 'draft' };
|
|
13
|
-
const requested = params.key !== undefined ? params.key : params.statusId;
|
|
14
|
-
if (requested === undefined) {
|
|
15
|
-
throw new Error('setOrderStatus: pass a status key, or null to clear the status');
|
|
16
|
-
}
|
|
17
|
-
if (requested === null) {
|
|
18
|
-
order.customStatus = null;
|
|
19
|
-
}
|
|
20
|
-
else {
|
|
21
|
-
const def = MOCK_ORDER_STATUSES.find((s) => s.key === requested) ??
|
|
22
|
-
(params.key === undefined ? MOCK_ORDER_STATUSES.find((s) => s.id === requested) : undefined);
|
|
23
|
-
if (!def) {
|
|
24
|
-
throw new Error(`setOrderStatus: unknown status "${requested}"`);
|
|
25
|
-
}
|
|
26
|
-
if (def.requiresPaymentState && !def.requiresPaymentState.includes(from.payment)) {
|
|
27
|
-
throw new Error(`setOrderStatus: "${def.label}" requires payment state ${def.requiresPaymentState.join(' or ')} (order is ${from.payment})`);
|
|
28
|
-
}
|
|
29
|
-
if (def.fulfillmentState)
|
|
30
|
-
order.fulfillmentState = def.fulfillmentState;
|
|
31
|
-
order.customStatus = { id: def.id, key: def.key, label: def.label, setAt: new Date().toISOString(), setBy: null };
|
|
32
|
-
}
|
|
33
|
-
mockPublishEvent('orders', 'order-updated', { order });
|
|
34
|
-
const to = { payment: order.paymentState ?? 'unpaid', fulfillment: order.fulfillmentState ?? 'draft' };
|
|
35
|
-
return {
|
|
36
|
-
success: true,
|
|
37
|
-
orderId: order._id,
|
|
38
|
-
customStatus: order.customStatus ?? null,
|
|
39
|
-
from,
|
|
40
|
-
to,
|
|
41
|
-
order,
|
|
42
|
-
timestamp: new Date().toISOString(),
|
|
43
|
-
};
|
|
44
|
-
};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { CFOrder, CFOrderCustomStatus } from '../../CommonTypes';
|
|
2
|
-
import type { CFStatePair } from '../../common-types/order-state';
|
|
3
|
-
export interface SetOrderStatusParams {
|
|
4
|
-
/** Order to set the status on. Omit for the live cart's order. */
|
|
5
|
-
orderId?: string;
|
|
6
|
-
/** Key of one of the flow's statuses (see getOrderStatuses), or null to clear the status. */
|
|
7
|
-
key?: string | null;
|
|
8
|
-
/**
|
|
9
|
-
* @deprecated Use `key`. Kept for flows written before keys: matched against a status's
|
|
10
|
-
* key, then its id. Ignored when `key` is given.
|
|
11
|
-
*/
|
|
12
|
-
statusId?: string | null;
|
|
13
|
-
}
|
|
14
|
-
export interface SetOrderStatusResponse {
|
|
15
|
-
success: boolean;
|
|
16
|
-
orderId: string;
|
|
17
|
-
/** The order's status after the call; null when cleared. */
|
|
18
|
-
customStatus: CFOrderCustomStatus | null;
|
|
19
|
-
/** State before and after — they differ only when the status is bound to a fulfillment state the order wasn't in. */
|
|
20
|
-
from: CFStatePair | null;
|
|
21
|
-
to: CFStatePair | null;
|
|
22
|
-
order: CFOrder;
|
|
23
|
-
timestamp: string;
|
|
24
|
-
}
|
|
25
|
-
export type SetOrderStatus = (params: SetOrderStatusParams) => Promise<SetOrderStatusResponse>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { MOCK_ORDERS, MOCK_PARKED_ORDERS, mockPublishEvent } from '../../demo/database';
|
|
2
|
-
/** Type for the demo's live cart, which has no order until it is paid or parked. */
|
|
3
|
-
let mockCartOrderType = null;
|
|
4
|
-
export const normalizeOrderType = (value) => {
|
|
5
|
-
if (value === null)
|
|
6
|
-
return null;
|
|
7
|
-
if (typeof value !== 'string' || !value.trim()) {
|
|
8
|
-
throw new Error('setOrderType: orderType must be a non-empty string or null');
|
|
9
|
-
}
|
|
10
|
-
return value.trim();
|
|
11
|
-
};
|
|
12
|
-
export const mockSetOrderType = async (params) => {
|
|
13
|
-
console.log('[Mock] setOrderType called', params);
|
|
14
|
-
const orderType = normalizeOrderType(params?.orderType);
|
|
15
|
-
const timestamp = new Date().toISOString();
|
|
16
|
-
if (!params.orderId) {
|
|
17
|
-
mockCartOrderType = orderType;
|
|
18
|
-
return { success: true, orderId: null, orderType: mockCartOrderType, timestamp };
|
|
19
|
-
}
|
|
20
|
-
const order = [...MOCK_ORDERS, ...MOCK_PARKED_ORDERS].find((o) => o._id === params.orderId);
|
|
21
|
-
if (!order) {
|
|
22
|
-
throw new Error(`Order with ID ${params.orderId} not found`);
|
|
23
|
-
}
|
|
24
|
-
order.orderType = orderType;
|
|
25
|
-
mockPublishEvent('orders', 'order-updated', { order });
|
|
26
|
-
return { success: true, orderId: order._id, orderType, timestamp };
|
|
27
|
-
};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export interface SetOrderTypeParams {
|
|
2
|
-
/**
|
|
3
|
-
* Order to label. Omit to target the live cart — including a cart that isn't an
|
|
4
|
-
* order yet; the type is carried onto the order when it's created.
|
|
5
|
-
*/
|
|
6
|
-
orderId?: string;
|
|
7
|
-
/** Any non-empty label (e.g. 'takeout', 'pickup', 'delivery'), or null to clear it. */
|
|
8
|
-
orderType: string | null;
|
|
9
|
-
}
|
|
10
|
-
export interface SetOrderTypeResponse {
|
|
11
|
-
success: boolean;
|
|
12
|
-
/** The order that was updated, or null when the live cart has no order yet. */
|
|
13
|
-
orderId: string | null;
|
|
14
|
-
orderType: string | null;
|
|
15
|
-
timestamp: string;
|
|
16
|
-
}
|
|
17
|
-
export type SetOrderType = (params: SetOrderTypeParams) => Promise<SetOrderTypeResponse>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { SetOutlet } from './types';
|
|
2
|
-
/**
|
|
3
|
-
* Standalone mock of switching location.
|
|
4
|
-
*
|
|
5
|
-
* It mirrors the two REFUSALS the real command makes — a missing id, and an
|
|
6
|
-
* outlet that cannot take a payment — because those are the mistakes a builder
|
|
7
|
-
* actually hits. A mock that accepted anything would let a location picker look
|
|
8
|
-
* finished and then strand a shopper at a dead payment step on the real site.
|
|
9
|
-
*
|
|
10
|
-
* The unconnected id comes from the `getOutlets` mock rather than being repeated
|
|
11
|
-
* here, so the two cannot drift into telling different stories.
|
|
12
|
-
*/
|
|
13
|
-
export declare const mockSetOutlet: SetOutlet;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { MOCK_UNCONNECTED_OUTLET_ID } from '../get-outlets/mock';
|
|
2
|
-
/**
|
|
3
|
-
* Standalone mock of switching location.
|
|
4
|
-
*
|
|
5
|
-
* It mirrors the two REFUSALS the real command makes — a missing id, and an
|
|
6
|
-
* outlet that cannot take a payment — because those are the mistakes a builder
|
|
7
|
-
* actually hits. A mock that accepted anything would let a location picker look
|
|
8
|
-
* finished and then strand a shopper at a dead payment step on the real site.
|
|
9
|
-
*
|
|
10
|
-
* The unconnected id comes from the `getOutlets` mock rather than being repeated
|
|
11
|
-
* here, so the two cannot drift into telling different stories.
|
|
12
|
-
*/
|
|
13
|
-
export const mockSetOutlet = async (params) => {
|
|
14
|
-
console.log('[Mock] setOutlet called', params);
|
|
15
|
-
if (!params)
|
|
16
|
-
throw new Error('Params required');
|
|
17
|
-
if (!params.outletId || !params.outletId.trim()) {
|
|
18
|
-
throw new Error('setOutlet: outletId is required');
|
|
19
|
-
}
|
|
20
|
-
if (params.outletId === MOCK_UNCONNECTED_OUTLET_ID) {
|
|
21
|
-
throw new Error(`setOutlet: outlet ${params.outletId} cannot take an online payment — offer only outlets with connected: true`);
|
|
22
|
-
}
|
|
23
|
-
return { outletId: params.outletId, rehydrated: true, timestamp: new Date().toISOString() };
|
|
24
|
-
};
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
export interface SetOutletParams {
|
|
2
|
-
/** An `id` from `getOutlets`. */
|
|
3
|
-
outletId: string;
|
|
4
|
-
}
|
|
5
|
-
export interface SetOutletResponse {
|
|
6
|
-
/** The location now in effect. */
|
|
7
|
-
outletId: string;
|
|
8
|
-
/**
|
|
9
|
-
* `true` when the catalog and tax tables were re-pulled for this location.
|
|
10
|
-
*
|
|
11
|
-
* `false` means the switch took effect but the refresh could not reach the
|
|
12
|
-
* server — the shop is running on what it already had cached. Totals may be
|
|
13
|
-
* the previous location's until the next refresh pass lands, so a flow can
|
|
14
|
-
* tell the shopper to try again rather than quietly showing stale tax.
|
|
15
|
-
*/
|
|
16
|
-
rehydrated: boolean;
|
|
17
|
-
timestamp: string;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Switch the shop to another of the company's locations.
|
|
21
|
-
*
|
|
22
|
-
* REFUSES AN OUTLET THAT CANNOT TAKE A PAYMENT, and one that does not belong to
|
|
23
|
-
* this company, rather than letting either fail later at the payment step. Check
|
|
24
|
-
* `connected` from `getOutlets` and do not offer those, so this refusal is a
|
|
25
|
-
* backstop rather than something a shopper ever sees.
|
|
26
|
-
*
|
|
27
|
-
* The cart survives the switch. Its lines are kept and re-priced; a line that is
|
|
28
|
-
* not purchasable at the new location is not silently dropped here, it is
|
|
29
|
-
* reported when the checkout is next priced.
|
|
30
|
-
*/
|
|
31
|
-
export type SetOutlet = (params: SetOutletParams) => Promise<SetOutletResponse>;
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
// Set Outlet Types
|
|
2
|
-
//
|
|
3
|
-
// Choose which of the company's locations this shop is ordering from.
|
|
4
|
-
//
|
|
5
|
-
// WHAT IT ACTUALLY CHANGES. An outlet decides three things, and a shop that lets
|
|
6
|
-
// a shopper pick one has to move all three together:
|
|
7
|
-
//
|
|
8
|
-
// tax rates follow the outlet's own address, so the total moves
|
|
9
|
-
// availability stock is counted per location, and a product can be hidden at one
|
|
10
|
-
// fulfilment the order records where the goods come from, so the right
|
|
11
|
-
// location's stock is the one that is drawn down
|
|
12
|
-
//
|
|
13
|
-
// So this is not a display preference. It re-pulls the catalog for the new
|
|
14
|
-
// location, re-hydrates the tax tables, and re-prices the cart. The totals a
|
|
15
|
-
// flow reads afterwards are the new location's.
|
|
16
|
-
//
|
|
17
|
-
// SAFE MID-CHECKOUT. Checkout starts when a shopper ARRIVES, so by the time
|
|
18
|
-
// anyone changes their mind an order usually already exists. That order is
|
|
19
|
-
// re-priced and moved to the new outlet in place, keeping its id and its receipt
|
|
20
|
-
// id, rather than being abandoned and replaced.
|
|
21
|
-
export {};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Set scheduled-for action
|
|
3
|
-
* Calls the setScheduledFor action on the parent window
|
|
4
|
-
*/
|
|
5
|
-
import { commandFrameClient } from '../../client';
|
|
6
|
-
export const setScheduledFor = async (params) => {
|
|
7
|
-
return await commandFrameClient.call('setScheduledFor', params);
|
|
8
|
-
};
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { MOCK_ORDERS, MOCK_PARKED_ORDERS, mockPublishEvent } from '../../demo/database';
|
|
2
|
-
/** Time for the demo's live cart, which has no order until it is paid or parked. */
|
|
3
|
-
let mockCartScheduledFor = null;
|
|
4
|
-
/**
|
|
5
|
-
* An ISO 8601 date-time WITH a zone — 'Z' or an offset. A zoneless time ('2026-10-13T19:00') is
|
|
6
|
-
* refused: it would mean a different moment on every device. Date.parse alone is too lenient
|
|
7
|
-
* (it accepts strings like "tomorrow at 7"), so the shape is checked first.
|
|
8
|
-
*/
|
|
9
|
-
const ISO_DATE_TIME = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d{1,9})?)?(Z|[+-]\d{2}:?\d{2})$/;
|
|
10
|
-
/** The YYYY-MM-DD part is a real day — Date.parse quietly rolls "Feb 30" over to March 2. */
|
|
11
|
-
const isCalendarDate = (text) => {
|
|
12
|
-
const [y, m, d] = text.slice(0, 10).split('-').map(Number);
|
|
13
|
-
const day = new Date(Date.UTC(y, m - 1, d));
|
|
14
|
-
return day.getUTCFullYear() === y && day.getUTCMonth() === m - 1 && day.getUTCDate() === d;
|
|
15
|
-
};
|
|
16
|
-
/** ISO 8601 in, UTC ISO 8601 out; null stays null (as soon as possible). */
|
|
17
|
-
export const normalizeScheduledFor = (value) => {
|
|
18
|
-
if (value === null)
|
|
19
|
-
return null;
|
|
20
|
-
if (typeof value !== 'string' || !value.trim()) {
|
|
21
|
-
throw new Error('setScheduledFor: scheduledFor must be an ISO 8601 date-time or null');
|
|
22
|
-
}
|
|
23
|
-
const text = value.trim();
|
|
24
|
-
const ms = ISO_DATE_TIME.test(text) && isCalendarDate(text) ? Date.parse(text) : NaN;
|
|
25
|
-
if (Number.isNaN(ms)) {
|
|
26
|
-
throw new Error(`setScheduledFor: "${value}" is not an ISO 8601 date-time with Z or an offset`);
|
|
27
|
-
}
|
|
28
|
-
return new Date(ms).toISOString();
|
|
29
|
-
};
|
|
30
|
-
export const mockSetScheduledFor = async (params) => {
|
|
31
|
-
console.log('[Mock] setScheduledFor called', params);
|
|
32
|
-
const scheduledFor = normalizeScheduledFor(params?.scheduledFor);
|
|
33
|
-
const timestamp = new Date().toISOString();
|
|
34
|
-
if (!params.orderId) {
|
|
35
|
-
mockCartScheduledFor = scheduledFor;
|
|
36
|
-
return { success: true, orderId: null, scheduledFor: mockCartScheduledFor, timestamp };
|
|
37
|
-
}
|
|
38
|
-
const order = [...MOCK_ORDERS, ...MOCK_PARKED_ORDERS].find((o) => o._id === params.orderId);
|
|
39
|
-
if (!order) {
|
|
40
|
-
throw new Error(`Order with ID ${params.orderId} not found`);
|
|
41
|
-
}
|
|
42
|
-
order.scheduledFor = scheduledFor;
|
|
43
|
-
mockPublishEvent('orders', 'order-updated', { order });
|
|
44
|
-
return { success: true, orderId: order._id, scheduledFor, timestamp };
|
|
45
|
-
};
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export interface SetScheduledForParams {
|
|
2
|
-
/**
|
|
3
|
-
* Order to schedule. Omit to target the live cart — including a cart that isn't an
|
|
4
|
-
* order yet; the time is carried onto the order when it's created.
|
|
5
|
-
*/
|
|
6
|
-
orderId?: string;
|
|
7
|
-
/**
|
|
8
|
-
* When the customer wants the order, as an ISO 8601 date-time with Z or an offset (e.g.
|
|
9
|
-
* '2026-10-13T23:00:00.000Z' or '2026-10-13T19:00:00-04:00'), or null for as soon as possible.
|
|
10
|
-
* Stored in UTC.
|
|
11
|
-
*/
|
|
12
|
-
scheduledFor: string | null;
|
|
13
|
-
}
|
|
14
|
-
export interface SetScheduledForResponse {
|
|
15
|
-
success: boolean;
|
|
16
|
-
/** The order that was updated, or null when the live cart has no order yet. */
|
|
17
|
-
orderId: string | null;
|
|
18
|
-
/** The time after the call, normalised to UTC ISO 8601 — or null (as soon as possible). */
|
|
19
|
-
scheduledFor: string | null;
|
|
20
|
-
timestamp: string;
|
|
21
|
-
}
|
|
22
|
-
export type SetScheduledFor = (params: SetScheduledForParams) => Promise<SetScheduledForResponse>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { StartCheckout } from './types';
|
|
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 declare const mockStartCheckout: StartCheckout;
|
|
@@ -1,80 +0,0 @@
|
|
|
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
|
-
};
|
|
@@ -1,90 +0,0 @@
|
|
|
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>;
|
|
@@ -1,10 +0,0 @@
|
|
|
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 {};
|
package/dist/demo/shipping.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
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
|
-
};
|