@shopfront/bridge 1.10.0 → 1.13.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/.idea/{shopfront-embedded-bridge.iml → embedded-bridge.iml} +0 -0
  2. package/.idea/inspectionProfiles/Project_Default.xml +1 -2
  3. package/.idea/modules.xml +1 -1
  4. package/README.md +3 -2
  5. package/lib/APIs/CurrentSale/Sale.d.ts +12 -0
  6. package/lib/APIs/CurrentSale/Sale.js +18 -0
  7. package/lib/APIs/CurrentSale/SaleProduct.d.ts +1 -1
  8. package/lib/APIs/CurrentSale/SaleProduct.js +1 -2
  9. package/lib/APIs/CurrentSale/ShopfrontSaleState.d.ts +1 -0
  10. package/lib/APIs/CurrentSale/index.js +5 -1
  11. package/lib/APIs/InternalMessages/InternalMessageSource.d.ts +1 -1
  12. package/lib/Actions/BaseAction.d.ts +13 -8
  13. package/lib/Actions/BaseAction.js +7 -6
  14. package/lib/Actions/Button.js +0 -1
  15. package/lib/Actions/Redirect.js +0 -2
  16. package/lib/Actions/SaleKey.js +0 -1
  17. package/lib/Actions/SaleUpdate.d.ts +5 -2
  18. package/lib/Actions/SaleUpdate.js +0 -1
  19. package/lib/Actions/Toast.d.ts +1 -2
  20. package/lib/Application.d.ts +57 -8
  21. package/lib/Application.js +118 -11
  22. package/lib/ApplicationEvents.d.ts +54 -4
  23. package/lib/ApplicationEvents.js +8 -4
  24. package/lib/Bridge.d.ts +1 -1
  25. package/lib/Bridge.js +6 -2
  26. package/lib/Common/EventEmitter.d.ts +4 -3
  27. package/lib/Common/Serializable.d.ts +1 -1
  28. package/lib/EmitableEvents/SellScreenPromotionApplicable.d.ts +13 -0
  29. package/lib/EmitableEvents/SellScreenPromotionApplicable.js +19 -0
  30. package/lib/Events/AudioPermissionChange.d.ts +6 -0
  31. package/lib/Events/AudioPermissionChange.js +13 -0
  32. package/lib/Events/BaseEvent.d.ts +5 -4
  33. package/lib/Events/BaseEvent.js +1 -0
  34. package/lib/Events/Callback.d.ts +1 -1
  35. package/lib/Events/Callback.js +2 -2
  36. package/lib/Events/FormatIntegratedProduct.d.ts +14 -3
  37. package/lib/Events/FormatIntegratedProduct.js +1 -1
  38. package/lib/Events/InternalPageMessage.d.ts +4 -8
  39. package/lib/Events/InternalPageMessage.js +1 -1
  40. package/lib/Events/PaymentMethodsEnabled.d.ts +15 -0
  41. package/lib/Events/PaymentMethodsEnabled.js +21 -0
  42. package/lib/Events/Ready.d.ts +2 -2
  43. package/lib/Events/Ready.js +1 -1
  44. package/lib/Events/RegisterChanged.js +1 -1
  45. package/lib/Events/RequestButtons.d.ts +7 -2
  46. package/lib/Events/RequestButtons.js +2 -2
  47. package/lib/Events/RequestCustomerListOptions.d.ts +3 -2
  48. package/lib/Events/RequestCustomerListOptions.js +3 -2
  49. package/lib/Events/RequestSaleKeys.d.ts +2 -1
  50. package/lib/Events/RequestSaleKeys.js +2 -2
  51. package/lib/Events/RequestSellScreenOptions.d.ts +3 -2
  52. package/lib/Events/RequestSellScreenOptions.js +3 -2
  53. package/lib/Events/RequestSettings.d.ts +3 -2
  54. package/lib/Events/RequestSettings.js +3 -2
  55. package/lib/Events/RequestTableColumns.d.ts +6 -2
  56. package/lib/Events/RequestTableColumns.js +1 -1
  57. package/lib/Events/SaleComplete.d.ts +2 -1
  58. package/lib/Events/SaleComplete.js +1 -1
  59. package/lib/Events/UIPipeline.d.ts +15 -0
  60. package/lib/Events/UIPipeline.js +31 -0
  61. package/lib/Utilities/ActionEventRegistrar.d.ts +3 -3
  62. package/lib/Utilities/MiscTypes.d.ts +3 -0
  63. package/lib/Utilities/Static.js +2 -0
  64. package/lib/index.d.ts +2 -1
  65. package/lib/index.js +8 -2
  66. package/package.json +31 -27
  67. package/.idea/compiler.xml +0 -6
  68. package/.idea/misc.xml +0 -6
  69. package/bitbucket-pipelines.yml +0 -22
