npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-esim-compatibility-checker

v0.1.0

Published

Check whether a device supports eSIM, plus a browsable catalog of eSIM compatible devices.

Readme

react-native-esim-compatibility-checker

Check whether a device can run an eSIM, without making the user dial a code and interpret the result themselves.

Two independent features:

  1. Detection. Ask the device directly whether it supports eSIM.
  2. Catalog. A browsable, searchable list of eSIM compatible devices, for building a "supported devices" screen.

The two never mix. Detection reads the hardware. The catalog is display data.

Install

npm install react-native-esim-compatibility-checker

No permissions and no entitlements are required on either platform.

Detection

import { checkEsimSupport } from 'react-native-esim-compatibility-checker';

const result = await checkEsimSupport();

if (result.state === 'supported') {
  // Offer the eSIM flow.
} else if (result.state === 'unsupported') {
  // Offer a physical SIM instead.
} else {
  // Could not tell. Ask the user rather than guessing.
}

result carries six fields:

| Field | Meaning | | --- | --- | | state | supported, unsupported or unknown | | source | which signal decided, so a surprising verdict is debuggable | | deviceIdentifier | raw hardware identifier, iPhone17,1 or SM-S928B | | deviceName | human readable name, or null if not in the bundled map | | deviceFamily | iphone, ipad, android or unknown | | warning | set only when something is worth telling you, null otherwise |

unknown is a real answer

It means no signal could settle the question. Reporting unsupported there would be a confident wrong answer, which is the exact failure this package exists to avoid. Treat unknown as "ask the user", not as "no".

How each platform decides

iPhone. Apple's generation numbering splits exactly on eSIM. Generation 10 is iPhone 8, 8 Plus and X, none with eSIM. Generation 11 is XS, XS Max and XR, the first with it. So the rule is a comparison, not a list, and it stays correct for iPhones that do not exist yet.

iPad. There is no clean cutoff, so eSIM capable models come from a small table. Family 8 and above qualify, plus the 7th generation iPad, whose family siblings do not. A qualifying model then needs a detected cellular radio, because the Wi-Fi only build of the same model has no eSIM and the identifier does not distinguish them. No radio found means unknown, never unsupported.

Android. Two signals, either positive wins. EuiccManager.isEnabled() from Android 9, and the android.hardware.telephony.euicc hardware feature from Android 13. The second rescues devices where a carrier build disables the eSIM profile assistant while the hardware is present. Below Android 9 there is no eSIM API at all, so the answer is unsupported.

CoreTelephony is only ever a positive. Apple documents supportsCellularPlan() as whether the device and your app meet provisioning requirements, and it is entangled with the carrier entitlement, so it returns false on plenty of eSIM capable hardware. A true from it can promote a result. A false from it never overrides a model rule. When the model says supported and CoreTelephony disagrees, you get a warning instead, because that is how a regional variant without eSIM hardware shows up.

Simulators and emulators always report unknown. They cannot answer this, and pretending otherwise teaches you to trust a result that means nothing.

Catalog

import {
  getDevices,
  getBrands,
  getCategories,
  searchDevices,
  checkDeviceByName,
} from 'react-native-esim-compatibility-checker';

getCategories();                          // ['phones', 'watches', 'laptops', 'tablets']
getDevices({ category: 'phones' });       // every listed phone
getDevices({ brand: 'Samsung' });         // one brand
getBrands('phones');                      // brands within a category
searchDevices('pixel');                   // free text over name and brand
checkDeviceByName('galaxy s25 plus');     // 'supported' | 'unsupported' | 'unknown'

Name matching normalises case, spacing and punctuation, so galaxy s25 plus finds Galaxy S25+.

checkDeviceByName returns unknown for anything not listed. The catalog holds no negative entries, so absence proves nothing.

Keeping it current

The catalog ships inside the package, so the library works offline and needs no hosting. To push new devices without a release, refresh it from a URL you own:

import { refreshCatalog, restoreCatalog } from 'react-native-esim-compatibility-checker';

await refreshCatalog('https://example.com/esim-catalog.json');

A failed or malformed refresh leaves the bundled catalog in place, so the package never degrades below what it shipped with. A payload whose schemaVersion does not match is rejected rather than half applied.

Persistence is yours to choose. The package ships no storage dependency:

await restoreCatalog({ get: readFromYourStorage });                  // at startup
await refreshCatalog(url, { set: writeToYourStorage });              // later

What this package does not do

It answers whether the hardware can run an eSIM. It does not report whether a profile is already installed, and it does not expose the EID. Both need carrier privileges a third party library cannot have.

Regenerating the data

node scripts/generate-apple-device-names.mjs   # identifier to name map
node scripts/convert-catalog.mjs <source.txt>  # catalog from the source list

The name map is cosmetic. A missing entry shows the raw identifier and can never change a verdict.

License

MIT