@final-commerce/command-frame 0.1.57 → 0.1.59
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 +2 -2
- package/dist/actions/set-active-product/mock.js +37 -24
- package/dist/actions/set-active-product-discount/action.d.ts +6 -0
- package/dist/actions/set-active-product-discount/action.js +8 -0
- package/dist/actions/set-active-product-discount/mock.d.ts +2 -0
- package/dist/actions/set-active-product-discount/mock.js +20 -0
- package/dist/actions/set-active-product-discount/types.d.ts +16 -0
- package/dist/actions/set-active-product-discount/types.js +1 -0
- package/dist/actions/set-active-product-fee/action.d.ts +6 -0
- package/dist/actions/set-active-product-fee/action.js +8 -0
- package/dist/actions/set-active-product-fee/mock.d.ts +2 -0
- package/dist/actions/set-active-product-fee/mock.js +22 -0
- package/dist/actions/set-active-product-fee/types.d.ts +19 -0
- package/dist/actions/set-active-product-fee/types.js +1 -0
- package/dist/actions/terminal-payment/mock.js +2 -1
- package/dist/actions/terminal-payment/types.d.ts +2 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/projects/render/mocks.js +4 -0
- package/dist/projects/render/types.d.ts +3 -1
- package/dist/pubsub/subscriber.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -75,7 +75,7 @@ const context = await client.getContext();
|
|
|
75
75
|
The pub/sub system allows iframe extensions to subscribe to topics and receive real-time events published by the host (Render). Subscriptions are **page-scoped** -- they fire only while the iframe is mounted on the current page.
|
|
76
76
|
|
|
77
77
|
- **[Pub/Sub Documentation](./src/pubsub/README.md)**
|
|
78
|
-
- **Topics:** Cart (
|
|
78
|
+
- **Topics:** Cart (9), Customers (8), Orders (4), Payments (2), Products (4), Refunds (4), Print (3), Custom Tables (3), Outlet (2), Station (2), Session (2), Users (2).
|
|
79
79
|
|
|
80
80
|
```typescript
|
|
81
81
|
import { topics } from '@final-commerce/command-frame';
|
|
@@ -117,7 +117,7 @@ hooks.unregister('my-extension:cart-log');
|
|
|
117
117
|
### What you should do
|
|
118
118
|
|
|
119
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.
|
|
120
|
+
2. The helper validates `event.source === window.top`, parses params, and replies with the same **`PostMessageResponse`** envelope as the rest of Command Frame (`requestId`, `success`, `data` / `error`).
|
|
121
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
122
|
|
|
123
123
|
Exported APIs: `installExtensionRefundListener`, `EXTENSION_REFUND_REQUEST_ACTION`, types **`ExtensionRefundParams`** / **`ExtensionRefundResponse`**.
|
|
@@ -1,34 +1,47 @@
|
|
|
1
|
+
import { MOCK_PRODUCTS, setMockActiveProduct } from "../../demo/database";
|
|
1
2
|
export const mockSetActiveProduct = async (params) => {
|
|
2
3
|
console.log("[Mock] setActiveProduct called", params);
|
|
3
4
|
if (!params?.variantId) {
|
|
4
5
|
throw new Error("Variant ID is required");
|
|
5
6
|
}
|
|
6
|
-
|
|
7
|
+
const { variantId } = params;
|
|
8
|
+
let matchedProduct;
|
|
9
|
+
let matchedVariant;
|
|
10
|
+
for (const product of MOCK_PRODUCTS) {
|
|
11
|
+
const variant = product.variants.find(v => v._id === variantId);
|
|
12
|
+
if (variant) {
|
|
13
|
+
matchedProduct = product;
|
|
14
|
+
matchedVariant = variant;
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const activeProduct = {
|
|
19
|
+
id: matchedProduct?._id || "mock_product",
|
|
20
|
+
internalId: `internal_${Date.now()}`,
|
|
21
|
+
externalId: matchedVariant?.externalId || "mock_external_id",
|
|
22
|
+
productExternalId: matchedProduct?.externalId || "mock_product_external_id",
|
|
23
|
+
variantId: matchedVariant?._id || variantId,
|
|
24
|
+
name: matchedProduct?.name || "Mock Product",
|
|
25
|
+
sku: matchedVariant?.sku || "mock_sku",
|
|
26
|
+
price: matchedVariant?.price || 100,
|
|
27
|
+
images: matchedVariant?.images || matchedProduct?.images || [],
|
|
28
|
+
taxTableId: matchedProduct?.taxTable || "mock_tax_table_id",
|
|
29
|
+
quantity: 1,
|
|
30
|
+
note: undefined,
|
|
31
|
+
discount: undefined,
|
|
32
|
+
description: matchedProduct?.description || "Mock Description",
|
|
33
|
+
barcodeId: matchedVariant?.barcode || "mock_barcode_id",
|
|
34
|
+
stock: matchedVariant?.inventory?.[0]?.stock ?? 100,
|
|
35
|
+
allowBackOrder: matchedVariant?.allowBackorder || false,
|
|
36
|
+
fee: undefined,
|
|
37
|
+
isUnlimited: !matchedVariant?.manageStock,
|
|
38
|
+
attributes: matchedVariant?.attributes?.map(a => a.value).join(", ") || "",
|
|
39
|
+
localQuantity: 1,
|
|
40
|
+
};
|
|
41
|
+
setMockActiveProduct(activeProduct);
|
|
7
42
|
return {
|
|
8
43
|
success: true,
|
|
9
|
-
product:
|
|
10
|
-
id: "mock_product",
|
|
11
|
-
internalId: "mock_internal_id",
|
|
12
|
-
externalId: "mock_external_id",
|
|
13
|
-
productExternalId: "mock_product_external_id",
|
|
14
|
-
variantId: params.variantId,
|
|
15
|
-
name: "Mock Product",
|
|
16
|
-
sku: "mock_sku",
|
|
17
|
-
price: 100,
|
|
18
|
-
images: [],
|
|
19
|
-
taxTableId: "mock_tax_table_id",
|
|
20
|
-
quantity: 1,
|
|
21
|
-
note: "Mock Note",
|
|
22
|
-
discount: undefined,
|
|
23
|
-
description: "Mock Description",
|
|
24
|
-
barcodeId: "mock_barcode_id",
|
|
25
|
-
stock: 100,
|
|
26
|
-
allowBackOrder: false,
|
|
27
|
-
fee: undefined,
|
|
28
|
-
isUnlimited: false,
|
|
29
|
-
attributes: "Mock Attributes",
|
|
30
|
-
localQuantity: 1,
|
|
31
|
-
},
|
|
44
|
+
product: activeProduct,
|
|
32
45
|
timestamp: new Date().toISOString()
|
|
33
46
|
};
|
|
34
47
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Set active product discount action
|
|
3
|
+
* Updates the discount on the currently active product (without adding to cart)
|
|
4
|
+
*/
|
|
5
|
+
import { commandFrameClient } from "../../client";
|
|
6
|
+
export const setActiveProductDiscount = async (params) => {
|
|
7
|
+
return await commandFrameClient.call("setActiveProductDiscount", params);
|
|
8
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { MOCK_ACTIVE_PRODUCT, setMockActiveProduct } from "../../demo/database";
|
|
2
|
+
export const mockSetActiveProductDiscount = async (params) => {
|
|
3
|
+
console.log("[Mock] setActiveProductDiscount called", params);
|
|
4
|
+
if (!MOCK_ACTIVE_PRODUCT) {
|
|
5
|
+
throw new Error("No active product. Call setActiveProduct first.");
|
|
6
|
+
}
|
|
7
|
+
const discount = {
|
|
8
|
+
value: params.amount,
|
|
9
|
+
isPercent: params.isPercent || false,
|
|
10
|
+
label: params.label || "Discount"
|
|
11
|
+
};
|
|
12
|
+
setMockActiveProduct({ ...MOCK_ACTIVE_PRODUCT, discount });
|
|
13
|
+
return {
|
|
14
|
+
success: true,
|
|
15
|
+
amount: params.amount,
|
|
16
|
+
isPercent: discount.isPercent,
|
|
17
|
+
label: discount.label,
|
|
18
|
+
timestamp: new Date().toISOString()
|
|
19
|
+
};
|
|
20
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface SetActiveProductDiscountParams {
|
|
2
|
+
/** The discount amount. If isPercent is true, this is a percentage. */
|
|
3
|
+
amount: number;
|
|
4
|
+
/** Defaults to `false`. */
|
|
5
|
+
isPercent?: boolean;
|
|
6
|
+
/** Defaults to "Discount". */
|
|
7
|
+
label?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface SetActiveProductDiscountResponse {
|
|
10
|
+
success: boolean;
|
|
11
|
+
amount: number;
|
|
12
|
+
isPercent: boolean;
|
|
13
|
+
label: string;
|
|
14
|
+
timestamp: string;
|
|
15
|
+
}
|
|
16
|
+
export type SetActiveProductDiscount = (params: SetActiveProductDiscountParams) => Promise<SetActiveProductDiscountResponse>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Set active product fee action
|
|
3
|
+
* Updates the fee on the currently active product (without adding to cart)
|
|
4
|
+
*/
|
|
5
|
+
import { commandFrameClient } from "../../client";
|
|
6
|
+
export const setActiveProductFee = async (params) => {
|
|
7
|
+
return await commandFrameClient.call("setActiveProductFee", params);
|
|
8
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { MOCK_ACTIVE_PRODUCT, setMockActiveProduct } from "../../demo/database";
|
|
2
|
+
export const mockSetActiveProductFee = async (params) => {
|
|
3
|
+
console.log("[Mock] setActiveProductFee called", params);
|
|
4
|
+
if (!MOCK_ACTIVE_PRODUCT) {
|
|
5
|
+
throw new Error("No active product. Call setActiveProduct first.");
|
|
6
|
+
}
|
|
7
|
+
const fee = {
|
|
8
|
+
label: params.label || "Fee",
|
|
9
|
+
amount: params.amount,
|
|
10
|
+
isPercent: params.isPercent || false,
|
|
11
|
+
applyTaxes: params.applyTaxes || false
|
|
12
|
+
};
|
|
13
|
+
setMockActiveProduct({ ...MOCK_ACTIVE_PRODUCT, fee });
|
|
14
|
+
return {
|
|
15
|
+
success: true,
|
|
16
|
+
amount: params.amount,
|
|
17
|
+
isPercent: fee.isPercent,
|
|
18
|
+
label: fee.label,
|
|
19
|
+
applyTaxes: fee.applyTaxes,
|
|
20
|
+
timestamp: new Date().toISOString()
|
|
21
|
+
};
|
|
22
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface SetActiveProductFeeParams {
|
|
2
|
+
amount: number;
|
|
3
|
+
/** Defaults to `false`. */
|
|
4
|
+
isPercent?: boolean;
|
|
5
|
+
/** Defaults to "Fee". */
|
|
6
|
+
label?: string;
|
|
7
|
+
/** Defaults to `false`. */
|
|
8
|
+
applyTaxes?: boolean;
|
|
9
|
+
taxTableId?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface SetActiveProductFeeResponse {
|
|
12
|
+
success: boolean;
|
|
13
|
+
amount: number;
|
|
14
|
+
isPercent: boolean;
|
|
15
|
+
label: string;
|
|
16
|
+
applyTaxes: boolean;
|
|
17
|
+
timestamp: string;
|
|
18
|
+
}
|
|
19
|
+
export type SetActiveProductFee = (params: SetActiveProductFeeParams) => Promise<SetActiveProductFeeResponse>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { createOrderFromCart, MOCK_CART } from "../../demo/database";
|
|
2
2
|
export const mockTerminalPayment = async (params) => {
|
|
3
3
|
console.log("[Mock] terminalPayment called", params);
|
|
4
|
+
const connectionType = params?.paymentType || "Cloud";
|
|
4
5
|
// Simulate terminal interaction
|
|
5
|
-
window.alert(
|
|
6
|
+
window.alert(`Demo: Processing ${connectionType} Terminal Payment...\n(Please tap, insert, or swipe card on terminal)`);
|
|
6
7
|
const amount = params?.amount || MOCK_CART.total;
|
|
7
8
|
// Mocking terminal payment success immediately
|
|
8
9
|
const order = createOrderFromCart("card", amount, "stripe_terminal");
|
|
@@ -2,6 +2,8 @@ import { CFOrder } from "../../CommonTypes";
|
|
|
2
2
|
export interface TerminalPaymentParams {
|
|
3
3
|
/** If not provided, uses the cart total. */
|
|
4
4
|
amount?: number;
|
|
5
|
+
/** "Bluetooth" or "Cloud". Defaults to "Cloud". */
|
|
6
|
+
paymentType?: 'Bluetooth' | 'Cloud';
|
|
5
7
|
}
|
|
6
8
|
export interface TerminalPaymentResponse {
|
|
7
9
|
success: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -20,6 +20,8 @@ export declare const command: {
|
|
|
20
20
|
readonly getFinalContext: import("./actions/get-final-context/types").GetFinalContext;
|
|
21
21
|
readonly addProductNote: import("./actions/add-product-note/types").AddProductNote;
|
|
22
22
|
readonly addProductFee: import("./actions/add-product-fee/types").AddProductFee;
|
|
23
|
+
readonly setActiveProductFee: import("./actions/set-active-product-fee/types").SetActiveProductFee;
|
|
24
|
+
readonly setActiveProductDiscount: import("./actions/set-active-product-discount/types").SetActiveProductDiscount;
|
|
23
25
|
readonly getActiveProduct: import("./actions/get-active-product/types").GetActiveProduct;
|
|
24
26
|
readonly setActiveProduct: import("./actions/set-active-product/types").SetActiveProduct;
|
|
25
27
|
readonly adjustInventory: import("./actions/adjust-inventory/types").AdjustInventory;
|
|
@@ -131,6 +133,8 @@ export type { GetContext, GetContextResponse, GetContextResponseManage, GetConte
|
|
|
131
133
|
export type { GetFinalContext, GetFinalContextResponse } from "./actions/get-final-context/types";
|
|
132
134
|
export type { AddProductNote, AddProductNoteParams, AddProductNoteResponse } from "./actions/add-product-note/types";
|
|
133
135
|
export type { AddProductFee, AddProductFeeParams, AddProductFeeResponse } from "./actions/add-product-fee/types";
|
|
136
|
+
export type { SetActiveProductFee, SetActiveProductFeeParams, SetActiveProductFeeResponse } from "./actions/set-active-product-fee/types";
|
|
137
|
+
export type { SetActiveProductDiscount, SetActiveProductDiscountParams, SetActiveProductDiscountResponse } from "./actions/set-active-product-discount/types";
|
|
134
138
|
export type { GetActiveProduct, GetActiveProductResponse } from "./actions/get-active-product/types";
|
|
135
139
|
export type { SetActiveProduct, SetActiveProductParams, SetActiveProductResponse } from "./actions/set-active-product/types";
|
|
136
140
|
export type { AdjustInventory, AdjustInventoryParams, AdjustInventoryResponse } from "./actions/adjust-inventory/types";
|
package/dist/index.js
CHANGED
|
@@ -19,6 +19,8 @@ import { updateCartItemQuantity } from "./actions/update-cart-item-quantity/acti
|
|
|
19
19
|
// Product Actions
|
|
20
20
|
import { addProductNote } from "./actions/add-product-note/action";
|
|
21
21
|
import { addProductFee } from "./actions/add-product-fee/action";
|
|
22
|
+
import { setActiveProductFee } from "./actions/set-active-product-fee/action";
|
|
23
|
+
import { setActiveProductDiscount } from "./actions/set-active-product-discount/action";
|
|
22
24
|
import { getActiveProduct } from "./actions/get-active-product/action";
|
|
23
25
|
import { setActiveProduct } from "./actions/set-active-product/action";
|
|
24
26
|
import { adjustInventory } from "./actions/adjust-inventory/action";
|
|
@@ -131,6 +133,8 @@ export const command = {
|
|
|
131
133
|
// Product Actions
|
|
132
134
|
addProductNote,
|
|
133
135
|
addProductFee,
|
|
136
|
+
setActiveProductFee,
|
|
137
|
+
setActiveProductDiscount,
|
|
134
138
|
getActiveProduct,
|
|
135
139
|
setActiveProduct,
|
|
136
140
|
adjustInventory,
|
|
@@ -7,6 +7,8 @@ import { mockEditCustomer } from "../../actions/edit-customer/mock";
|
|
|
7
7
|
import { mockAddOrderNote } from "../../actions/add-order-note/mock";
|
|
8
8
|
import { mockAddProductDiscount } from "../../actions/add-product-discount/mock";
|
|
9
9
|
import { mockAddProductFee } from "../../actions/add-product-fee/mock";
|
|
10
|
+
import { mockSetActiveProductFee } from "../../actions/set-active-product-fee/mock";
|
|
11
|
+
import { mockSetActiveProductDiscount } from "../../actions/set-active-product-discount/mock";
|
|
10
12
|
import { mockGetActiveProduct } from "../../actions/get-active-product/mock";
|
|
11
13
|
import { mockSetActiveProduct } from "../../actions/set-active-product/mock";
|
|
12
14
|
import { mockAddProductNote } from "../../actions/add-product-note/mock";
|
|
@@ -91,6 +93,8 @@ export const RENDER_MOCKS = {
|
|
|
91
93
|
addOrderNote: mockAddOrderNote,
|
|
92
94
|
addProductDiscount: mockAddProductDiscount,
|
|
93
95
|
addProductFee: mockAddProductFee,
|
|
96
|
+
setActiveProductFee: mockSetActiveProductFee,
|
|
97
|
+
setActiveProductDiscount: mockSetActiveProductDiscount,
|
|
94
98
|
getActiveProduct: mockGetActiveProduct,
|
|
95
99
|
setActiveProduct: mockSetActiveProduct,
|
|
96
100
|
addProductNote: mockAddProductNote,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExampleFunction, GetProducts, AddCustomSale, GetCustomers, AssignCustomer, AddCustomer, EditCustomer, GetCategories, GetOrders, GetRefunds, AddProductDiscount, AddProductToCart, RemoveProductFromCart, UpdateCartItemQuantity, AddCartDiscount, GetContext, GetFinalContext, AddProductNote, AddProductFee, GetActiveProduct, SetActiveProduct, 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, RemoveCartDiscount, GetActiveOrder, GetActiveCustomer, SetActiveCustomer, GetActiveOutlet, SetActiveOutlet, GetActiveStation, SetActiveStation, GetActiveSession, SetActiveSession, GetActiveUser, SetActiveUser, GetActiveRefund, SetActiveRefund } from "../../index";
|
|
1
|
+
import type { ExampleFunction, GetProducts, AddCustomSale, GetCustomers, AssignCustomer, AddCustomer, EditCustomer, GetCategories, GetOrders, GetRefunds, AddProductDiscount, AddProductToCart, RemoveProductFromCart, UpdateCartItemQuantity, AddCartDiscount, GetContext, GetFinalContext, AddProductNote, AddProductFee, SetActiveProductFee, SetActiveProductDiscount, GetActiveProduct, SetActiveProduct, 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, RemoveCartDiscount, GetActiveOrder, GetActiveCustomer, SetActiveCustomer, GetActiveOutlet, SetActiveOutlet, GetActiveStation, SetActiveStation, GetActiveSession, SetActiveSession, GetActiveUser, SetActiveUser, GetActiveRefund, SetActiveRefund } from "../../index";
|
|
2
2
|
export interface RenderProviderActions {
|
|
3
3
|
exampleFunction: ExampleFunction;
|
|
4
4
|
getProducts: GetProducts;
|
|
@@ -19,6 +19,8 @@ export interface RenderProviderActions {
|
|
|
19
19
|
getFinalContext: GetFinalContext;
|
|
20
20
|
addProductNote: AddProductNote;
|
|
21
21
|
addProductFee: AddProductFee;
|
|
22
|
+
setActiveProductFee: SetActiveProductFee;
|
|
23
|
+
setActiveProductDiscount: SetActiveProductDiscount;
|
|
22
24
|
getActiveProduct: GetActiveProduct;
|
|
23
25
|
setActiveProduct: SetActiveProduct;
|
|
24
26
|
adjustInventory: AdjustInventory;
|
|
@@ -13,7 +13,7 @@ export class TopicSubscriber {
|
|
|
13
13
|
this.debug = options.debug ?? false;
|
|
14
14
|
this.useGlobalDebug = options.debug === undefined;
|
|
15
15
|
// Detect standalone mode (not inside any iframe)
|
|
16
|
-
if (typeof window !==
|
|
16
|
+
if (typeof window !== "undefined" && (!window.top || window.top === window)) {
|
|
17
17
|
this.mockMode = true;
|
|
18
18
|
if (this.isDebugEnabled()) {
|
|
19
19
|
console.log("[TopicSubscriber] Mock Mode enabled (standalone mode detected)");
|