@nosslabs/iap 7.0.0 → 7.1.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/dist/index.d.cts CHANGED
@@ -950,6 +950,39 @@ interface RestoreResult<TEntitlement extends EntitlementBase = EntitlementBase>
950
950
  entitlements: TEntitlement[];
951
951
  }
952
952
 
953
+ /**
954
+ * The user's App Store / Google Play storefront — i.e. the country their
955
+ * store account is registered to, which is the platform-blessed signal for
956
+ * region-dependent decisions (regional pricing/offers, and gating
957
+ * external-payment links whose eligibility the OS itself keys to storefront
958
+ * country, *not* device locale).
959
+ *
960
+ * `countryCode` is normalized to **ISO 3166-1 alpha-2** across platforms so
961
+ * consumers compare one consistent value (Apple's native code is alpha-3,
962
+ * Google's is alpha-2). The raw native code is preserved in `countryCodeRaw`.
963
+ *
964
+ * Treat the value as a **UX / targeting hint** and read it live (never cache):
965
+ * for compliance- or entitlement-sensitive enforcement, trust the server-side
966
+ * signed storefront (App Store Server API `storefront` / Play Developer API
967
+ * `regionCode`) instead, since the client value can be unreliable (TestFlight
968
+ * historically reports `"USA"`) or empty (EU alternative distribution).
969
+ */
970
+ interface Storefront {
971
+ /**
972
+ * ISO 3166-1 alpha-2 country code (normalized), e.g. `'US'`. In the rare
973
+ * case the native value can't be normalized (an unrecognized code), this
974
+ * falls back to the uppercased raw value — compare against `countryCodeRaw`
975
+ * if you need certainty about the format.
976
+ */
977
+ countryCode: string;
978
+ /** Raw native value (whitespace-trimmed): alpha-3 on iOS (`'USA'`), alpha-2 on Android (`'US'`). */
979
+ countryCodeRaw: string;
980
+ /** Apple-defined storefront identifier (iOS only); `undefined` on Android. */
981
+ storefrontId?: string;
982
+ /** Store the value came from. */
983
+ platform: Platform;
984
+ }
985
+
953
986
  interface IAP<TEntitlement extends EntitlementBase = EntitlementBase> {
954
987
  initialize(): Promise<void>;
955
988
  /**
@@ -1030,6 +1063,25 @@ interface IAP<TEntitlement extends EntitlementBase = EntitlementBase> {
1030
1063
  * yet ingested by the store are silently skipped (no error).
1031
1064
  */
1032
1065
  getProducts(): Promise<Product[]>;
1066
+ /**
1067
+ * Read the current storefront — the country the user's App Store / Google
1068
+ * Play account is registered to. Use it to drive region-dependent UI:
1069
+ * regional offers/pricing, and gating external-payment links whose
1070
+ * eligibility the platform itself keys to storefront country (not device
1071
+ * locale).
1072
+ *
1073
+ * `countryCode` is normalized to ISO 3166-1 alpha-2 across platforms (raw
1074
+ * native code preserved on `countryCodeRaw`). Resolves `null` when no
1075
+ * storefront is available — on web, when the installed
1076
+ * `@capgo/native-purchases` doesn't register the native method, when the
1077
+ * native call fails, or when the store reports an empty country (e.g. EU
1078
+ * alternative distribution).
1079
+ *
1080
+ * Read live — do not cache. Treat the value as a UX/targeting hint; for
1081
+ * compliance- or entitlement-sensitive enforcement, trust the server-side
1082
+ * signed storefront from your backend instead.
1083
+ */
1084
+ getStorefront(): Promise<Storefront | null>;
1033
1085
  hasEntitlement(key: string): boolean;
1034
1086
  /** Returns a defensive shallow copy. Each entitlement is frozen. */
1035
1087
  getEntitlements(): TEntitlement[];
@@ -1214,4 +1266,4 @@ declare class HttpBackendAdapter<TEntitlement extends EntitlementBase = Entitlem
1214
1266
  listProducts(): Promise<ConfiguredProduct[]>;
1215
1267
  }
