@final-commerce/command-frame 0.5.0 → 0.6.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.
Files changed (69) hide show
  1. package/README.md +5 -5
  2. package/dist/CommonTypes.d.ts +6 -6
  3. package/dist/CommonTypes.js +2 -2
  4. package/dist/actions/add-cart-discount/mock.d.ts +1 -1
  5. package/dist/actions/add-cart-discount/mock.js +8 -8
  6. package/dist/actions/add-cart-fee/mock.d.ts +1 -1
  7. package/dist/actions/add-cart-fee/mock.js +8 -8
  8. package/dist/actions/add-product-to-cart/mock.d.ts +1 -1
  9. package/dist/actions/add-product-to-cart/mock.js +24 -10
  10. package/dist/actions/add-product-to-cart/types.d.ts +13 -1
  11. package/dist/actions/adjust-inventory/mock.d.ts +1 -1
  12. package/dist/actions/adjust-inventory/mock.js +6 -6
  13. package/dist/actions/apply-transition/mock.d.ts +1 -1
  14. package/dist/actions/apply-transition/mock.js +8 -8
  15. package/dist/actions/apply-transition/types.d.ts +1 -1
  16. package/dist/actions/authenticate-user/mock.d.ts +1 -1
  17. package/dist/actions/authenticate-user/mock.js +3 -3
  18. package/dist/actions/calculate-refund-total/action.d.ts +1 -1
  19. package/dist/actions/calculate-refund-total/action.js +2 -2
  20. package/dist/actions/can-transition/types.d.ts +1 -1
  21. package/dist/actions/cash-payment/mock.d.ts +1 -1
  22. package/dist/actions/cash-payment/mock.js +10 -10
  23. package/dist/actions/cash-payment/types.d.ts +1 -1
  24. package/dist/actions/extension-payment/mock.d.ts +1 -1
  25. package/dist/actions/extension-payment/mock.js +3 -3
  26. package/dist/actions/extension-payment/types.d.ts +1 -1
  27. package/dist/actions/get-available-transitions/mock.d.ts +1 -1
  28. package/dist/actions/get-available-transitions/mock.js +19 -19
  29. package/dist/actions/get-final-context/mock.d.ts +1 -1
  30. package/dist/actions/get-final-context/mock.js +2 -2
  31. package/dist/actions/get-products/mock.d.ts +1 -1
  32. package/dist/actions/get-products/mock.js +26 -9
  33. package/dist/actions/get-refunds/types.d.ts +1 -1
  34. package/dist/actions/get-remaining-refundable-quantities/action.d.ts +1 -1
  35. package/dist/actions/get-remaining-refundable-quantities/action.js +2 -2
  36. package/dist/actions/get-remaining-refundable-quantities/mock.d.ts +1 -1
  37. package/dist/actions/get-remaining-refundable-quantities/mock.js +2 -2
  38. package/dist/actions/integration-payment/types.d.ts +1 -1
  39. package/dist/actions/park-order/types.d.ts +1 -1
  40. package/dist/actions/partial-payment/mock.d.ts +1 -1
  41. package/dist/actions/partial-payment/mock.js +8 -8
  42. package/dist/actions/partial-payment/types.d.ts +1 -1
  43. package/dist/actions/print/mock.d.ts +1 -1
  44. package/dist/actions/print/mock.js +9 -9
  45. package/dist/actions/print/types.d.ts +6 -6
  46. package/dist/actions/redeem-payment/types.d.ts +1 -1
  47. package/dist/actions/remove-cart-fee/mock.d.ts +1 -1
  48. package/dist/actions/remove-cart-fee/mock.js +7 -7
  49. package/dist/actions/remove-product-from-cart/mock.d.ts +1 -1
  50. package/dist/actions/remove-product-from-cart/mock.js +11 -8
  51. package/dist/actions/resume-parked-order/types.d.ts +1 -1
  52. package/dist/actions/select-all-refund-items/action.d.ts +1 -1
  53. package/dist/actions/select-all-refund-items/action.js +2 -2
  54. package/dist/actions/set-active-product/mock.d.ts +1 -1
  55. package/dist/actions/set-active-product/mock.js +19 -14
  56. package/dist/actions/set-active-refund/types.d.ts +1 -1
  57. package/dist/actions/tap-to-pay-payment/mock.d.ts +1 -1
  58. package/dist/actions/tap-to-pay-payment/mock.js +6 -6
  59. package/dist/actions/tap-to-pay-payment/types.d.ts +1 -1
  60. package/dist/actions/terminal-payment/mock.d.ts +1 -1
  61. package/dist/actions/terminal-payment/mock.js +6 -6
  62. package/dist/actions/terminal-payment/types.d.ts +2 -2
  63. package/dist/actions/update-cart-item-quantity/mock.d.ts +1 -1
  64. package/dist/actions/update-cart-item-quantity/mock.js +23 -15
  65. package/dist/actions/update-cart-item-quantity/types.d.ts +8 -1
  66. package/dist/actions/upsert-custom-table-data/mock.d.ts +1 -1
  67. package/dist/actions/upsert-custom-table-data/mock.js +3 -3
  68. package/dist/demo/database.js +30 -4
  69. package/package.json +2 -2
