workspace-tools 0.16.0 → 0.18.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,82 @@
2
2
  "name": "workspace-tools",
3
3
  "entries": [
4
4
  {
5
- "date": "Tue, 25 May 2021 21:47:22 GMT",
5
+ "date": "Fri, 07 Jan 2022 00:04:25 GMT",
6
+ "tag": "workspace-tools_v0.18.0",
7
+ "version": "0.18.0",
8
+ "comments": {
9
+ "minor": [
10
+ {
11
+ "author": "kchau@microsoft.com",
12
+ "package": "workspace-tools",
13
+ "comment": "speed up workspace-tools - reducing weight and adding caches - lazy load pkg mgr helpers",
14
+ "commit": "6105a8eb81e4972b9ffbdd18669a137f0f5d9400"
15
+ }
16
+ ]
17
+ }
18
+ },
19
+ {
20
+ "date": "Thu, 02 Dec 2021 17:11:12 GMT",
21
+ "tag": "workspace-tools_v0.17.0",
22
+ "version": "0.17.0",
23
+ "comments": {
24
+ "minor": [
25
+ {
26
+ "author": "riacarmin@microsoft.com",
27
+ "package": "workspace-tools",
28
+ "comment": "Implements NPM workspaces support to parseLockFile utility.",
29
+ "commit": "0d9b3bd5c091e238d302f4a6912692e2eda95385"
30
+ }
31
+ ]
32
+ }
33
+ },
34
+ {
35
+ "date": "Thu, 21 Oct 2021 20:01:33 GMT",
36
+ "tag": "workspace-tools_v0.16.2",
37
+ "version": "0.16.2",
38
+ "comments": {
39
+ "none": [
40
+ {
41
+ "author": "elcraig@microsoft.com",
42
+ "package": "workspace-tools",
43
+ "comment": "Update beachball and add ignorePatterns",
44
+ "commit": "1aca866df2443581ce221c08b8e783a7054fcd7d"
45
+ }
46
+ ]
47
+ }
48
+ },
49
+ {
50
+ "date": "Thu, 03 Jun 2021 20:23:22 GMT",
51
+ "tag": "workspace-tools_v0.16.2",
52
+ "version": "0.16.2",
53
+ "comments": {
54
+ "patch": [
55
+ {
56
+ "comment": "get the right default remote branch",
57
+ "author": "kchau@microsoft.com",
58
+ "commit": "cb3c26d432f838805190f9afb65181f682c0145a",
59
+ "package": "workspace-tools"
60
+ }
61
+ ]
62
+ }
63
+ },
64
+ {
65
+ "date": "Thu, 27 May 2021 20:04:05 GMT",
66
+ "tag": "workspace-tools_v0.16.1",
67
+ "version": "0.16.1",
68
+ "comments": {
69
+ "patch": [
70
+ {
71
+ "comment": "getting rid of console logs from the library",
72
+ "author": "kchau@microsoft.com",
73
+ "commit": "7f47e421c14b9122d19f848f8039ae266c55e692",
74
+ "package": "workspace-tools"
75
+ }
76
+ ]
77
+ }
78
+ },
79
+ {
80
+ "date": "Tue, 25 May 2021 21:47:27 GMT",
6
81
  "tag": "workspace-tools_v0.16.0",
7
82
  "version": "0.16.0",
8
83
  "comments": {
package/CHANGELOG.md CHANGED
@@ -1,12 +1,44 @@
1
1
  # Change Log - workspace-tools
2
2
 
3
- This log was last generated on Tue, 25 May 2021 21:47:22 GMT and should not be manually modified.
3
+ This log was last generated on Fri, 07 Jan 2022 00:04:25 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 0.18.0
8
+
9
+ Fri, 07 Jan 2022 00:04:25 GMT
10
+
11
+ ### Minor changes
12
+
13
+ - speed up workspace-tools - reducing weight and adding caches - lazy load pkg mgr helpers (kchau@microsoft.com)
14
+
15
+ ## 0.17.0
16
+
17
+ Thu, 02 Dec 2021 17:11:12 GMT
18
+
19
+ ### Minor changes
20
+
21
+ - Implements NPM workspaces support to parseLockFile utility. (riacarmin@microsoft.com)
22
+
23
+ ## 0.16.2
24
+
25
+ Thu, 03 Jun 2021 20:23:22 GMT
26
+
27
+ ### Patches
28
+
29
+ - get the right default remote branch (kchau@microsoft.com)
30
+
31
+ ## 0.16.1
32
+
33
+ Thu, 27 May 2021 20:04:05 GMT
34
+
35
+ ### Patches
36
+
37
+ - getting rid of console logs from the library (kchau@microsoft.com)
38
+
7
39
  ## 0.16.0
8
40
 
9
- Tue, 25 May 2021 21:47:22 GMT
41
+ Tue, 25 May 2021 21:47:27 GMT
10
42
 
11
43
  ### Minor changes
12
44
 
package/README.md CHANGED
@@ -2,10 +2,11 @@
2
2
 
3
3
  A collection of tools that are useful in a git-controlled monorepo that is managed by one of these software:
4
4
 
5
+ - lerna
6
+ - npm workspaces
7
+ - pnpm workspaces
5
8
  - rush
6
9
  - yarn workspaces
7
- - pnpm workspaces
8
- - lerna
9
10
 
10
11
  # Environment Variables
11
12
 
@@ -17,7 +18,7 @@ default node.js maxBuffer of 1MB)
17
18
  ## PREFERRED_WORKSPACE_MANAGER
18
19
 
19
20
  Sometimes multiple package manager files are checked in. It is necessary to hint to `workspace-tools` which manager
20
- is used: `yarn`, `pnpm`, `rush`, or `lerna`
21
+ is used: `npm`, `yarn`, `pnpm`, `rush`, or `lerna`
21
22
 
22
23
  # Contributing
23
24
 
@@ -1,3 +1,12 @@
1
1
  module.exports = {
2
2
  scope: ["!src/__fixtures__/**/*"],
3
+ ignorePatterns: [
4
+ ".github/**",
5
+ ".prettierrc",
6
+ "jest.config.js",
7
+ "src/__fixtures__/**",
8
+ "src/__tests__/**",
9
+ // This prevents dependabot from being blocked by change file requirements for lock file-only changes
10
+ "yarn.lock",
11
+ ],
3
12
  };
@@ -18,7 +18,6 @@ describe("getDefaultRemote()", () => {
18
18
  // arrange
19
19
  const cwd = setupFixture_1.setupFixture("basic");
20
20
  setupFixture_1.setupLocalRemote(cwd, "myRemote", "basic");
21
- console.log(cwd);
22
21
  // act
23
22
  const remote = git_1.getDefaultRemote(cwd);
24
23
  // assert
@@ -2,22 +2,39 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const setupFixture_1 = require("../helpers/setupFixture");
4
4
  const lockfile_1 = require("../lockfile");
5
+ const ERROR_MESSAGES = {
6
+ NO_LOCK: "You do not have yarn.lock, pnpm-lock.yaml or package-lock.json. Please use one of these package managers.",
7
+ UNSUPPORTED: "Your package-lock.json version is not supported: lockfileVersion is 1. You need npm version 7 or above and package-lock version 2 or above. Please, upgrade npm or choose a different package manager.",
8
+ };
5
9
  describe("parseLockFile()", () => {
10
+ // General
11
+ it("throws if it cannot find lock file", async () => {
12
+ const packageRoot = await setupFixture_1.setupFixture("basic-without-lock-file");
13
+ await expect(lockfile_1.parseLockFile(packageRoot)).rejects.toThrow(ERROR_MESSAGES.NO_LOCK);
14
+ });
15
+ // NPM
16
+ it("parses package-lock.json file when it is found", async () => {
17
+ const packageRoot = await setupFixture_1.setupFixture("monorepo-npm");
18
+ const parsedLockeFile = await lockfile_1.parseLockFile(packageRoot);
19
+ expect(parsedLockeFile).toHaveProperty("type", "success");
20
+ });
21
+ it("throws if npm version is unsupported", async () => {
22
+ const packageRoot = await setupFixture_1.setupFixture("monorepo-npm-unsupported");
23
+ await expect(lockfile_1.parseLockFile(packageRoot)).rejects.toThrow(ERROR_MESSAGES.UNSUPPORTED);
24
+ });
25
+ // Yarn
6
26
  it("parses yarn.lock file when it is found", async () => {
7
27
  const packageRoot = await setupFixture_1.setupFixture("basic");
8
28
  const parsedLockeFile = await lockfile_1.parseLockFile(packageRoot);
9
29
  expect(parsedLockeFile).toHaveProperty("type", "success");
10
30
  });
11
- it("throws if it cannot find a yarn.lock file", async () => {
12
- const packageRoot = await setupFixture_1.setupFixture("basic-without-lock-file");
13
- await expect(lockfile_1.parseLockFile(packageRoot)).rejects.toThrow("You do not have either yarn.lock nor pnpm-lock.yaml. Please use one of these package managers");
14
- });
15
31
  it("parses combined ranges in yarn.lock", async () => {
16
32
  const packageRoot = await setupFixture_1.setupFixture("basic-yarn");
17
33
  const parsedLockeFile = await lockfile_1.parseLockFile(packageRoot);
18
34
  expect(parsedLockeFile.object["@babel/code-frame@^7.0.0"].version).toBe(parsedLockeFile.object["@babel/code-frame@^7.8.3"].version);
19
35
  });
20
- it("parses pnpm-lock.yaml properly", async () => {
36
+ // PNPM
37
+ it("parses pnpm-lock.yaml file when it is found", async () => {
21
38
  const packageRoot = await setupFixture_1.setupFixture("basic-pnpm");
22
39
  const parsedLockeFile = await lockfile_1.parseLockFile(packageRoot);
23
40
  expect(Object.keys(parsedLockeFile.object["yargs@16.2.0"].dependencies)).toContain("cliui");
@@ -17,7 +17,7 @@ function getPackageInfos(cwd) {
17
17
  }
18
18
  catch (e) {
19
19
  // Pass, the package.json is invalid
20
- console.warn(`Invalid package.json file detected ${packageJsonPath}: `, e);
20
+ throw new Error(`Invalid package.json file detected ${packageJsonPath}: ${e.message}`);
21
21
  }
22
22
  });
23
23
  return packageInfos;
@@ -5,25 +5,25 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const path_1 = __importDefault(require("path"));
7
7
  const globby_1 = __importDefault(require("globby"));
8
+ const packagePathsCache = {};
8
9
  function getPackagePaths(workspacesRoot, packages) {
9
- const packagePaths = packages.map((glob) => {
10
- const globbed = globby_1.default
11
- .sync(path_1.default.join(glob, "package.json").replace(/\\/g, "/"), {
12
- cwd: workspacesRoot,
13
- absolute: true,
14
- ignore: ["**/node_modules/**"],
15
- })
16
- .map((p) => path_1.default.dirname(p));
17
- return globbed;
18
- });
19
- /*
20
- * fast-glob returns unix style path,
21
- * so we use path.join to align the path with the platform.
22
- */
23
- return packagePaths
24
- .reduce((acc, cur) => {
25
- return [...acc, ...cur];
10
+ if (packagePathsCache[workspacesRoot]) {
11
+ return packagePathsCache[workspacesRoot];
12
+ }
13
+ const packagePaths = globby_1.default
14
+ .sync(packages.map((glob) => path_1.default.join(glob, "package.json").replace(/\\/g, "/")), {
15
+ cwd: workspacesRoot,
16
+ absolute: true,
17
+ ignore: ["**/node_modules/**"],
18
+ stats: false,
26
19
  })
27
- .map((p) => path_1.default.join(p));
20
+ .map((p) => path_1.default.dirname(p));
21
+ if (path_1.default.sep === "/") {
22
+ packagePathsCache[workspacesRoot] = packagePaths;
23
+ }
24
+ else {
25
+ packagePathsCache[workspacesRoot] = packagePaths.map((p) => p.replace(/\//g, path_1.default.sep));
26
+ }
27
+ return packagePathsCache[workspacesRoot];
28
28
  }
29
29
  exports.getPackagePaths = getPackagePaths;
package/lib/git.d.ts CHANGED
@@ -23,25 +23,25 @@ export declare function gitFailFast(args: string[], options?: {
23
23
  cwd: string;
24
24
  maxBuffer?: number;
25
25
  }): void;
26
- export declare function getUntrackedChanges(cwd: string): string[] | undefined;
26
+ export declare function getUntrackedChanges(cwd: string): string[];
27
27
  export declare function fetchRemote(remote: string, cwd: string): void;
28
28
  export declare function fetchRemoteBranch(remote: string, remoteBranch: string, cwd: string): void;
29
29
  /**
30
30
  * Gets all the changes that have not been staged yet
31
31
  * @param cwd
32
32
  */
33
- export declare function getUnstagedChanges(cwd: string): string[] | undefined;
34
- export declare function getChanges(branch: string, cwd: string): string[] | undefined;
33
+ export declare function getUnstagedChanges(cwd: string): string[];
34
+ export declare function getChanges(branch: string, cwd: string): string[];
35
35
  /**
36
36
  * Gets all the changes between the branch and the merge-base
37
37
  * @param branch
38
38
  * @param cwd
39
39
  */
40
40
  export declare function getBranchChanges(branch: string, cwd: string): string[];
41
- export declare function getChangesBetweenRefs(fromRef: string, toRef: string, options: string[], pattern: string, cwd: string): string[] | undefined;
42
- export declare function getStagedChanges(cwd: string): string[] | undefined;
43
- export declare function getRecentCommitMessages(branch: string, cwd: string): string[] | undefined;
44
- export declare function getUserEmail(cwd: string): string | null | undefined;
41
+ export declare function getChangesBetweenRefs(fromRef: string, toRef: string, options: string[], pattern: string, cwd: string): string[];
42
+ export declare function getStagedChanges(cwd: string): string[];
43
+ export declare function getRecentCommitMessages(branch: string, cwd: string): string[];
44
+ export declare function getUserEmail(cwd: string): string | null;
45
45
  export declare function getBranchName(cwd: string): string | null;
46
46
  export declare function getFullBranchRef(branch: string, cwd: string): string | null;
47
47
  export declare function getShortBranchName(fullBranchRef: string, cwd: string): string | null;
package/lib/git.js CHANGED
@@ -61,10 +61,10 @@ exports.git = git;
61
61
  function gitFailFast(args, options) {
62
62
  const gitResult = git(args, options);
63
63
  if (!gitResult.success) {
64
- console.error(`CRITICAL ERROR: running git command: git ${args.join(" ")}!`);
65
- console.error(gitResult.stdout && gitResult.stdout.toString().trimRight());
66
- console.error(gitResult.stderr && gitResult.stderr.toString().trimRight());
67
- process.exit(1);
64
+ process.exitCode = 1;
65
+ throw new Error(`CRITICAL ERROR: running git command: git ${args.join(" ")}!
66
+ ${gitResult.stdout && gitResult.stdout.toString().trimRight()}
67
+ ${gitResult.stderr && gitResult.stderr.toString().trimRight()}`);
68
68
  }
69
69
  }
70
70
  exports.gitFailFast = gitFailFast;
@@ -92,7 +92,7 @@ function getUntrackedChanges(cwd) {
92
92
  return untracked;
93
93
  }
94
94
  catch (e) {
95
- console.error("Cannot gather information about changes: ", e.message);
95
+ throw new Error(`Cannot gather information about untracked changes: ${e.message}`);
96
96
  }
97
97
  }
98
98
  exports.getUntrackedChanges = getUntrackedChanges;
@@ -119,7 +119,7 @@ function getUnstagedChanges(cwd) {
119
119
  return processGitOutput(git(["--no-pager", "diff", "--name-only", "--relative"], { cwd }));
120
120
  }
121
121
  catch (e) {
122
- console.error("Cannot gather information about changes: ", e.message);
122
+ throw new Error(`Cannot gather information about unstaged changes: ${e.message}`);
123
123
  }
124
124
  }
125
125
  exports.getUnstagedChanges = getUnstagedChanges;
@@ -128,7 +128,7 @@ function getChanges(branch, cwd) {
128
128
  return processGitOutput(git(["--no-pager", "diff", "--relative", "--name-only", branch + "..."], { cwd }));
129
129
  }
130
130
  catch (e) {
131
- console.error("Cannot gather information about changes: ", e.message);
131
+ throw new Error(`Cannot gather information about changes: ${e.message}`);
132
132
  }
133
133
  }
134
134
  exports.getChanges = getChanges;
@@ -142,7 +142,7 @@ function getBranchChanges(branch, cwd) {
142
142
  return processGitOutput(git(["--no-pager", "diff", "--name-only", "--relative", branch + "..."], { cwd }));
143
143
  }
144
144
  catch (e) {
145
- throw new Error(e.message);
145
+ throw new Error(`Cannot gather information about branch changes: ${e.message}`);
146
146
  }
147
147
  }
148
148
  exports.getBranchChanges = getBranchChanges;
@@ -153,7 +153,7 @@ function getChangesBetweenRefs(fromRef, toRef, options, pattern, cwd) {
153
153
  }));
154
154
  }
155
155
  catch (e) {
156
- console.error("Cannot gather information about changes: ", e.message);
156
+ throw new Error(`Cannot gather information about change between refs changes (${fromRef} to ${toRef}): ${e.message}`);
157
157
  }
158
158
  }
159
159
  exports.getChangesBetweenRefs = getChangesBetweenRefs;
@@ -162,7 +162,7 @@ function getStagedChanges(cwd) {
162
162
  return processGitOutput(git(["--no-pager", "diff", "--relative", "--staged", "--name-only"], { cwd }));
163
163
  }
164
164
  catch (e) {
165
- console.error("Cannot gather information about changes: ", e.message);
165
+ throw new Error(`Cannot gather information about staged changes: ${e.message}`);
166
166
  }
167
167
  }
168
168
  exports.getStagedChanges = getStagedChanges;
@@ -177,7 +177,7 @@ function getRecentCommitMessages(branch, cwd) {
177
177
  return lines.map((line) => line.trim());
178
178
  }
179
179
  catch (e) {
180
- console.error("Cannot gather information about recent commits: ", e.message);
180
+ throw new Error(`Cannot gather information about recent commits: ${e.message}`);
181
181
  }
182
182
  }
183
183
  exports.getRecentCommitMessages = getRecentCommitMessages;
@@ -190,7 +190,7 @@ function getUserEmail(cwd) {
190
190
  return results.stdout;
191
191
  }
192
192
  catch (e) {
193
- console.error("Cannot gather information about user.email: ", e.message);
193
+ throw new Error(`Cannot gather information about user.email: ${e.message}`);
194
194
  }
195
195
  }
196
196
  exports.getUserEmail = getUserEmail;
@@ -202,7 +202,7 @@ function getBranchName(cwd) {
202
202
  }
203
203
  }