1216
1268
 
1217
- export { type AppUserId, type AppUserIdFetcherContext, type BackendAdapter, type BackendConfig, type BackendConfigInput, type ConfiguredProduct, DEFAULT_PERMANENT_ERROR_CODES, type DefaultEntitlement, type EntitlementBase, type EventMap, type EventName, type EventPayload, HttpBackendAdapter, HttpClient, type HttpRequest, type IAP, type IAPConfig, type IAPConfigInput, IAPError, IAPErrorCode, type LogLevel, type Logger, type NativeTransaction, type OptionsConfig, type Platform, type Product, type ProductType, type PurchaseOptions, type PurchaseResult, type RestoreRequest, type RestoreRequestTransaction, type RestoreResponse, type RestoreResult, type StorageConfig, type Unsubscribe, VERSION, type VerifiedTransaction, type VerifyAppleRequest, type VerifyGoogleRequest, type VerifyResponse, createIAP, errorHint, isIAPError };
1269
+ export { type AppUserId, type AppUserIdFetcherContext, type BackendAdapter, type BackendConfig, type BackendConfigInput, type ConfiguredProduct, DEFAULT_PERMANENT_ERROR_CODES, type DefaultEntitlement, type EntitlementBase, type EventMap, type EventName, type EventPayload, HttpBackendAdapter, HttpClient, type HttpRequest, type IAP, type IAPConfig, type IAPConfigInput, IAPError, IAPErrorCode, type LogLevel, type Logger, type NativeTransaction, type OptionsConfig, type Platform, type Product, type ProductType, type PurchaseOptions, type PurchaseResult, type RestoreRequest, type RestoreRequestTransaction, type RestoreResponse, type RestoreResult, type StorageConfig, type Storefront, type Unsubscribe, VERSION, type VerifiedTransaction, type VerifyAppleRequest, type VerifyGoogleRequest, type VerifyResponse, createIAP, errorHint, isIAPError };
package/dist/index.d.ts CHANGED
@@ -950,6 +950,39 @@ interface RestoreResult<TEntitlement extends EntitlementBase = EntitlementBase>
950
950
  entitlements: TEntitlement[];
951
951
  }
952
952
 
953
+ /**
954
+ * The user's App Store / Google Play storefront — i.e. the country their
955
+ * store account is registered to, which is the platform-blessed signal for
956
+ * region-dependent decisions (regional pricing/offers, and gating
957
+ * external-payment links whose eligibility the OS itself keys to storefront
958
+ * country, *not* device locale).
959
+ *
960
+ * `countryCode` is normalized to **ISO 3166-1 alpha-2** across platforms so
961
+ * consumers compare one consistent value (Apple's native code is alpha-3,
962
+ * Google's is alpha-2). The raw native code is preserved in `countryCodeRaw`.
963
+ *
964
+ * Treat the value as a **UX / targeting hint** and read it live (never cache):
965
+ * for compliance- or entitlement-sensitive enforcement, trust the server-side
966
+ * signed storefront (App Store Server API `storefront` / Play Developer API
967
+ * `regionCode`) instead, since the client value can be unreliable (TestFlight
968
+ * historically reports `"USA"`) or empty (EU alternative distribution).
969
+ */
970
+ interface Storefront {
971
+ /**
972
+ * ISO 3166-1 alpha-2 country code (normalized), e.g. `'US'`. In the rare
973
+ * case the native value can't be normalized (an unrecognized code), this
974
+ * falls back to the uppercased raw value — compare against `countryCodeRaw`
975
+ * if you need certainty about the format.
976
+ */
977
+ countryCode: string;
978
+ /** Raw native value (whitespace-trimmed): alpha-3 on iOS (`'USA'`), alpha-2 on Android (`'US'`). */
979
+ countryCodeRaw: string;
980
+ /** Apple-defined storefront identifier (iOS only); `undefined` on Android. */
981
+ storefrontId?: string;
982
+ /** Store the value came from. */
983
+ platform: Platform;
984
+ }
985
+
953
986
  interface IAP<TEntitlement extends EntitlementBase = EntitlementBase> {
954
987
  initialize(): Promise<void>;
955
988
  /**
@@ -1030,6 +1063,25 @@ interface IAP<TEntitlement extends EntitlementBase = EntitlementBase> {
1030
1063
  * yet ingested by the store are silently skipped (no error).
1031
1064
  */
1032
1065
  getProducts(): Promise<Product[]>;
1066
+ /**
1067
+ * Read the current storefront — the country the user's App Store / Google
1068
+ * Play account is registered to. Use it to drive region-dependent UI:
1069
+ * regional offers/pricing, and gating external-payment links whose
1070
+ * eligibility the platform itself keys to storefront country (not device
1071
+ * locale).
1072
+ *
1073
+ * `countryCode` is normalized to ISO 3166-1 alpha-2 across platforms (raw
1074
+ * native code preserved on `countryCodeRaw`). Resolves `null` when no
1075
+ * storefront is available — on web, when the installed
1076
+ * `@capgo/native-purchases` doesn't register the native method, when the
1077
+ * native call fails, or when the store reports an empty country (e.g. EU
1078
+ * alternative distribution).
1079
+ *
1080
+ * Read live — do not cache. Treat the value as a UX/targeting hint; for
1081
+ * compliance- or entitlement-sensitive enforcement, trust the server-side
1082
+ * signed storefront from your backend instead.
1083
+ */
1084
+ getStorefront(): Promise<Storefront | null>;
1033
1085
  hasEntitlement(key: string): boolean;
1034
1086
  /** Returns a defensive shallow copy. Each entitlement is frozen. */
1035
1087
  getEntitlements(): TEntitlement[];
@@ -1214,4 +1266,4 @@ declare class HttpBackendAdapter<TEntitlement extends EntitlementBase = Entitlem
1214
1266
  listProducts(): Promise<ConfiguredProduct[]>;
1215
1267
  }