@@ -1,7 +1,6 @@
1
1
  <component name="InspectionProjectProfileManager">
2
2
  <profile version="1.0">
3
3
  <option name="myName" value="Project Default" />
4
- <inspection_tool class="JSIgnoredPromiseFromCall" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
5
- <inspection_tool class="JSMethodCanBeStatic" enabled="false" level="WARNING" enabled_by_default="false" />
4
+ <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
6
5
  </profile>
7
6
  </component>
package/.idea/modules.xml CHANGED
@@ -2,7 +2,7 @@
2
2
  <project version="4">
3
3
  <component name="ProjectModuleManager">
4
4
  <modules>
5
- <module fileurl="file://$PROJECT_DIR$/.idea/shopfront-embedded-bridge.iml" filepath="$PROJECT_DIR$/.idea/shopfront-embedded-bridge.iml" />
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/embedded-bridge.iml" filepath="$PROJECT_DIR$/.idea/embedded-bridge.iml" />
6
6
  </modules>
7
7
  </component>
8
8
  </project>
package/README.md CHANGED
@@ -1,5 +1,6 @@
1
- #Shopfront Embedded Bridge
1
+ # Shopfront Embedded Bridge
2
+
2
3
  This is the bridge library to use with the Shopfront Embedded API.
3
4
 
4
5
  For more information, check out the documentation on the