204
204
  catch (e) {
205
- console.error("Cannot get branch name: ", e.message);
205
+ throw new Error(`Cannot get branch name: ${e.message}`);
206
206
  }
207
207
  return null;
208
208
  }
@@ -233,7 +233,7 @@ function getCurrentHash(cwd) {
233
233
  }
234
234
  }
235
235
  catch (e) {
236
- console.error("Cannot get current git hash");
236
+ throw new Error(`Cannot get current git hash: ${e.message}`);
237
237
  }
238
238
  return null;
239
239
  }
@@ -273,7 +273,7 @@ function stage(patterns, cwd) {
273
273
  });
274
274
  }
275
275
  catch (e) {
276
- console.error("Cannot stage changes", e.message);
276
+ throw new Error(`Cannot stage changes: ${e.message}`);
277
277
  }
278
278
  }
279
279
  exports.stage = stage;
@@ -281,13 +281,11 @@ function commit(message, cwd, options = []) {
281
281
  try {
282
282
  const commitResults = git(["commit", "-m", message, ...options], { cwd });
283
283
  if (!commitResults.success) {
284
- console.error("Cannot commit changes");
285
- console.log(commitResults.stdout);
286
- console.error(commitResults.stderr);
284
+ throw new Error(`Cannot commit changes: ${commitResults.stdout} ${commitResults.stderr}`);
287
285
  }
288
286
  }
289
287
  catch (e) {
290
- console.error("Cannot commit changes", e.message);
288
+ throw new Error(`Cannot commit changes: ${e.message}`);
291
289
  }
292
290
  }
