create-brainerce-store 1.12.2 → 1.12.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-brainerce-store",
3
- "version": "1.12.2",
3
+ "version": "1.12.3",
4
4
  "description": "Scaffold a production-ready e-commerce storefront connected to Brainerce",
5
5
  "bin": {
6
6
  "create-brainerce-store": "dist/index.js"
@@ -82,6 +82,7 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
82
82
  onError: (_r: unknown) => {},
83
83
  onTimeout: () => {},
84
84
  onWalletChange: (_s: string) => {},
85
+ retryRender: () => {},
85
86
  });
86
87
 
87
88
  const handleSuccess = useCallback(
@@ -115,8 +116,9 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
115
116
  ];
116
117
  const msg = extractMessage(response);
117
118
  if (TRANSIENT.some((e) => msg.includes(e))) {
118
- console.info('Payment SDK: transient startup error (will retry):', msg);
119
- return; // Don't show error — renderWhenReady will retry
119
+ console.info('Payment SDK: transient error, retrying render in 1s:', msg);
120
+ setTimeout(() => cbRef.current.retryRender(), 1000);
121
+ return;
120
122
  }
121
123
  console.error('Payment SDK error:', response);
122
124
  setError(msg || t('paymentError'));
@@ -133,6 +135,7 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
133
135
  }
134
136
  if (state === 'close') setSdkReady(false);
135
137
  },
138
+ retryRender: () => {},
136
139
  };
137
140
 
138
141
  // =========================================================================
@@ -220,6 +223,8 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
220
223
 
221
224
  // --- Init: called in s.onload (as Grow docs require) ---
222
225
  function initSdk(sdk: PaymentClientSdk) {
226
+ if (sdkInitDone) return; // Guard against double init
227
+
223
228
  const global = (window as any)[sdk.globalName!];
224
229
  if (!global) {
225
230
  setError(t('failedToLoadPaymentSdk'));
@@ -245,37 +250,47 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
245
250
  sdkInitDone = true;
246
251
  }
247
252
 
248
- // --- Render: retry until wallet actually opens (onWalletChange) ---
249
- // No artificial timeout the SDK fires onTimeout when the session expires.
250
- function renderWhenReady(sdk: PaymentClientSdk, intent: PaymentIntent) {
253
+ // --- Render: call once, then safety-net retries if wallet doesn't open ---
254
+ // Grow SDK sometimes silently swallows renderPaymentOptions when its
255
+ // internal resources (mp.min.js etc.) aren't fully loaded yet.
256
+ // Strategy: render once, then retry up to 3 times with increasing delays
257
+ // (2s, 3s, 4s) if onWalletChange("open") hasn't fired.
258
+ let pendingRender: { sdk: PaymentClientSdk; intent: PaymentIntent } | null = null;
259
+ let renderAttempts = 0;
260
+ const MAX_RENDER_ATTEMPTS = 4;
261
+
262
+ function renderPayment(sdk: PaymentClientSdk, intent: PaymentIntent) {
251
263
  const global = (window as any)[sdk.globalName!];
252
- if (!global) return;
264
+ if (!global || walletOpenRef.current) return;
253
265
 
254
266
  const renderMethod = sdk.renderMethod || 'renderPaymentOptions';
255
267
  const renderArg = sdk.renderArg || intent.clientSecret;
256
- let renderCalled = false;
257
-
258
- function attempt() {
259
- if (walletOpenRef.current) return;
260
- try {
261
- global[renderMethod](renderArg);
262
- renderCalled = true;
263
- console.info('Payment SDK: render call accepted');
264
- } catch (err) {
265
- console.info('Payment SDK: render not ready yet, retrying...');
266
- }
268
+ renderAttempts++;
269
+
270
+ try {
271
+ global[renderMethod](renderArg);
272
+ console.info(`Payment SDK: renderPaymentOptions called (attempt ${renderAttempts})`);
273
+ } catch (err) {
274
+ console.info('Payment SDK: render threw, will retry in 1s');
267
275
  }
268
276
 
269
- // Try immediately, then keep retrying until onWalletChange('open') fires
270
- attempt();
271
- const id = setInterval(() => {
272
- if (walletOpenRef.current) {
273
- clearInterval(id);
274
- return;
275
- }
276
- if (!renderCalled) attempt();
277
- }, 500);
278
- cleanups.push(() => clearInterval(id));
277
+ // Safety net: if wallet doesn't open within a delay, retry
278
+ if (renderAttempts < MAX_RENDER_ATTEMPTS) {
279
+ const delay = 1000 + renderAttempts * 1000; // 2s, 3s, 4s
280
+ const retryId = setTimeout(() => {
281
+ if (!walletOpenRef.current) {
282
+ console.info(`Payment SDK: wallet not open after ${delay}ms, retrying render...`);
283
+ renderPayment(sdk, intent);
284
+ }
285
+ }, delay);
286
+ cleanups.push(() => clearTimeout(retryId));
287
+ }
288
+ }
289
+
290
+ function retryRender() {
291
+ if (pendingRender && !walletOpenRef.current) {
292
+ renderPayment(pendingRender.sdk, pendingRender.intent);
293
+ }
279
294
  }
280
295
 
281
296
  // =============================================
@@ -326,14 +341,18 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
326
341
  }
327
342
  if (sdk.renderType !== 'sdk-widget' || !sdk.globalName) return;
328
343
 
344
+ // Store for retryRender from onError callback
345
+ pendingRender = { sdk, intent };
346
+ cbRef.current.retryRender = retryRender;
347
+
329
348
  // If SDK wasn't loaded from providers, load + init now
330
349
  if (!sdkInitDone) {
331
350
  loadScript(sdk);
332
- // Wait for init to complete, then render
351
+ // Wait for init to complete, then render once
333
352
  const id = setInterval(() => {
334
353
  if (sdkInitDone) {
335
354
  clearInterval(id);
336
- renderWhenReady(sdk, intent);
355
+ renderPayment(sdk, intent);
337
356
  }
338
357
  }, 100);
339
358
  cleanups.push(() => clearInterval(id));
@@ -358,8 +377,8 @@ export function PaymentStep({ checkoutId, className }: PaymentStepProps) {
358
377
  }
359
378
  }
360
379
 
361
- // SDK ready — render
362
- renderWhenReady(sdk, intent);
380
+ // SDK ready — render once
381
+ renderPayment(sdk, intent);
363
382
  });
364
383
 
365
384
  return () => cleanups.forEach((fn) => fn());