Skip to content

ReactNative: New init setup#34665

Merged
ndelangen merged 13 commits into
nextfrom
norbert/m3-generator-orchestration
May 5, 2026
Merged

ReactNative: New init setup#34665
ndelangen merged 13 commits into
nextfrom
norbert/m3-generator-orchestration

Conversation

@ndelangen
Copy link
Copy Markdown
Member

@ndelangen ndelangen commented Apr 30, 2026

Split out of #34333 (M1). Tracking issue: #34276.

What I did

Wires the React Native generator end-to-end during storybook init:

  • Calls the M1 metro-config codemod to wrap the project's metro.config.{js,ts,cjs} with withStorybook(...), falling back to a guidance comment when the AST transform can't be applied safely.
  • Calls the M2 entrypoint generator to write .rnstorybook/index.{ts,js}.
  • Adds generateScripts to derive storybook:ios / storybook:android npm scripts and request cross-env when needed.
  • Updates ProjectTypeService to detect React Native projects via the expo dependency in addition to react-native / react-native-scripts.
    This is the orchestration layer that makes the React Native init flow user-facing.

Stack

This PR is stacked on M1 + M2 and depends on them. It's targeted at next for review, but the diff right now also includes the M1 and M2 commits because GitHub shows everything between this branch and next. Once those merge, this PR's diff will collapse to the M3-only files.

Merge order

  1. M1 → next
  2. M2 → next
  3. This PR (M3) → next (diff will shrink to M3-only)

Checklist for Contributors

Testing

The changes in this PR are covered in the following automated tests:

  • stories
  • unit tests
  • integration tests
  • end-to-end tests

Manual testing

Test 1: Fresh Expo project (TypeScript)

npx create-expo-app@latest MyExpoApp
cd MyExpoApp
npx storybook@canary init

Verify:

  • metro.config.js is wrapped with withStorybook(...) and imports from @storybook/react-native/withStorybook
  • .rnstorybook/index.tsx exists and contains AppRegistry.registerComponent
  • .rnstorybook/main.ts and .rnstorybook/preview.tsx exist
  • package.json has storybook:ios and storybook:android scripts with STORYBOOK_ENABLED=true
  • Run STORYBOOK_ENABLED=true npx expo start — Storybook launches with example stories visible
  • Run npx expo start (without the env var) — your app launches normally, no Storybook

Test 2: Existing project with a metro config already present

npx create-expo-app@latest MyExistingApp
cd MyExistingApp
npx expo customize metro.config.js
npx storybook@canary init

Verify:

  • Existing metro.config.js is modified in-place, not overwritten
  • withStorybook(...) wraps the existing export
  • Existing config (e.g. getDefaultConfig) is preserved inside the wrapper

Test 3: React Native CLI project (no Expo)

npx @react-native-community/cli init MyRNApp
cd MyRNApp
npx storybook@canary init

Verify:

  • metro.config.js is detected and wrapped correctly
  • package.json scripts wrap the existing react-native commands (not expo)
  • STORYBOOK_ENABLED=true npx react-native start launches Storybook

Documentation

  • Add or update documentation reflecting your changes
  • If you are deprecating/removing a feature, make sure to update
    MIGRATION.MD

Checklist for Maintainers

  • When this PR is ready for testing, make sure to add ci:normal, ci:merged or ci:daily GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found in code/lib/cli-storybook/src/sandbox-templates.ts

  • Make sure this PR contains one of the labels below:

    Available labels
    • bug: Internal changes that fixes incorrect behavior.
    • maintenance: User-facing maintenance tasks.
    • dependencies: Upgrading (sometimes downgrading) dependencies.
    • build: Internal-facing build tooling & test updates. Will not show up in release changelog.
    • cleanup: Minor cleanup style change. Will not show up in release changelog.
    • documentation: Documentation only changes. Will not show up in release changelog.
    • feature request: Introducing a new feature.
    • BREAKING CHANGE: Changes that break compatibility in some way with current major version.
    • other: Changes that don't fit in the above categories.

🦋 Canary release

This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the @storybookjs/core team here.

core team members can create a canary release here or locally with gh workflow run --repo storybookjs/storybook publish.yml --field pr=<PR_NUMBER>

Wires the React Native generator end-to-end during `storybook init`:

- Calls the M1 metro-config codemod to wrap the project's
  `metro.config.{js,ts,cjs}` with `withStorybook(...)`, falling back to a
  guidance comment when the AST transform can't be applied safely.