293
291
  exports.commit = commit;
@@ -367,7 +365,22 @@ function normalizeRepoUrl(repositoryUrl) {
367
365
  }
368
366
  function getDefaultRemoteBranch(branch, cwd) {
369
367
  const defaultRemote = getDefaultRemote(cwd);
370
- branch = branch || getDefaultBranch(cwd);
368
+ const showRemote = git(["remote", "show", defaultRemote], { cwd });
369
+ /**
370
+ * The `showRemote` returns something like this in stdout:
371
+ *
372
+ * * remote origin
373
+ * Fetch URL: ../monorepo-upstream/
374
+ * Push URL: ../monorepo-upstream/
375
+ * HEAD branch: main
376
+ *
377
+ */
378
+ const headBranchLine = showRemote.stdout.split(/\n/).find(line => line.includes('HEAD branch'));
379
+ let remoteDefaultBranch;
380
+ if (headBranchLine) {
381
+ remoteDefaultBranch = headBranchLine.replace(/^\s*HEAD branch:\s+/, '');
382
+ }
383
+ branch = branch || remoteDefaultBranch || getDefaultBranch(cwd);
371
384
  return `${defaultRemote}/${branch}`;
372
385
  }
373
386
  exports.getDefaultRemoteBranch = getDefaultRemoteBranch;