5
- [Shopfront developer website](https://developer.onshopfront.com/documentation/Embedded/Introduction).
6
+ [Shopfront developer website](https://developer.onshopfront.com/documentation/Embedded/Introduction).
@@ -80,6 +80,12 @@ export declare class Sale {
80
80
  * @returns {string}
81
81
  */
82
82
  getOrderReference(): string;
83
+ /**
84
+ * Get the current meta data for the sale
85
+ *
86
+ * @returns {Record<string, unknown>}
87
+ */
88
+ getMetaData(): Record<string, unknown>;
83
89
  /**
84
90
  * Cancel the current sale in progress.
85
91
  *
@@ -162,6 +168,12 @@ export declare class Sale {
162
168
  * @returns {Promise<void>}
163
169
  */
164
170
  setOrderReference(reference: string): Promise<void>;
171
+ /**
172
+ * Set the meta data of the sale, this will override the previous meta data.
173
+ *
174
+ * @param metaData
175
+ */
176
+ setMetaData(metaData: Record<string, unknown>): Promise<void>;
165
177
  /**
166
178
  * Update a product's details, currently this only updates the top-level meta data
167
179
  * @param product
@@ -125,6 +125,14 @@ class Sale {
125
125
  getOrderReference() {
126
126
  return this.sale.orderReference;
127
127
  }
128
+ /**
129
+ * Get the current meta data for the sale
130
+ *
131
+ * @returns {Record<string, unknown>}
132
+ */
133
+ getMetaData() {
134
+ return this.sale.metaData;
135
+ }
128
136
  /**
129
137
  * Cancel the current sale in progress.
130
138
  *
@@ -257,6 +265,16 @@ class Sale {
257
265
  reference,
258
266
  }));
259
267
  }
268
+ /**
269
+ * Set the meta data of the sale, this will override the previous meta data.
270
+ *
271
+ * @param metaData
272
+ */
273
+ setMetaData(metaData) {
274
+ return this.sendSaleUpdate(new SaleUpdate_1.SaleUpdate("SALE_META_DATA", {
275
+ metaData,
276
+ }));
277
+ }
260
278
  /**
261
279
  * Update a product's details, currently this only updates the top-level meta data
262
280
  * @param product
@@ -73,7 +73,7 @@ export declare class SaleProduct {
73
73
  *
74
74
  * @returns {ShopfrontSaleProductType | undefined}
75
75
  */
76
- getType(): "Normal" | "Voucher" | "Basket" | "Package" | "Component" | undefined;
76
+ getType(): ShopfrontSaleProductType | undefined;
77
77
  /**
78
78
  * Get the tax rate amount.
79
79
  * This is the rate of the tax rate (e.g. 10 is a tax rate of 10%).
@@ -44,10 +44,9 @@ class SaleProduct {
44
44
  * @param {Array<number>} indexAddress
45
45
  */
46
46
  setInternal(data, indexAddress) {
47
- var _a;
48
47
  this.name = data.name;
49
48
  this.type = data.type;
50
- this.taxRateAmount = ((_a = data.tax) === null || _a === void 0 ? void 0 : _a.amount) || 0;
49
+ this.taxRateAmount = data.tax?.amount || 0;
51
50
  this.note = data.note;
52
51
  this.edited = data.edited;
53
52
  this.caseQuantity = data.caseQuantity;
@@ -48,5 +48,6 @@ export interface ShopfrontSaleState {
48
48
  orderReference: string;
49
49
  refundReason: string;
50
50
  priceSet: string | null;
51
+ metaData: Record<string, unknown>;
51
52
  }
52
53
  export {};
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -6,5 +6,5 @@ export declare class InternalMessageSource {
6
6
  protected method: InternalPageMessageMethod;
7
7
  protected url: string;
8
8
  constructor(application: Application, method: InternalPageMessageMethod, url: string);
9
- send(message: any): void;
9
+ send(message: unknown): void;
10
10
  }
@@ -1,21 +1,26 @@
1
1
  import { EventEmitter } from "../Common/EventEmitter";
2
2
  import { Serializable, Serialized } from "../Common/Serializable";
3
+ interface BaseActionConstructor<T> {
4
+ new (...args: Array<never>): BaseAction<T>;
5
+ new (serialized: Serialized<T>): BaseAction<T>;
6
+ }
3
7
  export declare class BaseAction<T> extends EventEmitter {
4
8
  protected target: string;
5
9
  protected events: Array<{
6
- callback: Function;
10
+ callback: (...args: Array<unknown>) => void;
7
11
  type: string;
8
12
  id: string;
9
13
  }>;
10
- protected properties: Array<any>;
14
+ protected properties: Array<unknown>;
11
15
  static serializedRegistry: {
12
- [id: string]: any;
16
+ [id: string]: BaseActionConstructor<unknown>;
13
17
  };
14
- constructor(serialized: Serialized<T>, type: any);
18
+ constructor(serialized: Serialized<T>, type: BaseActionConstructor<T>);
15
19
  serialize(): Serialized<T>;
16
- protected serializeProperties(properties: Array<any>): Array<any>;
20
+ protected serializeProperties(properties: Array<unknown>): Array<unknown>;
17
21
  static deserialize<T extends Serializable<T>>(serialized: Serialized<T>): T;
18
- addEventListener(event: string, callback: Function): void;
19
- removeEventListener(event: string, callback: Function): void;
20
- handleRegistrarEvent(id: string, data: any): void;
22
+ addEventListener(event: string, callback: (...args: Array<unknown>) => void): void;
23
+ removeEventListener(event: string, callback: (...args: Array<unknown>) => void): void;
24
+ handleRegistrarEvent(id: string, data: unknown): void;
21
25
  }
26
+ export {};
@@ -44,17 +44,18 @@ let BaseAction = BaseAction_1 = class BaseAction extends EventEmitter_1.EventEmi
44
44
  const results = [];
45
45
  // Loop through current layer of properties
46
46
  for (let i = 0, l = properties.length; i < l; i++) {
47
- if (Array.isArray(properties[i])) {
47
+ const property = properties[i];
48
+ if (Array.isArray(property)) {
48
49
  // Prepare to recurse through next layer of properties
49
- results.push(this.serializeProperties(properties[i]));
50
+ results.push(this.serializeProperties(property));
50
51
  }
51
- else if (properties[i] instanceof BaseAction_1) {
52
+ else if (property instanceof BaseAction_1) {
52
53
  // Serialize property
53
- results.push(properties[i].serialize());
54
+ results.push(property.serialize());
54
55
  }
55
56
  else {
56
57
  // Assume that the property is already serializable
57
- results.push(properties[i]);
58
+ results.push(property);
58
59
  }
59
60
  }
60
61
  return results;
@@ -102,6 +103,6 @@ let BaseAction = BaseAction_1 = class BaseAction extends EventEmitter_1.EventEmi
102
103
  };
103
104
  BaseAction.serializedRegistry = {};
104
105
  BaseAction = BaseAction_1 = __decorate([
105
- Static_1.staticImplements()
106
+ (0, Static_1.staticImplements)()
106
107
  ], BaseAction);
107
108
  exports.BaseAction = BaseAction;
@@ -19,7 +19,6 @@ class Button extends BaseAction_1.BaseAction {
19
19
  })(), Button);
20
20
  this.supportedEvents = ["click"];
21
21
  if (typeof icon === "undefined" && typeof label !== "string") {
22
- label = label;
23
22
  this.label = label.properties[0];
24
23
  this.icon = label.properties[1];
25
24
  }
@@ -19,7 +19,6 @@ class InternalRedirect extends BaseAction_1.BaseAction {
19
19
  })(), InternalRedirect);
20
20
  this.supportedEvents = ["click"];
21
21
  if (typeof to !== "string") {
22
- to = to;
23
22
  this.to = to.properties[0];
24
23
  }
25
24
  else {
@@ -47,7 +46,6 @@ class ExternalRedirect extends BaseAction_1.BaseAction {
47
46
  this.to = to;
48
47
  }
49
48
  else {
50
- to = to;
51
49
  this.to = new URL(to.properties[0]);
52
50
  }
53
51
  }
@@ -19,7 +19,6 @@ class SaleKey extends BaseAction_1.BaseAction {
19
19
  })(), SaleKey);
