expo-modules-autolinking 3.0.14 → 3.0.16

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/CHANGELOG.md CHANGED
@@ -10,7 +10,25 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
- ## 3.0.14 — 2025-10-01
13
+ ## 3.0.16 — 2025-10-20
14
+
15
+ ### 🐛 Bug fixes
16
+
17
+ - Ignore missing `package.json` name property when scanning dependencies ([#40367](https://github.com/expo/expo/pull/40367) by [@kitten](https://github.com/kitten))
18
+ - fix globMatchFunctorAllAsync to check if globbed path is a file to prevent errors ([#40437](https://github.com/expo/expo/pull/40437) by [@artus9033](https://github.com/artus9033))
19
+
20
+ ## 3.0.15 — 2025-10-09
21
+
22
+ ### 🐛 Bug fixes
23
+
24
+ - [iOS] Added build phase script for a workaround to autolinking-generated react-native-config output not being used in ReactCodegen script phase due to temp output directory. ([#40219](https://github.com/expo/expo/pull/40219) by [@chrfalch](https://github.com/chrfalch))
25
+
26
+ ### 💡 Others
27
+
28
+ - Check `react-native` and `react-native-tvos` for duplicates in the verify command explicitly ([#40180](https://github.com/expo/expo/pull/40180) by [@kitten](https://github.com/kitten))
29
+ - [Android] Sync flavor dimensions and product flavors from app to expo module ([#40238](https://github.com/expo/expo/pull/40238) by [@kosmydel](https://github.com/kosmydel))
30
+
31
+ ## 3.0.14 - 2025-10-01
14
32
 
15
33
  ### 💡 Others
16
34
 
@@ -1,6 +1,7 @@
1
1
  package expo.modules.plugin
2
2
 
3
3
  import com.android.build.api.variant.AndroidComponentsExtension
4
+ import com.android.build.gradle.BaseExtension
4
5
  import com.android.build.gradle.internal.tasks.factory.dependsOn
5
6
  import expo.modules.plugin.text.Colors
6
7
  import expo.modules.plugin.text.withColor
@@ -27,6 +28,9 @@ open class ExpoAutolinkingPlugin : Plugin<Project> {
27
28
  project.logger.quiet("")
28
29
  project.logger.quiet("Using expo modules")
29
30
 
31
+ val appProject = findAppProject(project.rootProject)
32
+ appProject?.let { copyAppDimensionsAndFlavorsToProject(project, it) }
33
+
30
34
  val (prebuiltProjects, projects) = config.allProjects.partition { project ->
31
35
  project.usePublication
32
36
  }
@@ -91,4 +95,79 @@ open class ExpoAutolinkingPlugin : Plugin<Project> {
91
95
  it.options.set(options.toJson())
92
96
  }
93
97
  }
98
+
99
+ private fun findAppProject(root: Project): Project? {
100
+ return root.allprojects.firstOrNull { it.plugins.hasPlugin("com.android.application") }
101
+ }
102
+
103
+ private fun copyAppDimensionsAndFlavorsToProject(
104
+ project: Project,
105
+ appProject: Project
106
+ ) {
107
+ val appAndroid = appProject.extensions.findByName("android") as? BaseExtension ?: run {
108
+ return
109
+ }
110
+ val consumerAndroid = project.extensions.findByName("android") as? BaseExtension ?: run {
111
+ return
112
+ }
113
+
114
+ val appDimensions = syncFlavorDimensions(project, consumerAndroid, appAndroid)
115
+ copyMissingProductFlavors(project, consumerAndroid, appAndroid, appDimensions)
116
+ }
117
+
118
+ private fun syncFlavorDimensions(
119
+ project: Project,
120
+ consumerAndroid: BaseExtension,
121
+ appAndroid: BaseExtension
122
+ ): List<String> {
123
+ val appDimensions = appAndroid
124
+ .flavorDimensionList
125
+ .takeIf { it.isNotEmpty() }
126
+ ?: return emptyList()
127
+
128
+ val consumerDimensions = (consumerAndroid.flavorDimensionList).toMutableList()
129
+ val dimensionsAdded = appDimensions.any { dimension ->
130
+ if (dimension !in consumerDimensions) {
131
+ consumerDimensions.add(dimension)
132
+ true
133
+ } else {
134
+ false
135
+ }
136
+ }
137
+
138
+ if (dimensionsAdded) {
139
+ consumerAndroid.flavorDimensions(*consumerDimensions.toTypedArray())
140
+ project.logger.quiet(" -> Copied/merged flavorDimensions: ${consumerDimensions.joinToString()}")
141
+ }
142
+
143
+ return appDimensions
144
+ }
145
+
146
+ private fun copyMissingProductFlavors(
147
+ project: Project,
148
+ consumerAndroid: BaseExtension,
149
+ appAndroid: BaseExtension,
150
+ appDimensions: List<String>
151
+ ) {
152
+ val appFlavors = appAndroid.productFlavors
153
+ val consumerFlavors = consumerAndroid.productFlavors
154
+ val existingFlavorNames = consumerFlavors.map { it.name }.toSet()
155
+
156
+ appFlavors.forEach { appFlavor ->
157
+ if (appFlavor.name !in existingFlavorNames) {
158
+ val dimension = appFlavor.dimension ?: appDimensions.singleOrNull()
159
+
160
+ consumerFlavors.create(appFlavor.name).apply {
161
+ this.dimension = dimension
162
+ appFlavor.applicationIdSuffix?.let { this.applicationIdSuffix = it }
163
+ appFlavor.versionNameSuffix?.let { this.versionNameSuffix = it }
164
+ if (appFlavor.manifestPlaceholders.isNotEmpty()) {
165
+ this.manifestPlaceholders.putAll(appFlavor.manifestPlaceholders)
166
+ }
167
+ }
168
+
169
+ project.logger.quiet(" -> Created flavor '${appFlavor.name}' (dimension='$dimension') in :${project.path}")
170
+ }
171
+ }
172
+ }
94
173
  }
@@ -10,6 +10,8 @@ const fs_1 = __importDefault(require("fs"));
10
10
  const path_1 = __importDefault(require("path"));
11
11
  const autolinkingOptions_1 = require("./autolinkingOptions");
12
12
  const dependencies_1 = require("../dependencies");
13
+ // NOTE(@kitten): These are excluded explicitly, but we want to include them for the verify command explicitly
14
+ const INCLUDE_PACKAGES = ['react-native', 'react-native-tvos'];
13
15
  function verifyCommand(cli) {
14
16
  return (0, autolinkingOptions_1.registerAutolinkingArguments)(cli.command('verify'))
15
17
  .option('-v, --verbose', 'Output all results instead of just warnings.', () => true, false)
@@ -20,7 +22,7 @@ function verifyCommand(cli) {
20
22
  const autolinkingOptionsLoader = (0, autolinkingOptions_1.createAutolinkingOptionsLoader)(commandArguments);
21
23
  const appRoot = await autolinkingOptionsLoader.getAppRoot();
22
24
  const linker = (0, dependencies_1.makeCachedDependenciesLinker)({ projectRoot: appRoot });
23
- const results = (0, dependencies_1.mergeResolutionResults)(await Promise.all(platforms.map((platform) => (0, dependencies_1.scanDependencyResolutionsForPlatform)(linker, platform))));
25
+ const results = (0, dependencies_1.mergeResolutionResults)(await Promise.all(platforms.map((platform) => (0, dependencies_1.scanDependencyResolutionsForPlatform)(linker, platform, INCLUDE_PACKAGES))));
24
26
  await verifySearchResults(results, {
25
27
  appRoot,
26
28
  verbose: !!commandArguments.verbose,
@@ -1 +1 @@
1
- {"version":3,"file":"verifyCommand.js","sourceRoot":"","sources":["../../src/commands/verifyCommand.ts"],"names":[],"mappings":"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","sourcesContent":["import chalk from 'chalk';\nimport commander from 'commander';\nimport fs from 'fs';\nimport path from 'path';\n\nimport {\n AutolinkingCommonArguments,\n createAutolinkingOptionsLoader,\n registerAutolinkingArguments,\n} from './autolinkingOptions';\nimport {\n type BaseDependencyResolution,\n type DependencyResolution,\n type ResolutionResult,\n DependencyResolutionSource,\n makeCachedDependenciesLinker,\n mergeResolutionResults,\n scanDependencyResolutionsForPlatform,\n} from '../dependencies';\n\ninterface VerifyArguments extends AutolinkingCommonArguments {\n verbose?: boolean | null;\n json?: boolean | null;\n}\n\nexport function verifyCommand(cli: commander.CommanderStatic) {\n return registerAutolinkingArguments(cli.command('verify'))\n .option('-v, --verbose', 'Output all results instead of just warnings.', () => true, false)\n .option('-j, --json', 'Output results in the plain JSON format.', () => true, false)\n .option(\n '-p, --platform [platform]',\n 'The platform to validate native modules for. Available options: \"android\", \"ios\", \"both\"',\n 'both'\n )\n .action(async (commandArguments: VerifyArguments) => {\n const platforms =\n commandArguments.platform === 'both' ? ['android', 'ios'] : [commandArguments.platform!];\n const autolinkingOptionsLoader = createAutolinkingOptionsLoader(commandArguments);\n const appRoot = await autolinkingOptionsLoader.getAppRoot();\n const linker = makeCachedDependenciesLinker({ projectRoot: appRoot });\n const results = mergeResolutionResults(\n await Promise.all(\n platforms.map((platform) => scanDependencyResolutionsForPlatform(linker, platform))\n )\n );\n await verifySearchResults(results, {\n appRoot,\n verbose: !!commandArguments.verbose,\n json: !!commandArguments.json,\n });\n });\n}\n\ninterface VerifyOptions {\n appRoot: string;\n verbose?: boolean;\n json?: boolean;\n}\n\ninterface VerifyGroups {\n reactNativeProjectConfig: DependencyResolution[];\n searchPaths: DependencyResolution[];\n dependencies: DependencyResolution[];\n duplicates: DependencyResolution[];\n}\n\n/**\n * Verifies the search results by checking whether there are no duplicates.\n */\nexport async function verifySearchResults(\n results: ResolutionResult,\n options: VerifyOptions\n): Promise<void> {\n const { appRoot } = options;\n\n async function getHumanReadableDependency(dependency: BaseDependencyResolution): Promise<string> {\n let version = dependency.version || null;\n if (!version) {\n try {\n const pkgContents = await fs.promises.readFile(\n path.join(dependency.path, 'package.json'),\n 'utf8'\n );\n const pkg: unknown = JSON.parse(pkgContents);\n if (pkg && typeof pkg === 'object' && 'version' in pkg && typeof pkg.version === 'string') {\n version = pkg.version;\n }\n } catch (error) {\n version = null;\n }\n }\n const relative = path.relative(appRoot, dependency.originPath);\n return version\n ? `${dependency.name}@${version} (at: ${relative})`\n : `${dependency.name} at: ${relative}`;\n }\n\n const groups: VerifyGroups = {\n reactNativeProjectConfig: [],\n searchPaths: [],\n dependencies: [],\n duplicates: [],\n };\n\n for (const moduleName in results) {\n const revision = results[moduleName];\n if (!revision) {\n continue;\n } else if (revision.duplicates?.length) {\n groups.duplicates.push(revision);\n } else {\n switch (revision.source) {\n case DependencyResolutionSource.RN_CLI_LOCAL:\n groups.reactNativeProjectConfig.push(revision);\n break;\n case DependencyResolutionSource.SEARCH_PATH:\n groups.searchPaths.push(revision);\n break;\n case DependencyResolutionSource.RECURSIVE_RESOLUTION:\n groups.dependencies.push(revision);\n break;\n }\n }\n }\n\n if (options.json) {\n console.log(JSON.stringify(groups));\n return;\n }\n\n if (options.verbose) {\n const sortResolutions = (resolutions: DependencyResolution[]) =>\n [...resolutions].sort((a, b) => a.name.localeCompare(b.name));\n\n if (groups.reactNativeProjectConfig.length) {\n console.log(\n `🔎 Found ${groups.reactNativeProjectConfig.length} modules from React Native project config`\n );\n for (const revision of sortResolutions(groups.reactNativeProjectConfig)) {\n console.log(` - ${await getHumanReadableDependency(revision)}`);\n }\n }\n\n if (groups.searchPaths.length) {\n console.log(`🔎 Found ${groups.searchPaths.length} modules in search paths`);\n for (const revision of sortResolutions(groups.searchPaths)) {\n console.log(` - ${await getHumanReadableDependency(revision)}`);\n }\n }\n\n console.log(`🔎 Found ${groups.dependencies.length} modules in dependencies`);\n for (const revision of sortResolutions(groups.dependencies)) {\n console.log(` - ${await getHumanReadableDependency(revision)}`);\n }\n }\n\n if (groups.duplicates.length) {\n for (const revision of groups.duplicates) {\n console.warn(`⚠️ Found duplicate installations for ${chalk.green(revision.name)}`);\n const revisions = [revision, ...(revision.duplicates ?? [])];\n for (let idx = 0; idx < revisions.length; idx++) {\n const prefix = idx !== revisions.length - 1 ? '├─' : '└─';\n const duplicate = revisions[idx];\n console.log(` ${prefix} ${await getHumanReadableDependency(duplicate)}`);\n }\n }\n\n console.warn(\n '⚠️ Multiple versions of the same module may introduce some side effects or compatibility issues.\\n' +\n `Resolve your dependency issues and deduplicate your dependencies. Learn more: https://expo.fyi/resolving-dependency-issues`\n );\n } else {\n console.log('✅ Everything is fine!');\n }\n}\n"]}
1
+ {"version":3,"file":"verifyCommand.js","sourceRoot":"","sources":["../../src/commands/verifyCommand.ts"],"names":[],"mappings":";;;;;AA4BA,sCA4BC;AAkBD,kDAyGC;AAnLD,kDAA0B;AAE1B,4CAAoB;AACpB,gDAAwB;AAExB,6DAI8B;AAC9B,kDAQyB;AAEzB,8GAA8G;AAC9G,MAAM,gBAAgB,GAAG,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC;AAO/D,SAAgB,aAAa,CAAC,GAA8B;IAC1D,OAAO,IAAA,iDAA4B,EAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;SACvD,MAAM,CAAC,eAAe,EAAE,8CAA8C,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC;SAC1F,MAAM,CAAC,YAAY,EAAE,0CAA0C,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC;SACnF,MAAM,CACL,2BAA2B,EAC3B,0FAA0F,EAC1F,MAAM,CACP;SACA,MAAM,CAAC,KAAK,EAAE,gBAAiC,EAAE,EAAE;QAClD,MAAM,SAAS,GACb,gBAAgB,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,QAAS,CAAC,CAAC;QAC3F,MAAM,wBAAwB,GAAG,IAAA,mDAA8B,EAAC,gBAAgB,CAAC,CAAC;QAClF,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC,UAAU,EAAE,CAAC;QAC5D,MAAM,MAAM,GAAG,IAAA,2CAA4B,EAAC,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC;QACtE,MAAM,OAAO,GAAG,IAAA,qCAAsB,EACpC,MAAM,OAAO,CAAC,GAAG,CACf,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CACzB,IAAA,mDAAoC,EAAC,MAAM,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CACzE,CACF,CACF,CAAC;QACF,MAAM,mBAAmB,CAAC,OAAO,EAAE;YACjC,OAAO;YACP,OAAO,EAAE,CAAC,CAAC,gBAAgB,CAAC,OAAO;YACnC,IAAI,EAAE,CAAC,CAAC,gBAAgB,CAAC,IAAI;SAC9B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC;AAeD;;GAEG;AACI,KAAK,UAAU,mBAAmB,CACvC,OAAyB,EACzB,OAAsB;IAEtB,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAE5B,KAAK,UAAU,0BAA0B,CAAC,UAAoC;QAC5E,IAAI,OAAO,GAAG,UAAU,CAAC,OAAO,IAAI,IAAI,CAAC;QACzC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,MAAM,YAAE,CAAC,QAAQ,CAAC,QAAQ,CAC5C,cAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,cAAc,CAAC,EAC1C,MAAM,CACP,CAAC;gBACF,MAAM,GAAG,GAAY,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;gBAC7C,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,SAAS,IAAI,GAAG,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;oBAC1F,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;gBACxB,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;QACH,CAAC;QACD,MAAM,QAAQ,GAAG,cAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;QAC/D,OAAO,OAAO;YACZ,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,IAAI,OAAO,SAAS,QAAQ,GAAG;YACnD,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,QAAQ,QAAQ,EAAE,CAAC;IAC3C,CAAC;IAED,MAAM,MAAM,GAAiB;QAC3B,wBAAwB,EAAE,EAAE;QAC5B,WAAW,EAAE,EAAE;QACf,YAAY,EAAE,EAAE;QAChB,UAAU,EAAE,EAAE;KACf,CAAC;IAEF,KAAK,MAAM,UAAU,IAAI,OAAO,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;QACrC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,SAAS;QACX,CAAC;aAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;YACvC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,QAAQ,QAAQ,CAAC,MAAM,EAAE,CAAC;gBACxB;oBACE,MAAM,CAAC,wBAAwB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;oBAC/C,MAAM;gBACR;oBACE,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;oBAClC,MAAM;gBACR;oBACE,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;oBACnC,MAAM;YACV,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;QACpC,OAAO;IACT,CAAC;IAED,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,eAAe,GAAG,CAAC,WAAmC,EAAE,EAAE,CAC9D,CAAC,GAAG,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAEhE,IAAI,MAAM,CAAC,wBAAwB,CAAC,MAAM,EAAE,CAAC;YAC3C,OAAO,CAAC,GAAG,CACT,aAAa,MAAM,CAAC,wBAAwB,CAAC,MAAM,2CAA2C,CAC/F,CAAC;YACF,KAAK,MAAM,QAAQ,IAAI,eAAe,CAAC,MAAM,CAAC,wBAAwB,CAAC,EAAE,CAAC;gBACxE,OAAO,CAAC,GAAG,CAAC,MAAM,MAAM,0BAA0B,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,WAAW,CAAC,MAAM,0BAA0B,CAAC,CAAC;YAC9E,KAAK,MAAM,QAAQ,IAAI,eAAe,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC3D,OAAO,CAAC,GAAG,CAAC,MAAM,MAAM,0BAA0B,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,YAAY,CAAC,MAAM,0BAA0B,CAAC,CAAC;QAC/E,KAAK,MAAM,QAAQ,IAAI,eAAe,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;YAC5D,OAAO,CAAC,GAAG,CAAC,MAAM,MAAM,0BAA0B,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;QAC7B,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,yCAAyC,eAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpF,MAAM,SAAS,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC;YAC7D,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC;gBAChD,MAAM,MAAM,GAAG,GAAG,KAAK,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC1D,MAAM,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;gBACjC,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,IAAI,MAAM,0BAA0B,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;YAC5E,CAAC;QACH,CAAC;QAED,OAAO,CAAC,IAAI,CACV,qGAAqG;YACnG,4HAA4H,CAC/H,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACvC,CAAC;AACH,CAAC","sourcesContent":["import chalk from 'chalk';\nimport commander from 'commander';\nimport fs from 'fs';\nimport path from 'path';\n\nimport {\n AutolinkingCommonArguments,\n createAutolinkingOptionsLoader,\n registerAutolinkingArguments,\n} from './autolinkingOptions';\nimport {\n type BaseDependencyResolution,\n type DependencyResolution,\n type ResolutionResult,\n DependencyResolutionSource,\n makeCachedDependenciesLinker,\n mergeResolutionResults,\n scanDependencyResolutionsForPlatform,\n} from '../dependencies';\n\n// NOTE(@kitten): These are excluded explicitly, but we want to include them for the verify command explicitly\nconst INCLUDE_PACKAGES = ['react-native', 'react-native-tvos'];\n\ninterface VerifyArguments extends AutolinkingCommonArguments {\n verbose?: boolean | null;\n json?: boolean | null;\n}\n\nexport function verifyCommand(cli: commander.CommanderStatic) {\n return registerAutolinkingArguments(cli.command('verify'))\n .option('-v, --verbose', 'Output all results instead of just warnings.', () => true, false)\n .option('-j, --json', 'Output results in the plain JSON format.', () => true, false)\n .option(\n '-p, --platform [platform]',\n 'The platform to validate native modules for. Available options: \"android\", \"ios\", \"both\"',\n 'both'\n )\n .action(async (commandArguments: VerifyArguments) => {\n const platforms =\n commandArguments.platform === 'both' ? ['android', 'ios'] : [commandArguments.platform!];\n const autolinkingOptionsLoader = createAutolinkingOptionsLoader(commandArguments);\n const appRoot = await autolinkingOptionsLoader.getAppRoot();\n const linker = makeCachedDependenciesLinker({ projectRoot: appRoot });\n const results = mergeResolutionResults(\n await Promise.all(\n platforms.map((platform) =>\n scanDependencyResolutionsForPlatform(linker, platform, INCLUDE_PACKAGES)\n )\n )\n );\n await verifySearchResults(results, {\n appRoot,\n verbose: !!commandArguments.verbose,\n json: !!commandArguments.json,\n });\n });\n}\n\ninterface VerifyOptions {\n appRoot: string;\n verbose?: boolean;\n json?: boolean;\n}\n\ninterface VerifyGroups {\n reactNativeProjectConfig: DependencyResolution[];\n searchPaths: DependencyResolution[];\n dependencies: DependencyResolution[];\n duplicates: DependencyResolution[];\n}\n\n/**\n * Verifies the search results by checking whether there are no duplicates.\n */\nexport async function verifySearchResults(\n results: ResolutionResult,\n options: VerifyOptions\n): Promise<void> {\n const { appRoot } = options;\n\n async function getHumanReadableDependency(dependency: BaseDependencyResolution): Promise<string> {\n let version = dependency.version || null;\n if (!version) {\n try {\n const pkgContents = await fs.promises.readFile(\n path.join(dependency.path, 'package.json'),\n 'utf8'\n );\n const pkg: unknown = JSON.parse(pkgContents);\n if (pkg && typeof pkg === 'object' && 'version' in pkg && typeof pkg.version === 'string') {\n version = pkg.version;\n }\n } catch (error) {\n version = null;\n }\n }\n const relative = path.relative(appRoot, dependency.originPath);\n return version\n ? `${dependency.name}@${version} (at: ${relative})`\n : `${dependency.name} at: ${relative}`;\n }\n\n const groups: VerifyGroups = {\n reactNativeProjectConfig: [],\n searchPaths: [],\n dependencies: [],\n duplicates: [],\n };\n\n for (const moduleName in results) {\n const revision = results[moduleName];\n if (!revision) {\n continue;\n } else if (revision.duplicates?.length) {\n groups.duplicates.push(revision);\n } else {\n switch (revision.source) {\n case DependencyResolutionSource.RN_CLI_LOCAL:\n groups.reactNativeProjectConfig.push(revision);\n break;\n case DependencyResolutionSource.SEARCH_PATH:\n groups.searchPaths.push(revision);\n break;\n case DependencyResolutionSource.RECURSIVE_RESOLUTION:\n groups.dependencies.push(revision);\n break;\n }\n }\n }\n\n if (options.json) {\n console.log(JSON.stringify(groups));\n return;\n }\n\n if (options.verbose) {\n const sortResolutions = (resolutions: DependencyResolution[]) =>\n [...resolutions].sort((a, b) => a.name.localeCompare(b.name));\n\n if (groups.reactNativeProjectConfig.length) {\n console.log(\n `🔎 Found ${groups.reactNativeProjectConfig.length} modules from React Native project config`\n );\n for (const revision of sortResolutions(groups.reactNativeProjectConfig)) {\n console.log(` - ${await getHumanReadableDependency(revision)}`);\n }\n }\n\n if (groups.searchPaths.length) {\n console.log(`🔎 Found ${groups.searchPaths.length} modules in search paths`);\n for (const revision of sortResolutions(groups.searchPaths)) {\n console.log(` - ${await getHumanReadableDependency(revision)}`);\n }\n }\n\n console.log(`🔎 Found ${groups.dependencies.length} modules in dependencies`);\n for (const revision of sortResolutions(groups.dependencies)) {\n console.log(` - ${await getHumanReadableDependency(revision)}`);\n }\n }\n\n if (groups.duplicates.length) {\n for (const revision of groups.duplicates) {\n console.warn(`⚠️ Found duplicate installations for ${chalk.green(revision.name)}`);\n const revisions = [revision, ...(revision.duplicates ?? [])];\n for (let idx = 0; idx < revisions.length; idx++) {\n const prefix = idx !== revisions.length - 1 ? '├─' : '└─';\n const duplicate = revisions[idx];\n console.log(` ${prefix} ${await getHumanReadableDependency(duplicate)}`);\n }\n }\n\n console.warn(\n '⚠️ Multiple versions of the same module may introduce some side effects or compatibility issues.\\n' +\n `Resolve your dependency issues and deduplicate your dependencies. Learn more: https://expo.fyi/resolving-dependency-issues`\n );\n } else {\n console.log('✅ Everything is fine!');\n }\n}\n"]}
@@ -3,7 +3,6 @@ export declare function defaultShouldIncludeDependency(dependencyName: string):
3
3
  export declare const fastJoin: (from: string, append: string) => string;
4
4
  export declare const maybeRealpath: (target: string) => Promise<string | null>;
5
5
  export type PackageJson = Record<string, unknown> & {
6
- name: string;
7
6
  version?: string;
8
7
  };
9
8
  export declare const loadPackageJson: (input: string, ...args: any[]) => Promise<any>;
@@ -56,9 +56,6 @@ exports.loadPackageJson = (0, utils_1.memoize)(async function loadPackageJson(js
56
56
  if (typeof json !== 'object' || json == null) {
57
57
  return null;
58
58
  }
59
- else if (typeof json.name !== 'string' || !json.name) {
60
- return null;
61
- }
62
59
  return json;
63
60
  }
64
61
  catch {
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/dependencies/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { memoize } from '../utils';\nimport type { DependencyResolution, ResolutionResult } from './types';\n\nconst NODE_MODULES_PATTERN = `${path.sep}node_modules${path.sep}`;\n\n// The default dependencies we exclude don't contain dependency chains leading to autolinked modules\nexport function defaultShouldIncludeDependency(dependencyName: string): boolean {\n const scopeName =\n dependencyName[0] === '@' ? dependencyName.slice(1, dependencyName.indexOf('/')) : null;\n if (\n scopeName === 'babel' ||\n scopeName === 'types' ||\n scopeName === 'eslint' ||\n scopeName === 'typescript-eslint'\n ) {\n return false;\n }\n switch (dependencyName) {\n case '@expo/cli':\n case '@expo/config':\n case '@expo/metro-config':\n case '@expo/package-manager':\n case '@expo/prebuild-config':\n case '@expo/env':\n case '@react-native/codegen':\n case 'eslint':\n case 'eslint-config-expo':\n case 'eslint-plugin-expo':\n return false;\n default:\n return true;\n }\n}\n\nexport const fastJoin: (from: string, append: string) => string =\n path.sep === '/'\n ? (from, append) => `${from}${path.sep}${append}`\n : (from, append) =>\n `${from}${path.sep}${append[0] === '@' ? append.replace('/', path.sep) : append}`;\n\nexport const maybeRealpath = async (target: string): Promise<string | null> => {\n try {\n return await fs.promises.realpath(target);\n } catch {\n return null;\n }\n};\n\nexport type PackageJson = Record<string, unknown> & { name: string; version?: string };\n\nexport const loadPackageJson = memoize(async function loadPackageJson(\n jsonPath: string\n): Promise<PackageJson | null> {\n try {\n const packageJsonText = await fs.promises.readFile(jsonPath, 'utf8');\n const json = JSON.parse(packageJsonText);\n if (typeof json !== 'object' || json == null) {\n return null;\n } else if (typeof json.name !== 'string' || !json.name) {\n return null;\n }\n return json;\n } catch {\n return null;\n }\n});\n\nexport function mergeWithDuplicate(\n a: DependencyResolution,\n b: DependencyResolution\n): DependencyResolution {\n let target: DependencyResolution;\n let duplicate: DependencyResolution;\n if (a.depth < b.depth) {\n target = a;\n duplicate = b;\n } else if (b.depth < a.depth) {\n target = b;\n duplicate = a;\n } else {\n // If both are equal, then the shallowest path wins\n const pathDepthA = a.originPath.split(NODE_MODULES_PATTERN).length;\n const pathDepthB = b.originPath.split(NODE_MODULES_PATTERN).length;\n if (pathDepthA < pathDepthB) {\n target = a;\n duplicate = b;\n } else if (pathDepthB < pathDepthA) {\n target = b;\n duplicate = a;\n } else {\n target = a;\n duplicate = b;\n }\n }\n const duplicates = target.duplicates || (target.duplicates = []);\n if (target.path !== duplicate.path) {\n duplicates.push({\n name: duplicate.name,\n version: duplicate.version,\n path: duplicate.path,\n originPath: duplicate.originPath,\n });\n }\n if (duplicate.duplicates?.length) {\n duplicates.push(\n ...duplicate.duplicates.filter((child) =>\n duplicates.every((parent) => parent.path !== child.path)\n )\n );\n }\n return target;\n}\n\nexport async function filterMapResolutionResult<T extends { name: string }>(\n results: ResolutionResult,\n filterMap: (resolution: DependencyResolution) => Promise<T | null> | T | null\n): Promise<Record<string, T>> {\n const resolutions = await Promise.all(\n Object.keys(results).map(async (key) => {\n const resolution = results[key];\n return resolution ? await filterMap(resolution) : null;\n })\n );\n const output: Record<string, T> = Object.create(null);\n for (let idx = 0; idx < resolutions.length; idx++) {\n const resolution = resolutions[idx];\n if (resolution != null) {\n output[resolution.name] = resolution;\n }\n }\n return output;\n}\n\nexport function mergeResolutionResults(results: ResolutionResult[]) {\n if (results.length === 1) {\n return results[0];\n }\n const output: ResolutionResult = Object.create(null);\n for (let idx = 0; idx < results.length; idx++) {\n for (const key in results[idx]) {\n const resolution = results[idx][key]!;\n const prevResolution = output[key];\n if (prevResolution != null) {\n output[key] = mergeWithDuplicate(prevResolution, resolution);\n } else {\n output[key] = resolution;\n }\n }\n }\n return output;\n}\n"]}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/dependencies/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { memoize } from '../utils';\nimport type { DependencyResolution, ResolutionResult } from './types';\n\nconst NODE_MODULES_PATTERN = `${path.sep}node_modules${path.sep}`;\n\n// The default dependencies we exclude don't contain dependency chains leading to autolinked modules\nexport function defaultShouldIncludeDependency(dependencyName: string): boolean {\n const scopeName =\n dependencyName[0] === '@' ? dependencyName.slice(1, dependencyName.indexOf('/')) : null;\n if (\n scopeName === 'babel' ||\n scopeName === 'types' ||\n scopeName === 'eslint' ||\n scopeName === 'typescript-eslint'\n ) {\n return false;\n }\n switch (dependencyName) {\n case '@expo/cli':\n case '@expo/config':\n case '@expo/metro-config':\n case '@expo/package-manager':\n case '@expo/prebuild-config':\n case '@expo/env':\n case '@react-native/codegen':\n case 'eslint':\n case 'eslint-config-expo':\n case 'eslint-plugin-expo':\n return false;\n default:\n return true;\n }\n}\n\nexport const fastJoin: (from: string, append: string) => string =\n path.sep === '/'\n ? (from, append) => `${from}${path.sep}${append}`\n : (from, append) =>\n `${from}${path.sep}${append[0] === '@' ? append.replace('/', path.sep) : append}`;\n\nexport const maybeRealpath = async (target: string): Promise<string | null> => {\n try {\n return await fs.promises.realpath(target);\n } catch {\n return null;\n }\n};\n\nexport type PackageJson = Record<string, unknown> & { version?: string };\n\nexport const loadPackageJson = memoize(async function loadPackageJson(\n jsonPath: string\n): Promise<PackageJson | null> {\n try {\n const packageJsonText = await fs.promises.readFile(jsonPath, 'utf8');\n const json = JSON.parse(packageJsonText);\n if (typeof json !== 'object' || json == null) {\n return null;\n }\n return json;\n } catch {\n return null;\n }\n});\n\nexport function mergeWithDuplicate(\n a: DependencyResolution,\n b: DependencyResolution\n): DependencyResolution {\n let target: DependencyResolution;\n let duplicate: DependencyResolution;\n if (a.depth < b.depth) {\n target = a;\n duplicate = b;\n } else if (b.depth < a.depth) {\n target = b;\n duplicate = a;\n } else {\n // If both are equal, then the shallowest path wins\n const pathDepthA = a.originPath.split(NODE_MODULES_PATTERN).length;\n const pathDepthB = b.originPath.split(NODE_MODULES_PATTERN).length;\n if (pathDepthA < pathDepthB) {\n target = a;\n duplicate = b;\n } else if (pathDepthB < pathDepthA) {\n target = b;\n duplicate = a;\n } else {\n target = a;\n duplicate = b;\n }\n }\n const duplicates = target.duplicates || (target.duplicates = []);\n if (target.path !== duplicate.path) {\n duplicates.push({\n name: duplicate.name,\n version: duplicate.version,\n path: duplicate.path,\n originPath: duplicate.originPath,\n });\n }\n if (duplicate.duplicates?.length) {\n duplicates.push(\n ...duplicate.duplicates.filter((child) =>\n duplicates.every((parent) => parent.path !== child.path)\n )\n );\n }\n return target;\n}\n\nexport async function filterMapResolutionResult<T extends { name: string }>(\n results: ResolutionResult,\n filterMap: (resolution: DependencyResolution) => Promise<T | null> | T | null\n): Promise<Record<string, T>> {\n const resolutions = await Promise.all(\n Object.keys(results).map(async (key) => {\n const resolution = results[key];\n return resolution ? await filterMap(resolution) : null;\n })\n );\n const output: Record<string, T> = Object.create(null);\n for (let idx = 0; idx < resolutions.length; idx++) {\n const resolution = resolutions[idx];\n if (resolution != null) {\n output[resolution.name] = resolution;\n }\n }\n return output;\n}\n\nexport function mergeResolutionResults(results: ResolutionResult[]) {\n if (results.length === 1) {\n return results[0];\n }\n const output: ResolutionResult = Object.create(null);\n for (let idx = 0; idx < results.length; idx++) {\n for (const key in results[idx]) {\n const resolution = results[idx][key]!;\n const prevResolution = output[key];\n if (prevResolution != null) {\n output[key] = mergeWithDuplicate(prevResolution, resolution);\n } else {\n output[key] = resolution;\n }\n }\n }\n return output;\n}\n"]}
@@ -19,11 +19,14 @@ async function fileExistsAsync(file) {
19
19
  * Search files that match the glob pattern and return all matches from the matchFunctor.
20
20
  */
21
21
  async function globMatchFunctorAllAsync(globPattern, matchFunctor, options) {
22
- const globStream = glob_1.glob.stream(globPattern, { ...options, withFileTypes: false });
22
+ const globStream = glob_1.glob.stream(globPattern, { withFileTypes: true });
23
23
  const cwd = options?.cwd !== undefined ? `${options.cwd}` : process.cwd();
24
24
  const results = [];
25
- for await (const file of globStream) {
26
- let filePath = file.toString();
25
+ for await (const globPath of globStream) {
26
+ if (!globPath.isFile()) {
27
+ continue;
28
+ }
29
+ let filePath = globPath.fullpath();
27
30
  if (!path_1.default.isAbsolute(filePath)) {
28
31
  filePath = path_1.default.resolve(cwd, filePath);
29
32
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fileUtils.js","sourceRoot":"","sources":["../src/fileUtils.ts"],"names":[],"mappings":";;;;;AAYA,0CAEC;AAKD,4DAoBC;AAKD,gEAmBC;AA/DD,2DAA6B;AAC7B,+BAAyC;AACzC,gDAAwB;AAOxB;;GAEG;AACI,KAAK,UAAU,eAAe,CAAC,IAAY;IAChD,OAAO,CAAC,MAAM,kBAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,KAAK,CAAC;AACpE,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,wBAAwB,CAC5C,WAAmB,EACnB,YAA0B,EAC1B,OAAqB;IAErB,MAAM,UAAU,GAAG,WAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,GAAG,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;IAClF,MAAM,GAAG,GAAG,OAAO,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1E,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QACpC,IAAI,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,cAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,QAAQ,GAAG,cAAI,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACzC,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACjD,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,0BAA0B,CAC9C,WAAmB,EACnB,YAA0B,EAC1B,OAAqB;IAErB,MAAM,UAAU,GAAG,WAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,GAAG,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;IAClF,MAAM,GAAG,GAAG,OAAO,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1E,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QACpC,IAAI,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,cAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,QAAQ,GAAG,cAAI,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACzC,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACjD,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;YACpB,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import fs from 'fs/promises';\nimport { glob, GlobOptions } from 'glob';\nimport path from 'path';\n\n/**\n * A matching function that takes a file path and its contents and returns a string if it matches, or null otherwise.\n */\ntype MatchFunctor = (filePath: string, contents: Buffer) => string | null;\n\n/**\n * Check if the file exists.\n */\nexport async function fileExistsAsync(file: string): Promise<boolean> {\n return (await fs.stat(file).catch(() => null))?.isFile() ?? false;\n}\n\n/**\n * Search files that match the glob pattern and return all matches from the matchFunctor.\n */\nexport async function globMatchFunctorAllAsync(\n globPattern: string,\n matchFunctor: MatchFunctor,\n options?: GlobOptions\n): Promise<string[]> {\n const globStream = glob.stream(globPattern, { ...options, withFileTypes: false });\n const cwd = options?.cwd !== undefined ? `${options.cwd}` : process.cwd();\n const results: string[] = [];\n for await (const file of globStream) {\n let filePath = file.toString();\n if (!path.isAbsolute(filePath)) {\n filePath = path.resolve(cwd, filePath);\n }\n const contents = await fs.readFile(filePath);\n const matched = matchFunctor(filePath, contents);\n if (matched != null) {\n results.push(matched);\n }\n }\n return results;\n}\n\n/**\n * Search files that match the glob pattern and return the first match from the matchFunctor.\n */\nexport async function globMatchFunctorFirstAsync(\n globPattern: string,\n matchFunctor: MatchFunctor,\n options?: GlobOptions\n): Promise<string | null> {\n const globStream = glob.stream(globPattern, { ...options, withFileTypes: false });\n const cwd = options?.cwd !== undefined ? `${options.cwd}` : process.cwd();\n for await (const file of globStream) {\n let filePath = file.toString();\n if (!path.isAbsolute(filePath)) {\n filePath = path.resolve(cwd, filePath);\n }\n const contents = await fs.readFile(filePath);\n const matched = matchFunctor(filePath, contents);\n if (matched != null) {\n return matched;\n }\n }\n return null;\n}\n"]}
1
+ {"version":3,"file":"fileUtils.js","sourceRoot":"","sources":["../src/fileUtils.ts"],"names":[],"mappings":";;;;;AAYA,0CAEC;AAKD,4DAuBC;AAKD,gEAmBC;AAlED,2DAA6B;AAC7B,+BAAyC;AACzC,gDAAwB;AAOxB;;GAEG;AACI,KAAK,UAAU,eAAe,CAAC,IAAY;IAChD,OAAO,CAAC,MAAM,kBAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,KAAK,CAAC;AACpE,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,wBAAwB,CAC5C,WAAmB,EACnB,YAA0B,EAC1B,OAAqB;IAErB,MAAM,UAAU,GAAG,WAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACrE,MAAM,GAAG,GAAG,OAAO,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1E,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,KAAK,EAAE,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;QACxC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YACvB,SAAS;QACX,CAAC;QACD,IAAI,QAAQ,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACnC,IAAI,CAAC,cAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,QAAQ,GAAG,cAAI,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACzC,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACjD,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,0BAA0B,CAC9C,WAAmB,EACnB,YAA0B,EAC1B,OAAqB;IAErB,MAAM,UAAU,GAAG,WAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,GAAG,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;IAClF,MAAM,GAAG,GAAG,OAAO,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1E,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QACpC,IAAI,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,cAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,QAAQ,GAAG,cAAI,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACzC,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACjD,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;YACpB,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import fs from 'fs/promises';\nimport { glob, GlobOptions } from 'glob';\nimport path from 'path';\n\n/**\n * A matching function that takes a file path and its contents and returns a string if it matches, or null otherwise.\n */\ntype MatchFunctor = (filePath: string, contents: Buffer) => string | null;\n\n/**\n * Check if the file exists.\n */\nexport async function fileExistsAsync(file: string): Promise<boolean> {\n return (await fs.stat(file).catch(() => null))?.isFile() ?? false;\n}\n\n/**\n * Search files that match the glob pattern and return all matches from the matchFunctor.\n */\nexport async function globMatchFunctorAllAsync(\n globPattern: string,\n matchFunctor: MatchFunctor,\n options?: GlobOptions\n): Promise<string[]> {\n const globStream = glob.stream(globPattern, { withFileTypes: true });\n const cwd = options?.cwd !== undefined ? `${options.cwd}` : process.cwd();\n const results: string[] = [];\n for await (const globPath of globStream) {\n if (!globPath.isFile()) {\n continue;\n }\n let filePath = globPath.fullpath();\n if (!path.isAbsolute(filePath)) {\n filePath = path.resolve(cwd, filePath);\n }\n const contents = await fs.readFile(filePath);\n const matched = matchFunctor(filePath, contents);\n if (matched != null) {\n results.push(matched);\n }\n }\n return results;\n}\n\n/**\n * Search files that match the glob pattern and return the first match from the matchFunctor.\n */\nexport async function globMatchFunctorFirstAsync(\n globPattern: string,\n matchFunctor: MatchFunctor,\n options?: GlobOptions\n): Promise<string | null> {\n const globStream = glob.stream(globPattern, { ...options, withFileTypes: false });\n const cwd = options?.cwd !== undefined ? `${options.cwd}` : process.cwd();\n for await (const file of globStream) {\n let filePath = file.toString();\n if (!path.isAbsolute(filePath)) {\n filePath = path.resolve(cwd, filePath);\n }\n const contents = await fs.readFile(filePath);\n const matched = matchFunctor(filePath, contents);\n if (matched != null) {\n return matched;\n }\n }\n return null;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-modules-autolinking",
3
- "version": "3.0.14",
3
+ "version": "3.0.16",
4
4
  "description": "Scripts that autolink Expo modules.",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -46,5 +46,5 @@
46
46
  "require-from-string": "^2.0.2",
47
47
  "resolve-from": "^5.0.0"
48
48
  },
49
- "gitHead": "1ab3b9621b78b77b81049ebf06149753a1e0898c"
49
+ "gitHead": "ea56136a4420322f46d00e4b1549595d8f85150e"
50
50
  }
@@ -22,10 +22,91 @@ module Pod
22
22
  class Installer
23
23
  private
24
24
 
25
+ _original_run_podfile_post_install_hooks = instance_method(:run_podfile_post_install_hooks)
25
26
  _original_run_podfile_pre_install_hooks = instance_method(:run_podfile_pre_install_hooks)
27
+ _script_phase_name = '[Expo Autolinking] Run Codegen with autolinking'
26
28
 
27
29
  public
28
30
 
31
+ define_method(:run_podfile_post_install_hooks) do
32
+ # Call original implementation first
33
+ _original_run_podfile_post_install_hooks.bind(self).()
34
+
35
+ # Next we'll perform an Expo workaround for Codegen in React Native where it uses the wrong output path for
36
+ # the generated files. This can be remove when the following PR is merged and released upstream:
37
+ # https://github.com/facebook/react-native/pull/54066
38
+ # TODO: chrfalch - remove when RN PR is released
39
+ # Find the ReactCodegen pod target in the pods project
40
+ react_codegen_native_target = self.pods_project.targets.find { |target| target.name == 'ReactCodegen' }
41
+
42
+ if react_codegen_native_target
43
+ # Check if the build phase already exists
44
+ already_exists = react_codegen_native_target.build_phases.any? do |phase|
45
+ phase.is_a?(Xcodeproj::Project::Object::PBXShellScriptBuildPhase) && phase.name == _script_phase_name
46
+ end
47
+
48
+ if !already_exists
49
+ Pod::UI.puts "[Expo] ".blue + "Adding '#{_script_phase_name}' build phase to ReactCodegen"
50
+
51
+ # Create the new shell script build phase
52
+ phase = react_codegen_native_target.new_shell_script_build_phase(_script_phase_name)
53
+ phase.shell_path = '/bin/sh'
54
+ phase.shell_script = <<~SH
55
+ # Remove this step when the fix is merged and released.
56
+ # See: https://github.com/facebook/react-native/pull/54066
57
+
58
+ # This re-runs Codegen without the broken "scripts/react_native_pods_utils/script_phases.sh" script, causing Codegen to run without autolinking.
59
+ # Instead of using "script_phases.sh" which always runs inside DerivedData, we run it in the normal "/ios" folder
60
+ # See: https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods_utils/script_phases.sh
61
+ pushd "$PODS_ROOT/../" > /dev/null
62
+ RCT_SCRIPT_POD_INSTALLATION_ROOT="$PODS_ROOT/.."
63
+ popd >/dev/null
64
+
65
+ export RCT_SCRIPT_RN_DIR="$REACT_NATIVE_PATH" # This is set by Expo
66
+ export RCT_SCRIPT_APP_PATH="$RCT_SCRIPT_POD_INSTALLATION_ROOT/.."
67
+ export RCT_SCRIPT_OUTPUT_DIR="$RCT_SCRIPT_POD_INSTALLATION_ROOT"
68
+ export RCT_SCRIPT_TYPE="withCodegenDiscovery"
69
+
70
+ # This is the broken script that runs inside DerivedData, meaning it can't find the autolinking result in `ios/build/generated/autolinking.json`.
71
+ # Resulting in Codegen running with it's own autolinking, not discovering transitive peer dependencies.
72
+ # export SCRIPT_PHASES_SCRIPT="$RCT_SCRIPT_RN_DIR/scripts/react_native_pods_utils/script_phases.sh"
73
+ export WITH_ENVIRONMENT="$RCT_SCRIPT_RN_DIR/scripts/xcode/with-environment.sh"
74
+
75
+ # Start of workaround code
76
+
77
+ # Load the $NODE_BINARY from the "with-environment.sh" script
78
+ source "$WITH_ENVIRONMENT"
79
+
80
+ # Run this script directly in the right folders:
81
+ # https://github.com/facebook/react-native/blob/3f7f9d8fb8beb41408d092870a7c7cac58029a4d/packages/react-native/scripts/react_native_pods_utils/script_phases.sh#L96-L101
82
+ pushd "$RCT_SCRIPT_RN_DIR" >/dev/null || exit 1
83
+ set -x
84
+ "$NODE_BINARY" "scripts/generate-codegen-artifacts.js" --path "$RCT_SCRIPT_APP_PATH" --outputPath "$RCT_SCRIPT_OUTPUT_DIR" --targetPlatform "ios"
85
+ set +x
86
+ popd >/dev/null || exit 1
87
+
88
+ # End of workaround code
89
+ SH
90
+
91
+ # Find the index of the "Compile Sources" phase (PBXSourcesBuildPhase)
92
+ compile_sources_index = react_codegen_native_target.build_phases.find_index do |p|
93
+ p.is_a?(Xcodeproj::Project::Object::PBXSourcesBuildPhase)
94
+ end
95
+
96
+ if compile_sources_index
97
+ # Remove the phase from its current position (it was added at the end)
98
+ react_codegen_native_target.build_phases.delete(phase)
99
+ # Insert it before the "Compile Sources" phase
100
+ react_codegen_native_target.build_phases.insert(compile_sources_index, phase)
101
+ else
102
+ Pod::UI.puts "[Expo] ".yellow + "Could not find 'Compile Sources' phase, build phase added at default position"
103
+ end
104
+ end
105
+ else
106
+ Pod::UI.puts "[Expo] ".yellow + "ReactCodegen target not found in pods project"
107
+ end
108
+ end
109
+
29
110
  define_method(:run_podfile_pre_install_hooks) do
30
111
  # Call original implementation first
31
112
  _original_run_podfile_pre_install_hooks.bind(self).()
@@ -18,6 +18,9 @@ import {
18
18
  scanDependencyResolutionsForPlatform,
19
19
  } from '../dependencies';
20
20
 
21
+ // NOTE(@kitten): These are excluded explicitly, but we want to include them for the verify command explicitly
22
+ const INCLUDE_PACKAGES = ['react-native', 'react-native-tvos'];
23
+
21
24
  interface VerifyArguments extends AutolinkingCommonArguments {
22
25
  verbose?: boolean | null;
23
26
  json?: boolean | null;
@@ -40,7 +43,9 @@ export function verifyCommand(cli: commander.CommanderStatic) {
40
43
  const linker = makeCachedDependenciesLinker({ projectRoot: appRoot });
41
44
  const results = mergeResolutionResults(
42
45
  await Promise.all(
43
- platforms.map((platform) => scanDependencyResolutionsForPlatform(linker, platform))
46
+ platforms.map((platform) =>
47
+ scanDependencyResolutionsForPlatform(linker, platform, INCLUDE_PACKAGES)
48
+ )
44
49
  )
45
50
  );
46
51
  await verifySearchResults(results, {
@@ -49,7 +49,7 @@ export const maybeRealpath = async (target: string): Promise<string | null> => {
49
49
  }
50
50
  };
51
51
 
52
- export type PackageJson = Record<string, unknown> & { name: string; version?: string };
52
+ export type PackageJson = Record<string, unknown> & { version?: string };
53
53
 
54
54
  export const loadPackageJson = memoize(async function loadPackageJson(
55
55
  jsonPath: string
@@ -59,8 +59,6 @@ export const loadPackageJson = memoize(async function loadPackageJson(
59
59
  const json = JSON.parse(packageJsonText);
60
60
  if (typeof json !== 'object' || json == null) {
61
61
  return null;
62
- } else if (typeof json.name !== 'string' || !json.name) {
63
- return null;
64
62
  }
65
63
  return json;
66
64
  } catch {
package/src/fileUtils.ts CHANGED
@@ -22,11 +22,14 @@ export async function globMatchFunctorAllAsync(
22
22
  matchFunctor: MatchFunctor,
23
23
  options?: GlobOptions
24
24
  ): Promise<string[]> {
25
- const globStream = glob.stream(globPattern, { ...options, withFileTypes: false });
25
+ const globStream = glob.stream(globPattern, { withFileTypes: true });
26
26
  const cwd = options?.cwd !== undefined ? `${options.cwd}` : process.cwd();
27
27
  const results: string[] = [];
28
- for await (const file of globStream) {
29
- let filePath = file.toString();
28
+ for await (const globPath of globStream) {
29
+ if (!globPath.isFile()) {
30
+ continue;
31
+ }
32
+ let filePath = globPath.fullpath();
30
33
  if (!path.isAbsolute(filePath)) {
31
34
  filePath = path.resolve(cwd, filePath);
32
35
  }