nativekeel 0.1.18 → 0.1.19

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/README.md CHANGED
@@ -6,7 +6,7 @@ Health check for React Native and Expo apps. One command, no install, no account
6
6
  npx nativekeel
7
7
  ```
8
8
 
9
- **What's new in 0.1.18:** the upgrade plan only suggests library versions your current React Native supports, moves React Navigation and RN Firebase packages together, and says plainly when a vulnerable package has no fixed release. **0.1.17:** every vulnerable package shows the version that fixes it; Expo apps get one line for the packages the SDK upgrade moves. Recent releases added a *Start here* list in every report, hacking risks mapped to OWASP MASVS, crash and performance checks. Every check is tuned on 450+ open-source React Native and Expo apps to keep false alarms out. [All releases →](https://nativekeel.com/changelog)
9
+ **What's new in 0.1.19:** better plans for apps that are far behind: library targets that fit the React Native you have, not the latest. **0.1.18:** the upgrade plan only suggests library versions your current React Native supports, moves React Navigation and RN Firebase packages together, and says plainly when a vulnerable package has no fixed release. Recent releases added a *Start here* list in every report, hacking risks mapped to OWASP MASVS, crash and performance checks. Every check is tuned on 450+ open-source React Native and Expo apps to keep false alarms out. [All releases →](https://nativekeel.com/changelog)
10
10
 
11
11
  ```
12
12
  Summary 4 critical · 5 high · 4 medium · 6 low
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nativekeel",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "description": "Health check for React Native and Expo apps: upgrade blockers, store deadlines, crash risks, vulnerable dependencies and leaked secrets, with a step-by-step upgrade plan.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/plan.js CHANGED
@@ -177,6 +177,8 @@ export function buildPlan(result) {
177
177
  const pm = isExpo ? { ...basePm, add: 'npx expo install' } : basePm;
178
178
  const pinned = isExpo ? expoPinnedNames(result.project.root) : new Set();
179
179
  const movesWithExpo = (name) => isExpo && movesWithExpoSdk(name, pinned);
180
+ // Packages the React Native upgrade steps move (React Native itself and the compatibility tables).
181
+ const movesWithRn = (name) => !isExpo && !!byKind('upgrade-rn').length && (name === 'react-native' || !!COMPAT[name]);
180
182
  const installed = new Set(result.deps.map((d) => d.name));
181
183
  const byKind = (kind) => result.findings.filter((f) => f.fix && f.fix.kind === kind).map((f) => f.fix);
182
184
  const phases = [];
@@ -290,7 +292,7 @@ export function buildPlan(result) {
290
292
  } else if (f.fix.kind === 'vuln-dep' && (f.fix.severity === 'critical' || f.fix.severity === 'high')) {
291
293
  const v = f.fix;
292
294
  if (v.noFix) sec.push({ sev, step: `\`${v.name}\` ${v.from} has ${v.severity} known vulnerabilities and no fixed release (the latest is ${v.latest}): replace it, or make sure it never handles untrusted input.` });
293
- else sec.push({ sev, step: `Update \`${v.name}\` ${v.from}${v.to ? ` to ${v.to}${v.to.startsWith('a release') ? '' : ' or later'}` : ''}: it has ${v.severity} known vulnerabilities. ${movesWithExpo(v.name) ? 'Expo pins it: the SDK upgrade below moves it.' : 'Check its changelog for breaking changes.'}` });
295
+ else sec.push({ sev, step: `Update \`${v.name}\` ${v.from}${v.to ? ` to ${v.to}${v.to.startsWith('a release') ? '' : ' or later'}` : ''}: it has ${v.severity} known vulnerabilities. ${movesWithExpo(v.name) ? 'Expo pins it: the SDK upgrade below moves it.' : movesWithRn(v.name) ? 'The React Native steps below move it past this version; if you ship before them, update it now.' : 'Check its changelog for breaking changes.'}` });
294
296
  }
295
297
  }
296
298
  const securitySteps = sec.sort((a, b) => a.sev - b.sev).map((x) => x.step);
@@ -369,17 +371,21 @@ export function buildPlan(result) {
369
371
  // The React Native steps move them further.
370
372
  const curMinor = result.project.reactNative ? Number(result.project.reactNative.split('.')[1]) : null;
371
373
  const archNow = !byKind('enable-new-arch').length;
374
+ const rnTarget = byKind('upgrade-rn')[0];
375
+ const rnBehind = !!(rnTarget && curMinor !== null && Number(rnTarget.to.split('.')[1]) - curMinor >= 3);
372
376
  const nativeBumps = byKind('bump-dep')
373
377
  .filter((d) => d.native && !movesWithExpo(d.name))
374
378
  .map((d) => {
375
379
  if (!COMPAT[d.name] || curMinor === null) return d;
376
380
  const best = bestRange(d.name, curMinor, archNow);
377
- if (!best) return d;
381
+ if (!best) return null; // the table starts later: the React Native steps move it
378
382
  if (compareVersions(d.from, best.from) >= 0 && (!best.to || compareVersions(d.from, best.to) <= 0)) return null;
379
383
  if (compareVersions(d.from, best.from) > 0) return null;
380
384
  return { ...d, to: best.range, capped: `0.${curMinor}` };
381
385
  })
382
- .filter(Boolean);
386
+ .filter(Boolean)
387
+ // Far behind: the latest release usually needs a newer React Native than the app has.
388
+ .map((d) => (rnBehind && !d.capped ? { ...d, to: `the newest release that supports React Native 0.${curMinor} (latest is ${d.to})` } : d));
383
389
  if (nativeBumps.length) {
384
390
  phases.push({
385
391
  title: 'Update native modules on the current React Native version',