20
20
  this.supportedEvents = ["click"];
21
21
  if (typeof name === "undefined" && typeof id !== "string") {
22
- id = id;
23
22
  this.id = id.properties[0];
24
23
  this.name = id.properties[1];
25
24
  }
@@ -26,11 +26,11 @@ export interface SaleUpdateChanges {
26
26
  cashout?: number;
27
27
  status?: ShopfrontSalePaymentStatus;
28
28
  };
29
- SALE_CANCEL: {};
29
+ SALE_CANCEL: Record<string, never>;
30
30
  CUSTOMER_ADD: {
31
31
  id: string;
32
32
  };
33
- CUSTOMER_REMOVE: {};
33
+ CUSTOMER_REMOVE: Record<string, never>;
34
34
  SALE_EXTERNAL_NOTE: {
35
35
  note: string;
36
36
  append?: boolean;
@@ -42,6 +42,9 @@ export interface SaleUpdateChanges {
42
42
  SALE_ORDER_REFERENCE: {
43
43
  reference: string;
44
44
  };
45
+ SALE_META_DATA: {
46
+ metaData: Record<string, unknown>;
47
+ };
45
48
  PRODUCT_UPDATE: {
46
49
  id: string;
47
50
  indexAddress: Array<number>;
@@ -19,7 +19,6 @@ class SaleUpdate extends BaseAction_1.BaseAction {
19
19
  })(), SaleUpdate);
20
20
  this.supportedEvents = [];
21
21
  if (typeof data === "undefined" && typeof type !== "string") {
22
- type = type;
23
22
  this.type = type.properties[0];
24
23
  this.data = type.properties[1];
25
24
  }
@@ -1,10 +1,9 @@
1
1
  import { BaseAction } from "./BaseAction";
2
2
  import { Serialized } from "../Common/Serializable";
3
- declare type ToastType = "success" | "error" | "information" | "warning";
3
+ export declare type ToastType = "success" | "error" | "information" | "warning";
4
4
  export declare class Toast extends BaseAction<Toast> {
5
5
  protected supportedEvents: string[];
6
6
  protected type: ToastType;
7
7
  protected message: string;
8
8
  constructor(type: Serialized<Toast> | ToastType, message?: string);
9
9
  }
10
- export {};
@@ -1,10 +1,12 @@
1
1
  import { Bridge } from "./Bridge";
2
- import { DirectShopfrontEvent, FromShopfront, FromShopfrontCallbacks, FromShopfrontInternal, RegisterChangedEvent } from "./ApplicationEvents";
2
+ import { DirectShopfrontEvent, FromShopfront, FromShopfrontCallbacks, FromShopfrontInternal, RegisterChangedEvent, SoundEvents } from "./ApplicationEvents";
3
3
  import { Serializable } from "./Common/Serializable";
4
4
  import { BaseEmitableEvent } from "./EmitableEvents/BaseEmitableEvent";
5
5
  import { Sale } from "./APIs/CurrentSale";
6
+ import { ShopfrontSaleState } from "./APIs/CurrentSale/ShopfrontSaleState";
6
7
  import { Database } from "./APIs/Database/Database";
7
8
  import { MaybePromise } from "./Utilities/MiscTypes";
9
+ import { BaseEvent } from "./Events/BaseEvent";
8
10
  export declare class Application {
9
11
  protected bridge: Bridge;
10
12
  protected isReady: boolean;
@@ -13,7 +15,7 @@ export declare class Application {
13
15
  protected outlet: string | null;
14
16
  protected user: string | null;
15
17
  protected listeners: {
16
- [key in keyof Omit<FromShopfront, "CALLBACK">]: Map<Function, FromShopfront[key]>;
18
+ [key in keyof Omit<FromShopfront, "CALLBACK">]: Map<(...args: Array<unknown>) => void, FromShopfront[key] & BaseEvent>;
17
19
  };
18
20
  protected directListeners: {
19
21
  [K in DirectShopfrontEvent]?: Set<(data: unknown) => void | Promise<void>>;
@@ -21,22 +23,26 @@ export declare class Application {
21
23
  database: Database;
22
24
  constructor(bridge: Bridge);
23
25
  destroy(): void;
24
- protected handleEvent: (event: keyof FromShopfront | keyof FromShopfrontInternal, data: any, id: string) => void;
25
- protected emit(event: keyof Omit<FromShopfront, "CALLBACK"> | DirectShopfrontEvent, data: any, id: string): MaybePromise<void>;
26
+ protected handleEvent: (event: keyof FromShopfront | keyof FromShopfrontInternal, data: Record<string, unknown>, id: string) => void;
27
+ protected emit(event: keyof Omit<FromShopfront, "CALLBACK"> | DirectShopfrontEvent, data: Record<string, unknown> | undefined, id: string): void | Promise<void>;
26
28
  addEventListener<E extends keyof FromShopfrontCallbacks>(event: E, callback: FromShopfrontCallbacks[E]): void;
27
29
  addEventListener<D>(event: DirectShopfrontEvent, callback: (event: D) => MaybePromise<void>): void;
28
- removeEventListener(event: keyof Omit<FromShopfront, "CALLBACK"> | DirectShopfrontEvent, callback: (...args: Array<any>) => MaybePromise<any>): void;
29
- send(item: BaseEmitableEvent<any>): void;
30
- send(item: Serializable<any>): void;
30
+ removeEventListener(event: keyof Omit<FromShopfront, "CALLBACK"> | DirectShopfrontEvent, callback: (...args: Array<unknown>) => MaybePromise<void>): void;
31
+ send(item: BaseEmitableEvent<unknown>): void;
32
+ send(item: Serializable<unknown>): void;
31
33
  download(file: string): void;
32
34
  redirect(toLocation: string, externalRedirect?: boolean): void;
33
35
  load(): () => void;
34
36
  protected handleEventCallback(data: {
35
37
  id?: string;
36
- data: any;
38
+ data: unknown;
37
39
  }): void;
38
40
  protected handleLocationChanged(data: RegisterChangedEvent): void;
39
41
  getAuthenticationKey(): string;
42
+ protected dataIsSaleEvent(data: Record<string, unknown>): data is {
43
+ requestId: string;
44
+ saleState: ShopfrontSaleState | false;
45
+ };
40
46
  /**
41
47
  * Get the current sale on the sell screen, if the current device is not a register
42
48
  * then this will return false.
@@ -44,6 +50,12 @@ export declare class Application {
44
50
  * @returns {Promise<Sale | boolean>}
45
51
  */
46
52
  getCurrentSale(): Promise<Sale | false>;
53
+ protected dataIsLocation(data: Record<string, unknown>): data is {
54
+ requestId: string;
55
+ register: string | null;
56
+ outlet: string | null;
57
+ user: string | null;
58
+ };
47
59
  /**
48
60
  * Get the location from Shopfront
49
61
  */
@@ -53,5 +65,42 @@ export declare class Application {
53
65
  user: string | null;
54
66
  }>;
55
67
  printReceipt(content: string): void;
68
+ protected dataIsAudioResponse(data: Record<string, unknown>): data is {
69
+ requestId: string;
70
+ success: boolean;
71
+ message?: string;
72
+ };
73
+ protected sendAudioRequest(type: SoundEvents, data?: unknown): Promise<{
74
+ success: boolean;
75
+ message?: string;
76
+ }>;
77
+ /**
78
+ * Requests permission from the user to be able to play audio
79
+ */
80
+ requestAudioPermission(): Promise<{
81
+ success: boolean;
82
+ message?: string;
83
+ }>;
84
+ /**
85
+ * Requests shopfront to preload audio so that it can be pre-cached before being played
86
+ * @param url
87
+ */
88
+ audioPreload(url: string): Promise<{
89
+ success: boolean;
90
+ message?: string;
91
+ }>;
92
+ /**
93
+ * Requests the sound to be played
94
+ * @param url
95
+ */
96
+ audioPlay(url: string): Promise<{
97
+ success: boolean;
98
+ message?: string;
99
+ }>;
100
+ protected dataIsOption<TValueType>(data: Record<string, unknown>): data is {
101
+ requestId: string;
102
+ option: string;
103
+ value: TValueType | undefined;
104
+ };
56
105
  getOption<TValueType>(option: string, defaultValue: TValueType): Promise<TValueType>;
57
106
  }
@@ -21,6 +21,9 @@ const FormatIntegratedProduct_1 = require("./Events/FormatIntegratedProduct");
21
21
  const RequestCustomerListOptions_1 = require("./Events/RequestCustomerListOptions");
22
22
  const RequestSaleKeys_1 = require("./Events/RequestSaleKeys");
23
23
  const SaleComplete_1 = require("./Events/SaleComplete");
24
+ const UIPipeline_1 = require("./Events/UIPipeline");
25
+ const PaymentMethodsEnabled_1 = require("./Events/PaymentMethodsEnabled");
26
+ const AudioPermissionChange_1 = require("./Events/AudioPermissionChange");
24
27
  // noinspection JSUnusedGlobalSymbols
25
28
  class Application {
26
29
  constructor(bridge) {
@@ -36,6 +39,9 @@ class Application {
36
39
  REQUEST_CUSTOMER_LIST_OPTIONS: new Map(),
37
40
  REQUEST_SALE_KEYS: new Map(),
38
41
  SALE_COMPLETE: new Map(),
42
+ UI_PIPELINE: new Map(),
43
+ PAYMENT_METHODS_ENABLED: new Map(),
44
+ AUDIO_PERMISSION_CHANGE: new Map(),
39
45
  };
40
46
  this.directListeners = {};
41
47
  this.handleEvent = (event, data, id) => {
@@ -66,7 +72,8 @@ class Application {
66
72
  else if (event === "RESPONSE_CURRENT_SALE" ||
67
73
  event === "RESPONSE_DATABASE_REQUEST" ||
68
74
  event === "RESPONSE_LOCATION" ||
69
- event === "RESPONSE_OPTION") {
75
+ event === "RESPONSE_OPTION" ||
76
+ event === "RESPONSE_AUDIO_REQUEST") {
70
77
  // Handled elsewhere
71
78
  return;
72
79
  }
@@ -109,8 +116,8 @@ class Application {
109
116
  if (this.listeners[event].size === 0) {
110
117
  return this.bridge.sendMessage(ApplicationEvents_1.ToShopfront.NOT_LISTENING_TO_EVENT, event, id);
111
118
  }
112
- for (let e of this.listeners[event].values()) {
113
- results.push(e.emit(data));
119
+ for (const e of this.listeners[event].values()) {
120
+ results.push(e.emit(data, this.bridge));
114
121
  }
115
122
  // Respond if necessary
116
123
  switch (event) {
@@ -152,6 +159,18 @@ class Application {
152
159
  results = results;
153
160
  return Promise.all(results)
154
161
  .then(res => RequestSaleKeys_1.RequestSaleKeys.respond(this.bridge, res.flat(), id));
162
+ case "UI_PIPELINE":
163
+ results = results;
164
+ return Promise.all(results)
165
+ .then(res => {
166
+ return UIPipeline_1.UIPipeline.respond(this.bridge, res.flat(), id);
167
+ });
168
+ case "PAYMENT_METHODS_ENABLED":
169
+ results = results;
170
+ return Promise.all(results)
171
+ .then(res => {
172
+ return PaymentMethodsEnabled_1.PaymentMethodsEnabled.respond(this.bridge, res.flat(), id);
173
+ });
155
174
  }
156
175
  }
157
176
  addEventListener(event, callback) {
@@ -160,10 +179,13 @@ class Application {
160
179
  if (typeof this.directListeners[event] === "undefined") {
161
180
  this.directListeners[event] = new Set();
162
181
  }
182
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
163
183
  this.directListeners[event].add(callback);
164
184
  return;
165
185
  }
166
- let c = null;
186
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
187
+ let c;
188
+ event = event;
167
189
  switch (event) {
168
190
  case "READY":
169
191
  c = new Ready_1.Ready(callback);
@@ -209,8 +231,20 @@ class Application {
209
231
  c = new SaleComplete_1.SaleComplete(callback);
210
232
  this.listeners[event].set(callback, c);
211
233
  break;
234
+ case "UI_PIPELINE":
235
+ c = new UIPipeline_1.UIPipeline(callback);
236
+ this.listeners[event].set(callback, c);
237
+ break;
238
+ case "PAYMENT_METHODS_ENABLED":
239
+ c = new PaymentMethodsEnabled_1.PaymentMethodsEnabled(callback);
240
+ this.listeners[event].set(callback, c);
241
+ break;
242
+ case "AUDIO_PERMISSION_CHANGE":
243
+ c = new AudioPermissionChange_1.AudioPermissionChange(callback);
244
+ this.listeners[event].set(callback, c);
245
+ break;
212
246
  }
213
- if (c === null) {
247
+ if (typeof c === "undefined") {
214
248
  throw new TypeError(`${event} has not been defined`);
215
249
  }
216
250
  if (event === "READY" && this.isReady) {
@@ -223,9 +257,8 @@ class Application {
223
257
  }
224
258
  }
225
259
  removeEventListener(event, callback) {
226
- var _a;
227
260
  if (ApplicationEvents_1.directShopfrontEvents.includes(event)) {
228
- (_a = this.directListeners[event]) === null || _a === void 0 ? void 0 : _a.delete(callback);
261
+ this.directListeners[event]?.delete(callback);
229
262
  return;
230
263
  }
231
264
  this.listeners[event].delete(callback);
@@ -259,7 +292,7 @@ class Application {
259
292
  if (typeof data.id === "undefined") {
260
293
  return;
261
294
  }
262
- let id = data.id;
295
+ const id = data.id;
263
296
  ActionEventRegistrar_1.default.fire(id, data.data);
264
297
  }
265
298
  handleLocationChanged(data) {
@@ -270,6 +303,9 @@ class Application {
270
303
  getAuthenticationKey() {
271
304
  return this.key;
272
305
  }
306
+ dataIsSaleEvent(data) {
307
+ return typeof data.requestId === "string" && (data.saleState === false || typeof data.saleState === "object");
308
+ }
273
309
  /**
274
310
  * Get the current sale on the sell screen, if the current device is not a register
275
311
  * then this will return false.
@@ -283,7 +319,9 @@ class Application {
283
319
  if (event !== "RESPONSE_CURRENT_SALE") {
284
320
  return;
285
321
  }
286
- data = data;
322
+ if (!this.dataIsSaleEvent(data)) {
323
+ return;
324
+ }
287
325
  if (data.requestId !== saleRequest) {
288
326
  return;
289
327
  }
@@ -301,6 +339,12 @@ class Application {
301
339
  }
302
340
  return new CurrentSale_1.Sale(this, saleState);
303
341
  }
342
+ dataIsLocation(data) {
343
+ return typeof data.requestId === "string" &&
344
+ (typeof data.register === "string" || data.register === null) &&
345
+ (typeof data.outlet === "string" || data.outlet === null) &&
346
+ (typeof data.user === "string" || data.user === null);
347
+ }
304
348
  /**
305
349
  * Get the location from Shopfront
306
350
  */
@@ -311,7 +355,9 @@ class Application {
311
355
  if (event !== "RESPONSE_LOCATION") {
312
356
  return;
313
357
  }
314
- data = data;
358
+ if (!this.dataIsLocation(data)) {
359
+ return;
360
+ }
315
361
  if (data.requestId !== locationRequest) {
316
362
  return;
317
363
  }
@@ -336,6 +382,65 @@ class Application {
336
382
  type: "text",
337
383
  });
338
384
  }
385
+ dataIsAudioResponse(data) {
386
+ return typeof data.requestId === "string" &&
387
+ typeof data.success === "boolean" && (typeof data.message === "string" ||
388
+ typeof data.message === "undefined");
389
+ }
390
+ sendAudioRequest(type, data) {
391
+ const request = `AudioRequest-${type}-${Date.now().toString()}`;
392
+ const promise = new Promise(res => {
393
+ const listener = (event, data) => {
394
+ if (event !== "RESPONSE_AUDIO_REQUEST") {
395
+ return;
396
+ }
397
+ if (!this.dataIsAudioResponse(data)) {
398
+ return;
399
+ }
400
+ if (data.requestId !== request) {
401
+ return;
402
+ }
403
+ this.bridge.removeEventListener(listener);
404
+ res({
405
+ success: data.success,
406
+ message: data.message,
407
+ });
408
+ };
409
+ this.bridge.addEventListener(listener);
410
+ });
411
+ this.bridge.sendMessage(type, {
412
+ requestId: request,
413
+ data,
414
+ });
415
+ return promise;
416
+ }
417
+ /**
418
+ * Requests permission from the user to be able to play audio
419
+ */
420
+ requestAudioPermission() {
421
+ return this.sendAudioRequest(ApplicationEvents_1.ToShopfront.AUDIO_REQUEST_PERMISSION);
422
+ }
423
+ /**
424
+ * Requests shopfront to preload audio so that it can be pre-cached before being played
425
+ * @param url
426
+ */
427
+ audioPreload(url) {
428
+ return this.sendAudioRequest(ApplicationEvents_1.ToShopfront.AUDIO_PRELOAD, {
429
+ url
430
+ });
431
+ }
432
+ /**
433
+ * Requests the sound to be played
434
+ * @param url
435
+ */
436
+ audioPlay(url) {
437
+ return this.sendAudioRequest(ApplicationEvents_1.ToShopfront.AUDIO_PLAY, {
438
+ url
439
+ });
440
+ }
441
+ dataIsOption(data) {
442
+ return typeof data.requestId === "string" && typeof data.option === "string";
443
+ }
339
444
  async getOption(option, defaultValue) {
340
445
  const request = `OptionRequest-${Date.now().toString()}`;
341
446
  const promise = new Promise(res => {
@@ -343,7 +448,9 @@ class Application {
343
448
  if (event !== "RESPONSE_OPTION") {
344
449
  return;
345
450
  }
346
- data = data;
451
+ if (!this.dataIsOption(data)) {
452
+ return;
453
+ }
347
454
  if (data.requestId !== request) {
348
455
  return;
349
456
  }