1216
1268
 
1217
- export { type AppUserId, type AppUserIdFetcherContext, type BackendAdapter, type BackendConfig, type BackendConfigInput, type ConfiguredProduct, DEFAULT_PERMANENT_ERROR_CODES, type DefaultEntitlement, type EntitlementBase, type EventMap, type EventName, type EventPayload, HttpBackendAdapter, HttpClient, type HttpRequest, type IAP, type IAPConfig, type IAPConfigInput, IAPError, IAPErrorCode, type LogLevel, type Logger, type NativeTransaction, type OptionsConfig, type Platform, type Product, type ProductType, type PurchaseOptions, type PurchaseResult, type RestoreRequest, type RestoreRequestTransaction, type RestoreResponse, type RestoreResult, type StorageConfig, type Unsubscribe, VERSION, type VerifiedTransaction, type VerifyAppleRequest, type VerifyGoogleRequest, type VerifyResponse, createIAP, errorHint, isIAPError };
1269
+ export { type AppUserId, type AppUserIdFetcherContext, type BackendAdapter, type BackendConfig, type BackendConfigInput, type ConfiguredProduct, DEFAULT_PERMANENT_ERROR_CODES, type DefaultEntitlement, type EntitlementBase, type EventMap, type EventName, type EventPayload, HttpBackendAdapter, HttpClient, type HttpRequest, type IAP, type IAPConfig, type IAPConfigInput, IAPError, IAPErrorCode, type LogLevel, type Logger, type NativeTransaction, type OptionsConfig, type Platform, type Product, type ProductType, type PurchaseOptions, type PurchaseResult, type RestoreRequest, type RestoreRequestTransaction, type RestoreResponse, type RestoreResult, type StorageConfig, type Storefront, type Unsubscribe, VERSION, type VerifiedTransaction, type VerifyAppleRequest, type VerifyGoogleRequest, type VerifyResponse, createIAP, errorHint, isIAPError };
package/dist/index.js CHANGED
@@ -137,11 +137,293 @@ var init_platform = __esm({
137
137
  }
138
138
  });
139
139
 
