@lage-run/hasher 1.9.2 → 1.9.3
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/lib/PackageTree.d.ts +2 -2
- package/lib/PackageTree.js.map +1 -1
- package/lib/TargetHasher.d.ts +14 -21
- package/lib/TargetHasher.js +14 -32
- package/lib/TargetHasher.js.map +1 -1
- package/lib/resolveExternalDependencies.d.ts +14 -11
- package/lib/resolveExternalDependencies.js +25 -28
- package/lib/resolveExternalDependencies.js.map +1 -1
- package/package.json +13 -11
- package/CHANGELOG.json +0 -735
- package/CHANGELOG.md +0 -323
- package/jest.config.js +0 -1
- package/lib/__fixtures__/config/backfill.config.d.ts +0 -1
- package/lib/__fixtures__/config/packages/package-1/backfill.config.d.ts +0 -0
- package/lib/__fixtures__/monorepo-nested/packages/package-a/build/another/file.d.ts +0 -1
- package/lib/__fixtures__/monorepo-nested/packages/package-a/build/another/file.js +0 -2
- package/lib/__fixtures__/monorepo-nested/packages/package-a/build/another/file.js.map +0 -1
- package/lib/__fixtures__/monorepo-with-global-files/some-global.config.d.ts +0 -1
- package/lib/__fixtures__/monorepo-with-global-files/some-global2.config.d.ts +0 -1
- package/lib/__fixtures__/monorepo-with-global-files-different-tasks/some-global.config.d.ts +0 -1
- package/lib/__tests__/PackageTree.test.d.ts +0 -1
- package/lib/__tests__/PackageTree.test.js +0 -76
- package/lib/__tests__/PackageTree.test.js.map +0 -1
- package/lib/__tests__/TargetHasher.test.d.ts +0 -1
- package/lib/__tests__/TargetHasher.test.js +0 -213
- package/lib/__tests__/TargetHasher.test.js.map +0 -1
- package/lib/__tests__/getPackageDeps.test.d.ts +0 -1
- package/lib/__tests__/getPackageDeps.test.js +0 -310
- package/lib/__tests__/getPackageDeps.test.js.map +0 -1
- package/lib/__tests__/resolveDependenciesHelper.d.ts +0 -3
- package/lib/__tests__/resolveDependenciesHelper.js +0 -66
- package/lib/__tests__/resolveDependenciesHelper.js.map +0 -1
- package/lib/__tests__/resolveExternalDependencies.test.d.ts +0 -1
- package/lib/__tests__/resolveExternalDependencies.test.js +0 -154
- package/lib/__tests__/resolveExternalDependencies.test.js.map +0 -1
- package/lib/__tests__/resolveInternalDependencies.test.d.ts +0 -1
- package/lib/__tests__/resolveInternalDependencies.test.js +0 -131
- package/lib/__tests__/resolveInternalDependencies.test.js.map +0 -1
- package/lib/nameAtVersion.d.ts +0 -1
- package/lib/nameAtVersion.js +0 -13
- package/lib/nameAtVersion.js.map +0 -1
- package/lib/resolveInternalDependencies.d.ts +0 -6
- package/lib/resolveInternalDependencies.js +0 -26
- package/lib/resolveInternalDependencies.js.map +0 -1
- package/tsconfig.json +0 -7
package/lib/PackageTree.d.ts
CHANGED
|
@@ -13,8 +13,8 @@ export declare class PackageTree {
|
|
|
13
13
|
#private;
|
|
14
14
|
private options;
|
|
15
15
|
constructor(options: PackageTreeOptions);
|
|
16
|
-
reset
|
|
16
|
+
private reset;
|
|
17
17
|
initialize(): Promise<void>;
|
|
18
|
-
addToPackageTree
|
|
18
|
+
private addToPackageTree;
|
|
19
19
|
getPackageFiles(packageName: string, patterns: string[]): string[];
|
|
20
20
|
}
|
package/lib/PackageTree.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/PackageTree.ts"],"sourcesContent":["import { type PackageInfos } from \"workspace-tools\";\n\nimport execa from \"execa\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport micromatch from \"micromatch\";\n\nexport interface PackageTreeOptions {\n root: string;\n packageInfos: PackageInfos;\n includeUntracked: boolean;\n}\n\ninterface PathNode {\n children: {\n [key: string]: PathNode;\n };\n\n isPackage: boolean;\n}\n\n/**\n * Package Tree keeps a data structure to quickly find all files in a package.\n *\n * TODO: add a watcher to make sure the tree is up to date during a \"watched\" run.\n */\nexport class PackageTree {\n #tree: PathNode = { children: {}, isPackage: true };\n #packageFiles: Record<string, string[]> = {};\n #memoizedPackageFiles: Record<string, string[]> = {};\n\n constructor(private options: PackageTreeOptions) {}\n\n reset(): void {\n // reset the internal state\n this.#tree = { children: {}, isPackage: true };\n this.#packageFiles = {};\n this.#memoizedPackageFiles = {};\n }\n\n async initialize(): Promise<void> {\n const { root, includeUntracked, packageInfos } = this.options;\n\n this.reset();\n\n // Generate path tree of all packages in workspace (scale: ~2000 * ~3)\n for (const info of Object.values(packageInfos)) {\n const packagePath = path.dirname(info.packageJsonPath);\n const pathParts = path.relative(root, packagePath).split(/[\\\\/]/);\n\n let currentNode = this.#tree;\n\n for (const part of pathParts) {\n // initialize the children if not already done\n currentNode.children[part] = currentNode.children[part] || { children: {}, isPackage: false };\n currentNode = currentNode.children[part];\n }\n\n currentNode.isPackage = true;\n }\n\n // Get all files in the workspace (scale: ~2000) according to git\n const lsFilesResults = await execa(\"git\", [\"ls-files\", \"-z\"], { cwd: root });\n\n if (lsFilesResults.exitCode === 0) {\n const files = lsFilesResults.stdout.split(\"\\0\").filter((f) => Boolean(f) && fs.existsSync(path.join(root, f)));\n this.addToPackageTree(files);\n }\n\n if (includeUntracked) {\n // Also get all untracked files in the workspace according to git\n const lsOtherResults = await execa(\"git\", [\"ls-files\", \"-o\", \"-z\", \"--exclude-standard\"], { cwd: root });\n if (lsOtherResults.exitCode === 0) {\n const files = lsOtherResults.stdout.split(\"\\0\").filter(Boolean);\n this.addToPackageTree(files);\n }\n }\n }\n\n addToPackageTree(filePaths: string[]): void {\n // key: path/to/package (packageRoot), value: array of a tuple of [file, hash]\n const packageFiles = this.#packageFiles;\n\n for (const entry of filePaths) {\n const pathParts = entry.split(/[\\\\/]/);\n\n let node = this.#tree;\n\n const pathPartsBuffer: string[] = [];\n let packagePathParts: string[] = [];\n\n for (const part of pathParts) {\n if (node.children[part]) {\n node = node.children[part] as PathNode;\n pathPartsBuffer.push(part);\n\n if (node.isPackage) {\n packagePathParts = [...pathPartsBuffer];\n }\n } else {\n break;\n }\n }\n\n const packageRoot = packagePathParts.join(\"/\");\n packageFiles[packageRoot] = packageFiles[packageRoot] || [];\n packageFiles[packageRoot].push(entry);\n }\n }\n\n getPackageFiles(packageName: string, patterns: string[]): string[] {\n const { root, packageInfos } = this.options;\n const packagePath = path.relative(root, path.dirname(packageInfos[packageName].packageJsonPath)).replace(/\\\\/g, \"/\");\n\n const packageFiles = this.#packageFiles[packagePath];\n\n if (!packageFiles) {\n return [];\n }\n\n const key = `${packageName}\\0${patterns.join(\"\\0\")}`;\n\n if (!this.#memoizedPackageFiles[key]) {\n const packagePatterns = patterns.map((pattern) => {\n if (pattern.startsWith(\"!\")) {\n return `!${path.join(packagePath, pattern.slice(1)).replace(/\\\\/g, \"/\")}`;\n }\n\n return path.join(packagePath, pattern).replace(/\\\\/g, \"/\");\n });\n this.#memoizedPackageFiles[key] = micromatch(packageFiles, packagePatterns, { dot: true });\n }\n\n return this.#memoizedPackageFiles[key];\n }\n}\n"],"names":["PackageTree","reset","children","isPackage","initialize","root","includeUntracked","packageInfos","options","info","Object","values","packagePath","path","dirname","packageJsonPath","pathParts","relative","split","currentNode","part","lsFilesResults","execa","cwd","exitCode","files","stdout","filter","f","Boolean","fs","existsSync","join","addToPackageTree","lsOtherResults","filePaths","packageFiles","entry","node","pathPartsBuffer","packagePathParts","push","packageRoot","getPackageFiles","packageName","patterns","replace","key","packagePatterns","map","pattern","startsWith","slice","micromatch","dot"],"mappings":";;;;+BA0BaA;;;eAAAA;;;8DAxBK;6DACD;2DACF;mEACQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAsBrB,qCACA,6CACA;AAHK,MAAMA;
|
|
1
|
+
{"version":3,"sources":["../src/PackageTree.ts"],"sourcesContent":["import { type PackageInfos } from \"workspace-tools\";\n\nimport execa from \"execa\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport micromatch from \"micromatch\";\n\nexport interface PackageTreeOptions {\n root: string;\n packageInfos: PackageInfos;\n includeUntracked: boolean;\n}\n\ninterface PathNode {\n children: {\n [key: string]: PathNode;\n };\n\n isPackage: boolean;\n}\n\n/**\n * Package Tree keeps a data structure to quickly find all files in a package.\n *\n * TODO: add a watcher to make sure the tree is up to date during a \"watched\" run.\n */\nexport class PackageTree {\n #tree: PathNode = { children: {}, isPackage: true };\n #packageFiles: Record<string, string[]> = {};\n #memoizedPackageFiles: Record<string, string[]> = {};\n\n constructor(private options: PackageTreeOptions) {}\n\n private reset(): void {\n // reset the internal state\n this.#tree = { children: {}, isPackage: true };\n this.#packageFiles = {};\n this.#memoizedPackageFiles = {};\n }\n\n public async initialize(): Promise<void> {\n const { root, includeUntracked, packageInfos } = this.options;\n\n this.reset();\n\n // Generate path tree of all packages in workspace (scale: ~2000 * ~3)\n for (const info of Object.values(packageInfos)) {\n const packagePath = path.dirname(info.packageJsonPath);\n const pathParts = path.relative(root, packagePath).split(/[\\\\/]/);\n\n let currentNode = this.#tree;\n\n for (const part of pathParts) {\n // initialize the children if not already done\n currentNode.children[part] = currentNode.children[part] || { children: {}, isPackage: false };\n currentNode = currentNode.children[part];\n }\n\n currentNode.isPackage = true;\n }\n\n // Get all files in the workspace (scale: ~2000) according to git\n const lsFilesResults = await execa(\"git\", [\"ls-files\", \"-z\"], { cwd: root });\n\n if (lsFilesResults.exitCode === 0) {\n const files = lsFilesResults.stdout.split(\"\\0\").filter((f) => Boolean(f) && fs.existsSync(path.join(root, f)));\n this.addToPackageTree(files);\n }\n\n if (includeUntracked) {\n // Also get all untracked files in the workspace according to git\n const lsOtherResults = await execa(\"git\", [\"ls-files\", \"-o\", \"-z\", \"--exclude-standard\"], { cwd: root });\n if (lsOtherResults.exitCode === 0) {\n const files = lsOtherResults.stdout.split(\"\\0\").filter(Boolean);\n this.addToPackageTree(files);\n }\n }\n }\n\n private addToPackageTree(filePaths: string[]): void {\n // key: path/to/package (packageRoot), value: array of a tuple of [file, hash]\n const packageFiles = this.#packageFiles;\n\n for (const entry of filePaths) {\n const pathParts = entry.split(/[\\\\/]/);\n\n let node = this.#tree;\n\n const pathPartsBuffer: string[] = [];\n let packagePathParts: string[] = [];\n\n for (const part of pathParts) {\n if (node.children[part]) {\n node = node.children[part] as PathNode;\n pathPartsBuffer.push(part);\n\n if (node.isPackage) {\n packagePathParts = [...pathPartsBuffer];\n }\n } else {\n break;\n }\n }\n\n const packageRoot = packagePathParts.join(\"/\");\n packageFiles[packageRoot] = packageFiles[packageRoot] || [];\n packageFiles[packageRoot].push(entry);\n }\n }\n\n public getPackageFiles(packageName: string, patterns: string[]): string[] {\n const { root, packageInfos } = this.options;\n const packagePath = path.relative(root, path.dirname(packageInfos[packageName].packageJsonPath)).replace(/\\\\/g, \"/\");\n\n const packageFiles = this.#packageFiles[packagePath];\n\n if (!packageFiles) {\n return [];\n }\n\n const key = `${packageName}\\0${patterns.join(\"\\0\")}`;\n\n if (!this.#memoizedPackageFiles[key]) {\n const packagePatterns = patterns.map((pattern) => {\n if (pattern.startsWith(\"!\")) {\n return `!${path.join(packagePath, pattern.slice(1)).replace(/\\\\/g, \"/\")}`;\n }\n\n return path.join(packagePath, pattern).replace(/\\\\/g, \"/\");\n });\n this.#memoizedPackageFiles[key] = micromatch(packageFiles, packagePatterns, { dot: true });\n }\n\n return this.#memoizedPackageFiles[key];\n }\n}\n"],"names":["PackageTree","reset","children","isPackage","initialize","root","includeUntracked","packageInfos","options","info","Object","values","packagePath","path","dirname","packageJsonPath","pathParts","relative","split","currentNode","part","lsFilesResults","execa","cwd","exitCode","files","stdout","filter","f","Boolean","fs","existsSync","join","addToPackageTree","lsOtherResults","filePaths","packageFiles","entry","node","pathPartsBuffer","packagePathParts","push","packageRoot","getPackageFiles","packageName","patterns","replace","key","packagePatterns","map","pattern","startsWith","slice","micromatch","dot"],"mappings":"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"}
|
package/lib/TargetHasher.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { Target } from "@lage-run/target-graph";
|
|
2
|
-
import { type
|
|
3
|
-
import type { DependencyMap } from "workspace-tools/lib/graph/createDependencyMap.js";
|
|
2
|
+
import { type DependencyMap } from "workspace-tools";
|
|
4
3
|
import { FileHasher } from "./FileHasher.js";
|
|
5
4
|
import type { Logger } from "@lage-run/logger";
|
|
6
5
|
import { PackageTree } from "./PackageTree.js";
|
|
@@ -25,32 +24,26 @@ export interface TargetManifest {
|
|
|
25
24
|
}
|
|
26
25
|
/**
|
|
27
26
|
* TargetHasher is a class that can be used to generate a hash of a target.
|
|
28
|
-
*
|
|
29
|
-
* Currently, it encapsulates the use of `backfill-hasher` to generate a hash.
|
|
27
|
+
* It uses `glob-hasher` internally.
|
|
30
28
|
*/
|
|
31
29
|
export declare class TargetHasher {
|
|
32
30
|
private options;
|
|
33
|
-
targetHashesLog
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
targetHashesDirectory: string;
|
|
38
|
-
logger: Logger | undefined;
|
|
39
|
-
fileHasher: FileHasher;
|
|
31
|
+
private targetHashesLog;
|
|
32
|
+
private targetHashesDirectory;
|
|
33
|
+
private logger;
|
|
34
|
+
private fileHasher;
|
|
40
35
|
packageTree: PackageTree | undefined;
|
|
41
|
-
initializedPromise
|
|
42
|
-
packageInfos
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
targetHashes: Record<string, string>;
|
|
36
|
+
private initializedPromise;
|
|
37
|
+
private packageInfos;
|
|
38
|
+
private globalInputsHash;
|
|
39
|
+
private lockInfo;
|
|
40
|
+
private targetHashes;
|
|
47
41
|
dependencyMap: DependencyMap;
|
|
48
|
-
getPackageInfos(workspacePackages: WorkspaceInfos): PackageInfos;
|
|
49
42
|
constructor(options: TargetHasherOptions);
|
|
50
|
-
ensureInitialized
|
|
43
|
+
private ensureInitialized;
|
|
51
44
|
initialize(): Promise<void>;
|
|
52
45
|
hash(target: Target): Promise<string>;
|
|
53
|
-
writeTargetHashesManifest
|
|
54
|
-
getEnvironmentGlobHashes
|
|
46
|
+
private writeTargetHashesManifest;
|
|
47
|
+
private getEnvironmentGlobHashes;
|
|
55
48
|
cleanup(): Promise<void>;
|
|
56
49
|
}
|
package/lib/TargetHasher.js
CHANGED
|
@@ -13,9 +13,7 @@ const _globby = require("@lage-run/globby");
|
|
|
13
13
|
const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
|
|
14
14
|
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
|
|
15
15
|
const _workspacetools = require("workspace-tools");
|
|
16
|
-
const _infoFromPackageJson = require("workspace-tools/lib/infoFromPackageJson.js");
|
|
17
16
|
const _hashStrings = require("./hashStrings.js");
|
|
18
|
-
const _resolveInternalDependencies = require("./resolveInternalDependencies.js");
|
|
19
17
|
const _resolveExternalDependencies = require("./resolveExternalDependencies.js");
|
|
20
18
|
const _FileHasher = require("./FileHasher.js");
|
|
21
19
|
const _PackageTree = require("./PackageTree.js");
|
|
@@ -39,29 +37,6 @@ function _interop_require_default(obj) {
|
|
|
39
37
|
};
|
|
40
38
|
}
|
|
41
39
|
class TargetHasher {
|
|
42
|
-
getPackageInfos(workspacePackages) {
|
|
43
|
-
const { root } = this.options;
|
|
44
|
-
const packageInfos = {};
|
|
45
|
-
if (workspacePackages.length) {
|
|
46
|
-
for (const pkg of workspacePackages){
|
|
47
|
-
packageInfos[pkg.name] = pkg.packageJson;
|
|
48
|
-
}
|
|
49
|
-
} else {
|
|
50
|
-
const packageJsonPath = _path.default.join(root, "package.json");
|
|
51
|
-
if (_fs.default.existsSync(packageJsonPath)) {
|
|
52
|
-
try {
|
|
53
|
-
const packageJson = JSON.parse(_fs.default.readFileSync(packageJsonPath, "utf-8"));
|
|
54
|
-
const rootInfo = (0, _infoFromPackageJson.infoFromPackageJson)(packageJson, packageJsonPath);
|
|
55
|
-
if (rootInfo) {
|
|
56
|
-
packageInfos[rootInfo.name] = rootInfo;
|
|
57
|
-
}
|
|
58
|
-
} catch (e) {
|
|
59
|
-
throw new Error(`Invalid package.json file detected ${packageJsonPath}: ${e?.message || e}`);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return packageInfos;
|
|
64
|
-
}
|
|
65
40
|
ensureInitialized() {
|
|
66
41
|
if (!this.initializedPromise) {
|
|
67
42
|
throw new Error("TargetHasher is not initialized");
|
|
@@ -77,8 +52,17 @@ class TargetHasher {
|
|
|
77
52
|
this.fileHasher.readManifest().then(()=>(0, _globby.globAsync)(environmentGlob, {
|
|
78
53
|
cwd: root
|
|
79
54
|
})).then((files)=>this.fileHasher.hash(files)).then((hash)=>this.globalInputsHash = hash),
|
|
80
|
-
(0, _workspacetools.
|
|
81
|
-
|
|
55
|
+
(0, _workspacetools.getPackageInfosAsync)(root).then((packageInfos)=>{
|
|
56
|
+
if (Object.keys(packageInfos).length) {
|
|
57
|
+
this.packageInfos = packageInfos;
|
|
58
|
+
} else {
|
|
59
|
+
const rootInfo = (0, _workspacetools.getPackageInfo)(root);
|
|
60
|
+
if (rootInfo) {
|
|
61
|
+
this.packageInfos = {
|
|
62
|
+
[rootInfo.name]: rootInfo
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
82
66
|
this.dependencyMap = (0, _workspacetools.createDependencyMap)(this.packageInfos, {
|
|
83
67
|
withDevDependencies: true,
|
|
84
68
|
withPeerDependencies: false
|
|
@@ -118,14 +102,13 @@ class TargetHasher {
|
|
|
118
102
|
// 1. add hash of target's inputs
|
|
119
103
|
// 2. add hash of target packages' internal and external deps
|
|
120
104
|
const { dependencies, devDependencies } = this.packageInfos[target.packageName];
|
|
121
|
-
const workspaceInfo = this.workspaceInfo;
|
|
122
105
|
const parsedLock = this.lockInfo;
|
|
123
106
|
const allDependencies = {
|
|
124
107
|
...dependencies,
|
|
125
108
|
...devDependencies
|
|
126
109
|
};
|
|
127
|
-
const internalDeps =
|
|
128
|
-
const externalDeps = (0, _resolveExternalDependencies.resolveExternalDependencies)(allDependencies,
|
|
110
|
+
const internalDeps = Object.keys(allDependencies).filter((dep)=>this.packageInfos[dep]);
|
|
111
|
+
const externalDeps = (0, _resolveExternalDependencies.resolveExternalDependencies)(allDependencies, this.packageInfos, parsedLock);
|
|
129
112
|
const resolvedDependencies = [
|
|
130
113
|
...internalDeps,
|
|
131
114
|
...externalDeps
|
|
@@ -176,7 +159,7 @@ class TargetHasher {
|
|
|
176
159
|
}
|
|
177
160
|
async cleanup() {
|
|
178
161
|
this.writeTargetHashesManifest();
|
|
179
|
-
|
|
162
|
+
this.fileHasher.writeManifest();
|
|
180
163
|
}
|
|
181
164
|
constructor(options){
|
|
182
165
|
_define_property(this, "options", void 0);
|
|
@@ -187,7 +170,6 @@ class TargetHasher {
|
|
|
187
170
|
_define_property(this, "packageTree", void 0);
|
|
188
171
|
_define_property(this, "initializedPromise", void 0);
|
|
189
172
|
_define_property(this, "packageInfos", void 0);
|
|
190
|
-
_define_property(this, "workspaceInfo", void 0);
|
|
191
173
|
_define_property(this, "globalInputsHash", void 0);
|
|
192
174
|
_define_property(this, "lockInfo", void 0);
|
|
193
175
|
_define_property(this, "targetHashes", void 0);
|
package/lib/TargetHasher.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/TargetHasher.ts"],"sourcesContent":["import type { Target } from \"@lage-run/target-graph\";\nimport { hash } from \"glob-hasher\";\nimport { globAsync } from \"@lage-run/globby\";\n\nimport fs from \"fs\";\nimport path from \"path\";\nimport {\n type ParsedLock,\n type WorkspaceInfos,\n type PackageInfos,\n getWorkspaceInfosAsync,\n parseLockFile,\n createDependencyMap,\n} from \"workspace-tools\";\nimport type { DependencyMap } from \"workspace-tools/lib/graph/createDependencyMap.js\";\nimport { infoFromPackageJson } from \"workspace-tools/lib/infoFromPackageJson.js\";\n\nimport { hashStrings } from \"./hashStrings.js\";\nimport { resolveInternalDependencies } from \"./resolveInternalDependencies.js\";\nimport { resolveExternalDependencies } from \"./resolveExternalDependencies.js\";\nimport { FileHasher } from \"./FileHasher.js\";\nimport type { Logger } from \"@lage-run/logger\";\nimport { PackageTree } from \"./PackageTree.js\";\nimport { getInputFiles } from \"./getInputFiles.js\";\n\nexport interface TargetHasherOptions {\n root: string;\n environmentGlob: string[];\n cacheKey?: string;\n cliArgs?: string[];\n logger?: Logger;\n}\n\nexport interface TargetManifest {\n id: string;\n hash: string;\n globalInputsHash: string;\n dependency: Record<string, string>;\n fileHasher: FileHasher;\n files: Record<\n string,\n {\n mtimeMs: number;\n size: number;\n hash: string;\n }\n >;\n}\n\n/**\n * TargetHasher is a class that can be used to generate a hash of a target.\n *\n * Currently, it encapsulates the use of `backfill-hasher` to generate a hash.\n */\nexport class TargetHasher {\n targetHashesLog: Record<string, { fileHashes: Record<string, string>; globalFileHashes: Record<string, string> }> = {};\n targetHashesDirectory: string;\n\n logger: Logger | undefined;\n fileHasher: FileHasher;\n packageTree: PackageTree | undefined;\n\n initializedPromise: Promise<unknown> | undefined;\n\n packageInfos: PackageInfos = {};\n workspaceInfo: WorkspaceInfos | undefined;\n globalInputsHash: Record<string, string> | undefined;\n lockInfo: ParsedLock | undefined;\n targetHashes: Record<string, string> = {};\n\n dependencyMap: DependencyMap = {\n dependencies: new Map(),\n dependents: new Map(),\n };\n\n getPackageInfos(workspacePackages: WorkspaceInfos): PackageInfos {\n const { root } = this.options;\n const packageInfos: PackageInfos = {};\n\n if (workspacePackages.length) {\n for (const pkg of workspacePackages) {\n packageInfos[pkg.name] = pkg.packageJson;\n }\n } else {\n const packageJsonPath = path.join(root, \"package.json\");\n if (fs.existsSync(packageJsonPath)) {\n try {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, \"utf-8\"));\n const rootInfo = infoFromPackageJson(packageJson, packageJsonPath);\n if (rootInfo) {\n packageInfos[rootInfo.name] = rootInfo;\n }\n } catch (e) {\n throw new Error(`Invalid package.json file detected ${packageJsonPath}: ${(e as Error)?.message || e}`);\n }\n }\n }\n\n return packageInfos;\n }\n\n constructor(private options: TargetHasherOptions) {\n const { root, logger } = options;\n this.logger = logger;\n\n this.fileHasher = new FileHasher({\n root,\n });\n\n this.targetHashesDirectory = path.join(root, \"node_modules\", \".cache\", \"lage\", \"hashes\");\n\n if (!fs.existsSync(this.targetHashesDirectory)) {\n fs.mkdirSync(this.targetHashesDirectory, { recursive: true });\n }\n }\n\n ensureInitialized(): void {\n if (!this.initializedPromise) {\n throw new Error(\"TargetHasher is not initialized\");\n }\n }\n\n async initialize(): Promise<void> {\n const { environmentGlob, root } = this.options;\n\n if (this.initializedPromise) {\n await this.initializedPromise;\n return;\n }\n\n this.initializedPromise = Promise.all([\n this.fileHasher\n .readManifest()\n .then(() => globAsync(environmentGlob, { cwd: root }))\n .then((files) => this.fileHasher.hash(files))\n .then((hash) => (this.globalInputsHash = hash)),\n\n getWorkspaceInfosAsync(root)\n .then((workspaceInfo) => (this.workspaceInfo = workspaceInfo))\n .then(() => {\n this.packageInfos = this.getPackageInfos(this.workspaceInfo!);\n\n this.dependencyMap = createDependencyMap(this.packageInfos, { withDevDependencies: true, withPeerDependencies: false });\n this.packageTree = new PackageTree({\n root,\n packageInfos: this.packageInfos,\n\n // TODO: (optimization) false if process.env.TF_BUILD || process.env.CI\n includeUntracked: true,\n });\n\n return this.packageTree.initialize();\n }),\n\n parseLockFile(root).then((lockInfo) => (this.lockInfo = lockInfo)),\n ]);\n\n await this.initializedPromise;\n\n if (this.logger !== undefined) {\n const globalInputsHash = hashStrings(Object.values(this.globalInputsHash ?? {}));\n this.logger.verbose(`Global inputs hash: ${globalInputsHash}`);\n }\n }\n\n async hash(target: Target): Promise<string> {\n this.ensureInitialized();\n\n const { root } = this.options;\n\n if (target.cwd === root && target.cache) {\n if (!target.inputs) {\n throw new Error(`No \"inputs\" specified for target \"${target.id}\"; cannot cache.`);\n }\n\n const files = await globAsync(target.inputs, { cwd: root });\n const fileFashes = hash(files, { cwd: root }) ?? {};\n\n const hashes = Object.values(fileFashes) as string[];\n\n return hashStrings(hashes);\n }\n\n // 1. add hash of target's inputs\n // 2. add hash of target packages' internal and external deps\n const { dependencies, devDependencies } = this.packageInfos[target.packageName!];\n\n const workspaceInfo = this.workspaceInfo!;\n const parsedLock = this.lockInfo!;\n\n const allDependencies: Record<string, string> = {\n ...dependencies,\n ...devDependencies,\n };\n\n const internalDeps = resolveInternalDependencies(allDependencies, workspaceInfo);\n const externalDeps = resolveExternalDependencies(allDependencies, workspaceInfo, parsedLock);\n const resolvedDependencies = [...internalDeps, ...externalDeps].sort();\n\n const files = getInputFiles(target, this.dependencyMap, this.packageTree!);\n const fileHashes = this.fileHasher.hash(files) ?? {}; // this list is sorted by file name\n\n // get target hashes\n const targetDepHashes = target.dependencies?.sort().map((targetDep) => this.targetHashes[targetDep]);\n\n const globalFileHashes = await this.getEnvironmentGlobHashes(root, target);\n\n const combinedHashes = [\n // Environmental hashes\n ...Object.values(globalFileHashes),\n `${target.id}|${JSON.stringify(this.options.cliArgs)}`,\n this.options.cacheKey || \"\",\n\n // File content hashes based on target.inputs\n ...Object.values(fileHashes),\n\n // Dependency hashes\n ...resolvedDependencies,\n ...targetDepHashes,\n ].filter(Boolean);\n\n const hashString = hashStrings(combinedHashes);\n\n this.targetHashes[target.id] = hashString;\n\n this.targetHashesLog[target.id] = { fileHashes, globalFileHashes };\n\n return hashString;\n }\n\n writeTargetHashesManifest(): void {\n for (const [id, { fileHashes, globalFileHashes }] of Object.entries(this.targetHashesLog)) {\n const targetHashesManifestPath = path.join(this.targetHashesDirectory, `${id}.json`);\n if (!fs.existsSync(path.dirname(targetHashesManifestPath))) {\n fs.mkdirSync(path.dirname(targetHashesManifestPath), { recursive: true });\n }\n fs.writeFileSync(targetHashesManifestPath, JSON.stringify({ fileHashes, globalFileHashes }), \"utf-8\");\n }\n }\n\n async getEnvironmentGlobHashes(root: string, target: Target): Promise<Record<string, string>> {\n const globalFileHashes = target.environmentGlob\n ? this.fileHasher.hash(await globAsync(target.environmentGlob ?? [], { cwd: root }))\n : (this.globalInputsHash ?? {});\n\n return globalFileHashes;\n }\n\n async cleanup(): Promise<void> {\n this.writeTargetHashesManifest();\n await this.fileHasher.writeManifest();\n }\n}\n"],"names":["TargetHasher","getPackageInfos","workspacePackages","root","options","packageInfos","length","pkg","name","packageJson","packageJsonPath","path","join","fs","existsSync","JSON","parse","readFileSync","rootInfo","infoFromPackageJson","e","Error","message","ensureInitialized","initializedPromise","initialize","environmentGlob","Promise","all","fileHasher","readManifest","then","globAsync","cwd","files","hash","globalInputsHash","getWorkspaceInfosAsync","workspaceInfo","dependencyMap","createDependencyMap","withDevDependencies","withPeerDependencies","packageTree","PackageTree","includeUntracked","parseLockFile","lockInfo","logger","undefined","hashStrings","Object","values","verbose","target","cache","inputs","id","fileFashes","hashes","dependencies","devDependencies","packageName","parsedLock","allDependencies","internalDeps","resolveInternalDependencies","externalDeps","resolveExternalDependencies","resolvedDependencies","sort","getInputFiles","fileHashes","targetDepHashes","map","targetDep","targetHashes","globalFileHashes","getEnvironmentGlobHashes","combinedHashes","stringify","cliArgs","cacheKey","filter","Boolean","hashString","targetHashesLog","writeTargetHashesManifest","entries","targetHashesManifestPath","targetHashesDirectory","dirname","mkdirSync","recursive","writeFileSync","cleanup","writeManifest","Map","dependents","FileHasher"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/TargetHasher.ts"],"sourcesContent":["import type { Target } from \"@lage-run/target-graph\";\nimport { hash } from \"glob-hasher\";\nimport { globAsync } from \"@lage-run/globby\";\n\nimport fs from \"fs\";\nimport path from \"path\";\nimport {\n type DependencyMap,\n type ParsedLock,\n type PackageInfos,\n parseLockFile,\n createDependencyMap,\n getPackageInfo,\n getPackageInfosAsync,\n} from \"workspace-tools\";\n\nimport { hashStrings } from \"./hashStrings.js\";\nimport { resolveExternalDependencies } from \"./resolveExternalDependencies.js\";\nimport { FileHasher } from \"./FileHasher.js\";\nimport type { Logger } from \"@lage-run/logger\";\nimport { PackageTree } from \"./PackageTree.js\";\nimport { getInputFiles } from \"./getInputFiles.js\";\n\nexport interface TargetHasherOptions {\n root: string;\n environmentGlob: string[];\n cacheKey?: string;\n cliArgs?: string[];\n logger?: Logger;\n}\n\nexport interface TargetManifest {\n id: string;\n hash: string;\n globalInputsHash: string;\n dependency: Record<string, string>;\n fileHasher: FileHasher;\n files: Record<\n string,\n {\n mtimeMs: number;\n size: number;\n hash: string;\n }\n >;\n}\n\n/**\n * TargetHasher is a class that can be used to generate a hash of a target.\n * It uses `glob-hasher` internally.\n */\nexport class TargetHasher {\n private targetHashesLog: Record<string, { fileHashes: Record<string, string>; globalFileHashes: Record<string, string> }> = {};\n private targetHashesDirectory: string;\n\n private logger: Logger | undefined;\n private fileHasher: FileHasher;\n public packageTree: PackageTree | undefined;\n\n private initializedPromise: Promise<unknown> | undefined;\n\n private packageInfos: PackageInfos = {};\n private globalInputsHash: Record<string, string> | undefined;\n private lockInfo: ParsedLock | undefined;\n private targetHashes: Record<string, string> = {};\n\n public dependencyMap: DependencyMap = {\n dependencies: new Map(),\n dependents: new Map(),\n };\n\n constructor(private options: TargetHasherOptions) {\n const { root, logger } = options;\n this.logger = logger;\n\n this.fileHasher = new FileHasher({\n root,\n });\n\n this.targetHashesDirectory = path.join(root, \"node_modules\", \".cache\", \"lage\", \"hashes\");\n\n if (!fs.existsSync(this.targetHashesDirectory)) {\n fs.mkdirSync(this.targetHashesDirectory, { recursive: true });\n }\n }\n\n private ensureInitialized(): void {\n if (!this.initializedPromise) {\n throw new Error(\"TargetHasher is not initialized\");\n }\n }\n\n public async initialize(): Promise<void> {\n const { environmentGlob, root } = this.options;\n\n if (this.initializedPromise) {\n await this.initializedPromise;\n return;\n }\n\n this.initializedPromise = Promise.all([\n this.fileHasher\n .readManifest()\n .then(() => globAsync(environmentGlob, { cwd: root }))\n .then((files) => this.fileHasher.hash(files))\n .then((hash) => (this.globalInputsHash = hash)),\n\n getPackageInfosAsync(root).then((packageInfos) => {\n if (Object.keys(packageInfos).length) {\n this.packageInfos = packageInfos;\n } else {\n const rootInfo = getPackageInfo(root);\n if (rootInfo) {\n this.packageInfos = { [rootInfo.name]: rootInfo };\n }\n }\n\n this.dependencyMap = createDependencyMap(this.packageInfos, { withDevDependencies: true, withPeerDependencies: false });\n this.packageTree = new PackageTree({\n root,\n packageInfos: this.packageInfos,\n\n // TODO: (optimization) false if process.env.TF_BUILD || process.env.CI\n includeUntracked: true,\n });\n\n return this.packageTree.initialize();\n }),\n\n parseLockFile(root).then((lockInfo) => (this.lockInfo = lockInfo)),\n ]);\n\n await this.initializedPromise;\n\n if (this.logger !== undefined) {\n const globalInputsHash = hashStrings(Object.values(this.globalInputsHash ?? {}));\n this.logger.verbose(`Global inputs hash: ${globalInputsHash}`);\n }\n }\n\n public async hash(target: Target): Promise<string> {\n this.ensureInitialized();\n\n const { root } = this.options;\n\n if (target.cwd === root && target.cache) {\n if (!target.inputs) {\n throw new Error(`No \"inputs\" specified for target \"${target.id}\"; cannot cache.`);\n }\n\n const files = await globAsync(target.inputs, { cwd: root });\n const fileFashes = hash(files, { cwd: root }) ?? {};\n\n const hashes = Object.values(fileFashes) as string[];\n\n return hashStrings(hashes);\n }\n\n // 1. add hash of target's inputs\n // 2. add hash of target packages' internal and external deps\n const { dependencies, devDependencies } = this.packageInfos[target.packageName!];\n\n const parsedLock = this.lockInfo!;\n\n const allDependencies: Record<string, string> = {\n ...dependencies,\n ...devDependencies,\n };\n\n const internalDeps = Object.keys(allDependencies).filter((dep) => this.packageInfos[dep]);\n const externalDeps = resolveExternalDependencies(allDependencies, this.packageInfos, parsedLock);\n const resolvedDependencies = [...internalDeps, ...externalDeps].sort();\n\n const files = getInputFiles(target, this.dependencyMap, this.packageTree!);\n const fileHashes = this.fileHasher.hash(files) ?? {}; // this list is sorted by file name\n\n // get target hashes\n const targetDepHashes = target.dependencies?.sort().map((targetDep) => this.targetHashes[targetDep]);\n\n const globalFileHashes = await this.getEnvironmentGlobHashes(root, target);\n\n const combinedHashes = [\n // Environmental hashes\n ...Object.values(globalFileHashes),\n `${target.id}|${JSON.stringify(this.options.cliArgs)}`,\n this.options.cacheKey || \"\",\n\n // File content hashes based on target.inputs\n ...Object.values(fileHashes),\n\n // Dependency hashes\n ...resolvedDependencies,\n ...targetDepHashes,\n ].filter(Boolean);\n\n const hashString = hashStrings(combinedHashes);\n\n this.targetHashes[target.id] = hashString;\n\n this.targetHashesLog[target.id] = { fileHashes, globalFileHashes };\n\n return hashString;\n }\n\n private writeTargetHashesManifest(): void {\n for (const [id, { fileHashes, globalFileHashes }] of Object.entries(this.targetHashesLog)) {\n const targetHashesManifestPath = path.join(this.targetHashesDirectory, `${id}.json`);\n if (!fs.existsSync(path.dirname(targetHashesManifestPath))) {\n fs.mkdirSync(path.dirname(targetHashesManifestPath), { recursive: true });\n }\n fs.writeFileSync(targetHashesManifestPath, JSON.stringify({ fileHashes, globalFileHashes }), \"utf-8\");\n }\n }\n\n private async getEnvironmentGlobHashes(root: string, target: Target): Promise<Record<string, string>> {\n const globalFileHashes = target.environmentGlob\n ? this.fileHasher.hash(await globAsync(target.environmentGlob ?? [], { cwd: root }))\n : (this.globalInputsHash ?? {});\n\n return globalFileHashes;\n }\n\n public async cleanup(): Promise<void> {\n this.writeTargetHashesManifest();\n this.fileHasher.writeManifest();\n }\n}\n"],"names":["TargetHasher","ensureInitialized","initializedPromise","Error","initialize","environmentGlob","root","options","Promise","all","fileHasher","readManifest","then","globAsync","cwd","files","hash","globalInputsHash","getPackageInfosAsync","packageInfos","Object","keys","length","rootInfo","getPackageInfo","name","dependencyMap","createDependencyMap","withDevDependencies","withPeerDependencies","packageTree","PackageTree","includeUntracked","parseLockFile","lockInfo","logger","undefined","hashStrings","values","verbose","target","cache","inputs","id","fileFashes","hashes","dependencies","devDependencies","packageName","parsedLock","allDependencies","internalDeps","filter","dep","externalDeps","resolveExternalDependencies","resolvedDependencies","sort","getInputFiles","fileHashes","targetDepHashes","map","targetDep","targetHashes","globalFileHashes","getEnvironmentGlobHashes","combinedHashes","JSON","stringify","cliArgs","cacheKey","Boolean","hashString","targetHashesLog","writeTargetHashesManifest","entries","targetHashesManifestPath","path","join","targetHashesDirectory","fs","existsSync","dirname","mkdirSync","recursive","writeFileSync","cleanup","writeManifest","Map","dependents","FileHasher"],"mappings":"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"}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import { type PackageInfos, type ParsedLock } from "workspace-tools";
|
|
2
|
+
type Dependencies = Record<string, string>;
|
|
3
|
+
export type DependencyQueue = [name: string, versionRange: string][];
|
|
4
|
+
export type DependencySpec = `${string}@${string}`;
|
|
5
|
+
/** Filter the `dependencies` object to only contain deps from outside the repo. */
|
|
6
|
+
export declare function _filterExternalDependencies(dependencies: Dependencies, packageInfos: PackageInfos): Dependencies;
|
|
7
|
+
export declare function _addToQueue(dependencies: Dependencies | undefined, done: Set<DependencySpec>, queue: DependencyQueue): void;
|
|
8
|
+
/**
|
|
9
|
+
* Resolve versions for external (outside repo) dependencies and their transitive dependencies
|
|
10
|
+
* using the lock file.
|
|
11
|
+
* @returns Array of strings in the format `name@version`
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveExternalDependencies(allDependencies: Dependencies, packageInfos: PackageInfos, lockInfo: ParsedLock): DependencySpec[];
|
|
14
|
+
export {};
|
|
@@ -9,51 +9,46 @@ function _export(target, all) {
|
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
11
|
_export(exports, {
|
|
12
|
-
get
|
|
13
|
-
return
|
|
12
|
+
get _addToQueue () {
|
|
13
|
+
return _addToQueue;
|
|
14
14
|
},
|
|
15
|
-
get
|
|
16
|
-
return
|
|
15
|
+
get _filterExternalDependencies () {
|
|
16
|
+
return _filterExternalDependencies;
|
|
17
17
|
},
|
|
18
18
|
get resolveExternalDependencies () {
|
|
19
19
|
return resolveExternalDependencies;
|
|
20
20
|
}
|
|
21
21
|
});
|
|
22
22
|
const _workspacetools = require("workspace-tools");
|
|
23
|
-
|
|
24
|
-
function filterExternalDependencies(dependencies, workspaces) {
|
|
25
|
-
const workspacePackageNames = workspaces.map((ws)=>ws.name);
|
|
23
|
+
function _filterExternalDependencies(dependencies, packageInfos) {
|
|
26
24
|
const externalDependencies = {};
|
|
27
|
-
|
|
28
|
-
if (
|
|
25
|
+
for (const [name, versionRange] of Object.entries(dependencies)){
|
|
26
|
+
if (!packageInfos[name]) {
|
|
29
27
|
externalDependencies[name] = versionRange;
|
|
30
28
|
}
|
|
31
|
-
}
|
|
29
|
+
}
|
|
32
30
|
return externalDependencies;
|
|
33
31
|
}
|
|
34
|
-
function isDone(done, key) {
|
|
35
|
-
return done.indexOf(key) >= 0;
|
|
36
|
-
}
|
|
37
32
|
function isInQueue(queue, key) {
|
|
38
|
-
return
|
|
33
|
+
return queue.some(([name, versionRange])=>`${name}@${versionRange}` === key);
|
|
39
34
|
}
|
|
40
|
-
function
|
|
35
|
+
function _addToQueue(dependencies, done, queue) {
|
|
41
36
|
if (dependencies) {
|
|
42
|
-
|
|
43
|
-
const versionRangeSignature =
|
|
44
|
-
if (!
|
|
37
|
+
for (const [name, versionRange] of Object.entries(dependencies)){
|
|
38
|
+
const versionRangeSignature = `${name}@${versionRange}`;
|
|
39
|
+
if (!done.has(versionRangeSignature) && !isInQueue(queue, versionRangeSignature)) {
|
|
45
40
|
queue.push([
|
|
46
41
|
name,
|
|
47
42
|
versionRange
|
|
48
43
|
]);
|
|
49
44
|
}
|
|
50
|
-
}
|
|
45
|
+
}
|
|
51
46
|
}
|
|
52
47
|
}
|
|
53
|
-
function resolveExternalDependencies(allDependencies,
|
|
54
|
-
const externalDependencies =
|
|
55
|
-
const done =
|
|
56
|
-
const doneRange =
|
|
48
|
+
function resolveExternalDependencies(allDependencies, packageInfos, lockInfo) {
|
|
49
|
+
const externalDependencies = _filterExternalDependencies(allDependencies, packageInfos);
|
|
50
|
+
const done = new Set();
|
|
51
|
+
const doneRange = new Set();
|
|
57
52
|
const queue = Object.entries(externalDependencies);
|
|
58
53
|
while(queue.length > 0){
|
|
59
54
|
const next = queue.shift();
|
|
@@ -61,15 +56,17 @@ function resolveExternalDependencies(allDependencies, workspaces, lockInfo) {
|
|
|
61
56
|
continue;
|
|
62
57
|
}
|
|
63
58
|
const [name, versionRange] = next;
|
|
64
|
-
doneRange.
|
|
59
|
+
doneRange.add(`${name}@${versionRange}`);
|
|
65
60
|
const lockFileResult = (0, _workspacetools.queryLockFile)(name, versionRange, lockInfo);
|
|
66
61
|
if (lockFileResult) {
|
|
67
62
|
const { version, dependencies } = lockFileResult;
|
|
68
|
-
|
|
69
|
-
done.
|
|
63
|
+
_addToQueue(dependencies, doneRange, queue);
|
|
64
|
+
done.add(`${name}@${version}`);
|
|
70
65
|
} else {
|
|
71
|
-
done.
|
|
66
|
+
done.add(`${name}@${versionRange}`);
|
|
72
67
|
}
|
|
73
68
|
}
|
|
74
|
-
return
|
|
69
|
+
return [
|
|
70
|
+
...done
|
|
71
|
+
];
|
|
75
72
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/resolveExternalDependencies.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["../src/resolveExternalDependencies.ts"],"sourcesContent":["import { queryLockFile, type PackageInfos, type ParsedLock } from \"workspace-tools\";\n\ntype Dependencies = Record<string, string>;\n\nexport type DependencyQueue = [name: string, versionRange: string][];\n\nexport type DependencySpec = `${string}@${string}`;\n\n/** Filter the `dependencies` object to only contain deps from outside the repo. */\nexport function _filterExternalDependencies(dependencies: Dependencies, packageInfos: PackageInfos): Dependencies {\n const externalDependencies: Dependencies = {};\n\n for (const [name, versionRange] of Object.entries(dependencies)) {\n if (!packageInfos[name]) {\n externalDependencies[name] = versionRange;\n }\n }\n\n return externalDependencies;\n}\n\nfunction isInQueue(queue: DependencyQueue, key: string): boolean {\n return queue.some(([name, versionRange]) => `${name}@${versionRange}` === key);\n}\n\nexport function _addToQueue(dependencies: Dependencies | undefined, done: Set<DependencySpec>, queue: DependencyQueue): void {\n if (dependencies) {\n for (const [name, versionRange] of Object.entries(dependencies)) {\n const versionRangeSignature = `${name}@${versionRange}` as const;\n\n if (!done.has(versionRangeSignature) && !isInQueue(queue, versionRangeSignature)) {\n queue.push([name, versionRange]);\n }\n }\n }\n}\n\n/**\n * Resolve versions for external (outside repo) dependencies and their transitive dependencies\n * using the lock file.\n * @returns Array of strings in the format `name@version`\n */\nexport function resolveExternalDependencies(\n allDependencies: Dependencies,\n packageInfos: PackageInfos,\n lockInfo: ParsedLock\n): DependencySpec[] {\n const externalDependencies = _filterExternalDependencies(allDependencies, packageInfos);\n\n const done = new Set<DependencySpec>();\n const doneRange = new Set<DependencySpec>();\n const queue: DependencyQueue = Object.entries(externalDependencies);\n\n while (queue.length > 0) {\n const next = queue.shift();\n\n if (!next) {\n continue;\n }\n\n const [name, versionRange] = next;\n doneRange.add(`${name}@${versionRange}`);\n\n const lockFileResult = queryLockFile(name, versionRange, lockInfo);\n\n if (lockFileResult) {\n const { version, dependencies } = lockFileResult;\n\n _addToQueue(dependencies, doneRange, queue);\n done.add(`${name}@${version}`);\n } else {\n done.add(`${name}@${versionRange}`);\n }\n }\n\n return [...done];\n}\n"],"names":["_addToQueue","_filterExternalDependencies","resolveExternalDependencies","dependencies","packageInfos","externalDependencies","name","versionRange","Object","entries","isInQueue","queue","key","some","done","versionRangeSignature","has","push","allDependencies","lockInfo","Set","doneRange","length","next","shift","add","lockFileResult","queryLockFile","version"],"mappings":";;;;;;;;;;;QAyBgBA;eAAAA;;QAhBAC;eAAAA;;QAiCAC;eAAAA;;;gCA1CkD;AAS3D,SAASD,4BAA4BE,YAA0B,EAAEC,YAA0B;IAChG,MAAMC,uBAAqC,CAAC;IAE5C,KAAK,MAAM,CAACC,MAAMC,aAAa,IAAIC,OAAOC,OAAO,CAACN,cAAe;QAC/D,IAAI,CAACC,YAAY,CAACE,KAAK,EAAE;YACvBD,oBAAoB,CAACC,KAAK,GAAGC;QAC/B;IACF;IAEA,OAAOF;AACT;AAEA,SAASK,UAAUC,KAAsB,EAAEC,GAAW;IACpD,OAAOD,MAAME,IAAI,CAAC,CAAC,CAACP,MAAMC,aAAa,GAAK,GAAGD,KAAK,CAAC,EAAEC,cAAc,KAAKK;AAC5E;AAEO,SAASZ,YAAYG,YAAsC,EAAEW,IAAyB,EAAEH,KAAsB;IACnH,IAAIR,cAAc;QAChB,KAAK,MAAM,CAACG,MAAMC,aAAa,IAAIC,OAAOC,OAAO,CAACN,cAAe;YAC/D,MAAMY,wBAAwB,GAAGT,KAAK,CAAC,EAAEC,cAAc;YAEvD,IAAI,CAACO,KAAKE,GAAG,CAACD,0BAA0B,CAACL,UAAUC,OAAOI,wBAAwB;gBAChFJ,MAAMM,IAAI,CAAC;oBAACX;oBAAMC;iBAAa;YACjC;QACF;IACF;AACF;AAOO,SAASL,4BACdgB,eAA6B,EAC7Bd,YAA0B,EAC1Be,QAAoB;IAEpB,MAAMd,uBAAuBJ,4BAA4BiB,iBAAiBd;IAE1E,MAAMU,OAAO,IAAIM;IACjB,MAAMC,YAAY,IAAID;IACtB,MAAMT,QAAyBH,OAAOC,OAAO,CAACJ;IAE9C,MAAOM,MAAMW,MAAM,GAAG,EAAG;QACvB,MAAMC,OAAOZ,MAAMa,KAAK;QAExB,IAAI,CAACD,MAAM;YACT;QACF;QAEA,MAAM,CAACjB,MAAMC,aAAa,GAAGgB;QAC7BF,UAAUI,GAAG,CAAC,GAAGnB,KAAK,CAAC,EAAEC,cAAc;QAEvC,MAAMmB,iBAAiBC,IAAAA,6BAAa,EAACrB,MAAMC,cAAcY;QAEzD,IAAIO,gBAAgB;YAClB,MAAM,EAAEE,OAAO,EAAEzB,YAAY,EAAE,GAAGuB;YAElC1B,YAAYG,cAAckB,WAAWV;YACrCG,KAAKW,GAAG,CAAC,GAAGnB,KAAK,CAAC,EAAEsB,SAAS;QAC/B,OAAO;YACLd,KAAKW,GAAG,CAAC,GAAGnB,KAAK,CAAC,EAAEC,cAAc;QACpC;IACF;IAEA,OAAO;WAAIO;KAAK;AAClB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lage-run/hasher",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.3",
|
|
4
4
|
"description": "Hasher for Lage Targets",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "https://github.com/microsoft/lage"
|
|
@@ -9,20 +9,21 @@
|
|
|
9
9
|
"main": "lib/index.js",
|
|
10
10
|
"types": "lib/index.d.ts",
|
|
11
11
|
"scripts": {
|
|
12
|
-
"build": "
|
|
13
|
-
"
|
|
14
|
-
"
|
|
12
|
+
"build": "yarn types && yarn transpile",
|
|
13
|
+
"transpile": "monorepo-scripts transpile",
|
|
14
|
+
"types": "yarn run -T tsc",
|
|
15
|
+
"test": "yarn run -T jest",
|
|
15
16
|
"lint": "monorepo-scripts lint"
|
|
16
17
|
},
|
|
17
18
|
"dependencies": {
|
|
18
|
-
"@lage-run/globby": "^
|
|
19
|
-
"@lage-run/logger": "^1.3.
|
|
20
|
-
"@lage-run/target-graph": "^0.12.
|
|
19
|
+
"@lage-run/globby": "^13.0.1",
|
|
20
|
+
"@lage-run/logger": "^1.3.3",
|
|
21
|
+
"@lage-run/target-graph": "^0.12.3",
|
|
21
22
|
"execa": "^5.1.1",
|
|
22
23
|
"glob-hasher": "^1.4.2",
|
|
23
24
|
"graceful-fs": "^4.2.11",
|
|
24
25
|
"micromatch": "^4.0.8",
|
|
25
|
-
"workspace-tools": "^0.
|
|
26
|
+
"workspace-tools": "^0.41.0"
|
|
26
27
|
},
|
|
27
28
|
"devDependencies": {
|
|
28
29
|
"@lage-run/monorepo-fixture": "^0.1.0",
|
|
@@ -30,7 +31,8 @@
|
|
|
30
31
|
"@types/graceful-fs": "^4.1.6",
|
|
31
32
|
"@types/micromatch": "^4.0.0"
|
|
32
33
|
},
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
|
|
34
|
+
"files": [
|
|
35
|
+
"lib/!(__*)",
|
|
36
|
+
"lib/!(__*)/**"
|
|
37
|
+
]
|
|
36
38
|
}
|