@final-commerce/command-frame 0.4.1-preprod.1 → 0.4.2-preprod.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,7 +16,7 @@ The library provides three main capabilities:
16
16
  | **Pub/Sub** | Subscribe to real-time events from the host (e.g. cart changes, payments) | Page-scoped (while iframe is mounted) |
17
17
  | **Hooks** | Register business-logic callbacks that persist across all pages | Session-scoped (survives page navigation) |
18
18
  | **Interceptors** | Gate POS flows (approve / modify / block) at named points | Blocking; host waits for your response |
19
- | **Refund commands** | Refund payments to gift cards or redeem tenders via `redeemRefund`, or mixed-destination legs on `processPartialRefund`; query engine capacity with `getRefundPlan` | Request/response per call |
19
+ | **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 |
20
20
 
21
21
  Domain models (orders, cart, customers, products, and related types) are documented in **[Types reference](./src/types/README.md)**.
22
22
 
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Check permission action
3
+ * Calls the checkPermission action on the parent window
4
+ */
5
+ import type { CheckPermission } from './types';
6
+ export declare const checkPermission: CheckPermission;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Check permission action
3
+ * Calls the checkPermission action on the parent window
4
+ */
5
+ import { commandFrameClient } from '../../client';
6
+ export const checkPermission = async (params) => {
7
+ return await commandFrameClient.call('checkPermission', params);
8
+ };
@@ -0,0 +1,8 @@
1
+ import { CheckPermission } from './types';
2
+ /**
3
+ * Standalone mock: `allowed: true` for every permission EXCEPT the magic name
4
+ * `'mock_denied'`, which returns `allowed: false` — so flows can exercise both
5
+ * UI branches outside the iframe. The runtime answers from the hydrated
6
+ * active user's role instead.
7
+ */
8
+ export declare const mockCheckPermission: CheckPermission;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Standalone mock: `allowed: true` for every permission EXCEPT the magic name
3
+ * `'mock_denied'`, which returns `allowed: false` — so flows can exercise both
4
+ * UI branches outside the iframe. The runtime answers from the hydrated
5
+ * active user's role instead.
6
+ */
7
+ export const mockCheckPermission = async (params) => {
8
+ console.log('[Mock] checkPermission called', params);
9
+ if (!params?.permission) {
10
+ throw new Error('permission is required');
11
+ }
12
+ return {
13
+ success: true,
14
+ permission: params.permission,
15
+ allowed: params.permission !== 'mock_denied',
16
+ timestamp: new Date().toISOString(),
17
+ };
18
+ };
@@ -0,0 +1,17 @@
1
+ export interface CheckPermissionParams {
2
+ /** Permission name, e.g. 'issue_refunds'. */
3
+ permission: string;
4
+ }
5
+ export interface CheckPermissionResponse {
6
+ success: boolean;
7
+ /** Echo of the permission that was checked. */
8
+ permission: string;
9
+ /**
10
+ * True when the active user holds the permission — either explicitly on
11
+ * their role, or implicitly because their user type does not carry a role
12
+ * (company owner, final/org staff).
13
+ */
14
+ allowed: boolean;
15
+ timestamp: string;
16
+ }
17
+ export type CheckPermission = (params: CheckPermissionParams) => Promise<CheckPermissionResponse>;
@@ -0,0 +1,9 @@
1
+ // Check Permission Types
2
+ //
3
+ // READ-ONLY query: does the ACTIVE user hold a named permission? Truth source
4
+ // is the runtime's hydrated active user (role + permissions from the synced
5
+ // `users`/`roles` collections). Use it to PRE-GATE UI (hide/disable a Refund
6
+ // button, show "You are not allowed to initiate refunds") — it is not the
7
+ // security boundary: mutating refund commands enforce `issue_refunds`
8
+ // runtime-side regardless (`REFUND_PERMISSION_DENIED: ` prefix).
9
+ export {};
@@ -1,6 +1,4 @@
1
1
  import { MOCK_ORDERS, mockPublishEvent } from '../../demo/database';
2
- // Payment states in which an order is refundable
3
- const REFUNDABLE_PAYMENT_STATES = ['paid', 'partially_refunded'];
4
2
  // Track refunded amounts per order to enforce remaining capacity gate
5
3
  const mockRefundedAmounts = {};
