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

saif-prebuild-guard

v1.0.0

Published

Catches Expo config-plugin conflicts (missing packages, duplicate plugins, colliding native config keys) before you spend 10-20 minutes waiting for eas build to fail.

Readme

saif-prebuild-guard

Catches Expo config-plugin conflicts before you spend 10-20 minutes waiting for eas build to fail.

Created by Saif Ullah Abid.

The problem

Modern Expo apps use Continuous Native Generation (CNG) — instead of hand-editing native Android/iOS project files, you list "config plugins" (expo-camera, expo-notifications, @react-native-firebase/app, and dozens more) in app.json, and Expo generates the native project from them at build time.

This is powerful, but it has a real, common failure mode with no existing tooling built specifically around it: two plugins can silently modify the same native setting, a plugin can be listed but never actually installed, or the same plugin can accidentally end up listed twice with different configs. None of these show up in your editor. None of them show up in Expo Go. They only show up after a real eas build run — typically 10 to 20 minutes of cloud build time — fails, often with a native build error that doesn't obviously point back to the actual cause.

saif-prebuild-guard checks for these specific, real mistakes statically, in about a second, before you burn a build.

What it checks

  1. Plugin listed but not installed — a plugin appears in app.json's plugins array but isn't in package.json. Guaranteed to fail at prebuild time; this is the single most common version of this bug.

  2. The same plugin listed twice — Continuous Native Generation applies it twice, which can duplicate native permission entries or silently apply two different configurations depending on order.

  3. Two different plugins that modify the same native setting — checked against a curated database of well-known Expo config plugins and the native keys they're documented to touch (permissions, Info.plist keys, Gradle build values, Firebase config file registration). Not a guaranteed failure, but a concrete, worth-checking-before-you-build risk.

Install

npm install --save-dev saif-prebuild-guard

Usage

Run it from your Expo project root:

npx saif-prebuild-guard

Real output, from the deliberately broken example project included in this repo:

Checked: app.json
6 plugin entries declared

error  Plugin "expo-document-scanner-not-installed" is listed in your app config but is not in package.json. This will fail at prebuild/build time.
error  Plugin "expo-build-properties" appears 2 times in your plugins array. Continuous Native Generation will apply it 2 times, which can duplicate native entries or apply conflicting configuration from each occurrence.
warning  "expo-notifications" and "@react-native-firebase/messaging" both modify: android.permission.POST_NOTIFICATIONS, android.googleServicesFile. Verify their configuration doesn't conflict before building.

2 error(s), 1 warning(s)

Exits with code 1 if any error-severity finding exists — drop it into CI, right before your eas build step:

- run: npx saif-prebuild-guard
- run: eas build --platform all --non-interactive

Catching this in a 1-second check instead of a 15-minute failed cloud build is the entire point.

Supported config formats

  • app.json — fully supported (plain JSON)
  • app.config.js / app.config.ts — best-effort: literal plugin entries ("expo-camera", ["expo-build-properties", {...}]) are extracted correctly; plugins added via computed/dynamic logic are skipped rather than guessed at, for the same reason described below.

The plugin database is a curated starting set, not a universal registry

This is the single most important honesty note in this README. saif-prebuild-guard ships with a hand-curated set of well-known Expo config plugins and their documented native effects — it is not an exhaustive database of every Expo config plugin that exists. An unlisted plugin is simply skipped by the "shared native key" check rather than assumed to be either safe or conflicting. The "not installed" and "duplicate plugin" checks work for any plugin regardless of whether it's in the database, since those two only need the plugin's name, not its documented effects.

The database lives in src/pluginDatabase.ts as a plain, readable list — extending it for a plugin you use that isn't covered yet is a two-minute edit and a genuinely useful contribution.

Proof it works

26 automated tests, including a full integration test that runs the tool against a deliberately broken example project and confirms it catches exactly the right violations, plus a clean project confirming zero false positives:

npm test
# tests 26
# suites 8
# pass 26
# fail 0

License

MIT


Built by Saif Ullah Abid