expo-codemod 1.1.6 → 56.0.0

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.
Files changed (36) hide show
  1. package/README.md +75 -102
  2. package/bin/expo-codemod.js +1 -6
  3. package/build/index.d.ts +1 -0
  4. package/build/index.js +70 -0
  5. package/build/index.js.map +1 -0
  6. package/build/log.d.ts +6 -0
  7. package/build/log.js +41 -0
  8. package/build/log.js.map +1 -0
  9. package/build/run/index.d.ts +17 -0
  10. package/build/run/index.js +136 -0
  11. package/build/run/index.js.map +1 -0
  12. package/build/transforms/index.d.ts +3 -0
  13. package/build/transforms/index.js +23 -0
  14. package/build/transforms/index.js.map +1 -0
  15. package/build/transforms/sdk-56-expo-router-react-navigation-replace.d.ts +14 -0
  16. package/build/transforms/sdk-56-expo-router-react-navigation-replace.js +106 -0
  17. package/build/transforms/sdk-56-expo-router-react-navigation-replace.js.map +1 -0
  18. package/build/utils/args.d.ts +3 -0
  19. package/build/utils/args.js +73 -0
  20. package/build/utils/args.js.map +1 -0
  21. package/build/utils/runner.d.ts +7 -0
  22. package/build/utils/runner.js +23 -0
  23. package/build/utils/runner.js.map +1 -0
  24. package/package.json +34 -24
  25. package/build/cli.d.ts +0 -1
  26. package/build/cli.js +0 -106
  27. package/build/cli.js.map +0 -1
  28. package/build/transforms/sdk33-imports.d.ts +0 -2
  29. package/build/transforms/sdk33-imports.js +0 -174
  30. package/build/transforms/sdk33-imports.js.map +0 -1
  31. package/build/transforms/sdk37-imports.d.ts +0 -2
  32. package/build/transforms/sdk37-imports.js +0 -66
  33. package/build/transforms/sdk37-imports.js.map +0 -1
  34. package/build/transforms/sdk41-async-storage.d.ts +0 -2
  35. package/build/transforms/sdk41-async-storage.js +0 -47
  36. package/build/transforms/sdk41-async-storage.js.map +0 -1
package/README.md CHANGED
@@ -1,143 +1,116 @@
1
- # expo-codemod
2
-
3
- `expo-codemod` is collection of codemods (transforms) for projects using the Expo SDK and a small command-line interface (CLI) for running the codemods.
4
-
5
- The codemods can be used to transform JavaScript (.js, .jsx) and TypeScript (.ts, .tsx) files.
6
-
7
- ## Installation
8
-
9
- You can run `expo-codemod` using `npx` without having to install it (Node.js 8.x, 10.x or 12.x is required):
10
-
11
- ```
12
- npx expo-codemod
13
- ```
14
-
15
- Alternatively, you can install it globally:
1
+ <!-- Title -->
2
+
3
+ <h1 align="center">expo-codemod</h1>
4
+
5
+ <p align="center">CLI and jscodeshift codemods for migrating Expo apps between SDK versions</p>
6
+
7
+ <p align="center">
8
+ <a aria-label="expo documentation" href="https://docs.expo.dev/router/introduction/">📚 Read the Documentation</a>
9
+ &ensp;•&ensp;
10
+ <a aria-label="expo blog" href="https://expo.dev/blog">Learn more on our blog</a>
11
+ &ensp;•&ensp;
12
+ <a aria-label="Contribute to expo-codemod" href="#contributing">Contribute to expo-codemod</a>
13
+ </p>
14
+
15
+ <p align="center">
16
+ <a aria-label="Join the Expo Discord" href="https://discord.gg/4gtbPAdpaE" target="_blank">
17
+ <img alt="Discord" src="https://img.shields.io/discord/695411232856997968.svg?style=for-the-badge&color=5865F2&logo=discord&logoColor=FFFFFF" />
18
+ </a>
19
+ </p>
20
+
21
+ <p align="center">
22
+ <a aria-label="Follow @expo on X" href="https://x.com/intent/follow?screen_name=expo" target="_blank">
23
+ <img alt="Expo on X" src="https://img.shields.io/badge/X-000000?style=for-the-badge&logo=x&logoColor=white" target="_blank" />
24
+ </a>&nbsp;
25
+ <a aria-label="Follow @expo on GitHub" href="https://github.com/expo" target="_blank">
26
+ <img alt="Expo on GitHub" src="https://img.shields.io/badge/GitHub-222222?style=for-the-badge&logo=github&logoColor=white" target="_blank" />
27
+ </a>&nbsp;
28
+ <a aria-label="Follow @expo on Reddit" href="https://www.reddit.com/r/expo/" target="_blank">
29
+ <img alt="Expo on Reddit" src="https://img.shields.io/badge/Reddit-FF4500?style=for-the-badge&logo=reddit&logoColor=white" target="_blank" />
30
+ </a>&nbsp;
31
+ <a aria-label="Follow @expo on Bluesky" href="https://bsky.app/profile/expo.dev" target="_blank">
32
+ <img alt="Expo on Bluesky" src="https://img.shields.io/badge/Bluesky-1DA1F2?style=for-the-badge&logo=bluesky&logoColor=white" target="_blank" />
33
+ </a>&nbsp;
34
+ <a aria-label="Follow @expo on LinkedIn" href="https://www.linkedin.com/company/expo-dev" target="_blank">
35
+ <img alt="Expo on LinkedIn" src="https://img.shields.io/badge/LinkedIn-0077B5?style=for-the-badge&logo=LinkedIn&logoColor=white" target="_blank" />
36
+ </a>
37
+
38
+ <p align="center">⭐️ Be sure to star the Expo GitHub repo if you enjoy using the project! ⭐️</p>
39
+ </p>
40
+
41
+ ---
42
+
43
+ The `expo-codemod` package is a CLI binary provided to help you upgrade between Expo SDK versions.
16
44
 
