expo-migrate-module

Migrates Swift Expo native modules from the 1.0 definition DSL to the 2.0 macro API.

Updated Sep 11, 2026
One-click install
npx skills add https://github.com/CYRUS-pinto/pi-bot --skill expo-migrate-module-cyrus-pinto
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: expo-migrate-module
Source: https://github.com/CYRUS-pinto/pi-bot/tree/main/.agents/skills/expo-migrate-module
Command: npx skills add https://github.com/CYRUS-pinto/pi-bot --skill expo-migrate-module-cyrus-pinto

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill includes references (resource) components.

What problem does it solve? Migrating an existing Expo native module from the Expo Modules API 1.0 definition DSL to the 2.0 macro API is error-prone: macro defaults can silently rename events, change record requiredness, or move blocking work onto the JS thread, breaking the JavaScript contract. This Skill provides a verified, incremental migration workflow that preserves the observable JS/TypeScript API. ## Core Features & Use Cases - Contract-preserving migration: Inventories every exported member (functions, properties, constants, events, records, shared objects) and migrates them group by group while keeping JS names, arity, defaults, and sync/async behavior stable. - Compatibility verification: Checks the actually installed expo-modules-core and macro declarations instead of trusting SDK version numbers, classifying each member as Migrate, Keep in DSL, or Blocked. - Mixed-mode support: Allows @ExpoModule to coexist with a non-empty definition() so unsupported members (views, queue-pinned functions, sync events) stay safely on the 1.0 DSL. - Use Case: You maintain an Expo module written with Name(), Function(), AsyncFunction(), and Events() and want to adopt @ExpoModule, @JS, @Event, and @Record incrementally without breaking existing JS call sites or tests. ## Quick Start Use the expo-migrate-module skill to migrate this module's Swift implementation from the 1.0 definition DSL to the 2.0 macro API without changing its JavaScript contract.

Frequently Asked Questions about expo-migrate-module

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I migrate an Expo module from the 1.0 DSL to the 2.0 macro API?

Inventory every exported member first, then migrate one semantic group at a time: module naming, functions, properties, events, shared objects, and records. Verify macro and core support in the checked-out expo-modules-core before each group, and keep unsupported members in the 1.0 definition() block.

What Expo version is required for the Modules API 2.0 macros?

The 2.0 macros require expo 57.0.7 or newer. Check the installed version in package.json or with npm ls expo before editing, and still verify the checked-out source because macro and core support varies within 57.x releases.

Can @ExpoModule coexist with the 1.0 definition() DSL?

Yes, mixed mode is supported when the paired core merges both surfaces. Keep unsupported entries like views, queue-pinned functions, or sync events in definition(), avoid duplicate names across macro and DSL registrations, and delete definition() only when it is empty.

Why does my event name change after migrating to @Event?

The default @Event wire name strips a leading 'on' and decapitalizes the remainder, so onProgress becomes progress. Pass the original wire name explicitly, such as @Event("onProgress"), to preserve the existing JS listener contract.

When should I not migrate a 1.0 AsyncFunction to a 2.0 async method?

Do not migrate queue-pinned functions or blocking bodies as-is, because 2.0 async members start on the JS actor instead of a background queue. Restructure with Swift Concurrency or dispatch to the original queue inside a checked continuation, or keep the function on the DSL.

Does this migration cover Android Kotlin modules or new module creation?

No, the scope is limited to existing Apple/Swift modules. Kotlin stays on the 1.0 DSL unless explicitly requested, and the workflow is not intended for creating new modules or general Expo SDK upgrades.