@monorepolint/rules 0.6.0-alpha.5 → 0.6.0-alpha.6
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 +1 -1
- package/.turbo/turbo-test.log +446 -94
- package/.turbo/turbo-transpile-typescript.log +5 -5
- package/CHANGELOG.md +102 -0
- package/build/js/index.js +413 -368
- package/build/js/index.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/REMOVE.d.ts +2 -0
- package/build/types/REMOVE.d.ts.map +1 -0
- package/build/types/__tests__/alphabeticalDependencies.spec.d.ts +8 -0
- package/build/types/__tests__/alphabeticalDependencies.spec.d.ts.map +1 -0
- package/build/types/__tests__/forceError.spec.d.ts +8 -0
- package/build/types/__tests__/forceError.spec.d.ts.map +1 -0
- package/build/types/__tests__/oncePerPackage.spec.d.ts +8 -0
- package/build/types/__tests__/oncePerPackage.spec.d.ts.map +1 -0
- package/build/types/__tests__/standardTsconfig.spec.d.ts +8 -0
- package/build/types/__tests__/standardTsconfig.spec.d.ts.map +1 -0
- package/build/types/bannedDependencies.d.ts +9 -33
- package/build/types/bannedDependencies.d.ts.map +1 -1
- package/build/types/consistentDependencies.d.ts +6 -6
- package/build/types/consistentDependencies.d.ts.map +1 -1
- package/build/types/consistentVersions.d.ts +6 -10
- package/build/types/consistentVersions.d.ts.map +1 -1
- package/build/types/fileContents.d.ts +3 -2
- package/build/types/fileContents.d.ts.map +1 -1
- package/build/types/index.d.ts +1 -0
- package/build/types/index.d.ts.map +1 -1
- package/build/types/mustSatisfyPeerDependencies.d.ts +12 -190
- package/build/types/mustSatisfyPeerDependencies.d.ts.map +1 -1
- package/build/types/nestedWorkspaces.d.ts +2 -2
- package/build/types/nestedWorkspaces.d.ts.map +1 -1
- package/build/types/oncePerPackage.d.ts +6 -6
- package/build/types/oncePerPackage.d.ts.map +1 -1
- package/build/types/packageEntry.d.ts +11 -33
- package/build/types/packageEntry.d.ts.map +1 -1
- package/build/types/packageOrder.d.ts +2 -1
- package/build/types/packageOrder.d.ts.map +1 -1
- package/build/types/packageScript.d.ts +13 -22
- package/build/types/packageScript.d.ts.map +1 -1
- package/build/types/requireDependency.d.ts +5 -20
- package/build/types/requireDependency.d.ts.map +1 -1
- package/build/types/standardTsconfig.d.ts +12 -19
- package/build/types/standardTsconfig.d.ts.map +1 -1
- package/build/types/util/zodSchemas.d.ts +14 -0
- package/build/types/util/zodSchemas.d.ts.map +1 -0
- package/coverage/block-navigation.js +1 -1
- package/coverage/clover.xml +1454 -1442
- package/coverage/coverage-final.json +21 -19
- package/coverage/index.html +27 -27
- package/coverage/sorter.js +21 -7
- package/coverage/src/REMOVE.ts.html +88 -0
- package/coverage/src/alphabeticalDependencies.ts.html +34 -34
- package/coverage/src/alphabeticalScripts.ts.html +5 -5
- package/coverage/src/bannedDependencies.ts.html +20 -53
- package/coverage/src/consistentDependencies.ts.html +20 -14
- package/coverage/src/consistentVersions.ts.html +330 -183
- package/coverage/src/fileContents.ts.html +223 -88
- package/coverage/src/forceError.ts.html +60 -60
- package/coverage/src/index.html +127 -112
- package/coverage/src/index.ts.html +11 -5
- package/coverage/src/mustSatisfyPeerDependencies.ts.html +15 -501
- package/coverage/src/nestedWorkspaces.ts.html +5 -5
- package/coverage/src/oncePerPackage.ts.html +59 -59
- package/coverage/src/packageEntry.ts.html +121 -91
- package/coverage/src/packageOrder.ts.html +44 -14
- package/coverage/src/packageScript.ts.html +235 -88
- package/coverage/src/requireDependency.ts.html +241 -82
- package/coverage/src/standardTsconfig.ts.html +193 -193
- package/coverage/src/util/checkAlpha.ts.html +40 -40
- package/coverage/src/util/createRuleFactory.ts.html +19 -19
- package/coverage/src/util/index.html +30 -15
- package/coverage/src/util/makeDirectory.ts.html +11 -11
- package/coverage/src/util/packageDependencyGraphService.ts.html +1 -1
- package/coverage/src/util/zodSchemas.ts.html +130 -0
- package/package.json +14 -14
- package/src/REMOVE.ts +1 -0
- package/src/__tests__/alphabeticalDependencies.spec.ts +102 -0
- package/src/__tests__/alphabeticalScripts.spec.ts +18 -0
- package/src/__tests__/bannedDependencies.spec.ts +49 -0
- package/src/__tests__/consistentDependencies.spec.ts +23 -0
- package/src/__tests__/consistentVersions.spec.ts +142 -0
- package/src/__tests__/fileContents.spec.ts +348 -0
- package/src/__tests__/forceError.spec.ts +70 -0
- package/src/__tests__/mustSatisfyPeerDependencies.spec.ts +44 -0
- package/src/__tests__/nestedWorkspaces.spec.ts +14 -0
- package/src/__tests__/oncePerPackage.spec.ts +75 -0
- package/src/__tests__/packageEntry.spec.ts +177 -0
- package/src/__tests__/packageOrder.spec.ts +22 -0
- package/src/__tests__/packageScript.spec.ts +549 -0
- package/src/__tests__/requireDependency.spec.ts +259 -2
- package/src/__tests__/standardTsconfig.spec.ts +91 -0
- package/src/bannedDependencies.ts +14 -25
- package/src/consistentDependencies.ts +10 -8
- package/src/consistentVersions.ts +132 -83
- package/src/fileContents.ts +80 -35
- package/src/index.ts +2 -0
- package/src/mustSatisfyPeerDependencies.ts +10 -172
- package/src/nestedWorkspaces.ts +4 -4
- package/src/oncePerPackage.ts +6 -6
- package/src/packageEntry.ts +60 -50
- package/src/packageOrder.ts +19 -9
- package/src/packageScript.ts +67 -18
- package/src/requireDependency.ts +84 -31
- package/src/standardTsconfig.ts +26 -26
- package/src/util/zodSchemas.ts +15 -0
|
@@ -10,6 +10,7 @@ import { readFileSync, writeFileSync } from "node:fs";
|
|
|
10
10
|
import * as path from "node:path";
|
|
11
11
|
import * as tmp from "tmp";
|
|
12
12
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
13
|
+
import { REMOVE } from "../REMOVE.js";
|
|
13
14
|
import { requireDependency } from "../requireDependency.js";
|
|
14
15
|
import { makeDirectoryRecursively } from "../util/makeDirectory.js";
|
|
15
16
|
import { jsonToString } from "./utils.js";
|
|
@@ -55,11 +56,18 @@ const OPTIONS = {
|
|
|
55
56
|
},
|
|
56
57
|
devDependencies: {
|
|
57
58
|
bar: "^2.0.0",
|
|
58
|
-
baz:
|
|
59
|
+
baz: REMOVE,
|
|
59
60
|
},
|
|
60
61
|
} as const;
|
|
61
62
|
|
|
62
|
-
const CORRECT_OUTPUT = jsonToString(
|
|
63
|
+
const CORRECT_OUTPUT = jsonToString({
|
|
64
|
+
dependencies: {
|
|
65
|
+
foo: "1.0.0",
|
|
66
|
+
},
|
|
67
|
+
devDependencies: {
|
|
68
|
+
bar: "^2.0.0",
|
|
69
|
+
},
|
|
70
|
+
});
|
|
63
71
|
|
|
64
72
|
describe("requireDependency", () => {
|
|
65
73
|
tmp.setGracefulCleanup();
|
|
@@ -155,4 +163,253 @@ describe("requireDependency", () => {
|
|
|
155
163
|
const contents = readFile("./packages/wrong/package.json");
|
|
156
164
|
expect(contents).toEqual(CORRECT_OUTPUT);
|
|
157
165
|
});
|
|
166
|
+
|
|
167
|
+
describe("Missing package.json handling", () => {
|
|
168
|
+
it("handles gracefully when package.json does not exist", () => {
|
|
169
|
+
const { workspaceContext } = makeWorkspace({ fix: false });
|
|
170
|
+
// Don't create a package.json file
|
|
171
|
+
|
|
172
|
+
expect(() => {
|
|
173
|
+
requireDependency({ options: { dependencies: { foo: "1.0.0" } } }).check(workspaceContext);
|
|
174
|
+
}).toThrow(); // Should throw when trying to get package.json
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
describe("Invalid package.json structure", () => {
|
|
179
|
+
it("handles package.json with non-object dependencies", () => {
|
|
180
|
+
const { addFile, checkAndSpy } = makeWorkspace({ fix: false });
|
|
181
|
+
addFile("./package.json", PACKAGE_ROOT);
|
|
182
|
+
addFile(
|
|
183
|
+
"./packages/test/package.json",
|
|
184
|
+
jsonToString({
|
|
185
|
+
name: "test-package",
|
|
186
|
+
dependencies: "invalid-dependencies", // Should be an object
|
|
187
|
+
}),
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
// This won't throw - it will treat dependencies as undefined and add an error
|
|
191
|
+
const { addErrorSpy } = checkAndSpy("./packages/test");
|
|
192
|
+
requireDependency({ options: { dependencies: { foo: "1.0.0" } } }).check(
|
|
193
|
+
checkAndSpy("./packages/test").context,
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
// Should add error for missing dependencies block
|
|
197
|
+
expect(addErrorSpy).toHaveBeenCalled();
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it("handles malformed JSON in package.json", () => {
|
|
201
|
+
const { addFile, workspaceContext } = makeWorkspace({ fix: false });
|
|
202
|
+
addFile("./package.json", "{ invalid json }");
|
|
203
|
+
|
|
204
|
+
expect(() => {
|
|
205
|
+
requireDependency({ options: { dependencies: { foo: "1.0.0" } } }).check(workspaceContext);
|
|
206
|
+
}).toThrow(); // Should throw when parsing invalid JSON
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
describe("REMOVE symbol edge cases", () => {
|
|
211
|
+
it("handles REMOVE on non-existent dependency", () => {
|
|
212
|
+
const { addFile, workspaceContext } = makeWorkspace({ fix: true });
|
|
213
|
+
addFile("./package.json", PACKAGE_ROOT);
|
|
214
|
+
addFile(
|
|
215
|
+
"./packages/test/package.json",
|
|
216
|
+
jsonToString({
|
|
217
|
+
name: "test",
|
|
218
|
+
dependencies: {},
|
|
219
|
+
}),
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
const context = workspaceContext.createChildContext(
|
|
223
|
+
path.resolve(workspaceContext.packageDir, "packages/test"),
|
|
224
|
+
);
|
|
225
|
+
const addErrorSpy = vi.spyOn(context, "addError");
|
|
226
|
+
|
|
227
|
+
requireDependency({
|
|
228
|
+
options: {
|
|
229
|
+
dependencies: {
|
|
230
|
+
nonExistent: REMOVE,
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
}).check(context);
|
|
234
|
+
|
|
235
|
+
// Should not add any errors since the dependency doesn't exist (desired state achieved)
|
|
236
|
+
expect(addErrorSpy).toHaveBeenCalledTimes(0);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it("handles multiple REMOVE operations", () => {
|
|
240
|
+
const { addFile, readFile, workspaceContext } = makeWorkspace({ fix: true });
|
|
241
|
+
addFile("./package.json", PACKAGE_ROOT);
|
|
242
|
+
addFile(
|
|
243
|
+
"./packages/test/package.json",
|
|
244
|
+
jsonToString({
|
|
245
|
+
name: "test",
|
|
246
|
+
dependencies: {
|
|
247
|
+
toRemove1: "1.0.0",
|
|
248
|
+
toRemove2: "2.0.0",
|
|
249
|
+
toKeep: "3.0.0",
|
|
250
|
+
},
|
|
251
|
+
devDependencies: {
|
|
252
|
+
devToRemove: "1.0.0",
|
|
253
|
+
},
|
|
254
|
+
}),
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
const context = workspaceContext.createChildContext(
|
|
258
|
+
path.resolve(workspaceContext.packageDir, "packages/test"),
|
|
259
|
+
);
|
|
260
|
+
const addErrorSpy = vi.spyOn(context, "addError");
|
|
261
|
+
|
|
262
|
+
requireDependency({
|
|
263
|
+
options: {
|
|
264
|
+
dependencies: {
|
|
265
|
+
toRemove1: REMOVE,
|
|
266
|
+
toRemove2: REMOVE,
|
|
267
|
+
},
|
|
268
|
+
devDependencies: {
|
|
269
|
+
devToRemove: REMOVE,
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
}).check(context);
|
|
273
|
+
|
|
274
|
+
expect(addErrorSpy).toHaveBeenCalledTimes(3); // Three removals
|
|
275
|
+
|
|
276
|
+
const updatedPackage = JSON.parse(readFile("./packages/test/package.json"));
|
|
277
|
+
expect(updatedPackage.dependencies).toEqual({ toKeep: "3.0.0" });
|
|
278
|
+
expect(updatedPackage.devDependencies).toEqual({});
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it("handles REMOVE when dependency section doesn't exist", () => {
|
|
282
|
+
const { addFile, workspaceContext } = makeWorkspace({ fix: false });
|
|
283
|
+
addFile("./package.json", PACKAGE_ROOT);
|
|
284
|
+
addFile(
|
|
285
|
+
"./packages/test/package.json",
|
|
286
|
+
jsonToString({
|
|
287
|
+
name: "test",
|
|
288
|
+
// No dependencies section at all
|
|
289
|
+
}),
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
const context = workspaceContext.createChildContext(
|
|
293
|
+
path.resolve(workspaceContext.packageDir, "packages/test"),
|
|
294
|
+
);
|
|
295
|
+
const addErrorSpy = vi.spyOn(context, "addError");
|
|
296
|
+
|
|
297
|
+
requireDependency({
|
|
298
|
+
options: {
|
|
299
|
+
dependencies: {
|
|
300
|
+
nonExistent: REMOVE,
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
}).check(context);
|
|
304
|
+
|
|
305
|
+
// No error should be added since we're only trying to remove from a non-existent block
|
|
306
|
+
// This is the improved behavior - don't create dependency blocks just for removal
|
|
307
|
+
expect(addErrorSpy).toHaveBeenCalledTimes(0);
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
it("handles mixed ADD and REMOVE when dependency section doesn't exist", () => {
|
|
311
|
+
const { addFile, readFile, workspaceContext } = makeWorkspace({ fix: true });
|
|
312
|
+
addFile("./package.json", PACKAGE_ROOT);
|
|
313
|
+
addFile(
|
|
314
|
+
"./packages/test/package.json",
|
|
315
|
+
jsonToString({
|
|
316
|
+
name: "test",
|
|
317
|
+
// No dependencies section at all
|
|
318
|
+
}),
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
const context = workspaceContext.createChildContext(
|
|
322
|
+
path.resolve(workspaceContext.packageDir, "packages/test"),
|
|
323
|
+
);
|
|
324
|
+
const addErrorSpy = vi.spyOn(context, "addError");
|
|
325
|
+
|
|
326
|
+
requireDependency({
|
|
327
|
+
options: {
|
|
328
|
+
dependencies: {
|
|
329
|
+
toAdd: "1.0.0",
|
|
330
|
+
nonExistent: REMOVE, // This shouldn't create the block
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
}).check(context);
|
|
334
|
+
|
|
335
|
+
// Should add error only for missing block needed for the ADD operation
|
|
336
|
+
expect(addErrorSpy).toHaveBeenCalledTimes(1);
|
|
337
|
+
|
|
338
|
+
const updatedPackage = JSON.parse(readFile("./packages/test/package.json"));
|
|
339
|
+
expect(updatedPackage.dependencies).toEqual({ toAdd: "1.0.0" });
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
it("handles mixed ADD and REMOVE with existing dependencies", () => {
|
|
343
|
+
const { addFile, readFile, workspaceContext } = makeWorkspace({ fix: true });
|
|
344
|
+
addFile("./package.json", PACKAGE_ROOT);
|
|
345
|
+
addFile(
|
|
346
|
+
"./packages/test/package.json",
|
|
347
|
+
jsonToString({
|
|
348
|
+
name: "test",
|
|
349
|
+
dependencies: {
|
|
350
|
+
existing: "1.0.0",
|
|
351
|
+
toRemove: "2.0.0",
|
|
352
|
+
},
|
|
353
|
+
}),
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
const context = workspaceContext.createChildContext(
|
|
357
|
+
path.resolve(workspaceContext.packageDir, "packages/test"),
|
|
358
|
+
);
|
|
359
|
+
const addErrorSpy = vi.spyOn(context, "addError");
|
|
360
|
+
|
|
361
|
+
requireDependency({
|
|
362
|
+
options: {
|
|
363
|
+
dependencies: {
|
|
364
|
+
toAdd: "3.0.0",
|
|
365
|
+
existing: "1.0.0", // Correct version, no error
|
|
366
|
+
toRemove: REMOVE,
|
|
367
|
+
},
|
|
368
|
+
},
|
|
369
|
+
}).check(context);
|
|
370
|
+
|
|
371
|
+
// Should add errors for ADD and REMOVE operations
|
|
372
|
+
expect(addErrorSpy).toHaveBeenCalledTimes(2);
|
|
373
|
+
|
|
374
|
+
const updatedPackage = JSON.parse(readFile("./packages/test/package.json"));
|
|
375
|
+
expect(updatedPackage.dependencies).toEqual({
|
|
376
|
+
existing: "1.0.0",
|
|
377
|
+
toAdd: "3.0.0",
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
describe("Options Validation", () => {
|
|
383
|
+
it("should accept valid options", () => {
|
|
384
|
+
const ruleModule = requireDependency({ options: {} });
|
|
385
|
+
|
|
386
|
+
expect(() => ruleModule.validateOptions({})).not.toThrow();
|
|
387
|
+
expect(() => ruleModule.validateOptions({ dependencies: { "react": "^18.0.0" } })).not
|
|
388
|
+
.toThrow();
|
|
389
|
+
expect(() =>
|
|
390
|
+
ruleModule.validateOptions({
|
|
391
|
+
devDependencies: { "typescript": "^5.0.0" },
|
|
392
|
+
peerDependencies: { "react": ">=16.0.0" },
|
|
393
|
+
})
|
|
394
|
+
).not.toThrow();
|
|
395
|
+
|
|
396
|
+
// Optional versions (REMOVE)
|
|
397
|
+
expect(() =>
|
|
398
|
+
ruleModule.validateOptions({
|
|
399
|
+
dependencies: { "react": REMOVE },
|
|
400
|
+
})
|
|
401
|
+
).not.toThrow();
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
it("should reject invalid options", () => {
|
|
405
|
+
const ruleModule = requireDependency({ options: {} });
|
|
406
|
+
|
|
407
|
+
// @ts-expect-error testing invalid input
|
|
408
|
+
expect(() => ruleModule.validateOptions({ dependencies: "react" })).toThrow();
|
|
409
|
+
// @ts-expect-error testing invalid input
|
|
410
|
+
expect(() => ruleModule.validateOptions({ dependencies: { "react": 123 } })).toThrow();
|
|
411
|
+
// @ts-expect-error testing invalid input
|
|
412
|
+
expect(() => ruleModule.validateOptions({ devDependencies: [] })).toThrow();
|
|
413
|
+
});
|
|
414
|
+
});
|
|
158
415
|
});
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright 2019 Palantir Technologies, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the MIT license. See LICENSE file in the project root for details.
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Context } from "@monorepolint/config";
|
|
9
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
10
|
+
import { standardTsconfig } from "../standardTsconfig.js";
|
|
11
|
+
import { AddErrorSpy, createTestingWorkspace, HOST_FACTORIES, TestingWorkspace } from "./utils.js";
|
|
12
|
+
|
|
13
|
+
describe.each(HOST_FACTORIES)("standardTsconfig ($name)", (hostFactory) => {
|
|
14
|
+
let workspace: TestingWorkspace;
|
|
15
|
+
let spy: AddErrorSpy;
|
|
16
|
+
let context: Context;
|
|
17
|
+
|
|
18
|
+
beforeEach(async () => {
|
|
19
|
+
workspace = await createTestingWorkspace({
|
|
20
|
+
fixFlag: true,
|
|
21
|
+
host: hostFactory.make(),
|
|
22
|
+
});
|
|
23
|
+
context = workspace.context;
|
|
24
|
+
spy = vi.spyOn(workspace.context, "addError");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("creates tsconfig.json when missing with template", async () => {
|
|
28
|
+
const template = { compilerOptions: { strict: true } };
|
|
29
|
+
|
|
30
|
+
await standardTsconfig({ options: { template } }).check(context);
|
|
31
|
+
|
|
32
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
33
|
+
expect(workspace.readFile("tsconfig.json")).toContain("\"strict\": true");
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("does nothing when tsconfig.json matches template", async () => {
|
|
37
|
+
const template = { compilerOptions: { strict: true } };
|
|
38
|
+
const expectedContent = JSON.stringify({ ...template, references: [] }, undefined, 2) + "\n";
|
|
39
|
+
|
|
40
|
+
workspace.writeFile("tsconfig.json", expectedContent);
|
|
41
|
+
|
|
42
|
+
await standardTsconfig({ options: { template } }).check(context);
|
|
43
|
+
|
|
44
|
+
expect(spy).toHaveBeenCalledTimes(0);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe("Options Validation", () => {
|
|
48
|
+
it("should accept valid options", () => {
|
|
49
|
+
const ruleModule1 = standardTsconfig({
|
|
50
|
+
options: { template: { compilerOptions: { strict: true } } },
|
|
51
|
+
});
|
|
52
|
+
const ruleModule2 = standardTsconfig({ options: { templateFile: "tsconfig.template.json" } });
|
|
53
|
+
const ruleModule3 = standardTsconfig({
|
|
54
|
+
options: { generator: () => JSON.stringify({ compilerOptions: {} }) },
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
expect(() => ruleModule1.validateOptions({ template: { compilerOptions: { strict: true } } }))
|
|
58
|
+
.not.toThrow();
|
|
59
|
+
expect(() => ruleModule2.validateOptions({ templateFile: "tsconfig.template.json" })).not
|
|
60
|
+
.toThrow();
|
|
61
|
+
expect(() =>
|
|
62
|
+
ruleModule3.validateOptions({
|
|
63
|
+
generator: () => JSON.stringify({ compilerOptions: {} }),
|
|
64
|
+
excludedReferences: ["@types/*"],
|
|
65
|
+
})
|
|
66
|
+
).not.toThrow();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("should reject invalid options", () => {
|
|
70
|
+
const ruleModule = standardTsconfig({ options: { template: {} } });
|
|
71
|
+
|
|
72
|
+
// Missing required source
|
|
73
|
+
expect(() => ruleModule.validateOptions({})).toThrow();
|
|
74
|
+
|
|
75
|
+
// Multiple sources (violates constraint)
|
|
76
|
+
expect(() =>
|
|
77
|
+
ruleModule.validateOptions({
|
|
78
|
+
template: {},
|
|
79
|
+
templateFile: "file.json",
|
|
80
|
+
})
|
|
81
|
+
).toThrow();
|
|
82
|
+
|
|
83
|
+
expect(() =>
|
|
84
|
+
ruleModule.validateOptions({
|
|
85
|
+
generator: () => "",
|
|
86
|
+
template: {},
|
|
87
|
+
})
|
|
88
|
+
).toThrow();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
});
|
|
@@ -6,10 +6,9 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { Context } from "@monorepolint/config";
|
|
9
|
-
import { matchesAnyGlob } from "@monorepolint/utils";
|
|
10
|
-
import { AggregateTiming } from "@monorepolint/utils";
|
|
9
|
+
import { AggregateTiming, matchesAnyGlob } from "@monorepolint/utils";
|
|
11
10
|
import * as path from "node:path";
|
|
12
|
-
import
|
|
11
|
+
import { z } from "zod";
|
|
13
12
|
import { createRuleFactory } from "./util/createRuleFactory.js";
|
|
14
13
|
import {
|
|
15
14
|
IPackageDependencyGraphNode,
|
|
@@ -17,30 +16,20 @@ import {
|
|
|
17
16
|
} from "./util/packageDependencyGraphService.js";
|
|
18
17
|
// FIXME: This rule is messed. bannedTransitiveDependencies doesnt glob
|
|
19
18
|
|
|
20
|
-
const bannedDepGlobsField =
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
glob:
|
|
24
|
-
exact:
|
|
19
|
+
const bannedDepGlobsField = z.union([
|
|
20
|
+
z.array(z.string()),
|
|
21
|
+
z.object({
|
|
22
|
+
glob: z.array(z.string()).optional(),
|
|
23
|
+
exact: z.array(z.string()).optional(),
|
|
25
24
|
}),
|
|
26
|
-
);
|
|
25
|
+
]);
|
|
27
26
|
|
|
28
|
-
const Options =
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}),
|
|
33
|
-
r.Record({
|
|
34
|
-
bannedDependencies: bannedDepGlobsField.optional(),
|
|
35
|
-
bannedTransitiveDependencies: r.Array(r.String),
|
|
36
|
-
}),
|
|
37
|
-
r.Record({
|
|
38
|
-
bannedDependencies: bannedDepGlobsField.optional(),
|
|
39
|
-
bannedTransitiveDependencies: r.Array(r.String).optional(),
|
|
40
|
-
}),
|
|
41
|
-
);
|
|
27
|
+
const Options = z.object({
|
|
28
|
+
bannedDependencies: bannedDepGlobsField.optional(),
|
|
29
|
+
bannedTransitiveDependencies: z.array(z.string()).optional(),
|
|
30
|
+
});
|
|
42
31
|
|
|
43
|
-
export type Options =
|
|
32
|
+
export type Options = z.infer<typeof Options>;
|
|
44
33
|
|
|
45
34
|
/**
|
|
46
35
|
* We use this locally to avoid making a billion sets. Because check is called once per package
|
|
@@ -113,7 +102,7 @@ export const bannedDependencies = createRuleFactory<Options>({
|
|
|
113
102
|
|
|
114
103
|
aggregateTiming.stop();
|
|
115
104
|
},
|
|
116
|
-
validateOptions: Options.
|
|
105
|
+
validateOptions: Options.parse,
|
|
117
106
|
printStats: () => {
|
|
118
107
|
aggregateTiming.printResults();
|
|
119
108
|
},
|
|
@@ -7,14 +7,16 @@
|
|
|
7
7
|
|
|
8
8
|
import { Context } from "@monorepolint/config";
|
|
9
9
|
import { diff } from "jest-diff";
|
|
10
|
-
import
|
|
10
|
+
import { z } from "zod";
|
|
11
11
|
import { createRuleFactory } from "./util/createRuleFactory.js";
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
|
|
13
|
+
const Options = z.union([
|
|
14
|
+
z.undefined(),
|
|
15
|
+
z.object({
|
|
16
|
+
ignoredDependencies: z.array(z.string()),
|
|
17
|
+
}),
|
|
18
|
+
]);
|
|
19
|
+
export type Options = z.infer<typeof Options>;
|
|
18
20
|
|
|
19
21
|
const skippedVersions = ["*", "latest"];
|
|
20
22
|
|
|
@@ -25,7 +27,7 @@ export const consistentDependencies = createRuleFactory<Options>({
|
|
|
25
27
|
checkDeps(context, args, "devDependencies");
|
|
26
28
|
// we don't check peer deps since they can be more lenient
|
|
27
29
|
},
|
|
28
|
-
validateOptions: Options.
|
|
30
|
+
validateOptions: Options.parse,
|
|
29
31
|
});
|
|
30
32
|
|
|
31
33
|
function checkDeps(
|