17
45
  ```
18
- npm install --global expo-codemod
46
+ npx expo-codemod <transform> <paths...>
19
47
  ```
20
48
 
21
- (Installing with `yarn global add` works too.)
22
-
23
49
  ## Usage
24
50
 
51
+ Run a transform against one or more paths or globs:
52
+
25
53
  ```sh
26
54
  npx expo-codemod <transform> <paths...>
27
55
  ```
28
56
 
29
57
  ```
30
58
  Options:
31
- <transform> (required) name of transform to apply to files
32
- (see a list of transforms available below)
33
- <paths...> one or more paths or globs (e.g. src/**/*.js) of sources to transform
34
- files in .gitignore are ignored by default
35
- -h, --help print this help message
36
- -p, --parser <babel|flow|ts|tsx> parser to use to parse the source files
37
- (default: babel, ts or tsx based on the file extension)
38
-
39
- Transforms available:
40
- sdk33-imports
41
- sdk37-imports
42
- sdk41-async-storage
59
+ <transform> (required) name of transform to apply to files
60
+ (see a list of transforms available below)
61
+ <paths...> one or more paths or globs (e.g. src/**/*.tsx) of sources to transform
62
+ -h, --help print this help message
63
+ -v, --version print the CLI version
43
64
  ```
44
65
 
