@final-commerce/command-frame 0.1.72 → 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.
Files changed (88) hide show
  1. package/README.md +50 -28
  2. package/dist/CommonTypes.d.ts +143 -7
  3. package/dist/CommonTypes.js +112 -0
  4. package/dist/actions/apply-transition/action.d.ts +2 -0
  5. package/dist/actions/apply-transition/action.js +4 -0
  6. package/dist/actions/apply-transition/mock.d.ts +6 -0
  7. package/dist/actions/apply-transition/mock.js +33 -0
  8. package/dist/actions/apply-transition/types.d.ts +17 -0
  9. package/dist/actions/apply-transition/types.js +1 -0
  10. package/dist/actions/can-transition/action.d.ts +2 -0
  11. package/dist/actions/can-transition/action.js +4 -0
  12. package/dist/actions/can-transition/mock.d.ts +6 -0
  13. package/dist/actions/can-transition/mock.js +28 -0
  14. package/dist/actions/can-transition/types.d.ts +11 -0
  15. package/dist/actions/can-transition/types.js +1 -0
  16. package/dist/actions/cash-payment/types.d.ts +5 -0
  17. package/dist/actions/delete-parked-order/types.d.ts +3 -0
  18. package/dist/actions/extension-payment/types.d.ts +5 -0
  19. package/dist/actions/get-available-transitions/action.d.ts +2 -0
  20. package/dist/actions/get-available-transitions/action.js +4 -0
  21. package/dist/actions/get-available-transitions/mock.d.ts +6 -0
  22. package/dist/actions/get-available-transitions/mock.js +26 -0
  23. package/dist/actions/get-available-transitions/types.d.ts +9 -0
  24. package/dist/actions/get-available-transitions/types.js +1 -0
  25. package/dist/actions/get-smart-grid-layout/action.d.ts +2 -0
  26. package/dist/actions/get-smart-grid-layout/action.js +4 -0
  27. package/dist/actions/get-smart-grid-layout/mock.d.ts +2 -0
  28. package/dist/actions/get-smart-grid-layout/mock.js +9 -0
  29. package/dist/actions/get-smart-grid-layout/types.d.ts +10 -0
  30. package/dist/actions/get-smart-grid-layout/types.js +1 -0
  31. package/dist/actions/initiate-refund/types.d.ts +3 -0
  32. package/dist/actions/open-extension-overlay/mock.d.ts +2 -0
  33. package/dist/actions/open-extension-overlay/mock.js +1 -0
  34. package/dist/actions/open-extension-overlay/types.d.ts +9 -0
  35. package/dist/actions/open-extension-overlay/types.js +1 -0
  36. package/dist/actions/park-order/types.d.ts +3 -0
  37. package/dist/actions/partial-payment/types.d.ts +5 -0
  38. package/dist/actions/process-partial-refund/types.d.ts +3 -0
  39. package/dist/actions/remove-product-from-cart/mock.js +5 -5
  40. package/dist/actions/resolve-extension-overlay/mock.d.ts +2 -0
  41. package/dist/actions/resolve-extension-overlay/mock.js +1 -0
  42. package/dist/actions/resolve-extension-overlay/types.d.ts +9 -0
  43. package/dist/actions/resolve-extension-overlay/types.js +1 -0
  44. package/dist/actions/resume-parked-order/types.d.ts +3 -0
  45. package/dist/actions/save-smart-grid-layout/action.d.ts +2 -0
  46. package/dist/actions/save-smart-grid-layout/action.js +4 -0
  47. package/dist/actions/save-smart-grid-layout/mock.d.ts +2 -0
  48. package/dist/actions/save-smart-grid-layout/mock.js +10 -0
  49. package/dist/actions/save-smart-grid-layout/types.d.ts +10 -0
  50. package/dist/actions/save-smart-grid-layout/types.js +1 -0
  51. package/dist/actions/tap-to-pay-payment/types.d.ts +5 -0
  52. package/dist/actions/terminal-payment/types.d.ts +5 -0
  53. package/dist/actions/update-cart-item-quantity/mock.js +9 -9
  54. package/dist/actions/vendara-payment/types.d.ts +5 -0
  55. package/dist/common-types/index.d.ts +1 -0
  56. package/dist/common-types/index.js +1 -0
  57. package/dist/common-types/order-state.d.ts +32 -0
  58. package/dist/common-types/order-state.js +6 -0
  59. package/dist/common-types/state-fragment.d.ts +77 -0
  60. package/dist/common-types/state-fragment.js +10 -0
  61. package/dist/demo/database.d.ts +2 -1
  62. package/dist/demo/database.js +13 -0
  63. package/dist/fragments/index.d.ts +1 -0
  64. package/dist/fragments/index.js +1 -0
  65. package/dist/fragments/preorder-no-deposit.d.ts +26 -0
  66. package/dist/fragments/preorder-no-deposit.js +166 -0
  67. package/dist/index.d.ts +18 -4
  68. package/dist/index.js +19 -3
  69. package/dist/interceptors/index.d.ts +21 -0
  70. package/dist/interceptors/index.js +53 -0
  71. package/dist/interceptors/types.d.ts +26 -0
  72. package/dist/interceptors/types.js +1 -0
  73. package/dist/projects/render/mocks.js +13 -1
  74. package/dist/projects/render/types.d.ts +9 -1
  75. package/dist/pubsub/topics/orders/index.js +10 -0
  76. package/dist/pubsub/topics/orders/state-transition-blocked/types.d.ts +16 -0
  77. package/dist/pubsub/topics/orders/state-transition-blocked/types.js +1 -0
  78. package/dist/pubsub/topics/orders/state-transition-completed/types.d.ts +15 -0
  79. package/dist/pubsub/topics/orders/state-transition-completed/types.js +1 -0
  80. package/dist/pubsub/topics/orders/types.d.ts +6 -2
  81. package/dist/pubsub/topics/orders/types.js +2 -0
  82. package/package.json +1 -1
  83. package/dist/actions/extension-refund/constants.d.ts +0 -2
  84. package/dist/actions/extension-refund/constants.js +0 -2
  85. package/dist/actions/extension-refund/extension-refund-listener.d.ts +0 -11
  86. package/dist/actions/extension-refund/extension-refund-listener.js +0 -60
  87. package/dist/actions/extension-refund/types.d.ts +0 -32
  88. package/dist/actions/extension-refund/types.js +0 -5