@@ -386,7 +399,6 @@ function getDefaultRemote(cwd) {
386
399
  packageJson = JSON.parse(fs_1.default.readFileSync(path_1.default.join(paths_1.findGitRoot(cwd), "package.json")).toString());
387
400
  }
388
401
  catch (e) {
389
- console.log("failed to read package.json");
390
402
  throw new Error("invalid package.json detected");
391
403
  }
392
404
  const { repository } = packageJson;
@@ -412,7 +424,6 @@ function getDefaultRemote(cwd) {
412
424
  }
413
425
  }
414
426
  }
415
- console.log(`Defaults to "origin"`);
416
427
  return "origin";
417
428
  }
418
429
  exports.getDefaultRemote = getDefaultRemote;
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const path_1 = __importDefault(require("path"));
7
7
  const find_up_1 = __importDefault(require("find-up"));
8
8
  const fs_extra_1 = __importDefault(require("fs-extra"));
9
- const fs_extra_2 = __importDefault(require("fs-extra"));
10
9
  const tmp_1 = __importDefault(require("tmp"));
11
10
  const git_1 = require("../git");
12
11
  // tmp is supposed to be able to clean up automatically, but this doesn't always work within jest.
@@ -39,8 +38,8 @@ function setupFixture(fixtureName) {
39
38
  // ensure that the configuration for this repo does not collide
40
39
  // with any global configuration the user had made, so we have
41
40
  // a 'fixed' value for our tests, regardless of user configuration
42
- git_1.gitFailFast(['symbolic-ref', 'HEAD', 'refs/heads/main'], { cwd });
43
- git_1.gitFailFast(['config', 'init.defaultBranch', 'main'], { cwd });
41
+ git_1.gitFailFast(["symbolic-ref", "HEAD", "refs/heads/main"], { cwd });
42
+ git_1.gitFailFast(["config", "init.defaultBranch", "main"], { cwd });
44
43
  git_1.stageAndCommit(["."], "test", cwd);
45
44
  return cwd;
46
45
  }