45
- For example, to apply the `sdk33-imports` transform to all source files in the `src` folder, run:
46
-
47
- ```
48
- npx expo-codemod sdk33-imports src
49
- ```
50
-
51
- You can also use glob patterns (make sure to wrap the patterns in quotes):
52
-
53
- ```
54
- npx expo-codemod sdk33-imports '**/*.js' '**/*.{ts,tsx}'
55
- ```
56
-
57
- ### Advanced usage with jscodeshift
58
-
59
- The CLI is a wrapper over [jscodeshift](https://github.com/facebook/jscodeshift). If you need more fine grained control of jscodeshift or parser options, you can also use the jscodeshift CLI directly. First install `expo-codemod` and `jscodeshift`:
66
+ For example, to run a transform over everything under `src`:
60
67
 
61
68
  ```sh
62
- npm install --save-dev expo-codemod
63
- npm install --global jscodeshift
69
+ npx expo-codemod sdk-56-expo-router-react-navigation-replace src
64
70
  ```
65
71
 
66
- You can pass the transform filename to jscodeshift using the `--transform` option, for example:
72
+ Globs work too (wrap them in quotes so the shell doesn't expand them):
67
73
 
68
74
  ```sh
69
- jscodeshift --transform ./node_modules/expo-codemod/build/transforms/sdk33-imports.js --no-babel --ignore-config .gitignore .
75
+ npx expo-codemod sdk-56-expo-router-react-navigation-replace '**/*.{ts,tsx,js,jsx}'
70
76
  ```
71
77
 
72
- Read more about jscodeshift options [here](https://github.com/facebook/jscodeshift#usage-cli).
73
-
74
- ## Troubleshooting
75
-
76
- ### Custom babel.config.js not being used
77
-
78
- As per [#676](https://github.com/expo/expo-cli/issues/676#issuecomment-505793327) you can pass in the `--parser=flow` option.
79
-
80
78
  ## Transforms
81
79
 
82
- ### `sdk33-imports`
83
-
84
- _Used to migrate a project from SDK 32 to SDK 33._
85
-
86
- Transforms imports from the `expo` package that were deprecated in Expo SDK 33 to imports from the individual packages.
87
-
88
- #### Example
89
-
90
- Input:
91
-
92
- ```js
93
- import { Accelerometer, GestureHandler, MapView } from 'expo';
94
- ```
95
-
96
- Output:
80
+ ### `sdk-56-expo-router-react-navigation-replace`
97
81
 
98
- ```js
99
- import { Accelerometer } from 'expo-sensors';
100
- import * as GestureHandler from 'react-native-gesture-handler';
101
- import MapView from 'react-native-maps';
102
- ```
82
+ _Used to migrate a React Navigation app to Expo Router (SDK 56)._
103
83
 
104
- ### `sdk37-imports`
84
+ Replaces imports from `@react-navigation/*` with their `expo-router` equivalents.
105
85
 
106
- _Used to migrate a project from SDK 36 to SDK 37._
86
+ | From | To |
87
+ | ----------------------------------- | -------------------------- |
88
+ | `@react-navigation/native` | `expo-router` |
89
+ | `@react-navigation/stack` | `expo-router/js-stack` |
90
+ | `@react-navigation/bottom-tabs` | `expo-router/js-tabs` |
91
+ | `@react-navigation/material-top-tabs` | `expo-router/js-top-tabs` |
107
92
 
108
- Transforms imports of `AuthSession` and `ScreenOrientation` that were extracted out from the `expo` package to `expo-auth-session` and `expo-screen-orientation` packages for SDK 37.
93
+ Default and namespace imports (`import X from ...` / `import * as X from ...`) from the mapped packages are not supported.
109
94
 
110
95
  #### Example
111
96
 
112
97
  Input:
113
98
 
114
- ```js
115
- import { AuthSession, ScreenOrientation } from 'expo';
99
+ ```ts
100
+ import { NavigationContainer, useNavigation } from '@react-navigation/native';
101
+ import { useRouter } from 'expo-router';
116
102
  ```
117
103
 
118
104
  Output:
119
105
 
120
- ```js
121
- import * as AuthSession from 'expo-auth-session';
122
- import * as ScreenOrientation from 'expo-screen-orientation';
106
+ ```ts
107
+ import { NavigationContainer, useNavigation, useRouter } from "expo-router";
123
108
  ```
124
109
 
125
- ### `sdk41-async-storage`
126
-
127
- _Used to migrate a project from SDK 40 to SDK 41._
128
-
129
- Transforms imports of the renamed package `@react-native-community/async-storage` to `@react-native-async-storage/async-storage`.
110
+ # Contributing
130
111
 
131
- #### Example
132
-
133
- Input:
112
+ ## Adding a new transform
134
113
 
135
- ```js
136
- import AsyncStorage from '@react-native-community/async-storage';
137
- ```
138
-
139
- Output:
140
-
141
- ```js
142
- import AsyncStorage from '@react-native-async-storage/async-storage';
143
- ```
114
+ 1. Drop a new file under `src/transforms/` named `sdk-<n>-<description>.ts` exporting a default jscodeshift `Transform` function. After the next build the runtime glob in [`src/transforms/index.ts`](./src/transforms/index.ts) picks it up automatically — no other wiring needed.
115
+ 2. Add a sibling test under `src/transforms/__tests__/<name>-test.ts` using `applyTransform` from `jscodeshift/dist/testUtils`.
116
+ 3. Document the transform under [`## Transforms`](#transforms) above with a from/to table and a short example.
@@ -1,8 +1,3 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- require('../build/cli.js')
4
- .runAsync(process.argv)
5
- .catch(error => {
6
- console.error(error);
7
- process.exit(1);
8
- });
3
+ require('../build/index.js');
@@ -0,0 +1 @@
1
+ export type Command = (argv?: string[]) => Promise<void>;
package/build/index.js ADDED
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const path_1 = __importDefault(require("path"));
40
+ const util_1 = require("util");
41
+ const Log = __importStar(require("./log"));
42
+ async function main() {
43
+ const argv = process.argv.slice(2);
44
+ // strict:false so unknown flags pass through to the inner runCommand parser,
45
+ // which owns the strict validation.
46
+ const { values } = (0, util_1.parseArgs)({
47
+ args: argv,
48
+ options: {
49
+ version: { type: 'boolean', short: 'v' },
50
+ },
51
+ allowPositionals: true,
52
+ strict: false,
53
+ });
54
+ if (values.version) {
55
+ // After build, this file is at build/index.js, so the package root is one level up.
56
+ const pkg = require(path_1.default.resolve(__dirname, '..', 'package.json'));
57
+ Log.log(pkg.version);
58
+ process.exit(0);
59
+ }
60
+ const { runCommand } = await import('./run/index.js');
61
+ await runCommand(argv);
62
+ }
63
+ process.on('SIGINT', () => process.exit(0));
64
+ process.on('SIGTERM', () => process.exit(0));
65
+ main().catch((error) => {
66
+ const message = error instanceof Error ? error.message : String(error);
67
+ Log.error(message);
68
+ process.exit(1);
69
+ });
70
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,gDAAwB;AACxB,+BAAiC;AAEjC,2CAA6B;AAI7B,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,6EAA6E;IAC7E,oCAAoC;IACpC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAA,gBAAS,EAAC;QAC3B,IAAI,EAAE,IAAI;QACV,OAAO,EAAE;YACP,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE;SACzC;QACD,gBAAgB,EAAE,IAAI;QACtB,MAAM,EAAE,KAAK;KACd,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,oFAAoF;QACpF,MAAM,GAAG,GAAG,OAAO,CAAC,cAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;QACnE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACtD,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAE7C,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC9B,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
package/build/log.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export declare function log(...message: string[]): void;
2
+ export declare function error(...message: string[]): void;
3
+ /** Print an error and provide additional info (the stack trace) in debug mode. */
4
+ export declare function exception(e: Error): void;
5
+ /** Log a message and exit the current process. If the `code` is non-zero then `console.error` will be used instead of `console.log`. */
6
+ export declare function exit(message: string | Error, code?: number): never;
package/build/log.js ADDED
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.log = log;
7
+ exports.error = error;
8
+ exports.exception = exception;
9
+ exports.exit = exit;
10
+ /**
11
+ * These functions are copied from packages/@expo/cli/src/log.ts
12
+ */
13
+ const chalk_1 = __importDefault(require("chalk"));
14
+ function log(...message) {
15
+ console.log(...message);
16
+ }
17
+ function error(...message) {
18
+ console.error(...message);
19
+ }
20
+ /** Print an error and provide additional info (the stack trace) in debug mode. */
21
+ function exception(e) {
22
+ const { env } = require('./utils/env');
23
+ error(chalk_1.default.red(e.toString()) + (env.EXPO_DEBUG ? '\n' + chalk_1.default.gray(e.stack) : ''));
24
+ }
25
+ /** Log a message and exit the current process. If the `code` is non-zero then `console.error` will be used instead of `console.log`. */
26
+ function exit(message, code = 1) {
27
+ if (message instanceof Error) {
28
+ exception(message);
29
+ process.exit(code);
30
+ }
31
+ if (message) {
32
+ if (code === 0) {
33
+ log(message);
34
+ }
35
+ else {
36
+ error(message);
37
+ }
38
+ }
39
+ process.exit(code);
40
+ }
41
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":";;;;;AAKA,kBAEC;AAED,sBAEC;AAGD,8BAGC;AAGD,oBAeC;AAnCD;;GAEG;AACH,kDAA0B;AAE1B,SAAgB,GAAG,CAAC,GAAG,OAAiB;IACtC,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;AAC1B,CAAC;AAED,SAAgB,KAAK,CAAC,GAAG,OAAiB;IACxC,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,kFAAkF;AAClF,SAAgB,SAAS,CAAC,CAAQ;IAChC,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACvC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,GAAG,eAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACtF,CAAC;AAED,wIAAwI;AACxI,SAAgB,IAAI,CAAC,OAAuB,EAAE,OAAe,CAAC;IAC5D,IAAI,OAAO,YAAY,KAAK,EAAE,CAAC;QAC7B,SAAS,CAAC,OAAO,CAAC,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IAED,IAAI,OAAO,EAAE,CAAC;QACZ,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YACf,GAAG,CAAC,OAAO,CAAC,CAAC;QACf,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,OAAO,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { Command } from '../index';
2
+ export type ParsedCommand = {
3
+ transform: string;
4
+ paths: string[];
5
+ };
6
+ /**
7
+ * Parse argv, validate it against the available transforms, and return the
8
+ * resolved command. Prints help and exits when --help is passed or required
9
+ * arguments are missing.
10
+ */
11
+ export declare function parseAndValidateArgs(argv: string[] | undefined): Promise<ParsedCommand>;
12
+ /**
13
+ * Expand the given paths into a file list and dispatch them to the jscodeshift
14
+ * runner. Files are split by extension into the `tsx` and `jsx` parser buckets.
15
+ */
16
+ export declare function resolveAndDispatch(command: ParsedCommand): Promise<void>;
17
+ export declare const runCommand: Command;
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.runCommand = void 0;
40
+ exports.parseAndValidateArgs = parseAndValidateArgs;
41
+ exports.resolveAndDispatch = resolveAndDispatch;
42
+ const chalk_1 = __importDefault(require("chalk"));
43
+ const path_1 = __importDefault(require("path"));
44
+ const tinyglobby_1 = require("tinyglobby");
45
+ const Log = __importStar(require("../log"));
46
+ const transforms_1 = require("../transforms");
47
+ const args_1 = require("../utils/args");
48
+ const runner_1 = require("../utils/runner");
49
+ const transformsBlock = (transforms) => ['', ` ${chalk_1.default.bold('Transforms available')}`, ...transforms.map((t) => ` ${t}`), ''].join('\n');
50
+ /**
51
+ * Parse argv, validate it against the available transforms, and return the
52
+ * resolved command. Prints help and exits when --help is passed or required
53
+ * arguments are missing.
54
+ */
55
+ async function parseAndValidateArgs(argv) {
56
+ const { values, positionals } = (0, args_1.parseArgsOrExit)({
57
+ args: argv,
58
+ options: {
59
+ help: { type: 'boolean', short: 'h' },
60
+ },
61
+ allowPositionals: true,
62
+ strict: true,
63
+ });
64
+ const transforms = await (0, transforms_1.listTransformsAsync)();
65
+ const [transform, ...paths] = positionals;
66
+ if (values.help || !transform || paths.length === 0) {
67
+ (0, args_1.printHelp)('Run a codemod transform against the given paths.', 'npx expo-codemod <transform> <paths...>', [
68
+ '<transform> (required) name of transform to apply to files',
69
+ ' (see a list of transforms available below)',
70
+ '<paths...> one or more paths or globs (e.g. src/**/*.tsx)',
71
+ '-h, --help print this help message',
72
+ '-v, --version print the CLI version',
73
+ ].join('\n'), transformsBlock(transforms));
74
+ }
75
+ if (!transforms.includes(transform)) {
76
+ Log.exit(`Transform "${transform}" does not exist. Valid options: ${transforms.join(', ')}`);
77
+ }
78
+ return { transform, paths };
79
+ }
80
+ /**
81
+ * Expand the given paths into a file list and dispatch them to the jscodeshift
82
+ * runner. Files are split by extension into the `tsx` and `jsx` parser buckets.
83
+ */
84
+ async function resolveAndDispatch(command) {
85
+ const { transform, paths } = command;
86
+ const allFiles = await (0, tinyglobby_1.glob)(paths, {
87
+ ignore: ['**/node_modules/**'],
88
+ });
89
+ const tsxFiles = [];
90
+ const tsFiles = [];
91
+ const jsxFiles = [];
92
+ for (const file of allFiles) {
93
+ const ext = path_1.default.extname(file);
94
+ if (ext === '.tsx')
95
+ tsxFiles.push(file);
96
+ else if (ext === '.ts')
97
+ tsFiles.push(file);
98
+ else if (ext === '.js' || ext === '.jsx')
99
+ jsxFiles.push(file);
100
+ }
101
+ const mappings = {
102
+ ts: tsFiles,
103
+ tsx: tsxFiles,
104
+ jsx: jsxFiles,
105
+ };
106
+ const stats = await Promise.all(Object.entries(mappings)
107
+ .filter(([_, files]) => files.length)
108
+ .map(async ([parser, files]) => {
109
+ Log.log(`Transforming ${files.length} ${parser.toUpperCase()} files...`);
110
+ return await (0, runner_1.runTransformAsync)({
111
+ files,
112
+ parser: parser,
113
+ transform,
114
+ });
115
+ }));
116
+ const combinedStats = stats.reduce((acc, { error, ok, nochange, skip, timeElapsed }) => ({
117
+ error: acc.error + error,
118
+ ok: acc.ok + ok,
119
+ nochange: acc.nochange + nochange,
120
+ skip: acc.skip + skip,
121
+ timeElapsed: Math.max(acc.timeElapsed, Number(timeElapsed)),
122
+ }), { error: 0, ok: 0, nochange: 0, skip: 0, timeElapsed: 0 });
123
+ Log.log('');
124
+ Log.log('Results:');
125
+ Log.log(chalk_1.default.red(` ${combinedStats.error} errors`));
126
+ // Log.log(chalk.yellow(` ${combinedStats.nochange} unmodified`));
127
+ Log.log(chalk_1.default.yellow(` ${combinedStats.skip} skipped`));
128
+ Log.log(chalk_1.default.green(` ${combinedStats.ok} ok`));
129
+ Log.log(` Time elapsed: ${combinedStats.timeElapsed.toFixed(2)}s`);
130
+ }
131
+ const runCommand = async (argv) => {
132
+ const command = await parseAndValidateArgs(argv);
133
+ await resolveAndDispatch(command);
134
+ };
135
+ exports.runCommand = runCommand;
136
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/run/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare const TRANSFORM_DIR: string;
2
+ export declare function listTransformsAsync(): Promise<string[]>;
3
+ export declare function transformFilePath(transform: string): string;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.TRANSFORM_DIR = void 0;
7
+ exports.listTransformsAsync = listTransformsAsync;
8
+ exports.transformFilePath = transformFilePath;
9
+ const path_1 = __importDefault(require("path"));
10
+ const tinyglobby_1 = require("tinyglobby");
11
+ exports.TRANSFORM_DIR = __dirname;
12
+ async function listTransformsAsync() {
13
+ // *.js, since this function will be called from within build folder
14
+ const modules = await (0, tinyglobby_1.glob)(['*.js'], { cwd: exports.TRANSFORM_DIR });
15
+ return modules
16
+ .map((filename) => path_1.default.basename(filename, '.js'))
17
+ .filter((name) => name !== 'index')
18
+ .sort();
19
+ }
20
+ function transformFilePath(transform) {
21
+ return path_1.default.join(exports.TRANSFORM_DIR, `${transform}.js`);
22
+ }
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transforms/index.ts"],"names":[],"mappings":";;;;;;AAKA,kDAOC;AAED,8CAEC;AAhBD,gDAAwB;AACxB,2CAAkC;AAErB,QAAA,aAAa,GAAG,SAAS,CAAC;AAEhC,KAAK,UAAU,mBAAmB;IACvC,oEAAoE;IACpE,MAAM,OAAO,GAAG,MAAM,IAAA,iBAAI,EAAC,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,qBAAa,EAAE,CAAC,CAAC;IAC7D,OAAO,OAAO;SACX,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,cAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;SACjD,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,OAAO,CAAC;SAClC,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,SAAgB,iBAAiB,CAAC,SAAiB;IACjD,OAAO,cAAI,CAAC,IAAI,CAAC,qBAAa,EAAE,GAAG,SAAS,KAAK,CAAC,CAAC;AACrD,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Codemod: Replace @react-navigation/* imports with expo-router equivalents.
3
+ *
4
+ * Mapping:
5
+ * @react-navigation/native → expo-router
6
+ * @react-navigation/stack → expo-router/js-stack
7
+ * @react-navigation/bottom-tabs → expo-router/js-tabs
8
+ * @react-navigation/material-top-tabs → expo-router/js-top-tabs
9
+ *
10
+ * After replacement, duplicate `expo-router` imports are merged into one.
11
+ */
12
+ import type { Transform } from 'jscodeshift';
13
+ declare const transform: Transform;
14
+ export default transform;