@morefin/cashier-bootstrapper 0.3.6 → 0.3.7

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
@@ -100,6 +100,33 @@ new CashierBootstrapper('#cashier-root', {
100
100
  });
101
101
  ```
102
102
 
103
+ The bootstrapper calls `onReady` after the cashier iframe has registered its runtime message listener. If the cashier build does not support that ready signal, the bootstrapper falls back to iframe load after 3 seconds to preserve existing integrations.
104
+
105
+ For asynchronous merchant configuration, return or await the async work from `onReady`. The cashier stays in its host-configuration loading state until the returned promise completes.
106
+
107
+ ```typescript
108
+ import { CashierBootstrapper } from '@morefin/cashier-bootstrapper';
109
+
110
+ new CashierBootstrapper('#cashier-root', {
111
+ properties: { environment: CASHIER_ENVIRONMENT }
112
+ }, async api => {
113
+ const css = await fetch('/merchant-cashier-theme.css').then(response => response.text());
114
+ api.setCss(css);
115
+ });
116
+ ```
117
+
118
+ Avoid starting async setup without returning it. In this example, the bootstrapper cannot wait for the timer, so the cashier may become visible before the CSS is applied:
119
+
120
+ ```typescript
121
+ new CashierBootstrapper('#cashier-root', {
122
+ properties: { environment: CASHIER_ENVIRONMENT }
123
+ }, api => {
124
+ setTimeout(() => {
125
+ api.setCss(css);
126
+ }, 1000);
127
+ });
128
+ ```
129
+
103
130
  ### Transaction Result Callbacks
104
131
 
105
132
  ```typescript
@@ -140,11 +167,13 @@ Iframe-based embed that loads the cashier URL and exposes runtime controls once
140
167
  - `container: string | HTMLElement | null | undefined` - Where the iframe is appended. If omitted, `config.properties.container` is used (falling back to `document.body`).
141
168
  - `config?: CashierIframeConfig` - Request params and iframe properties. `properties.environment` is required.
142
169
  - `config.callbacks?: CashierCallbacks` - Host callback handlers for cashier result events.
143
- - `onReady?: (api: CashierIframeApi) => void` - Called when the iframe loads; exposes helpers:
170
+ - `onReady?: (api: CashierIframeApi) => void | Promise<void>` - Called when the cashier iframe is ready for runtime messages; exposes helpers:
144
171
  - `api.setCss(css: string)` – inject CSS inside the cashier iframe
145
172
  - `api.updateData(data: object)` – post updated `APP_DATA` to the cashier
146
173
  - `api.pause()` / `api.resume()` – forward pause/resume signals
147
174
 
175
+ If `onReady` returns a promise, the bootstrapper waits for it before notifying the cashier that host configuration is completed. Return or await asynchronous CSS/data setup so the cashier does not render before merchant configuration is applied.
176
+
148
177
  ## Types
149
178
 
