Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .ai/context/current-state.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Upgrade State

sdk: 54
target_sdk: 55
target_expo: 55.0.14
target_react: 19.2.0
target_rn: 0.83.4
phase: step6_cli_updated

## Completed

- Step 0: Target version resolved (SDK 55 / 55.0.14)
- Step 1: Changelogs read (Expo SDK 55 + RN 0.83)
- Step 2: Template project package.json updated (all expo-* to 55.x.x exact versions)
- Step 2b: app.json updated (removed newArchEnabled)
- Step 3: Codegen root — no changes needed
- Step 4: Runtime package.json updated, builds pass (snapshot tests deferred)
- Step 4b: Codegen build passes
- Step 5: Template verification — deferred to user
- Step 6: CLI updated (expo-launcher.js, requirements.js, packageLock.json)

## Key Changes

- All expo-* packages now use major version 55 (new versioning scheme)
- expo-av removed (no expo-av@^55 exists, replaced by expo-video + expo-audio)
- Legacy Architecture dropped (newArchEnabled removed from app.json)
- RN 0.83 has zero breaking changes
- Node.js minimum bumped to 20.19.4
- CLI version checks now use semver.gte for forward compatibility

## Next

- Step 7: Breaking changes review
- Step 8: Final cross-repo validation

## Blocking Issues

- expo-av removal needs runtime source code review
- expo-navigation-bar deprecations need runtime review
- 157 snapshot test failures (expected, can update with npm test -- -u)
14 changes: 14 additions & 0 deletions .cursor/rules/expo-upgrade-workflow.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
description: Expo SDK upgrade workflow rules
globs:
alwaysApply: false
---

# Expo Upgrade Workflow

- Changelog URL: `https://expo.dev/changelog/sdk-{MAJOR}` (never full semver in URL).
- When RN version changes, `@react-native/*` scoped packages must match the new RN version.
- Run `scripts/validate-versions.sh` to check cross-repo version alignment before finalizing.
- After updating runtime, run `npm run build` (yalc-publishes automatically) before verifying template.
- Do NOT auto-apply breaking change fixes. Present findings to user, wait for confirmation.
- Use `npx expo install --fix` in the template project to determine SDK-compatible module versions.
20 changes: 20 additions & 0 deletions .cursor/rules/npm-registry-verification.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
description: Verify npm package versions exist before updating package.json
globs: **/package.json
alwaysApply: false
---

# NPM Registry Verification

**Before changing ANY package version in ANY `package.json`, verify the exact version exists on the npm registry.**

Run the following check for every package version change:

```bash
npm view <package-name>@<version> version
```

- If the command returns the version, it exists — proceed.
- If the command returns an error or empty result, the version does NOT exist — do not use it.
- When unsure of the exact version, list available versions with `npm view <package-name> versions --json` and pick the closest compatible one.
- NEVER write a version into `package.json` without confirming it is published on npm.
13 changes: 13 additions & 0 deletions .cursor/rules/platform.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
description: WaveMaker React Native platform engineering constraints
alwaysApply: true
---

# WaveMaker RN Platform Rules

- Generated Expo apps must NOT be edited directly. All changes originate from codegen templates or runtime source.
- Three repos must stay in sync: `wavemaker-rn-codegen` (template), `wavemaker-rn-runtime`, `wm-reactnative-cli`.
- Template uses `file:.yalc/...` for `@wavemaker/app-rn-runtime`, `@wavemaker/variables`, `@wavemaker/rn-codegen` — these are local dev links, not npm versions.
- Build order: runtime → codegen → verify template → CLI.
- Shared dependencies (`react`, `react-native`, `expo-*`, `react-native-*`, `@react-navigation/*`) must have identical versions across all repos.
- Prefer scripts over manual commands. Check `scripts/` before writing inline bash.
127 changes: 127 additions & 0 deletions .cursor/upgrading-expo/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
---
name: upgrading-expo
description: Upgrade Expo SDK across WaveMaker RN ecosystem
version: 6.0.0
---

## References

- ./references/common/new-architecture.md -- SDK +53
- ./references/common/react-19.md -- SDK +54
- ./references/common/react-compiler.md -- SDK +54

## Context

- State tracker: `.ai/context/current-state.md` — read at start, update after each phase.
- Platform rules auto-loaded from `.cursor/rules/platform.mdc`.

## Version Resolution Strategy

**Compatibility first. Do not blindly upgrade to latest.** Pick versions that are known to be compatible with the target Expo SDK and React Native version:

