@final-commerce/command-frame 0.1.42 → 0.1.44

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 (32) hide show
  1. package/README.md +34 -0
  2. package/dist/CommonTypes.d.ts +18 -8
  3. package/dist/actions/add-non-revenue-item/action.d.ts +2 -0
  4. package/dist/actions/add-non-revenue-item/action.js +4 -0
  5. package/dist/actions/add-non-revenue-item/mock.d.ts +2 -0
  6. package/dist/actions/add-non-revenue-item/mock.js +41 -0
  7. package/dist/actions/add-non-revenue-item/types.d.ts +36 -0
  8. package/dist/actions/add-non-revenue-item/types.js +1 -0
  9. package/dist/actions/extension-payment/action.d.ts +5 -0
  10. package/dist/actions/extension-payment/action.js +7 -0
  11. package/dist/actions/extension-payment/mock.d.ts +2 -0
  12. package/dist/actions/extension-payment/mock.js +11 -0
  13. package/dist/actions/extension-payment/types.d.ts +19 -0
  14. package/dist/actions/extension-payment/types.js +1 -0
  15. package/dist/actions/extension-refund/constants.d.ts +2 -0
  16. package/dist/actions/extension-refund/constants.js +2 -0
  17. package/dist/actions/extension-refund/extension-refund-listener.d.ts +11 -0
  18. package/dist/actions/extension-refund/extension-refund-listener.js +60 -0
  19. package/dist/actions/extension-refund/types.d.ts +32 -0
  20. package/dist/actions/extension-refund/types.js +5 -0
  21. package/dist/actions/redeem-payment/action.d.ts +5 -0
  22. package/dist/actions/redeem-payment/action.js +7 -0
  23. package/dist/actions/redeem-payment/mock.d.ts +2 -0
  24. package/dist/actions/redeem-payment/mock.js +4 -0
  25. package/dist/actions/redeem-payment/types.d.ts +12 -0
  26. package/dist/actions/redeem-payment/types.js +1 -0
  27. package/dist/demo/database.js +2 -0
  28. package/dist/index.d.ts +9 -0
  29. package/dist/index.js +8 -0
  30. package/dist/projects/render/mocks.js +6 -0
  31. package/dist/projects/render/types.d.ts +4 -1
  32. package/package.json +5 -2
package/README.md CHANGED
@@ -13,6 +13,7 @@ The library provides three main capabilities:
13
13
  | **Commands** | Call host functions from the iframe (e.g. get products, open cash drawer) | Request/response per call |
14
14
  | **Pub/Sub** | Subscribe to real-time events from the host (e.g. cart changes, payments) | Page-scoped (while iframe is mounted) |
15
15
  | **Hooks** | Register business-logic callbacks that persist across all pages | Session-scoped (survives page navigation) |
16
+ | **Host → iframe refunds** | Render asks the extension to reverse redeem / gift-card payments before completing a POS refund | Parent `postMessage` + `requestId` (see below) |
16
17
 
17
18
  ## Installation
18
19
 