@@ -59,9 +58,9 @@ function setupLocalRemote(cwd, remoteName, fixtureName) {
59
58
  git_1.gitFailFast(["remote", "add", remoteName, remoteUrl], { cwd });
60
59
  // Configure url in package.json
61
60
  const pkgJsonPath = path_1.default.join(cwd, "package.json");
62
- const pkgJson = fs_extra_2.default.readJSONSync(pkgJsonPath);
63
- fs_extra_2.default.writeJSONSync(pkgJsonPath, Object.assign(Object.assign({}, pkgJson), { repository: {
64
- url: remoteUrl
65
- } }));
61
+ const pkgJson = JSON.parse(fs_extra_1.default.readFileSync(pkgJsonPath, "utf-8"));
62
+ fs_extra_1.default.writeFileSync(pkgJsonPath, JSON.stringify(Object.assign(Object.assign({}, pkgJson), { repository: {
63
+ url: remoteUrl,
64
+ } }), null, 2));
66
65
  }
67
66
  exports.setupLocalRemote = setupLocalRemote;
@@ -3,4 +3,4 @@ import { nameAtVersion } from "./nameAtVersion";
3
3
  export declare function parseLockFile(packageRoot: string): Promise<ParsedLock>;
4
4
  export { nameAtVersion };
5
5
  export { queryLockFile } from "./queryLockFile";
6
- export * from './types';
6
+ export * from "./types";
@@ -10,12 +10,13 @@ var __importStar = (this && this.__importStar) || function (mod) {
10
10
  return result;
11
11
  };
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
+ // NOTE: never place the import of lockfile implementation here, as it slows down the library as a whole
13
14
  const find_up_1 = __importDefault(require("find-up"));
14
- const fs_extra_1 = __importDefault(require("fs-extra"));
15
- const read_yaml_file_1 = __importDefault(require("read-yaml-file"));
15
+ const fs_1 = __importDefault(require("fs"));
16
16
  const nameAtVersion_1 = require("./nameAtVersion");
17
17
  exports.nameAtVersion = nameAtVersion_1.nameAtVersion;
18
18
  const parsePnpmLock_1 = require("./parsePnpmLock");
19
+ const parseNpmLock_1 = require("./parseNpmLock");
19
20
  const memoization = {};
