@monorepolint/utils 0.6.0-alpha.2 → 0.6.0-alpha.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/.turbo/turbo-clean.log +1 -1
- package/.turbo/turbo-compile-typescript.log +1 -1
- package/.turbo/turbo-lint.log +7 -7
- package/.turbo/turbo-test.log +14 -10
- package/.turbo/turbo-transpile-typescript.log +3 -3
- package/CHANGELOG.md +2 -0
- package/build/js/index.js +493 -443
- package/build/js/index.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/CachingHost.d.ts.map +1 -1
- package/build/types/Host.d.ts.map +1 -1
- package/build/types/PackageJson.d.ts.map +1 -1
- package/build/types/SimpleHost.d.ts.map +1 -1
- package/build/types/Table.d.ts.map +1 -1
- package/build/types/findWorkspaceDir.d.ts.map +1 -1
- package/build/types/getPackageNameToDir.d.ts.map +1 -1
- package/build/types/getWorkspacePackageDirs.d.ts.map +1 -1
- package/build/types/index.d.ts +7 -7
- package/build/types/index.d.ts.map +1 -1
- package/build/types/matchesAnyGlob.d.ts.map +1 -1
- package/build/types/mutateJson.d.ts.map +1 -1
- package/build/types/nanosecondsToSanity.d.ts.map +1 -1
- package/coverage/AggregateTiming.ts.html +2 -2
- package/coverage/CachingHost.ts.html +258 -42
- package/coverage/Host.ts.html +15 -3
- package/coverage/PackageJson.ts.html +4 -4
- package/coverage/SimpleHost.ts.html +40 -7
- package/coverage/Table.ts.html +148 -31
- package/coverage/Timing.ts.html +1 -1
- package/coverage/clover.xml +533 -389
- package/coverage/coverage-final.json +13 -13
- package/coverage/findWorkspaceDir.ts.html +4 -4
- package/coverage/getPackageNameToDir.ts.html +18 -6
- package/coverage/getWorkspacePackageDirs.ts.html +174 -138
- package/coverage/index.html +40 -40
- package/coverage/index.ts.html +30 -30
- package/coverage/matchesAnyGlob.ts.html +37 -10
- package/coverage/mutateJson.ts.html +17 -5
- package/coverage/nanosecondsToSanity.ts.html +11 -5
- package/package.json +1 -2
- package/src/AggregateTiming.ts +1 -1
- package/src/CachingHost.ts +106 -34
- package/src/Host.ts +5 -1
- package/src/PackageJson.ts +3 -3
- package/src/SimpleHost.ts +14 -3
- package/src/Table.ts +62 -23
- package/src/__tests__/CachingHost.spec.ts +203 -166
- package/src/findWorkspaceDir.ts +3 -3
- package/src/getPackageNameToDir.ts +6 -2
- package/src/getWorkspacePackageDirs.ts +22 -10
- package/src/index.ts +7 -7
- package/src/matchesAnyGlob.ts +12 -3
- package/src/mutateJson.ts +5 -1
- package/src/nanosecondsToSanity.ts +3 -1
- package/vitest.config.mjs +10 -7
- package/vitest.config.mjs.timestamp-1736878329730-aa478e2241542.mjs +2 -2
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* Licensed under the MIT license. See LICENSE file in the project root for details.
|
|
5
5
|
*
|
|
6
6
|
*/
|
|
7
|
-
import { describe, expect, it, beforeEach } from "vitest";
|
|
8
|
-
import { CachingHost } from "../CachingHost.js";
|
|
9
7
|
import * as realfs from "node:fs";
|
|
10
|
-
import * as path from "node:path";
|
|
11
8
|
import * as os from "node:os";
|
|
9
|
+
import * as path from "node:path";
|
|
10
|
+
import { beforeEach, describe, expect, it } from "vitest";
|
|
11
|
+
import { CachingHost } from "../CachingHost.js";
|
|
12
12
|
|
|
13
13
|
interface TestCase<T> {
|
|
14
14
|
getFs: () => T;
|
|
@@ -25,220 +25,257 @@ class RealFsTestCase implements TestCase<typeof realfs> {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
describe(CachingHost, () => {
|
|
28
|
-
describe.each([["fs", new RealFsTestCase()]])(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
28
|
+
describe.each([["fs", new RealFsTestCase()]])(
|
|
29
|
+
"%s",
|
|
30
|
+
(_testCaseName, testCase) => {
|
|
31
|
+
let baseDir: string;
|
|
32
|
+
let fs: ReturnType<typeof testCase.getFs>;
|
|
33
|
+
|
|
34
|
+
let SYMLINK_JSON_PATH: string;
|
|
35
|
+
let SYMLINK_TXT_PATH: string;
|
|
36
|
+
let FILE_JSON_PATH: string;
|
|
37
|
+
let FILE_TXT_PATH: string;
|
|
38
|
+
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
fs = testCase.getFs();
|
|
41
|
+
baseDir = testCase.createTmpDir();
|
|
42
|
+
|
|
43
|
+
SYMLINK_JSON_PATH = path.resolve(baseDir, "symlink.json");
|
|
44
|
+
SYMLINK_TXT_PATH = path.resolve(baseDir, "symlink.txt");
|
|
45
|
+
FILE_TXT_PATH = path.resolve(baseDir, "file.txt");
|
|
46
|
+
FILE_JSON_PATH = path.resolve(baseDir, "file.json");
|
|
47
|
+
|
|
48
|
+
fs.writeFileSync(FILE_JSON_PATH, JSON.stringify({ hi: "mom" }), {
|
|
49
|
+
encoding: "utf-8",
|
|
50
|
+
});
|
|
51
|
+
fs.symlinkSync(FILE_JSON_PATH, SYMLINK_JSON_PATH);
|
|
52
|
+
|
|
53
|
+
fs.writeFileSync(FILE_TXT_PATH, "hi dad", { encoding: "utf-8" });
|
|
54
|
+
fs.symlinkSync(FILE_TXT_PATH, SYMLINK_TXT_PATH);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
function expectFileToExist(file: string) {
|
|
58
|
+
return expect(fs.existsSync(file));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function expectFileContents(file: string) {
|
|
62
|
+
return expect(fs.readFileSync(file, { encoding: "utf-8" }));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function expectSymlinkTarget(src: string, target: string) {
|
|
66
|
+
const stat = fs.lstatSync(src);
|
|
67
|
+
expect(stat.isSymbolicLink() && fs.readlinkSync(src)).toEqual(target);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
it("Answers exists() properly", async () => {
|
|
71
|
+
expect.assertions(2);
|
|
72
|
+
await realfs.promises.writeFile(path.join(baseDir, "b.txt"), "hi", {
|
|
73
|
+
encoding: "utf-8",
|
|
74
|
+
});
|
|
75
|
+
const host = new CachingHost(fs as any);
|
|
76
|
+
expect(host.exists(path.join(baseDir, "b.txt"))).toBe(true);
|
|
77
|
+
expect(host.exists(path.join(baseDir, "nosuchfile.txt"))).toBe(false);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("properly handles deletes", async () => {
|
|
81
|
+
expect.assertions(2);
|
|
82
|
+
const host = new CachingHost(fs as any);
|
|
83
|
+
|
|
84
|
+
host.writeFile(path.join(baseDir, "b.txt"), "hi", {
|
|
85
|
+
encoding: "utf-8",
|
|
86
|
+
});
|
|
87
|
+
host.deleteFile(path.join(baseDir, "b.txt"));
|
|
88
|
+
host.deleteFile(path.join(baseDir, "a.json"));
|
|
45
89
|
|
|
46
|
-
|
|
47
|
-
fs.symlinkSync(FILE_JSON_PATH, SYMLINK_JSON_PATH);
|
|
90
|
+
await host.flush();
|
|
48
91
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
92
|
+
expectFileToExist(path.join(baseDir, "b.txt")).toBeFalsy();
|
|
93
|
+
expectFileToExist(path.join(baseDir, "a.txt")).toBeFalsy();
|
|
94
|
+
});
|
|
52
95
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
96
|
+
it("handles simple read/write workflow", async () => {
|
|
97
|
+
expect.assertions(1);
|
|
56
98
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
99
|
+
const host = new CachingHost(fs as any);
|
|
100
|
+
host.writeFile(FILE_JSON_PATH, "cow", { encoding: "utf-8" });
|
|
60
101
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
102
|
+
expect(host.readFile(FILE_JSON_PATH, { encoding: "utf-8" })).toEqual(
|
|
103
|
+
"cow",
|
|
104
|
+
);
|
|
105
|
+
});
|
|
65
106
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
await realfs.promises.writeFile(path.join(baseDir, "b.txt"), "hi", { encoding: "utf-8" });
|
|
69
|
-
const host = new CachingHost(fs as any);
|
|
70
|
-
expect(host.exists(path.join(baseDir, "b.txt"))).toBe(true);
|
|
71
|
-
expect(host.exists(path.join(baseDir, "nosuchfile.txt"))).toBe(false);
|
|
72
|
-
});
|
|
107
|
+
it("handles target symlink changing", async () => {
|
|
108
|
+
expect.assertions(1);
|
|
73
109
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const host = new CachingHost(fs as any);
|
|
110
|
+
const host = new CachingHost(fs as any);
|
|
111
|
+
host.writeFile(FILE_JSON_PATH, "cow", { encoding: "utf-8" });
|
|
77
112
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
113
|
+
expect(host.readFile(FILE_JSON_PATH, { encoding: "utf-8" })).toEqual(
|
|
114
|
+
"cow",
|
|
115
|
+
);
|
|
116
|
+
});
|
|
81
117
|
|
|
82
|
-
|
|
118
|
+
it("handles writing symlinks properly", async () => {
|
|
119
|
+
expect.assertions(8);
|
|
83
120
|
|
|
84
|
-
|
|
85
|
-
expectFileToExist(path.join(baseDir, "a.txt")).toBeFalsy();
|
|
86
|
-
});
|
|
121
|
+
const host = new CachingHost(fs as any);
|
|
87
122
|
|
|
88
|
-
|
|
89
|
-
|
|
123
|
+
// file.json should now hold "hmm"
|
|
124
|
+
host.writeFile(SYMLINK_JSON_PATH, "hmm", { encoding: "utf-8" });
|
|
90
125
|
|
|
91
|
-
|
|
92
|
-
|
|
126
|
+
expect(host.readFile(SYMLINK_JSON_PATH, { encoding: "utf-8" })).toEqual(
|
|
127
|
+
"hmm",
|
|
128
|
+
);
|
|
129
|
+
expect(host.readFile(FILE_JSON_PATH, { encoding: "utf-8" })).toEqual(
|
|
130
|
+
"hmm",
|
|
131
|
+
);
|
|
93
132
|
|
|
94
|
-
|
|
95
|
-
|
|
133
|
+
// Write it out so we can verify disk is right
|
|
134
|
+
await host.flush();
|
|
96
135
|
|
|
97
|
-
|
|
98
|
-
|
|
136
|
+
expectFileToExist(SYMLINK_JSON_PATH).toBeTruthy();
|
|
137
|
+
expectFileToExist(FILE_TXT_PATH).toBeTruthy();
|
|
99
138
|
|
|
100
|
-
|
|
101
|
-
|
|
139
|
+
expectFileContents(FILE_JSON_PATH).toBe("hmm");
|
|
140
|
+
expectFileContents(SYMLINK_JSON_PATH).toBe("hmm");
|
|
102
141
|
|
|
103
|
-
|
|
104
|
-
});
|
|
142
|
+
expectSymlinkTarget(SYMLINK_JSON_PATH, FILE_JSON_PATH);
|
|
105
143
|
|
|
106
|
-
|
|
107
|
-
|
|
144
|
+
expect(host.readFile(SYMLINK_JSON_PATH, { encoding: "utf-8" })).toEqual(
|
|
145
|
+
"hmm",
|
|
146
|
+
);
|
|
147
|
+
});
|
|
108
148
|
|
|
109
|
-
|
|
149
|
+
it("handles writing symlinks properly if you read it first", async () => {
|
|
150
|
+
expect.assertions(8);
|
|
110
151
|
|
|
111
|
-
|
|
112
|
-
|
|
152
|
+
const host = new CachingHost(fs as any);
|
|
153
|
+
host.readFile(SYMLINK_JSON_PATH);
|
|
113
154
|
|
|
114
|
-
|
|
115
|
-
|
|
155
|
+
// file.json should now hold "hmm"
|
|
156
|
+
host.writeFile(path.join(baseDir, "symlink.json"), "hmm", {
|
|
157
|
+
encoding: "utf-8",
|
|
158
|
+
});
|
|
116
159
|
|
|
117
|
-
|
|
118
|
-
|
|
160
|
+
expect(host.readFile(SYMLINK_JSON_PATH, { encoding: "utf-8" })).toEqual(
|
|
161
|
+
"hmm",
|
|
162
|
+
);
|
|
163
|
+
expect(host.readFile(FILE_JSON_PATH, { encoding: "utf-8" })).toEqual(
|
|
164
|
+
"hmm",
|
|
165
|
+
);
|
|
119
166
|
|
|
120
|
-
|
|
121
|
-
|
|
167
|
+
// Write it out so we can verify disk is right
|
|
168
|
+
await host.flush();
|
|
122
169
|
|
|
123
|
-
|
|
124
|
-
|
|
170
|
+
expectFileToExist(SYMLINK_JSON_PATH).toBeTruthy();
|
|
171
|
+
expectFileToExist(FILE_TXT_PATH).toBeTruthy();
|
|
125
172
|
|
|
126
|
-
|
|
173
|
+
expectFileContents(FILE_JSON_PATH).toBe("hmm");
|
|
174
|
+
expectFileContents(SYMLINK_JSON_PATH).toBe("hmm");
|
|
127
175
|
|
|
128
|
-
|
|
129
|
-
});
|
|
176
|
+
expectSymlinkTarget(SYMLINK_JSON_PATH, FILE_JSON_PATH);
|
|
130
177
|
|
|
131
|
-
|
|
132
|
-
|
|
178
|
+
expect(host.readFile(SYMLINK_JSON_PATH, { encoding: "utf-8" })).toEqual(
|
|
179
|
+
"hmm",
|
|
180
|
+
);
|
|
181
|
+
});
|
|
133
182
|
|
|
134
|
-
|
|
135
|
-
|
|
183
|
+
it("handles creating new symlinks", async () => {
|
|
184
|
+
expect.assertions(8);
|
|
136
185
|
|
|
137
|
-
|
|
138
|
-
host.writeFile(path.join(baseDir, "symlink.json"), "hmm", { encoding: "utf-8" });
|
|
186
|
+
const host = new CachingHost(fs as any);
|
|
139
187
|
|
|
140
|
-
|
|
141
|
-
expect(host.readFile(FILE_JSON_PATH, { encoding: "utf-8" })).toEqual("hmm");
|
|
188
|
+
host.readFile(SYMLINK_JSON_PATH);
|
|
142
189
|
|
|
143
|
-
|
|
144
|
-
|
|
190
|
+
// file.json should now hold "hmm"
|
|
191
|
+
host.writeFile(path.join(baseDir, "symlink.json"), "hmm", {
|
|
192
|
+
encoding: "utf-8",
|
|
193
|
+
});
|
|
145
194
|
|
|
146
|
-
|
|
147
|
-
|
|
195
|
+
expect(host.readFile(SYMLINK_JSON_PATH, { encoding: "utf-8" })).toEqual(
|
|
196
|
+
"hmm",
|
|
197
|
+
);
|
|
198
|
+
expect(host.readFile(FILE_JSON_PATH, { encoding: "utf-8" })).toEqual(
|
|
199
|
+
"hmm",
|
|
200
|
+
);
|
|
148
201
|
|
|
149
|
-
|
|
150
|
-
|
|
202
|
+
// Write it out so we can verify disk is right
|
|
203
|
+
await host.flush();
|
|
151
204
|
|
|
152
|
-
|
|
205
|
+
expectFileToExist(SYMLINK_JSON_PATH).toBeTruthy();
|
|
206
|
+
expectFileToExist(FILE_TXT_PATH).toBeTruthy();
|
|
153
207
|
|
|
154
|
-
|
|
155
|
-
|
|
208
|
+
expectFileContents(FILE_JSON_PATH).toBe("hmm");
|
|
209
|
+
expectFileContents(SYMLINK_JSON_PATH).toBe("hmm");
|
|
156
210
|
|
|
157
|
-
|
|
158
|
-
expect.assertions(8);
|
|
211
|
+
expectSymlinkTarget(SYMLINK_JSON_PATH, FILE_JSON_PATH);
|
|
159
212
|
|
|
160
|
-
|
|
213
|
+
expect(host.readFile(SYMLINK_JSON_PATH, { encoding: "utf-8" })).toEqual(
|
|
214
|
+
"hmm",
|
|
215
|
+
);
|
|
216
|
+
});
|
|
161
217
|
|
|
162
|
-
|
|
218
|
+
it("makes directories", async () => {
|
|
219
|
+
expect.assertions(3);
|
|
163
220
|
|
|
164
|
-
|
|
165
|
-
host.writeFile(path.join(baseDir, "symlink.json"), "hmm", { encoding: "utf-8" });
|
|
221
|
+
const host = new CachingHost(fs as any);
|
|
166
222
|
|
|
167
|
-
|
|
168
|
-
|
|
223
|
+
host.mkdir(path.join(baseDir, "foo", "bar", "baz"), {
|
|
224
|
+
recursive: true,
|
|
225
|
+
});
|
|
169
226
|
|
|
170
|
-
|
|
171
|
-
|
|
227
|
+
// Write it out so we can verify disk is right
|
|
228
|
+
await host.flush();
|
|
172
229
|
|
|
173
|
-
|
|
174
|
-
|
|
230
|
+
expectFileToExist(path.join(baseDir, "foo")).toBeTruthy();
|
|
231
|
+
expectFileToExist(path.join(baseDir, "foo", "bar")).toBeTruthy();
|
|
232
|
+
expectFileToExist(path.join(baseDir, "foo", "bar", "baz")).toBeTruthy();
|
|
233
|
+
});
|
|
175
234
|
|
|
176
|
-
|
|
177
|
-
|
|
235
|
+
it("can unlink empty dirs", async () => {
|
|
236
|
+
expect.assertions(1);
|
|
178
237
|
|
|
179
|
-
|
|
238
|
+
// base setup
|
|
239
|
+
const fooDirPath = path.join(baseDir, "foo");
|
|
240
|
+
fs.mkdirSync(fooDirPath, { recursive: true });
|
|
180
241
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
it("makes directories", async () => {
|
|
185
|
-
expect.assertions(3);
|
|
186
|
-
|
|
187
|
-
const host = new CachingHost(fs as any);
|
|
188
|
-
|
|
189
|
-
host.mkdir(path.join(baseDir, "foo", "bar", "baz"), { recursive: true });
|
|
190
|
-
|
|
191
|
-
// Write it out so we can verify disk is right
|
|
192
|
-
await host.flush();
|
|
193
|
-
|
|
194
|
-
expectFileToExist(path.join(baseDir, "foo")).toBeTruthy();
|
|
195
|
-
expectFileToExist(path.join(baseDir, "foo", "bar")).toBeTruthy();
|
|
196
|
-
expectFileToExist(path.join(baseDir, "foo", "bar", "baz")).toBeTruthy();
|
|
197
|
-
});
|
|
242
|
+
// prep obj
|
|
243
|
+
const host = new CachingHost(fs as any);
|
|
244
|
+
host.rmdir(fooDirPath);
|
|
198
245
|
|
|
199
|
-
|
|
200
|
-
|
|
246
|
+
// Write it out so we can verify disk is right
|
|
247
|
+
await host.flush();
|
|
201
248
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
fs.mkdirSync(fooDirPath, { recursive: true });
|
|
249
|
+
expectFileToExist(fooDirPath).toBeFalsy();
|
|
250
|
+
});
|
|
205
251
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
host.rmdir(fooDirPath);
|
|
252
|
+
it("doesnt let you delete a directory with files", async () => {
|
|
253
|
+
expect.assertions(2);
|
|
209
254
|
|
|
210
|
-
|
|
211
|
-
|
|
255
|
+
const fooDirPath = path.join(baseDir, "foo");
|
|
256
|
+
const barFilePath = path.join(fooDirPath, "bar.txt");
|
|
212
257
|
|
|
213
|
-
|
|
214
|
-
|
|
258
|
+
const host = new CachingHost(fs as any);
|
|
259
|
+
host.mkdir(fooDirPath, { recursive: true });
|
|
260
|
+
host.writeJson(barFilePath, { hi: 5 });
|
|
215
261
|
|
|
216
|
-
|
|
217
|
-
|
|
262
|
+
expect(() => {
|
|
263
|
+
host.rmdir(fooDirPath);
|
|
264
|
+
}).toThrow();
|
|
218
265
|
|
|
219
|
-
|
|
220
|
-
|
|
266
|
+
// Write it out so we can verify disk is right
|
|
267
|
+
await host.flush();
|
|
221
268
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
host.writeJson(barFilePath, { hi: 5 });
|
|
269
|
+
expectFileToExist(fooDirPath).toBeTruthy();
|
|
270
|
+
});
|
|
225
271
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
it("doesn't let you rmdir() a file", () => {
|
|
237
|
-
expect.assertions(1);
|
|
238
|
-
const host = new CachingHost(fs as any);
|
|
239
|
-
expect(() => {
|
|
240
|
-
host.rmdir(FILE_JSON_PATH);
|
|
241
|
-
}).toThrow();
|
|
242
|
-
});
|
|
243
|
-
});
|
|
272
|
+
it("doesn't let you rmdir() a file", () => {
|
|
273
|
+
expect.assertions(1);
|
|
274
|
+
const host = new CachingHost(fs as any);
|
|
275
|
+
expect(() => {
|
|
276
|
+
host.rmdir(FILE_JSON_PATH);
|
|
277
|
+
}).toThrow();
|
|
278
|
+
});
|
|
279
|
+
},
|
|
280
|
+
);
|
|
244
281
|
});
|
package/src/findWorkspaceDir.ts
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
*
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import { findUp } from "find-up";
|
|
9
|
+
import * as fs from "fs";
|
|
8
10
|
import * as path from "path";
|
|
9
11
|
import { Host } from "./Host.js";
|
|
10
12
|
import { PackageJson } from "./PackageJson.js";
|
|
11
|
-
import * as fs from "fs";
|
|
12
|
-
import { findUp } from "find-up";
|
|
13
13
|
|
|
14
14
|
export async function findPnpmWorkspaceDir(cwd: string) {
|
|
15
15
|
const workspaceManifestLocation = await findUp("pnpm-workspace.yaml", {
|
|
@@ -20,7 +20,7 @@ export async function findPnpmWorkspaceDir(cwd: string) {
|
|
|
20
20
|
|
|
21
21
|
export async function findWorkspaceDir(
|
|
22
22
|
host: Pick<Host, "readJson" | "exists">,
|
|
23
|
-
dir: string
|
|
23
|
+
dir: string,
|
|
24
24
|
): Promise<string | undefined> {
|
|
25
25
|
// Defining workspaces in package.json is not necessary in PNPM
|
|
26
26
|
const maybePnpmWorkspaceDir = await findPnpmWorkspaceDir(dir);
|
|
@@ -17,11 +17,15 @@ import { PackageJson } from "./PackageJson.js";
|
|
|
17
17
|
export async function getPackageNameToDir(
|
|
18
18
|
host: Pick<Host, "readJson" | "exists">,
|
|
19
19
|
workspaceDir: string,
|
|
20
|
-
resolvePaths: boolean = false
|
|
20
|
+
resolvePaths: boolean = false,
|
|
21
21
|
) {
|
|
22
22
|
const ret = new Map<string, string>();
|
|
23
23
|
|
|
24
|
-
const workspacePackages = await getWorkspacePackageDirs(
|
|
24
|
+
const workspacePackages = await getWorkspacePackageDirs(
|
|
25
|
+
host,
|
|
26
|
+
workspaceDir,
|
|
27
|
+
resolvePaths,
|
|
28
|
+
);
|
|
25
29
|
for (const packageDir of workspacePackages) {
|
|
26
30
|
const packagePath = pathJoin(packageDir, "package.json");
|
|
27
31
|
const { name } = host.readJson(packagePath) as PackageJson;
|
|
@@ -5,19 +5,19 @@
|
|
|
5
5
|
*
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import { findPackages } from "find-packages";
|
|
8
9
|
import { existsSync } from "fs";
|
|
9
10
|
import * as glob from "glob";
|
|
10
|
-
import * as path from "node:path";
|
|
11
11
|
import * as fs from "node:fs";
|
|
12
|
+
import * as path from "node:path";
|
|
13
|
+
import readYamlFile from "read-yaml-file";
|
|
12
14
|
import { Host } from "./Host.js";
|
|
13
15
|
import { PackageJson } from "./PackageJson.js";
|
|
14
|
-
import readYamlFile from "read-yaml-file";
|
|
15
|
-
import { findPackages } from "find-packages";
|
|
16
16
|
|
|
17
17
|
async function findPNPMWorkspacePackages(workspaceRoot: string) {
|
|
18
18
|
workspaceRoot = fs.realpathSync(workspaceRoot);
|
|
19
19
|
const workspaceManifest = await readYamlFile.default<{ packages?: string[] }>(
|
|
20
|
-
path.join(workspaceRoot, "pnpm-workspace.yaml")
|
|
20
|
+
path.join(workspaceRoot, "pnpm-workspace.yaml"),
|
|
21
21
|
);
|
|
22
22
|
|
|
23
23
|
return findPackages(workspaceRoot, {
|
|
@@ -30,21 +30,29 @@ async function findPNPMWorkspacePackages(workspaceRoot: string) {
|
|
|
30
30
|
export async function getWorkspacePackageDirs(
|
|
31
31
|
host: Pick<Host, "readJson" | "exists">,
|
|
32
32
|
workspaceDir: string,
|
|
33
|
-
resolvePaths: boolean = false
|
|
33
|
+
resolvePaths: boolean = false,
|
|
34
34
|
) {
|
|
35
|
-
const packageJson = host.readJson(
|
|
35
|
+
const packageJson = host.readJson(
|
|
36
|
+
path.join(workspaceDir, "package.json"),
|
|
37
|
+
) as PackageJson;
|
|
36
38
|
|
|
37
|
-
const isPnpmWorkspace = host.exists(
|
|
39
|
+
const isPnpmWorkspace = host.exists(
|
|
40
|
+
path.join(workspaceDir, "pnpm-workspace.yaml"),
|
|
41
|
+
);
|
|
38
42
|
if (isPnpmWorkspace) {
|
|
39
43
|
const workspacePackages = await findPNPMWorkspacePackages(workspaceDir);
|
|
40
44
|
if (workspacePackages.length === 0) {
|
|
41
45
|
throw new Error("Invalid workspaceDir: " + workspaceDir);
|
|
42
46
|
}
|
|
43
|
-
return workspacePackages.map((project) => project.dir).filter((d) =>
|
|
47
|
+
return workspacePackages.map((project) => project.dir).filter((d) =>
|
|
48
|
+
d !== workspaceDir
|
|
49
|
+
);
|
|
44
50
|
}
|
|
45
51
|
|
|
46
52
|
if (!packageJson.workspaces) {
|
|
47
|
-
throw new Error(
|
|
53
|
+
throw new Error(
|
|
54
|
+
"Unsupported! Monorepo is not backed by either pnpm nor yarn workspaces.",
|
|
55
|
+
);
|
|
48
56
|
}
|
|
49
57
|
|
|
50
58
|
const ret: string[] = [];
|
|
@@ -54,7 +62,11 @@ export async function getWorkspacePackageDirs(
|
|
|
54
62
|
|
|
55
63
|
for (const pattern of packageGlobs) {
|
|
56
64
|
for (const packagePath of glob.sync(pattern, { cwd: workspaceDir })) {
|
|
57
|
-
const packageJsonPath = path.join(
|
|
65
|
+
const packageJsonPath = path.join(
|
|
66
|
+
workspaceDir,
|
|
67
|
+
packagePath,
|
|
68
|
+
"package.json",
|
|
69
|
+
);
|
|
58
70
|
|
|
59
71
|
if (existsSync(packageJsonPath)) {
|
|
60
72
|
if (resolvePaths === true) {
|
package/src/index.ts
CHANGED
|
@@ -5,16 +5,16 @@
|
|
|
5
5
|
*
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
export {
|
|
9
|
-
export {
|
|
10
|
-
export { PackageJson } from "./PackageJson.js";
|
|
8
|
+
export { AggregateTiming } from "./AggregateTiming.js";
|
|
9
|
+
export { CachingHost } from "./CachingHost.js";
|
|
11
10
|
export { findWorkspaceDir } from "./findWorkspaceDir.js";
|
|
12
11
|
export { getPackageNameToDir } from "./getPackageNameToDir.js";
|
|
12
|
+
export { getWorkspacePackageDirs } from "./getWorkspacePackageDirs.js";
|
|
13
13
|
export { Host } from "./Host.js";
|
|
14
|
-
export { SimpleHost } from "./SimpleHost.js";
|
|
15
|
-
export { CachingHost } from "./CachingHost.js";
|
|
16
14
|
export { matchesAnyGlob } from "./matchesAnyGlob.js";
|
|
15
|
+
export { mutateJson } from "./mutateJson.js";
|
|
17
16
|
export { nanosecondsToSanity } from "./nanosecondsToSanity.js";
|
|
18
|
-
export {
|
|
19
|
-
export {
|
|
17
|
+
export { PackageJson } from "./PackageJson.js";
|
|
18
|
+
export { SimpleHost } from "./SimpleHost.js";
|
|
20
19
|
export { Table } from "./Table.js";
|
|
20
|
+
export { Timing } from "./Timing.js";
|
package/src/matchesAnyGlob.ts
CHANGED
|
@@ -14,12 +14,18 @@ import { Table } from "./Table.js";
|
|
|
14
14
|
* Multimap cache of whether a needle was found in the glob haystack. Short circuits many
|
|
15
15
|
* individual checks against the globs.
|
|
16
16
|
*/
|
|
17
|
-
const cache = new Map
|
|
17
|
+
const cache = new Map<
|
|
18
|
+
/* haystack */ readonly string[],
|
|
19
|
+
Map</* needle */ string, /* result */ boolean>
|
|
20
|
+
>();
|
|
18
21
|
|
|
19
22
|
/**
|
|
20
23
|
* Multimap cache of whether a needle matches a glob. Allows us to avoid regexp's.
|
|
21
24
|
*/
|
|
22
|
-
const singleMatcherCache = new Map
|
|
25
|
+
const singleMatcherCache = new Map<
|
|
26
|
+
/* glob */ string,
|
|
27
|
+
Map</* needle */ string, /* result*/ boolean>
|
|
28
|
+
>();
|
|
23
29
|
|
|
24
30
|
/**
|
|
25
31
|
* Cache of glob to regular expression. Compiling the regular expression is expensive.
|
|
@@ -39,7 +45,10 @@ interface MatchesAnyGlob {
|
|
|
39
45
|
(needle: string, haystack: readonly string[]): boolean | undefined;
|
|
40
46
|
printStats?: () => void;
|
|
41
47
|
}
|
|
42
|
-
export const matchesAnyGlob: MatchesAnyGlob = function matchesAnyGlobFunc(
|
|
48
|
+
export const matchesAnyGlob: MatchesAnyGlob = function matchesAnyGlobFunc(
|
|
49
|
+
needle: string,
|
|
50
|
+
haystack: readonly string[],
|
|
51
|
+
) {
|
|
43
52
|
matchTime -= process.hrtime.bigint();
|
|
44
53
|
|
|
45
54
|
let cacheForHaystack = cache.get(haystack);
|
package/src/mutateJson.ts
CHANGED
|
@@ -6,7 +6,11 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { Host } from "./Host.js";
|
|
9
|
-
export function mutateJson<T extends object>(
|
|
9
|
+
export function mutateJson<T extends object>(
|
|
10
|
+
path: string,
|
|
11
|
+
host: Host,
|
|
12
|
+
mutator: (f: T) => T,
|
|
13
|
+
) {
|
|
10
14
|
let file = host.readJson(path) as T;
|
|
11
15
|
file = mutator(file);
|
|
12
16
|
host.writeJson(path, file);
|
|
@@ -6,5 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
export function nanosecondsToSanity(n: bigint, precision: number = 9) {
|
|
9
|
-
return n / BigInt(1000000000) + "."
|
|
9
|
+
return n / BigInt(1000000000) + "."
|
|
10
|
+
+ ("" + (n % BigInt(1000000000))).padStart(9, "0").substring(0, precision)
|
|
11
|
+
+ "s";
|
|
10
12
|
}
|