package/README.md CHANGED
@@ -10,11 +10,11 @@ Command Frame provides a structured way to build integrations that run inside Fi
10
10
 
11
11
  The library provides three main capabilities:
12
12
 
13
- | Capability | Purpose | Scope |
14
- | ------------------- | ------------------------------------------------------------------------- | ----------------------------------------- |
15
- | **Commands** | Call host functions from the iframe (e.g. get products, open cash drawer) | Request/response per call |
16
- | **Pub/Sub** | Subscribe to real-time events from the host (e.g. cart changes, payments) | Page-scoped (while iframe is mounted) |
17
- | **Refund commands** | Refund payments to gift cards or redeem tenders via `redeemRefund`, or mixed-destination legs on `processPartialRefund`; query engine capacity with `getRefundPlan`; pre-gate UI with `checkPermission` (`issue_refunds` is enforced runtime-side) | Request/response per call |
13
+ | Capability | Purpose | Scope |
14
+ | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- |
15
+ | **Commands** | Call host functions from the iframe (e.g. get products, open cash drawer) | Request/response per call |
16
+ | **Pub/Sub** | Subscribe to real-time events from the host (e.g. cart changes, payments) | Page-scoped (while iframe is mounted) |
17
+ | **Refund commands** | Refund payments to gift cards or redeem tenders via `redeemRefund`, or mixed-destination legs on `processPartialRefund`; query engine capacity with `getRefundPlan`; pre-gate UI with `checkPermission` (`issue_refunds` is enforced runtime-side) | Request/response per call |
18
18
 
19
19
  Domain models (orders, cart, customers, products, and related types) are documented in **[Types reference](./src/types/README.md)**.
20
20
 
@@ -1,6 +1,6 @@
1
- export * from "./common-types";
2
- import type { Tax, Tip, Address, MetadataItem, PosDataItem, CartFeeTaxEntry, CartFeeItem, CartDiscountItem, OrderNote, NonRevenueItem, DiscountDetail, FeeDetail, DiscountLineItem, FeeLineItem, LineItem, TipPayment, RefundedTipPayment, PaymentMethod, Discount, CustomFee, Summary, CustomSale, RefundedCustomSale, RefundItem, RefundedLineItem, ActiveStation, ActiveSession, ActiveOutlet, ActiveUser, ActiveUserRole, ActiveOrder, ActiveCart, ActivePark, ActiveCompany, ActiveCustomSales, ActiveProduct, ActiveCustomer, FullProduct, ProductVariant, Inventory, CustomerNote, Attribute, AttributeOption, Category, Transaction, ActiveSplitPayment } from "@final-commerce/common/pos-types";
3
- export { CurrencyCode, ProductType as CFProductType, UserTypes as CFUserTypes } from "@final-commerce/common";
1
+ export * from './common-types';
2
+ import type { Tax, Tip, Address, MetadataItem, PosDataItem, CartFeeTaxEntry, CartFeeItem, CartDiscountItem, OrderNote, NonRevenueItem, DiscountDetail, FeeDetail, DiscountLineItem, FeeLineItem, LineItem, TipPayment, RefundedTipPayment, PaymentMethod, Discount, CustomFee, Summary, CustomSale, RefundedCustomSale, RefundItem, RefundedLineItem, ActiveStation, ActiveSession, ActiveOutlet, ActiveUser, ActiveUserRole, ActiveOrder, ActiveCart, ActivePark, ActiveCompany, ActiveCustomSales, ActiveProduct, ActiveCustomer, FullProduct, ProductVariant, Inventory, CustomerNote, Attribute, AttributeOption, Category, Transaction, ActiveSplitPayment } from '@final-commerce/common/pos-types';
3
+ export { CurrencyCode, ProductType as CFProductType, UserTypes as CFUserTypes } from '@final-commerce/common';
4
4
  /** Open record used as a base for active entities. */