20
21
  async function parseLockFile(packageRoot) {
21
22
  const yarnLockPath = await find_up_1.default(["yarn.lock", "common/config/rush/yarn.lock"], { cwd: packageRoot });
@@ -25,7 +26,7 @@ async function parseLockFile(packageRoot) {
25
26
  return memoization[yarnLockPath];
26
27
  }
27
28
  const parseYarnLock = (await Promise.resolve().then(() => __importStar(require("@yarnpkg/lockfile")))).parse;
28
- const yarnLock = fs_extra_1.default.readFileSync(yarnLockPath).toString();
29
+ const yarnLock = fs_1.default.readFileSync(yarnLockPath, 'utf-8');
29
30
  const parsed = parseYarnLock(yarnLock);
30
31
  memoization[yarnLockPath] = parsed;
31
32
  return parsed;
@@ -36,12 +37,33 @@ async function parseLockFile(packageRoot) {
36
37
  if (memoization[pnpmLockPath]) {
37
38
  return memoization[pnpmLockPath];
38
39
  }
39
- const yaml = await read_yaml_file_1.default(pnpmLockPath);
40
+ const readYamlFile = require("read-yaml-file");
41
+ const yaml = (await readYamlFile(pnpmLockPath));
40
42
  const parsed = parsePnpmLock_1.parsePnpmLock(yaml);
41
43
  memoization[pnpmLockPath] = parsed;
42
44
  return memoization[pnpmLockPath];
43
45
  }
44
- throw new Error("You do not have either yarn.lock nor pnpm-lock.yaml. Please use one of these package managers");
46
+ // Third, try for npm workspaces
47
+ let npmLockPath = await find_up_1.default(["package-lock.json"], { cwd: packageRoot });
48
+ if (npmLockPath) {
49
+ if (memoization[npmLockPath]) {
50
+ return memoization[npmLockPath];
51
+ }
52
+ let npmLockJson;
53
+ try {
54
+ npmLockJson = fs_1.default.readFileSync(npmLockPath, 'utf-8');
55
+ }
56
+ catch (_a) {
57
+ throw new Error("Couldn’t parse package-lock.json.");
58
+ }
59
+ const npmLock = JSON.parse(npmLockJson.toString());
60
+ if (!(npmLock === null || npmLock === void 0 ? void 0 : npmLock.lockfileVersion) || npmLock.lockfileVersion < 2) {
61
+ throw new Error(`Your package-lock.json version is not supported: lockfileVersion is ${npmLock.lockfileVersion}. You need npm version 7 or above and package-lock version 2 or above. Please, upgrade npm or choose a different package manager.`);
62
+ }
63
+ memoization[npmLockPath] = parseNpmLock_1.parseNpmLock(npmLock);
64
+ return memoization[npmLockPath];
65
+ }
66
+ throw new Error("You do not have yarn.lock, pnpm-lock.yaml or package-lock.json. Please use one of these package managers.");
45
67
  }
46
68
  exports.parseLockFile = parseLockFile;
47
69
  var queryLockFile_1 = require("./queryLockFile");
@@ -0,0 +1,2 @@
1
+ import { ParsedLock, NpmLockFile } from "./types";
2
+ export declare const parseNpmLock: (lock: NpmLockFile) => ParsedLock;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseNpmLock = (lock) => {
4
+ var _a;
5
+ return ({
6
+ object: (_a = lock.dependencies) !== null && _a !== void 0 ? _a : {},
7
+ type: "success",
8
+ });
9
+ };
@@ -16,3 +16,34 @@ export interface PnpmLockFile {
16
16
  [name: string]: any;
17
17
  };
18
18
  }