@@ -0,0 +1,6 @@
1
+ import type { GetAvailableTransitionsParams, GetAvailableTransitionsResponse } from "./types";
2
+ /**
3
+ * Mock implementation: returns a fixed set of plausible transitions
4
+ * so the demo app has data to render.
5
+ */
6
+ export declare const getAvailableTransitionsMock: (_params: GetAvailableTransitionsParams) => Promise<GetAvailableTransitionsResponse>;
@@ -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 {};
@@ -0,0 +1,2 @@
1
+ import type { GetSmartGridLayout } from "./types";
2
+ export declare const getSmartGridLayout: GetSmartGridLayout;
@@ -0,0 +1,4 @@
1
+ import { commandFrameClient } from "../../client";
2
+ export const getSmartGridLayout = async (params) => {
3
+ return await commandFrameClient.call("getSmartGridLayout", params);
4
+ };
@@ -0,0 +1,2 @@
1
+ import { GetSmartGridLayout } from "./types";
2
+ export declare const mockGetSmartGridLayout: GetSmartGridLayout;
@@ -0,0 +1,9 @@
1
+ import { MOCK_SMART_GRID_LAYOUTS } from "../../demo/database";
2
+ export const mockGetSmartGridLayout = (params) => {
3
+ console.log("[Mock] getSmartGridLayout called", params);
4
+ return Promise.resolve({
5
+ success: true,
6
+ layout: MOCK_SMART_GRID_LAYOUTS[params.gridId] ?? null,
7
+ timestamp: new Date().toISOString()
8
+ });
9
+ };
@@ -0,0 +1,10 @@
1
+ import { CFSmartGridLayout } from "../../CommonTypes";
2
+ export interface GetSmartGridLayoutParams {
3
+ gridId: string;
4
+ }
5
+ export interface GetSmartGridLayoutResponse {
6
+ success: boolean;
7
+ layout: CFSmartGridLayout | null;
8
+ timestamp: string;
9
+ }
10
+ export type GetSmartGridLayout = (params: GetSmartGridLayoutParams) => Promise<GetSmartGridLayoutResponse>;
@@ -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,2 @@
1
+ import type { OpenExtensionOverlay } from "./types";
2
+ export declare const mockOpenExtensionOverlay: OpenExtensionOverlay;
@@ -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 = async (params) => {
2
+ export const mockRemoveProductFromCart = (params) => {
3
3
  console.log("[Mock] removeProductFromCart called", params);
4
4
  if (!params?.internalId) {
5
- throw new Error('internalId is required');
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('cart', 'product-deleted', {
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,2 @@
1
+ import type { ResolveExtensionOverlay } from "./types";
2
+ export declare const mockResolveExtensionOverlay: ResolveExtensionOverlay;
@@ -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>;
@@ -0,0 +1,2 @@
1
+ import type { SaveSmartGridLayout } from "./types";
2
+ export declare const saveSmartGridLayout: SaveSmartGridLayout;
@@ -0,0 +1,4 @@
1
+ import { commandFrameClient } from "../../client";
2
+ export const saveSmartGridLayout = async (params) => {
3
+ return await commandFrameClient.call("saveSmartGridLayout", params);
4
+ };
@@ -0,0 +1,2 @@
1
+ import { SaveSmartGridLayout } from "./types";
2
+ export declare const mockSaveSmartGridLayout: SaveSmartGridLayout;
@@ -0,0 +1,10 @@
1
+ import { MOCK_SMART_GRID_LAYOUTS } from "../../demo/database";
2
+ export const mockSaveSmartGridLayout = (params) => {
3
+ console.log("[Mock] saveSmartGridLayout called", params);
4
+ MOCK_SMART_GRID_LAYOUTS[params.layout.gridId] = params.layout;
5
+ return Promise.resolve({
6
+ success: true,
7
+ gridId: params.layout.gridId,
8
+ timestamp: new Date().toISOString()
9
+ });
10
+ };
@@ -0,0 +1,10 @@
1
+ import { CFSmartGridLayout } from "../../CommonTypes";
2
+ export interface SaveSmartGridLayoutParams {
3
+ layout: CFSmartGridLayout;
4
+ }
5
+ export interface SaveSmartGridLayoutResponse {
6
+ success: boolean;
7
+ gridId: string;
8
+ timestamp: string;
9
+ }
10
+ export type SaveSmartGridLayout = (params: SaveSmartGridLayoutParams) => Promise<SaveSmartGridLayoutResponse>;
@@ -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 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 = async (params) => {
2
+ export const mockUpdateCartItemQuantity = (params) => {
3
3
  console.log("[Mock] updateCartItemQuantity called", params);
4
4
  if (!params?.internalId) {
5
- throw new Error('internalId is required');
5
+ throw new Error("internalId is required");
6
6
  }
7
7
  if (params.quantity === undefined || params.quantity === null) {
8
- throw new Error('quantity is required');
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('cart', 'product-deleted', {
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('cart', 'product-updated', {
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>;
@@ -1,2 +1,3 @@
1
1
  export * from "./custom-tables";
2
2
  export * from "./custom-extensions";
3
+ export * from "./order-state";
@@ -1,2 +1,3 @@
1
1
  export * from "./custom-tables";
2
2
  export * from "./custom-extensions";
3
+ export * from "./order-state";
@@ -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,6 @@
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 {};
@@ -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 {};
@@ -2,7 +2,7 @@
2
2
  * Mock Database for Standalone/Demo Mode
3
3
  * Stores mock data that mimics the Render environment
4
4
  */
5
- import { CFActiveCompany, CFActiveUser, CFActiveStation, CFActiveOutlet, CFActiveOrder, CFCustomer, CFProduct, CFActiveCart, CFCategory, CFActiveProduct, CFSession, CFActiveRefundDetails } from "../CommonTypes";
5
+ import { CFActiveCompany, CFActiveUser, CFActiveStation, CFActiveOutlet, CFActiveOrder, CFCustomer, CFProduct, CFActiveCart, CFCategory, CFActiveProduct, CFSession, CFActiveRefundDetails, CFSmartGridLayout } from "../CommonTypes";
6
6
  export * from "./mocks";
7
7
  /** Replace mock catalog / context data in place (same array references mock handlers use). */
8
8
  export interface MockDatabaseConfig {
@@ -64,6 +64,7 @@ export declare let MOCK_OUTLET: CFActiveOutlet;
64
64
  export declare let MOCK_CART: CFActiveCart;
65
65
  export declare let MOCK_ACTIVE_PRODUCT: CFActiveProduct;
66
66
  export declare const setMockActiveProduct: (activeProduct: CFActiveProduct) => void;
67
+ export declare const MOCK_SMART_GRID_LAYOUTS: Record<string, CFSmartGridLayout>;
67
68
  export declare const resetMockCart: () => void;
68
69
  /**
69
70
  * Replace in-memory mock data used by default mock handlers. Arrays are mutated in place
@@ -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,
@@ -463,6 +469,10 @@ export let MOCK_ACTIVE_PRODUCT;
463
469
  export const setMockActiveProduct = (activeProduct) => {
464
470
  MOCK_ACTIVE_PRODUCT = activeProduct;
465
471
  };
472
+ // In-memory smart-grid layouts keyed by gridId. Used by mockGetSmartGridLayout /
473
+ // mockSaveSmartGridLayout so the standalone builder (no command-frame host) can
474
+ // round-trip layouts within a session.
475
+ export const MOCK_SMART_GRID_LAYOUTS = {};
466
476
  // Helper to reset cart
467
477
  export const resetMockCart = () => {
468
478
  MOCK_CART = {
@@ -603,6 +613,9 @@ export const createOrderFromCart = (paymentType, amount, processor = "cash") =>
603
613
  companyId: MOCK_COMPANY.id,
604
614
  externalId: null,
605
615
  status: "completed",
616
+ paymentState: "paid",
617
+ fulfillmentState: "fulfilled",
618
+ displayState: "Completed",
606
619
  customer: MOCK_CART.customer ? MOCK_CART.customer : null,
607
620
  summary: {
608
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;