@rushstack/rush-resolver-cache-plugin 5.133.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +24 -0
- package/README.md +7 -0
- package/dist/rush-resolver-cache-plugin.d.ts +15 -0
- package/dist/tsdoc-metadata.json +11 -0
- package/lib/afterInstallAsync.d.ts +10 -0
- package/lib/afterInstallAsync.d.ts.map +1 -0
- package/lib/afterInstallAsync.js +115 -0
- package/lib/afterInstallAsync.js.map +1 -0
- package/lib/computeResolverCacheFromLockfileAsync.d.ts +60 -0
- package/lib/computeResolverCacheFromLockfileAsync.d.ts.map +1 -0
- package/lib/computeResolverCacheFromLockfileAsync.js +105 -0
- package/lib/computeResolverCacheFromLockfileAsync.js.map +1 -0
- package/lib/externals.d.ts +11 -0
- package/lib/externals.d.ts.map +1 -0
- package/lib/externals.js +24 -0
- package/lib/externals.js.map +1 -0
- package/lib/helpers.d.ts +37 -0
- package/lib/helpers.d.ts.map +1 -0
- package/lib/helpers.js +175 -0
- package/lib/helpers.js.map +1 -0
- package/lib/index.d.ts +10 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +60 -0
- package/lib/index.js.map +1 -0
- package/lib/types.d.ts +15 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +5 -0
- package/lib/types.js.map +1 -0
- package/package.json +43 -0
- package/rush-plugin-manifest.json +10 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
@rushstack/rush-pnpm-resolver-cache-plugin
|
|
2
|
+
|
|
3
|
+
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4
|
+
|
|
5
|
+
MIT License
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
8
|
+
a copy of this software and associated documentation files (the
|
|
9
|
+
"Software"), to deal in the Software without restriction, including
|
|
10
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
11
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
12
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
13
|
+
the following conditions:
|
|
14
|
+
|
|
15
|
+
The above copyright notice and this permission notice shall be
|
|
16
|
+
included in all copies or substantial portions of the Software.
|
|
17
|
+
|
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
19
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
20
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
21
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
22
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
23
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
24
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# @rushstack/rush-resolver-cache-plugin
|
|
2
|
+
|
|
3
|
+
A Rush plugin that runs after successful dependency installation and generates a cache file to optimize node module resolution.
|
|
4
|
+
|
|
5
|
+
When this plugin is installed, it will produce a file called `resolver-cache.json` in the temp directory of the default subspace, e.g. `<repo>/common/temp/default/resolver-cache.json`
|
|
6
|
+
|
|
7
|
+
To use this file, load it, call JSON.parse, and pass the result as the `cacheData` property to the `WorkspaceLayoutCache` constructor from `@rushstack/webpack-workspace-resolve-plugin`. The `workspaceRoot` property should be set to the path `<repo>`.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { IRushPlugin } from '@rushstack/rush-sdk';
|
|
2
|
+
import type { RushConfiguration } from '@rushstack/rush-sdk';
|
|
3
|
+
import type { RushSession } from '@rushstack/rush-sdk';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Plugin that caches information from the package manager after installation to speed up resolution of imports.
|
|
7
|
+
* @beta
|
|
8
|
+
*/
|
|
9
|
+
declare class RushResolverCachePlugin implements IRushPlugin {
|
|
10
|
+
readonly pluginName: 'RushResolverCachePlugin';
|
|
11
|
+
apply(rushSession: RushSession, rushConfiguration: RushConfiguration): void;
|
|
12
|
+
}
|
|
13
|
+
export default RushResolverCachePlugin;
|
|
14
|
+
|
|
15
|
+
export { }
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// This file is read by tools that parse documentation comments conforming to the TSDoc standard.
|
|
2
|
+
// It should be published with your NPM package. It should not be tracked by Git.
|
|
3
|
+
{
|
|
4
|
+
"tsdocVersion": "0.12",
|
|
5
|
+
"toolPackages": [
|
|
6
|
+
{
|
|
7
|
+
"packageName": "@microsoft/api-extractor",
|
|
8
|
+
"packageVersion": "7.47.7"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RushSession, RushConfiguration, ILogger, Subspace } from '@rushstack/rush-sdk';
|
|
2
|
+
/**
|
|
3
|
+
* Plugin entry point for after install.
|
|
4
|
+
* @param rushSession - The Rush Session
|
|
5
|
+
* @param rushConfiguration - The Rush Configuration
|
|
6
|
+
* @param subspace - The subspace that was just installed
|
|
7
|
+
* @param logger - The initialized logger
|
|
8
|
+
*/
|
|
9
|
+
export declare function afterInstallAsync(rushSession: RushSession, rushConfiguration: RushConfiguration, subspace: Subspace, logger: ILogger): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=afterInstallAsync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"afterInstallAsync.d.ts","sourceRoot":"","sources":["../src/afterInstallAsync.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,WAAW,EACX,iBAAiB,EAEjB,OAAO,EAEP,QAAQ,EACT,MAAM,qBAAqB,CAAC;AAgC7B;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,WAAW,EACxB,iBAAiB,EAAE,iBAAiB,EACpC,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,IAAI,CAAC,CAuGf"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
|
3
|
+
// See LICENSE in the project root for license information.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.afterInstallAsync = void 0;
|
|
6
|
+
const externals_1 = require("./externals");
|
|
7
|
+
const computeResolverCacheFromLockfileAsync_1 = require("./computeResolverCacheFromLockfileAsync");
|
|
8
|
+
/**
|
|
9
|
+
* Gets information used to determine compatibility of optional dependencies.
|
|
10
|
+
* @returns Information about the platform Rush is running on
|
|
11
|
+
*/
|
|
12
|
+
function getPlatformInfo() {
|
|
13
|
+
var _a, _b, _c;
|
|
14
|
+
// Acquiring the libc version is a bit more obnoxious than platform and arch,
|
|
15
|
+
// but all of them are ultimately on the same object.
|
|
16
|
+
const { platform: os, arch: cpu, glibcVersionRuntime
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
+
} = (_c = (_b = (_a = process.report) === null || _a === void 0 ? void 0 : _a.getReport()) === null || _b === void 0 ? void 0 : _b.header) !== null && _c !== void 0 ? _c : process;
|
|
19
|
+
const libc = glibcVersionRuntime ? 'glibc' : 'musl';
|
|
20
|
+
return {
|
|
21
|
+
os,
|
|
22
|
+
cpu,
|
|
23
|
+
libc
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Plugin entry point for after install.
|
|
28
|
+
* @param rushSession - The Rush Session
|
|
29
|
+
* @param rushConfiguration - The Rush Configuration
|
|
30
|
+
* @param subspace - The subspace that was just installed
|
|
31
|
+
* @param logger - The initialized logger
|
|
32
|
+
*/
|
|
33
|
+
async function afterInstallAsync(rushSession, rushConfiguration, subspace, logger) {
|
|
34
|
+
const { terminal } = logger;
|
|
35
|
+
const rushRoot = `${rushConfiguration.rushJsonFolder}/`;
|
|
36
|
+
const lockFilePath = subspace.getCommittedShrinkwrapFilename();
|
|
37
|
+
const workspaceRoot = subspace.getSubspaceTempFolderPath();
|
|
38
|
+
const projectByImporterPath = rushConfiguration.getProjectLookupForRoot(workspaceRoot);
|
|
39
|
+
const pnpmStoreDir = `${rushConfiguration.pnpmOptions.pnpmStorePath}/v3/files/`;
|
|
40
|
+
terminal.writeLine(`Using pnpm-lock from: ${lockFilePath}`);
|
|
41
|
+
terminal.writeLine(`Using pnpm store folder: ${pnpmStoreDir}`);
|
|
42
|
+
const lockFile = externals_1.PnpmShrinkwrapFile.loadFromFile(lockFilePath, {
|
|
43
|
+
withCaching: true
|
|
44
|
+
});
|
|
45
|
+
if (!lockFile) {
|
|
46
|
+
throw new Error(`Failed to load shrinkwrap file: ${lockFilePath}`);
|
|
47
|
+
}
|
|
48
|
+
const cacheFilePath = `${workspaceRoot}/resolver-cache.json`;
|
|
49
|
+
terminal.writeLine(`Resolver cache will be written at ${cacheFilePath}`);
|
|
50
|
+
async function afterExternalPackagesAsync(contexts, missingOptionalDependencies) {
|
|
51
|
+
/**
|
|
52
|
+
* Loads the index file from the pnpm store to discover nested package.json files in an external package
|
|
53
|
+
* For internal packages, assumes there are no nested package.json files.
|
|
54
|
+
* @param context - The context to find nested package.json files for
|
|
55
|
+
* @returns A promise that resolves when the nested package.json files are found, if applicable
|
|
56
|
+
*/
|
|
57
|
+
async function findNestedPackageJsonsForContextAsync(context) {
|
|
58
|
+
const { descriptionFileRoot, descriptionFileHash } = context;
|
|
59
|
+
if (descriptionFileHash === undefined) {
|
|
60
|
+
// Assume this package has no nested package json files for now.
|
|
61
|
+
terminal.writeDebugLine(`Package at ${descriptionFileRoot} does not having a file list. Assuming no nested "package.json" files.`);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// Convert an integrity hash like
|
|
65
|
+
// sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw==
|
|
66
|
+
// To its hex representation, e.g.
|
|
67
|
+
// 0baba219027e1ade11c875d762dfaff5ff92375bfcdf1ebc511c20c4d43df1cbc7f24c62bb2c1618fe1778d675a5a3b367adda6377137220844093455258e52f
|
|
68
|
+
const prefixIndex = descriptionFileHash.indexOf('-');
|
|
69
|
+
const hash = Buffer.from(descriptionFileHash.slice(prefixIndex + 1), 'base64').toString('hex');
|
|
70
|
+
// The pnpm store directory has index files of package contents at paths:
|
|
71
|
+
// <store>/v3/files/<hash (0-2)>/<hash (2-)>-index.json
|
|
72
|
+
// See https://github.com/pnpm/pnpm/blob/f394cfccda7bc519ceee8c33fc9b68a0f4235532/store/cafs/src/getFilePathInCafs.ts#L33
|
|
73
|
+
const indexPath = `${pnpmStoreDir}${hash.slice(0, 2)}/${hash.slice(2)}-index.json`;
|
|
74
|
+
try {
|
|
75
|
+
const indexContent = await externals_1.FileSystem.readFileAsync(indexPath);
|
|
76
|
+
const { files } = JSON.parse(indexContent);
|
|
77
|
+
const filteredFiles = Object.keys(files).filter((file) => file.endsWith('/package.json'));
|
|
78
|
+
if (filteredFiles.length > 0) {
|
|
79
|
+
// eslint-disable-next-line require-atomic-updates
|
|
80
|
+
context.files = filteredFiles.map((x) => x.slice(0, -13));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
if (!context.optional) {
|
|
85
|
+
throw new Error(`Error reading index file for: "${context.descriptionFileRoot}" (${descriptionFileHash})`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
terminal.writeLine(`Trimming missing optional dependency at: ${descriptionFileRoot}`);
|
|
89
|
+
contexts.delete(descriptionFileRoot);
|
|
90
|
+
missingOptionalDependencies.add(descriptionFileRoot);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// For external packages, update the contexts with data from the pnpm store
|
|
95
|
+
// This gives us the list of nested package.json files, as well as the actual package name
|
|
96
|
+
// We could also cache package.json contents, but that proves to be inefficient.
|
|
97
|
+
await externals_1.Async.forEachAsync(contexts.values(), findNestedPackageJsonsForContextAsync, {
|
|
98
|
+
concurrency: 20
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
const cacheFile = await (0, computeResolverCacheFromLockfileAsync_1.computeResolverCacheFromLockfileAsync)({
|
|
102
|
+
workspaceRoot,
|
|
103
|
+
commonPrefixToTrim: rushRoot,
|
|
104
|
+
platformInfo: getPlatformInfo(),
|
|
105
|
+
projectByImporterPath,
|
|
106
|
+
lockfile: lockFile,
|
|
107
|
+
afterExternalPackagesAsync
|
|
108
|
+
});
|
|
109
|
+
const serialized = JSON.stringify(cacheFile);
|
|
110
|
+
await externals_1.FileSystem.writeFileAsync(cacheFilePath, serialized, {
|
|
111
|
+
ensureFolderExists: true
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
exports.afterInstallAsync = afterInstallAsync;
|
|
115
|
+
//# sourceMappingURL=afterInstallAsync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"afterInstallAsync.js","sourceRoot":"","sources":["../src/afterInstallAsync.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type {\n RushSession,\n RushConfiguration,\n RushConfigurationProject,\n ILogger,\n LookupByPath,\n Subspace\n} from '@rushstack/rush-sdk';\nimport type { IResolverCacheFile } from '@rushstack/webpack-workspace-resolve-plugin';\n\nimport { Async, FileSystem, PnpmShrinkwrapFile } from './externals';\nimport {\n computeResolverCacheFromLockfileAsync,\n type IPlatformInfo\n} from './computeResolverCacheFromLockfileAsync';\nimport type { IResolverContext } from './types';\n\n/**\n * Gets information used to determine compatibility of optional dependencies.\n * @returns Information about the platform Rush is running on\n */\nfunction getPlatformInfo(): IPlatformInfo {\n // Acquiring the libc version is a bit more obnoxious than platform and arch,\n // but all of them are ultimately on the same object.\n const {\n platform: os,\n arch: cpu,\n glibcVersionRuntime\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } = (process.report?.getReport() as any)?.header ?? process;\n const libc: 'glibc' | 'musl' = glibcVersionRuntime ? 'glibc' : 'musl';\n\n return {\n os,\n cpu,\n libc\n };\n}\n\n/**\n * Plugin entry point for after install.\n * @param rushSession - The Rush Session\n * @param rushConfiguration - The Rush Configuration\n * @param subspace - The subspace that was just installed\n * @param logger - The initialized logger\n */\nexport async function afterInstallAsync(\n rushSession: RushSession,\n rushConfiguration: RushConfiguration,\n subspace: Subspace,\n logger: ILogger\n): Promise<void> {\n const { terminal } = logger;\n const rushRoot: string = `${rushConfiguration.rushJsonFolder}/`;\n\n const lockFilePath: string = subspace.getCommittedShrinkwrapFilename();\n const workspaceRoot: string = subspace.getSubspaceTempFolderPath();\n\n const projectByImporterPath: LookupByPath<RushConfigurationProject> =\n rushConfiguration.getProjectLookupForRoot(workspaceRoot);\n\n const pnpmStoreDir: string = `${rushConfiguration.pnpmOptions.pnpmStorePath}/v3/files/`;\n\n terminal.writeLine(`Using pnpm-lock from: ${lockFilePath}`);\n terminal.writeLine(`Using pnpm store folder: ${pnpmStoreDir}`);\n\n const lockFile: PnpmShrinkwrapFile | undefined = PnpmShrinkwrapFile.loadFromFile(lockFilePath, {\n withCaching: true\n });\n if (!lockFile) {\n throw new Error(`Failed to load shrinkwrap file: ${lockFilePath}`);\n }\n\n const cacheFilePath: string = `${workspaceRoot}/resolver-cache.json`;\n\n terminal.writeLine(`Resolver cache will be written at ${cacheFilePath}`);\n\n async function afterExternalPackagesAsync(\n contexts: Map<string, IResolverContext>,\n missingOptionalDependencies: Set<string>\n ): Promise<void> {\n /**\n * Loads the index file from the pnpm store to discover nested package.json files in an external package\n * For internal packages, assumes there are no nested package.json files.\n * @param context - The context to find nested package.json files for\n * @returns A promise that resolves when the nested package.json files are found, if applicable\n */\n async function findNestedPackageJsonsForContextAsync(context: IResolverContext): Promise<void> {\n const { descriptionFileRoot, descriptionFileHash } = context;\n\n if (descriptionFileHash === undefined) {\n // Assume this package has no nested package json files for now.\n terminal.writeDebugLine(\n `Package at ${descriptionFileRoot} does not having a file list. Assuming no nested \"package.json\" files.`\n );\n return;\n }\n\n // Convert an integrity hash like\n // sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw==\n // To its hex representation, e.g.\n // 0baba219027e1ade11c875d762dfaff5ff92375bfcdf1ebc511c20c4d43df1cbc7f24c62bb2c1618fe1778d675a5a3b367adda6377137220844093455258e52f\n const prefixIndex: number = descriptionFileHash.indexOf('-');\n const hash: string = Buffer.from(descriptionFileHash.slice(prefixIndex + 1), 'base64').toString('hex');\n\n // The pnpm store directory has index files of package contents at paths:\n // <store>/v3/files/<hash (0-2)>/<hash (2-)>-index.json\n // See https://github.com/pnpm/pnpm/blob/f394cfccda7bc519ceee8c33fc9b68a0f4235532/store/cafs/src/getFilePathInCafs.ts#L33\n const indexPath: string = `${pnpmStoreDir}${hash.slice(0, 2)}/${hash.slice(2)}-index.json`;\n\n try {\n const indexContent: string = await FileSystem.readFileAsync(indexPath);\n const { files } = JSON.parse(indexContent);\n\n const filteredFiles: string[] = Object.keys(files).filter((file) => file.endsWith('/package.json'));\n if (filteredFiles.length > 0) {\n // eslint-disable-next-line require-atomic-updates\n context.files = filteredFiles.map((x) => x.slice(0, -13));\n }\n } catch (error) {\n if (!context.optional) {\n throw new Error(\n `Error reading index file for: \"${context.descriptionFileRoot}\" (${descriptionFileHash})`\n );\n } else {\n terminal.writeLine(`Trimming missing optional dependency at: ${descriptionFileRoot}`);\n contexts.delete(descriptionFileRoot);\n missingOptionalDependencies.add(descriptionFileRoot);\n }\n }\n }\n\n // For external packages, update the contexts with data from the pnpm store\n // This gives us the list of nested package.json files, as well as the actual package name\n // We could also cache package.json contents, but that proves to be inefficient.\n await Async.forEachAsync(contexts.values(), findNestedPackageJsonsForContextAsync, {\n concurrency: 20\n });\n }\n\n const cacheFile: IResolverCacheFile = await computeResolverCacheFromLockfileAsync({\n workspaceRoot,\n commonPrefixToTrim: rushRoot,\n platformInfo: getPlatformInfo(),\n projectByImporterPath,\n lockfile: lockFile,\n afterExternalPackagesAsync\n });\n\n const serialized: string = JSON.stringify(cacheFile);\n\n await FileSystem.writeFileAsync(cacheFilePath, serialized, {\n ensureFolderExists: true\n });\n}\n"]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { LookupByPath } from '@rushstack/rush-sdk';
|
|
2
|
+
import type { IResolverCacheFile } from '@rushstack/webpack-workspace-resolve-plugin';
|
|
3
|
+
import type { PnpmShrinkwrapFile } from './externals';
|
|
4
|
+
import type { IResolverContext } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* The only parts of a RushConfigurationProject needed by this tool.
|
|
7
|
+
* Reduced for unit test typings.
|
|
8
|
+
*/
|
|
9
|
+
export interface IPartialRushProject {
|
|
10
|
+
projectFolder: string;
|
|
11
|
+
packageJson: {
|
|
12
|
+
name: string;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export interface IPlatformInfo {
|
|
16
|
+
os: typeof process.platform;
|
|
17
|
+
cpu: typeof process.arch;
|
|
18
|
+
libc: 'glibc' | 'musl';
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Options for computing the resolver cache from a lockfile.
|
|
22
|
+
*/
|
|
23
|
+
export interface IComputeResolverCacheFromLockfileOptions {
|
|
24
|
+
/**
|
|
25
|
+
* The root folder of the workspace being installed
|
|
26
|
+
*/
|
|
27
|
+
workspaceRoot: string;
|
|
28
|
+
/**
|
|
29
|
+
* The common root path to trim from the description file roots for brevity
|
|
30
|
+
*/
|
|
31
|
+
commonPrefixToTrim: string;
|
|
32
|
+
/**
|
|
33
|
+
* Information about the platform Rush is running on
|
|
34
|
+
*/
|
|
35
|
+
platformInfo: IPlatformInfo;
|
|
36
|
+
/**
|
|
37
|
+
* A lookup of projects by their importer path
|
|
38
|
+
*/
|
|
39
|
+
projectByImporterPath: Pick<LookupByPath<IPartialRushProject>, 'findChildPath'>;
|
|
40
|
+
/**
|
|
41
|
+
* The lockfile to compute the cache from
|
|
42
|
+
*/
|
|
43
|
+
lockfile: PnpmShrinkwrapFile;
|
|
44
|
+
/**
|
|
45
|
+
* A callback to process external packages after they have been enumerated.
|
|
46
|
+
* Broken out as a separate function to facilitate testing without hitting the disk.
|
|
47
|
+
* @remarks This is useful for fetching additional data from the pnpm store
|
|
48
|
+
* @param contexts - The current context information per description file root
|
|
49
|
+
* @param missingOptionalDependencies - The set of optional dependencies that were not installed
|
|
50
|
+
* @returns A promise that resolves when the external packages have been processed
|
|
51
|
+
*/
|
|
52
|
+
afterExternalPackagesAsync?: (contexts: Map<string, IResolverContext>, missingOptionalDependencies: Set<string>) => Promise<void>;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Given a lockfile and information about the workspace and platform, computes the resolver cache file.
|
|
56
|
+
* @param params - The options for computing the resolver cache
|
|
57
|
+
* @returns A promise that resolves with the resolver cache file
|
|
58
|
+
*/
|
|
59
|
+
export declare function computeResolverCacheFromLockfileAsync(params: IComputeResolverCacheFromLockfileOptions): Promise<IResolverCacheFile>;
|
|
60
|
+
//# sourceMappingURL=computeResolverCacheFromLockfileAsync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computeResolverCacheFromLockfileAsync.d.ts","sourceRoot":"","sources":["../src/computeResolverCacheFromLockfileAsync.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAEV,kBAAkB,EACnB,MAAM,6CAA6C,CAAC;AAErD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,OAAO,CAAC,QAAQ,CAAC;IAC5B,GAAG,EAAE,OAAO,OAAO,CAAC,IAAI,CAAC;IACzB,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;CACxB;AAkBD;;GAEG;AACH,MAAM,WAAW,wCAAwC;IACvD;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,YAAY,EAAE,aAAa,CAAC;IAC5B;;OAEG;IACH,qBAAqB,EAAE,IAAI,CAAC,YAAY,CAAC,mBAAmB,CAAC,EAAE,eAAe,CAAC,CAAC;IAChF;;OAEG;IACH,QAAQ,EAAE,kBAAkB,CAAC;IAC7B;;;;;;;OAOG;IACH,0BAA0B,CAAC,EAAE,CAC3B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,EACvC,2BAA2B,EAAE,GAAG,CAAC,MAAM,CAAC,KACrC,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAsB,qCAAqC,CACzD,MAAM,EAAE,wCAAwC,GAC/C,OAAO,CAAC,kBAAkB,CAAC,CAwG7B"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
|
3
|
+
// See LICENSE in the project root for license information.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.computeResolverCacheFromLockfileAsync = void 0;
|
|
6
|
+
const helpers_1 = require("./helpers");
|
|
7
|
+
function isPackageCompatible(pack, platformInfo) {
|
|
8
|
+
var _a, _b, _c;
|
|
9
|
+
if ((_a = pack.os) === null || _a === void 0 ? void 0 : _a.every((value) => value.toLowerCase() !== platformInfo.os)) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
if ((_b = pack.cpu) === null || _b === void 0 ? void 0 : _b.every((value) => value.toLowerCase() !== platformInfo.cpu)) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
if ((_c = pack.libc) === null || _c === void 0 ? void 0 : _c.every((value) => value.toLowerCase() !== platformInfo.libc)) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Given a lockfile and information about the workspace and platform, computes the resolver cache file.
|
|
22
|
+
* @param params - The options for computing the resolver cache
|
|
23
|
+
* @returns A promise that resolves with the resolver cache file
|
|
24
|
+
*/
|
|
25
|
+
async function computeResolverCacheFromLockfileAsync(params) {
|
|
26
|
+
var _a;
|
|
27
|
+
const { workspaceRoot, commonPrefixToTrim, platformInfo, projectByImporterPath, lockfile, afterExternalPackagesAsync } = params;
|
|
28
|
+
const contexts = new Map();
|
|
29
|
+
const missingOptionalDependencies = new Set();
|
|
30
|
+
// Enumerate external dependencies first, to simplify looping over them for store data
|
|
31
|
+
for (const [key, pack] of lockfile.packages) {
|
|
32
|
+
let name = pack.name;
|
|
33
|
+
const descriptionFileRoot = (0, helpers_1.getDescriptionFileRootFromKey)(workspaceRoot, key, name);
|
|
34
|
+
// Skip optional dependencies that are incompatible with the current environment
|
|
35
|
+
if (pack.optional && !isPackageCompatible(pack, platformInfo)) {
|
|
36
|
+
missingOptionalDependencies.add(descriptionFileRoot);
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const integrity = (_a = pack.resolution) === null || _a === void 0 ? void 0 : _a.integrity;
|
|
40
|
+
if (!name && key.startsWith('/')) {
|
|
41
|
+
const versionIndex = key.indexOf('@', 2);
|
|
42
|
+
name = key.slice(1, versionIndex);
|
|
43
|
+
}
|
|
44
|
+
if (!name) {
|
|
45
|
+
throw new Error(`Missing name for ${key}`);
|
|
46
|
+
}
|
|
47
|
+
const context = {
|
|
48
|
+
descriptionFileRoot,
|
|
49
|
+
descriptionFileHash: integrity,
|
|
50
|
+
isProject: false,
|
|
51
|
+
name,
|
|
52
|
+
deps: new Map(),
|
|
53
|
+
ordinal: contexts.size,
|
|
54
|
+
optional: pack.optional
|
|
55
|
+
};
|
|
56
|
+
contexts.set(descriptionFileRoot, context);
|
|
57
|
+
if (pack.dependencies) {
|
|
58
|
+
(0, helpers_1.resolveDependencies)(workspaceRoot, pack.dependencies, context);
|
|
59
|
+
}
|
|
60
|
+
if (pack.optionalDependencies) {
|
|
61
|
+
(0, helpers_1.resolveDependencies)(workspaceRoot, pack.optionalDependencies, context);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (afterExternalPackagesAsync) {
|
|
65
|
+
await afterExternalPackagesAsync(contexts, missingOptionalDependencies);
|
|
66
|
+
}
|
|
67
|
+
// Add the data for workspace projects
|
|
68
|
+
for (const [importerPath, importer] of lockfile.importers) {
|
|
69
|
+
// Ignore the root project. This plugin assumes you don't have one.
|
|
70
|
+
// A non-empty root project results in global dependency hoisting, and that's bad for strictness.
|
|
71
|
+
if (importerPath === '.') {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const project = projectByImporterPath.findChildPath(importerPath);
|
|
75
|
+
if (!project) {
|
|
76
|
+
throw new Error(`Missing project for importer ${importerPath}`);
|
|
77
|
+
}
|
|
78
|
+
const context = {
|
|
79
|
+
descriptionFileRoot: project.projectFolder,
|
|
80
|
+
descriptionFileHash: undefined, // Not needed anymore
|
|
81
|
+
name: project.packageJson.name,
|
|
82
|
+
isProject: true,
|
|
83
|
+
deps: new Map(),
|
|
84
|
+
ordinal: contexts.size
|
|
85
|
+
};
|
|
86
|
+
contexts.set(project.projectFolder, context);
|
|
87
|
+
if (importer.dependencies) {
|
|
88
|
+
(0, helpers_1.resolveDependencies)(workspaceRoot, importer.dependencies, context);
|
|
89
|
+
}
|
|
90
|
+
if (importer.devDependencies) {
|
|
91
|
+
(0, helpers_1.resolveDependencies)(workspaceRoot, importer.devDependencies, context);
|
|
92
|
+
}
|
|
93
|
+
if (importer.optionalDependencies) {
|
|
94
|
+
(0, helpers_1.resolveDependencies)(workspaceRoot, importer.optionalDependencies, context);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Convert the intermediate representation to the final cache file
|
|
98
|
+
const serializedContexts = Array.from(contexts, (0, helpers_1.createContextSerializer)(missingOptionalDependencies, contexts, commonPrefixToTrim));
|
|
99
|
+
const cacheFile = {
|
|
100
|
+
contexts: serializedContexts
|
|
101
|
+
};
|
|
102
|
+
return cacheFile;
|
|
103
|
+
}
|
|
104
|
+
exports.computeResolverCacheFromLockfileAsync = computeResolverCacheFromLockfileAsync;
|
|
105
|
+
//# sourceMappingURL=computeResolverCacheFromLockfileAsync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computeResolverCacheFromLockfileAsync.js","sourceRoot":"","sources":["../src/computeResolverCacheFromLockfileAsync.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { LookupByPath } from '@rushstack/rush-sdk';\nimport type { IPnpmShrinkwrapDependencyYaml } from '@rushstack/rush-sdk/lib/logic/pnpm/PnpmShrinkwrapFile';\nimport type {\n ISerializedResolveContext,\n IResolverCacheFile\n} from '@rushstack/webpack-workspace-resolve-plugin';\n\nimport type { PnpmShrinkwrapFile } from './externals';\nimport { getDescriptionFileRootFromKey, resolveDependencies, createContextSerializer } from './helpers';\nimport type { IResolverContext } from './types';\n\n/**\n * The only parts of a RushConfigurationProject needed by this tool.\n * Reduced for unit test typings.\n */\nexport interface IPartialRushProject {\n projectFolder: string;\n packageJson: {\n name: string;\n };\n}\n\nexport interface IPlatformInfo {\n os: typeof process.platform;\n cpu: typeof process.arch;\n libc: 'glibc' | 'musl';\n}\n\nfunction isPackageCompatible(\n pack: Pick<IPnpmShrinkwrapDependencyYaml, 'os' | 'cpu' | 'libc'>,\n platformInfo: IPlatformInfo\n): boolean {\n if (pack.os?.every((value) => value.toLowerCase() !== platformInfo.os)) {\n return false;\n }\n if (pack.cpu?.every((value) => value.toLowerCase() !== platformInfo.cpu)) {\n return false;\n }\n if (pack.libc?.every((value) => value.toLowerCase() !== platformInfo.libc)) {\n return false;\n }\n return true;\n}\n\n/**\n * Options for computing the resolver cache from a lockfile.\n */\nexport interface IComputeResolverCacheFromLockfileOptions {\n /**\n * The root folder of the workspace being installed\n */\n workspaceRoot: string;\n /**\n * The common root path to trim from the description file roots for brevity\n */\n commonPrefixToTrim: string;\n /**\n * Information about the platform Rush is running on\n */\n platformInfo: IPlatformInfo;\n /**\n * A lookup of projects by their importer path\n */\n projectByImporterPath: Pick<LookupByPath<IPartialRushProject>, 'findChildPath'>;\n /**\n * The lockfile to compute the cache from\n */\n lockfile: PnpmShrinkwrapFile;\n /**\n * A callback to process external packages after they have been enumerated.\n * Broken out as a separate function to facilitate testing without hitting the disk.\n * @remarks This is useful for fetching additional data from the pnpm store\n * @param contexts - The current context information per description file root\n * @param missingOptionalDependencies - The set of optional dependencies that were not installed\n * @returns A promise that resolves when the external packages have been processed\n */\n afterExternalPackagesAsync?: (\n contexts: Map<string, IResolverContext>,\n missingOptionalDependencies: Set<string>\n ) => Promise<void>;\n}\n\n/**\n * Given a lockfile and information about the workspace and platform, computes the resolver cache file.\n * @param params - The options for computing the resolver cache\n * @returns A promise that resolves with the resolver cache file\n */\nexport async function computeResolverCacheFromLockfileAsync(\n params: IComputeResolverCacheFromLockfileOptions\n): Promise<IResolverCacheFile> {\n const {\n workspaceRoot,\n commonPrefixToTrim,\n platformInfo,\n projectByImporterPath,\n lockfile,\n afterExternalPackagesAsync\n } = params;\n const contexts: Map<string, IResolverContext> = new Map();\n const missingOptionalDependencies: Set<string> = new Set();\n\n // Enumerate external dependencies first, to simplify looping over them for store data\n for (const [key, pack] of lockfile.packages) {\n let name: string | undefined = pack.name;\n const descriptionFileRoot: string = getDescriptionFileRootFromKey(workspaceRoot, key, name);\n\n // Skip optional dependencies that are incompatible with the current environment\n if (pack.optional && !isPackageCompatible(pack, platformInfo)) {\n missingOptionalDependencies.add(descriptionFileRoot);\n continue;\n }\n\n const integrity: string | undefined = pack.resolution?.integrity;\n\n if (!name && key.startsWith('/')) {\n const versionIndex: number = key.indexOf('@', 2);\n name = key.slice(1, versionIndex);\n }\n\n if (!name) {\n throw new Error(`Missing name for ${key}`);\n }\n\n const context: IResolverContext = {\n descriptionFileRoot,\n descriptionFileHash: integrity,\n isProject: false,\n name,\n deps: new Map(),\n ordinal: contexts.size,\n optional: pack.optional\n };\n\n contexts.set(descriptionFileRoot, context);\n\n if (pack.dependencies) {\n resolveDependencies(workspaceRoot, pack.dependencies, context);\n }\n if (pack.optionalDependencies) {\n resolveDependencies(workspaceRoot, pack.optionalDependencies, context);\n }\n }\n\n if (afterExternalPackagesAsync) {\n await afterExternalPackagesAsync(contexts, missingOptionalDependencies);\n }\n\n // Add the data for workspace projects\n for (const [importerPath, importer] of lockfile.importers) {\n // Ignore the root project. This plugin assumes you don't have one.\n // A non-empty root project results in global dependency hoisting, and that's bad for strictness.\n if (importerPath === '.') {\n continue;\n }\n\n const project: IPartialRushProject | undefined = projectByImporterPath.findChildPath(importerPath);\n if (!project) {\n throw new Error(`Missing project for importer ${importerPath}`);\n }\n\n const context: IResolverContext = {\n descriptionFileRoot: project.projectFolder,\n descriptionFileHash: undefined, // Not needed anymore\n name: project.packageJson.name,\n isProject: true,\n deps: new Map(),\n ordinal: contexts.size\n };\n\n contexts.set(project.projectFolder, context);\n\n if (importer.dependencies) {\n resolveDependencies(workspaceRoot, importer.dependencies, context);\n }\n if (importer.devDependencies) {\n resolveDependencies(workspaceRoot, importer.devDependencies, context);\n }\n if (importer.optionalDependencies) {\n resolveDependencies(workspaceRoot, importer.optionalDependencies, context);\n }\n }\n\n // Convert the intermediate representation to the final cache file\n const serializedContexts: ISerializedResolveContext[] = Array.from(\n contexts,\n createContextSerializer(missingOptionalDependencies, contexts, commonPrefixToTrim)\n );\n\n const cacheFile: IResolverCacheFile = {\n contexts: serializedContexts\n };\n\n return cacheFile;\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Operation as OperationType, OperationStatus as OperationStatusType } from '@rushstack/rush-sdk';
|
|
2
|
+
import type { PnpmShrinkwrapFile as PnpmShrinkwrapFileType } from '@rushstack/rush-sdk/lib/logic/pnpm/PnpmShrinkwrapFile';
|
|
3
|
+
declare const Operation: typeof OperationType, OperationStatus: typeof OperationStatusType;
|
|
4
|
+
type Operation = OperationType;
|
|
5
|
+
type OperationStatus = OperationStatusType;
|
|
6
|
+
export { Operation, OperationStatus };
|
|
7
|
+
export declare const PnpmShrinkwrapFile: typeof PnpmShrinkwrapFileType;
|
|
8
|
+
export type PnpmShrinkwrapFile = PnpmShrinkwrapFileType;
|
|
9
|
+
export declare const Async: typeof import("@rushstack/node-core-library/lib/Async").Async;
|
|
10
|
+
export declare const FileSystem: typeof import("@rushstack/node-core-library/lib/FileSystem").FileSystem;
|
|
11
|
+
//# sourceMappingURL=externals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"externals.d.ts","sourceRoot":"","sources":["../src/externals.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,IAAI,aAAa,EAAE,eAAe,IAAI,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC9G,OAAO,KAAK,EAAE,kBAAkB,IAAI,sBAAsB,EAAE,MAAM,uDAAuD,CAAC;AAO1H,QAAA,MAAQ,SAAS,wBAAE,eAAe,4BAA4B,CAAC;AAE/D,KAAK,SAAS,GAAG,aAAa,CAAC;AAE/B,KAAK,eAAe,GAAG,mBAAmB,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;AAgBtC,eAAO,MAAQ,kBAAkB,+BAEyB,CAAC;AAE3D,MAAM,MAAM,kBAAkB,GAAG,sBAAsB,CAAC;AAGxD,eAAO,MAAQ,KAAK,+DAEnB,CAAC;AACF,eAAO,MAAQ,UAAU,yEAExB,CAAC"}
|
package/lib/externals.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
|
3
|
+
// See LICENSE in the project root for license information.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.FileSystem = exports.Async = exports.PnpmShrinkwrapFile = exports.OperationStatus = exports.Operation = void 0;
|
|
6
|
+
const { Operation, OperationStatus } = ___rush___rushLibModule;
|
|
7
|
+
exports.Operation = Operation;
|
|
8
|
+
exports.OperationStatus = OperationStatus;
|
|
9
|
+
// Support this plugin being webpacked.
|
|
10
|
+
const req = typeof __non_webpack_require__ === 'function' ? __non_webpack_require__ : require;
|
|
11
|
+
const entryModule = req.main;
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13
|
+
function getExternal(name) {
|
|
14
|
+
const externalPath = req.resolve(name, {
|
|
15
|
+
paths: entryModule === null || entryModule === void 0 ? void 0 : entryModule.paths
|
|
16
|
+
});
|
|
17
|
+
return req(externalPath);
|
|
18
|
+
}
|
|
19
|
+
// Private Rush APIs
|
|
20
|
+
exports.PnpmShrinkwrapFile = getExternal('@microsoft/rush-lib/lib/logic/pnpm/PnpmShrinkwrapFile').PnpmShrinkwrapFile;
|
|
21
|
+
// Avoid bundling expensive stuff that's already part of Rush.
|
|
22
|
+
exports.Async = getExternal(`@rushstack/node-core-library/lib/Async`).Async;
|
|
23
|
+
exports.FileSystem = getExternal(`@rushstack/node-core-library/lib/FileSystem`).FileSystem;
|
|
24
|
+
//# sourceMappingURL=externals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"externals.js","sourceRoot":"","sources":["../src/externals.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAY3D,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,GAAG,uBAAuB,CAAC;AAMtD,8BAAS;AAAE,0CAAe;AAEnC,uCAAuC;AACvC,MAAM,GAAG,GAAmB,OAAO,uBAAuB,KAAK,UAAU,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,OAAO,CAAC;AAE9G,MAAM,WAAW,GAAuB,GAAG,CAAC,IAAI,CAAC;AACjD,8DAA8D;AAC9D,SAAS,WAAW,CAAgB,IAAY;IAC9C,MAAM,YAAY,GAAW,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE;QAC7C,KAAK,EAAE,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,KAAK;KAC1B,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC,YAAY,CAAC,CAAC;AAC3B,CAAC;AAED,oBAAoB;AACL,0BAAkB,GAAK,WAAW,CAE/C,uDAAuD,CAAC,oBAAC;AAI3D,8DAA8D;AAC/C,aAAK,GAAK,WAAW,CAClC,wCAAwC,CACzC,OAAC;AACa,kBAAU,GAAK,WAAW,CACvC,6CAA6C,CAC9C,YAAC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type Module from 'node:module';\n\nimport type { Operation as OperationType, OperationStatus as OperationStatusType } from '@rushstack/rush-sdk';\nimport type { PnpmShrinkwrapFile as PnpmShrinkwrapFileType } from '@rushstack/rush-sdk/lib/logic/pnpm/PnpmShrinkwrapFile';\nimport type * as rushSdkType from '@rushstack/rush-sdk';\n\n// Ultra-cheap \"I am a Rush plugin\" import of rush-lib\n// eslint-disable-next-line @typescript-eslint/naming-convention\ndeclare const ___rush___rushLibModule: typeof rushSdkType;\n\nconst { Operation, OperationStatus } = ___rush___rushLibModule;\n// eslint-disable-next-line @typescript-eslint/no-redeclare\ntype Operation = OperationType;\n// eslint-disable-next-line @typescript-eslint/no-redeclare\ntype OperationStatus = OperationStatusType;\n\nexport { Operation, OperationStatus };\n\n// Support this plugin being webpacked.\nconst req: typeof require = typeof __non_webpack_require__ === 'function' ? __non_webpack_require__ : require;\n\nconst entryModule: Module | undefined = req.main;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction getExternal<TResult = any>(name: string): TResult {\n const externalPath: string = req.resolve(name, {\n paths: entryModule?.paths\n });\n\n return req(externalPath);\n}\n\n// Private Rush APIs\nexport const { PnpmShrinkwrapFile } = getExternal<\n typeof import('@rushstack/rush-sdk/lib/logic/pnpm/PnpmShrinkwrapFile')\n>('@microsoft/rush-lib/lib/logic/pnpm/PnpmShrinkwrapFile');\n// eslint-disable-next-line @typescript-eslint/no-redeclare\nexport type PnpmShrinkwrapFile = PnpmShrinkwrapFileType;\n\n// Avoid bundling expensive stuff that's already part of Rush.\nexport const { Async } = getExternal<typeof import('@rushstack/node-core-library/lib/Async')>(\n `@rushstack/node-core-library/lib/Async`\n);\nexport const { FileSystem } = getExternal<typeof import('@rushstack/node-core-library/lib/FileSystem')>(\n `@rushstack/node-core-library/lib/FileSystem`\n);\n"]}
|
package/lib/helpers.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { ISerializedResolveContext } from '@rushstack/webpack-workspace-resolve-plugin';
|
|
2
|
+
import type { IDependencyEntry, IResolverContext } from './types';
|
|
3
|
+
export declare function createBase32Hash(input: string): string;
|
|
4
|
+
export declare function depPathToFilename(depPath: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Computes the root folder for a dependency from a reference to it in another package
|
|
7
|
+
* @param lockfileFolder - The folder that contains the lockfile
|
|
8
|
+
* @param key - The key of the dependency
|
|
9
|
+
* @param specifier - The specifier in the lockfile for the dependency
|
|
10
|
+
* @param context - The owning package
|
|
11
|
+
* @returns The identifier for the dependency
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveDependencyKey(lockfileFolder: string, key: string, specifier: string, context: IResolverContext): string;
|
|
14
|
+
/**
|
|
15
|
+
* Computes the physical path to a dependency based on its entry
|
|
16
|
+
* @param lockfileFolder - The folder that contains the lockfile during installation
|
|
17
|
+
* @param key - The key of the dependency
|
|
18
|
+
* @param name - The name of the dependency, if provided
|
|
19
|
+
* @returns The physical path to the dependency
|
|
20
|
+
*/
|
|
21
|
+
export declare function getDescriptionFileRootFromKey(lockfileFolder: string, key: string, name?: string): string;
|
|
22
|
+
export declare function resolveDependencies(lockfileFolder: string, collection: Record<string, IDependencyEntry>, context: IResolverContext): void;
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
* @param depPath - The path to the dependency
|
|
26
|
+
* @returns The folder name for the dependency
|
|
27
|
+
*/
|
|
28
|
+
export declare function depPathToFilenameUnescaped(depPath: string): string;
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
* @param missingOptionalDependencies - The set of optional dependencies that were not installed
|
|
32
|
+
* @param contexts - The map of context roots to their respective contexts
|
|
33
|
+
* @param commonPathPrefix - The common root path to trim
|
|
34
|
+
* @returns A function that serializes a context into a format that can be written to disk
|
|
35
|
+
*/
|
|
36
|
+
export declare function createContextSerializer(missingOptionalDependencies: Set<string>, contexts: Map<string, IResolverContext>, commonPathPrefix: string): (entry: [string, IResolverContext]) => ISerializedResolveContext;
|
|
37
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AAE7F,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAMlE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CA4BtD;AAGD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CASzD;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,cAAc,EAAE,MAAM,EACtB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,gBAAgB,GACxB,MAAM,CAcR;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAYxG;AAED,wBAAgB,mBAAmB,CACjC,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAC5C,OAAO,EAAE,gBAAgB,GACxB,IAAI,CAON;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAQlE;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,2BAA2B,EAAE,GAAG,CAAC,MAAM,CAAC,EACxC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,EACvC,gBAAgB,EAAE,MAAM,GACvB,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC,KAAK,yBAAyB,CA4BlE"}
|
package/lib/helpers.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
|
3
|
+
// See LICENSE in the project root for license information.
|
|
4
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
5
|
+
if (k2 === undefined) k2 = k;
|
|
6
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
8
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
9
|
+
}
|
|
10
|
+
Object.defineProperty(o, k2, desc);
|
|
11
|
+
}) : (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
o[k2] = m[k];
|
|
14
|
+
}));
|
|
15
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
16
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
17
|
+
}) : function(o, v) {
|
|
18
|
+
o["default"] = v;
|
|
19
|
+
});
|
|
20
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
21
|
+
if (mod && mod.__esModule) return mod;
|
|
22
|
+
var result = {};
|
|
23
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
24
|
+
__setModuleDefault(result, mod);
|
|
25
|
+
return result;
|
|
26
|
+
};
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.createContextSerializer = exports.depPathToFilenameUnescaped = exports.resolveDependencies = exports.getDescriptionFileRootFromKey = exports.resolveDependencyKey = exports.depPathToFilename = exports.createBase32Hash = void 0;
|
|
29
|
+
const node_crypto_1 = require("node:crypto");
|
|
30
|
+
const path = __importStar(require("node:path"));
|
|
31
|
+
const MAX_LENGTH_WITHOUT_HASH = 120 - 26 - 1;
|
|
32
|
+
const BASE32 = 'abcdefghijklmnopqrstuvwxyz234567'.split('');
|
|
33
|
+
// https://github.com/swansontec/rfc4648.js/blob/ead9c9b4b68e5d4a529f32925da02c02984e772c/src/codec.ts#L82-L118
|
|
34
|
+
function createBase32Hash(input) {
|
|
35
|
+
const data = (0, node_crypto_1.createHash)('md5').update(input).digest();
|
|
36
|
+
const mask = 0x1f;
|
|
37
|
+
let out = '';
|
|
38
|
+
let bits = 0; // Number of bits currently in the buffer
|
|
39
|
+
let buffer = 0; // Bits waiting to be written out, MSB first
|
|
40
|
+
for (let i = 0; i < data.length; ++i) {
|
|
41
|
+
// eslint-disable-next-line no-bitwise
|
|
42
|
+
buffer = (buffer << 8) | (0xff & data[i]);
|
|
43
|
+
bits += 8;
|
|
44
|
+
// Write out as much as we can:
|
|
45
|
+
while (bits > 5) {
|
|
46
|
+
bits -= 5;
|
|
47
|
+
// eslint-disable-next-line no-bitwise
|
|
48
|
+
out += BASE32[mask & (buffer >> bits)];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Partial character:
|
|
52
|
+
if (bits) {
|
|
53
|
+
// eslint-disable-next-line no-bitwise
|
|
54
|
+
out += BASE32[mask & (buffer << (5 - bits))];
|
|
55
|
+
}
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
exports.createBase32Hash = createBase32Hash;
|
|
59
|
+
// https://github.com/pnpm/pnpm/blob/f394cfccda7bc519ceee8c33fc9b68a0f4235532/packages/dependency-path/src/index.ts#L167-L189
|
|
60
|
+
function depPathToFilename(depPath) {
|
|
61
|
+
let filename = depPathToFilenameUnescaped(depPath).replace(/[\\/:*?"<>|]/g, '+');
|
|
62
|
+
if (filename.includes('(')) {
|
|
63
|
+
filename = filename.replace(/(\)\()|\(/g, '_').replace(/\)$/, '');
|
|
64
|
+
}
|
|
65
|
+
if (filename.length > 120 || (filename !== filename.toLowerCase() && !filename.startsWith('file+'))) {
|
|
66
|
+
return `${filename.substring(0, MAX_LENGTH_WITHOUT_HASH)}_${createBase32Hash(filename)}`;
|
|
67
|
+
}
|
|
68
|
+
return filename;
|
|
69
|
+
}
|
|
70
|
+
exports.depPathToFilename = depPathToFilename;
|
|
71
|
+
/**
|
|
72
|
+
* Computes the root folder for a dependency from a reference to it in another package
|
|
73
|
+
* @param lockfileFolder - The folder that contains the lockfile
|
|
74
|
+
* @param key - The key of the dependency
|
|
75
|
+
* @param specifier - The specifier in the lockfile for the dependency
|
|
76
|
+
* @param context - The owning package
|
|
77
|
+
* @returns The identifier for the dependency
|
|
78
|
+
*/
|
|
79
|
+
function resolveDependencyKey(lockfileFolder, key, specifier, context) {
|
|
80
|
+
if (specifier.startsWith('/')) {
|
|
81
|
+
return getDescriptionFileRootFromKey(lockfileFolder, specifier);
|
|
82
|
+
}
|
|
83
|
+
else if (specifier.startsWith('link:')) {
|
|
84
|
+
if (context.isProject) {
|
|
85
|
+
return path.posix.join(context.descriptionFileRoot, specifier.slice(5));
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
return path.posix.join(lockfileFolder, specifier.slice(5));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else if (specifier.startsWith('file:')) {
|
|
92
|
+
return getDescriptionFileRootFromKey(lockfileFolder, specifier, key);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
return getDescriptionFileRootFromKey(lockfileFolder, `/${key}@${specifier}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exports.resolveDependencyKey = resolveDependencyKey;
|
|
99
|
+
/**
|
|
100
|
+
* Computes the physical path to a dependency based on its entry
|
|
101
|
+
* @param lockfileFolder - The folder that contains the lockfile during installation
|
|
102
|
+
* @param key - The key of the dependency
|
|
103
|
+
* @param name - The name of the dependency, if provided
|
|
104
|
+
* @returns The physical path to the dependency
|
|
105
|
+
*/
|
|
106
|
+
function getDescriptionFileRootFromKey(lockfileFolder, key, name) {
|
|
107
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
108
|
+
if (!key.startsWith('file:')) {
|
|
109
|
+
name = key.slice(1, key.indexOf('@', 2));
|
|
110
|
+
}
|
|
111
|
+
if (!name) {
|
|
112
|
+
throw new Error(`Missing package name for ${key}`);
|
|
113
|
+
}
|
|
114
|
+
const originFolder = `${lockfileFolder}/node_modules/.pnpm/${depPathToFilename(key)}/node_modules`;
|
|
115
|
+
const descriptionFileRoot = `${originFolder}/${name}`;
|
|
116
|
+
return descriptionFileRoot;
|
|
117
|
+
}
|
|
118
|
+
exports.getDescriptionFileRootFromKey = getDescriptionFileRootFromKey;
|
|
119
|
+
function resolveDependencies(lockfileFolder, collection, context) {
|
|
120
|
+
for (const [key, value] of Object.entries(collection)) {
|
|
121
|
+
const version = typeof value === 'string' ? value : value.version;
|
|
122
|
+
const resolved = resolveDependencyKey(lockfileFolder, key, version, context);
|
|
123
|
+
context.deps.set(key, resolved);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
exports.resolveDependencies = resolveDependencies;
|
|
127
|
+
/**
|
|
128
|
+
*
|
|
129
|
+
* @param depPath - The path to the dependency
|
|
130
|
+
* @returns The folder name for the dependency
|
|
131
|
+
*/
|
|
132
|
+
function depPathToFilenameUnescaped(depPath) {
|
|
133
|
+
if (depPath.indexOf('file:') !== 0) {
|
|
134
|
+
if (depPath.startsWith('/')) {
|
|
135
|
+
depPath = depPath.slice(1);
|
|
136
|
+
}
|
|
137
|
+
return depPath;
|
|
138
|
+
}
|
|
139
|
+
return depPath.replace(':', '+');
|
|
140
|
+
}
|
|
141
|
+
exports.depPathToFilenameUnescaped = depPathToFilenameUnescaped;
|
|
142
|
+
/**
|
|
143
|
+
*
|
|
144
|
+
* @param missingOptionalDependencies - The set of optional dependencies that were not installed
|
|
145
|
+
* @param contexts - The map of context roots to their respective contexts
|
|
146
|
+
* @param commonPathPrefix - The common root path to trim
|
|
147
|
+
* @returns A function that serializes a context into a format that can be written to disk
|
|
148
|
+
*/
|
|
149
|
+
function createContextSerializer(missingOptionalDependencies, contexts, commonPathPrefix) {
|
|
150
|
+
return ([descriptionFileRoot, context]) => {
|
|
151
|
+
const deps = {};
|
|
152
|
+
for (const [key, contextRoot] of context.deps) {
|
|
153
|
+
if (missingOptionalDependencies.has(contextRoot)) {
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
const resolutionContext = contexts.get(contextRoot);
|
|
157
|
+
if (!resolutionContext) {
|
|
158
|
+
throw new Error(`Missing context for ${contextRoot}!`);
|
|
159
|
+
}
|
|
160
|
+
deps[key] = resolutionContext.ordinal;
|
|
161
|
+
}
|
|
162
|
+
if (!context.name) {
|
|
163
|
+
throw new Error(`Missing name for ${descriptionFileRoot}`);
|
|
164
|
+
}
|
|
165
|
+
const serializedContext = {
|
|
166
|
+
name: context.name,
|
|
167
|
+
root: descriptionFileRoot.slice(commonPathPrefix.length),
|
|
168
|
+
dirInfoFiles: context.files,
|
|
169
|
+
deps
|
|
170
|
+
};
|
|
171
|
+
return serializedContext;
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
exports.createContextSerializer = createContextSerializer;
|
|
175
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { createHash } from 'node:crypto';\nimport * as path from 'node:path';\n\nimport type { ISerializedResolveContext } from '@rushstack/webpack-workspace-resolve-plugin';\n\nimport type { IDependencyEntry, IResolverContext } from './types';\n\nconst MAX_LENGTH_WITHOUT_HASH: number = 120 - 26 - 1;\nconst BASE32: string[] = 'abcdefghijklmnopqrstuvwxyz234567'.split('');\n\n// https://github.com/swansontec/rfc4648.js/blob/ead9c9b4b68e5d4a529f32925da02c02984e772c/src/codec.ts#L82-L118\nexport function createBase32Hash(input: string): string {\n const data: Buffer = createHash('md5').update(input).digest();\n\n const mask: 0x1f = 0x1f;\n let out: string = '';\n\n let bits: number = 0; // Number of bits currently in the buffer\n let buffer: number = 0; // Bits waiting to be written out, MSB first\n for (let i: number = 0; i < data.length; ++i) {\n // eslint-disable-next-line no-bitwise\n buffer = (buffer << 8) | (0xff & data[i]);\n bits += 8;\n\n // Write out as much as we can:\n while (bits > 5) {\n bits -= 5;\n // eslint-disable-next-line no-bitwise\n out += BASE32[mask & (buffer >> bits)];\n }\n }\n\n // Partial character:\n if (bits) {\n // eslint-disable-next-line no-bitwise\n out += BASE32[mask & (buffer << (5 - bits))];\n }\n\n return out;\n}\n\n// https://github.com/pnpm/pnpm/blob/f394cfccda7bc519ceee8c33fc9b68a0f4235532/packages/dependency-path/src/index.ts#L167-L189\nexport function depPathToFilename(depPath: string): string {\n let filename: string = depPathToFilenameUnescaped(depPath).replace(/[\\\\/:*?\"<>|]/g, '+');\n if (filename.includes('(')) {\n filename = filename.replace(/(\\)\\()|\\(/g, '_').replace(/\\)$/, '');\n }\n if (filename.length > 120 || (filename !== filename.toLowerCase() && !filename.startsWith('file+'))) {\n return `${filename.substring(0, MAX_LENGTH_WITHOUT_HASH)}_${createBase32Hash(filename)}`;\n }\n return filename;\n}\n\n/**\n * Computes the root folder for a dependency from a reference to it in another package\n * @param lockfileFolder - The folder that contains the lockfile\n * @param key - The key of the dependency\n * @param specifier - The specifier in the lockfile for the dependency\n * @param context - The owning package\n * @returns The identifier for the dependency\n */\nexport function resolveDependencyKey(\n lockfileFolder: string,\n key: string,\n specifier: string,\n context: IResolverContext\n): string {\n if (specifier.startsWith('/')) {\n return getDescriptionFileRootFromKey(lockfileFolder, specifier);\n } else if (specifier.startsWith('link:')) {\n if (context.isProject) {\n return path.posix.join(context.descriptionFileRoot, specifier.slice(5));\n } else {\n return path.posix.join(lockfileFolder, specifier.slice(5));\n }\n } else if (specifier.startsWith('file:')) {\n return getDescriptionFileRootFromKey(lockfileFolder, specifier, key);\n } else {\n return getDescriptionFileRootFromKey(lockfileFolder, `/${key}@${specifier}`);\n }\n}\n\n/**\n * Computes the physical path to a dependency based on its entry\n * @param lockfileFolder - The folder that contains the lockfile during installation\n * @param key - The key of the dependency\n * @param name - The name of the dependency, if provided\n * @returns The physical path to the dependency\n */\nexport function getDescriptionFileRootFromKey(lockfileFolder: string, key: string, name?: string): string {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n if (!key.startsWith('file:')) {\n name = key.slice(1, key.indexOf('@', 2));\n }\n if (!name) {\n throw new Error(`Missing package name for ${key}`);\n }\n\n const originFolder: string = `${lockfileFolder}/node_modules/.pnpm/${depPathToFilename(key)}/node_modules`;\n const descriptionFileRoot: string = `${originFolder}/${name}`;\n return descriptionFileRoot;\n}\n\nexport function resolveDependencies(\n lockfileFolder: string,\n collection: Record<string, IDependencyEntry>,\n context: IResolverContext\n): void {\n for (const [key, value] of Object.entries(collection)) {\n const version: string = typeof value === 'string' ? value : value.version;\n const resolved: string = resolveDependencyKey(lockfileFolder, key, version, context);\n\n context.deps.set(key, resolved);\n }\n}\n\n/**\n *\n * @param depPath - The path to the dependency\n * @returns The folder name for the dependency\n */\nexport function depPathToFilenameUnescaped(depPath: string): string {\n if (depPath.indexOf('file:') !== 0) {\n if (depPath.startsWith('/')) {\n depPath = depPath.slice(1);\n }\n return depPath;\n }\n return depPath.replace(':', '+');\n}\n\n/**\n *\n * @param missingOptionalDependencies - The set of optional dependencies that were not installed\n * @param contexts - The map of context roots to their respective contexts\n * @param commonPathPrefix - The common root path to trim\n * @returns A function that serializes a context into a format that can be written to disk\n */\nexport function createContextSerializer(\n missingOptionalDependencies: Set<string>,\n contexts: Map<string, IResolverContext>,\n commonPathPrefix: string\n): (entry: [string, IResolverContext]) => ISerializedResolveContext {\n return ([descriptionFileRoot, context]: [string, IResolverContext]): ISerializedResolveContext => {\n const deps: ISerializedResolveContext['deps'] = {};\n for (const [key, contextRoot] of context.deps) {\n if (missingOptionalDependencies.has(contextRoot)) {\n continue;\n }\n\n const resolutionContext: IResolverContext | undefined = contexts.get(contextRoot);\n if (!resolutionContext) {\n throw new Error(`Missing context for ${contextRoot}!`);\n }\n deps[key] = resolutionContext.ordinal;\n }\n\n if (!context.name) {\n throw new Error(`Missing name for ${descriptionFileRoot}`);\n }\n\n const serializedContext: ISerializedResolveContext = {\n name: context.name,\n root: descriptionFileRoot.slice(commonPathPrefix.length),\n dirInfoFiles: context.files,\n deps\n };\n\n return serializedContext;\n };\n}\n"]}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IRushPlugin, RushSession, RushConfiguration } from '@rushstack/rush-sdk';
|
|
2
|
+
/**
|
|
3
|
+
* Plugin that caches information from the package manager after installation to speed up resolution of imports.
|
|
4
|
+
* @beta
|
|
5
|
+
*/
|
|
6
|
+
export default class RushResolverCachePlugin implements IRushPlugin {
|
|
7
|
+
readonly pluginName: 'RushResolverCachePlugin';
|
|
8
|
+
apply(rushSession: RushSession, rushConfiguration: RushConfiguration): void;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,iBAAiB,EAIlB,MAAM,qBAAqB,CAAC;AAE7B;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,uBAAwB,YAAW,WAAW;IACjE,SAAgB,UAAU,EAAE,yBAAyB,CAA6B;IAE3E,KAAK,CAAC,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,iBAAiB,GAAG,IAAI;CAkCnF"}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
|
3
|
+
// See LICENSE in the project root for license information.
|
|
4
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
5
|
+
if (k2 === undefined) k2 = k;
|
|
6
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
8
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
9
|
+
}
|
|
10
|
+
Object.defineProperty(o, k2, desc);
|
|
11
|
+
}) : (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
o[k2] = m[k];
|
|
14
|
+
}));
|
|
15
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
16
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
17
|
+
}) : function(o, v) {
|
|
18
|
+
o["default"] = v;
|
|
19
|
+
});
|
|
20
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
21
|
+
if (mod && mod.__esModule) return mod;
|
|
22
|
+
var result = {};
|
|
23
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
24
|
+
__setModuleDefault(result, mod);
|
|
25
|
+
return result;
|
|
26
|
+
};
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
/**
|
|
29
|
+
* Plugin that caches information from the package manager after installation to speed up resolution of imports.
|
|
30
|
+
* @beta
|
|
31
|
+
*/
|
|
32
|
+
class RushResolverCachePlugin {
|
|
33
|
+
constructor() {
|
|
34
|
+
this.pluginName = 'RushResolverCachePlugin';
|
|
35
|
+
}
|
|
36
|
+
apply(rushSession, rushConfiguration) {
|
|
37
|
+
rushSession.hooks.afterInstall.tapPromise(this.pluginName, async (command, subspace) => {
|
|
38
|
+
const logger = rushSession.getLogger('RushResolverCachePlugin');
|
|
39
|
+
if (rushConfiguration.packageManager !== 'pnpm') {
|
|
40
|
+
logger.emitError(new Error('The RushResolverCachePlugin currently only supports the "pnpm" package manager'));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const pnpmMajorVersion = parseInt(rushConfiguration.packageManagerToolVersion.split('.')[0],
|
|
44
|
+
/* radix */ 10);
|
|
45
|
+
// Lockfile format parsing logic changed in pnpm v8.
|
|
46
|
+
if (pnpmMajorVersion < 8) {
|
|
47
|
+
logger.emitError(new Error('The RushResolverCachePlugin currently only supports pnpm version >=8'));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
// This plugin is not currently webpacked, but these comments are here for future proofing.
|
|
51
|
+
const { afterInstallAsync } = await Promise.resolve().then(() => __importStar(require(
|
|
52
|
+
/* webpackChunkMode: 'eager' */
|
|
53
|
+
/* webpackExports: ["afterInstallAsync"] */
|
|
54
|
+
'./afterInstallAsync')));
|
|
55
|
+
await afterInstallAsync(rushSession, rushConfiguration, subspace, logger);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.default = RushResolverCachePlugin;
|
|
60
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;;;;;;;;;;;;;;;;;;;;;;;AAW3D;;;GAGG;AACH,MAAqB,uBAAuB;IAA5C;QACkB,eAAU,GAA8B,yBAAyB,CAAC;IAoCpF,CAAC;IAlCQ,KAAK,CAAC,WAAwB,EAAE,iBAAoC;QACzE,WAAW,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,CACvC,IAAI,CAAC,UAAU,EACf,KAAK,EAAE,OAAqB,EAAE,QAAkB,EAAE,EAAE;YAClD,MAAM,MAAM,GAAY,WAAW,CAAC,SAAS,CAAC,yBAAyB,CAAC,CAAC;YAEzE,IAAI,iBAAiB,CAAC,cAAc,KAAK,MAAM,EAAE,CAAC;gBAChD,MAAM,CAAC,SAAS,CACd,IAAI,KAAK,CAAC,gFAAgF,CAAC,CAC5F,CAAC;gBACF,OAAO;YACT,CAAC;YAED,MAAM,gBAAgB,GAAW,QAAQ,CACvC,iBAAiB,CAAC,yBAAyB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACzD,WAAW,CAAC,EAAE,CACf,CAAC;YACF,oDAAoD;YACpD,IAAI,gBAAgB,GAAG,CAAC,EAAE,CAAC;gBACzB,MAAM,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAC,CAAC;gBACpG,OAAO;YACT,CAAC;YAED,2FAA2F;YAC3F,MAAM,EAAE,iBAAiB,EAAE,GAAG;YAC5B,+BAA+B;YAC/B,2CAA2C;YAC3C,qBAAqB,GACtB,CAAC;YAEF,MAAM,iBAAiB,CAAC,WAAW,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC5E,CAAC,CACF,CAAC;IACJ,CAAC;CACF;AArCD,0CAqCC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type {\n IRushPlugin,\n RushSession,\n RushConfiguration,\n IRushCommand,\n ILogger,\n Subspace\n} from '@rushstack/rush-sdk';\n\n/**\n * Plugin that caches information from the package manager after installation to speed up resolution of imports.\n * @beta\n */\nexport default class RushResolverCachePlugin implements IRushPlugin {\n public readonly pluginName: 'RushResolverCachePlugin' = 'RushResolverCachePlugin';\n\n public apply(rushSession: RushSession, rushConfiguration: RushConfiguration): void {\n rushSession.hooks.afterInstall.tapPromise(\n this.pluginName,\n async (command: IRushCommand, subspace: Subspace) => {\n const logger: ILogger = rushSession.getLogger('RushResolverCachePlugin');\n\n if (rushConfiguration.packageManager !== 'pnpm') {\n logger.emitError(\n new Error('The RushResolverCachePlugin currently only supports the \"pnpm\" package manager')\n );\n return;\n }\n\n const pnpmMajorVersion: number = parseInt(\n rushConfiguration.packageManagerToolVersion.split('.')[0],\n /* radix */ 10\n );\n // Lockfile format parsing logic changed in pnpm v8.\n if (pnpmMajorVersion < 8) {\n logger.emitError(new Error('The RushResolverCachePlugin currently only supports pnpm version >=8'));\n return;\n }\n\n // This plugin is not currently webpacked, but these comments are here for future proofing.\n const { afterInstallAsync } = await import(\n /* webpackChunkMode: 'eager' */\n /* webpackExports: [\"afterInstallAsync\"] */\n './afterInstallAsync'\n );\n\n await afterInstallAsync(rushSession, rushConfiguration, subspace, logger);\n }\n );\n }\n}\n"]}
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface IResolverContext {
|
|
2
|
+
descriptionFileRoot: string;
|
|
3
|
+
descriptionFileHash: string | undefined;
|
|
4
|
+
name: string;
|
|
5
|
+
deps: Map<string, string>;
|
|
6
|
+
isProject: boolean;
|
|
7
|
+
ordinal: number;
|
|
8
|
+
optional?: boolean;
|
|
9
|
+
files?: string[];
|
|
10
|
+
}
|
|
11
|
+
export type IDependencyEntry = string | {
|
|
12
|
+
version: string;
|
|
13
|
+
specifier: string;
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,MAAM,gBAAgB,GACxB,MAAM,GACN;IACE,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC"}
|
package/lib/types.js
ADDED
package/lib/types.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nexport interface IResolverContext {\n descriptionFileRoot: string;\n descriptionFileHash: string | undefined;\n name: string;\n deps: Map<string, string>;\n isProject: boolean;\n ordinal: number;\n optional?: boolean;\n files?: string[];\n}\n\nexport type IDependencyEntry =\n | string\n | {\n version: string;\n specifier: string;\n };\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rushstack/rush-resolver-cache-plugin",
|
|
3
|
+
"version": "5.133.0",
|
|
4
|
+
"description": "A Rush plugin that generates a resolver cache file after successful install.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"url": "https://github.com/microsoft/rushstack.git",
|
|
8
|
+
"type": "git",
|
|
9
|
+
"directory": "rush-plugins/rush-resolver-cache-plugin"
|
|
10
|
+
},
|
|
11
|
+
"main": "lib-commonjs/index.js",
|
|
12
|
+
"types": "dist/rush-resolver-cache-plugin.d.ts",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@rushstack/rush-sdk": "5.133.0"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/webpack-env": "1.18.0",
|
|
18
|
+
"@rushstack/lookup-by-path": "0.1.2",
|
|
19
|
+
"@rushstack/terminal": "0.14.0",
|
|
20
|
+
"@rushstack/node-core-library": "5.7.0",
|
|
21
|
+
"@rushstack/heft": "0.67.0",
|
|
22
|
+
"local-node-rig": "1.0.0",
|
|
23
|
+
"@rushstack/webpack-workspace-resolve-plugin": "0.1.1"
|
|
24
|
+
},
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"require": "./lib/index.js",
|
|
28
|
+
"types": "./dist/rush-resolver-cache-plugin.d.ts"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"typesVersions": {
|
|
32
|
+
"*": {
|
|
33
|
+
".": [
|
|
34
|
+
"dist/rush-resolver-cache-plugin.d.ts"
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "heft test --clean",
|
|
40
|
+
"_phase:build": "heft run --only build -- --clean",
|
|
41
|
+
"_phase:test": "heft run --only test -- --clean"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugin-manifest.schema.json",
|
|
3
|
+
"plugins": [
|
|
4
|
+
{
|
|
5
|
+
"pluginName": "rush-resolver-cache-plugin",
|
|
6
|
+
"description": "Rush plugin for generating a resolver cache file after successful install.",
|
|
7
|
+
"entryPoint": "lib/index.js"
|
|
8
|
+
}
|
|
9
|
+
]
|
|
10
|
+
}
|