- Calls the M2 entrypoint generator to write `.rnstorybook/index.{ts,js}`.
- Adds `generateScripts` to derive `storybook:ios` / `storybook:android`
  npm scripts and request `cross-env` when needed.
- Updates `ProjectTypeService` to detect React Native projects via the
  `expo` dependency in addition to `react-native` / `react-native-scripts`.

This is the orchestration layer that makes the React Native init flow
user-facing. It depends on the M1 codemod and M2 entrypoint generator —
this PR is stacked on top of those branches and should be merged after
them. Once M1 and M2 land on `next`, this PR's diff will reduce to the
M3-only files.

Files added (M3):
- `src/generators/REACT_NATIVE/generateScripts.{ts,test.ts}`
- `src/generators/REACT_NATIVE/index.test.ts`

Files modified (M3):
- `src/generators/REACT_NATIVE/index.ts` — orchestration
- `src/services/ProjectTypeService.{ts,test.ts}` — expo detection

Split out of #34333 (M3). Tracking issue: #34276.

Made-with: Cursor
Copilot AI review requested due to automatic review settings April 30, 2026 08:53
@ndelangen ndelangen self-assigned this Apr 30, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Wires up a new end-to-end React Native setup path for storybook init in create-storybook, including Metro config codemodding, .rnstorybook entrypoint generation, and platform run-script derivation, plus improved RN project detection.

Changes:

  • Add Metro config codemod to wrap metro.config.* exports with withStorybook(...), with fallback guidance comment on unsupported shapes.
  • Generate .rnstorybook/index.(ts|js) entrypoint and derive storybook:ios / storybook:android scripts (optionally adding cross-env).
  • Expand RN project auto-detection to include expo dependency, with unit tests.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
