@final-commerce/command-frame 0.1.73 → 0.1.74
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/README.md +50 -28
- package/dist/CommonTypes.d.ts +124 -7
- package/dist/CommonTypes.js +112 -0
- package/dist/actions/apply-transition/action.d.ts +2 -0
- package/dist/actions/apply-transition/action.js +4 -0
- package/dist/actions/apply-transition/mock.d.ts +6 -0
- package/dist/actions/apply-transition/mock.js +33 -0
- package/dist/actions/apply-transition/types.d.ts +17 -0
- package/dist/actions/apply-transition/types.js +1 -0
- package/dist/actions/can-transition/action.d.ts +2 -0
- package/dist/actions/can-transition/action.js +4 -0
- package/dist/actions/can-transition/mock.d.ts +6 -0
- package/dist/actions/can-transition/mock.js +28 -0
- package/dist/actions/can-transition/types.d.ts +11 -0
- package/dist/actions/can-transition/types.js +1 -0
- package/dist/actions/cash-payment/types.d.ts +5 -0
- package/dist/actions/delete-parked-order/types.d.ts +3 -0
- package/dist/actions/extension-payment/types.d.ts +5 -0
- package/dist/actions/get-available-transitions/action.d.ts +2 -0
- package/dist/actions/get-available-transitions/action.js +4 -0
- package/dist/actions/get-available-transitions/mock.d.ts +6 -0
- package/dist/actions/get-available-transitions/mock.js +26 -0
- package/dist/actions/get-available-transitions/types.d.ts +9 -0
- package/dist/actions/get-available-transitions/types.js +1 -0
- package/dist/actions/initiate-refund/types.d.ts +3 -0
- package/dist/actions/open-extension-overlay/mock.d.ts +2 -0
- package/dist/actions/open-extension-overlay/mock.js +1 -0
- package/dist/actions/open-extension-overlay/types.d.ts +9 -0
- package/dist/actions/open-extension-overlay/types.js +1 -0
- package/dist/actions/park-order/types.d.ts +3 -0
- package/dist/actions/partial-payment/types.d.ts +5 -0
- package/dist/actions/process-partial-refund/types.d.ts +3 -0
- package/dist/actions/remove-product-from-cart/mock.js +5 -5
- package/dist/actions/resolve-extension-overlay/mock.d.ts +2 -0
- package/dist/actions/resolve-extension-overlay/mock.js +1 -0
- package/dist/actions/resolve-extension-overlay/types.d.ts +9 -0
- package/dist/actions/resolve-extension-overlay/types.js +1 -0
- package/dist/actions/resume-parked-order/types.d.ts +3 -0
- package/dist/actions/tap-to-pay-payment/types.d.ts +5 -0
- package/dist/actions/terminal-payment/types.d.ts +5 -0
- package/dist/actions/update-cart-item-quantity/mock.js +9 -9
- package/dist/actions/vendara-payment/types.d.ts +5 -0
- package/dist/common-types/index.d.ts +1 -0
- package/dist/common-types/index.js +1 -0
- package/dist/common-types/order-state.d.ts +32 -0
- package/dist/common-types/order-state.js +6 -0
- package/dist/common-types/state-fragment.d.ts +77 -0
- package/dist/common-types/state-fragment.js +10 -0
- package/dist/demo/database.js +9 -0
- package/dist/fragments/index.d.ts +1 -0
- package/dist/fragments/index.js +1 -0
- package/dist/fragments/preorder-no-deposit.d.ts +26 -0
- package/dist/fragments/preorder-no-deposit.js +166 -0
- package/dist/index.d.ts +14 -4
- package/dist/index.js +13 -3
- package/dist/interceptors/index.d.ts +21 -0
- package/dist/interceptors/index.js +53 -0
- package/dist/interceptors/types.d.ts +26 -0
- package/dist/interceptors/types.js +1 -0
- package/dist/projects/render/mocks.js +8 -0
- package/dist/projects/render/types.d.ts +7 -1
- package/dist/pubsub/topics/orders/index.js +10 -0
- package/dist/pubsub/topics/orders/state-transition-blocked/types.d.ts +16 -0
- package/dist/pubsub/topics/orders/state-transition-blocked/types.js +1 -0
- package/dist/pubsub/topics/orders/state-transition-completed/types.d.ts +15 -0
- package/dist/pubsub/topics/orders/state-transition-completed/types.js +1 -0
- package/dist/pubsub/topics/orders/types.d.ts +6 -2
- package/dist/pubsub/topics/orders/types.js +2 -0
- package/package.json +1 -1
- package/dist/actions/extension-refund/constants.d.ts +0 -2
- package/dist/actions/extension-refund/constants.js +0 -2
- package/dist/actions/extension-refund/extension-refund-listener.d.ts +0 -11
- package/dist/actions/extension-refund/extension-refund-listener.js +0 -60
- package/dist/actions/extension-refund/types.d.ts +0 -32
- package/dist/actions/extension-refund/types.js +0 -5
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock implementation: returns a fixed set of plausible transitions
|
|
3
|
+
* so the demo app has data to render.
|
|
4
|
+
*/
|
|
5
|
+
export const getAvailableTransitionsMock = async (_params) => ({
|
|
6
|
+
transitions: [
|
|
7
|
+
{
|
|
8
|
+
to: { payment: "refunded", fulfillment: "returned" },
|
|
9
|
+
displayLabel: "Full Refund",
|
|
10
|
+
conditions: [{ met: true, description: "Order is paid" }],
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
to: { payment: "partially_refunded", fulfillment: "partially_returned" },
|
|
14
|
+
displayLabel: "Partial Refund",
|
|
15
|
+
conditions: [{ met: true, description: "Order is paid" }],
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
to: { payment: "voided", fulfillment: "cancelled" },
|
|
19
|
+
displayLabel: "Void Order",
|
|
20
|
+
conditions: [
|
|
21
|
+
{ met: true, description: "Order exists" },
|
|
22
|
+
{ met: false, description: "No payments captured (mock: skipped)" },
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CFAvailableTransition } from "../../common-types/order-state";
|
|
2
|
+
export interface GetAvailableTransitionsParams {
|
|
3
|
+
/** Order to evaluate. Required — we need the current state. */
|
|
4
|
+
orderId: string;
|
|
5
|
+
}
|
|
6
|
+
export interface GetAvailableTransitionsResponse {
|
|
7
|
+
transitions: CFAvailableTransition[];
|
|
8
|
+
}
|
|
9
|
+
export type GetAvailableTransitions = (params: GetAvailableTransitionsParams) => Promise<GetAvailableTransitionsResponse>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CFTransitionResult } from "../../common-types/order-state";
|
|
1
2
|
export interface InitiateRefundParams {
|
|
2
3
|
/** The ID of the order to refund. If not provided, uses the currently active order. */
|
|
3
4
|
orderId?: string;
|
|
@@ -6,5 +7,7 @@ export interface InitiateRefundResponse {
|
|
|
6
7
|
success: boolean;
|
|
7
8
|
orderId: string;
|
|
8
9
|
timestamp: string;
|
|
10
|
+
/** Present when the state machine blocked or forced the transition. */
|
|
11
|
+
transitionResult?: CFTransitionResult;
|
|
9
12
|
}
|
|
10
13
|
export type InitiateRefund = (params?: InitiateRefundParams) => Promise<InitiateRefundResponse>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const mockOpenExtensionOverlay = async (_params) => true;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { InterceptorPoint, InterceptorReturn } from "../../interceptors/types";
|
|
2
|
+
export interface OpenExtensionOverlayParams {
|
|
3
|
+
point: InterceptorPoint;
|
|
4
|
+
payload?: any;
|
|
5
|
+
/** Owning extension id. Injected by the host for interceptor-originated calls; optional for direct calls. */
|
|
6
|
+
extensionId?: string;
|
|
7
|
+
}
|
|
8
|
+
export type OpenExtensionOverlayResponse = InterceptorReturn;
|
|
9
|
+
export type OpenExtensionOverlay = (params: OpenExtensionOverlayParams) => Promise<OpenExtensionOverlayResponse>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { CFOrder } from "../../CommonTypes";
|
|
2
|
+
import type { CFTransitionResult } from "../../common-types/order-state";
|
|
2
3
|
export interface ParkOrderResponse {
|
|
3
4
|
success: boolean;
|
|
4
5
|
order: CFOrder;
|
|
5
6
|
timestamp: string;
|
|
7
|
+
/** Present when the state machine blocked or forced the transition. */
|
|
8
|
+
transitionResult?: CFTransitionResult;
|
|
6
9
|
}
|
|
7
10
|
export type ParkOrder = () => Promise<ParkOrderResponse>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CFOrder } from "../../CommonTypes";
|
|
2
|
+
import type { CFTransitionResult } from "../../common-types/order-state";
|
|
2
3
|
export interface PartialPaymentParams {
|
|
3
4
|
/** The payment amount (required if openUI is false). */
|
|
4
5
|
amount?: number;
|
|
@@ -6,6 +7,8 @@ export interface PartialPaymentParams {
|
|
|
6
7
|
isPercent?: boolean;
|
|
7
8
|
/** If true, opens the split payment UI. */
|
|
8
9
|
openUI?: boolean;
|
|
10
|
+
/** Override the fulfillment state after full payment. Render resolves the cascade. */
|
|
11
|
+
checkoutFulfillmentTarget?: string;
|
|
9
12
|
}
|
|
10
13
|
export interface PartialPaymentResponse {
|
|
11
14
|
success: boolean;
|
|
@@ -14,5 +17,7 @@ export interface PartialPaymentResponse {
|
|
|
14
17
|
openUI: boolean;
|
|
15
18
|
order: CFOrder | null;
|
|
16
19
|
timestamp: string;
|
|
20
|
+
/** Present when the state machine blocked or forced the transition. */
|
|
21
|
+
transitionResult?: CFTransitionResult;
|
|
17
22
|
}
|
|
18
23
|
export type PartialPayment = (params?: PartialPaymentParams) => Promise<PartialPaymentResponse>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CFTransitionResult } from "../../common-types/order-state";
|
|
1
2
|
export interface ProcessPartialRefundParams {
|
|
2
3
|
/** Optional refund reason. */
|
|
3
4
|
reason?: string;
|
|
@@ -15,5 +16,7 @@ export interface ProcessPartialRefundResponse {
|
|
|
15
16
|
success: boolean;
|
|
16
17
|
refundId: string;
|
|
17
18
|
timestamp: string;
|
|
19
|
+
/** Present when the state machine blocked or forced the transition. */
|
|
20
|
+
transitionResult?: CFTransitionResult;
|
|
18
21
|
}
|
|
19
22
|
export type ProcessPartialRefund = (params?: ProcessPartialRefundParams) => Promise<ProcessPartialRefundResponse>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { MOCK_CART, mockPublishEvent } from "../../demo/database";
|
|
2
|
-
export const mockRemoveProductFromCart =
|
|
2
|
+
export const mockRemoveProductFromCart = (params) => {
|
|
3
3
|
console.log("[Mock] removeProductFromCart called", params);
|
|
4
4
|
if (!params?.internalId) {
|
|
5
|
-
throw new Error(
|
|
5
|
+
throw new Error("internalId is required");
|
|
6
6
|
}
|
|
7
7
|
const { internalId } = params;
|
|
8
8
|
// Find the product in the cart
|
|
@@ -20,13 +20,13 @@ export const mockRemoveProductFromCart = async (params) => {
|
|
|
20
20
|
MOCK_CART.amountToBeCharged = MOCK_CART.total;
|
|
21
21
|
MOCK_CART.remainingBalance = MOCK_CART.total;
|
|
22
22
|
// Publish product-deleted event
|
|
23
|
-
mockPublishEvent(
|
|
23
|
+
mockPublishEvent("cart", "product-deleted", {
|
|
24
24
|
product: product,
|
|
25
25
|
internalId: internalId
|
|
26
26
|
});
|
|
27
|
-
return {
|
|
27
|
+
return Promise.resolve({
|
|
28
28
|
success: true,
|
|
29
29
|
internalId: internalId,
|
|
30
30
|
timestamp: new Date().toISOString()
|
|
31
|
-
};
|
|
31
|
+
});
|
|
32
32
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const mockResolveExtensionOverlay = async (_params) => ({ success: true });
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { InterceptorReturn } from "../../interceptors/types";
|
|
2
|
+
export interface ResolveExtensionOverlayParams {
|
|
3
|
+
overlayId: string;
|
|
4
|
+
result: InterceptorReturn;
|
|
5
|
+
}
|
|
6
|
+
export interface ResolveExtensionOverlayResponse {
|
|
7
|
+
success: boolean;
|
|
8
|
+
}
|
|
9
|
+
export type ResolveExtensionOverlay = (params: ResolveExtensionOverlayParams) => Promise<ResolveExtensionOverlayResponse>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CFOrder } from "../../CommonTypes";
|
|
2
|
+
import type { CFTransitionResult } from "../../common-types/order-state";
|
|
2
3
|
export interface ResumeParkedOrderParams {
|
|
3
4
|
orderId: string;
|
|
4
5
|
}
|
|
@@ -6,5 +7,7 @@ export interface ResumeParkedOrderResponse {
|
|
|
6
7
|
success: boolean;
|
|
7
8
|
order: CFOrder;
|
|
8
9
|
timestamp: string;
|
|
10
|
+
/** Present when the state machine blocked or forced the transition. */
|
|
11
|
+
transitionResult?: CFTransitionResult;
|
|
9
12
|
}
|
|
10
13
|
export type ResumeParkedOrder = (params?: ResumeParkedOrderParams) => Promise<ResumeParkedOrderResponse>;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { CFOrder } from "../../CommonTypes";
|
|
2
|
+
import type { CFTransitionResult } from "../../common-types/order-state";
|
|
2
3
|
export interface TapToPayPaymentParams {
|
|
3
4
|
/** If not provided, uses the cart total. */
|
|
4
5
|
amount?: number;
|
|
6
|
+
/** Override the fulfillment state after full payment. Render resolves the cascade. */
|
|
7
|
+
checkoutFulfillmentTarget?: string;
|
|
5
8
|
}
|
|
6
9
|
export interface TapToPayPaymentResponse {
|
|
7
10
|
success: boolean;
|
|
@@ -9,5 +12,7 @@ export interface TapToPayPaymentResponse {
|
|
|
9
12
|
paymentType: string;
|
|
10
13
|
order: CFOrder | null;
|
|
11
14
|
timestamp: string;
|
|
15
|
+
/** Present when the state machine blocked or forced the transition. */
|
|
16
|
+
transitionResult?: CFTransitionResult;
|
|
12
17
|
}
|
|
13
18
|
export type TapToPayPayment = (params?: TapToPayPaymentParams) => Promise<TapToPayPaymentResponse>;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { CFOrder } from "../../CommonTypes";
|
|
2
|
+
import type { CFTransitionResult } from "../../common-types/order-state";
|
|
2
3
|
export interface TerminalPaymentParams {
|
|
3
4
|
/** If not provided, uses the cart total. */
|
|
4
5
|
amount?: number;
|
|
5
6
|
/** "Bluetooth" or "Cloud". Defaults to "Cloud". */
|
|
6
7
|
paymentType?: 'Bluetooth' | 'Cloud';
|
|
8
|
+
/** Override the fulfillment state after full payment. Render resolves the cascade. */
|
|
9
|
+
checkoutFulfillmentTarget?: string;
|
|
7
10
|
}
|
|
8
11
|
export interface TerminalPaymentResponse {
|
|
9
12
|
success: boolean;
|
|
@@ -11,5 +14,7 @@ export interface TerminalPaymentResponse {
|
|
|
11
14
|
paymentType: string;
|
|
12
15
|
order: CFOrder | null;
|
|
13
16
|
timestamp: string;
|
|
17
|
+
/** Present when the state machine blocked or forced the transition. */
|
|
18
|
+
transitionResult?: CFTransitionResult;
|
|
14
19
|
}
|
|
15
20
|
export type TerminalPayment = (params?: TerminalPaymentParams) => Promise<TerminalPaymentResponse>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { MOCK_CART, mockPublishEvent } from "../../demo/database";
|
|
2
|
-
export const mockUpdateCartItemQuantity =
|
|
2
|
+
export const mockUpdateCartItemQuantity = (params) => {
|
|
3
3
|
console.log("[Mock] updateCartItemQuantity called", params);
|
|
4
4
|
if (!params?.internalId) {
|
|
5
|
-
throw new Error(
|
|
5
|
+
throw new Error("internalId is required");
|
|
6
6
|
}
|
|
7
7
|
if (params.quantity === undefined || params.quantity === null) {
|
|
8
|
-
throw new Error(
|
|
8
|
+
throw new Error("quantity is required");
|
|
9
9
|
}
|
|
10
10
|
const { internalId, quantity } = params;
|
|
11
11
|
// Find the product in the cart
|
|
@@ -25,16 +25,16 @@ export const mockUpdateCartItemQuantity = async (params) => {
|
|
|
25
25
|
MOCK_CART.amountToBeCharged = MOCK_CART.total;
|
|
26
26
|
MOCK_CART.remainingBalance = MOCK_CART.total;
|
|
27
27
|
// Publish product-deleted event
|
|
28
|
-
mockPublishEvent(
|
|
28
|
+
mockPublishEvent("cart", "product-deleted", {
|
|
29
29
|
product: product,
|
|
30
30
|
internalId: internalId
|
|
31
31
|
});
|
|
32
|
-
return {
|
|
32
|
+
return Promise.resolve({
|
|
33
33
|
success: true,
|
|
34
34
|
internalId: internalId,
|
|
35
35
|
quantity: 0,
|
|
36
36
|
timestamp: new Date().toISOString()
|
|
37
|
-
};
|
|
37
|
+
});
|
|
38
38
|
}
|
|
39
39
|
// Update quantity
|
|
40
40
|
const quantityDelta = quantity - previousQuantity;
|
|
@@ -46,15 +46,15 @@ export const mockUpdateCartItemQuantity = async (params) => {
|
|
|
46
46
|
MOCK_CART.amountToBeCharged = MOCK_CART.total;
|
|
47
47
|
MOCK_CART.remainingBalance = MOCK_CART.total;
|
|
48
48
|
// Publish product-updated event
|
|
49
|
-
mockPublishEvent(
|
|
49
|
+
mockPublishEvent("cart", "product-updated", {
|
|
50
50
|
product: product,
|
|
51
51
|
previousQuantity: previousQuantity,
|
|
52
52
|
newQuantity: quantity
|
|
53
53
|
});
|
|
54
|
-
return {
|
|
54
|
+
return Promise.resolve({
|
|
55
55
|
success: true,
|
|
56
56
|
internalId: internalId,
|
|
57
57
|
quantity: quantity,
|
|
58
58
|
timestamp: new Date().toISOString()
|
|
59
|
-
};
|
|
59
|
+
});
|
|
60
60
|
};
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { CFOrder } from "../../CommonTypes";
|
|
2
|
+
import type { CFTransitionResult } from "../../common-types/order-state";
|
|
2
3
|
export interface VendaraPaymentParams {
|
|
3
4
|
/** If not provided, uses the cart total. */
|
|
4
5
|
amount?: number;
|
|
6
|
+
/** Override the fulfillment state after full payment. Render resolves the cascade. */
|
|
7
|
+
checkoutFulfillmentTarget?: string;
|
|
5
8
|
}
|
|
6
9
|
export interface VendaraPaymentResponse {
|
|
7
10
|
success: boolean;
|
|
@@ -9,5 +12,7 @@ export interface VendaraPaymentResponse {
|
|
|
9
12
|
paymentType: string;
|
|
10
13
|
order: CFOrder | null;
|
|
11
14
|
timestamp: string;
|
|
15
|
+
/** Present when the state machine blocked or forced the transition. */
|
|
16
|
+
transitionResult?: CFTransitionResult;
|
|
12
17
|
}
|
|
13
18
|
export type VendaraPayment = (params?: VendaraPaymentParams) => Promise<VendaraPaymentResponse>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State machine protocol types for the command-frame boundary.
|
|
3
|
+
* These mirror @final-commerce/common shapes but carry no logic.
|
|
4
|
+
* command-frame must NOT depend on common.
|
|
5
|
+
*/
|
|
6
|
+
export interface CFStatePair {
|
|
7
|
+
payment: string;
|
|
8
|
+
fulfillment: string;
|
|
9
|
+
}
|
|
10
|
+
export type CFBlockedBy = "financial_invariant" | "cross_axis_rule" | "path" | "condition";
|
|
11
|
+
export interface CFTransitionResult {
|
|
12
|
+
allowed: boolean;
|
|
13
|
+
blockedBy?: CFBlockedBy;
|
|
14
|
+
guard?: string;
|
|
15
|
+
reason?: string;
|
|
16
|
+
failedConditions?: CFFailedCondition[];
|
|
17
|
+
}
|
|
18
|
+
export interface CFFailedCondition {
|
|
19
|
+
field: string;
|
|
20
|
+
operator: string;
|
|
21
|
+
value: unknown;
|
|
22
|
+
reason?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface CFConditionStatus {
|
|
25
|
+
met: boolean;
|
|
26
|
+
description: string;
|
|
27
|
+
}
|
|
28
|
+
export interface CFAvailableTransition {
|
|
29
|
+
to: CFStatePair;
|
|
30
|
+
displayLabel: string;
|
|
31
|
+
conditions: CFConditionStatus[];
|
|
32
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State config fragment types for the command-frame boundary.
|
|
3
|
+
* These mirror @final-commerce/common's StateConfigFragment shapes but carry no logic.
|
|
4
|
+
* command-frame must NOT depend on common.
|
|
5
|
+
*
|
|
6
|
+
* Extensions pass a CFStateConfigFragment to Render, which merges it into the
|
|
7
|
+
* running StoredStateConfig via mergeFragment(). All contributed entries are tagged
|
|
8
|
+
* with the extension's id (_sourceExtensionId) so they can be cleaned up on unregister.
|
|
9
|
+
*/
|
|
10
|
+
import type { CFStatePair } from "./order-state";
|
|
11
|
+
export type CFConditionOperator = "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "notIn" | "isEmpty" | "isNotEmpty";
|
|
12
|
+
export interface CFCondition {
|
|
13
|
+
/** Dot-path into the OrderContext, e.g. "order.balance" or "computed.totalPaid". */
|
|
14
|
+
field: string;
|
|
15
|
+
operator: CFConditionOperator;
|
|
16
|
+
value: unknown;
|
|
17
|
+
}
|
|
18
|
+
/** All conditions in a group are AND'd together. */
|
|
19
|
+
export interface CFConditionGroup {
|
|
20
|
+
conditions: CFCondition[];
|
|
21
|
+
}
|
|
22
|
+
/** Groups are OR'd — the first passing group satisfies the set. */
|
|
23
|
+
export interface CFTransitionConditionSet {
|
|
24
|
+
id: string;
|
|
25
|
+
label: string;
|
|
26
|
+
groups: CFConditionGroup[];
|
|
27
|
+
}
|
|
28
|
+
export interface CFPaymentTransitionPath {
|
|
29
|
+
from: string;
|
|
30
|
+
to: string;
|
|
31
|
+
/** References a CFTransitionConditionSet.id in the same fragment. */
|
|
32
|
+
conditionSetId?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface CFFulfillmentTransitionPath {
|
|
35
|
+
from: string;
|
|
36
|
+
to: string;
|
|
37
|
+
conditionSetId?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface CFCrossAxisRule {
|
|
40
|
+
id: string;
|
|
41
|
+
label: string;
|
|
42
|
+
description?: string;
|
|
43
|
+
enabled: boolean;
|
|
44
|
+
/** Which axis + target state(s) activate this rule. */
|
|
45
|
+
trigger: {
|
|
46
|
+
axis: "payment" | "fulfillment";
|
|
47
|
+
to: string[];
|
|
48
|
+
};
|
|
49
|
+
/** Which axis + states must be present when the trigger fires. */
|
|
50
|
+
requires: {
|
|
51
|
+
axis: "payment" | "fulfillment";
|
|
52
|
+
states: string[];
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export interface CFDisplayStateRule {
|
|
56
|
+
paymentState?: string[];
|
|
57
|
+
fulfillmentState?: string[];
|
|
58
|
+
label: string;
|
|
59
|
+
color?: string;
|
|
60
|
+
icon?: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Partial config contributed by an extension. Render merges this into the
|
|
64
|
+
* running StoredStateConfig. All arrays are appended; display rules replace
|
|
65
|
+
* on key collision.
|
|
66
|
+
*
|
|
67
|
+
* IDs (crossAxisRules, transitionConditions) must be unique across the merged
|
|
68
|
+
* config — prefix them with your extension id to avoid collisions.
|
|
69
|
+
*/
|
|
70
|
+
export interface CFStateConfigFragment {
|
|
71
|
+
paymentPaths?: CFPaymentTransitionPath[];
|
|
72
|
+
fulfillmentPaths?: CFFulfillmentTransitionPath[];
|
|
73
|
+
crossAxisRules?: CFCrossAxisRule[];
|
|
74
|
+
transitionConditions?: CFTransitionConditionSet[];
|
|
75
|
+
validInitialStates?: CFStatePair[];
|
|
76
|
+
displayStateMap?: CFDisplayStateRule[];
|
|
77
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State config fragment types for the command-frame boundary.
|
|
3
|
+
* These mirror @final-commerce/common's StateConfigFragment shapes but carry no logic.
|
|
4
|
+
* command-frame must NOT depend on common.
|
|
5
|
+
*
|
|
6
|
+
* Extensions pass a CFStateConfigFragment to Render, which merges it into the
|
|
7
|
+
* running StoredStateConfig via mergeFragment(). All contributed entries are tagged
|
|
8
|
+
* with the extension's id (_sourceExtensionId) so they can be cleaned up on unregister.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
package/dist/demo/database.js
CHANGED
|
@@ -335,6 +335,9 @@ export const MOCK_ORDER_1 = {
|
|
|
335
335
|
companyId: MOCK_COMPANY.id,
|
|
336
336
|
externalId: null,
|
|
337
337
|
status: "completed",
|
|
338
|
+
paymentState: "paid",
|
|
339
|
+
fulfillmentState: "fulfilled",
|
|
340
|
+
displayState: "Completed",
|
|
338
341
|
customer: MOCK_CUSTOMER_1,
|
|
339
342
|
summary: {
|
|
340
343
|
total: 2100,
|
|
@@ -382,6 +385,9 @@ export const MOCK_ORDER_2 = {
|
|
|
382
385
|
companyId: MOCK_COMPANY.id,
|
|
383
386
|
externalId: null,
|
|
384
387
|
status: "completed",
|
|
388
|
+
paymentState: "paid",
|
|
389
|
+
fulfillmentState: "fulfilled",
|
|
390
|
+
displayState: "Completed",
|
|
385
391
|
customer: MOCK_CUSTOMER_2,
|
|
386
392
|
summary: {
|
|
387
393
|
total: 3000,
|
|
@@ -607,6 +613,9 @@ export const createOrderFromCart = (paymentType, amount, processor = "cash") =>
|
|
|
607
613
|
companyId: MOCK_COMPANY.id,
|
|
608
614
|
externalId: null,
|
|
609
615
|
status: "completed",
|
|
616
|
+
paymentState: "paid",
|
|
617
|
+
fulfillmentState: "fulfilled",
|
|
618
|
+
displayState: "Completed",
|
|
610
619
|
customer: MOCK_CART.customer ? MOCK_CART.customer : null,
|
|
611
620
|
summary: {
|
|
612
621
|
total: totalNum,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { preorderNoDepositFragment } from "./preorder-no-deposit";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { preorderNoDepositFragment } from "./preorder-no-deposit";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { CFStateConfigFragment } from "../common-types/state-fragment";
|
|
2
|
+
/**
|
|
3
|
+
* Pre-order fragment — no deposit required.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors preorder-with-deposit but removes the cross-axis rule that gates
|
|
6
|
+
* `on_hold` on payment state. An order can be placed on hold while still
|
|
7
|
+
* `unpaid` — payment is collected later (pay-at-pickup, BOPIS, COD, etc.).
|
|
8
|
+
*
|
|
9
|
+
* State flow:
|
|
10
|
+
*
|
|
11
|
+
* unpaid|on_hold → (cashier collects payment) → paid|on_hold
|
|
12
|
+
* ↓
|
|
13
|
+
* (progress fulfillment)
|
|
14
|
+
* ↓
|
|
15
|
+
* paid|in_progress
|
|
16
|
+
*
|
|
17
|
+
* Key difference from preorder-with-deposit:
|
|
18
|
+
* - No cross-axis rule blocking `on_hold` when unpaid. The cashier can
|
|
19
|
+
* confirm the pre-order without collecting a deposit first.
|
|
20
|
+
* - `unpaid|on_hold` is whitelisted as a valid first-save state pair.
|
|
21
|
+
* - `in_progress` still requires at least a partial payment (you must pay
|
|
22
|
+
* before the merchant starts fulfilling).
|
|
23
|
+
*
|
|
24
|
+
* Prefix all IDs with your extension id before merging to avoid collisions.
|
|
25
|
+
*/
|
|
26
|
+
export declare const preorderNoDepositFragment: CFStateConfigFragment;
|