monorepo-next 8.4.1 → 8.6.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monorepo-next",
3
- "version": "8.4.1",
3
+ "version": "8.6.0",
4
4
  "description": "Detach monorepo packages from normal linking",
5
5
  "bin": {
6
6
  "next": "bin/next.js"
@@ -62,7 +62,9 @@
62
62
  "conventional-recommended-bump": "6.1.0",
63
63
  "debug": "^4.3.1",
64
64
  "execa": "^5.0.0",
65
+ "glob": "^8.0.0",
65
66
  "inquirer": "^8.0.0",
67
+ "js-yaml": "^4.0.0",
66
68
  "minimatch": "^5.0.0",
67
69
  "npm-packlist": "^5.0.0",
68
70
  "rfc6902": "^5.0.0",
@@ -76,8 +78,9 @@
76
78
  "@crowdstrike/commitlint": "^5.0.0",
77
79
  "chai": "^4.2.0",
78
80
  "chai-as-promised": "^7.1.1",
81
+ "common-tags": "^1.8.2",
79
82
  "eslint": "^8.0.0",
80
- "eslint-config-crowdstrike": "^4.0.0",
83
+ "eslint-config-crowdstrike": "^7.0.0",
81
84
  "eslint-config-crowdstrike-node": "^3.0.0",
82
85
  "eslint-plugin-json-files": "^1.0.0",
83
86
  "eslint-plugin-mocha": "^10.0.0",
@@ -86,7 +89,7 @@
86
89
  "git-fixtures": "^4.0.0",
87
90
  "mocha": "^10.0.0",
88
91
  "mocha-helpers": "^6.2.1",
89
- "remark-cli": "^10.0.0",
92
+ "remark-cli": "^11.0.0",
90
93
  "remark-preset-lint-crowdstrike": "^2.0.0",
91
94
  "renovate-config-standard": "^2.0.0",
92
95
  "sinon": "^14.0.0",
@@ -21,22 +21,17 @@ async function getPackageChangedFiles({
21
21
  packageCwd,
22
22
  options,
23
23
  }) {
24
- let isAncestor = await isCommitAncestorOf(fromCommit, toCommit, options);
25
-
26
- let olderCommit;
27
- let newerCommit;
28
- if (isAncestor) {
29
- olderCommit = fromCommit;
30
- newerCommit = toCommit;
31
- } else {
32
- olderCommit = toCommit;
33
- newerCommit = fromCommit;
34
- }
24
+ // Be careful you don't accidentally use `...` instead of `..`.
25
+ // `...` finds the merge-base and uses that instead of `fromCommit`.
26
+ // https://stackoverflow.com/a/60496462
27
+ let committedChanges = await git(['diff', '--name-only', `${fromCommit}..${toCommit}`, packageCwd], options);
35
28
 
36
- let committedChanges = await git(['diff', '--name-only', `${olderCommit}...${newerCommit}`, packageCwd], options);
37
29
  committedChanges = getLinesFromOutput(committedChanges);
30
+
38
31
  let dirtyChanges = await git(['status', '--porcelain', packageCwd, '-u'], options);
32
+
39
33
  dirtyChanges = getLinesFromOutput(dirtyChanges).map(line => line.substr(3));
34
+
40
35
  let changedFiles = Array.from(new Set(committedChanges).union(dirtyChanges));
41
36
 
42
37
  return changedFiles;
@@ -4,7 +4,7 @@ const path = require('path');
4
4
  const semver = require('semver');
5
5
  const dependencyTypes = require('./dependency-types');
6
6
  const readJson = require('./json').read;
7
- const getWorkspacesPaths = require('./get-workspaces-paths');
7
+ const { getWorkspacesPaths } = require('./get-workspaces-paths');
8
8
 
9
9
  function copyDeps(left, right) {
10
10
  for (let dependencyType of dependencyTypes) {
@@ -77,7 +77,7 @@ async function buildDepGraph({
77
77
  }) {
78
78
  let workspacePackageJson = await readJson(path.join(workspaceCwd, 'package.json'));
79
79
 
80
- let workspaces = await getWorkspacesPaths({ workspaceCwd });
80
+ let workspaces = await getWorkspacesPaths({ cwd: workspaceCwd });
81
81
 
82
82
  let packageDirs = workspaces.map(dir => path.join(workspaceCwd, dir));
83
83
 
@@ -1,33 +1,178 @@
1
1
  'use strict';
2
2
 
3
3
  const execa = require('execa');
4
+ const fs = { ...require('fs'), ...require('fs').promises };
5
+ const { promisify } = require('util');
6
+ const glob = promisify(require('glob'));
7
+ const jsYaml = require('js-yaml');
4
8
  const path = require('path');
5
9
  const readJson = require('./json').read;
10
+ const readJsonSync = require('./json').readSync;
11
+
12
+ function processPnpm({ stdout }, cwd) {
13
+ let workspaces = stdout.split(/\r?\n/).reduce((workspaces, workspace) => {
14
+ if (!workspace.startsWith('No projects matched the filters')) {
15
+ if (process.platform === 'darwin' && workspace.startsWith(`${path.sep}private${path.sep}`)) {
16
+ workspace = `${path.sep}${path.relative(`${path.sep}private`, workspace)}`;
17
+ }
18
+
19
+ let relative = path.relative(cwd, workspace);
20
+
21
+ workspaces.push(relative);
22
+ }
23
+
24
+ return workspaces;
25
+ }, []);
26
+
27
+ return workspaces;
28
+ }
29
+
30
+ function processYarn({ stdout }) {
31
+ let json = JSON.parse(stdout);
32
+
33
+ let workspaces = Object.values(json).map(({ location }) => location);
34
+
35
+ return workspaces;
36
+ }
37
+
38
+ function processPnpmYaml(buffer) {
39
+ // read packagesGlobs excluding packagesGLobs starting with !
40
+ // https://pnpm.io/pnpm-workspace_yaml
41
+ let packagesGlobs = jsYaml.load(buffer).packages.filter((packagesGlob) => !packagesGlob.startsWith('!'));
42
+
43
+ return packagesGlobs;
44
+ }
45
+
46
+ function processGlobs({ cwd, _2dFilesArray, isPnpm }) {
47
+ let _1dFilesArray = Array.prototype.concat.apply([], _2dFilesArray);
48
+
49
+ let packagePaths = [...new Set(_1dFilesArray)];
50
+
51
+ let neededYarnKeys = ['name', 'version'];
52
+
53
+ let workspaces = packagePaths.filter(packagePath => {
54
+ let packageJson;
55
+
56
+ try {
57
+ packageJson = readJsonSync(path.join(cwd, packagePath, 'package.json'));
58
+ } catch (err) {
59
+ if (err.code === 'ENOENT') {
60
+ return;
61
+ }
62
+
63
+ throw err;
64
+ }
65
+
66
+ if (isPnpm) {
67
+ return true;
68
+ }
69
+
70
+ // for yarn, not a valid package if name and version are missing in package.json
71
+ if (neededYarnKeys.every(key => key in packageJson)) {
72
+ return true;
73
+ }
74
+ });
75
+
76
+ return workspaces;
77
+ }
6
78
 
7
79
  async function getWorkspacesPaths({
8
- workspaceCwd,
80
+ cwd,
81
+ shouldSpawn = false,
82
+ }) {
83
+ let workspacePackageJson = await readJson(path.join(cwd, 'package.json'));
84
+
85
+ let { workspaces } = workspacePackageJson;
86
+
87
+ let isPnpm = !workspaces;
88
+
89
+ if (shouldSpawn) {
90
+ if (isPnpm) {
91
+ workspaces = processPnpm(
92
+ await execa('pnpm', ['recursive', 'exec', '--', 'node', '-e', 'console.log(process.cwd())'], {
93
+ cwd,
94
+ }),
95
+ cwd,
96
+ );
97
+ } else {
98
+ workspaces = processYarn(
99
+ await execa('yarn', ['--silent', 'workspaces', 'info'], {
100
+ cwd,
101
+ }),
102
+ );
103
+ }
104
+ } else {
105
+ let packagesGlobs;
106
+
107
+ if (isPnpm) {
108
+ packagesGlobs = processPnpmYaml(
109
+ await fs.readFile(path.join(cwd, 'pnpm-workspace.yaml')),
110
+ );
111
+ } else {
112
+ packagesGlobs = workspaces.packages || workspaces;
113
+ }
114
+
115
+ let _2dFilesArray = await Promise.all(packagesGlobs.map(packagesGlob => {
116
+ return glob(packagesGlob, {
117
+ cwd,
118
+ });
119
+ }));
120
+
121
+ workspaces = processGlobs({ cwd, _2dFilesArray, isPnpm });
122
+ }
123
+
124
+ return workspaces;
125
+ }
126
+
127
+ function getWorkspacesPathsSync({
128
+ cwd,
129
+ shouldSpawn = false,
9
130
  }) {
10
- let workspacePackageJson = await readJson(path.join(workspaceCwd, 'package.json'));
131
+ let workspacePackageJson = readJsonSync(path.join(cwd, 'package.json'));
11
132
 
12
133
  let { workspaces } = workspacePackageJson;
13
134
 
14
- if (!workspaces) {
15
- workspaces = (await execa('pnpm', ['recursive', 'exec', '--', 'node', '-e', 'console.log(process.cwd())'], { cwd: workspaceCwd })).stdout
16
- .split(/\r?\n/)
17
- .map(workspace => path.relative(workspaceCwd, workspace));
135
+ let isPnpm = !workspaces;
136
+
137
+ if (shouldSpawn) {
138
+ if (isPnpm) {
139
+ workspaces = processPnpm(
140
+ execa.sync('pnpm', ['recursive', 'exec', '--', 'node', '-e', 'console.log(process.cwd())'], {
141
+ cwd,
142
+ }),
143
+ cwd,
144
+ );
145
+ } else {
146
+ workspaces = processYarn(
147
+ execa.sync('yarn', ['--silent', 'workspaces', 'info'], {
148
+ cwd,
149
+ }),
150
+ );
151
+ }
18
152
  } else {
19
- let jsonString = (
20
- await execa('yarn', ['--silent', 'workspaces', 'info'], {
21
- cwd: workspaceCwd,
22
- })
23
- ).stdout;
24
-
25
- let workspacesJson = JSON.parse(jsonString);
26
-
27
- workspaces = Object.values(workspacesJson).map(({ location }) => location);
153
+ let packagesGlobs;
154
+
155
+ if (isPnpm) {
156
+ packagesGlobs = processPnpmYaml(
157
+ fs.readFileSync(path.join(cwd, 'pnpm-workspace.yaml')),
158
+ );
159
+ } else {
160
+ packagesGlobs = workspaces.packages || workspaces;
161
+ }
162
+
163
+ let _2dFilesArray = packagesGlobs.map(packagesGlob => {
164
+ return glob.sync(packagesGlob, {
165
+ cwd,
166
+ });
167
+ });
168
+
169
+ workspaces = processGlobs({ cwd, _2dFilesArray, isPnpm });
28
170
  }
29
171
 
30
172
  return workspaces;
31
173
  }
32
174
 
33
- module.exports = getWorkspacesPaths;
175
+ module.exports = {
176
+ getWorkspacesPaths,
177
+ getWorkspacesPathsSync,
178
+ };
package/src/json.js CHANGED
@@ -11,6 +11,10 @@ async function read(path) {
11
11
  return JSON.parse(await fs.readFile(path, 'utf8'));
12
12
  }
13
13
 
14
+ function readSync(path) {
15
+ return JSON.parse(fs.readFileSync(path, 'utf8'));
16
+ }
17
+
14
18
  async function write(path, json) {
15
19
  await fs.writeFile(path, stringify(json));
16
20
  }
@@ -18,5 +22,6 @@ async function write(path, json) {
18
22
  module.exports = {
19
23
  stringify,
20
24
  read,
25
+ readSync,
21
26
  write,
22
27
  };
package/src/releasable.js CHANGED
@@ -18,6 +18,32 @@ const filesContributingToReleasability = new Set([
18
18
 
19
19
  const packageJsonDevChangeRegex = /^\/(?:devDependencies|publishConfig)(?:\/|$)/m;
20
20
 
21
+ const relativePathRegex = /^\.{2}(?:\/|\\|$)/;
22
+
23
+ function removeSubDirs(files) {
24
+ let remainingFiles = new Set(files);
25
+
26
+ for (let file of remainingFiles) {
27
+ let isSubDir = remainingFiles.some(nextFile => {
28
+ if (file === nextFile) {
29
+ return false;
30
+ }
31
+
32
+ let relative = path.relative(file, nextFile);
33
+
34
+ let isSubDir = !relativePathRegex.test(relative);
35
+
36
+ return isSubDir;
37
+ });
38
+
39
+ if (isSubDir) {
40
+ remainingFiles.delete(file);
41
+ }
42
+ }
43
+
44
+ return remainingFiles;
45
+ }
46
+
21
47
  async function prepareTmpPackage({
22
48
  cwd,
23
49
  tmpDir,
@@ -38,11 +64,11 @@ async function prepareTmpPackage({
38
64
  }
39
65
  }
40
66
 
41
- for (let file of changedFiles) {
42
- if (filesContributingToReleasability.has(file)) {
43
- continue;
44
- }
67
+ let remainingFiles = changedFiles.diff(filesContributingToReleasability);
68
+
69
+ remainingFiles = removeSubDirs(remainingFiles);
45
70
 
71
+ for (let file of remainingFiles) {
46
72
  let filePath = path.join(tmpDir, file);
47
73
 
48
74
  await fs.mkdir(path.dirname(filePath), { recursive: true });
@@ -161,4 +187,6 @@ async function getChangedReleasableFiles({
161
187
  module.exports = {
162
188
  getChangedReleasableFiles,
163
189
  packageJsonDevChangeRegex,
190
+ removeSubDirs,
191
+ relativePathRegex,
164
192
  };