5
5
  export type CFActiveEntity = Record<string, unknown>;
6
6
  export type CFDiscount = Discount;
@@ -52,7 +52,7 @@ export type CFActiveCart = ActiveCart;
52
52
  export type CFActivePark = ActivePark;
53
53
  export type CFActiveCompany = ActiveCompany;
54
54
  /** Tile kinds a SmartGrid cell can represent. Mirrors common's `BaseTile['type']`. */
55
- export type CFTileType = "empty" | "product" | "action" | "category" | "folder" | "back";
55
+ export type CFTileType = 'empty' | 'product' | 'action' | 'category' | 'folder' | 'back';
56
56
  /**
57
57
  * A single positioned cell in a SmartGrid layout. The wire/extension-facing shape
58
58
  * (Render's adapter maps this to/from common's `BaseTile`).
@@ -96,7 +96,7 @@ export interface CFActiveRefundDetails {
96
96
  refundProcessingStatus?: CFRefundProcessingStatus | null;
97
97
  sessionRefundedTotal?: number;
98
98
  }
99
- export type CFProjectName = "kaching" | "Manage";
99
+ export type CFProjectName = 'kaching' | 'Manage';
100
100
  export interface CFContextRender {
101
101
  userId: string | null;
102
102
  companyId: string | null;
@@ -126,7 +126,7 @@ export interface CFContextRender {
126
126
  thousandSeparator: string | null;
127
127
  decimalSeparator: string | null;
128
128
  user: Record<string, unknown> | null;
129
- company: Omit<Record<string, unknown>, "settings"> | null;
129
+ company: Omit<Record<string, unknown>, 'settings'> | null;
130
130
  station: Record<string, unknown> | null;
131
131
  outlet: Record<string, unknown> | null;
132
132
  timestamp: string;
@@ -1,6 +1,6 @@
1
- export * from "./common-types";
1
+ export * from './common-types';
2
2
  // Enums — re-exported from common (single source). CurrencyCode keeps its name;
3
3
  // CFProductType/CFUserTypes alias common's ProductType/UserTypes. Note: common's
4
4
  // UserTypes uses `COMPANY_OWNER` where command-frame's enum previously had `OWNER`
5
5
  // (same value `'owner'`).
6
- export { CurrencyCode, ProductType as CFProductType, UserTypes as CFUserTypes } from "@final-commerce/common";
6
+ export { CurrencyCode, ProductType as CFProductType, UserTypes as CFUserTypes } from '@final-commerce/common';
@@ -1,2 +1,2 @@
1
- import { AddCartDiscount } from "./types";
1
+ import { AddCartDiscount } from './types';
2
2
  export declare const mockAddCartDiscount: AddCartDiscount;
@@ -1,18 +1,18 @@
1
- import { MOCK_CART, mockPublishEvent } from "../../demo/database";
2
- import { percentToFraction, requireMinorUnitsInteger } from "../../demo/units";
1
+ import { MOCK_CART, mockPublishEvent } from '../../demo/database';
2
+ import { percentToFraction, requireMinorUnitsInteger } from '../../demo/units';
3
3
  export const mockAddCartDiscount = async (params) => {
4
- console.log("[Mock] addCartDiscount called", params);
4
+ console.log('[Mock] addCartDiscount called', params);
5
5
  if (params) {
6
6
  // FI-6991: a fixed amount arrives as an INTEGER in MINOR units (500 =
7
7
  // $5.00) and is stored directly; a percent arrives raw (50 = 50%) and is
8
8
  // stored as a fraction (0.5). Same as the real handler.
9
9
  const value = params.isPercent
10
10
  ? percentToFraction(params.amount)
11
- : requireMinorUnitsInteger(params.amount, "Discount amount");
11
+ : requireMinorUnitsInteger(params.amount, 'Discount amount');
12
12
  MOCK_CART.discount = {
13
13
  value,
14
14
  isPercent: params.isPercent,
15
- label: params.label
15
+ label: params.label,
16
16
  };
17
17
  if (params.isPercent) {
18
18
  MOCK_CART.total = MOCK_CART.subtotal * (1 - value);
@@ -24,14 +24,14 @@ export const mockAddCartDiscount = async (params) => {
24
24
  MOCK_CART.remainingBalance = MOCK_CART.total;
25
25
  // Publish cart-discount-added event
26
26
  mockPublishEvent('cart', 'cart-discount-added', {
27
- discount: MOCK_CART.discount
27
+ discount: MOCK_CART.discount,
28
28
  });
29
29
  }
30
30
  return {
31
31
  success: true,
32
32
  amount: params?.amount || 0,
33
33
  isPercent: params?.isPercent || false,
34
- label: params?.label || "",
35
- timestamp: new Date().toISOString()
34
+ label: params?.label || '',
35
+ timestamp: new Date().toISOString(),
36
36
  };
37
37
  };
@@ -1,2 +1,2 @@
1
- import { AddCartFee } from "./types";
1
+ import { AddCartFee } from './types';
2
2
  export declare const mockAddCartFee: AddCartFee;
@@ -1,7 +1,7 @@
1
- import { MOCK_CART } from "../../demo/database";
2
- import { percentToFraction, requireMinorUnitsInteger } from "../../demo/units";
1
+ import { MOCK_CART } from '../../demo/database';
2
+ import { percentToFraction, requireMinorUnitsInteger } from '../../demo/units';
3
3
  export const mockAddCartFee = async (params) => {
4
- console.log("[Mock] addCartFee called", params);
4
+ console.log('[Mock] addCartFee called', params);
5
5
  if (params) {
6
6
  if (!MOCK_CART.customFee)
7
7
  MOCK_CART.customFee = [];
@@ -10,13 +10,13 @@ export const mockAddCartFee = async (params) => {
10
10
  // stored as a fraction (0.5). Same as the real handler.
11
11
  const storedAmount = params.isPercent
12
12
  ? percentToFraction(params.amount)
13
- : requireMinorUnitsInteger(params.amount, "Fee amount");
13
+ : requireMinorUnitsInteger(params.amount, 'Fee amount');
14
14
  MOCK_CART.customFee.push({
15
- label: params.label || "Fee",
15
+ label: params.label || 'Fee',
16
16
  amount: storedAmount,
17
17
  isPercent: params.isPercent || false,
18
18
  applyTaxes: params.applyTaxes || false,
19
- taxTableId: params.taxTableId
19
+ taxTableId: params.taxTableId,
20
20
  });
21
21
  const feeAmount = params.isPercent ? MOCK_CART.subtotal * storedAmount : storedAmount;
22
22
  MOCK_CART.total += feeAmount;
@@ -27,8 +27,8 @@ export const mockAddCartFee = async (params) => {
27
27
  success: true,
28
28
  amount: params?.amount || 0,
29
29
  isPercent: params?.isPercent || false,
30
- label: params?.label || "",
30
+ label: params?.label || '',
31
31
  applyTaxes: params?.applyTaxes || false,
32
- timestamp: new Date().toISOString()
32
+ timestamp: new Date().toISOString(),
33
33
  };
34
34
  };
@@ -1,2 +1,2 @@
1
- import { AddProductToCart } from "./types";
1
+ import { AddProductToCart } from './types';
2
2
  export declare const mockAddProductToCart: AddProductToCart;
@@ -1,15 +1,19 @@
1
- import { MOCK_CART, MOCK_PRODUCTS, mockPublishEvent } from "../../demo/database";
1
+ import { MOCK_CART, MOCK_PRODUCTS, mockPublishEvent } from '../../demo/database';
2
+ import { extendPrice, isValidQuantity, resolveUnit } from '@final-commerce/common';
2
3
  export const mockAddProductToCart = async (params) => {
3
- console.log("[Mock] addProductToCart called", params);
4
+ console.log('[Mock] addProductToCart called', params);
4
5
  const variantId = params?.variantId;
5
6
  const quantity = params?.quantity || 1;
7
+ if (!Number.isFinite(quantity) || quantity <= 0) {
8
+ throw new Error(`${quantity} is not a quantity`);
9
+ }
6
10
  let product = MOCK_PRODUCTS[0]; // Default fallback
7
11
  let variant = product.variants[0];
8
12
  // Determine variant and product from variantId
9
13
  if (variantId) {
10
14
  // Search through all products to find the one containing this variant
11
15
  for (const p of MOCK_PRODUCTS) {
12
- const foundVariant = p.variants.find(v => v._id === variantId);
16
+ const foundVariant = p.variants.find((v) => v._id === variantId);
13
17
  if (foundVariant) {
14
18
  product = p;
15
19
  variant = foundVariant;
@@ -17,12 +21,20 @@ export const mockAddProductToCart = async (params) => {
17
21
  }
18
22
  }
19
23
  }
24
+ // A measured variant carries a resolved unit; the host does the same. What the unit can
25
+ // express is its precision — 1.5 of a kilogram is a sale, 1.5 of a piece is a typo.
26
+ const unit = variant.unitId ? resolveUnit(variant.unitId) : undefined;
27
+ if (!isValidQuantity(quantity, unit ?? { unitId: 'piece', ratioToBase: 1, precision: 0 })) {
28
+ throw new Error(unit
29
+ ? `${quantity} is finer than ${unit.abbreviation} can express (${unit.precision} decimals)`
30
+ : `${product.name} is sold by the piece, so ${quantity} is not a quantity it can sell in`);
31
+ }
20
32
  // Add to MOCK_CART
21
- const internalId = product._id + "_" + Date.now();
33
+ const internalId = product._id + '_' + Date.now();
22
34
  // Process optional fields for mock
23
35
  let note = undefined;
24
36
  if (params?.notes) {
25
- note = Array.isArray(params.notes) ? params.notes.join(", ") : params.notes;
37
+ note = Array.isArray(params.notes) ? params.notes.join(', ') : params.notes;
26
38
  }
27
39
  const activeProduct = {
28
40
  ...product,
@@ -33,16 +45,18 @@ export const mockAddProductToCart = async (params) => {
33
45
  price: Number(variant.price),
34
46
  taxTableId: product.taxTable,
35
47
  stock: variant.inventory?.[0]?.stock || 0,
48
+ ...(unit ? { unit } : {}),
36
49
  images: product.images || [],
37
50
  localQuantity: quantity,
38
51
  sku: variant.sku,
39
- attributes: variant.attributes.map(a => `${a.name}: ${a.value}`).join(", "),
40
- note: note
52
+ attributes: variant.attributes.map((a) => `${a.name}: ${a.value}`).join(', '),
53
+ note: note,
41
54
  // discount/fee could be added here to mock object if CFActiveProduct supports it
42
55
  };
43
56
  MOCK_CART.products.push(activeProduct);
44
- // Recalculate totals
45
- const lineTotal = activeProduct.price * quantity;
57
+ // Recalculate totals. extendPrice, not a raw multiply: a fractional quantity times an
58
+ // integer-minor price leaves fractional cents, which no order may carry.
59
+ const lineTotal = extendPrice(activeProduct.price, quantity);
46
60
  MOCK_CART.subtotal += lineTotal;
47
61
  // Simple total calculation (ignoring taxes/fees for mock simplicity unless needed)
48
62
  MOCK_CART.total += lineTotal;
@@ -57,6 +71,6 @@ export const mockAddProductToCart = async (params) => {
57
71
  internalId: activeProduct.internalId,
58
72
  name: activeProduct.name,
59
73
  quantity: quantity,
60
- timestamp: new Date().toISOString()
74
+ timestamp: new Date().toISOString(),
61
75
  };
62
76
  };
@@ -3,7 +3,19 @@ import type { AddProductFeeParams } from "../add-product-fee/types";
3
3
  export interface AddProductToCartParams {
4
4
  /** ID of the variant to add. */