150
179
  ```typescript
package/dist/index.d.ts CHANGED
@@ -21,6 +21,7 @@ export declare class CashierBootstrapper {
21
21
  private managedRedirectTab?;
22
22
  private managedRedirectTabTransactionId?;
23
23
  private managedRedirectTabCheckIntervalId?;
24
+ private iframeLoadFallbackTimeoutId?;
24
25
  private origin;
25
26
  private ready;
26
27
  private readonly fullConfig;
@@ -29,10 +30,12 @@ export declare class CashierBootstrapper {
29
30
  private readonly onReady?;
30
31
  private readonly callbacks?;
31
32
  private readonly messageListener;
32
- constructor(container: string | HTMLElement | null | undefined, config?: CashierIframeConfig, onReady?: (api: CashierIframeApi) => void);
33
+ constructor(container: string | HTMLElement | null | undefined, config?: CashierIframeConfig, onReady?: (api: CashierIframeApi) => void | Promise<void>);
33
34
  private bootstrapIframe;
34
35
  private createIframeShell;
35
36
  private handleLoad;
37
+ private completeReady;
38
+ private runHostReadyCallback;
36
39
  private postMessage;
37
40
  private handleIframeMessage;
38
41
  private handleCashierResultEvent;
package/dist/index.js CHANGED
@@ -3,6 +3,8 @@ const CASHIER_PATH = '/cashier';
3
3
  const FINGERPRINT_CDN = 'https://cdn.jsdelivr.net/npm/@fingerprintjs/fingerprintjs@4/dist/fp.min.js';
4
4
  const CASHIER_REDIRECT_EVENT = 'CASHIER_REDIRECT';
5
5
  const CASHIER_REDIRECT_TAB_CLOSED_EVENT = 'CASHIER_REDIRECT_TAB_CLOSED';
6
+ const CASHIER_READY_EVENT = 'CASHIER_READY';
7
+ const CASHIER_HOST_CONFIG_DONE_EVENT = 'CASHIER_HOST_CONFIG_DONE';
6
8
  const TOP_URL_REPLACE_EVENT = 'TOP_URL_REPLACE';
7
9
  const CASHIER_IFRAME_OVERLAY_CLOSE_EVENT = 'CASHIER_IFRAME_OVERLAY_CLOSE';
8
10
  const CASHIER_RESULT_EVENT = 'CASHIER_RESULT';
@@ -213,8 +215,8 @@ export class CashierBootstrapper {
213
215
  const src = buildIframeUrl(this.host, this.fullConfig.requestParams, this.allowedHostnames, fp);
214
216
  this.origin = getOriginFromUrl(src, this.allowedHostnames);
215
217
  if (this.iframe) {
216
- this.iframe.src = src;
217
218
  this.iframe.onload = () => this.handleLoad();
219
+ this.iframe.src = src;
218
220
  }
219
221
  }
220
222
  createIframeShell(container) {
@@ -241,11 +243,33 @@ export class CashierBootstrapper {
241
243
  return iframe;
242
244
  }
243
245
  handleLoad() {
246
+ if (this.ready)
247
+ return;
248
+ if (this.iframeLoadFallbackTimeoutId !== undefined)
249
+ return;
250
+ this.iframeLoadFallbackTimeoutId = setTimeout(() => this.completeReady(), 3000);
251
+ }
252
+ completeReady() {
244
253
  if (this.ready)
245
254
  return;
246
255
  this.ready = true;
247
- if (this.onReady) {
248
- this.onReady(this.api());
256
+ if (this.iframeLoadFallbackTimeoutId !== undefined) {
257
+ clearTimeout(this.iframeLoadFallbackTimeoutId);
258
+ this.iframeLoadFallbackTimeoutId = undefined;
259
+ }
260
+ void this.runHostReadyCallback();
261
+ }
262
+ async runHostReadyCallback() {
263
+ try {
264
+ if (this.onReady) {
265
+ await this.onReady(this.api());
266
+ }
267
+ }
268
+ catch (err) {
269
+ console.error('Host ready callback threw an error.', err);
270
+ }
271
+ finally {
272
+ this.postMessage(CASHIER_HOST_CONFIG_DONE_EVENT, {});
249
273
  }
250
274
  }
251
275
  postMessage(eventType, payload) {
@@ -267,6 +291,12 @@ export class CashierBootstrapper {
267
291
  return;
268
292
  }
269
293
  const { eventType, payload } = event.data;
294
+ if (eventType === CASHIER_READY_EVENT) {
295
+ if (sourceIsMainCashierIframe) {
296
+ this.completeReady();
297
+ }
298
+ return;
299
+ }
270
300
  if (eventType === CASHIER_IFRAME_OVERLAY_CLOSE_EVENT) {
271
301
  if (sourceIsOverlayIframe) {
272
302
  this.closeProviderRedirectOverlay();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morefin/cashier-bootstrapper",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "description": "Bootstrap service for initializing cashier payment page data from API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",