@@ -109,6 +110,39 @@ hooks.register('cart', async (event, hostCommands) => {
109
110
  hooks.unregister('my-extension:cart-log');
110
111
  ```
111
112
 
113
+ ## Host-initiated extension refunds (redeem / gift card)
114
+
115
+ **Extensions that accept redeem / extension payments must implement a refund listener.** When staff refund an order paid with `paymentType: "redeem"`, Render (host) `postMessage`s into your iframe **before** it records the refund locally. If your app does not handle this message, redeem refunds will time out or fail.
116
+
117
+ ### What you should do
118
+
119
+ 1. **Recommended:** call **`installExtensionRefundListener`** once when your extension boots (e.g. next to your `RenderClient` setup). Pass an `async` handler that calls your provider (gift card API, wallet, etc.) and returns an **`ExtensionRefundResponse`** (`success`, optional `error`, optional `extensionTransactionId` for receipts / support).
120
+ 2. The helper validates `event.source === window.parent`, parses params, and replies with the same **`PostMessageResponse`** envelope as the rest of Command Frame (`requestId`, `success`, `data` / `error`).
121
+ 3. **Alternative:** implement a `window` `message` listener yourself using the same contract (action name: **`extensionRefundRequest`**, or import **`EXTENSION_REFUND_REQUEST_ACTION`** from this package).
122
+
123
+ Exported APIs: `installExtensionRefundListener`, `EXTENSION_REFUND_REQUEST_ACTION`, types **`ExtensionRefundParams`** / **`ExtensionRefundResponse`**.
124
+
125
+ ```typescript
126
+ import {
127
+ installExtensionRefundListener,
128
+ type ExtensionRefundParams,
129
+ type ExtensionRefundResponse
130
+ } from '@final-commerce/command-frame';
131
+
132
+ const unsubscribe = installExtensionRefundListener(async (params: ExtensionRefundParams): Promise<ExtensionRefundResponse> => {
133
+ // params.paymentType === "redeem", params.amount in major currency units, params.saleId, params.processor, etc.
134
+ const ok = await myGiftCardProvider.refund(params);
135
+ return ok
136
+ ? { success: true, extensionTransactionId: ok.providerRefundId }
137
+ : { success: false, error: 'Refund declined' };
138
+ });
139
+
140
+ // on teardown (optional)
141
+ // unsubscribe();
142
+ ```
143
+
144
+ **Full protocol, edge cases, and manual handling:** **[Extension refund documentation](./src/actions/extension-refund/README.md)**.
145
+
112
146
  ## Development & Testing
113
147
 
114
148
  ### Demo Mode / Mocking
@@ -184,6 +184,8 @@ export interface CFSummary {
184
184
  taxes: CFTax[];
185
185
  tip?: CFTip | null;
186
186
  isTaxInclusive: boolean;
187
+ /** Portion of order total that is non-revenue (e.g. gift card load), same string money format as `total` */
188
+ nonRevenueTotal?: string;
187
189
  }
188
190
  export interface CFCartDiscountItem {
189
191
  label: string;
@@ -234,13 +236,14 @@ export interface CFPosDataItem {
234
236
  export interface CFDiscountDetail {
235
237
  percentage: number;
236
238
  amount: string;
237
- const?: string;
239
+ label?: string;
238
240
  }
239
241
  export interface CFFeeDetail {
240
242
  percentage: number;
241
243
  amount: string;
242
244
  tax: string;
243
245
  taxTableId: string;
246
+ label?: string;
244
247
  }
245
248
  export interface CFDiscountLineItem {
246
249
  itemDiscount: CFDiscountDetail;
@@ -286,13 +289,7 @@ export interface CFCustomSale {
286
289
  cartDiscount: CFDiscountDetail;
287
290
  };
288
291
  fee: {
289
- cartFee: {
290
- amount: string;
291
- label: string;
292
- percentage: number;
293
- tax: string;
294
- taxTableId: string;
295
- };
292
+ cartFee: CFFeeDetail;
296
293
  };
297
294
  }
298
295
  export interface CFRefundedLineItem {
@@ -353,6 +350,8 @@ export interface CFOrder {
353
350
  shipping: CFAddress | null;
354
351
  lineItems: CFLineItem[];
355
352
  customSales: CFCustomSale[];
353
+ /** Gift card / liability purchase lines (not product revenue) */
354
+ nonRevenueItems?: CFNonRevenueItem[];
356
355
  refund?: CFRefundItem[];
357
356
  balance: string;
358
357
  signature?: string | null;
@@ -438,6 +437,15 @@ export interface CFActiveCustomSales {
438
437
  discount?: any;
439
438
  fee?: any;
440
439
  }
440
+ /** Non-revenue cart line (e.g. gift card load) — aligned with Render NonRevenueItem */
441
+ export interface CFNonRevenueItem {
442
+ id: string;
443
+ amount: number | string;
444
+ label?: string;
445
+ metadata?: Record<string, unknown>;
446
+ applyTaxes?: boolean;
447
+ taxTableId?: string;
448
+ }
441
449
  export interface CFActiveCart extends CFActiveEntity {
442
450
  tax?: number;
443
451
  total: number;
@@ -446,6 +454,8 @@ export interface CFActiveCart extends CFActiveEntity {
446
454
  customFee?: CFCustomFee[];
447
455
  products: CFActiveProduct[];
448
456
  customSales?: CFActiveCustomSales[];
457
+ /** Gift card / liability lines — included in cart total */
458
+ nonRevenueItems?: CFNonRevenueItem[];
449
459
  remainingBalance?: number;
450
460
  amountToBeCharged: number;
451
461
  customer?: Partial<CFCustomer | null> | null;
@@ -0,0 +1,2 @@
1
+ import type { AddNonRevenueItem } from "./types";
2
+ export declare const addNonRevenueItem: AddNonRevenueItem;
@@ -0,0 +1,4 @@
1
+ import { commandFrameClient } from "../../client";
2
+ export const addNonRevenueItem = async (params) => {
3
+ return await commandFrameClient.call("addNonRevenueItem", params);
4
+ };
@@ -0,0 +1,2 @@
1
+ import { AddNonRevenueItem } from "./types";
2
+ export declare const mockAddNonRevenueItem: AddNonRevenueItem;
@@ -0,0 +1,41 @@
1
+ import { MOCK_CART } from "../../demo/database";
2
+ export const mockAddNonRevenueItem = async (params) => {
3
+ console.log("[Mock] addNonRevenueItem called", params);
4
+ const amount = Number(params.amount);
5
+ if (!Number.isFinite(amount) || amount <= 0) {
6
+ throw new Error("amount must be a positive number");
7
+ }
8
+ const lineId = `nr-mock-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
9
+ const refId = params.id;
10
+ const metadata = {
11
+ ...(params.metadata ?? {}),
12
+ refId
13
+ };
14
+ const row = {
15
+ id: lineId,
16
+ amount,
17
+ applyTaxes: params.applyTaxes === true,
18
+ ...(params.taxTableId ? { taxTableId: params.taxTableId } : {}),
19
+ ...(params.label !== undefined ? { label: params.label } : {}),
20
+ metadata
21
+ };
22
+ if (!MOCK_CART.nonRevenueItems) {
23
+ MOCK_CART.nonRevenueItems = [];
24
+ }
25
+ MOCK_CART.nonRevenueItems.push(row);
26
+ MOCK_CART.total += amount;
27
+ MOCK_CART.amountToBeCharged = MOCK_CART.total;
28
+ MOCK_CART.remainingBalance = MOCK_CART.total;
29
+ MOCK_CART.subtotal = (MOCK_CART.subtotal ?? 0) + amount;
30
+ return {
31
+ success: true,
32
+ id: lineId,
33
+ refId,
34
+ amount,
35
+ label: params.label,
36
+ metadata,
37
+ ...(params.applyTaxes === true ? { applyTaxes: true } : {}),
38
+ ...(params.taxTableId ? { taxTableId: params.taxTableId } : {}),
39
+ timestamp: new Date().toISOString()
40
+ };
41
+ };
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Add a non-revenue line to the host cart (e.g. gift card liability / load).
3
+ * Extensions send id, amount, and optional label/metadata; host sums into cart total.
4
+ */
5
+ export interface AddNonRevenueItemParams {
6
+ /**
7
+ * Reference id from the extension (e.g. product/sku key). Stored in cart line metadata as refId.
8
+ * The cart uses a separate unique line id per add so multiple lines can share the same refId.
9
+ */
10
+ id: string;
11
+ /** Amount in major currency units (e.g. dollars), same as cart totals */
12
+ amount: number;
13
+ /** Short label for receipts/UI */
14
+ label?: string;
15
+ /** Extra fields (customTableId, cardCode, etc.) */
16
+ metadata?: Record<string, unknown>;
17
+ /**
18
+ * When true, line may be taxed (requires taxTableId when taxing is implemented). Default false — e.g. gift card load is typically not taxed.
19
+ */
20
+ applyTaxes?: boolean;
21
+ taxTableId?: string;
22
+ }
23
+ export interface AddNonRevenueItemResponse {
24
+ success: true;
25
+ /** Unique cart line id (use for remove / correlation) */
26
+ id: string;
27
+ /** Same as request `id` — extension reference */
28
+ refId: string;
29
+ amount: number;
30
+ label?: string;
31
+ metadata?: Record<string, unknown>;
32
+ applyTaxes?: boolean;
33
+ taxTableId?: string;
34
+ timestamp: string;
35
+ }
36
+ export type AddNonRevenueItem = (params: AddNonRevenueItemParams) => Promise<AddNonRevenueItemResponse>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generic extension payment — host handles wire action `extensionPayment` and routes by `paymentType`.
3
+ */
4
+ import type { ExtensionPayment } from "./types";
5
+ export declare const extensionPayment: ExtensionPayment;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Generic extension payment — host handles wire action `extensionPayment` and routes by `paymentType`.
3
+ */
4
+ import { commandFrameClient } from "../../client";
5
+ export const extensionPayment = async (params) => {
6
+ return await commandFrameClient.call("extensionPayment", params);
7
+ };
@@ -0,0 +1,2 @@
1
+ import { ExtensionPayment } from "./types";
2
+ export declare const mockExtensionPayment: ExtensionPayment;
@@ -0,0 +1,11 @@
1
+ import { MOCK_ORDERS } from "../../demo/database";
2
+ export const mockExtensionPayment = async (params) => {
3
+ const paymentType = params?.paymentType ?? "redeem";
4
+ return {
5
+ success: true,
6
+ amount: params?.amount ?? null,
7
+ paymentType,
8
+ order: MOCK_ORDERS[0],
9
+ timestamp: new Date().toISOString()
10
+ };
11
+ };
@@ -0,0 +1,19 @@
1
+ import { CFOrder } from "../../CommonTypes";
2
+ /** Params for extension-initiated payments; host routes by `paymentType`. */
3
+ export interface ExtensionPaymentParams {
4
+ paymentType: string;
5
+ processor?: string;
6
+ amount?: number;
7
+ label?: string;
8
+ referenceId?: string;
9
+ extensionId?: string;
10
+ metadata?: Record<string, unknown>;
11
+ }
12
+ export interface ExtensionPaymentResponse {
13
+ success: boolean;
14
+ amount: number | null;
15
+ paymentType: string;
16
+ order: CFOrder | null;
17
+ timestamp: string;
18
+ }
19
+ export type ExtensionPayment = (params?: ExtensionPaymentParams) => Promise<ExtensionPaymentResponse>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ /** postMessage `action` for host → iframe extension refund requests. */
2
+ export declare const EXTENSION_REFUND_REQUEST_ACTION = "extensionRefundRequest";
@@ -0,0 +1,2 @@
1
+ /** postMessage `action` for host → iframe extension refund requests. */
2
+ export const EXTENSION_REFUND_REQUEST_ACTION = "extensionRefundRequest";
@@ -0,0 +1,11 @@
1
+ import type { ExtensionRefundParams, ExtensionRefundResponse } from "./types";
2
+ /**
3
+ * Install a message listener in the **extension iframe** so the host can request refunds.
4
+ * Validates `event.source === window.parent` before handling.
5
+ *
6
+ * Replies with {@link PostMessageResponse}, using `event.origin` as the target origin when posting back to the parent.
7
+ *
8
+ * @param handler - Perform the extension-side refund (API call, etc.)
9
+ * @returns Unsubscribe function
10
+ */
11
+ export declare function installExtensionRefundListener(handler: (params: ExtensionRefundParams) => Promise<ExtensionRefundResponse>): () => void;
@@ -0,0 +1,60 @@
1
+ import { EXTENSION_REFUND_REQUEST_ACTION } from "./constants";
2
+ function isRecord(value) {
3
+ return typeof value === "object" && value !== null;
4
+ }
5
+ /**
6
+ * Install a message listener in the **extension iframe** so the host can request refunds.
7
+ * Validates `event.source === window.parent` before handling.
8
+ *
9
+ * Replies with {@link PostMessageResponse}, using `event.origin` as the target origin when posting back to the parent.
10
+ *
11
+ * @param handler - Perform the extension-side refund (API call, etc.)
12
+ * @returns Unsubscribe function
13
+ */
14
+ export function installExtensionRefundListener(handler) {
15
+ const onMessage = async (event) => {
16
+ const raw = event.data;
17
+ if (!isRecord(raw) || raw.action !== EXTENSION_REFUND_REQUEST_ACTION) {
18
+ return;
19
+ }
20
+ const requestId = raw.requestId;
21
+ if (typeof requestId !== "string") {
22
+ return;
23
+ }
24
+ if (event.source !== window.parent || !event.source) {
25
+ return;
26
+ }
27
+ const source = event.source;
28
+ const replyOrigin = typeof event.origin === "string" ? event.origin : "*";
29
+ const params = raw.params;
30
+ try {
31
+ if (!params || typeof params.paymentType !== "string" || typeof params.amount !== "number" || typeof params.saleId !== "string") {
32
+ const errPayload = {
33
+ requestId,
34
+ success: false,
35
+ error: "Invalid extension refund params"
36
+ };
37
+ source.postMessage(errPayload, replyOrigin);
38
+ return;
39
+ }
40
+ const result = await handler(params);
41
+ const payload = {
42
+ requestId,
43
+ success: true,
44
+ data: result
45
+ };
46
+ source.postMessage(payload, replyOrigin);
47
+ }
48
+ catch (e) {
49
+ const message = e instanceof Error ? e.message : String(e);
50
+ const errPayload = {
51
+ requestId,
52
+ success: false,
53
+ error: message
54
+ };
55
+ source.postMessage(errPayload, replyOrigin);
56
+ }
57
+ };
58
+ window.addEventListener("message", onMessage);
59
+ return () => window.removeEventListener("message", onMessage);
60
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Host-initiated refund request for extension-controlled payments (e.g. redeem / gift card).
3
+ * The host (Render) postMessages the iframe; the extension performs the provider refund and replies.
4
+ */
5
+ /**
6
+ * Parameters sent from host to extension for a refund.
7
+ *
8
+ * **`amount` uses major currency units** (e.g. dollars), consistent with the string amount
9
+ * passed through `sendRefundPaymentRequest` in Render (parsed with `parseFloat` / `+amount`).
10
+ */
11
+ export interface ExtensionRefundParams {
12
+ /** e.g. `"redeem"` — matches order paymentMethods[].paymentType */
13
+ paymentType: string;
14
+ processor?: string;
15
+ /** Major currency units (same as refund flow amount string, not cents). */
16
+ amount: number;
17
+ /** Local sale transaction id (Mongo-style id from paymentMethods[].transactionId). */
18
+ saleId: string;
19
+ orderId?: string;
20
+ referenceId?: string;
21
+ metadata?: Record<string, unknown>;
22
+ }
23
+ /**
24
+ * Business result from the extension after attempting the refund.
25
+ * Transport success/failure uses {@link import("../../client").PostMessageResponse}.
26
+ */
27
+ export interface ExtensionRefundResponse {
28
+ success: boolean;
29
+ error?: string;
30
+ /** Provider/extension reference for the refund transaction, stored in local DB paymentData when present. */
31
+ extensionTransactionId?: string;
32
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Host-initiated refund request for extension-controlled payments (e.g. redeem / gift card).
3
+ * The host (Render) postMessages the iframe; the extension performs the provider refund and replies.
4
+ */
5
+ export {};
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Redeem payment — thin wrapper over {@link extensionPayment} with `paymentType: "redeem"`.
3
+ */
4
+ import type { RedeemPayment } from "./types";
5
+ export declare const redeemPayment: RedeemPayment;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Redeem payment — thin wrapper over {@link extensionPayment} with `paymentType: "redeem"`.
3
+ */
4
+ import { extensionPayment } from "../extension-payment/action";
5
+ export const redeemPayment = async (params) => {
6
+ return extensionPayment({ ...params, paymentType: "redeem" });
7
+ };
@@ -0,0 +1,2 @@
1
+ import type { RedeemPayment } from "./types";
2
+ export declare const mockRedeemPayment: RedeemPayment;
@@ -0,0 +1,4 @@
1
+ import { mockExtensionPayment } from "../extension-payment/mock";
2
+ export const mockRedeemPayment = async (params) => {
3
+ return mockExtensionPayment({ ...params, paymentType: "redeem" });
4
+ };
@@ -0,0 +1,12 @@
1
+ import type { ExtensionPaymentResponse } from "../extension-payment/types";
2
+ /** Redeem (e.g. gift card) — always uses paymentType `"redeem"` on the wire. */
3
+ export interface RedeemPaymentParams {
4
+ amount?: number;
5
+ processor?: string;
6
+ label?: string;
7
+ referenceId?: string;
8
+ extensionId?: string;
9
+ metadata?: Record<string, unknown>;
10
+ }
11
+ export type RedeemPaymentResponse = ExtensionPaymentResponse;
12
+ export type RedeemPayment = (params?: RedeemPaymentParams) => Promise<RedeemPaymentResponse>;
@@ -0,0 +1 @@
1
+ export {};
@@ -450,6 +450,7 @@ export let MOCK_CART = {
450
450
  remainingBalance: 0,
451
451
  products: [],
452
452
  customSales: [],
453
+ nonRevenueItems: [],
453
454
  customer: null
454
455
  };
455
456
  // Helper to reset cart
@@ -461,6 +462,7 @@ export const resetMockCart = () => {
461
462
  remainingBalance: 0,
462
463
  products: [],
463
464
  customSales: [],
465
+ nonRevenueItems: [],
464
466
  customer: null
465
467
  };
466
468
  };
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export declare const command: {
3
3
  readonly generateAPIKey: import("./actions/generate-api-key/types").GenerateAPIKey;
4
4
  readonly getProducts: import("./actions/get-products/types").GetProducts;
5
5
  readonly addCustomSale: import("./actions/add-custom-sale/types").AddCustomSale;
6
+ readonly addNonRevenueItem: import("./actions/add-non-revenue-item/types").AddNonRevenueItem;
6
7
  readonly getCustomers: import("./actions/get-customers/types").GetCustomers;
7
8
  readonly assignCustomer: import("./actions/assign-customer/types").AssignCustomer;
8
9
  readonly addCustomer: import("./actions/add-customer/types").AddCustomer;
@@ -30,6 +31,8 @@ export declare const command: {
30
31
  readonly tapToPayPayment: import("./actions/tap-to-pay-payment/types").TapToPayPayment;
31
32
  readonly terminalPayment: import("./actions/terminal-payment/types").TerminalPayment;
32
33
  readonly vendaraPayment: import("./actions/vendara-payment/types").VendaraPayment;
34
+ readonly extensionPayment: import("./actions/extension-payment/types").ExtensionPayment;
35
+ readonly redeemPayment: import("./actions/redeem-payment/types").RedeemPayment;
33
36
  readonly addCustomerNote: import("./actions/add-customer-note/types").AddCustomerNote;
34
37
  readonly removeCustomerFromCart: import("./actions/remove-customer-from-cart/types").RemoveCustomerFromCart;
35
38
  readonly goToStationHome: import("./actions/go-to-station-home/types").GoToStationHome;
@@ -74,6 +77,7 @@ export type { ExampleFunction, ExampleFunctionParams, ExampleFunctionResponse }
74
77
  export type { GenerateAPIKey, GenerateAPIKeyParams, GenerateAPIKeyResponse } from "./actions/generate-api-key/types";
75
78
  export type { GetProducts, GetProductsParams, GetProductsResponse } from "./actions/get-products/types";
76
79
  export type { AddCustomSale, AddCustomSaleParams, AddCustomSaleResponse } from "./actions/add-custom-sale/types";
80
+ export type { AddNonRevenueItem, AddNonRevenueItemParams, AddNonRevenueItemResponse } from "./actions/add-non-revenue-item/types";
77
81
  export type { GetCustomers, GetCustomersParams, GetCustomersResponse } from "./actions/get-customers/types";
78
82
  export type { AssignCustomer, AssignCustomerParams, AssignCustomerResponse } from "./actions/assign-customer/types";
79
83
  export type { AddCustomer, AddCustomerParams, AddCustomerResponse } from "./actions/add-customer/types";
@@ -114,6 +118,11 @@ export type { CashPayment, CashPaymentParams, CashPaymentResponse } from "./acti
114
118
  export type { TapToPayPayment, TapToPayPaymentParams, TapToPayPaymentResponse } from "./actions/tap-to-pay-payment/types";
115
119
  export type { TerminalPayment, TerminalPaymentParams, TerminalPaymentResponse } from "./actions/terminal-payment/types";
116
120
  export type { VendaraPayment, VendaraPaymentParams, VendaraPaymentResponse } from "./actions/vendara-payment/types";
121
+ export type { ExtensionPayment, ExtensionPaymentParams, ExtensionPaymentResponse } from "./actions/extension-payment/types";
122
+ export type { RedeemPayment, RedeemPaymentParams, RedeemPaymentResponse } from "./actions/redeem-payment/types";
123
+ export { EXTENSION_REFUND_REQUEST_ACTION } from "./actions/extension-refund/constants";
124
+ export { installExtensionRefundListener } from "./actions/extension-refund/extension-refund-listener";
125
+ export type { ExtensionRefundParams, ExtensionRefundResponse } from "./actions/extension-refund/types";
117
126
  export type { AddCustomerNote, AddCustomerNoteParams, AddCustomerNoteResponse } from "./actions/add-customer-note/types";
118
127
  export type { RemoveCustomerFromCart, RemoveCustomerFromCartResponse } from "./actions/remove-customer-from-cart/types";
119
128
  export type { GoToStationHome, GoToStationHomeResponse } from "./actions/go-to-station-home/types";
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
  import { exampleFunction } from "./actions/example-function/action";
3
3
  import { getProducts } from "./actions/get-products/action";
4
4
  import { addCustomSale } from "./actions/add-custom-sale/action";
5
+ import { addNonRevenueItem } from "./actions/add-non-revenue-item/action";
5
6
  import { getCustomers } from "./actions/get-customers/action";
6
7
  import { assignCustomer } from "./actions/assign-customer/action";
7
8
  import { addCustomer } from "./actions/add-customer/action";
@@ -30,6 +31,8 @@ import { cashPayment } from "./actions/cash-payment/action";
30
31
  import { tapToPayPayment } from "./actions/tap-to-pay-payment/action";
31
32
  import { terminalPayment } from "./actions/terminal-payment/action";
32
33
  import { vendaraPayment } from "./actions/vendara-payment/action";
34
+ import { extensionPayment } from "./actions/extension-payment/action";
35
+ import { redeemPayment } from "./actions/redeem-payment/action";
33
36
  // Customer Actions
34
37
  import { addCustomerNote } from "./actions/add-customer-note/action";
35
38
  import { removeCustomerFromCart } from "./actions/remove-customer-from-cart/action";
@@ -86,6 +89,7 @@ export const command = {
86
89
  generateAPIKey,
87
90
  getProducts,
88
91
  addCustomSale,
92
+ addNonRevenueItem,
89
93
  getCustomers,
90
94
  assignCustomer,
91
95
  addCustomer,
@@ -115,6 +119,8 @@ export const command = {
115
119
  tapToPayPayment,
116
120
  terminalPayment,
117
121
  vendaraPayment,
122
+ extensionPayment,
123
+ redeemPayment,
118
124
  // Customer Actions
119
125
  addCustomerNote,
120
126
  removeCustomerFromCart,
@@ -165,6 +171,8 @@ export const command = {
165
171
  getSecretVal,
166
172
  setSecretVal,
167
173
  };
174
+ export { EXTENSION_REFUND_REQUEST_ACTION } from "./actions/extension-refund/constants";
175
+ export { installExtensionRefundListener } from "./actions/extension-refund/extension-refund-listener";
168
176
  // Export Common Types
169
177
  export * from "./CommonTypes";
170
178
  // Export Provider
@@ -45,6 +45,9 @@ import { mockTerminalPayment } from "../../actions/terminal-payment/mock";
45
45
  import { mockTriggerWebhook } from "../../actions/trigger-webhook/mock";
46
46
  import { mockTriggerZapierWebhook } from "../../actions/trigger-zapier-webhook/mock";
47
47
  import { mockVendaraPayment } from "../../actions/vendara-payment/mock";
48
+ import { mockExtensionPayment } from "../../actions/extension-payment/mock";
49
+ import { mockRedeemPayment } from "../../actions/redeem-payment/mock";
50
+ import { mockAddNonRevenueItem } from "../../actions/add-non-revenue-item/mock";
48
51
  import { mockGetFinalContext } from "../../actions/get-final-context/mock";
49
52
  import { mockPrint } from "../../actions/print/mock";
50
53
  import { mockSetActiveOrder } from "../../actions/set-active-order/mock";
@@ -109,6 +112,9 @@ export const RENDER_MOCKS = {
109
112
  triggerWebhook: mockTriggerWebhook,
110
113
  triggerZapierWebhook: mockTriggerZapierWebhook,
111
114
  vendaraPayment: mockVendaraPayment,
115
+ extensionPayment: mockExtensionPayment,
116
+ redeemPayment: mockRedeemPayment,
117
+ addNonRevenueItem: mockAddNonRevenueItem,
112
118
  getFinalContext: mockGetFinalContext,
113
119
  print: mockPrint,
114
120
  setActiveOrder: mockSetActiveOrder,
@@ -1,4 +1,4 @@
1
- import type { ExampleFunction, GetProducts, AddCustomSale, GetCustomers, AssignCustomer, AddCustomer, GetCategories, GetOrders, GetRefunds, AddProductDiscount, AddProductToCart, RemoveProductFromCart, UpdateCartItemQuantity, AddCartDiscount, GetContext, GetFinalContext, AddProductNote, AddProductFee, AdjustInventory, AddOrderNote, AddCartFee, ClearCart, ParkOrder, ResumeParkedOrder, DeleteParkedOrder, InitiateRefund, CashPayment, TapToPayPayment, TerminalPayment, VendaraPayment, AddCustomerNote, RemoveCustomerFromCart, GoToStationHome, OpenCashDrawer, ShowNotification, ShowConfirmation, AuthenticateUser, PartialPayment, SwitchUser, TriggerWebhook, TriggerZapierWebhook, SetRefundStockAction, SelectAllRefundItems, ResetRefundDetails, CalculateRefundTotal, GetRemainingRefundableQuantities, ProcessPartialRefund, GetCurrentCart, Print, SetActiveOrder, GetCustomTables, GetCustomTableData, UpsertCustomTableData, DeleteCustomTableData, GetCustomExtensions, GetCurrentCompanyCustomExtensions, GetCustomExtensionCustomTables, GetCustomTableFields, GetSecretsKeys, GetSecretVal, SetSecretVal, GetUsers, GetRoles } from "../../index";
1
+ import type { ExampleFunction, GetProducts, AddCustomSale, GetCustomers, AssignCustomer, AddCustomer, GetCategories, GetOrders, GetRefunds, AddProductDiscount, AddProductToCart, RemoveProductFromCart, UpdateCartItemQuantity, AddCartDiscount, GetContext, GetFinalContext, AddProductNote, AddProductFee, AdjustInventory, AddOrderNote, AddCartFee, ClearCart, ParkOrder, ResumeParkedOrder, DeleteParkedOrder, InitiateRefund, CashPayment, TapToPayPayment, TerminalPayment, VendaraPayment, ExtensionPayment, RedeemPayment, AddNonRevenueItem, AddCustomerNote, RemoveCustomerFromCart, GoToStationHome, OpenCashDrawer, ShowNotification, ShowConfirmation, AuthenticateUser, PartialPayment, SwitchUser, TriggerWebhook, TriggerZapierWebhook, SetRefundStockAction, SelectAllRefundItems, ResetRefundDetails, CalculateRefundTotal, GetRemainingRefundableQuantities, ProcessPartialRefund, GetCurrentCart, Print, SetActiveOrder, GetCustomTables, GetCustomTableData, UpsertCustomTableData, DeleteCustomTableData, GetCustomExtensions, GetCurrentCompanyCustomExtensions, GetCustomExtensionCustomTables, GetCustomTableFields, GetSecretsKeys, GetSecretVal, SetSecretVal, GetUsers, GetRoles } from "../../index";
2
2
  export interface RenderProviderActions {
3
3
  exampleFunction: ExampleFunction;
4
4
  getProducts: GetProducts;
@@ -30,6 +30,9 @@ export interface RenderProviderActions {
30
30
  tapToPayPayment: TapToPayPayment;
31
31
  terminalPayment: TerminalPayment;
32
32
  vendaraPayment: VendaraPayment;
33
+ extensionPayment: ExtensionPayment;
34
+ redeemPayment: RedeemPayment;
35
+ addNonRevenueItem: AddNonRevenueItem;
33
36
  addCustomerNote: AddCustomerNote;
34
37
  removeCustomerFromCart: RemoveCustomerFromCart;
35
38
  goToStationHome: GoToStationHome;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@final-commerce/command-frame",
3
- "version": "0.1.42",
3
+ "version": "0.1.44",
4
4
  "description": "Commands Frame library",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -14,6 +14,8 @@
14
14
  "build": "tsc",
15
15
  "build:clean": "rm -rf dist && npm run build",
16
16
  "dev": "tsc --watch",
17
+ "test": "vitest",
18
+ "test:run": "vitest run",
17
19
  "prepublishOnly": "npm run build",
18
20
  "prepare": "npm run build",
19
21
  "format": "prettier --write .",
@@ -43,6 +45,7 @@
43
45
  "@typescript-eslint/eslint-plugin": "^8.48.0",
44
46
  "@typescript-eslint/parser": "^8.48.0",
45
47
  "prettier": "^3.7.1",
46
- "typescript": "^5.0.0"
48
+ "typescript": "^5.0.0",
49
+ "vitest": "^3.0.5"
47
50
  }
48
51
  }