Skip to content

Commit 3c50fbd

Browse files
committed
undo bin sorting
1 parent d8efd7f commit 3c50fbd

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

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

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
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+
27+
const asText = /** @type {const} */ ({ encoding: "utf-8" });
28+
29+
let manifestPath = "";
30+
let orig_rawManifest = "";
31+
return {
32+
hooks: {
33+
/** @type {(project: Project) => void} */
34+
validateProject(project) {
35+
const pp = npath.join(project.cwd, "package.json");
36+
manifestPath = npath.fromPortablePath(pp);
37+
orig_rawManifest = fs.readFileSync(manifestPath, asText);
38+
},
39+
/** @type {(project: Project, options: InstallOptions) => void} */
40+
afterAllInstalled() {
41+
const rawManifest = fs.readFileSync(manifestPath, asText);
42+
if (rawManifest === orig_rawManifest) {
43+
return;
44+
}
45+
46+
const manifest = JSON.parse(rawManifest);
47+
const bin = Object.keys(manifest.bin);
48+
49+
const orig_manifest = JSON.parse(orig_rawManifest);
50+
const orig_bin = Object.keys(orig_manifest.bin);
51+
52+
const length = bin.length;
53+
if (length !== orig_bin.length) {
54+
throw new Error("Did Yarn add something to the 'bin' field?");
55+
}
56+
57+
for (let i = 0; i < length; ++i) {
58+
if (bin[i] !== orig_bin[i]) {
59+
manifest.bin = orig_manifest.bin;
60+
const fd = fs.openSync(manifestPath, "w", 0o644);
61+
fs.writeSync(fd, JSON.stringify(manifest, undefined, 2));
62+
fs.writeSync(fd, "\n");
63+
fs.closeSync(fd);
64+
break;
65+
}
66+
}
67+
},
68+
},
69+
};
70+
},
71+
};

.yarnrc.yml

Lines changed: 1 addition & 0 deletions
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

0 commit comments

Comments
 (0)