1. Resolve the target Expo release first (`EXPO_TARGET_VERSION`) and use Expo's compatibility set as the source of truth for `expo-*` and tightly-coupled RN ecosystem packages.
2. For `expo-*` packages: prefer versions from `expo@<target>.bundledNativeModules` (or `expo@<target>` dependencies when bundled data is missing) instead of latest npm versions.
3. For all other packages (`react-native-*`, `@react-native/*`, `@react-navigation/*`, community packages, etc.): choose the highest version whose peer dependencies include the target `react`, `react-native`, and `expo` ranges. Do not choose a version only because it is newest.
4. For transitive deps that are also direct deps (e.g. `expo-modules-core`): match the version required by `expo@<target>`.
5. **Exception — `@react-native/*` scoped packages**: must match the React Native version line (e.g. `@react-native/assets-registry@0.83.x` for RN `0.83.x`).
6. Pin exact versions (no `~` or `^`) unless the user says otherwise.
7. Ignore upgrading this package versions (`victory-native`).

### Stability Gate

Only use a package version that has been published for **at least 5 days**. Check publish date with:
```bash
npm view <pkg>@<version> time --json | grep '<version>'
```
If the version was published less than 5 days ago, fall back to the previous stable version that meets the 5-day threshold. This avoids adopting freshly-published versions that may have undiscovered issues.

### Compatibility Verification

Before finalizing versions, verify each package's peer dependencies include the target `expo`, `react`, and `react-native` versions. Batch-check with:
```bash
npm view <pkg>@<version> peerDependencies --json
```
If a peer says `react-native: "0.84 - 0.86"` but we target `0.83`, that version is **not compatible** — find the highest version whose peer range includes `0.83`.

After dependency updates in template/generated app, run:
```bash
npx expo-doctor
npx expo install --fix
```
Use these as mandatory compatibility checks to align package versions with Expo expectations.

### Handling Peer Dependency Conflicts

- **Never use `--legacy-peer-deps`** for `npm install`. Instead, resolve peer conflicts properly by adding the conflicting resolution to the `"overrides"` section in `package.json` to force the desired version.
- Only fall back to an older version if the latest causes **runtime errors** (not just peer warnings).
- Document any overrides added in the upgrade state tracker.

## Step 0: Get Target Version

Ask user for target SDK. Resolve `EXPO_SDK_MAJOR` and `EXPO_TARGET_VERSION` (`npm view expo@^{MAJOR} version`). Run `bash ./scripts/resolve-expo-versions.sh <MAJOR>` to discover available versions for all expo-* packages. Update `.ai/context/current-state.md`.

## Step 1: Read Changelogs

Fetch `https://expo.dev/changelog/sdk-{EXPO_SDK_MAJOR}` (major only in URL). Extract: expo/react/RN versions, breaking changes, module updates.

Find RN blog post from Expo changelog or `https://reactnative.dev/blog`. When RN version changes, `@react-native/*` scoped packages must match.

## Step 2: Update Template Project (CONFIRM before next step)

Path: `wavemaker-rn-codegen/src/templates/project/`

- **`package.json`**: Update core versions + all deps. Read file for full list. Follow **Version Resolution Strategy** above. Check `overrides`. Include `expo-modules-core` as a direct dependency. **Before removing any package**, search all three repos for imports/usages; if found, notify user and wait for confirmation before removing.
- **`app.json`**: Check plugins, deprecated keys, `newArchEnabled`/`jsEngine`.
- **`metro.config.js`**: Check `expo/metro-config` API, transformer, SVG transformer compat.
- **Other**: Check `plugins/expo-screen-capture-plugin/package.json` peer dep.

**After updating, Wait for explicit confirmation before proceeding to Step 3.**

## Step 3: Update Codegen Root (CONFIRM before next step)

`wavemaker-rn-codegen/package.json` — review `@babel/*` and tooling deps.

**After updating, Wait for confirmation before proceeding to Step 4.**

## Step 4: Update Runtime (CONFIRM before next step)

`wavemaker-rn-runtime/package.json` — match all shared deps to template. Read file for full list.

**After updating, Wait for explicit confirmation before proceeding to build.**

### Build & yalc-publish

```bash
cd wavemaker-rn-runtime && npm install && npm run build && npm test
cd wavemaker-rn-codegen && npm install && npm run build && npm test
```

## Step 5: Update CLI (CONFIRM before next step)

- **`templates/package/packageLock.json`**: Regenerate from template project (`npm install --package-lock-only`), copy here.
- **`src/requirements.js`**: Update version floors (e.g. Node.js minimum from Expo changelog).
- **`src/expo-launcher.js`**: Add new SDK version handling. Use `semver.gte(semver.coerce(...))` for forward-compatible checks. Review `updatePackageJsonFile()`, `updateReanimatedPlugin()`, `barcodePort`.

**After updating, Wait for confirmation before proceeding to Step 6.**

## Step 6: Verify Template (BLOCKING)

Run `./scripts/run.sh --help` for commands. Verification types:
1. Web preview (expo) — `./scripts/run.sh web-preview <url> --clean`
2. Web preview (esbuild) — `./scripts/run.sh web-preview <url> --esbuild --clean`
3. Sync (Expo Go) — `./scripts/run.sh sync <url> --clean`
4. Android build — `./scripts/run.sh build android <src>`
5. iOS build — `./scripts/run.sh build ios <src>`