5
5
  variantId: string;
6
- /** Defaults to 1. */
6
+ /**
7
+ * Defaults to 1. **May be fractional** — a variant sold by weight, volume or length is priced
8
+ * per its own unit and keyed in that unit, so `0.456` kg is a quantity, not a typo.
9
+ *
10
+ * How many decimals are allowed is the variant's own business: `variant.unit.precision` —
11
+ * `3` for a litre, `0` for anything sold by the piece. The engine refuses a quantity finer
12
+ * than that and says which unit it was measured against; do not round, floor or clamp before
13
+ * sending, and never key a quantity in base units to work around it (a per-100g price with a
14
+ * gram count is explicitly not supported).
15
+ *
16
+ * A quantity field should take its step and its decimal count from `variant.unit.precision`,
17
+ * not from a constant.
18
+ */
7
19
  quantity?: number;
8
20
  /** Array of discounts to apply immediately. */
9
21
  discounts?: AddProductDiscountParams[];
@@ -1,2 +1,2 @@
1
- import { AdjustInventory } from "./types";
1
+ import { AdjustInventory } from './types';
2
2
  export declare const mockAdjustInventory: AdjustInventory;
@@ -1,6 +1,6 @@
1
- import { MOCK_PRODUCTS } from "../../demo/database";
1
+ import { MOCK_PRODUCTS } from '../../demo/database';
2
2
  export const mockAdjustInventory = async (params) => {
3
- console.log("[Mock] adjustInventory called", params);
3
+ console.log('[Mock] adjustInventory called', params);
4
4
  let newStock = 0;
5
5
  // Real handler keys off variantId (falling back to the active product's
6
6
  // variant); mirror that here by finding the owning product for the variant.
@@ -8,7 +8,7 @@ export const mockAdjustInventory = async (params) => {
8
8
  const variantId = params.variantId;
9
9
  let variant;
10
10
  for (const product of MOCK_PRODUCTS) {
11
- const match = product.variants.find(v => v._id === variantId);
11
+ const match = product.variants.find((v) => v._id === variantId);
12
12
  if (match) {
13
13
  variant = match;
14
14
  break;
@@ -32,9 +32,9 @@ export const mockAdjustInventory = async (params) => {
32
32
  }
33
33
  return {
34
34
  success: true,
35
- amount: params?.amount || "0",
36
- stockType: params?.stockType || "set",
35
+ amount: params?.amount || '0',
36
+ stockType: params?.stockType || 'set',
37
37
  newStock,
38
- timestamp: new Date().toISOString()
38
+ timestamp: new Date().toISOString(),
39
39
  };
40
40
  };
@@ -1,4 +1,4 @@
1
- import type { ApplyTransitionParams, ApplyTransitionResponse } from "./types";
1
+ import type { ApplyTransitionParams, ApplyTransitionResponse } from './types';
2
2
  /**
3
3
  * Mock implementation: applies all transitions except a known-invalid one
4
4
  * so the demo app can show both successful and blocked responses.
@@ -4,20 +4,20 @@
4
4
  */
5
5
  export const applyTransitionMock = (params) => {
6
6
  const { targetFulfillmentState } = params;
7
- if (targetFulfillmentState === "cancelled") {
7
+ if (targetFulfillmentState === 'cancelled') {
8
8
  return Promise.resolve({
9
9
  result: {
10
10
  allowed: false,
11
- blockedBy: "condition",
12
- guard: "no-cancel-open-order",
13
- reason: "Cannot cancel an order with open items"
14
- }
11
+ blockedBy: 'condition',
12
+ guard: 'no-cancel-open-order',
13
+ reason: 'Cannot cancel an order with open items',
14
+ },
15
15
  });
16
16
  }
17
17
  return Promise.resolve({
18
18
  result: { allowed: true },
19
- from: { payment: "unpaid", fulfillment: "draft" },
20
- to: { payment: "unpaid", fulfillment: targetFulfillmentState },
21
- displayState: `unpaid / ${targetFulfillmentState}`
19
+ from: { payment: 'unpaid', fulfillment: 'draft' },
20
+ to: { payment: 'unpaid', fulfillment: targetFulfillmentState },
21
+ displayState: `unpaid / ${targetFulfillmentState}`,
22
22
  });
23
23
  };
@@ -1,4 +1,4 @@
1
- import type { CFStatePair, CFTransitionResult } from "../../common-types/order-state";
1
+ import type { CFStatePair, CFTransitionResult } from '../../common-types/order-state';
2
2
  export interface ApplyTransitionParams {
3
3
  /** Order to transition. Omit to target the active order — materializing one from the live cart if none exists. */
4
4
  orderId?: string;
@@ -1,2 +1,2 @@
1
- import { AuthenticateUser } from "./types";
1
+ import { AuthenticateUser } from './types';
2
2
  export declare const mockAuthenticateUser: AuthenticateUser;
@@ -1,12 +1,12 @@
1
1
  export const mockAuthenticateUser = async (params) => {
2
- console.log("[Mock] authenticateUser called", params);
2
+ console.log('[Mock] authenticateUser called', params);
3
3
  // Headless path requires both userId and pin together (mirrors the handler guard).
4
4
  if ((params?.userId || params?.pin) && !(params?.userId && params?.pin)) {
5
- throw new Error("userId and pin must be provided together");
5
+ throw new Error('userId and pin must be provided together');
6
6
  }
7
7
  return {
8
8
  success: true,
9
9
  roleIds: params?.roleIds || [],
10
- timestamp: new Date().toISOString()
10
+ timestamp: new Date().toISOString(),
11
11
  };
12
12
  };
@@ -2,5 +2,5 @@
2
2
  * Calculate refund total action
3
3
  * Calls the calculateRefundTotal action on the parent window
4
4
  */
5
- import type { CalculateRefundTotal } from "./types";
5
+ import type { CalculateRefundTotal } from './types';
6
6
  export declare const calculateRefundTotal: CalculateRefundTotal;
@@ -2,7 +2,7 @@
2
2
  * Calculate refund total action
3
3
  * Calls the calculateRefundTotal action on the parent window
4
4
  */
5
- import { commandFrameClient } from "../../client";
5
+ import { commandFrameClient } from '../../client';
6
6
  export const calculateRefundTotal = async (params) => {
7
- return await commandFrameClient.call("calculateRefundTotal", params);
7
+ return await commandFrameClient.call('calculateRefundTotal', params);
8
8
  };
@@ -1,4 +1,4 @@
1
- import type { CFStatePair, CFTransitionResult } from "../../common-types/order-state";
1
+ import type { CFStatePair, CFTransitionResult } from '../../common-types/order-state';
2
2
  export interface CanTransitionParams {
3
3
  /** Order to evaluate. Defaults to the active order; if there is no active order (or none matches), evaluates as a brand-new order (from = null). */
4
4
  orderId?: string;
@@ -1,2 +1,2 @@
1
- import { CashPayment } from "./types";
1
+ import { CashPayment } from './types';
2
2
  export declare const mockCashPayment: CashPayment;
@@ -1,6 +1,6 @@
1
- import { applyMockPayment, MOCK_CART } from "../../demo/database";
1
+ import { applyMockPayment, MOCK_CART } from '../../demo/database';
2
2
  export const mockCashPayment = async (params) => {
3
- console.log("[Mock] cashPayment called", params);
3
+ console.log('[Mock] cashPayment called', params);
4
4
  const fail = (reason) => {
5
5
  console.warn(`[Mock] cashPayment rejected: ${reason}`);
6
6
  return {
@@ -9,17 +9,17 @@ export const mockCashPayment = async (params) => {
9
9
  openChangeCalculator: params?.openChangeCalculator ?? false,
10
10
  change: 0,
11
11
  cashRounding: 0,
12
- paymentType: "cash",
12
+ paymentType: 'cash',
13
13
  order: null,
14
14
  timestamp: new Date().toISOString(),
15
15
  saleFinalized: false,
16
- remainingBalance: 0
16
+ remainingBalance: 0,
17
17
  };
18
18
  };
19
19
  // Contract: `amount` is required, integer MINOR currency units — same
20
20
  // scale as the mock cart's totals, so comparisons are direct.
21
21
  if (params?.amount === undefined || params.amount === null) {
22
- return fail("amount is required (integer minor currency units)");
22
+ return fail('amount is required (integer minor currency units)');
23
23
  }
24
24
  const balanceDue = MOCK_CART.amountToBeCharged ?? MOCK_CART.total;
25
25
  if (params.amount > balanceDue) {
@@ -38,16 +38,16 @@ export const mockCashPayment = async (params) => {
38
38
  try {
39
39
  const input = window.prompt(`Amount due: $${(params.amount / 100).toFixed(2)}\nEnter amount tendered (dollars):`, (params.amount / 100).toFixed(2));
40
40
  if (input === null)
41
- return fail("cancelled");
41
+ return fail('cancelled');
42
42
  const tendered = parseFloat(input);
43
43
  if (!isNaN(tendered))
44
44
  change = Math.round(tendered * 100) - params.amount;
45
45
  }
46
46
  catch (e) {
47
- console.warn("Could not open prompt/alert (possibly in non-interactive environment)", e);
47
+ console.warn('Could not open prompt/alert (possibly in non-interactive environment)', e);
48
48
  }
49
49
  }
50
- const order = applyMockPayment(params.amount, "cash", "cash");
50
+ const order = applyMockPayment(params.amount, 'cash', 'cash');
51
51
  return {
52
52
  success: true,
53
53
  amount: params.amount,
@@ -55,10 +55,10 @@ export const mockCashPayment = async (params) => {
55
55
  change,
56
56
  tenderedAmount: params.tenderedAmount,
57
57
  cashRounding: 0,
58
- paymentType: "cash",
58
+ paymentType: 'cash',
59
59
  order,
60
60
  timestamp: new Date().toISOString(),
61
61
  saleFinalized: true,
62
- remainingBalance: 0
62
+ remainingBalance: 0,
63
63
  };
64
64
  };
@@ -1,4 +1,4 @@
1
- import { CFOrder } from "../../CommonTypes";
1
+ import { CFOrder } from '../../CommonTypes';
2
2
  export interface CashPaymentParams {
3
3
  /**
4
4
  * The amount to pay with this tender, in integer MINOR currency units
@@ -1,2 +1,2 @@
1
- import { ExtensionPayment } from "./types";
1
+ import { ExtensionPayment } from './types';
2
2
  export declare const mockExtensionPayment: ExtensionPayment;
@@ -1,6 +1,6 @@
1
- import { MOCK_ORDERS } from "../../demo/database";
1
+ import { MOCK_ORDERS } from '../../demo/database';
2
2
  export const mockExtensionPayment = async (params) => {
3
- const paymentType = params?.paymentType ?? "redeem";
3
+ const paymentType = params?.paymentType ?? 'redeem';
4
4
  return {
5
5
  success: true,
6
6
  amount: params?.amount ?? null,
@@ -10,6 +10,6 @@ export const mockExtensionPayment = async (params) => {
10
10
  change: 0,
11
11
  cashRounding: 0,
12
12
  saleFinalized: true,
13
- remainingBalance: 0
13
+ remainingBalance: 0,
14
14
  };
15
15
  };
@@ -1,4 +1,4 @@
1
- import { CFOrder } from "../../CommonTypes";
1
+ import { CFOrder } from '../../CommonTypes';
2
2
  /** Params for extension-initiated payments; host routes by `paymentType`. */
3
3
  export interface ExtensionPaymentParams {
4
4
  paymentType: string;
@@ -1,4 +1,4 @@
1
- import type { GetAvailableTransitions } from "./types";
1
+ import type { GetAvailableTransitions } from './types';
2
2
  /**
3
3
  * Mock implementation: returns a fixed set of plausible transitions
4
4
  * so the demo app has data to render. Mirrors an UNPAID order under the
@@ -7,32 +7,32 @@
7
7
  export const getAvailableTransitionsMock = () => Promise.resolve({
8
8
  transitions: [
9
9
  {
10
- to: { payment: "unpaid", fulfillment: "in_progress" },
11
- displayLabel: "Start Preparing",
12
- conditions: [{ met: true, description: "Order has items" }]
10
+ to: { payment: 'unpaid', fulfillment: 'in_progress' },
11
+ displayLabel: 'Start Preparing',
12
+ conditions: [{ met: true, description: 'Order has items' }],
13
13
  },
14
14
  {
15
- to: { payment: "unpaid", fulfillment: "fulfilled" },
16
- displayLabel: "Mark Fulfilled",
17
- conditions: [{ met: true, description: "Order has items" }]
15
+ to: { payment: 'unpaid', fulfillment: 'fulfilled' },
16
+ displayLabel: 'Mark Fulfilled',
17
+ conditions: [{ met: true, description: 'Order has items' }],
18
18
  },
19
19
  {
20
- to: { payment: "unpaid", fulfillment: "on_hold" },
21
- displayLabel: "Park Order",
22
- conditions: [{ met: true, description: "Order is open" }]
20
+ to: { payment: 'unpaid', fulfillment: 'on_hold' },
21
+ displayLabel: 'Park Order',
22
+ conditions: [{ met: true, description: 'Order is open' }],
23
23
  },
24
24
  {
25
- to: { payment: "paid", fulfillment: "fulfilled" },
26
- displayLabel: "Complete Payment",
27
- conditions: [{ met: true, description: "Balance due > 0" }]
25
+ to: { payment: 'paid', fulfillment: 'fulfilled' },
26
+ displayLabel: 'Complete Payment',
27
+ conditions: [{ met: true, description: 'Balance due > 0' }],
28
28
  },
29
29
  {
30
- to: { payment: "voided", fulfillment: "cancelled" },
31
- displayLabel: "Void Order",
30
+ to: { payment: 'voided', fulfillment: 'cancelled' },
31
+ displayLabel: 'Void Order',
32
32
  conditions: [
33
- { met: true, description: "Order exists" },
34
- { met: false, description: "No payments captured (mock: skipped)" }
35
- ]
36
- }
37
- ]
33
+ { met: true, description: 'Order exists' },
34
+ { met: false, description: 'No payments captured (mock: skipped)' },
35
+ ],
36
+ },
37
+ ],
38
38
  });
@@ -1,2 +1,2 @@
1
- import { GetFinalContext } from "./types";
1
+ import { GetFinalContext } from './types';
2
2
  export declare const mockGetFinalContext: GetFinalContext;
@@ -1,6 +1,6 @@
1
1
  export const mockGetFinalContext = async () => {
2
- console.log("[Mock] getFinalContext called");
2
+ console.log('[Mock] getFinalContext called');
3
3
  return {
4
- projectName: "kaching"
4
+ projectName: 'kaching',
5
5
  };
6
6
  };
@@ -1,2 +1,2 @@
1
- import { GetProducts } from "./types";
1
+ import { GetProducts } from './types';
2
2
  export declare const mockGetProducts: GetProducts;