19
+ export interface NpmWorkspacesInfo {
20
+ version: string;
21
+ workspaces: {
22
+ packages: string[];
23
+ };
24
+ }
25
+ export interface NpmSymlinkInfo {
26
+ resolved: string;
27
+ link: boolean;
28
+ integrity?: "sha512" | "sha1";
29
+ dev?: boolean;
30
+ optional?: boolean;
31
+ devOptional?: boolean;
32
+ dependencies?: {
33
+ [key: string]: LockDependency;
34
+ };
35
+ }
36
+ export interface NpmLockFile {
37
+ name: string;
38
+ version: string;
39
+ lockfileVersion?: 1 | 2 | 3;
40
+ requires?: boolean;
41
+ packages?: {
42
+ ""?: NpmWorkspacesInfo;
43
+ } & {
44
+ [key: string]: NpmSymlinkInfo | LockDependency;
45
+ };
46
+ dependencies?: {
47
+ [key: string]: LockDependency;
48
+ };
49
+ }
@@ -1,25 +1,23 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const implementations_1 = require("./implementations");
4
- const pnpm_1 = require("./implementations/pnpm");
5
- const yarn_1 = require("./implementations/yarn");
6
- const rush_1 = require("./implementations/rush");
7
- const npm_1 = require("./implementations/npm");
8
- const lerna_1 = require("./implementations/lerna");
9
- const workspaceGetter = {
10
- yarn: yarn_1.getYarnWorkspaceRoot,
11
- pnpm: pnpm_1.getPnpmWorkspaceRoot,
12
- rush: rush_1.getRushWorkspaceRoot,
13
- npm: npm_1.getNpmWorkspaceRoot,
14
- lerna: lerna_1.getLernaWorkspaceRoot,
15
- };
16
- const preferred = process.env
17
- .PREFERRED_WORKSPACE_MANAGER;
4
+ const preferred = process.env.PREFERRED_WORKSPACE_MANAGER;
18
5
  function getWorkspaceRoot(cwd) {
19
6
  const workspaceImplementation = preferred || implementations_1.getWorkspaceImplementation(cwd);
20
- if (!workspaceImplementation || !workspaceGetter[workspaceImplementation]) {
7
+ if (!workspaceImplementation) {
21
8
  return;
22
9
  }
23
- return workspaceGetter[workspaceImplementation](cwd);
10
+ switch (workspaceImplementation) {
11
+ case "yarn":
12
+ return require(`./implementations/yarn`).getYarnWorkspaceRoot(cwd);
13
+ case "pnpm":
14
+ return require(`./implementations/pnpm`).getPnpmWorkspaceRoot(cwd);
15
+ case "rush":
16
+ return require(`./implementations/rush`).getRushWorkspaceRoot(cwd);
17
+ case "npm":
18
+ return require(`./implementations/npm`).getNpmWorkspaceRoot(cwd);
19
+ case "lerna":
20
+ return require(`./implementations/lerna`).getLernaWorkspaceRoot(cwd);
21
+ }
24
22
  }
25
23
  exports.getWorkspaceRoot = getWorkspaceRoot;
@@ -1,25 +1,23 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const implementations_1 = require("./implementations");
4
- const pnpm_1 = require("./implementations/pnpm");
5
- const yarn_1 = require("./implementations/yarn");
6
- const rush_1 = require("./implementations/rush");
7
- const npm_1 = require("./implementations/npm");
8
- const lerna_1 = require("./implementations/lerna");
9
- const workspaceGetter = {
10
- yarn: yarn_1.getYarnWorkspaces,
11
- pnpm: pnpm_1.getPnpmWorkspaces,
12
- rush: rush_1.getRushWorkspaces,
13
- npm: npm_1.getNpmWorkspaces,
14
- lerna: lerna_1.getLernaWorkspaces,
15
- };
16
- const preferred = process.env
17
- .PREFERRED_WORKSPACE_MANAGER;
4
+ const preferred = process.env.PREFERRED_WORKSPACE_MANAGER;
18
5
  function getWorkspaces(cwd) {
19
6
  const workspaceImplementation = preferred || implementations_1.getWorkspaceImplementation(cwd);
20
- if (!workspaceImplementation || !workspaceGetter[workspaceImplementation]) {
7
+ if (!workspaceImplementation) {
21
8
  return [];
22
9
  }
23
- return workspaceGetter[workspaceImplementation](cwd);
10
+ switch (workspaceImplementation) {
11
+ case "yarn":
12
+ return require(`./implementations/yarn`).getYarnWorkspaces(cwd);
13
+ case "pnpm":
14
+ return require(`./implementations/pnpm`).getPnpmWorkspaces(cwd);
15
+ case "rush":
16
+ return require(`./implementations/rush`).getRushWorkspaces(cwd);
17
+ case "npm":
18
+ return require(`./implementations/npm`).getNpmWorkspaces(cwd);
19
+ case "lerna":
20
+ return require(`./implementations/lerna`).getLernaWorkspaces(cwd);
21
+ }
24
22
  }
25
23
  exports.getWorkspaces = getWorkspaces;
@@ -1,2 +1,10 @@
1
- export declare type WorkspaceImplementations = "yarn" | "pnpm" | "rush" | "npm" | 'lerna';
1
+ export declare type WorkspaceImplementations = "yarn" | "pnpm" | "rush" | "npm" | "lerna";
2
+ export interface ImplementationAndLockFile {
3
+ implementation: WorkspaceImplementations | undefined;
4
+ lockFile: string;
5
+ }
6
+ export declare function getWorkspaceImplementationAndLockFile(cwd: string): {
7
+ implementation: WorkspaceImplementations | undefined;
8
+ lockFile: string;
9
+ } | undefined;
2
10
  export declare function getWorkspaceImplementation(cwd: string): WorkspaceImplementations | undefined;
@@ -4,28 +4,55 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const find_up_1 = __importDefault(require("find-up"));
7
- function getWorkspaceImplementation(cwd) {
8
- // This needs to come before Yarn and NPM because
9
- // lerna can be used with either package manager
10
- const lernaJsonPath = find_up_1.default.sync("lerna.json", { cwd });
11
- if (lernaJsonPath) {
12
- return "lerna";
13
- }
14
- const yarnLockPath = find_up_1.default.sync("yarn.lock", { cwd });
15
- if (yarnLockPath) {
16
- return "yarn";
17
- }
18
- const pnpmLockPath = find_up_1.default.sync("pnpm-workspace.yaml", { cwd });
19
- if (pnpmLockPath) {
20
- return "pnpm";
7
+ const path_1 = __importDefault(require("path"));
8
+ const cache = {};
9
+ function getWorkspaceImplementationAndLockFile(cwd) {
10
+ if (cache[cwd]) {
11
+ return cache[cwd];
21
12
  }
22
- const rushJsonPath = find_up_1.default.sync("rush.json", { cwd });
23
- if (rushJsonPath) {
24
- return "rush";
13
+ const lockFile = find_up_1.default.sync(["lerna.json", "yarn.lock", "pnpm-workspace.yaml", "rush.json", "package-lock.json"], {
14
+ cwd,
15
+ });
16
+ if (!lockFile) {
17
+ return;
25
18
  }
26
- const npmLockPath = find_up_1.default.sync("package-lock.json", { cwd });
27
- if (npmLockPath) {
28
- return "npm";
19
+ switch (path_1.default.basename(lockFile)) {
20
+ case "lerna.json":
21
+ cache[cwd] = {
22
+ implementation: "lerna",
23
+ lockFile,
24
+ };
25
+ break;
26
+ case "yarn.lock":
27
+ cache[cwd] = {
28
+ implementation: "yarn",
29
+ lockFile,
30
+ };
31
+ break;
32
+ case "pnpm-workspace.yaml":
33
+ cache[cwd] = {
34
+ implementation: "pnpm",
35
+ lockFile,
36
+ };
37
+ break;
38
+ case "rush.json":
39
+ cache[cwd] = {
40
+ implementation: "rush",
41
+ lockFile,
42
+ };
43
+ break;
44
+ case "package-lock.json":
45
+ cache[cwd] = {
46
+ implementation: "npm",
47
+ lockFile,
48
+ };
49
+ break;
29
50
  }
51
+ return cache[cwd];
52
+ }
53
+ exports.getWorkspaceImplementationAndLockFile = getWorkspaceImplementationAndLockFile;
54
+ function getWorkspaceImplementation(cwd) {
55
+ var _a;
56
+ return (_a = getWorkspaceImplementationAndLockFile(cwd)) === null || _a === void 0 ? void 0 : _a.implementation;
30
57
  }
31
58
  exports.getWorkspaceImplementation = getWorkspaceImplementation;
@@ -10,7 +10,7 @@ function getNpmWorkspaceRoot(cwd) {
10
10
  }
11
11
  exports.getNpmWorkspaceRoot = getNpmWorkspaceRoot;
12
12
  function getNpmWorkspaces(cwd) {
13
- const yarnWorkspacesRoot = getNpmWorkspaceRoot(cwd);
14
- return packageJsonWorkspaces_1.getWorkspaceInfoFromWorkspaceRoot(yarnWorkspacesRoot);
13
+ const npmWorkspacesRoot = getNpmWorkspaceRoot(cwd);
14
+ return packageJsonWorkspaces_1.getWorkspaceInfoFromWorkspaceRoot(npmWorkspacesRoot);
15
15
  }
16
16
  exports.getNpmWorkspaces = getNpmWorkspaces;
@@ -3,13 +3,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const find_yarn_workspace_root_1 = __importDefault(require("find-yarn-workspace-root"));
7
6
  const fs_1 = __importDefault(require("fs"));
8
7
  const path_1 = __importDefault(require("path"));
8
+ const _1 = require(".");
9
9
  const getPackagePaths_1 = require("../../getPackagePaths");
10
10
  const getWorkspacePackageInfo_1 = require("../getWorkspacePackageInfo");
11
11
  function getPackageJsonWorkspaceRoot(cwd) {
12
- const packageJsonWorkspacesRoot = find_yarn_workspace_root_1.default(cwd);
12
+ var _a;
13
+ const lockFile = (_a = _1.getWorkspaceImplementationAndLockFile(cwd)) === null || _a === void 0 ? void 0 : _a.lockFile;
14
+ const packageJsonWorkspacesRoot = lockFile ? path_1.default.dirname(lockFile) : cwd;
13
15
  return packageJsonWorkspacesRoot;
14
16
  }
15
17
  exports.getPackageJsonWorkspaceRoot = getPackageJsonWorkspaceRoot;
@@ -5,7 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const path_1 = __importDefault(require("path"));
7
7
  const find_up_1 = __importDefault(require("find-up"));
8
- const read_yaml_file_1 = require("read-yaml-file");
9
8
  const getPackagePaths_1 = require("../../getPackagePaths");
10
9
  const getWorkspacePackageInfo_1 = require("../getWorkspacePackageInfo");
11
10
  function getPnpmWorkspaceRoot(cwd) {
@@ -20,7 +19,8 @@ function getPnpmWorkspaces(cwd) {
20
19
  try {
21
20
  const pnpmWorkspacesRoot = getPnpmWorkspaceRoot(cwd);
22
21
  const pnpmWorkspacesFile = path_1.default.join(pnpmWorkspacesRoot, "pnpm-workspace.yaml");
23
- const pnpmWorkspaces = read_yaml_file_1.sync(pnpmWorkspacesFile);
22
+ const readYaml = require("read-yaml-file").sync;
23
+ const pnpmWorkspaces = readYaml(pnpmWorkspacesFile);
24
24
  const packagePaths = getPackagePaths_1.getPackagePaths(pnpmWorkspacesRoot, pnpmWorkspaces.packages);
25
25
  const workspaceInfo = getWorkspacePackageInfo_1.getWorkspacePackageInfo(packagePaths);
26
26
  return workspaceInfo;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "workspace-tools",
3
- "version": "0.16.0",
3
+ "version": "0.18.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -19,8 +19,6 @@
19
19
  "dependencies": {
20
20
  "@yarnpkg/lockfile": "^1.1.0",
21
21
  "find-up": "^4.1.0",
22
- "find-yarn-workspace-root": "^1.2.1",
23
- "fs-extra": "^9.0.0",
24
22
  "git-url-parse": "^11.1.2",
25
23
  "globby": "^11.0.0",
26
24
  "jju": "^1.4.0",
@@ -28,7 +26,6 @@
28
26
  "read-yaml-file": "^2.0.0"
29
27
  },
30
28
  "devDependencies": {
31
- "@types/fs-extra": "^8.1.0",
32
29
  "@types/git-url-parse": "^9.0.0",
33
30
  "@types/glob": "^7.1.1",
34
31
  "@types/jest": "^25.2.2",
@@ -37,7 +34,7 @@
37
34
  "@types/node": ">=12.0.0",
38
35
  "@types/tmp": "^0.2.0",
39
36
  "@types/yarnpkg__lockfile": "^1.1.3",
40
- "beachball": "^2.2.0",
37
+ "beachball": "^2.17.0",
41
38
  "jest": "^25.0.0",
42
39
  "tmp": "^0.2.1",
43
40
  "ts-jest": "^25.5.1",