**This step is a gate. Do NOT proceed to Step 7 until the user explicitly provides pass/fail status for web-preview, sync, and build.** Ask the user for results and wait. If any verification fails, diagnose and fix in earlier steps, rebuild, and re-verify before moving on.

## Step 7: Breaking Changes

Search all three repos for affected code. Present to user with proposed fix. **Wait for confirmation before applying.**

## Step 8: Final Validation

Run `bash ./scripts/validate-versions.sh` for cross-repo alignment. Then: runtime build+test, codegen build+test, CLI e2e test.

Update `.ai/context/current-state.md` with final status.
Once upgrade is completed, update the user.
79 changes: 79 additions & 0 deletions .cursor/upgrading-expo/references/common/new-architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# New Architecture

The New Architecture is enabled by default in Expo SDK 53+. It replaces the legacy bridge with a faster, synchronous communication layer between JavaScript and native code.

## Documentation

Full guide: https://docs.expo.dev/guides/new-architecture/

## What Changed

- **JSI (JavaScript Interface)** — Direct synchronous calls between JS and native
- **Fabric** — New rendering system with concurrent features
- **TurboModules** — Lazy-loaded native modules with type safety

## SDK Compatibility

| SDK Version | New Architecture Status |
| ----------- | ----------------------- |
| SDK 53+ | Enabled by default |
| SDK 52 | Opt-in via app.json |
| SDK 51- | Experimental |

## Configuration

New Architecture is enabled by default. To explicitly disable (not recommended):

```json
{
"expo": {
"newArchEnabled": false
}
}
```

## Expo Go

Expo Go only supports the New Architecture as of SDK 53. Apps using the old architecture must use development builds.

## Common Migration Issues

### Native Module Compatibility

Some older native modules may not support the New Architecture. Check:

1. Module documentation for New Architecture support
2. GitHub issues for compatibility discussions
3. Consider alternatives if module is unmaintained

### Reanimated

React Native Reanimated requires `react-native-worklets` in SDK 54+:

```bash
npx expo install react-native-worklets
```

### Layout Animations

Some layout animations behave differently. Test thoroughly after upgrading.

## Verifying New Architecture

Check if New Architecture is active:

```tsx
import { Platform } from "react-native";

// Returns true if Fabric is enabled
const isNewArch = global._IS_FABRIC !== undefined;
```

Verify from the command line if the currently running app uses the New Architecture: `bunx xcobra expo eval "_IS_FABRIC"` -> `true`

## Troubleshooting

1. **Clear caches** — `npx expo start --clear`
2. **Clean prebuild** — `npx expo prebuild --clean`
3. **Check native modules** — Ensure all dependencies support New Architecture
4. **Review console warnings** — Legacy modules log compatibility warnings
79 changes: 79 additions & 0 deletions .cursor/upgrading-expo/references/common/react-19.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# React 19

React 19 is included in Expo SDK 54. This release simplifies several common patterns.

## Context Changes

### useContext → use

The `use` hook replaces `useContext`:

```tsx
// Before (React 18)
import { useContext } from "react";
const value = useContext(MyContext);

// After (React 19)
import { use } from "react";
const value = use(MyContext);
```

- The `use` hook can also read promises, enabling Suspense-based data fetching.
- `use` can be called conditionally, this simplifies components that consume multiple contexts.

### Context.Provider → Context

Context providers no longer need the `.Provider` suffix:

```tsx
// Before (React 18)
<ThemeContext.Provider value={theme}>
{children}
</ThemeContext.Provider>

// After (React 19)
<ThemeContext value={theme}>
{children}
</ThemeContext>
```

## ref as a Prop

### Removing forwardRef

Components can now receive `ref` as a regular prop. `forwardRef` is no longer needed:

```tsx
// Before (React 18)
import { forwardRef } from "react";

const Input = forwardRef<TextInput, Props>((props, ref) => {
return <TextInput ref={ref} {...props} />;
});

// After (React 19)
function Input({ ref, ...props }: Props & { ref?: React.Ref<TextInput> }) {
return <TextInput ref={ref} {...props} />;
}
```

### Migration Steps

1. Remove `forwardRef` wrapper
2. Add `ref` to the props destructuring
3. Update the type to include `ref?: React.Ref<T>`

## Other React 19 Features

- **Actions** — Functions that handle async transitions
- **useOptimistic** — Optimistic UI updates
- **useFormStatus** — Form submission state (web)
- **Document Metadata** — Native `<title>` and `<meta>` support (web)

## Cleanup Checklist

When upgrading to SDK 54:

- [ ] Replace `useContext` with `use`
- [ ] Remove `.Provider` from Context components
- [ ] Remove `forwardRef` wrappers, use `ref` prop instead
Loading