feat(tools-react-native): Add mergeTransformerConfigs function to @rnx-kit/tools-react-native#4044
Open
feat(tools-react-native): Add mergeTransformerConfigs function to @rnx-kit/tools-react-native#4044
Conversation
tido64
reviewed
Mar 25, 2026
| * Type guard to check if a value is a plain object (i.e., a record). This is used to ensure that we only attempt to | ||
| * recursively merge plain objects in the `simpleObjectMerge` function. | ||
| */ | ||
| function isRecord(value: unknown): value is Record<string, unknown> { |
Member
There was a problem hiding this comment.
Should this be parameterized?
Suggested change
| function isRecord(value: unknown): value is Record<string, unknown> { | |
| function isRecord<K extends string | number = string, V = unknown>(value: unknown): value is Record<K, V> { |
| function simpleObjectMerge( | ||
| ...options: Record<string, unknown>[] | ||
| ): Record<string, unknown> { | ||
| /** @type {Record<string, unknown>} */ |
Member
There was a problem hiding this comment.
Stray JSDoc
Suggested change
| /** @type {Record<string, unknown>} */ |
Comment on lines
+65
to
+67
| const getTransformOptionsFns = configs | ||
| .map((config) => config?.getTransformOptions) | ||
| .filter((fn) => typeof fn === "function"); |
Member
There was a problem hiding this comment.
Whenever you see .map followed by .filter, please rewrite it as .reduce or a for-loop instead:
Suggested change
| const getTransformOptionsFns = configs | |
| .map((config) => config?.getTransformOptions) | |
| .filter((fn) => typeof fn === "function"); | |
| const getTransformOptionsFns = configs | |
| .reduce<TransformerConfigT["getTransformOptions"][]>((result, config) => { | |
| const getTransformOptions = config?.getTransformOptions; | |
| if (typeof getTransformOptions === "function") { | |
| result.push(getTransformOptions); | |
| } | |
| return result; | |
| }, []); |
JavaScript's implementation is eager and will cause additional unnecessary allocations.
Comment on lines
+25
to
+27
| equal(result.minifierPath, "/minifier-b"); | ||
| equal(result.hermesParser, false); | ||
| equal(result.enableBabelRuntime, true); |
Member
There was a problem hiding this comment.
Can we use deepEqual to ensure that nothing else gets added?
| { hermesParser: false }, | ||
| { hermesParser: true } | ||
| ); | ||
| equal(result.hermesParser, true); |
Member
There was a problem hiding this comment.
Can we use deepEqual to ensure that nothing else gets added?
| transform: { | ||
| experimentalImportSupport: true, | ||
| inlineRequires: false, | ||
| nonInlinedRequires: ["react"], |
Member
There was a problem hiding this comment.
Can you add a test for how arrays should be handled?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This adds a utility for merging transformer configurations to tools-react-native to help with transformer merging. I added this as part of a new submodule called metro-utils for general metro utility functions.
I considered various other places for this. The main package it would make sense in is @rnx-kit/metro-config but that isn't a utility package used by other packages in react-native and has issues if you try to include it as a dependency of the cli. Given the already existing utilities for resolving packages from metro it made the most sense to add it to tools-react-native.
The function itself is straightforward and will perform a flat merge (which is what metro does) except if there are multiple getTransformOptions implementations in which case they will be wrapped with the results merged together in order of precedence. This function is used to initialize the babel transformers, it is called once with the results being serialized via json to the metro transformers.
Having the merge function be baked into the CLI is required so that any transform options being set by a transformer configuration don't get stomped by the esbuild transformer which is always added at the end. The esbuild transform options will take precedence still, but things like custom options can still be used in this case.