Skip to content

Commit 495ab48

Browse files
authored
fix: workaround for bunx picking the wrong binary (#2418)
`bunx react-native-test-app init` is not equivalent to `npx --package react-native-test-app init`. As of 1.2.5, `bunx` always picks the first binary (which used to be `configure-test-app`), making it look like the `init` command failed. By making `init` first, we get around this issue.
1 parent 4b9e162 commit 495ab48

File tree

6 files changed

+90
-38
lines changed

6 files changed

+90
-38
lines changed

.yarn/plugins/boost-workaround.cjs

+5-12
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
* @typedef {{ configuration: Configuration; cwd: string; workspaces: Workspace[]; }} Project
66
* @typedef {{ mode?: "skip-build" | "update-lockfile"; }} InstallOptions
77
*
8-
* @type {{ name: string; factory: (require: NodeRequire) => unknown; }}
8+
* @type {{ name: string; factory: (require: NodeJS.Require) => unknown; }}
99
*/
1010
module.exports = {
1111
name: "plugin-boost-workaround",
12-
factory: (_require) => ({
12+
factory: (require) => ({
1313
hooks: {
1414
/** @type {(project: Project, options: InstallOptions) => void} */
1515
afterAllInstalled(project, options) {
@@ -25,6 +25,7 @@ module.exports = {
2525
return;
2626
}
2727

28+
const { npath } = require("@yarnpkg/fslib");
2829
const fs = require("node:fs");
2930
const path = require("node:path");
3031

@@ -33,18 +34,10 @@ module.exports = {
3334
"node_modules/react-native-macos/third-party-podspecs/boost.podspec",
3435
];
3536

36-
/**
37-
* @param {string} p
38-
* @returns {string}
39-
*/
40-
function normalize(p) {
41-
// On Windows, paths are prefixed with `/`
42-
return p.replace(/^[/\\]([^/\\]+:[/\\])/, "$1");
43-
}
44-
4537
for (const ws of project.workspaces) {
4638
for (const boostPodspec of boostPodspecs) {
47-
const podspecPath = path.join(normalize(ws.cwd), boostPodspec);
39+
const workspaceDir = npath.fromPortablePath(ws.cwd);
40+
const podspecPath = path.join(workspaceDir, boostPodspec);
4841
if (!fs.existsSync(podspecPath)) {
4942
continue;
5043
}

.yarn/plugins/link-project.cjs

+6-13
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
* @typedef {{ configuration: Configuration; cwd: string; workspaces: Workspace[]; }} Project
66
* @typedef {{ mode?: "skip-build" | "update-lockfile"; }} InstallOptions
77
*
8-
* @type {{ name: string; factory: (require: NodeRequire) => unknown; }}
8+
* @type {{ name: string; factory: (require: NodeJS.Require) => unknown; }}
99
*/
1010
module.exports = {
1111
name: "plugin-link-project",
12-
factory: (_require) => ({
12+
factory: (require) => ({
1313
hooks: {
1414
/** @type {(project: Project, options: InstallOptions) => void} */
1515
afterAllInstalled(project, options) {
@@ -25,23 +25,15 @@ module.exports = {
2525
return;
2626
}
2727

28+
const { npath } = require("@yarnpkg/fslib");
2829
const fs = require("node:fs");
2930
const path = require("node:path");
3031

31-
/**
32-
* @param {string} p
33-
* @returns {string}
34-
*/
35-
function normalize(p) {
36-
// On Windows, paths are prefixed with `/`
37-
return p.replace(/^[/\\]([^/\\]+:[/\\])/, "$1");
38-
}
39-
4032
const noop = () => null;
4133
const mkdirOptions = { recursive: true, mode: 0o755 };
4234
const rmOptions = { force: true, maxRetries: 3, recursive: true };
4335

44-
const projectRoot = normalize(project.cwd);
36+
const projectRoot = npath.fromPortablePath(project.cwd);
4537
const manifestPath = path.join(projectRoot, "package.json");
4638

4739
fs.readFile(manifestPath, { encoding: "utf-8" }, (_err, manifest) => {
@@ -52,7 +44,8 @@ module.exports = {
5244
continue;
5345
}
5446

55-
const nodeModulesDir = path.join(normalize(ws.cwd), "node_modules");
47+
const workspaceDir = npath.fromPortablePath(ws.cwd);
48+
const nodeModulesDir = path.join(workspaceDir, "node_modules");
5649
const linkPath = path.join(nodeModulesDir, name);
5750

5851
fs.readlink(linkPath, (err, linkString) => {

.yarn/plugins/npm-workaround.cjs

+5-12
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
* @typedef {{ configuration: Configuration; cwd: string; workspaces: Workspace[]; }} Project
66
* @typedef {{ mode?: "skip-build" | "update-lockfile"; }} InstallOptions
77
*
8-
* @type {{ name: string; factory: (require: NodeRequire) => unknown; }}
8+
* @type {{ name: string; factory: (require: NodeJS.Require) => unknown; }}
99
*/
1010
module.exports = {
1111
name: "plugin-npm-workaround",
12-
factory: (_require) => ({
12+
factory: (require) => ({
1313
hooks: {
1414
/** @type {(project: Project, options: InstallOptions) => void} */
1515
afterAllInstalled(project, options) {
@@ -25,25 +25,18 @@ module.exports = {
2525
return;
2626
}
2727

28+
const { npath } = require("@yarnpkg/fslib");
2829
const fs = require("node:fs");
2930
const path = require("node:path");
3031

3132
const filesToPatch = [
3233
"node_modules/@react-native-community/cli/build/tools/npm.js",
3334
];
3435

35-
/**
36-
* @param {string} p
37-
* @returns {string}
38-
*/
39-
function normalize(p) {
40-
// On Windows, paths are prefixed with `/`
41-
return p.replace(/^[/\\]([^/\\]+:[/\\])/, "$1");
42-
}
43-
4436
for (const ws of project.workspaces) {
4537
for (const file of filesToPatch) {
46-
const jsPath = path.join(normalize(ws.cwd), file);
38+
const workspaceDir = npath.fromPortablePath(ws.cwd);
39+
const jsPath = path.join(workspaceDir, file);
4740
if (!fs.existsSync(jsPath)) {
4841
continue;
4942
}

.yarn/plugins/undo-bin-sorting.cjs

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// @ts-check
2+
/**
3+
* @typedef {{ values: Map<string, unknown>; }} Configuration
4+
* @typedef {{ cwd: string; }} Workspace
5+
* @typedef {{ configuration: Configuration; cwd: string; workspaces: Workspace[]; }} Project
6+
* @typedef {{ mode?: "skip-build" | "update-lockfile"; }} InstallOptions
7+
*/
8+
9+
/**
10+
* Yarn always sorts `package.json` during install. This is problematic because
11+
* we need the `bin` field to be in a specific order to workaround an issue with
12+
* `bunx` always picking the first binary.
13+
*
14+
* For more context, see:
15+
*
16+
* - https://github.com/microsoft/react-native-test-app/issues/2417
17+
* - https://github.com/yarnpkg/berry/issues/6184
18+
*
19+
* @type {{ name: string; factory: (require: NodeJS.Require) => unknown; }}
20+
*/
21+
module.exports = {
22+
name: "plugin-undo-bin-sorting",
23+
factory: (require) => {
24+
const { npath } = require("@yarnpkg/fslib");
25+
const fs = require("node:fs");
26+
const path = require("node:path");
27+
28+
const asText = /** @type {const} */ ({ encoding: "utf-8" });
29+
30+
let manifestPath = "";
31+
let orig_rawManifest = "";
32+
return {
33+
hooks: {
34+
/** @type {(project: Project) => void} */
35+
validateProject(project) {
36+
const projectRoot = npath.fromPortablePath(project.cwd);
37+
manifestPath = path.join(projectRoot, "package.json");
38+
orig_rawManifest = fs.readFileSync(manifestPath, asText);
39+
},
40+
/** @type {(project: Project, options: InstallOptions) => void} */
41+
afterAllInstalled() {
42+
const rawManifest = fs.readFileSync(manifestPath, asText);
43+
if (rawManifest === orig_rawManifest) {
44+
return;
45+
}
46+
47+
const manifest = JSON.parse(rawManifest);
48+
const bin = Object.keys(manifest.bin);
49+
50+
const orig_manifest = JSON.parse(orig_rawManifest);
51+
const orig_bin = Object.keys(orig_manifest.bin);
52+
53+
const length = bin.length;
54+
if (length !== orig_bin.length) {
55+
throw new Error("Did Yarn add something to the 'bin' field?");
56+
}
57+
58+
for (let i = 0; i < length; ++i) {
59+
if (bin[i] !== orig_bin[i]) {
60+
manifest.bin = orig_manifest.bin;
61+
const fd = fs.openSync(manifestPath, "w", 0o644);
62+
fs.writeSync(fd, JSON.stringify(manifest, undefined, 2));
63+
fs.writeSync(fd, "\n");
64+
fs.closeSync(fd);
65+
break;
66+
}
67+
}
68+
},
69+
},
70+
};
71+
},
72+
};

.yarnrc.yml

+1
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ plugins:
2525
- path: .yarn/plugins/link-project.cjs
2626
- path: .yarn/plugins/boost-workaround.cjs
2727
- path: .yarn/plugins/npm-workaround.cjs
28+
- path: .yarn/plugins/undo-bin-sorting.cjs
2829
tsEnableAutoTypes: false
2930
yarnPath: .yarn/releases/yarn-4.6.0.cjs

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@
5656
],
5757
"main": "scripts/configure-projects.js",
5858
"bin": {
59-
"configure-test-app": "scripts/configure.mjs",
6059
"init": "scripts/init.mjs",
6160
"init-test-app": "scripts/init.mjs",
61+
"configure-test-app": "scripts/configure.mjs",
6262
"install-windows-test-app": "windows/test-app.mjs"
6363
},
6464
"repository": {

0 commit comments

Comments
 (0)