@nosslabs/iap 5.0.0 → 7.0.0
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/CHANGELOG.md +108 -13
- package/README.md +7 -7
- package/dist/index.cjs +129 -253
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -15
- package/dist/index.d.ts +7 -15
- package/dist/index.js +129 -253
- package/dist/index.js.map +1 -1
- package/package.json +12 -11
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var core = require('@capacitor/core');
|
|
4
|
-
require('
|
|
4
|
+
var nativePurchases = require('@capgo/native-purchases');
|
|
5
5
|
var zod = require('zod');
|
|
6
6
|
var preferences = require('@capacitor/preferences');
|
|
7
7
|
|
|
@@ -85,7 +85,7 @@ var init_errors = __esm({
|
|
|
85
85
|
NOT_INITIALIZED: "Call iap.initialize() before this method, or recreate the instance after destroy().",
|
|
86
86
|
// Native plugin
|
|
87
87
|
PLATFORM_NOT_SUPPORTED: "In-app purchases run on iOS/Android only. Web is no-op by design \u2014 guard your purchase UI behind Capacitor.isNativePlatform().",
|
|
88
|
-
BILLING_NOT_AVAILABLE: "
|
|
88
|
+
BILLING_NOT_AVAILABLE: "The store billing service is unavailable. Confirm @capgo/native-purchases is installed and `npx cap sync` has run; check the device sandbox/test account is signed in.",
|
|
89
89
|
PRODUCT_NOT_FOUND: "Ensure the productId is registered in App Store Connect / Play Console AND in your createIAP({ products }) config.",
|
|
90
90
|
USER_CANCELLED: "No action needed \u2014 the user dismissed the native purchase sheet.",
|
|
91
91
|
PURCHASE_PENDING: "Android only: payment is awaiting external clearance (e.g. cash payment, bank verification). The backend will receive a Google RTDN webhook when it clears; call iap.refresh() afterward.",
|
|
@@ -139,295 +139,170 @@ var init_platform = __esm({
|
|
|
139
139
|
}
|
|
140
140
|
});
|
|
141
141
|
|
|
142
|
-
// src/adapters/native/
|
|
142
|
+
// src/adapters/native/capgo/native-adapter.ts
|
|
143
143
|
var native_adapter_exports = {};
|
|
144
144
|
__export(native_adapter_exports, {
|
|
145
|
-
|
|
145
|
+
CapgoNativeAdapter: () => CapgoNativeAdapter
|
|
146
146
|
});
|
|
147
|
-
function getCdv() {
|
|
148
|
-
const candidate = globalThis.CdvPurchase;
|
|
149
|
-
if (!candidate || !candidate.store) {
|
|
150
|
-
throw new exports.IAPError({
|
|
151
|
-
code: exports.IAPErrorCode.BILLING_NOT_AVAILABLE,
|
|
152
|
-
message: "cordova-plugin-purchase is not available. Ensure the plugin is installed and `npx cap sync` has run."
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
return candidate;
|
|
156
|
-
}
|
|
157
|
-
function currentCdvPlatform() {
|
|
158
|
-
const cdv = getCdv();
|
|
159
|
-
const platform = getPlatform();
|
|
160
|
-
if (platform === "android") return cdv.Platform.GOOGLE_PLAY;
|
|
161
|
-
return cdv.Platform.APPLE_APPSTORE;
|
|
162
|
-
}
|
|
163
|
-
function mapProductType(type) {
|
|
164
|
-
const cdv = getCdv();
|
|
165
|
-
switch (type) {
|
|
166
|
-
case "subscription":
|
|
167
|
-
return cdv.ProductType.PAID_SUBSCRIPTION;
|
|
168
|
-
case "consumable":
|
|
169
|
-
return cdv.ProductType.CONSUMABLE;
|
|
170
|
-
default:
|
|
171
|
-
return cdv.ProductType.NON_CONSUMABLE;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
function inferProductType(tx, configured) {
|
|
175
|
-
const id = tx.products[0]?.id;
|
|
176
|
-
if (!id) return "product";
|
|
177
|
-
const match = configured.find((p) => p.id === id);
|
|
178
|
-
return match?.type ?? "product";
|
|
179
|
-
}
|
|
180
147
|
function normalizeProduct(p, type) {
|
|
181
|
-
const
|
|
182
|
-
const phase = offer?.pricingPhases?.[0];
|
|
183
|
-
const priceMicros = phase?.priceMicros?.toString() ?? "0";
|
|
184
|
-
const priceString = phase?.price ?? "";
|
|
185
|
-
const currency = phase?.currency ?? "";
|
|
148
|
+
const priceMicros = Math.round(p.price * 1e6).toString();
|
|
186
149
|
return {
|
|
187
|
-
id: p.
|
|
150
|
+
id: p.identifier,
|
|
188
151
|
type,
|
|
189
|
-
title: p.title
|
|
190
|
-
description: p.description
|
|
191
|
-
priceString,
|
|
152
|
+
title: p.title,
|
|
153
|
+
description: p.description,
|
|
154
|
+
priceString: p.priceString,
|
|
192
155
|
priceMicros,
|
|
193
|
-
currency
|
|
156
|
+
currency: p.currencyCode
|
|
194
157
|
};
|
|
195
158
|
}
|
|
196
|
-
function normalizeTransaction(tx, productType
|
|
197
|
-
const platform = tx
|
|
198
|
-
const
|
|
199
|
-
const
|
|
159
|
+
function normalizeTransaction(tx, productType) {
|
|
160
|
+
const platform = inferPlatform(tx);
|
|
161
|
+
const token = platform === "google" ? tx.purchaseToken ?? tx.transactionId : tx.transactionId;
|
|
162
|
+
const native = {
|
|
200
163
|
platform,
|
|
201
|
-
productId,
|
|
164
|
+
productId: tx.productIdentifier,
|
|
202
165
|
token,
|
|
203
166
|
productType,
|
|
204
167
|
raw: tx
|
|
205
168
|
};
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
169
|
+
return native;
|
|
170
|
+
}
|
|
171
|
+
function inferPlatform(tx) {
|
|
172
|
+
if (tx.purchaseToken !== void 0 || tx.purchaseState !== void 0 || tx.orderId !== void 0) {
|
|
173
|
+
return "google";
|
|
209
174
|
}
|
|
210
|
-
|
|
175
|
+
if (tx.receipt !== void 0 || tx.jwsRepresentation !== void 0) {
|
|
176
|
+
return "apple";
|
|
177
|
+
}
|
|
178
|
+
return getPlatform() === "android" ? "google" : "apple";
|
|
211
179
|
}
|
|
212
|
-
function
|
|
213
|
-
|
|
214
|
-
return
|
|
180
|
+
function inferProductType(tx) {
|
|
181
|
+
if (tx.productType === "subs") return "subscription";
|
|
182
|
+
return "product";
|
|
215
183
|
}
|
|
216
|
-
function
|
|
217
|
-
|
|
218
|
-
return tx.transactionId || null;
|
|
219
|
-
}
|
|
220
|
-
const googleTx = tx;
|
|
221
|
-
return googleTx.nativePurchase?.purchaseToken ?? googleTx.parentReceipt?.purchaseToken ?? tx.transactionId ?? null;
|
|
184
|
+
function mapToPluginPurchaseType(type) {
|
|
185
|
+
return type === "subscription" ? nativePurchases.PURCHASE_TYPE.SUBS : nativePurchases.PURCHASE_TYPE.INAPP;
|
|
222
186
|
}
|
|
223
|
-
function
|
|
224
|
-
|
|
225
|
-
const
|
|
226
|
-
|
|
187
|
+
function mapPurchaseError(error, productId) {
|
|
188
|
+
if (error instanceof exports.IAPError) return error;
|
|
189
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
190
|
+
const lower = message.toLowerCase();
|
|
191
|
+
if (lower.includes("cancel")) {
|
|
227
192
|
return new exports.IAPError({
|
|
228
193
|
code: exports.IAPErrorCode.USER_CANCELLED,
|
|
229
|
-
message:
|
|
230
|
-
cause:
|
|
194
|
+
message: `Purchase of "${productId}" was cancelled.`,
|
|
195
|
+
cause: error
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
if (lower.includes("pending")) {
|
|
199
|
+
return new exports.IAPError({
|
|
200
|
+
code: exports.IAPErrorCode.PURCHASE_PENDING,
|
|
201
|
+
message: `Purchase of "${productId}" is pending external clearance.`,
|
|
202
|
+
cause: error
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
if (lower.includes("product not found") || lower.includes("cannot find product")) {
|
|
206
|
+
return new exports.IAPError({
|
|
207
|
+
code: exports.IAPErrorCode.PRODUCT_NOT_FOUND,
|
|
208
|
+
message: `Product "${productId}" was not found in the store catalog.`,
|
|
209
|
+
cause: error
|
|
231
210
|
});
|
|
232
211
|
}
|
|
233
212
|
return new exports.IAPError({
|
|
234
213
|
code: exports.IAPErrorCode.STORE_ERROR,
|
|
235
|
-
message:
|
|
236
|
-
cause:
|
|
214
|
+
message: `Native purchase of "${productId}" failed.`,
|
|
215
|
+
cause: error
|
|
237
216
|
});
|
|
238
217
|
}
|
|
239
|
-
var
|
|
218
|
+
var CapgoNativeAdapter;
|
|
240
219
|
var init_native_adapter = __esm({
|
|
241
|
-
"src/adapters/native/
|
|
220
|
+
"src/adapters/native/capgo/native-adapter.ts"() {
|
|
242
221
|
init_errors();
|
|
243
222
|
init_platform();
|
|
244
|
-
|
|
245
|
-
products;
|
|
246
|
-
bootstrapped = false;
|
|
247
|
-
bootstrapping = null;
|
|
248
|
-
pendingFinish = /* @__PURE__ */ new Map();
|
|
249
|
-
/** Long-lived bootstrap-time .approved() listener — kept for dispose(). */
|
|
250
|
-
bootstrapApprovedHandler = null;
|
|
251
|
-
constructor(opts) {
|
|
252
|
-
this.products = opts.products;
|
|
253
|
-
}
|
|
223
|
+
CapgoNativeAdapter = class {
|
|
254
224
|
async isAvailable() {
|
|
255
225
|
try {
|
|
256
|
-
await
|
|
257
|
-
return
|
|
226
|
+
const result = await nativePurchases.NativePurchases.isBillingSupported();
|
|
227
|
+
return result.isBillingSupported;
|
|
258
228
|
} catch {
|
|
259
229
|
return false;
|
|
260
230
|
}
|
|
261
231
|
}
|
|
262
232
|
async getProducts(requests) {
|
|
263
233
|
if (requests.length === 0) return [];
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
const
|
|
234
|
+
const inappIds = [];
|
|
235
|
+
const subsIds = [];
|
|
236
|
+
const requestById = /* @__PURE__ */ new Map();
|
|
267
237
|
for (const req of requests) {
|
|
268
|
-
|
|
269
|
-
if (
|
|
270
|
-
|
|
238
|
+
requestById.set(req.id, req.type);
|
|
239
|
+
if (req.type === "subscription") {
|
|
240
|
+
subsIds.push(req.id);
|
|
241
|
+
} else {
|
|
242
|
+
inappIds.push(req.id);
|
|
243
|
+
}
|
|
271
244
|
}
|
|
272
|
-
|
|
245
|
+
const [inapp, subs] = await Promise.all([
|
|
246
|
+
inappIds.length > 0 ? nativePurchases.NativePurchases.getProducts({
|
|
247
|
+
productIdentifiers: inappIds,
|
|
248
|
+
productType: nativePurchases.PURCHASE_TYPE.INAPP
|
|
249
|
+
}) : Promise.resolve({ products: [] }),
|
|
250
|
+
subsIds.length > 0 ? nativePurchases.NativePurchases.getProducts({
|
|
251
|
+
productIdentifiers: subsIds,
|
|
252
|
+
productType: nativePurchases.PURCHASE_TYPE.SUBS
|
|
253
|
+
}) : Promise.resolve({ products: [] })
|
|
254
|
+
]);
|
|
255
|
+
const all = [...inapp.products, ...subs.products];
|
|
256
|
+
return all.map((p) => normalizeProduct(p, requestById.get(p.identifier) ?? "product"));
|
|
273
257
|
}
|
|
274
258
|
async purchaseProduct(opts) {
|
|
275
|
-
const
|
|
276
|
-
const
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
code: exports.IAPErrorCode.PRODUCT_NOT_FOUND,
|
|
287
|
-
message: `Product "${opts.productId}" has no purchasable offer${opts.androidPlanId ? ` (planId="${opts.androidPlanId}")` : ""}.`
|
|
259
|
+
const purchaseType = mapToPluginPurchaseType(opts.productType);
|
|
260
|
+
const isConsumable = opts.productType === "consumable";
|
|
261
|
+
let tx;
|
|
262
|
+
try {
|
|
263
|
+
tx = await nativePurchases.NativePurchases.purchaseProduct({
|
|
264
|
+
productIdentifier: opts.productId,
|
|
265
|
+
productType: purchaseType,
|
|
266
|
+
planIdentifier: opts.androidPlanId,
|
|
267
|
+
appAccountToken: opts.appAccountToken,
|
|
268
|
+
isConsumable,
|
|
269
|
+
autoAcknowledgePurchases: false
|
|
288
270
|
});
|
|
271
|
+
} catch (error) {
|
|
272
|
+
throw mapPurchaseError(error, opts.productId);
|
|
289
273
|
}
|
|
290
|
-
return
|
|
291
|
-
let settled = false;
|
|
292
|
-
const cleanup = () => {
|
|
293
|
-
store.off(handleApproved);
|
|
294
|
-
};
|
|
295
|
-
const handleApproved = (tx) => {
|
|
296
|
-
if (settled) return;
|
|
297
|
-
if (!tx.products.some((p) => p.id === opts.productId)) return;
|
|
298
|
-
const token = transactionToken(tx);
|
|
299
|
-
if (!token) {
|
|
300
|
-
settled = true;
|
|
301
|
-
cleanup();
|
|
302
|
-
reject(
|
|
303
|
-
new exports.IAPError({
|
|
304
|
-
code: exports.IAPErrorCode.STORE_ERROR,
|
|
305
|
-
message: `Approved transaction for "${opts.productId}" has no token; cannot verify.`
|
|
306
|
-
})
|
|
307
|
-
);
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
settled = true;
|
|
311
|
-
cleanup();
|
|
312
|
-
const normalized = normalizeTransaction(tx, opts.productType, token);
|
|
313
|
-
this.pendingFinish.set(token, tx);
|
|
314
|
-
resolve(normalized);
|
|
315
|
-
};
|
|
316
|
-
store.when().approved(handleApproved);
|
|
317
|
-
const additionalData = opts.appAccountToken ? { applicationUsername: opts.appAccountToken } : void 0;
|
|
318
|
-
void Promise.resolve(offer.order(additionalData)).then((err) => {
|
|
319
|
-
if (settled) return;
|
|
320
|
-
if (!err) return;
|
|
321
|
-
settled = true;
|
|
322
|
-
cleanup();
|
|
323
|
-
reject(mapOrderError(err, opts.productId));
|
|
324
|
-
}).catch((cause) => {
|
|
325
|
-
if (settled) return;
|
|
326
|
-
settled = true;
|
|
327
|
-
cleanup();
|
|
328
|
-
reject(
|
|
329
|
-
new exports.IAPError({
|
|
330
|
-
code: exports.IAPErrorCode.STORE_ERROR,
|
|
331
|
-
message: `order() rejected for ${opts.productId}.`,
|
|
332
|
-
cause
|
|
333
|
-
})
|
|
334
|
-
);
|
|
335
|
-
});
|
|
336
|
-
});
|
|
274
|
+
return normalizeTransaction(tx, opts.productType);
|
|
337
275
|
}
|
|
338
276
|
async getOwnedTransactions() {
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
const out = [];
|
|
342
|
-
for (const tx of store.localTransactions) {
|
|
343
|
-
if (tx.state !== getCdv().TransactionState.APPROVED) continue;
|
|
344
|
-
const token = transactionToken(tx);
|
|
345
|
-
if (!token) continue;
|
|
346
|
-
const normalized = normalizeTransaction(tx, inferProductType(tx, this.products), token);
|
|
347
|
-
this.pendingFinish.set(token, tx);
|
|
348
|
-
out.push(normalized);
|
|
349
|
-
}
|
|
350
|
-
return out;
|
|
277
|
+
const result = await nativePurchases.NativePurchases.getPurchases();
|
|
278
|
+
return result.purchases.filter((tx) => tx.purchaseState === void 0 || tx.purchaseState === "1").map((tx) => normalizeTransaction(tx, inferProductType(tx)));
|
|
351
279
|
}
|
|
352
280
|
async acknowledge(transaction) {
|
|
353
|
-
const cdvTx = this.pendingFinish.get(transaction.token);
|
|
354
|
-
if (!cdvTx) {
|
|
355
|
-
return;
|
|
356
|
-
}
|
|
357
281
|
try {
|
|
358
|
-
await
|
|
359
|
-
|
|
282
|
+
await nativePurchases.NativePurchases.acknowledgePurchase({
|
|
283
|
+
purchaseToken: transaction.token
|
|
284
|
+
});
|
|
285
|
+
} catch (error) {
|
|
360
286
|
throw new exports.IAPError({
|
|
361
287
|
code: exports.IAPErrorCode.STORE_ERROR,
|
|
362
|
-
message: `Failed to
|
|
363
|
-
cause,
|
|
288
|
+
message: `Failed to acknowledge transaction for ${transaction.productId}.`,
|
|
289
|
+
cause: error,
|
|
364
290
|
recoverable: true
|
|
365
291
|
});
|
|
366
292
|
}
|
|
367
|
-
this.pendingFinish.delete(transaction.token);
|
|
368
293
|
}
|
|
369
294
|
async manageSubscriptions() {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
295
|
+
try {
|
|
296
|
+
await nativePurchases.NativePurchases.manageSubscriptions();
|
|
297
|
+
} catch (error) {
|
|
373
298
|
throw new exports.IAPError({
|
|
374
299
|
code: exports.IAPErrorCode.STORE_ERROR,
|
|
375
|
-
message:
|
|
300
|
+
message: "Failed to open the native subscription management UI.",
|
|
301
|
+
cause: error
|
|
376
302
|
});
|
|
377
303
|
}
|
|
378
304
|
}
|
|
379
305
|
async dispose() {
|
|
380
|
-
if (this.bootstrapApprovedHandler) {
|
|
381
|
-
try {
|
|
382
|
-
const cdv = globalThis.CdvPurchase;
|
|
383
|
-
cdv?.store?.off(this.bootstrapApprovedHandler);
|
|
384
|
-
} catch {
|
|
385
|
-
}
|
|
386
|
-
this.bootstrapApprovedHandler = null;
|
|
387
|
-
}
|
|
388
|
-
this.pendingFinish.clear();
|
|
389
|
-
this.bootstrapped = false;
|
|
390
|
-
this.bootstrapping = null;
|
|
391
|
-
}
|
|
392
|
-
// ----- internals -----
|
|
393
|
-
async ensureStore() {
|
|
394
|
-
await this.bootstrap();
|
|
395
|
-
return getCdv().store;
|
|
396
|
-
}
|
|
397
|
-
bootstrap() {
|
|
398
|
-
if (this.bootstrapped) return Promise.resolve();
|
|
399
|
-
if (this.bootstrapping) return this.bootstrapping;
|
|
400
|
-
this.bootstrapping = (async () => {
|
|
401
|
-
const cdv = getCdv();
|
|
402
|
-
const platform = currentCdvPlatform();
|
|
403
|
-
cdv.store.register(
|
|
404
|
-
this.products.map((p) => ({
|
|
405
|
-
id: p.id,
|
|
406
|
-
type: mapProductType(p.type),
|
|
407
|
-
platform
|
|
408
|
-
}))
|
|
409
|
-
);
|
|
410
|
-
const errors = await cdv.store.initialize([platform]);
|
|
411
|
-
if (errors && errors.length > 0) {
|
|
412
|
-
const first = errors[0];
|
|
413
|
-
throw new exports.IAPError({
|
|
414
|
-
code: exports.IAPErrorCode.BILLING_NOT_AVAILABLE,
|
|
415
|
-
message: first?.message ?? "cordova-plugin-purchase initialize() reported errors."
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
const handler = (tx) => {
|
|
419
|
-
const token = transactionToken(tx);
|
|
420
|
-
if (!token) return;
|
|
421
|
-
if (!this.pendingFinish.has(token)) {
|
|
422
|
-
this.pendingFinish.set(token, tx);
|
|
423
|
-
}
|
|
424
|
-
};
|
|
425
|
-
this.bootstrapApprovedHandler = handler;
|
|
426
|
-
cdv.store.when().approved(handler);
|
|
427
|
-
await cdv.store.update();
|
|
428
|
-
this.bootstrapped = true;
|
|
429
|
-
})();
|
|
430
|
-
return this.bootstrapping;
|
|
431
306
|
}
|
|
432
307
|
};
|
|
433
308
|
}
|
|
@@ -960,11 +835,11 @@ var WebStubAdapter = class {
|
|
|
960
835
|
};
|
|
961
836
|
|
|
962
837
|
// src/adapters/native/index.ts
|
|
963
|
-
async function selectNativeAdapter(
|
|
838
|
+
async function selectNativeAdapter() {
|
|
964
839
|
const platform = getPlatform();
|
|
965
840
|
if (platform === "ios" || platform === "android") {
|
|
966
841
|
const mod = await Promise.resolve().then(() => (init_native_adapter(), native_adapter_exports));
|
|
967
|
-
return new mod.
|
|
842
|
+
return new mod.CapgoNativeAdapter();
|
|
968
843
|
}
|
|
969
844
|
return new WebStubAdapter();
|
|
970
845
|
}
|
|
@@ -1862,6 +1737,24 @@ function createIAP(input) {
|
|
|
1862
1737
|
cachedAt: null,
|
|
1863
1738
|
products: Object.freeze([...config.products ?? []])
|
|
1864
1739
|
};
|
|
1740
|
+
async function refreshEntitlements() {
|
|
1741
|
+
requireInitialized(state);
|
|
1742
|
+
const previous = state.entitlements;
|
|
1743
|
+
const fetched = await state.backend.getEntitlements();
|
|
1744
|
+
const next = freezeAll(fetched);
|
|
1745
|
+
try {
|
|
1746
|
+
state.cachedAt = await state.cache.save(next);
|
|
1747
|
+
} catch (error) {
|
|
1748
|
+
state.logger.warn(
|
|
1749
|
+
"Failed to persist refreshed entitlements; in-memory state still updated.",
|
|
1750
|
+
error
|
|
1751
|
+
);
|
|
1752
|
+
}
|
|
1753
|
+
state.entitlements = next;
|
|
1754
|
+
if (!entitlementsEqual(previous, next)) {
|
|
1755
|
+
state.emitter.emit("entitlements-changed", { entitlements: next, previous });
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1865
1758
|
return {
|
|
1866
1759
|
async initialize() {
|
|
1867
1760
|
if (state.destroyed) {
|
|
@@ -1902,7 +1795,7 @@ function createIAP(input) {
|
|
|
1902
1795
|
state.products = Object.freeze([...validated.data]);
|
|
1903
1796
|
state.logger.debug(`Resolved ${validated.data.length} product(s) from backend manifest.`);
|
|
1904
1797
|
}
|
|
1905
|
-
state.adapter = await selectNativeAdapter(
|
|
1798
|
+
state.adapter = await selectNativeAdapter();
|
|
1906
1799
|
const configGetAuthHeaders = state.config.backend.getAuthHeaders;
|
|
1907
1800
|
const getAuthHeaders = configGetAuthHeaders ? async () => configGetAuthHeaders() : async () => ({});
|
|
1908
1801
|
const sharedDeps = {
|
|
@@ -1963,7 +1856,7 @@ function createIAP(input) {
|
|
|
1963
1856
|
logger: state.logger,
|
|
1964
1857
|
onResume: async () => {
|
|
1965
1858
|
try {
|
|
1966
|
-
await
|
|
1859
|
+
await refreshEntitlements();
|
|
1967
1860
|
} catch (error) {
|
|
1968
1861
|
state.logger.warn("refreshOnResume: refresh() failed.", error);
|
|
1969
1862
|
}
|
|
@@ -1974,7 +1867,7 @@ function createIAP(input) {
|
|
|
1974
1867
|
state.logger.debug("Cache exceeds TTL; scheduling background refresh.");
|
|
1975
1868
|
queueMicrotask(() => {
|
|
1976
1869
|
if (!state.initialized || state.destroyed) return;
|
|
1977
|
-
|
|
1870
|
+
refreshEntitlements().catch((error) => {
|
|
1978
1871
|
state.logger.warn("TTL background refresh failed.", error);
|
|
1979
1872
|
});
|
|
1980
1873
|
});
|
|
@@ -1982,24 +1875,7 @@ function createIAP(input) {
|
|
|
1982
1875
|
state.initialized = true;
|
|
1983
1876
|
state.emitter.emit("ready", void 0);
|
|
1984
1877
|
},
|
|
1985
|
-
|
|
1986
|
-
requireInitialized(state);
|
|
1987
|
-
const previous = state.entitlements;
|
|
1988
|
-
const fetched = await state.backend.getEntitlements();
|
|
1989
|
-
const next = freezeAll(fetched);
|
|
1990
|
-
try {
|
|
1991
|
-
state.cachedAt = await state.cache.save(next);
|
|
1992
|
-
} catch (error) {
|
|
1993
|
-
state.logger.warn(
|
|
1994
|
-
"Failed to persist refreshed entitlements; in-memory state still updated.",
|
|
1995
|
-
error
|
|
1996
|
-
);
|
|
1997
|
-
}
|
|
1998
|
-
state.entitlements = next;
|
|
1999
|
-
if (!entitlementsEqual(previous, next)) {
|
|
2000
|
-
state.emitter.emit("entitlements-changed", { entitlements: next, previous });
|
|
2001
|
-
}
|
|
2002
|
-
},
|
|
1878
|
+
refresh: refreshEntitlements,
|
|
2003
1879
|
async destroy() {
|
|
2004
1880
|
if (state.destroyed) return;
|
|
2005
1881
|
state.destroyed = true;
|