140
+ // src/lib/iso-country.ts
141
+ function toAlpha2(code) {
142
+ if (!code) return null;
143
+ const normalized = code.trim().toUpperCase();
144
+ if (normalized.length === 2) return normalized;
145
+ if (normalized.length === 3) return ALPHA3_TO_ALPHA2[normalized] ?? null;
146
+ return null;
147
+ }
148
+ var ALPHA3_TO_ALPHA2;
149
+ var init_iso_country = __esm({
150
+ "src/lib/iso-country.ts"() {
151
+ ALPHA3_TO_ALPHA2 = {
152
+ ABW: "AW",
153
+ AFG: "AF",
154
+ AGO: "AO",
155
+ AIA: "AI",
156
+ ALA: "AX",
157
+ ALB: "AL",
158
+ AND: "AD",
159
+ ARE: "AE",
160
+ ARG: "AR",
161
+ ARM: "AM",
162
+ ASM: "AS",
163
+ ATA: "AQ",
164
+ ATF: "TF",
165
+ ATG: "AG",
166
+ AUS: "AU",
167
+ AUT: "AT",
168
+ AZE: "AZ",
169
+ BDI: "BI",
170
+ BEL: "BE",
171
+ BEN: "BJ",
172
+ BES: "BQ",
173
+ BFA: "BF",
174
+ BGD: "BD",
175
+ BGR: "BG",
176
+ BHR: "BH",
177
+ BHS: "BS",
178
+ BIH: "BA",
179
+ BLM: "BL",
180
+ BLR: "BY",
181
+ BLZ: "BZ",
182
+ BMU: "BM",
183
+ BOL: "BO",
184
+ BRA: "BR",
185
+ BRB: "BB",
186
+ BRN: "BN",
187
+ BTN: "BT",
188
+ BVT: "BV",
189
+ BWA: "BW",
190
+ CAF: "CF",
191
+ CAN: "CA",
192
+ CCK: "CC",
193
+ CHE: "CH",
194
+ CHL: "CL",
195
+ CHN: "CN",
196
+ CIV: "CI",
197
+ CMR: "CM",
198
+ COD: "CD",
199
+ COG: "CG",
200
+ COK: "CK",
201
+ COL: "CO",
202
+ COM: "KM",
203
+ CPV: "CV",
204
+ CRI: "CR",
205
+ CUB: "CU",
206
+ CUW: "CW",
207
+ CXR: "CX",
208
+ CYM: "KY",
209
+ CYP: "CY",
210
+ CZE: "CZ",
211
+ DEU: "DE",
212
+ DJI: "DJ",
213
+ DMA: "DM",
214
+ DNK: "DK",
215
+ DOM: "DO",
216
+ DZA: "DZ",
217
+ ECU: "EC",
218
+ EGY: "EG",
219
+ ERI: "ER",
220
+ ESH: "EH",
221
+ ESP: "ES",
222
+ EST: "EE",
223
+ ETH: "ET",
224
+ FIN: "FI",
225
+ FJI: "FJ",
226
+ FLK: "FK",
227
+ FRA: "FR",
228
+ FRO: "FO",
229
+ FSM: "FM",
230
+ GAB: "GA",
231
+ GBR: "GB",
232
+ GEO: "GE",
233
+ GGY: "GG",
234
+ GHA: "GH",
235
+ GIB: "GI",
236
+ GIN: "GN",
237
+ GLP: "GP",
238
+ GMB: "GM",
239
+ GNB: "GW",
240
+ GNQ: "GQ",
241
+ GRC: "GR",
242
+ GRD: "GD",
243
+ GRL: "GL",
244
+ GTM: "GT",
245
+ GUF: "GF",
246
+ GUM: "GU",
247
+ GUY: "GY",
248
+ HKG: "HK",
249
+ HMD: "HM",
250
+ HND: "HN",
251
+ HRV: "HR",
252
+ HTI: "HT",
253
+ HUN: "HU",
254
+ IDN: "ID",
255
+ IMN: "IM",
256
+ IND: "IN",
257
+ IOT: "IO",
258
+ IRL: "IE",
259
+ IRN: "IR",
260
+ IRQ: "IQ",
261
+ ISL: "IS",
262
+ ISR: "IL",
263
+ ITA: "IT",
264
+ JAM: "JM",
265
+ JEY: "JE",
266
+ JOR: "JO",
267
+ JPN: "JP",
268
+ KAZ: "KZ",
269
+ KEN: "KE",
270
+ KGZ: "KG",
271
+ KHM: "KH",
272
+ KIR: "KI",
273
+ KNA: "KN",
274
+ KOR: "KR",
275
+ KWT: "KW",
276
+ LAO: "LA",
277
+ LBN: "LB",
278
+ LBR: "LR",
279
+ LBY: "LY",
280
+ LCA: "LC",
281
+ LIE: "LI",
282
+ LKA: "LK",
283
+ LSO: "LS",
284
+ LTU: "LT",
285
+ LUX: "LU",
286
+ LVA: "LV",
287
+ MAC: "MO",
288
+ MAF: "MF",
289
+ MAR: "MA",
290
+ MCO: "MC",
291
+ MDA: "MD",
292
+ MDG: "MG",
293
+ MDV: "MV",
294
+ MEX: "MX",
295
+ MHL: "MH",
296
+ MKD: "MK",
297
+ MLI: "ML",
298
+ MLT: "MT",
299
+ MMR: "MM",
300
+ MNE: "ME",
301
+ MNG: "MN",
302
+ MNP: "MP",
303
+ MOZ: "MZ",
304
+ MRT: "MR",
305
+ MSR: "MS",
306
+ MTQ: "MQ",
307
+ MUS: "MU",
308
+ MWI: "MW",
309
+ MYS: "MY",
310
+ MYT: "YT",
311
+ NAM: "NA",
312
+ NCL: "NC",
313
+ NER: "NE",
314
+ NFK: "NF",
315
+ NGA: "NG",
316
+ NIC: "NI",
317
+ NIU: "NU",
318
+ NLD: "NL",
319
+ NOR: "NO",
320
+ NPL: "NP",
321
+ NRU: "NR",
322
+ NZL: "NZ",
323
+ OMN: "OM",
324
+ PAK: "PK",
325
+ PAN: "PA",
326
+ PCN: "PN",
327
+ PER: "PE",
328
+ PHL: "PH",
329
+ PLW: "PW",
330
+ PNG: "PG",
331
+ POL: "PL",
332
+ PRI: "PR",
333
+ PRK: "KP",
334
+ PRT: "PT",
335
+ PRY: "PY",
336
+ PSE: "PS",
337
+ PYF: "PF",
338
+ QAT: "QA",
339
+ REU: "RE",
340
+ ROU: "RO",
341
+ RUS: "RU",
342
+ RWA: "RW",
343
+ SAU: "SA",
344
+ SDN: "SD",
345
+ SEN: "SN",
346
+ SGP: "SG",
347
+ SGS: "GS",
348
+ SHN: "SH",
349
+ SJM: "SJ",
350
+ SLB: "SB",
351
+ SLE: "SL",
352
+ SLV: "SV",
353
+ SMR: "SM",
354
+ SOM: "SO",
355
+ SPM: "PM",
356
+ SRB: "RS",
357
+ SSD: "SS",
358
+ STP: "ST",
359
+ SUR: "SR",
360
+ SVK: "SK",
361
+ SVN: "SI",
362
+ SWE: "SE",
363
+ SWZ: "SZ",
364
+ SXM: "SX",
365
+ SYC: "SC",
366
+ SYR: "SY",
367
+ TCA: "TC",
368
+ TCD: "TD",
369
+ TGO: "TG",
370
+ THA: "TH",
371
+ TJK: "TJ",
372
+ TKL: "TK",
373
+ TKM: "TM",
374
+ TLS: "TL",
375
+ TON: "TO",
376
+ TTO: "TT",
377
+ TUN: "TN",
378
+ TUR: "TR",
379
+ TUV: "TV",
380
+ TWN: "TW",
381
+ TZA: "TZ",
382
+ UGA: "UG",
383
+ UKR: "UA",
384
+ UMI: "UM",
385
+ URY: "UY",
386
+ USA: "US",
387
+ UZB: "UZ",
388
+ VAT: "VA",
389
+ VCT: "VC",
390
+ VEN: "VE",
391
+ VGB: "VG",
392
+ VIR: "VI",
393
+ VNM: "VN",
394
+ VUT: "VU",
395
+ WLF: "WF",
396
+ WSM: "WS",
397
+ YEM: "YE",
398
+ ZAF: "ZA",
399
+ ZMB: "ZM",
400
+ ZWE: "ZW"
401
+ };
402
+ }
403
+ });
404
+
140
405
  // src/adapters/native/capgo/native-adapter.ts