code/lib/create-storybook/templates/react-native/index.js Adds user-editable RN Storybook entrypoint template.
code/lib/create-storybook/src/services/ProjectTypeService.ts Detects RN projects via expo dependency.
code/lib/create-storybook/src/services/ProjectTypeService.test.ts Adds coverage for expo → RN detection.
code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.ts Implements Metro codemod + fallback comment behavior.
code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.test.ts Adds tests for Metro codemod/update/fallback flows.
code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts Orchestrates scripts + entrypoint generation + Metro codemod; updates post-config messaging.
code/lib/create-storybook/src/generators/REACT_NATIVE/index.test.ts Adds unit tests for RN generator orchestration and messaging.
code/lib/create-storybook/src/generators/REACT_NATIVE/generateScripts.ts Derives storybook:ios/android scripts from base scripts.
code/lib/create-storybook/src/generators/REACT_NATIVE/generateScripts.test.ts Adds unit tests for script derivation behavior.
code/lib/create-storybook/src/generators/REACT_NATIVE/generateEntrypoint.ts Generates `.rnstorybook/index.(ts
code/lib/create-storybook/src/generators/REACT_NATIVE/generateEntrypoint.test.ts Adds unit tests for entrypoint generation/overwrite behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.ts Outdated
Comment thread code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts
Comment thread code/lib/create-storybook/src/generators/REACT_NATIVE/generateScripts.ts Outdated
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 30, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Derives platform-specific Storybook run scripts from existing ios/android package scripts with STORYBOOK_ENABLED handling, adds an AST-based Metro config codemod that wraps exports with withStorybook (with fallback), tightens RN detection to require expo, and integrates these into the REACT_NATIVE generator flows.

React Native Storybook Setup Automation

Layer / File(s) Summary
Project Type Detection
code/lib/create-storybook/src/services/ProjectTypeService.ts, code/lib/create-storybook/src/services/ProjectTypeService.test.ts
React Native detection now requires expo (in addition to react-native/react-native-scripts); test added verifying detection when expo is present.
Platform Script Derivation (data & API)
code/lib/create-storybook/src/generators/REACT_NATIVE/generateScripts.ts, code/lib/create-storybook/src/generators/REACT_NATIVE/generateScripts.test.ts
New exported types and deriveStorybookPlatformScripts(scripts) introduced; extracts/trims ios/android base scripts, returns scriptsToAdd (storybook:ios/storybook:android) and missingBaseScripts; handles whitespace, STORYBOOK_ENABLED= presence, cross-env/cross-env-shell forms, preserves explicit STORYBOOK_ENABLED=false, and avoids mutating unrelated scripts.
Generator Integration (core wiring)
code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts, code/lib/create-storybook/src/generators/REACT_NATIVE/index.test.ts
configure derives platform scripts from package.json, records derivation, conditionally includes cross-env in packages to resolve only when required, generates RN entrypoint(s), runs runMetroCodemodOrFallback, stores Metro/codemod results; postConfigure logs derived run commands, Metro codemod summary, and targeted warnings for missing base scripts. Tests cover entrypoint generation, script overwrite, cross-env conditional resolution, and postConfigure messaging.
Metro Codemod (implementation & helpers)
code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.ts, code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.test.ts
New Metro codemod discovers metro config candidates (with Expo-assisted creation), parses via Recast/Babel, detects existing Storybook usage, injects or reuses withStorybook import/require, wraps module.exports/export default exports (preserving TS/Flow metadata), ensures import placement after directive-prologues/pragmas, prepends a single fallback comment on unsupported transforms/errors, and returns structured MetroCodemodResult statuses. Tests cover CJS/ESM transforms, idempotency, multi-file selection, Expo flow, fallback commenting, pragma preservation, and helper behaviors (containsStorybookImport, prependMetroFallbackComment).
sequenceDiagram
    participant CLI as User/CLI
    participant Generator as RN Generator
    participant Pkg as package.json
    participant Deriver as Script Derivation
    participant PM as Package Manager
    participant FS as File System
    participant Metro as Metro Codemod

    CLI->>Generator: configure()
    Generator->>Pkg: read scripts (ios/android)
    Pkg-->>Generator: base scripts
    Generator->>Deriver: deriveStorybookPlatformScripts(scripts)
    Deriver->>Deriver: trim & inject STORYBOOK_ENABLED / handle cross-env
    Deriver-->>Generator: scriptsToAdd, missingBaseScripts
    Generator->>PM: getDependencyVersion('cross-env')
    alt cross-env needed and missing
        Generator->>PM: add cross-env to versioned packages
    end
    Generator->>Pkg: addScripts(scriptsToAdd)
    Generator->>FS: generateReactNativeEntrypoint()
    Generator->>Metro: runMetroCodemodOrFallback({ packageManager, yes })
    Metro->>FS: detect metro config candidates (attempt expo customize if needed)
    Metro->>FS: read selected config
    Metro->>Metro: parse AST, detect Storybook import
    alt already configured
        Metro-->>Generator: skipped-existing-storybook-import
    else transformable
        Metro->>FS: write wrapped config (withStorybook)
        Metro-->>Generator: updated
    else unsupported / error
        Metro->>FS: prepend fallback comment
        Metro-->>Generator: fallback-commented
    end
    Generator-->>CLI: postConfigure logs (scripts, metro status, warnings)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.ts (1)

34-38: 💤 Low value

Minor: consider consolidating pattern logic.

STORYBOOK_PACKAGE_PATTERNS is only used in the catch fallback (line 103), while hasStorybookPackage duplicates the same check logic inline. This is fine for correctness but could be simplified by having hasStorybookPackage reference the constant.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.ts` around
lines 34 - 38, hasStorybookPackage duplicates the package-check logic already
expressed in STORYBOOK_PACKAGE_PATTERNS; update hasStorybookPackage to reference
the constant instead of reimplementing the checks (e.g., use
STORYBOOK_PACKAGE_PATTERNS.some(...) or equivalent) so the pattern logic is
centralized and the catch-fallback still uses the same source of truth
(STORYBOOK_PACKAGE_PATTERNS) — modify the hasStorybookPackage function
accordingly.
code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts (1)

20-21: ⚖️ Poor tradeoff

Module-level mutable state couples configure and postConfigure implicitly.

