@namiml/expo-sdk 3.4.5-dev.202607100416 → 3.4.5-dev.202607101515
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/dist/index.cjs +82 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.mjs +83 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/adapters/index.ts +2 -1
- package/src/components/NamiView.tsx +6 -0
- package/src/components/elements/NamiSegmentPicker.tsx +10 -1
- package/src/nami.ts +20 -2
- package/src/products/productStore.ts +63 -0
package/dist/index.cjs
CHANGED
|
@@ -292,6 +292,7 @@ class ExpoPurchaseAdapter {
|
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
const expoUIAdapter = new ExpoUIAdapter();
|
|
295
|
+
const expoPurchaseAdapter = new ExpoPurchaseAdapter();
|
|
295
296
|
let adaptersRegistered = false;
|
|
296
297
|
function registerExpoAdapters() {
|
|
297
298
|
if (adaptersRegistered) {
|
|
@@ -303,7 +304,7 @@ function registerExpoAdapters() {
|
|
|
303
304
|
device: new ExpoDeviceAdapter(),
|
|
304
305
|
ui: expoUIAdapter,
|
|
305
306
|
});
|
|
306
|
-
sdkCore.registerPurchaseAdapter(
|
|
307
|
+
sdkCore.registerPurchaseAdapter(expoPurchaseAdapter);
|
|
307
308
|
adaptersRegistered = true;
|
|
308
309
|
}
|
|
309
310
|
catch (error) {
|
|
@@ -312,6 +313,79 @@ function registerExpoAdapters() {
|
|
|
312
313
|
}
|
|
313
314
|
registerExpoAdapters();
|
|
314
315
|
|
|
316
|
+
// Accumulated store product details, keyed by product_ref_id (== sku_ref_id).
|
|
317
|
+
const productsById = new Map();
|
|
318
|
+
// Serializes backfill runs so concurrent launches/prefetches don't double-fetch
|
|
319
|
+
// or race the map (parity with the Apple SDK's backfillTaskLock).
|
|
320
|
+
let pending = Promise.resolve(false);
|
|
321
|
+
/** Collect unique store product ids (sku_ref_id) from the given paywalls' sku menus. */
|
|
322
|
+
function collectSkuRefIds(paywalls) {
|
|
323
|
+
const ids = new Set();
|
|
324
|
+
for (const paywall of paywalls ?? []) {
|
|
325
|
+
for (const menu of paywall?.sku_menus ?? []) {
|
|
326
|
+
for (const sku of menu?.products ?? []) {
|
|
327
|
+
if (sku?.sku_ref_id)
|
|
328
|
+
ids.add(sku.sku_ref_id);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return [...ids];
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Fetch store product details for any of `skuRefIds` not already loaded, merge them into
|
|
336
|
+
* the accumulated set, and push the union to core via NamiPaywallManager.setProductDetails.
|
|
337
|
+
* Serialized; returns whether new products were added. Never throws.
|
|
338
|
+
*/
|
|
339
|
+
function backfill(skuRefIds) {
|
|
340
|
+
pending = pending.then(() => backfillOnce(skuRefIds));
|
|
341
|
+
return pending;
|
|
342
|
+
}
|
|
343
|
+
async function backfillOnce(skuRefIds) {
|
|
344
|
+
const missing = [...new Set(skuRefIds)].filter((id) => id && !productsById.has(id));
|
|
345
|
+
if (!missing.length)
|
|
346
|
+
return false;
|
|
347
|
+
try {
|
|
348
|
+
const products = await expoPurchaseAdapter.getProducts(missing);
|
|
349
|
+
let added = false;
|
|
350
|
+
for (const product of products ?? []) {
|
|
351
|
+
if (product?.product_ref_id) {
|
|
352
|
+
productsById.set(product.product_ref_id, product);
|
|
353
|
+
added = true;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (added) {
|
|
357
|
+
sdkCore.NamiPaywallManager.setProductDetails([...productsById.values()]);
|
|
358
|
+
}
|
|
359
|
+
return added;
|
|
360
|
+
}
|
|
361
|
+
catch (error) {
|
|
362
|
+
sdkCore.logger.warn('[NamiExpo] Failed to load store products.', error);
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
/** Clear accumulated products. Called on Nami.reset so reconfigure doesn't serve stale data. */
|
|
367
|
+
function reset() {
|
|
368
|
+
pending = pending.then(() => {
|
|
369
|
+
productsById.clear();
|
|
370
|
+
return false;
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Prefetch StoreKit/Play product details for every configured paywall's SKUs so that
|
|
376
|
+
* prices are available before any paywall mounts (mirrors the Apple SDK startup load).
|
|
377
|
+
* Fire-and-forget and error-safe: a failure here never blocks configure.
|
|
378
|
+
*/
|
|
379
|
+
async function prefetchProducts() {
|
|
380
|
+
try {
|
|
381
|
+
const ids = collectSkuRefIds(sdkCore.NamiPaywallManager.allPaywalls());
|
|
382
|
+
if (ids.length)
|
|
383
|
+
await backfill(ids);
|
|
384
|
+
}
|
|
385
|
+
catch (error) {
|
|
386
|
+
sdkCore.logger.warn('[NamiExpo] Product prefetch skipped.', error);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
315
389
|
class Nami {
|
|
316
390
|
static get sdkVersion() {
|
|
317
391
|
return sdkCore.Nami.sdkVersion();
|
|
@@ -320,9 +394,12 @@ class Nami {
|
|
|
320
394
|
return sdkCore.Nami.sdkPackageVersion();
|
|
321
395
|
}
|
|
322
396
|
static async configure(config) {
|
|
323
|
-
|
|
397
|
+
const result = await sdkCore.Nami.configure(config);
|
|
398
|
+
void prefetchProducts();
|
|
399
|
+
return result;
|
|
324
400
|
}
|
|
325
401
|
static async reset() {
|
|
402
|
+
reset();
|
|
326
403
|
await sdkCore.Nami.reset?.();
|
|
327
404
|
}
|
|
328
405
|
}
|
|
@@ -3706,6 +3783,9 @@ const NamiView = ({ placement, url, onClose, onSignIn, onDeepLink, onPurchase, o
|
|
|
3706
3783
|
launchCacheRef.current.set(cacheKey, nextLaunch);
|
|
3707
3784
|
}
|
|
3708
3785
|
prewarmPaywallFonts([paywall, ...flowPaywalls]);
|
|
3786
|
+
const launchSkuRefIds = collectSkuRefIds([paywall, ...flowPaywalls].filter((item) => item != null));
|
|
3787
|
+
if (launchSkuRefIds.length)
|
|
3788
|
+
void backfill(launchSkuRefIds);
|
|
3709
3789
|
if (initialPaywall?.fonts) {
|
|
3710
3790
|
void prepareAndLoadFontsWithTimeout(initialPaywall.fonts);
|
|
3711
3791
|
}
|