@rushstack/webpack-workspace-resolve-plugin 0.1.2 → 0.3.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/CHANGELOG.json CHANGED
@@ -1,6 +1,35 @@
1
1
  {
2
2
  "name": "@rushstack/webpack-workspace-resolve-plugin",
3
3
  "entries": [
4
+ {
5
+ "version": "0.3.0",
6
+ "tag": "@rushstack/webpack-workspace-resolve-plugin_v0.3.0",
7
+ "date": "Wed, 28 Aug 2024 00:11:41 GMT",
8
+ "comments": {
9
+ "minor": [
10
+ {
11
+ "comment": "Expect the base path to be part of the resolver cache file."
12
+ }
13
+ ]
14
+ }
15
+ },
16
+ {
17
+ "version": "0.2.0",
18
+ "tag": "@rushstack/webpack-workspace-resolve-plugin_v0.2.0",
19
+ "date": "Tue, 27 Aug 2024 15:12:33 GMT",
20
+ "comments": {
21
+ "minor": [
22
+ {
23
+ "comment": "Support hierarchical `node_modules` folders."
24
+ }
25
+ ],
26
+ "dependency": [
27
+ {
28
+ "comment": "Updating dependency \"@rushstack/lookup-by-path\" to `0.2.0`"
29
+ }
30
+ ]
31
+ }
32
+ },
4
33
  {
5
34
  "version": "0.1.2",
6
35
  "tag": "@rushstack/webpack-workspace-resolve-plugin_v0.1.2",
package/CHANGELOG.md CHANGED
@@ -1,6 +1,20 @@
1
1
  # Change Log - @rushstack/webpack-workspace-resolve-plugin
2
2
 
3
- This log was last generated on Mon, 26 Aug 2024 02:00:11 GMT and should not be manually modified.
3
+ This log was last generated on Wed, 28 Aug 2024 00:11:41 GMT and should not be manually modified.
4
+
5
+ ## 0.3.0
6
+ Wed, 28 Aug 2024 00:11:41 GMT
7
+
8
+ ### Minor changes
9
+
10
+ - Expect the base path to be part of the resolver cache file.
11
+
12
+ ## 0.2.0
13
+ Tue, 27 Aug 2024 15:12:33 GMT
14
+
15
+ ### Minor changes
16
+
17
+ - Support hierarchical `node_modules` folders.
4
18
 
5
19
  ## 0.1.2
6
20
  Mon, 26 Aug 2024 02:00:11 GMT
package/README.md CHANGED
@@ -17,6 +17,14 @@ When using this plugin, the following options should be configured for your reso
17
17
  - `symlinks: false` - Since the cache knows the symlinks for package dependencies, you can avoid the cost of testing for other symlinks unless you are using additional symlinks.
18
18
  - `modules: []` - The cache should contain all information necessary to locate available dependencies for any arbitrary folder. If you need to allow resolution in other roots, you can add those, but omit `'node_modules'`.
19
19
 
20
+ ## Impact
21
+
22
+ This plugin should eliminate file system calls associated with the following operations of NodeJS module resolution in webpack:
23
+ - Find the nearest `package.json` to the calling module
24
+ - Locate a named package from a calling module
25
+ - Identify a `package.json` in a resolved directory
26
+ - Find the nearest `package.json` to a resolved file path
27
+
20
28
  ## Limitations
21
29
 
22
30
  This plugin depends on the presence of a cache file in the workspace to function. Data in this cache file is assumed not to change while the webpack process is running.
@@ -34,6 +34,10 @@ export declare interface IResolveContext {
34
34
  * @beta
35
35
  */
36
36
  export declare interface IResolverCacheFile {
37
+ /**
38
+ * The base path. All paths in context entries are prefixed by this path.
39
+ */
40
+ basePath: string;
37
41
  /**
38
42
  * The ordered list of all contexts in the cache
39
43
  */
@@ -55,9 +59,9 @@ export declare interface ISerializedResolveContext {
55
59
  */
56
60
  name: string;
57
61
  /**
58
- * Map of declared dependencies to the ordinal of the corresponding context.
62
+ * Map of declared dependencies (if any) to the ordinal of the corresponding context.
59
63
  */
60
- deps: Record<string, number>;
64
+ deps?: Record<string, number>;
61
65
  /**
62
66
  * Set of relative paths to nested `package.json` files within this context.
63
67
  * These paths are normalized to use `/` as the separator and should not begin with a leading `./`.
@@ -70,10 +74,6 @@ export declare interface ISerializedResolveContext {
70
74
  * @beta
71
75
  */
72
76
  export declare interface IWorkspaceLayoutCacheOptions {
73
- /**
74
- * The root folder of the workspace. All paths in the cache file are assumed to be relative to this folder.
75
- */
76
- workspaceRoot: string;
77
77
  /**
78
78
  * The parsed cache data. File reading is left as an exercise for the caller.
79
79
  */
@@ -109,7 +109,7 @@ export declare class WorkspaceLayoutCache {
109
109
  /**
110
110
  * A weak map of package JSON contents to their corresponding context objects
111
111
  */
112
- readonly contextForPackage: WeakMap<object, IResolveContext>;
112
+ readonly contextForPackage: WeakMap<object, IPrefixMatch<IResolveContext>>;
113
113
  readonly resolverPathSeparator: string;
114
114
  readonly normalizeToSlash: IPathNormalizationFunction;
115
115
  readonly normalizeToPlatform: IPathNormalizationFunction;
@@ -67,7 +67,7 @@ class KnownDescriptionFilePlugin {
67
67
  }
68
68
  (_b = resolveContext.fileDependencies) === null || _b === void 0 ? void 0 : _b.add(descriptionFilePath);
69
69
  // Store the resolver context since a WeakMap lookup is cheaper than walking the tree again
70
- contextForPackage.set(descriptionFileData, match.value);
70
+ contextForPackage.set(descriptionFileData, match);
71
71
  const obj = {
72
72
  ...request,
73
73
  descriptionFileRoot,
@@ -1 +1 @@
1
- {"version":3,"file":"KnownDescriptionFilePlugin.js","sourceRoot":"","sources":["../src/KnownDescriptionFilePlugin.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 { Resolver } from 'webpack';\nimport type { IPrefixMatch } from '@rushstack/lookup-by-path';\nimport type { IResolveContext, WorkspaceLayoutCache } from './WorkspaceLayoutCache';\n\ntype ResolveRequest = Parameters<Resolver['hooks']['resolveStep']['call']>[1];\n\n/**\n * A resolver plugin that optimizes locating the package.json file for a module.\n *\n * @internal\n */\nexport class KnownDescriptionFilePlugin {\n public readonly source: string;\n public readonly target: string;\n\n private readonly _skipForContext: boolean;\n private readonly _cache: WorkspaceLayoutCache;\n\n /**\n * Constructs a new instance of `KnownDescriptionFilePlugin`.\n * @param cache - The workspace layout cache\n * @param source - The resolve step to hook into\n * @param target - The resolve step to delegate to\n * @param skipForContext - If true, don't apply this plugin if the resolver is configured to resolve to a context\n */\n public constructor(cache: WorkspaceLayoutCache, source: string, target: string, skipForContext?: boolean) {\n this.source = source;\n this.target = target;\n this._cache = cache;\n this._skipForContext = !!skipForContext;\n }\n\n public apply(resolver: Resolver): void {\n if (this._skipForContext && resolver.options.resolveToContext) {\n return;\n }\n\n const target: ReturnType<Resolver['ensureHook']> = resolver.ensureHook(this.target);\n const { fileSystem } = resolver;\n\n function readDescriptionFileWithParse(\n descriptionFilePath: string,\n callback: (err: Error | null | undefined, data?: object) => void\n ): void {\n fileSystem.readFile(descriptionFilePath, (err: Error | null | undefined, data?: string | Buffer) => {\n if (!data?.length) {\n return callback(err);\n }\n // eslint-disable-next-line @rushstack/no-new-null\n callback(null, JSON.parse(data.toString()));\n });\n }\n\n const readDescriptionFile: (\n descriptionFilePath: string,\n cb: (err: Error | null | undefined, data?: object) => void\n ) => void = fileSystem.readJson?.bind(fileSystem) ?? readDescriptionFileWithParse;\n\n resolver\n .getHook(this.source)\n .tapAsync(KnownDescriptionFilePlugin.name, (request, resolveContext, callback) => {\n const { path } = request;\n if (!path) {\n // No request, nothing to do.\n return callback();\n }\n\n const cache: WorkspaceLayoutCache = this._cache;\n\n const match: IPrefixMatch<IResolveContext> | undefined =\n cache.contextLookup.findLongestPrefixMatch(path);\n if (!match) {\n // No description file available, proceed without.\n return callback();\n }\n\n const remainingPath: string = path.slice(match.index);\n const relativePath: string = `.${cache.normalizeToSlash?.(remainingPath) ?? remainingPath}`;\n const descriptionFileRoot: string = `${path.slice(0, match.index)}`;\n const descriptionFilePath: string = `${descriptionFileRoot}${cache.resolverPathSeparator}package.json`;\n\n const { contextForPackage } = cache;\n\n readDescriptionFile(descriptionFilePath, (err, descriptionFileData) => {\n if (!descriptionFileData) {\n resolveContext.missingDependencies?.add(descriptionFilePath);\n return callback(err);\n }\n\n resolveContext.fileDependencies?.add(descriptionFilePath);\n // Store the resolver context since a WeakMap lookup is cheaper than walking the tree again\n contextForPackage.set(descriptionFileData, match.value);\n\n const obj: ResolveRequest = {\n ...request,\n descriptionFileRoot,\n descriptionFilePath,\n descriptionFileData,\n relativePath\n };\n\n // Delegate to the resolver step at `target`.\n resolver.doResolve(\n target,\n obj,\n 'using description file: ' + descriptionFilePath + ' (relative path: ' + relativePath + ')',\n resolveContext,\n (e: Error | undefined, result: ResolveRequest | undefined) => {\n if (e) {\n return callback(e);\n }\n\n // Don't allow other processing\n if (result === undefined) {\n // eslint-disable-next-line @rushstack/no-new-null\n return callback(null, null);\n }\n // eslint-disable-next-line @rushstack/no-new-null\n callback(null, result);\n }\n );\n });\n });\n }\n}\n"]}
1
+ {"version":3,"file":"KnownDescriptionFilePlugin.js","sourceRoot":"","sources":["../src/KnownDescriptionFilePlugin.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 { Resolver } from 'webpack';\nimport type { IPrefixMatch } from '@rushstack/lookup-by-path';\nimport type { IResolveContext, WorkspaceLayoutCache } from './WorkspaceLayoutCache';\n\ntype ResolveRequest = Parameters<Resolver['hooks']['resolveStep']['call']>[1];\n\n/**\n * A resolver plugin that optimizes locating the package.json file for a module.\n *\n * @internal\n */\nexport class KnownDescriptionFilePlugin {\n public readonly source: string;\n public readonly target: string;\n\n private readonly _skipForContext: boolean;\n private readonly _cache: WorkspaceLayoutCache;\n\n /**\n * Constructs a new instance of `KnownDescriptionFilePlugin`.\n * @param cache - The workspace layout cache\n * @param source - The resolve step to hook into\n * @param target - The resolve step to delegate to\n * @param skipForContext - If true, don't apply this plugin if the resolver is configured to resolve to a context\n */\n public constructor(cache: WorkspaceLayoutCache, source: string, target: string, skipForContext?: boolean) {\n this.source = source;\n this.target = target;\n this._cache = cache;\n this._skipForContext = !!skipForContext;\n }\n\n public apply(resolver: Resolver): void {\n if (this._skipForContext && resolver.options.resolveToContext) {\n return;\n }\n\n const target: ReturnType<Resolver['ensureHook']> = resolver.ensureHook(this.target);\n const { fileSystem } = resolver;\n\n function readDescriptionFileWithParse(\n descriptionFilePath: string,\n callback: (err: Error | null | undefined, data?: object) => void\n ): void {\n fileSystem.readFile(descriptionFilePath, (err: Error | null | undefined, data?: string | Buffer) => {\n if (!data?.length) {\n return callback(err);\n }\n // eslint-disable-next-line @rushstack/no-new-null\n callback(null, JSON.parse(data.toString()));\n });\n }\n\n const readDescriptionFile: (\n descriptionFilePath: string,\n cb: (err: Error | null | undefined, data?: object) => void\n ) => void = fileSystem.readJson?.bind(fileSystem) ?? readDescriptionFileWithParse;\n\n resolver\n .getHook(this.source)\n .tapAsync(KnownDescriptionFilePlugin.name, (request, resolveContext, callback) => {\n const { path } = request;\n if (!path) {\n // No request, nothing to do.\n return callback();\n }\n\n const cache: WorkspaceLayoutCache = this._cache;\n\n const match: IPrefixMatch<IResolveContext> | undefined =\n cache.contextLookup.findLongestPrefixMatch(path);\n if (!match) {\n // No description file available, proceed without.\n return callback();\n }\n\n const remainingPath: string = path.slice(match.index);\n const relativePath: string = `.${cache.normalizeToSlash?.(remainingPath) ?? remainingPath}`;\n const descriptionFileRoot: string = `${path.slice(0, match.index)}`;\n const descriptionFilePath: string = `${descriptionFileRoot}${cache.resolverPathSeparator}package.json`;\n\n const { contextForPackage } = cache;\n\n readDescriptionFile(descriptionFilePath, (err, descriptionFileData) => {\n if (!descriptionFileData) {\n resolveContext.missingDependencies?.add(descriptionFilePath);\n return callback(err);\n }\n\n resolveContext.fileDependencies?.add(descriptionFilePath);\n // Store the resolver context since a WeakMap lookup is cheaper than walking the tree again\n contextForPackage.set(descriptionFileData, match);\n\n const obj: ResolveRequest = {\n ...request,\n descriptionFileRoot,\n descriptionFilePath,\n descriptionFileData,\n relativePath\n };\n\n // Delegate to the resolver step at `target`.\n resolver.doResolve(\n target,\n obj,\n 'using description file: ' + descriptionFilePath + ' (relative path: ' + relativePath + ')',\n resolveContext,\n (e: Error | undefined, result: ResolveRequest | undefined) => {\n if (e) {\n return callback(e);\n }\n\n // Don't allow other processing\n if (result === undefined) {\n // eslint-disable-next-line @rushstack/no-new-null\n return callback(null, null);\n }\n // eslint-disable-next-line @rushstack/no-new-null\n callback(null, result);\n }\n );\n });\n });\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"KnownPackageDependenciesPlugin.d.ts","sourceRoot":"","sources":["../src/KnownPackageDependenciesPlugin.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,OAAO,KAAK,EAAmB,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAIpF;;;;;GAKG;AACH,qBAAa,8BAA8B;IACzC,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,MAAM,EAAE,MAAM,CAAC;IAE/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAE9C;;;;;OAKG;gBACgB,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAMvE,KAAK,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;CAsDvC"}
1
+ {"version":3,"file":"KnownPackageDependenciesPlugin.d.ts","sourceRoot":"","sources":["../src/KnownPackageDependenciesPlugin.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,OAAO,KAAK,EAAmB,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAIpF;;;;;GAKG;AACH,qBAAa,8BAA8B;IACzC,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,MAAM,EAAE,MAAM,CAAC;IAE/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAE9C;;;;;OAKG;gBACgB,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAMvE,KAAK,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;CA4DvC"}
@@ -39,19 +39,23 @@ class KnownPackageDependenciesPlugin {
39
39
  return callback(new Error(`Expected descriptionFileData for ${path}`));
40
40
  }
41
41
  const cache = this._cache;
42
- const context = cache.contextForPackage.get(descriptionFileData);
43
- if (!context) {
42
+ let scope = cache.contextForPackage.get(descriptionFileData);
43
+ if (!scope) {
44
44
  return callback(new Error(`Expected context for ${request.descriptionFileRoot}`));
45
45
  }
46
- const match = context.findDependency(rawRequest);
47
- if (!match) {
46
+ let dependency;
47
+ while (scope && !dependency) {
48
+ dependency = scope.value.findDependency(rawRequest);
49
+ scope = scope.lastMatch;
50
+ }
51
+ if (!dependency) {
48
52
  return callback();
49
53
  }
50
- const isPackageRoot = match.index === rawRequest.length;
54
+ const isPackageRoot = dependency.index === rawRequest.length;
51
55
  const fullySpecified = isPackageRoot ? false : request.fullySpecified;
52
- const remainingPath = isPackageRoot ? '.' : `.${rawRequest.slice(match.index)}`;
56
+ const remainingPath = isPackageRoot ? '.' : `.${rawRequest.slice(dependency.index)}`;
53
57
  const relativePath = (remainingPath.length > 1 && ((_a = cache.normalizeToSlash) === null || _a === void 0 ? void 0 : _a.call(cache, remainingPath))) || remainingPath;
54
- const { descriptionFileRoot } = match.value;
58
+ const { descriptionFileRoot } = dependency.value;
55
59
  const obj = {
56
60
  ...request,
57
61
  path: descriptionFileRoot,
@@ -1 +1 @@
1
- {"version":3,"file":"KnownPackageDependenciesPlugin.js","sourceRoot":"","sources":["../src/KnownPackageDependenciesPlugin.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAQ3D;;;;;GAKG;AACH,MAAa,8BAA8B;IAMzC;;;;;OAKG;IACH,YAAmB,KAA2B,EAAE,MAAc,EAAE,MAAc;QAC5E,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAEM,KAAK,CAAC,QAAkB;QAC7B,MAAM,MAAM,GAAuC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEpF,QAAQ;aACL,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;aACpB,QAAQ,CAAC,8BAA8B,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,EAAE;;YACnF,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;YAC9C,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,QAAQ,EAAE,CAAC;YACpB,CAAC;YAED,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,OAAO,QAAQ,EAAE,CAAC;YACpB,CAAC;YAED,MAAM,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC;YACxC,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBACzB,OAAO,QAAQ,CAAC,IAAI,KAAK,CAAC,oCAAoC,IAAI,EAAE,CAAC,CAAC,CAAC;YACzE,CAAC;YAED,MAAM,KAAK,GAAyB,IAAI,CAAC,MAAM,CAAC;YAEhD,MAAM,OAAO,GAAgC,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;YAC9F,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,QAAQ,CAAC,IAAI,KAAK,CAAC,wBAAwB,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC;YACpF,CAAC;YAED,MAAM,KAAK,GAA8C,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;YAC5F,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,QAAQ,EAAE,CAAC;YACpB,CAAC;YAED,MAAM,aAAa,GAAY,KAAK,CAAC,KAAK,KAAK,UAAU,CAAC,MAAM,CAAC;YACjE,MAAM,cAAc,GAAwB,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC;YAC3F,MAAM,aAAa,GAAW,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YACxF,MAAM,YAAY,GAChB,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,KAAI,MAAA,KAAK,CAAC,gBAAgB,sDAAG,aAAa,CAAC,CAAA,CAAC,IAAI,aAAa,CAAC;YACzF,MAAM,EAAE,mBAAmB,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC;YAC5C,MAAM,GAAG,GAAmB;gBAC1B,GAAG,OAAO;gBACV,IAAI,EAAE,mBAAmB;gBACzB,mBAAmB;gBACnB,mBAAmB,EAAE,SAAS;gBAC9B,mBAAmB,EAAE,GAAG,mBAAmB,GAAG,KAAK,CAAC,qBAAqB,cAAc;gBAEvF,YAAY,EAAE,YAAY;gBAC1B,OAAO,EAAE,YAAY;gBACrB,cAAc;gBACd,MAAM,EAAE,KAAK;aACd,CAAC;YACF,kDAAkD;YAClD,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;IACP,CAAC;CACF;AAxED,wEAwEC","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 { Resolver } from 'webpack';\nimport type { IPrefixMatch } from '@rushstack/lookup-by-path';\nimport type { IResolveContext, WorkspaceLayoutCache } from './WorkspaceLayoutCache';\n\ntype ResolveRequest = Parameters<Resolver['hooks']['resolveStep']['call']>[1];\n\n/**\n * A resolver plugin that optimizes resolving installed dependencies for the current package.\n * Enforces strict resolution.\n *\n * @internal\n */\nexport class KnownPackageDependenciesPlugin {\n public readonly source: string;\n public readonly target: string;\n\n private readonly _cache: WorkspaceLayoutCache;\n\n /**\n * Constructs a new instance of `KnownPackageDependenciesPlugin`.\n * @param cache - The workspace layout cache\n * @param source - The resolve step to hook into\n * @param target - The resolve step to delegate to\n */\n public constructor(cache: WorkspaceLayoutCache, source: string, target: string) {\n this.source = source;\n this.target = target;\n this._cache = cache;\n }\n\n public apply(resolver: Resolver): void {\n const target: ReturnType<Resolver['ensureHook']> = resolver.ensureHook(this.target);\n\n resolver\n .getHook(this.source)\n .tapAsync(KnownPackageDependenciesPlugin.name, (request, resolveContext, callback) => {\n const { path, request: rawRequest } = request;\n if (!path) {\n return callback();\n }\n\n if (!rawRequest) {\n return callback();\n }\n\n const { descriptionFileData } = request;\n if (!descriptionFileData) {\n return callback(new Error(`Expected descriptionFileData for ${path}`));\n }\n\n const cache: WorkspaceLayoutCache = this._cache;\n\n const context: IResolveContext | undefined = cache.contextForPackage.get(descriptionFileData);\n if (!context) {\n return callback(new Error(`Expected context for ${request.descriptionFileRoot}`));\n }\n\n const match: IPrefixMatch<IResolveContext> | undefined = context.findDependency(rawRequest);\n if (!match) {\n return callback();\n }\n\n const isPackageRoot: boolean = match.index === rawRequest.length;\n const fullySpecified: boolean | undefined = isPackageRoot ? false : request.fullySpecified;\n const remainingPath: string = isPackageRoot ? '.' : `.${rawRequest.slice(match.index)}`;\n const relativePath: string =\n (remainingPath.length > 1 && cache.normalizeToSlash?.(remainingPath)) || remainingPath;\n const { descriptionFileRoot } = match.value;\n const obj: ResolveRequest = {\n ...request,\n path: descriptionFileRoot,\n descriptionFileRoot,\n descriptionFileData: undefined,\n descriptionFilePath: `${descriptionFileRoot}${cache.resolverPathSeparator}package.json`,\n\n relativePath: relativePath,\n request: relativePath,\n fullySpecified,\n module: false\n };\n // eslint-disable-next-line @rushstack/no-new-null\n resolver.doResolve(target, obj, null, resolveContext, callback);\n });\n }\n}\n"]}
1
+ {"version":3,"file":"KnownPackageDependenciesPlugin.js","sourceRoot":"","sources":["../src/KnownPackageDependenciesPlugin.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 { Resolver } from 'webpack';\nimport type { IPrefixMatch } from '@rushstack/lookup-by-path';\nimport type { IResolveContext, WorkspaceLayoutCache } from './WorkspaceLayoutCache';\n\ntype ResolveRequest = Parameters<Resolver['hooks']['resolveStep']['call']>[1];\n\n/**\n * A resolver plugin that optimizes resolving installed dependencies for the current package.\n * Enforces strict resolution.\n *\n * @internal\n */\nexport class KnownPackageDependenciesPlugin {\n public readonly source: string;\n public readonly target: string;\n\n private readonly _cache: WorkspaceLayoutCache;\n\n /**\n * Constructs a new instance of `KnownPackageDependenciesPlugin`.\n * @param cache - The workspace layout cache\n * @param source - The resolve step to hook into\n * @param target - The resolve step to delegate to\n */\n public constructor(cache: WorkspaceLayoutCache, source: string, target: string) {\n this.source = source;\n this.target = target;\n this._cache = cache;\n }\n\n public apply(resolver: Resolver): void {\n const target: ReturnType<Resolver['ensureHook']> = resolver.ensureHook(this.target);\n\n resolver\n .getHook(this.source)\n .tapAsync(KnownPackageDependenciesPlugin.name, (request, resolveContext, callback) => {\n const { path, request: rawRequest } = request;\n if (!path) {\n return callback();\n }\n\n if (!rawRequest) {\n return callback();\n }\n\n const { descriptionFileData } = request;\n if (!descriptionFileData) {\n return callback(new Error(`Expected descriptionFileData for ${path}`));\n }\n\n const cache: WorkspaceLayoutCache = this._cache;\n\n let scope: IPrefixMatch<IResolveContext> | undefined =\n cache.contextForPackage.get(descriptionFileData);\n if (!scope) {\n return callback(new Error(`Expected context for ${request.descriptionFileRoot}`));\n }\n\n let dependency: IPrefixMatch<IResolveContext> | undefined;\n while (scope && !dependency) {\n dependency = scope.value.findDependency(rawRequest);\n scope = scope.lastMatch;\n }\n\n if (!dependency) {\n return callback();\n }\n\n const isPackageRoot: boolean = dependency.index === rawRequest.length;\n const fullySpecified: boolean | undefined = isPackageRoot ? false : request.fullySpecified;\n const remainingPath: string = isPackageRoot ? '.' : `.${rawRequest.slice(dependency.index)}`;\n const relativePath: string =\n (remainingPath.length > 1 && cache.normalizeToSlash?.(remainingPath)) || remainingPath;\n const { descriptionFileRoot } = dependency.value;\n const obj: ResolveRequest = {\n ...request,\n path: descriptionFileRoot,\n descriptionFileRoot,\n descriptionFileData: undefined,\n descriptionFilePath: `${descriptionFileRoot}${cache.resolverPathSeparator}package.json`,\n\n relativePath: relativePath,\n request: relativePath,\n fullySpecified,\n module: false\n };\n // eslint-disable-next-line @rushstack/no-new-null\n resolver.doResolve(target, obj, null, resolveContext, callback);\n });\n }\n}\n"]}
@@ -14,9 +14,9 @@ export interface ISerializedResolveContext {
14
14
  */
15
15
  name: string;
16
16
  /**
17
- * Map of declared dependencies to the ordinal of the corresponding context.
17
+ * Map of declared dependencies (if any) to the ordinal of the corresponding context.
18
18
  */
19
- deps: Record<string, number>;
19
+ deps?: Record<string, number>;
20
20
  /**
21
21
  * Set of relative paths to nested `package.json` files within this context.
22
22
  * These paths are normalized to use `/` as the separator and should not begin with a leading `./`.
@@ -30,6 +30,10 @@ export interface ISerializedResolveContext {
30
30
  * @beta
31
31
  */
32
32
  export interface IResolverCacheFile {
33
+ /**
34
+ * The base path. All paths in context entries are prefixed by this path.
35
+ */
36
+ basePath: string;
33
37
  /**
34
38
  * The ordered list of all contexts in the cache
35
39
  */
@@ -55,10 +59,6 @@ export interface IResolveContext {
55
59
  * @beta
56
60
  */
57
61
  export interface IWorkspaceLayoutCacheOptions {
58
- /**
59
- * The root folder of the workspace. All paths in the cache file are assumed to be relative to this folder.
60
- */
61
- workspaceRoot: string;
62
62
  /**
63
63
  * The parsed cache data. File reading is left as an exercise for the caller.
64
64
  */
@@ -88,7 +88,7 @@ export declare class WorkspaceLayoutCache {
88
88
  /**
89
89
  * A weak map of package JSON contents to their corresponding context objects
90
90
  */
91
- readonly contextForPackage: WeakMap<object, IResolveContext>;
91
+ readonly contextForPackage: WeakMap<object, IPrefixMatch<IResolveContext>>;
92
92
  readonly resolverPathSeparator: string;
93
93
  readonly normalizeToSlash: IPathNormalizationFunction;
94
94
  readonly normalizeToPlatform: IPathNormalizationFunction;
@@ -1 +1 @@
1
- {"version":3,"file":"WorkspaceLayoutCache.d.ts","sourceRoot":"","sources":["../src/WorkspaceLayoutCache.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE5E;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,QAAQ,EAAE,yBAAyB,EAAE,CAAC;CACvC;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAAC,eAAe,CAAC,GAAG,SAAS,CAAC;CAC5E;AAED;;;GAGG;AACH,MAAM,WAAW,4BAA4B;IAC3C;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,SAAS,EAAE,kBAAkB,CAAC;IAC9B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;CACpC;AAED;;;;;GAKG;AACH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;AAUjF;;;GAGG;AACH,qBAAa,oBAAoB;IAC/B;;OAEG;IACH,SAAgB,aAAa,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC;IAC7D;;OAEG;IACH,SAAgB,iBAAiB,EAAE,OAAO,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAEpE,SAAgB,qBAAqB,EAAE,MAAM,CAAC;IAC9C,SAAgB,gBAAgB,EAAE,0BAA0B,CAAC;IAC7D,SAAgB,mBAAmB,EAAE,0BAA0B,CAAC;gBAE7C,OAAO,EAAE,4BAA4B;CAoFzD"}
1
+ {"version":3,"file":"WorkspaceLayoutCache.d.ts","sourceRoot":"","sources":["../src/WorkspaceLayoutCache.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE5E;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,QAAQ,EAAE,yBAAyB,EAAE,CAAC;CACvC;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAAC,eAAe,CAAC,GAAG,SAAS,CAAC;CAC5E;AAED;;;GAGG;AACH,MAAM,WAAW,4BAA4B;IAC3C;;OAEG;IACH,SAAS,EAAE,kBAAkB,CAAC;IAC9B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;CACpC;AAED;;;;;GAKG;AACH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;AAUjF;;;GAGG;AACH,qBAAa,oBAAoB;IAC/B;;OAEG;IACH,SAAgB,aAAa,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC;IAC7D;;OAEG;IACH,SAAgB,iBAAiB,EAAE,OAAO,CAAC,MAAM,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC,CAAC;IAElF,SAAgB,qBAAqB,EAAE,MAAM,CAAC;IAC9C,SAAgB,gBAAgB,EAAE,0BAA0B,CAAC;IAC7D,SAAgB,mBAAmB,EAAE,0BAA0B,CAAC;gBAE7C,OAAO,EAAE,4BAA4B;CA0FzD"}
@@ -17,10 +17,11 @@ function slashToBackslash(path) {
17
17
  */
18
18
  class WorkspaceLayoutCache {
19
19
  constructor(options) {
20
- const { workspaceRoot, cacheData, resolverPathSeparator = node_path_1.sep } = options;
20
+ const { cacheData, resolverPathSeparator = node_path_1.sep } = options;
21
21
  if (resolverPathSeparator !== '/' && resolverPathSeparator !== '\\') {
22
22
  throw new Error(`Unsupported directory separator: ${resolverPathSeparator}`);
23
23
  }
24
+ const { basePath } = cacheData;
24
25
  const resolveContexts = [];
25
26
  const contextLookup = new lookup_by_path_1.LookupByPath(undefined, resolverPathSeparator);
26
27
  this.contextLookup = contextLookup;
@@ -40,7 +41,7 @@ class WorkspaceLayoutCache {
40
41
  get descriptionFileRoot() {
41
42
  var _a;
42
43
  if (!this._descriptionFileRoot) {
43
- this._descriptionFileRoot = `${workspaceRoot}${resolverPathSeparator}${(_a = normalizeToPlatform === null || normalizeToPlatform === void 0 ? void 0 : normalizeToPlatform(this._serialized.root)) !== null && _a !== void 0 ? _a : this._serialized.root}`;
44
+ this._descriptionFileRoot = `${basePath}${(_a = normalizeToPlatform === null || normalizeToPlatform === void 0 ? void 0 : normalizeToPlatform(this._serialized.root)) !== null && _a !== void 0 ? _a : this._serialized.root}`;
44
45
  }
45
46
  return this._descriptionFileRoot;
46
47
  }
@@ -48,11 +49,14 @@ class WorkspaceLayoutCache {
48
49
  if (!this._dependencies) {
49
50
  // Lazy initialize this object since most packages won't be requested.
50
51
  const dependencies = new lookup_by_path_1.LookupByPath(undefined, '/');
52
+ const { name, deps } = this._serialized;
51
53
  // Handle the self-reference scenario
52
- dependencies.setItem(this._serialized.name, this);
53
- for (const [key, ordinal] of Object.entries(this._serialized.deps)) {
54
- // This calls into the array of instances that is owned by WorkpaceLayoutCache
55
- dependencies.setItem(key, resolveContexts[ordinal]);
54
+ dependencies.setItem(name, this);
55
+ if (deps) {
56
+ for (const [key, ordinal] of Object.entries(deps)) {
57
+ // This calls into the array of instances that is owned by WorkpaceLayoutCache
58
+ dependencies.setItem(key, resolveContexts[ordinal]);
59
+ }
56
60
  }
57
61
  this._dependencies = dependencies;
58
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"WorkspaceLayoutCache.js","sourceRoot":"","sources":["../src/WorkspaceLayoutCache.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 { sep as directorySeparator } from 'node:path';\n\nimport { LookupByPath, type IPrefixMatch } from '@rushstack/lookup-by-path';\n\n/**\n * Information about a local or installed npm package.\n * @beta\n */\nexport interface ISerializedResolveContext {\n /**\n * The path to the root folder of this context.\n * This path is normalized to use `/` as the separator and should not end with a trailing `/`.\n */\n root: string;\n /**\n * The name of this package. Used to inject a self-reference into the dependency map.\n */\n name: string;\n /**\n * Map of declared dependencies to the ordinal of the corresponding context.\n */\n deps: Record<string, number>;\n /**\n * Set of relative paths to nested `package.json` files within this context.\n * These paths are normalized to use `/` as the separator and should not begin with a leading `./`.\n */\n dirInfoFiles?: string[];\n}\n\n/**\n * The serialized form of the cache file. This file is expected to be generated by a separate tool from\n * information known to the package manager. Namely, the dependency relationships between packages, and\n * all the `package.json` files in the workspace (installed or local).\n * @beta\n */\nexport interface IResolverCacheFile {\n /**\n * The ordered list of all contexts in the cache\n */\n contexts: ISerializedResolveContext[];\n}\n\n/**\n * A context for resolving dependencies in a workspace.\n * @beta\n */\nexport interface IResolveContext {\n /**\n * The absolute path to the root folder of this context\n */\n descriptionFileRoot: string;\n /**\n * Find the context that corresponds to a module specifier, when requested in the current context.\n * @param request - The module specifier to resolve\n */\n findDependency(request: string): IPrefixMatch<IResolveContext> | undefined;\n}\n\n/**\n * Options for creating a `WorkspaceLayoutCache`.\n * @beta\n */\nexport interface IWorkspaceLayoutCacheOptions {\n /**\n * The root folder of the workspace. All paths in the cache file are assumed to be relative to this folder.\n */\n workspaceRoot: string;\n /**\n * The parsed cache data. File reading is left as an exercise for the caller.\n */\n cacheData: IResolverCacheFile;\n /**\n * The directory separator used in the `path` field of the resolver inputs.\n * Will usually be `path.sep`.\n */\n resolverPathSeparator?: '/' | '\\\\';\n}\n\n/**\n * A function that normalizes a path to a platform-specific format (if needed).\n * Will be undefined if the platform uses `/` as the path separator.\n *\n * @beta\n */\nexport type IPathNormalizationFunction = ((input: string) => string) | undefined;\n\nfunction backslashToSlash(path: string): string {\n return path.replace(/\\\\/g, '/');\n}\n\nfunction slashToBackslash(path: string): string {\n return path.replace(/\\//g, '\\\\');\n}\n\n/**\n * A cache of workspace layout information.\n * @beta\n */\nexport class WorkspaceLayoutCache {\n /**\n * A lookup of context roots to their corresponding context objects\n */\n public readonly contextLookup: LookupByPath<IResolveContext>;\n /**\n * A weak map of package JSON contents to their corresponding context objects\n */\n public readonly contextForPackage: WeakMap<object, IResolveContext>;\n\n public readonly resolverPathSeparator: string;\n public readonly normalizeToSlash: IPathNormalizationFunction;\n public readonly normalizeToPlatform: IPathNormalizationFunction;\n\n public constructor(options: IWorkspaceLayoutCacheOptions) {\n const { workspaceRoot, cacheData, resolverPathSeparator = directorySeparator } = options;\n\n if (resolverPathSeparator !== '/' && resolverPathSeparator !== '\\\\') {\n throw new Error(`Unsupported directory separator: ${resolverPathSeparator}`);\n }\n\n const resolveContexts: IResolveContext[] = [];\n const contextLookup: LookupByPath<IResolveContext> = new LookupByPath(undefined, resolverPathSeparator);\n\n this.contextLookup = contextLookup;\n this.contextForPackage = new WeakMap<object, IResolveContext>();\n\n const normalizeToSlash: IPathNormalizationFunction =\n resolverPathSeparator === '\\\\' ? backslashToSlash : undefined;\n const normalizeToPlatform: IPathNormalizationFunction =\n resolverPathSeparator === '\\\\' ? slashToBackslash : undefined;\n\n this.resolverPathSeparator = resolverPathSeparator;\n this.normalizeToSlash = normalizeToSlash;\n this.normalizeToPlatform = normalizeToPlatform;\n\n // Internal class due to coupling to `resolveContexts`\n class ResolveContext implements IResolveContext {\n private readonly _serialized: ISerializedResolveContext;\n private _descriptionFileRoot: string | undefined;\n private _dependencies: LookupByPath<IResolveContext> | undefined;\n\n public constructor(serialized: ISerializedResolveContext) {\n this._serialized = serialized;\n this._descriptionFileRoot = undefined;\n this._dependencies = undefined;\n }\n\n public get descriptionFileRoot(): string {\n if (!this._descriptionFileRoot) {\n this._descriptionFileRoot = `${workspaceRoot}${resolverPathSeparator}${\n normalizeToPlatform?.(this._serialized.root) ?? this._serialized.root\n }`;\n }\n return this._descriptionFileRoot;\n }\n\n public findDependency(request: string): IPrefixMatch<IResolveContext> | undefined {\n if (!this._dependencies) {\n // Lazy initialize this object since most packages won't be requested.\n const dependencies: LookupByPath<IResolveContext> = new LookupByPath(undefined, '/');\n // Handle the self-reference scenario\n dependencies.setItem(this._serialized.name, this);\n for (const [key, ordinal] of Object.entries(this._serialized.deps)) {\n // This calls into the array of instances that is owned by WorkpaceLayoutCache\n dependencies.setItem(key, resolveContexts[ordinal]);\n }\n this._dependencies = dependencies;\n }\n\n return this._dependencies.findLongestPrefixMatch(request);\n }\n }\n\n for (const serialized of cacheData.contexts) {\n const resolveContext: IResolveContext = new ResolveContext(serialized);\n resolveContexts.push(resolveContext);\n\n const descriptionFileRoot: string = resolveContext.descriptionFileRoot;\n contextLookup.setItem(descriptionFileRoot, resolveContext);\n\n // Handle nested package.json files. These may modify some properties, but the dependency resolution\n // will match the original package root. Typically these are used to set the `type` field to `module`.\n if (serialized.dirInfoFiles) {\n for (const file of serialized.dirInfoFiles) {\n contextLookup.setItemFromSegments(\n concat<string>(\n // Root is normalized to platform slashes\n LookupByPath.iteratePathSegments(descriptionFileRoot, resolverPathSeparator),\n // Subpaths are platform-agnostic\n LookupByPath.iteratePathSegments(file, '/')\n ),\n resolveContext\n );\n }\n }\n }\n }\n}\n\nfunction* concat<T>(a: Iterable<T>, b: Iterable<T>): IterableIterator<T> {\n yield* a;\n yield* b;\n}\n"]}
1
+ {"version":3,"file":"WorkspaceLayoutCache.js","sourceRoot":"","sources":["../src/WorkspaceLayoutCache.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 { sep as directorySeparator } from 'node:path';\n\nimport { LookupByPath, type IPrefixMatch } from '@rushstack/lookup-by-path';\n\n/**\n * Information about a local or installed npm package.\n * @beta\n */\nexport interface ISerializedResolveContext {\n /**\n * The path to the root folder of this context.\n * This path is normalized to use `/` as the separator and should not end with a trailing `/`.\n */\n root: string;\n /**\n * The name of this package. Used to inject a self-reference into the dependency map.\n */\n name: string;\n /**\n * Map of declared dependencies (if any) to the ordinal of the corresponding context.\n */\n deps?: Record<string, number>;\n /**\n * Set of relative paths to nested `package.json` files within this context.\n * These paths are normalized to use `/` as the separator and should not begin with a leading `./`.\n */\n dirInfoFiles?: string[];\n}\n\n/**\n * The serialized form of the cache file. This file is expected to be generated by a separate tool from\n * information known to the package manager. Namely, the dependency relationships between packages, and\n * all the `package.json` files in the workspace (installed or local).\n * @beta\n */\nexport interface IResolverCacheFile {\n /**\n * The base path. All paths in context entries are prefixed by this path.\n */\n basePath: string;\n /**\n * The ordered list of all contexts in the cache\n */\n contexts: ISerializedResolveContext[];\n}\n\n/**\n * A context for resolving dependencies in a workspace.\n * @beta\n */\nexport interface IResolveContext {\n /**\n * The absolute path to the root folder of this context\n */\n descriptionFileRoot: string;\n /**\n * Find the context that corresponds to a module specifier, when requested in the current context.\n * @param request - The module specifier to resolve\n */\n findDependency(request: string): IPrefixMatch<IResolveContext> | undefined;\n}\n\n/**\n * Options for creating a `WorkspaceLayoutCache`.\n * @beta\n */\nexport interface IWorkspaceLayoutCacheOptions {\n /**\n * The parsed cache data. File reading is left as an exercise for the caller.\n */\n cacheData: IResolverCacheFile;\n /**\n * The directory separator used in the `path` field of the resolver inputs.\n * Will usually be `path.sep`.\n */\n resolverPathSeparator?: '/' | '\\\\';\n}\n\n/**\n * A function that normalizes a path to a platform-specific format (if needed).\n * Will be undefined if the platform uses `/` as the path separator.\n *\n * @beta\n */\nexport type IPathNormalizationFunction = ((input: string) => string) | undefined;\n\nfunction backslashToSlash(path: string): string {\n return path.replace(/\\\\/g, '/');\n}\n\nfunction slashToBackslash(path: string): string {\n return path.replace(/\\//g, '\\\\');\n}\n\n/**\n * A cache of workspace layout information.\n * @beta\n */\nexport class WorkspaceLayoutCache {\n /**\n * A lookup of context roots to their corresponding context objects\n */\n public readonly contextLookup: LookupByPath<IResolveContext>;\n /**\n * A weak map of package JSON contents to their corresponding context objects\n */\n public readonly contextForPackage: WeakMap<object, IPrefixMatch<IResolveContext>>;\n\n public readonly resolverPathSeparator: string;\n public readonly normalizeToSlash: IPathNormalizationFunction;\n public readonly normalizeToPlatform: IPathNormalizationFunction;\n\n public constructor(options: IWorkspaceLayoutCacheOptions) {\n const { cacheData, resolverPathSeparator = directorySeparator } = options;\n\n if (resolverPathSeparator !== '/' && resolverPathSeparator !== '\\\\') {\n throw new Error(`Unsupported directory separator: ${resolverPathSeparator}`);\n }\n\n const { basePath } = cacheData;\n const resolveContexts: ResolveContext[] = [];\n const contextLookup: LookupByPath<IResolveContext> = new LookupByPath(undefined, resolverPathSeparator);\n\n this.contextLookup = contextLookup;\n this.contextForPackage = new WeakMap<object, IPrefixMatch<IResolveContext>>();\n\n const normalizeToSlash: IPathNormalizationFunction =\n resolverPathSeparator === '\\\\' ? backslashToSlash : undefined;\n const normalizeToPlatform: IPathNormalizationFunction =\n resolverPathSeparator === '\\\\' ? slashToBackslash : undefined;\n\n this.resolverPathSeparator = resolverPathSeparator;\n this.normalizeToSlash = normalizeToSlash;\n this.normalizeToPlatform = normalizeToPlatform;\n\n // Internal class due to coupling to `resolveContexts`\n class ResolveContext implements IResolveContext {\n private readonly _serialized: ISerializedResolveContext;\n private _descriptionFileRoot: string | undefined;\n private _dependencies: LookupByPath<IResolveContext> | undefined;\n\n public constructor(serialized: ISerializedResolveContext) {\n this._serialized = serialized;\n this._descriptionFileRoot = undefined;\n this._dependencies = undefined;\n }\n\n public get descriptionFileRoot(): string {\n if (!this._descriptionFileRoot) {\n this._descriptionFileRoot = `${basePath}${\n normalizeToPlatform?.(this._serialized.root) ?? this._serialized.root\n }`;\n }\n return this._descriptionFileRoot;\n }\n\n public findDependency(request: string): IPrefixMatch<IResolveContext> | undefined {\n if (!this._dependencies) {\n // Lazy initialize this object since most packages won't be requested.\n const dependencies: LookupByPath<IResolveContext> = new LookupByPath(undefined, '/');\n\n const { name, deps } = this._serialized;\n\n // Handle the self-reference scenario\n dependencies.setItem(name, this);\n if (deps) {\n for (const [key, ordinal] of Object.entries(deps)) {\n // This calls into the array of instances that is owned by WorkpaceLayoutCache\n dependencies.setItem(key, resolveContexts[ordinal]);\n }\n }\n this._dependencies = dependencies;\n }\n\n return this._dependencies.findLongestPrefixMatch(request);\n }\n }\n\n for (const serialized of cacheData.contexts) {\n const resolveContext: ResolveContext = new ResolveContext(serialized);\n resolveContexts.push(resolveContext);\n\n const descriptionFileRoot: string = resolveContext.descriptionFileRoot;\n contextLookup.setItem(descriptionFileRoot, resolveContext);\n\n // Handle nested package.json files. These may modify some properties, but the dependency resolution\n // will match the original package root. Typically these are used to set the `type` field to `module`.\n if (serialized.dirInfoFiles) {\n for (const file of serialized.dirInfoFiles) {\n contextLookup.setItemFromSegments(\n concat<string>(\n // Root is normalized to platform slashes\n LookupByPath.iteratePathSegments(descriptionFileRoot, resolverPathSeparator),\n // Subpaths are platform-agnostic\n LookupByPath.iteratePathSegments(file, '/')\n ),\n resolveContext\n );\n }\n }\n }\n }\n}\n\nfunction* concat<T>(a: Iterable<T>, b: Iterable<T>): IterableIterator<T> {\n yield* a;\n yield* b;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rushstack/webpack-workspace-resolve-plugin",
3
- "version": "0.1.2",
3
+ "version": "0.3.0",
4
4
  "description": "This plugin leverages workspace-level metadata to greatly accelerate module resolution.",
5
5
  "main": "lib/index.js",
6
6
  "typings": "dist/webpack-workspace-resolve-plugin.d.ts",
@@ -18,7 +18,7 @@
18
18
  "@types/node": "*"
19
19
  },
20
20
  "dependencies": {
21
- "@rushstack/lookup-by-path": "0.1.2"
21
+ "@rushstack/lookup-by-path": "0.2.0"
22
22
  },
23
23
  "devDependencies": {
24
24
  "memfs": "3.4.3",