Using module-scoped let variables to share state between lifecycle methods is fragile. If configure isn't called before postConfigure, or if the module is reused across multiple invocations without reinitializing, the state could be stale or undefined. Consider passing this data through a returned context object or storing it in a way that's explicitly scoped to the generator instance.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts` around lines
20 - 21, The module-level mutable variables lastMetroCodemodResult and
lastScriptDerivationResult create hidden coupling between configure and
postConfigure; instead refactor so configure returns (or stores in an
instance-scoped context) the results it computes and postConfigure accepts that
context as an argument (or the generator returns an object containing configure
and postConfigure bound to the same instance), remove the module-scoped lets,
and update callers to pass the returned context to postConfigure so state is
explicit and not shared across generator invocations.
code/lib/create-storybook/src/generators/REACT_NATIVE/index.test.ts (1)

150-172: 💤 Low value

Consider moving mock customization to a nested describe block with its own beforeEach.

The mock modification at line 155-157 happens inline within the test case. Per coding guidelines, mock implementations should be in beforeEach blocks rather than inline within test cases. You could wrap this test in a nested describe with its own beforeEach to configure the different getDependencyVersion behavior.

♻️ Suggested refactor
+  describe('when cross-env is already a dependency', () => {
+    beforeEach(() => {
+      // Override for this specific scenario
+    });
+
+    it('does not add cross-env', async () => {
+      const packageManager = createPackageManager({
+        ios: 'react-native run-ios',
+        android: 'react-native run-android',
+      });
+      packageManager.getDependencyVersion = vi.fn((dep: string) =>
+        dep === 'cross-env' ? '^7.0.3' : null
+      );
+      // ... rest of test
+    });
+  });

As per coding guidelines: "Avoid inline mock implementations within test cases in Vitest tests"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.test.ts` around
lines 150 - 172, Move the inline mock override of
packageManager.getDependencyVersion out of the it('does not add cross-env when
it is already a dependency') body by creating a nested describe block for this
scenario and adding a beforeEach that sets packageManager =
createPackageManager(...) and then assigns packageManager.getDependencyVersion =
vi.fn((dep: string) => dep === 'cross-env' ? '^7.0.3' : null); keep the test
body only calling reactNativeGenerator.configure(...) and the expect assertion
(remove the inline mock), ensuring the nested describe's beforeEach initializes
or resets DependencyCollector and other inputs the test relies on so state is
isolated for this case.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.ts`:
- Line 9: Replace the placeholder string in the exported constant
METRO_SETUP_DOCS_LINK with the official React Native Metro documentation URL;
locate the constant export (METRO_SETUP_DOCS_LINK) in the metroConfig.ts file
and update its value to the correct docs link (e.g., the canonical Metro bundler
docs or React Native Metro setup page) so consumers of METRO_SETUP_DOCS_LINK get
a valid reference before merging/release.

---

Nitpick comments:
In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.test.ts`:
- Around line 150-172: Move the inline mock override of
packageManager.getDependencyVersion out of the it('does not add cross-env when
it is already a dependency') body by creating a nested describe block for this
scenario and adding a beforeEach that sets packageManager =
createPackageManager(...) and then assigns packageManager.getDependencyVersion =
vi.fn((dep: string) => dep === 'cross-env' ? '^7.0.3' : null); keep the test
body only calling reactNativeGenerator.configure(...) and the expect assertion
(remove the inline mock), ensuring the nested describe's beforeEach initializes
or resets DependencyCollector and other inputs the test relies on so state is
isolated for this case.

In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts`:
- Around line 20-21: The module-level mutable variables lastMetroCodemodResult
and lastScriptDerivationResult create hidden coupling between configure and
postConfigure; instead refactor so configure returns (or stores in an
instance-scoped context) the results it computes and postConfigure accepts that
context as an argument (or the generator returns an object containing configure
and postConfigure bound to the same instance), remove the module-scoped lets,
and update callers to pass the returned context to postConfigure so state is
explicit and not shared across generator invocations.

In `@code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.ts`:
- Around line 34-38: hasStorybookPackage duplicates the package-check logic
already expressed in STORYBOOK_PACKAGE_PATTERNS; update hasStorybookPackage to
reference the constant instead of reimplementing the checks (e.g., use
STORYBOOK_PACKAGE_PATTERNS.some(...) or equivalent) so the pattern logic is
centralized and the catch-fallback still uses the same source of truth
(STORYBOOK_PACKAGE_PATTERNS) — modify the hasStorybookPackage function
accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ee79b61a-9654-4ce2-8363-93f012ad3ef1

📥 Commits

Reviewing files that changed from the base of the PR and between cf07244 and 265cfe4.

📒 Files selected for processing (11)
  • code/lib/create-storybook/src/generators/REACT_NATIVE/generateEntrypoint.test.ts
  • code/lib/create-storybook/src/generators/REACT_NATIVE/generateEntrypoint.ts
  • code/lib/create-storybook/src/generators/REACT_NATIVE/generateScripts.test.ts
  • code/lib/create-storybook/src/generators/REACT_NATIVE/generateScripts.ts
  • code/lib/create-storybook/src/generators/REACT_NATIVE/index.test.ts
  • code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts
  • code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.test.ts
  • code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.ts
  • code/lib/create-storybook/src/services/ProjectTypeService.test.ts
  • code/lib/create-storybook/src/services/ProjectTypeService.ts
  • code/lib/create-storybook/templates/react-native/index.js

Comment thread code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.ts Outdated
@storybook-app-bot
Copy link
Copy Markdown

storybook-app-bot Bot commented Apr 30, 2026

Package Benchmarks

Commit: 1330be2, ran on 5 May 2026 at 07:49:13 UTC

The following packages have significant changes to their size or dependencies:

@storybook/cli

Before After Difference
Dependency count 184 184 0
Self size 880 KB 880 KB 🚨 +8 B 🚨
Dependency size 68.28 MB 68.30 MB 🚨 +19 KB 🚨
Bundle Size Analyzer Link Link

create-storybook

Before After Difference
Dependency count 51 51 0
Self size 1.05 MB 1.07 MB 🚨 +18 KB 🚨
Dependency size 37.15 MB 37.15 MB 🚨 +2 KB 🚨
Bundle Size Analyzer node node

- Added tests to ensure correct behavior when the base script already sets STORYBOOK_ENABLED.
- Verified that explicit STORYBOOK_ENABLED=false is respected without overriding.
- Ensured STORYBOOK_ENABLED is injected correctly into existing cross-env and cross-env-shell prefixes.
- Included a test for trimming whitespace before applying the prefix.

These changes improve coverage and reliability of the script generation logic for React Native.

Fixes #34665 (comment)
@ndelangen ndelangen mentioned this pull request Apr 30, 2026
6 tasks
@ndelangen ndelangen requested review from JReinhold, dannyhw and valentinpalkovic and removed request for valentinpalkovic April 30, 2026 11:51
Comment thread code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts Outdated
Comment thread code/lib/create-storybook/templates/react-native/index.js
Comment thread code/lib/create-storybook/templates/react-native/index.js
Comment thread code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts
Comment thread code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts (1)

8-13: ⚠️ Potential issue | 🔴 Critical

Remove the duplicate generateReactNativeEntrypoint import on line 13.

Lines 8–11 already import generateReactNativeEntrypoint from './generateEntrypoint.ts'. The re-import on line 13 creates a duplicate identifier and will prevent compilation.

Fix
 import {
   type ReactNativeEntrypointTemplateVariant,
   generateReactNativeEntrypoint,
 } from './generateEntrypoint.ts';
 import { defineGeneratorModule } from '../modules/GeneratorModule.ts';
-import { generateReactNativeEntrypoint } from './generateEntrypoint.ts';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts` around lines
8 - 13, Remove the duplicate import of generateReactNativeEntrypoint (the second
import statement) so the module only imports generateReactNativeEntrypoint once
alongside ReactNativeEntrypointTemplateVariant; update the import block that
currently includes ReactNativeEntrypointTemplateVariant and
generateReactNativeEntrypoint and delete the redundant standalone
generateReactNativeEntrypoint import to avoid the duplicate identifier error.
🧹 Nitpick comments (1)
code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts (1)

103-117: ⚡ Quick win

Call the entrypoint generator only once.

The entrypoint is generated before templateVariant is known and then generated again with the derived variant. That first pass is redundant and may write the default variant before it gets overwritten.

Fix
-    await generateReactNativeEntrypoint({ language: context.language });
-
     const templateVariant: ReactNativeEntrypointTemplateVariant =
       detectReactNativeEntrypointTemplateVariant(packageManager.getAllDependencies());
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts` around lines
103 - 117, Remove the premature call to generateReactNativeEntrypoint so the
entrypoint is only created once after the template variant is known: run
runMetroCodemodOrFallback(...), call
detectReactNativeEntrypointTemplateVariant(packageManager.getAllDependencies()),
then invoke generateReactNativeEntrypoint({ language: context.language,
templateVariant }) (i.e., delete or move the earlier
generateReactNativeEntrypoint call so only the later call with the derived
templateVariant remains).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts`:
- Around line 8-13: Remove the duplicate import of generateReactNativeEntrypoint
(the second import statement) so the module only imports
generateReactNativeEntrypoint once alongside
ReactNativeEntrypointTemplateVariant; update the import block that currently
includes ReactNativeEntrypointTemplateVariant and generateReactNativeEntrypoint
and delete the redundant standalone generateReactNativeEntrypoint import to
avoid the duplicate identifier error.

---

Nitpick comments:
In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts`:
- Around line 103-117: Remove the premature call to
generateReactNativeEntrypoint so the entrypoint is only created once after the
template variant is known: run runMetroCodemodOrFallback(...), call
detectReactNativeEntrypointTemplateVariant(packageManager.getAllDependencies()),
then invoke generateReactNativeEntrypoint({ language: context.language,
templateVariant }) (i.e., delete or move the earlier
generateReactNativeEntrypoint call so only the later call with the derived
templateVariant remains).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f835b8e2-ac60-4ca2-9960-18f9a5ceabbd

📥 Commits

Reviewing files that changed from the base of the PR and between 6e88eac and 3dfb684.

📒 Files selected for processing (4)
  • code/lib/create-storybook/src/generators/REACT_NATIVE/index.test.ts
  • code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts
  • code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.test.ts
  • code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • code/lib/create-storybook/src/generators/REACT_NATIVE/index.test.ts
  • code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts (1)

102-115: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Duplicate generateReactNativeEntrypoint call.

generateReactNativeEntrypoint is called twice: once on line 102 without templateVariant, and again on lines 112-115 with templateVariant. The first call appears redundant since the second call immediately overwrites the generated entrypoint with the correct variant-specific template.

🔧 Suggested fix: remove the redundant first call
-    await generateReactNativeEntrypoint({ language: context.language });
-
     lastMetroCodemodResult = await runMetroCodemodOrFallback({
       packageManager,
       yes: !!context.yes,
     });

     const templateVariant: ReactNativeEntrypointTemplateVariant =
       detectReactNativeEntrypointTemplateVariant(packageManager.getAllDependencies());

     await generateReactNativeEntrypoint({
       language: context.language,
       templateVariant,
     });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts` around lines
102 - 115, The file calls generateReactNativeEntrypoint twice — once before
detecting the template variant and once after — causing the first generated file
to be immediately overwritten; remove the redundant first call (the await
generateReactNativeEntrypoint({ language: context.language }) placed before
runMetroCodemodOrFallback) so that generateReactNativeEntrypoint is only invoked
once after you compute templateVariant via
detectReactNativeEntrypointTemplateVariant(packageManager.getAllDependencies()),
keeping the runMetroCodemodOrFallback call and lastMetroCodemodResult intact.
🧹 Nitpick comments (1)
code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts (1)

23-24: 💤 Low value

Module-level state for cross-phase communication.

The module-level variables lastMetroCodemodResult and lastScriptDerivationResult are used to share state between configure and postConfigure. This pattern works within the generator lifecycle but could retain stale values if the module is reused across multiple init runs without process restart. Consider whether this is acceptable for your testing/CLI reuse scenarios.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts` around lines
23 - 24, The module-level variables lastMetroCodemodResult and
lastScriptDerivationResult are being used to pass data between configure and
postConfigure which can leak stale state across multiple runs; change the flow
to avoid module-level state by returning the results from configure (or
attaching them to the generator execution context/options) and then reading that
return/context in postConfigure, or if returning isn’t possible, explicitly
reset/clear those variables at the end of postConfigure; update references to
lastMetroCodemodResult and lastScriptDerivationResult in the configure and
postConfigure implementations so they use the passed/attached values (or are
cleared) instead of relying on module scope.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts`:
- Around line 102-115: The file calls generateReactNativeEntrypoint twice — once
before detecting the template variant and once after — causing the first
generated file to be immediately overwritten; remove the redundant first call
(the await generateReactNativeEntrypoint({ language: context.language }) placed
before runMetroCodemodOrFallback) so that generateReactNativeEntrypoint is only
invoked once after you compute templateVariant via
detectReactNativeEntrypointTemplateVariant(packageManager.getAllDependencies()),
keeping the runMetroCodemodOrFallback call and lastMetroCodemodResult intact.

---

Nitpick comments:
In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts`:
- Around line 23-24: The module-level variables lastMetroCodemodResult and
lastScriptDerivationResult are being used to pass data between configure and
postConfigure which can leak stale state across multiple runs; change the flow
to avoid module-level state by returning the results from configure (or
attaching them to the generator execution context/options) and then reading that
return/context in postConfigure, or if returning isn’t possible, explicitly
reset/clear those variables at the end of postConfigure; update references to
lastMetroCodemodResult and lastScriptDerivationResult in the configure and
postConfigure implementations so they use the passed/attached values (or are
cleared) instead of relying on module scope.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f6bfc79c-9a7b-4471-8f84-52d423643eaa

📥 Commits

Reviewing files that changed from the base of the PR and between 3dfb684 and 015ed85.

📒 Files selected for processing (4)
  • code/lib/create-storybook/src/generators/REACT_NATIVE/index.test.ts
  • code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts
  • code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.test.ts
  • code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.ts
✅ Files skipped from review due to trivial changes (1)
  • code/lib/create-storybook/src/generators/REACT_NATIVE/metroConfig.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • code/lib/create-storybook/src/generators/REACT_NATIVE/index.test.ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts (1)

103-116: ⚡ Quick win

Redundant entrypoint generation calls.

generateReactNativeEntrypoint is called twice: first at line 103 without templateVariant, then again at lines 113-116 with the detected variant. The second call overwrites the first. Move the detectReactNativeEntrypointTemplateVariant call before line 103 to consolidate into a single generation.

♻️ Proposed consolidation
+    const templateVariant: ReactNativeEntrypointTemplateVariant =
+      detectReactNativeEntrypointTemplateVariant(packageManager.getAllDependencies());
+
+    await generateReactNativeEntrypoint({
+      language: context.language,
+      templateVariant,
+    });
-    await generateReactNativeEntrypoint({ language: context.language });

     lastMetroCodemodResult = await runMetroCodemodOrFallback({
       packageManager,
       yes: !!context.yes,
     });

-    const templateVariant: ReactNativeEntrypointTemplateVariant =
-      detectReactNativeEntrypointTemplateVariant(packageManager.getAllDependencies());
-
-    await generateReactNativeEntrypoint({
-      language: context.language,
-      templateVariant,
-    });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts` around lines
103 - 116, There are two calls to generateReactNativeEntrypoint; remove the
first call and call detectReactNativeEntrypointTemplateVariant once before
generating the entrypoint so you only invoke generateReactNativeEntrypoint once
with the detected templateVariant. Specifically, call
detectReactNativeEntrypointTemplateVariant(packageManager.getAllDependencies())
earlier (before the initial generateReactNativeEntrypoint), then run
runMetroCodemodOrFallback as required, and finally call
generateReactNativeEntrypoint({ language: context.language, templateVariant })
once; delete the duplicate generateReactNativeEntrypoint invocation and keep
uses of context.language and context.yes as before.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts`:
- Around line 103-116: There are two calls to generateReactNativeEntrypoint;
remove the first call and call detectReactNativeEntrypointTemplateVariant once
before generating the entrypoint so you only invoke
generateReactNativeEntrypoint once with the detected templateVariant.
Specifically, call
detectReactNativeEntrypointTemplateVariant(packageManager.getAllDependencies())
earlier (before the initial generateReactNativeEntrypoint), then run
runMetroCodemodOrFallback as required, and finally call
generateReactNativeEntrypoint({ language: context.language, templateVariant })
once; delete the duplicate generateReactNativeEntrypoint invocation and keep
uses of context.language and context.yes as before.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 29741652-6d2e-4489-9dd0-228e3915f395

📥 Commits

Reviewing files that changed from the base of the PR and between 015ed85 and cceffd7.

📒 Files selected for processing (1)
  • code/lib/create-storybook/src/generators/REACT_NATIVE/index.ts

@ndelangen ndelangen merged commit 404e426 into next May 5, 2026
123 checks passed
@ndelangen ndelangen deleted the norbert/m3-generator-orchestration branch May 5, 2026 08:49
@github-actions github-actions Bot mentioned this pull request May 5, 2026
10 tasks
@ndelangen ndelangen changed the title CLI: New ReactNative init setup ReactNative: New init setup May 5, 2026
@ndelangen ndelangen added feature request and removed maintenance User-facing maintenance tasks labels May 5, 2026
@github-actions github-actions Bot mentioned this pull request May 5, 2026
14 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants