@lage-run/hasher 1.4.0 → 1.5.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
@@ -2,7 +2,28 @@
2
2
  "name": "@lage-run/hasher",
3
3
  "entries": [
4
4
  {
5
- "date": "Wed, 25 Sep 2024 20:27:33 GMT",
5
+ "date": "Fri, 27 Sep 2024 20:03:27 GMT",
6
+ "version": "1.5.0",
7
+ "tag": "@lage-run/hasher_v1.5.0",
8
+ "comments": {
9
+ "minor": [
10
+ {
11
+ "author": "kchau@microsoft.com",
12
+ "package": "@lage-run/hasher",
13
+ "commit": "2919f9041f931dc6ef65017f7aedb9fef9dab66d",
14
+ "comment": "exposes getInputFiles, packageTrees"
15
+ },
16
+ {
17
+ "author": "beachball",
18
+ "package": "@lage-run/hasher",
19
+ "comment": "Bump @lage-run/globby to v14.1.0",
20
+ "commit": "not available"
21
+ }
22
+ ]
23
+ }
24
+ },
25
+ {
26
+ "date": "Wed, 25 Sep 2024 20:28:10 GMT",
6
27
  "version": "1.4.0",
7
28
  "tag": "@lage-run/hasher_v1.4.0",
8
29
  "comments": {
package/CHANGELOG.md CHANGED
@@ -1,12 +1,21 @@
1
1
  # Change Log - @lage-run/hasher
2
2
 
3
- <!-- This log was last generated on Wed, 25 Sep 2024 20:27:33 GMT and should not be manually modified. -->
3
+ <!-- This log was last generated on Fri, 27 Sep 2024 20:03:27 GMT and should not be manually modified. -->
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 1.5.0
8
+
9
+ Fri, 27 Sep 2024 20:03:27 GMT
10
+
11
+ ### Minor changes
12
+
13
+ - exposes getInputFiles, packageTrees (kchau@microsoft.com)
14
+ - Bump @lage-run/globby to v14.1.0
15
+
7
16
  ## 1.4.0
8
17
 
9
- Wed, 25 Sep 2024 20:27:33 GMT
18
+ Wed, 25 Sep 2024 20:28:10 GMT
10
19
 
11
20
  ### Minor changes
12
21
 
@@ -45,14 +45,12 @@ export declare class TargetHasher {
45
45
  lockInfo: ParsedLock | undefined;
46
46
  targetHashes: Record<string, string>;
47
47
  dependencyMap: DependencyMap;
48
- memoizedEnvGlobResults: Map<string, string[]>;
49
- getMemorizedEnvGlobResults(envGlob: string[]): Promise<string[]>;
50
48
  getPackageInfos(workspacePackages: WorkspaceInfo): PackageInfos;
51
- expandInputPatterns(patterns: string[], target: Target): Record<string, string[]>;
52
49
  constructor(options: TargetHasherOptions);
53
50
  ensureInitialized(): void;
54
51
  initialize(): Promise<void>;
55
52
  hash(target: Target): Promise<string>;
56
53
  writeTargetHashesManifest(): void;
54
+ getEnvironmentGlobHashes(root: string, target: Target): Promise<Record<string, string>>;
57
55
  cleanup(): Promise<void>;
58
56
  }
@@ -9,7 +9,7 @@ Object.defineProperty(exports, "TargetHasher", {
9
9
  }
10
10
  });
11
11
  const _globhasher = require("glob-hasher");
12
- const _fastglob = /*#__PURE__*/ _interop_require_default(require("fast-glob"));
12
+ 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");
@@ -19,6 +19,7 @@ const _resolveInternalDependencies = require("./resolveInternalDependencies.js")
19
19
  const _resolveExternalDependencies = require("./resolveExternalDependencies.js");
20
20
  const _FileHasher = require("./FileHasher.js");
21
21
  const _PackageTree = require("./PackageTree.js");
22
+ const _getInputFiles = require("./getInputFiles.js");
22
23
  function _define_property(obj, key, value) {
23
24
  if (key in obj) {
24
25
  Object.defineProperty(obj, key, {
@@ -38,17 +39,6 @@ function _interop_require_default(obj) {
38
39
  };
39
40
  }
40
41
  class TargetHasher {
41
- async getMemorizedEnvGlobResults(envGlob) {
42
- const key = envGlob.join("\0ENV_GLOB\0");
43
- const { root } = this.options;
44
- if (!this.memoizedEnvGlobResults.has(key)) {
45
- const files = await (0, _fastglob.default)(envGlob, {
46
- cwd: root
47
- });
48
- this.memoizedEnvGlobResults.set(key, files);
49
- }
50
- return this.memoizedEnvGlobResults.get(key) ?? [];
51
- }
52
42
  getPackageInfos(workspacePackages) {
53
43
  const { root } = this.options;
54
44
  const packageInfos = {};
@@ -72,43 +62,6 @@ class TargetHasher {
72
62
  }
73
63
  return packageInfos;
74
64
  }
75
- expandInputPatterns(patterns, target) {
76
- const expandedPatterns = {};
77
- for (const pattern of patterns){
78
- if (pattern.startsWith("^") || pattern.startsWith("!^")) {
79
- const matchPattern = pattern.replace("^", "");
80
- // get all the packages that are transitive deps and add them to the list
81
- const queue = [
82
- target.packageName
83
- ];
84
- const visited = new Set();
85
- while(queue.length > 0){
86
- const pkg = queue.pop();
87
- if (visited.has(pkg)) {
88
- continue;
89
- }
90
- visited.add(pkg);
91
- if (pkg !== target.packageName) {
92
- expandedPatterns[pkg] = expandedPatterns[pkg] ?? [];
93
- expandedPatterns[pkg].push(matchPattern);
94
- }
95
- if (this.dependencyMap.dependencies.has(pkg)) {
96
- const deps = this.dependencyMap.dependencies.get(pkg);
97
- if (deps) {
98
- for (const dep of deps){
99
- queue.push(dep);
100
- }
101
- }
102
- }
103
- }
104
- } else {
105
- const pkg = target.packageName;
106
- expandedPatterns[pkg] = expandedPatterns[pkg] ?? [];
107
- expandedPatterns[pkg].push(pattern);
108
- }
109
- }
110
- return expandedPatterns;
111
- }
112
65
  ensureInitialized() {
113
66
  if (!this.initializedPromise) {
114
67
  throw new Error("TargetHasher is not initialized");
@@ -121,7 +74,9 @@ class TargetHasher {
121
74
  return;
122
75
  }
123
76
  this.initializedPromise = Promise.all([
124
- this.fileHasher.readManifest().then(()=>this.getMemorizedEnvGlobResults(environmentGlob)).then((files)=>this.fileHasher.hash(files)).then((hash)=>this.globalInputsHash = hash),
77
+ this.fileHasher.readManifest().then(()=>(0, _globby.globAsync)(environmentGlob, {
78
+ cwd: root
79
+ })).then((files)=>this.fileHasher.hash(files)).then((hash)=>this.globalInputsHash = hash),
125
80
  (0, _workspacetools.getWorkspacesAsync)(root).then((workspaceInfo)=>this.workspaceInfo = workspaceInfo).then(()=>{
126
81
  this.packageInfos = this.getPackageInfos(this.workspaceInfo);
127
82
  this.dependencyMap = (0, _workspacetools.createDependencyMap)(this.packageInfos, {
@@ -142,9 +97,6 @@ class TargetHasher {
142
97
  if (this.logger !== undefined) {
143
98
  const globalInputsHash = (0, _hashStrings.hashStrings)(Object.values(this.globalInputsHash ?? {}));
144
99
  this.logger.verbose(`Global inputs hash: ${globalInputsHash}`);
145
- // Log global input hashs to log file
146
- const globalInputsHashJson = JSON.stringify(this.globalInputsHash, null, 2);
147
- this.logger.silly(globalInputsHashJson);
148
100
  }
149
101
  }
150
102
  async hash(target) {
@@ -154,7 +106,7 @@ class TargetHasher {
154
106
  if (!target.inputs) {
155
107
  throw new Error("Root-level targets must have `inputs` defined if it has cache enabled.");
156
108
  }
157
- const files = await (0, _fastglob.default)(target.inputs, {
109
+ const files = await (0, _globby.globAsync)(target.inputs, {
158
110
  cwd: root
159
111
  });
160
112
  const fileFashes = (0, _globhasher.hash)(files, {
@@ -178,19 +130,11 @@ class TargetHasher {
178
130
  ...internalDeps,
179
131
  ...externalDeps
180
132
  ].sort();
181
- const inputs = target.inputs ?? [
182
- "**/*"
183
- ];
184
- const packagePatterns = this.expandInputPatterns(inputs, target);
185
- const files = [];
186
- for (const [pkg, patterns] of Object.entries(packagePatterns)){
187
- const packageFiles = this.packageTree.getPackageFiles(pkg, patterns);
188
- files.push(...packageFiles);
189
- }
133
+ const files = (0, _getInputFiles.getInputFiles)(target, this.dependencyMap, this.packageTree);
190
134
  const fileHashes = this.fileHasher.hash(files) ?? {}; // this list is sorted by file name
191
135
  // get target hashes
192
136
  const targetDepHashes = target.dependencies?.sort().map((targetDep)=>this.targetHashes[targetDep]);
193
- const globalFileHashes = target.environmentGlob ? this.fileHasher.hash(await this.getMemorizedEnvGlobResults(target.environmentGlob)) : this.globalInputsHash ?? {};
137
+ const globalFileHashes = await this.getEnvironmentGlobHashes(root, target);
194
138
  const combinedHashes = [
195
139
  // Environmental hashes
196
140
  ...Object.values(globalFileHashes),
@@ -224,6 +168,12 @@ class TargetHasher {
224
168
  }), "utf-8");
225
169
  }
226
170
  }
171
+ async getEnvironmentGlobHashes(root, target) {
172
+ const globalFileHashes = target.environmentGlob ? this.fileHasher.hash(await (0, _globby.globAsync)(target.environmentGlob ?? [], {
173
+ cwd: root
174
+ })) : this.globalInputsHash ?? {};
175
+ return globalFileHashes;
176
+ }
227
177
  async cleanup() {
228
178
  this.writeTargetHashesManifest();
229
179
  await this.fileHasher.writeManifest();
@@ -242,7 +192,6 @@ class TargetHasher {
242
192
  _define_property(this, "lockInfo", void 0);
243
193
  _define_property(this, "targetHashes", void 0);
244
194
  _define_property(this, "dependencyMap", void 0);
245
- _define_property(this, "memoizedEnvGlobResults", void 0);
246
195
  this.options = options;
247
196
  this.targetHashesLog = {};
248
197
  this.packageInfos = {};
@@ -251,7 +200,6 @@ class TargetHasher {
251
200
  dependencies: new Map(),
252
201
  dependents: new Map()
253
202
  };
254
- this.memoizedEnvGlobResults = new Map();
255
203
  const { root , logger } = options;
256
204
  this.logger = logger;
257
205
  this.fileHasher = new _FileHasher.FileHasher({
@@ -36,6 +36,25 @@ describe("The main Hasher class", ()=>{
36
36
  task
37
37
  };
38
38
  }
39
+ it("creates different hashes given different global environment glob", async ()=>{
40
+ const monorepo1 = await setupFixture("monorepo-with-global-files");
41
+ const hasher = new _index.TargetHasher({
42
+ root: monorepo1.root,
43
+ environmentGlob: [
44
+ "some-global.config.js"
45
+ ]
46
+ });
47
+ const target = createTarget(monorepo1.root, "package-a", "build");
48
+ const hash = await getHash(hasher, target);
49
+ const hasher2 = new _index.TargetHasher({
50
+ root: monorepo1.root,
51
+ environmentGlob: []
52
+ });
53
+ const target2 = createTarget(monorepo1.root, "package-a", "build");
54
+ const hash2 = await getHash(hasher2, target2);
55
+ expect(hash).not.toEqual(hash2);
56
+ monorepo1.cleanup();
57
+ });
39
58
  it("creates different hashes given different fixtures", async ()=>{
40
59
  const monorepo1 = await setupFixture("monorepo");
41
60
  const hasher = new _index.TargetHasher({
@@ -0,0 +1,3 @@
1
+ import { type Target } from "@lage-run/target-graph";
2
+ import { type DependencyMap } from "workspace-tools";
3
+ export declare function expandInputPatterns(patterns: string[], target: Target, dependencyMap: DependencyMap): Record<string, string[]>;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "expandInputPatterns", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return expandInputPatterns;
9
+ }
10
+ });
11
+ function expandInputPatterns(patterns, target, dependencyMap) {
12
+ const expandedPatterns = {};
13
+ for (const pattern of patterns){
14
+ if (pattern.startsWith("^") || pattern.startsWith("!^")) {
15
+ const matchPattern = pattern.replace("^", "");
16
+ // get all the packages that are transitive deps and add them to the list
17
+ const queue = [
18
+ target.packageName
19
+ ];
20
+ const visited = new Set();
21
+ while(queue.length > 0){
22
+ const pkg = queue.pop();
23
+ if (visited.has(pkg)) {
24
+ continue;
25
+ }
26
+ visited.add(pkg);
27
+ if (pkg !== target.packageName) {
28
+ expandedPatterns[pkg] = expandedPatterns[pkg] ?? [];
29
+ expandedPatterns[pkg].push(matchPattern);
30
+ }
31
+ if (dependencyMap.dependencies.has(pkg)) {
32
+ const deps = dependencyMap.dependencies.get(pkg);
33
+ if (deps) {
34
+ for (const dep of deps){
35
+ queue.push(dep);
36
+ }
37
+ }
38
+ }
39
+ }
40
+ } else {
41
+ const pkg = target.packageName;
42
+ expandedPatterns[pkg] = expandedPatterns[pkg] ?? [];
43
+ expandedPatterns[pkg].push(pattern);
44
+ }
45
+ }
46
+ return expandedPatterns;
47
+ }
@@ -0,0 +1,4 @@
1
+ import { type Target } from "@lage-run/target-graph";
2
+ import { type DependencyMap } from "workspace-tools";
3
+ import { type PackageTree } from "./PackageTree.js";
4
+ export declare function getInputFiles(target: Target, dependencyMap: DependencyMap, packageTree: PackageTree): string[];
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "getInputFiles", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return getInputFiles;
9
+ }
10
+ });
11
+ const _expandInputPatterns = require("./expandInputPatterns.js");
12
+ function getInputFiles(target, dependencyMap, packageTree) {
13
+ const inputs = target.inputs ?? [
14
+ "**/*"
15
+ ];
16
+ const packagePatterns = (0, _expandInputPatterns.expandInputPatterns)(inputs, target, dependencyMap);
17
+ const files = [];
18
+ for (const [pkg, patterns] of Object.entries(packagePatterns)){
19
+ const packageFiles = packageTree.getPackageFiles(pkg, patterns);
20
+ files.push(...packageFiles);
21
+ }
22
+ return files;
23
+ }
package/lib/index.d.ts CHANGED
@@ -1 +1,3 @@
1
1
  export { TargetHasher } from "./TargetHasher.js";
2
+ export { PackageTree } from "./PackageTree.js";
3
+ export { getInputFiles } from "./getInputFiles.js";
package/lib/index.js CHANGED
@@ -2,10 +2,23 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- Object.defineProperty(exports, "TargetHasher", {
6
- enumerable: true,
7
- get: function() {
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: all[name]
9
+ });
10
+ }
11
+ _export(exports, {
12
+ TargetHasher: function() {
8
13
  return _TargetHasher.TargetHasher;
14
+ },
15
+ PackageTree: function() {
16
+ return _PackageTree.PackageTree;
17
+ },
18
+ getInputFiles: function() {
19
+ return _getInputFiles.getInputFiles;
9
20
  }
10
21
  });
11
22
  const _TargetHasher = require("./TargetHasher.js");
23
+ const _PackageTree = require("./PackageTree.js");
24
+ const _getInputFiles = require("./getInputFiles.js");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lage-run/hasher",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Hasher for Lage Targets",
5
5
  "repository": {
6
6
  "url": "https://github.com/microsoft/lage"
@@ -15,10 +15,10 @@
15
15
  "lint": "monorepo-scripts lint"
16
16
  },
17
17
  "dependencies": {
18
+ "@lage-run/globby": "^14.1.0",
18
19
  "@lage-run/logger": "^1.3.1",
19
20
  "@lage-run/target-graph": "^0.8.10",
20
21
  "execa": "5.1.1",
21
- "fast-glob": "3.3.2",
22
22
  "glob-hasher": "^1.4.2",
23
23
  "graceful-fs": "4.2.11",
24
24
  "micromatch": "4.0.8",