-
Notifications
You must be signed in to change notification settings - Fork 92
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(polyfills): introduce
@rnx-kit/polyfills
- Loading branch information
Showing
9 changed files
with
271 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# @rnx-kit/polyfills | ||
|
||
[![Build](https://github.com/microsoft/rnx-kit/actions/workflows/build.yml/badge.svg)](https://github.com/microsoft/rnx-kit/actions/workflows/build.yml) | ||
[![npm version](https://img.shields.io/npm/v/@rnx-kit/polyfills)](https://www.npmjs.com/package/@rnx-kit/polyfills) | ||
|
||
🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧 | ||
|
||
### THIS TOOL IS EXPERIMENTAL — USE WITH CAUTION | ||
|
||
🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧 | ||
|
||
This is a polyfills "autolinker" for Metro. It works like native module | ||
autolinking, but gathers polyfills from dependencies instead. | ||
|
||
> **Note** | ||
> | ||
> This package is temporary. Ideally, this should be upstreamed to | ||
> `@react-native-community/cli`. | ||
## Motivation | ||
|
||
This package is part of | ||
[React Native WebAPIs](https://github.com/microsoft/rnx-kit/pull/2504). | ||
|
||
## Installation | ||
|
||
```sh | ||
yarn add @rnx-kit/polyfills --dev | ||
``` | ||
|
||
or if you're using npm | ||
|
||
```sh | ||
npm add --save-dev @rnx-kit/polyfills | ||
``` | ||
|
||
## Usage | ||
|
||
```diff | ||
const { makeMetroConfig } = require("@rnx-kit/metro-config"); | ||
const { getPolyfills } = require("@rnx-kit/polyfills"); | ||
module.exports = makeMetroConfig({ | ||
+ serializer: { | ||
+ getPolyfills, | ||
+ }, | ||
}); | ||
``` |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
{ | ||
"private": true, | ||
"name": "@rnx-kit/polyfills", | ||
"version": "0.0.1", | ||
"description": "EXPERIMENTAL - USE WITH CAUTION - New package called polyfills", | ||
"homepage": "https://github.com/microsoft/rnx-kit/tree/main/incubator/polyfills#readme", | ||
"license": "MIT", | ||
"author": { | ||
"name": "Microsoft Open Source", | ||
"email": "microsoftopensource@users.noreply.github.com" | ||
}, | ||
"files": [ | ||
"lib/*" | ||
], | ||
"main": "lib/index.js", | ||
"types": "lib/index.d.ts", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/microsoft/rnx-kit", | ||
"directory": "incubator/polyfills" | ||
}, | ||
"engines": { | ||
"node": ">=14.15" | ||
}, | ||
"scripts": { | ||
"build": "rnx-kit-scripts build", | ||
"format": "rnx-kit-scripts format", | ||
"lint": "rnx-kit-scripts lint", | ||
"test": "rnx-kit-scripts test" | ||
}, | ||
"dependencies": { | ||
"@rnx-kit/console": "^1.0.0", | ||
"@rnx-kit/tools-node": "^2.0.0", | ||
"@rnx-kit/tools-react-native": "^1.3.1" | ||
}, | ||
"peerDependencies": { | ||
"@react-native/js-polyfills": "*", | ||
"react-native": ">=0.71.0" | ||
}, | ||
"peerDependenciesMeta": { | ||
"@react-native/js-polyfills": { | ||
"optional": true | ||
} | ||
}, | ||
"devDependencies": { | ||
"@rnx-kit/scripts": "*", | ||
"eslint": "^8.0.0", | ||
"jest": "^29.2.1", | ||
"metro-config": "^0.73.7", | ||
"prettier": "^3.0.0", | ||
"typescript": "^5.0.0" | ||
}, | ||
"eslintConfig": { | ||
"extends": "@rnx-kit/eslint-config" | ||
}, | ||
"jest": { | ||
"preset": "@rnx-kit/scripts" | ||
}, | ||
"rnx-kit": { | ||
"alignDeps": { | ||
"presets": [ | ||
"microsoft/react-native", | ||
"@rnx-kit/scripts/align-deps-preset.js" | ||
], | ||
"requirements": [ | ||
"react-native@0.71" | ||
], | ||
"capabilities": [ | ||
"metro-config" | ||
] | ||
} | ||
}, | ||
"experimental": true | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { error } from "@rnx-kit/console"; | ||
import { getAvailablePlatforms } from "@rnx-kit/tools-react-native"; | ||
import type { Context } from "./types"; | ||
|
||
function getDefaultPolyfillsPath({ | ||
platform, | ||
projectRoot, | ||
}: Context): string | null { | ||
const options = { paths: [projectRoot] }; | ||
|
||
try { | ||
return require.resolve("@react-native/js-polyfills", options); | ||
} catch (_) { | ||
// `@react-native/js-polyfills` is available from 0.72+ | ||
} | ||
|
||
const platforms = getAvailablePlatforms(projectRoot); | ||
const reactNativePath = platforms[platform || "ios"] || "react-native"; | ||
|
||
try { | ||
return require.resolve(`${reactNativePath}/rn-get-polyfills`, options); | ||
} catch (_) { | ||
error( | ||
`Could not find polyfills for '${platform}' — if this is expected, you can ignore this error message` | ||
); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
export function getDefaultPolyfills(context: Context): string[] { | ||
const defaultPolyfillsPath = getDefaultPolyfillsPath(context); | ||
return defaultPolyfillsPath ? require(defaultPolyfillsPath)() : []; | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { error } from "@rnx-kit/console"; | ||
import { readPackage } from "@rnx-kit/tools-node"; | ||
import * as path from "path"; | ||
import type { Context } from "./types"; | ||
|
||
function getDependencies({ projectRoot }: Context): string[] { | ||
const manifest = readPackage(projectRoot); | ||
|
||
const dependencies = new Set<string>(); | ||
for (const section of ["dependencies", "devDependencies"] as const) { | ||
const names = manifest[section]; | ||
if (names) { | ||
Object.keys(names).forEach((name) => dependencies.add(name)); | ||
} | ||
} | ||
|
||
return Array.from(dependencies); | ||
} | ||
|
||
function isValidPath(p: string): boolean { | ||
return ( | ||
Boolean(p) && | ||
!p.startsWith("..") && | ||
!p.startsWith("/") && | ||
!/^[A-Za-z]:/.test(p) | ||
); | ||
} | ||
|
||
export function getDependencyPolyfills(context: Context): string[] { | ||
const polyfills: string[] = []; | ||
|
||
const options = { paths: [context.projectRoot] }; | ||
const dependencies = getDependencies(context); | ||
|
||
for (const name of dependencies) { | ||
try { | ||
const config = require.resolve(`${name}/react-native.config.js`, options); | ||
const polyfill = require(config).dependency?.api?.polyfill; | ||
if (typeof polyfill === "string") { | ||
if (!isValidPath(polyfill)) { | ||
error(`${name}: invalid polyfill path: ${polyfill}`); | ||
continue; | ||
} | ||
|
||
polyfills.push(path.resolve(path.dirname(config), polyfill)); | ||
} | ||
} catch (_) { | ||
// ignore | ||
} | ||
} | ||
|
||
return polyfills; | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { getDefaultPolyfills } from "./defaultPolyfills"; | ||
import { getDependencyPolyfills } from "./dependency"; | ||
import type { GetPolyfills } from "./types"; | ||
|
||
export const getPolyfills: GetPolyfills = ({ platform }) => { | ||
const context = { platform, projectRoot: process.cwd() }; | ||
const polyfills = getDefaultPolyfills(context); | ||
const dependencyPolyfills = getDependencyPolyfills(context); | ||
return polyfills.concat(dependencyPolyfills); | ||
}; | ||
|
||
export default getPolyfills; |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import type { ConfigT } from "metro-config"; | ||
|
||
export type Context = { | ||
platform: string | null; | ||
projectRoot: string; | ||
}; | ||
|
||
export type GetPolyfills = ConfigT["serializer"]["getPolyfills"]; |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { getDefaultPolyfills } from "../src/defaultPolyfills"; | ||
|
||
describe("getDefaultPolyfills", () => { | ||
const context = { | ||
platform: "ios", | ||
projectRoot: process.cwd(), | ||
}; | ||
|
||
it("should return default polyfills", () => { | ||
const defaultPolyfills = getDefaultPolyfills(context).sort(); | ||
expect(defaultPolyfills).toEqual([ | ||
expect.stringMatching(/[/\\]@react-native[/\\]polyfills[/\\]Object.es8.js$/), | ||
expect.stringMatching(/[/\\]@react-native[/\\]polyfills[/\\]console.js$/), | ||
expect.stringMatching(/[/\\]@react-native[/\\]polyfills[/\\]error-guard.js$/), | ||
]); | ||
}); | ||
}); |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"extends": "@rnx-kit/scripts/tsconfig-shared.json", | ||
"include": ["src"] | ||
} |
This file contains 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