141
406
  var native_adapter_exports = {};
142
407
  __export(native_adapter_exports, {
143
408
  CapgoNativeAdapter: () => CapgoNativeAdapter
144
409
  });
410
+ function nativeStorefrontRegistered() {
411
+ const headers = Capacitor.PluginHeaders;
412
+ return headers?.find((h) => h.name === "NativePurchases")?.methods?.some((m) => m.name === "getStorefront") ?? false;
413
+ }
414
+ function normalizeStorefront(raw) {
415
+ const code = raw?.countryCode?.trim();
416
+ if (!code) return null;
417
+ const platform = getPlatform() === "android" ? "google" : "apple";
418
+ return {
419
+ // alpha-2 when recognized; otherwise the uppercased raw code as a
420
+ // best-effort fallback (see `Storefront.countryCode`).
421
+ countryCode: toAlpha2(code) ?? code.toUpperCase(),
422
+ countryCodeRaw: code,
423
+ storefrontId: raw.storefrontId,
424
+ platform
425
+ };
426
+ }
145
427
  function normalizeProduct(p, type) {
146
428
  const priceMicros = Math.round(p.price * 1e6).toString();
147
429
  return {
@@ -217,6 +499,7 @@ var CapgoNativeAdapter;
217
499
  var init_native_adapter = __esm({
218
500
  "src/adapters/native/capgo/native-adapter.ts"() {
219
501
  init_errors();
502
+ init_iso_country();
220
503
  init_platform();
221
504
  CapgoNativeAdapter = class {
222
505
  async isAvailable() {
@@ -300,6 +583,24 @@ var init_native_adapter = __esm({
300
583
  });
301
584
  }
302
585
  }
586
+ /**
587
+ * Read the current storefront from the native plugin — which is expected to
588
+ * source it from StoreKit 2 `Storefront.current` on iOS (alpha-3) and
589
+ * `getBillingConfigAsync()` on Android (alpha-2) — normalizing `countryCode`
590
+ * to alpha-2. Silent like {@link CapgoNativeAdapter.isAvailable}: any
591
+ * unavailability — older plugin (no native method registered), native
592
+ * rejection, or empty country — resolves to `null` rather than throwing.
593
+ */
594
+ async getStorefront() {
595
+ if (!nativeStorefrontRegistered()) return null;
596
+ const np = NativePurchases;
597
+ try {
598
+ const raw = await np.getStorefront?.();
599
+ return raw ? normalizeStorefront(raw) : null;
600
+ } catch {
601
+ return null;
602
+ }
603
+ }
303
604
  async dispose() {
304
605
  }
305
606
  };
@@ -830,6 +1131,9 @@ var WebStubAdapter = class {
830
1131
  message: "Subscription management is not supported on the web platform."
831
1132
  });
832
1133
  }
1134
+ async getStorefront() {
1135
+ return null;
1136
+ }
833
1137
  };
834
1138
 
835
1139
  // src/adapters/native/index.ts
@@ -1931,6 +2235,10 @@ function createIAP(input) {
1931
2235
  }
1932
2236
  return state.adapter.getProducts(state.products.map((p) => ({ id: p.id, type: p.type })));
1933
2237
  },
2238
+ async getStorefront() {
2239
+ requireInitialized(state);
2240
+ return state.adapter?.getStorefront?.() ?? null;
2241
+ },
1934
2242
  hasEntitlement(key) {
1935
2243
  return state.entitlements.some((e) => e.key === key);
1936
2244
  },