6
4
  export const mockRedeemRefund = async (params) => {
@@ -18,10 +16,8 @@ export const mockRedeemRefund = async (params) => {
18
16
  throw new Error(`Order with ID ${params.orderId} not found`);
19
17
  }
20
18
  const orderId = order._id;
21
- // Check if order is in a refundable state
22
- if (!REFUNDABLE_PAYMENT_STATES.includes(order.paymentState)) {
23
- throw new Error(`ORDER_NOT_REFUNDABLE: order ${orderId} is '${order.paymentState}' — only 'paid' or 'partially_refunded' orders can be refunded`);
24
- }
19
+ // NO payment-state gate the runtime has none (partially_paid orders are
20
+ // refundable too); mirroring it here would teach devs a phantom error class.
25
21
  // Track refunded amounts and check remaining capacity
26
22
  const refundedSoFar = mockRefundedAmounts[orderId] || 0;
27
23
  const remainingCapacity = order.summary.total - refundedSoFar;
package/dist/index.d.ts CHANGED
@@ -82,6 +82,7 @@ export declare const command: {
82
82
  readonly processPartialRefund: import(".").ProcessPartialRefund;
83
83
  readonly redeemRefund: import(".").RedeemRefund;
84
84
  readonly getRefundPlan: import(".").GetRefundPlan;
85
+ readonly checkPermission: import(".").CheckPermission;
85
86
  readonly addProduct: import(".").AddProduct;
86
87
  readonly editProduct: import(".").EditProduct;
87
88
  readonly editProductVariants: import(".").EditProductVariants;
@@ -142,6 +143,7 @@ export type { GetRemainingRefundableQuantities, GetRemainingRefundableQuantities
142
143
  export type { ProcessPartialRefund, ProcessPartialRefundParams, ProcessPartialRefundResponse, } from './actions/process-partial-refund/types';
143
144
  export type { RedeemRefund, RedeemRefundParams, RedeemRefundResponse } from './actions/redeem-refund/types';
144
145
  export type { GetRefundPlan, GetRefundPlanParams, GetRefundPlanResponse, RefundPlanSource, } from './actions/get-refund-plan/types';
146
+ export type { CheckPermission, CheckPermissionParams, CheckPermissionResponse, } from './actions/check-permission/types';
145
147
  export type { InitiateRefund, InitiateRefundParams, InitiateRefundResponse } from './actions/initiate-refund/types';
146
148
  export type { OpenExtensionOverlay, OpenExtensionOverlayParams, OpenExtensionOverlayResponse, } from './actions/open-extension-overlay/types';
147
149
  export type { ResolveExtensionOverlay, ResolveExtensionOverlayParams, ResolveExtensionOverlayResponse, } from './actions/resolve-extension-overlay/types';
package/dist/index.js CHANGED
@@ -89,6 +89,7 @@ import { getRemainingRefundableQuantities } from './actions/get-remaining-refund
89
89
  import { processPartialRefund } from './actions/process-partial-refund/action';
90
90
  import { redeemRefund } from './actions/redeem-refund/action';
91
91
  import { getRefundPlan } from './actions/get-refund-plan/action';
92
+ import { checkPermission } from './actions/check-permission/action';
92
93
  // Custom Tables Actions
93
94
  import { getCustomTables } from './actions/get-custom-tables/action';
94
95
  import { getCustomTableFields } from './actions/get-custom-table-fields/action';
@@ -221,6 +222,7 @@ export const command = {
221
222
  processPartialRefund,
222
223
  redeemRefund,
223
224
  getRefundPlan,
225
+ checkPermission,
224
226
  // Product CRUD Actions
225
227
  addProduct,
226
228
  editProduct,
@@ -52,6 +52,7 @@ import { mockPartialPayment } from '../../actions/partial-payment/mock';
52
52
  import { mockProcessPartialRefund } from '../../actions/process-partial-refund/mock';
53
53
  import { mockRedeemRefund } from '../../actions/redeem-refund/mock';
54
54
  import { mockGetRefundPlan } from '../../actions/get-refund-plan/mock';
55
+ import { mockCheckPermission } from '../../actions/check-permission/mock';
55
56
  import { mockRemoveCustomerFromCart } from '../../actions/remove-customer-from-cart/mock';
56
57
  import { mockResetRefundDetails } from '../../actions/reset-refund-details/mock';
57
58
  import { mockResumeParkedOrder } from '../../actions/resume-parked-order/mock';
@@ -148,6 +149,7 @@ export const RENDER_MOCKS = {
148
149
  processPartialRefund: mockProcessPartialRefund,
149
150
  redeemRefund: mockRedeemRefund,
150
151
  getRefundPlan: mockGetRefundPlan,
152
+ checkPermission: mockCheckPermission,
151
153
  removeCustomerFromCart: mockRemoveCustomerFromCart,
152
154
  removeCartDiscount: mockRemoveCartDiscount,
153
155
  resetRefundDetails: mockResetRefundDetails,
@@ -1,4 +1,4 @@
1
- import type { ExampleFunction, GetProducts, AddCustomSale, EditCustomSale, GetCustomers, AssignCustomer, AddCustomer, EditCustomer, GetCategories, GetOrders, GetRefunds, GetTaxTables, AddProductDiscount, AddProductToCart, RemoveProductFromCart, UpdateCartItemQuantity, AddCartDiscount, GetContext, GetFinalContext, AddProductNote, AddProductFee, SetActiveProductFee, SetActiveProductDiscount, GetActiveProduct, SetActiveProduct, AdjustInventory, AddOrderNote, AddCartFee, ClearCart, ParkOrder, ResumeParkedOrder, DeleteParkedOrder, VoidOrder, InitiateRefund, CashPayment, GetCashRoundingAmount, TapToPayPayment, TerminalPayment, VendaraPayment, ExtensionPayment, RedeemPayment, AddNonRevenueItem, AddCustomerNote, RemoveCustomerNote, RemoveCustomerFromCart, GoToStationHome, OpenCashDrawer, ShowNotification, ShowConfirmation, AuthenticateUser, PartialPayment, SwitchUser, SetRefundStockAction, SelectAllRefundItems, ResetRefundDetails, CalculateRefundTotal, GetRemainingRefundableQuantities, ProcessPartialRefund, RedeemRefund, GetRefundPlan, GetCurrentCart, Print, SetActiveOrder, GetCustomTables, GetCustomTableData, UpsertCustomTableData, DeleteCustomTableData, GetCustomExtensions, GetCurrentCompanyCustomExtensions, GetCustomExtensionCustomTables, GetCustomTableFields, GetSecretsKeys, GetSecretVal, SetSecretVal, GetUsers, GetRoles, RemoveCartDiscount, GetActiveOrder, GetActiveCustomer, SetActiveCustomer, GetActiveOutlet, GetActiveStation, GetActiveSession, GetActiveUser, SetActiveUser, SetActiveRefund, RemoveProductDiscount, RemoveProductFee, RemoveProductNote, RemoveCartFee, RemoveOrderNote, RemoveCustomSale, RemoveNonRevenueItem, CanTransition, GetAvailableTransitions, ApplyTransition, IntegrationPayment, GetSmartGridLayout, SaveSmartGridLayout, SendEmail, SendSms } from '../../index';
1
+ import type { ExampleFunction, GetProducts, AddCustomSale, EditCustomSale, GetCustomers, AssignCustomer, AddCustomer, EditCustomer, GetCategories, GetOrders, GetRefunds, GetTaxTables, AddProductDiscount, AddProductToCart, RemoveProductFromCart, UpdateCartItemQuantity, AddCartDiscount, GetContext, GetFinalContext, AddProductNote, AddProductFee, SetActiveProductFee, SetActiveProductDiscount, GetActiveProduct, SetActiveProduct, AdjustInventory, AddOrderNote, AddCartFee, ClearCart, ParkOrder, ResumeParkedOrder, DeleteParkedOrder, VoidOrder, InitiateRefund, CashPayment, GetCashRoundingAmount, TapToPayPayment, TerminalPayment, VendaraPayment, ExtensionPayment, RedeemPayment, AddNonRevenueItem, AddCustomerNote, RemoveCustomerNote, RemoveCustomerFromCart, GoToStationHome, OpenCashDrawer, ShowNotification, ShowConfirmation, AuthenticateUser, PartialPayment, SwitchUser, SetRefundStockAction, SelectAllRefundItems, ResetRefundDetails, CalculateRefundTotal, GetRemainingRefundableQuantities, ProcessPartialRefund, RedeemRefund, GetRefundPlan, CheckPermission, GetCurrentCart, Print, SetActiveOrder, GetCustomTables, GetCustomTableData, UpsertCustomTableData, DeleteCustomTableData, GetCustomExtensions, GetCurrentCompanyCustomExtensions, GetCustomExtensionCustomTables, GetCustomTableFields, GetSecretsKeys, GetSecretVal, SetSecretVal, GetUsers, GetRoles, RemoveCartDiscount, GetActiveOrder, GetActiveCustomer, SetActiveCustomer, GetActiveOutlet, GetActiveStation, GetActiveSession, GetActiveUser, SetActiveUser, SetActiveRefund, RemoveProductDiscount, RemoveProductFee, RemoveProductNote, RemoveCartFee, RemoveOrderNote, RemoveCustomSale, RemoveNonRevenueItem, CanTransition, GetAvailableTransitions, ApplyTransition, IntegrationPayment, GetSmartGridLayout, SaveSmartGridLayout, SendEmail, SendSms } from '../../index';
2
2
  import type { OpenExtensionOverlay } from '../../actions/open-extension-overlay/types';
3
3
  import type { ResolveExtensionOverlay } from '../../actions/resolve-extension-overlay/types';
4
4
  export interface RenderProviderActions {
@@ -66,6 +66,7 @@ export interface RenderProviderActions {
66
66
  processPartialRefund: ProcessPartialRefund;
67
67
  redeemRefund: RedeemRefund;
68
68
  getRefundPlan: GetRefundPlan;
69
+ checkPermission: CheckPermission;
69
70
  getCurrentCart: GetCurrentCart;
70
71
  print: Print;
71
72
  setActiveOrder: SetActiveOrder;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@final-commerce/command-frame",
3
- "version": "0.4.1-preprod.1",
3
+ "version": "0.4.2-preprod.1",
4
4
  "description": "Commands Frame library",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",