Skip to content

Commit 49dd266

Browse files
authored
Update yarn to the latest stable version and add dynamic-extensions plugin (#3924)
* update yarn to 4.9.2 * add dynamic-extensions plugin * add some basic dynamic extension configuration
1 parent 479b93c commit 49dd266

File tree

7 files changed

+1094
-937
lines changed

7 files changed

+1094
-937
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// @ts-check
2+
3+
/**
4+
* @import { Configuration, Hooks, Manifest, PackageExtensionData, Plugin } from "@yarnpkg/core";
5+
* @import { PortablePath } from "@yarnpkg/fslib";
6+
* @typedef {{ cwd: string; manifest: Manifest["raw"]; }} Workspace;
7+
*/
8+
9+
const DYNAMIC_PACKAGE_EXTENSIONS_KEY = "dynamicPackageExtensions";
10+
11+
// This module *must* be CommonJS because `actions/setup-node` (and probably
12+
// other GitHub actions) does not support ESM. Yarn itself does.
13+
exports.name = "@rnx-kit/yarn-plugin-dynamic-extensions";
14+
15+
/** @type {(require: NodeJS.Require) => Plugin<Hooks>} */
16+
exports.factory = (require) => {
17+
const { Project, SettingsType, structUtils } = require("@yarnpkg/core");
18+
const { npath } = require("@yarnpkg/fslib");
19+
20+
/**
21+
* @param {Configuration} configuration
22+
* @param {PortablePath} projectRoot
23+
* @returns {Promise<((ws: Workspace) => PackageExtensionData | undefined) | void>}
24+
*/
25+
async function loadUserExtensions(configuration, projectRoot) {
26+
const packageExtensions = configuration.get(DYNAMIC_PACKAGE_EXTENSIONS_KEY);
27+
if (typeof packageExtensions !== "string") {
28+
return;
29+
}
30+
31+
const path = require("node:path");
32+
const { pathToFileURL } = require("node:url");
33+
34+
// Make sure we resolve user extensions relative to the source config
35+
const source = configuration.sources.get(DYNAMIC_PACKAGE_EXTENSIONS_KEY);
36+
const sourceDir = source ? npath.dirname(source) : projectRoot;
37+
38+
// On Windows, import paths must include the `file:` protocol.
39+
const root = npath.fromPortablePath(sourceDir);
40+
const url = pathToFileURL(path.resolve(root, packageExtensions));
41+
const external = await import(url.toString());
42+
return external?.default ?? external;
43+
}
44+
45+
/** @type {Plugin<Hooks>["configuration"] & Record<string, unknown>} */
46+
const configuration = {};
47+
configuration[DYNAMIC_PACKAGE_EXTENSIONS_KEY] = {
48+
description: "Path to module providing package extensions",
49+
type: SettingsType.STRING,
50+
};
51+
52+
return {
53+
configuration,
54+
hooks: {
55+
registerPackageExtensions: async (
56+
configuration,
57+
registerPackageExtension
58+
) => {
59+
const { projectCwd } = configuration;
60+
if (!projectCwd) {
61+
return;
62+
}
63+
64+
const getUserExtensions = await loadUserExtensions(
65+
configuration,
66+
projectCwd
67+
);
68+
if (!getUserExtensions) {
69+
return;
70+
}
71+
72+
const { workspace } = await Project.find(configuration, projectCwd);
73+
if (!workspace) {
74+
return;
75+
}
76+
77+
workspace.project.workspacesByCwd.forEach(({ cwd, manifest }) => {
78+
const { name, version, raw } = manifest;
79+
if (!name || !version) {
80+
return;
81+
}
82+
83+
/** @type {Workspace} */
84+
const workspace = { cwd: npath.fromPortablePath(cwd), manifest: raw };
85+
const data = getUserExtensions(workspace);
86+
if (!data) {
87+
return;
88+
}
89+
90+
const descriptor = structUtils.makeDescriptor(name, version);
91+
registerPackageExtension(descriptor, data);
92+
});
93+
},
94+
},
95+
};
96+
};

.yarn/releases/yarn-4.6.0.cjs

Lines changed: 0 additions & 934 deletions
This file was deleted.

.yarn/releases/yarn-4.9.2.cjs

Lines changed: 942 additions & 0 deletions
Large diffs are not rendered by default.

.yarnrc.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1+
dynamicPackageExtensions: ./scripts/dynamic.extensions.mjs
2+
13
enableGlobalCache: false
24

35
nodeLinker: node-modules
46

5-
yarnPath: .yarn/releases/yarn-4.6.0.cjs
7+
plugins:
8+
- checksum: 672e525b81762c6162366bd3ffec5e86ab8fac2655ef0267047e86a0f32e79a4bde0f170bc30479663f40aa3f006d91f8dc3289f679dd4dc5ae5a5d12ba3ad0b
9+
path: .yarn/plugins/@rnx-kit/yarn-plugin-dynamic-extensions.cjs
10+
spec: "https://raw.githubusercontent.com/microsoft/rnx-kit/main/incubator/yarn-plugin-dynamic-extensions/index.js"
11+
12+
yarnPath: .yarn/releases/yarn-4.9.2.cjs

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,5 +100,5 @@
100100
]
101101
}
102102
},
103-
"packageManager": "yarn@4.6.0"
103+
"packageManager": "yarn@4.9.2"
104104
}

scripts/dynamic.extensions.mjs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
import { fileURLToPath } from 'url';
4+
5+
/**
6+
* @param {Object} workspace The package currently being processed
7+
* @param {string} workspace.cwd Path of the current package
8+
* @param {Object} workspace.manifest The content of `package.json`
9+
* @returns {{
10+
* dependencies?: Record<string, string>;
11+
* peerDependencies?: Record<string, string>;
12+
* peerDependenciesMeta?: Record<string, { optional?: boolean }>;
13+
* }}
14+
*/
15+
16+
/**
17+
* These are the dependencies we want to ensure exist in each folder. They will not override
18+
* the dependencies in the package.json if already present.
19+
*/
20+
const scriptDependencies = getScriptFolderDependencies(['typescript', 'eslint', 'just-scripts']);
21+
22+
/**
23+
* Get the dependencies for the script folder, both `devDependencies` and `dependencies`
24+
* @param {string[]} keys - The keys of the dependencies to include
25+
* @returns {Record<string, string>} A map of dependencies for the script folder
26+
*/
27+
function getScriptFolderDependencies(keys) {
28+
const pkgJsonName = path.join(path.dirname(fileURLToPath(import.meta.url)), './package.json');
29+
const pkgJson = JSON.parse(fs.readFileSync(pkgJsonName, 'utf-8'));
30+
const mergedDeps = { ...pkgJson.devDependencies, ...pkgJson.dependencies };
31+
return Object.fromEntries(Object.entries(mergedDeps).filter(([key]) => keys.includes(key)));
32+
}
33+
34+
export default function ({ cwd, manifest }) {
35+
const dependenciesToAdd = {};
36+
Object.keys(scriptDependencies).forEach((key) => {
37+
if ((manifest?.dependencies && manifest.dependencies[key]) || (manifest?.devDependencies && manifest.devDependencies[key])) {
38+
// If the dependency already exists in the package.json, skip it
39+
return;
40+
}
41+
dependenciesToAdd[key] = scriptDependencies[key];
42+
});
43+
return {
44+
dependencies: dependenciesToAdd,
45+
};
46+
}

tester_deps/.yarnrc.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
yarnPath: ../.yarn/releases/yarn-4.6.0.cjs
1+
yarnPath: ../.yarn/releases/yarn-4.9.2.cjs

0 commit comments

Comments
 (0)