@monorepolint/rules 0.6.0-alpha.1 → 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.
Files changed (87) hide show
  1. package/.turbo/turbo-clean.log +1 -1
  2. package/.turbo/turbo-compile-typescript.log +1 -1
  3. package/.turbo/turbo-lint.log +1 -1
  4. package/.turbo/turbo-test.log +272 -667
  5. package/.turbo/turbo-transpile-typescript.log +5 -5
  6. package/CHANGELOG.md +42 -0
  7. package/build/js/index.js +411 -263
  8. package/build/js/index.js.map +1 -1
  9. package/build/tsconfig.tsbuildinfo +1 -1
  10. package/build/types/__tests__/utils.d.ts +4 -10
  11. package/build/types/__tests__/utils.d.ts.map +1 -1
  12. package/build/types/bannedDependencies.d.ts.map +1 -1
  13. package/build/types/fileContents.d.ts +1 -1
  14. package/build/types/fileContents.d.ts.map +1 -1
  15. package/build/types/index.d.ts +3 -3
  16. package/build/types/index.d.ts.map +1 -1
  17. package/build/types/mustSatisfyPeerDependencies.d.ts.map +1 -1
  18. package/build/types/nestedWorkspaces.d.ts.map +1 -1
  19. package/build/types/packageEntry.d.ts.map +1 -1
  20. package/build/types/packageOrder.d.ts.map +1 -1
  21. package/build/types/packageScript.d.ts.map +1 -1
  22. package/build/types/requireDependency.d.ts +12 -12
  23. package/build/types/requireDependency.d.ts.map +1 -1
  24. package/build/types/standardTsconfig.d.ts.map +1 -1
  25. package/build/types/util/checkAlpha.d.ts.map +1 -1
  26. package/build/types/util/createRuleFactory.d.ts.map +1 -1
  27. package/build/types/util/packageDependencyGraphService.d.ts.map +1 -1
  28. package/coverage/base.css +224 -0
  29. package/coverage/block-navigation.js +87 -0
  30. package/coverage/clover.xml +1887 -0
  31. package/coverage/coverage-final.json +19 -0
  32. package/coverage/favicon.png +0 -0
  33. package/coverage/index.html +131 -0
  34. package/coverage/prettify.css +1 -0
  35. package/coverage/prettify.js +2 -0
  36. package/coverage/sort-arrow-sprite.png +0 -0
  37. package/coverage/sorter.js +196 -0
  38. package/coverage/src/alphabeticalDependencies.ts.html +142 -0
  39. package/coverage/src/alphabeticalScripts.ts.html +136 -0
  40. package/coverage/src/bannedDependencies.ts.html +610 -0
  41. package/coverage/src/consistentDependencies.ts.html +394 -0
  42. package/coverage/src/consistentVersions.ts.html +619 -0
  43. package/coverage/src/fileContents.ts.html +409 -0
  44. package/coverage/src/index.html +311 -0
  45. package/coverage/src/index.ts.html +169 -0
  46. package/coverage/src/mustSatisfyPeerDependencies.ts.html +2605 -0
  47. package/coverage/src/nestedWorkspaces.ts.html +304 -0
  48. package/coverage/src/packageEntry.ts.html +376 -0
  49. package/coverage/src/packageOrder.ts.html +472 -0
  50. package/coverage/src/packageScript.ts.html +436 -0
  51. package/coverage/src/requireDependency.ts.html +349 -0
  52. package/coverage/src/standardTsconfig.ts.html +553 -0
  53. package/coverage/src/util/checkAlpha.ts.html +271 -0
  54. package/coverage/src/util/createRuleFactory.ts.html +196 -0
  55. package/coverage/src/util/index.html +161 -0
  56. package/coverage/src/util/makeDirectory.ts.html +157 -0
  57. package/coverage/src/util/packageDependencyGraphService.ts.html +508 -0
  58. package/package.json +15 -20
  59. package/src/__tests__/alphabeticalScripts.spec.ts +13 -5
  60. package/src/__tests__/bannedDependencies.spec.ts +47 -18
  61. package/src/__tests__/consistentDependencies.spec.ts +12 -6
  62. package/src/__tests__/consistentVersions.spec.ts +74 -20
  63. package/src/__tests__/fileContents.spec.ts +11 -7
  64. package/src/__tests__/mustSatisfyPeerDependencies.spec.ts +193 -78
  65. package/src/__tests__/nestedWorkspaces.spec.ts +12 -8
  66. package/src/__tests__/packageEntry.spec.ts +55 -49
  67. package/src/__tests__/packageOrder.spec.ts +78 -72
  68. package/src/__tests__/packageScript.spec.ts +27 -13
  69. package/src/__tests__/requireDependency.spec.ts +13 -7
  70. package/src/__tests__/utils.ts +18 -9
  71. package/src/bannedDependencies.ts +32 -15
  72. package/src/consistentDependencies.ts +22 -9
  73. package/src/consistentVersions.ts +84 -47
  74. package/src/fileContents.ts +24 -10
  75. package/src/index.ts +3 -3
  76. package/src/mustSatisfyPeerDependencies.ts +162 -66
  77. package/src/nestedWorkspaces.ts +23 -10
  78. package/src/packageEntry.ts +18 -11
  79. package/src/packageOrder.ts +9 -3
  80. package/src/packageScript.ts +37 -19
  81. package/src/requireDependency.ts +28 -11
  82. package/src/standardTsconfig.ts +32 -10
  83. package/src/util/checkAlpha.ts +5 -2
  84. package/src/util/createRuleFactory.ts +6 -2
  85. package/src/util/packageDependencyGraphService.ts +41 -14
  86. package/vitest.config.mjs +17 -0
  87. package/jest.config.cjs +0 -4
@@ -17,8 +17,8 @@ export const Options = r.Record({
17
17
  r.Record({
18
18
  options: r.Array(r.String.Or(r.Undefined)),
19
19
  fixValue: r.Union(r.String, r.Undefined, r.Literal(false)).optional(),
20
- })
21
- )
20
+ }),
21
+ ),
22
22
  ), // string => string
23
23
  });
24
24
 
@@ -35,10 +35,14 @@ export const packageScript = createRuleFactory<Options>({
35
35
  file: context.getPackageJsonPath(),
36
36
  message: MSG_NO_SCRIPTS_BLOCK,
37
37
  fixer: () => {
38
- mutateJson<PackageJson>(context.getPackageJsonPath(), context.host, (input) => {
39
- input.scripts = {};
40
- return input;
41
- });
38
+ mutateJson<PackageJson>(
39
+ context.getPackageJsonPath(),
40
+ context.host,
41
+ (input) => {
42
+ input.scripts = {};
43
+ return input;
44
+ },
45
+ );
42
46
  },
43
47
  });
44
48
  return;
@@ -59,26 +63,36 @@ export const packageScript = createRuleFactory<Options>({
59
63
  }
60
64
  allowedValues.add(q);
61
65
  }
62
- fixToEmpty = Object.prototype.hasOwnProperty.call(value, "fixValue") && value.fixValue === undefined;
66
+ fixToEmpty = Object.prototype.hasOwnProperty.call(value, "fixValue")
67
+ && value.fixValue === undefined;
63
68
  fixValue = value.fixValue;
64
69
  }
65
70
 
66
71
  const actualValue = packageJson.scripts[name];
67
72
 
68
- if (!allowedValues.has(actualValue) && !(allowEmpty === true && actualValue === undefined)) {
73
+ if (
74
+ !allowedValues.has(actualValue)
75
+ && !(allowEmpty === true && actualValue === undefined)
76
+ ) {
69
77
  let fixer;
70
78
 
71
- if (fixValue !== false && (fixValue !== undefined || fixToEmpty === true)) {
79
+ if (
80
+ fixValue !== false && (fixValue !== undefined || fixToEmpty === true)
81
+ ) {
72
82
  const q = fixValue;
73
83
  fixer = () => {
74
- mutateJson<PackageJson>(context.getPackageJsonPath(), context.host, (input) => {
75
- if (fixToEmpty && q === undefined) {
76
- delete input.scripts![name];
77
- } else {
78
- input.scripts![name] = q!;
79
- }
80
- return input;
81
- });
84
+ mutateJson<PackageJson>(
85
+ context.getPackageJsonPath(),
86
+ context.host,
87
+ (input) => {
88
+ if (fixToEmpty && q === undefined) {
89
+ delete input.scripts![name];
90
+ } else {
91
+ input.scripts![name] = q!;
92
+ }
93
+ return input;
94
+ },
95
+ );
82
96
  };
83
97
  }
84
98
 
@@ -88,8 +102,12 @@ export const packageScript = createRuleFactory<Options>({
88
102
 
89
103
  context.addError({
90
104
  file: context.getPackageJsonPath(),
91
- message: `Expected standardized script entry for '${name}'. Valid options: ${validOptionsString}`,
92
- longMessage: diff(validOptionsString + "\n", (packageJson.scripts[name] || "") + "\n"),
105
+ message:
106
+ `Expected standardized script entry for '${name}'. Valid options: ${validOptionsString}`,
107
+ longMessage: diff(
108
+ validOptionsString + "\n",
109
+ (packageJson.scripts[name] || "") + "\n",
110
+ ),
93
111
  fixer,
94
112
  });
95
113
  }
@@ -12,10 +12,10 @@ import * as r from "runtypes";
12
12
  import { createRuleFactory } from "./util/createRuleFactory.js";
13
13
 
14
14
  const Options = r.Partial({
15
- dependencies: r.Dictionary(r.String),
16
- devDependencies: r.Dictionary(r.String),
17
- peerDependencies: r.Dictionary(r.String),
18
- optionalDependencies: r.Dictionary(r.String),
15
+ dependencies: r.Dictionary(r.String.optional()),
16
+ devDependencies: r.Dictionary(r.String.optional()),
17
+ peerDependencies: r.Dictionary(r.String.optional()),
18
+ optionalDependencies: r.Dictionary(r.String.optional()),
19
19
  });
20
20
 
21
21
  type Options = r.Static<typeof Options>;
@@ -32,7 +32,8 @@ export const requireDependency = createRuleFactory({
32
32
  "peerDependencies" as const,
33
33
  "optionalDependencies" as const,
34
34
  ].forEach((type) => {
35
- if (!options[type]) {
35
+ const expectedEntries = options[type];
36
+ if (!expectedEntries) {
36
37
  return;
37
38
  }
38
39
 
@@ -42,7 +43,11 @@ export const requireDependency = createRuleFactory({
42
43
  message: `No ${type} block, cannot add required ${type}.`,
43
44
  fixer: () => {
44
45
  mutateJson<PackageJson>(packageJsonPath, context.host, (input) => {
45
- input[type] = options[type];
46
+ input[type] = Object.fromEntries(
47
+ Object.entries(expectedEntries).filter(([, v]) =>
48
+ v !== undefined
49
+ ),
50
+ ) as Record<string, string>;
46
51
  return input;
47
52
  });
48
53
  },
@@ -55,12 +60,24 @@ export const requireDependency = createRuleFactory({
55
60
  context.addError({
56
61
  file: packageJsonPath,
57
62
  message: `Expected dependency ${dep}@${version}`,
58
- longMessage: diff(`${dep}@${version}\n`, `${dep}@${packageJson[type]![dep] || "missing"}\n`)!,
63
+ longMessage: diff(
64
+ `${dep}@${version}\n`,
65
+ `${dep}@${packageJson[type]![dep] || "missing"}\n`,
66
+ )!,
59
67
  fixer: () => {
60
- mutateJson<PackageJson>(packageJsonPath, context.host, (input) => {
61
- input[type] = { ...input[type], [dep]: version };
62
- return input;
63
- });
68
+ mutateJson<PackageJson>(
69
+ packageJsonPath,
70
+ context.host,
71
+ (input) => {
72
+ if (version === undefined) {
73
+ input[type] = { ...input[type] };
74
+ delete input[type][dep];
75
+ } else {
76
+ input[type] = { ...input[type], [dep]: version };
77
+ }
78
+ return input;
79
+ },
80
+ );
64
81
  },
65
82
  });
66
83
  }
@@ -39,6 +39,7 @@ const Options = r
39
39
  return count === 1 || "Expect one of { generator, template, templateFile }";
40
40
  });
41
41
 
42
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
42
43
  export interface Options extends r.Static<typeof Options> {}
43
44
 
44
45
  export const standardTsconfig = createRuleFactory<Options>({
@@ -83,11 +84,23 @@ function getGenerator(context: Context, opts: Options) {
83
84
  } else if (opts.templateFile) {
84
85
  const { packageDir: workspacePackageDir } = context.getWorkspaceContext();
85
86
  const fullPath = path.resolve(workspacePackageDir, opts.templateFile);
86
- const template = JSON.parse(context.host.readFile(fullPath, { encoding: "utf-8" }));
87
-
88
- return makeGenerator(template, opts.excludedReferences, opts.additionalReferences, opts.tsconfigReferenceFile);
87
+ const template = JSON.parse(
88
+ context.host.readFile(fullPath, { encoding: "utf-8" }),
89
+ );
90
+
91
+ return makeGenerator(
92
+ template,
93
+ opts.excludedReferences,
94
+ opts.additionalReferences,
95
+ opts.tsconfigReferenceFile,
96
+ );
89
97
  } else if (opts.template) {
90
- return makeGenerator(opts.template, opts.excludedReferences, opts.additionalReferences, opts.tsconfigReferenceFile);
98
+ return makeGenerator(
99
+ opts.template,
100
+ opts.excludedReferences,
101
+ opts.additionalReferences,
102
+ opts.tsconfigReferenceFile,
103
+ );
91
104
  } else {
92
105
  throw new Error("Unable to make generator");
93
106
  }
@@ -98,7 +111,7 @@ function makeGenerator(
98
111
  template: any,
99
112
  excludedReferences: ReadonlyArray<string> | undefined,
100
113
  additionalReferences: ReadonlyArray<string> | undefined,
101
- tsconfigReferenceFile?: string
114
+ tsconfigReferenceFile?: string,
102
115
  ) {
103
116
  return async function generator(context: Context) {
104
117
  template = {
@@ -106,15 +119,24 @@ function makeGenerator(
106
119
  references: [],
107
120
  }; // make a copy and ensure we have a references array
108
121
 
109
- const nameToDirectory = await context.getWorkspaceContext().getPackageNameToDir();
122
+ const nameToDirectory = await context.getWorkspaceContext()
123
+ .getPackageNameToDir();
110
124
 
111
125
  const packageJson = context.getPackageJson();
112
- const deps = [...Object.keys(packageJson.dependencies || {}), ...Object.keys(packageJson.devDependencies || {})];
126
+ const deps = [
127
+ ...Object.keys(packageJson.dependencies || {}),
128
+ ...Object.keys(packageJson.devDependencies || {}),
129
+ ];
113
130
  for (const dep of deps) {
114
131
  const packageDir = nameToDirectory.get(dep);
115
- if (packageDir !== undefined && (excludedReferences === undefined || !matchesAnyGlob(dep, excludedReferences))) {
116
- const absoluteReferencePath =
117
- tsconfigReferenceFile !== undefined ? path.join(packageDir, tsconfigReferenceFile) : packageDir;
132
+ if (
133
+ packageDir !== undefined
134
+ && (excludedReferences === undefined
135
+ || !matchesAnyGlob(dep, excludedReferences))
136
+ ) {
137
+ const absoluteReferencePath = tsconfigReferenceFile !== undefined
138
+ ? path.join(packageDir, tsconfigReferenceFile)
139
+ : packageDir;
118
140
  template.references.push({
119
141
  path: path.relative(context.packageDir, absoluteReferencePath),
120
142
  });
@@ -10,7 +10,7 @@ import { diff } from "jest-diff";
10
10
 
11
11
  export function checkAlpha(
12
12
  context: Context,
13
- block: "dependencies" | "devDependencies" | "peerDependencies" | "scripts"
13
+ block: "dependencies" | "devDependencies" | "peerDependencies" | "scripts",
14
14
  ) {
15
15
  const packageJson = context.getPackageJson();
16
16
  const packagePath = context.getPackageJsonPath();
@@ -54,6 +54,9 @@ function arrayOrderCompare(a: ReadonlyArray<string>, b: ReadonlyArray<string>) {
54
54
  return true;
55
55
  }
56
56
 
57
- export function createIncorrectOrderErrorMessage(block: string, packageName: string) {
57
+ export function createIncorrectOrderErrorMessage(
58
+ block: string,
59
+ packageName: string,
60
+ ) {
58
61
  return `Incorrect order of ${block} in ${packageName}'s package.json`;
59
62
  }
@@ -2,7 +2,11 @@ import { Context, RuleEntry, RuleModule } from "@monorepolint/config";
2
2
 
3
3
  export type ValidateOptionsFn<X> = (options: unknown) => asserts options is X;
4
4
  export type RuleFactoryFn<T> = (ruleEntry: RuleEntry<T>) => RuleModule<T>;
5
- export type RuleCheckFn<O> = (context: Context, options: O, extra: { id: string }) => Promise<unknown> | unknown;
5
+ export type RuleCheckFn<O> = (
6
+ context: Context,
7
+ options: O,
8
+ extra: { id: string },
9
+ ) => Promise<unknown> | unknown;
6
10
 
7
11
  export interface RuleFactoryOptions<X> {
8
12
  name: string;
@@ -18,7 +22,7 @@ export function createRuleFactory<X>({
18
22
  validateOptions,
19
23
  printStats,
20
24
  }: RuleFactoryOptions<X>): RuleFactoryFn<X> {
21
- return function (ruleEntry) {
25
+ return function(ruleEntry) {
22
26
  const id = ruleEntry.id ?? `${name} :: ${globalId++}`;
23
27
  return {
24
28
  id,
@@ -19,7 +19,11 @@ export interface IPackageDependencyGraphNode {
19
19
  /** Service abstraction for constructing and traversing package dependency graphs. */
20
20
  export interface IPackageDependencyGraphService {
21
21
  /** Construct a graph of package dependencies. */
22
- buildDependencyGraph(packageJsonPath: string, host: Host, maxDepth?: number): IPackageDependencyGraphNode;
22
+ buildDependencyGraph(
23
+ packageJsonPath: string,
24
+ host: Host,
25
+ maxDepth?: number,
26
+ ): IPackageDependencyGraphNode;
23
27
 
24
28
  /** Traverse a package dependency graph. */
25
29
  traverse(
@@ -27,20 +31,27 @@ export interface IPackageDependencyGraphService {
27
31
  opts?: {
28
32
  /** Traverse each unique path to a given package (potentially slow). */
29
33
  traverseAllPaths?: boolean;
30
- }
31
- ): IterableIterator<IPackageDependencyGraphNode & { importPath: IPackageDependencyGraphNode[] }>;
34
+ },
35
+ ): IterableIterator<
36
+ IPackageDependencyGraphNode & { importPath: IPackageDependencyGraphNode[] }
37
+ >;
32
38
  }
33
39
 
34
40
  /** Default implementation of the package dependency graph service. */
35
- export class PackageDependencyGraphService implements IPackageDependencyGraphService {
41
+ export class PackageDependencyGraphService
42
+ implements IPackageDependencyGraphService
43
+ {
36
44
  /** Construct a graph of package dependencies and return the root node. */
37
45
  public buildDependencyGraph(
38
46
  startPackageJsonPath: string,
39
47
  host: Host,
40
- maxDepth?: number
48
+ maxDepth?: number,
41
49
  ): IPackageDependencyGraphNode {
42
50
  const nodes = new Map<string, IPackageDependencyGraphNode>();
43
- const visit = (packageJsonPath: string, currentDepth: number): IPackageDependencyGraphNode => {
51
+ const visit = (
52
+ packageJsonPath: string,
53
+ currentDepth: number,
54
+ ): IPackageDependencyGraphNode => {
44
55
  if (nodes.has(packageJsonPath)) {
45
56
  return nodes.get(packageJsonPath)!;
46
57
  }
@@ -60,14 +71,24 @@ export class PackageDependencyGraphService implements IPackageDependencyGraphSer
60
71
 
61
72
  const nextDepth = currentDepth + 1;
62
73
  if (maxDepth == null || nextDepth <= maxDepth) {
63
- const dependencies = packageJson.dependencies != null ? Object.keys(packageJson.dependencies) : [];
74
+ const dependencies = packageJson.dependencies != null
75
+ ? Object.keys(packageJson.dependencies)
76
+ : [];
64
77
  for (const dependency of dependencies) {
65
- const dependencyPackageJsonPath = resolvePackagePath(dependency, node.paths.rootDirectory);
78
+ const dependencyPackageJsonPath = resolvePackagePath(
79
+ dependency,
80
+ node.paths.rootDirectory,
81
+ );
66
82
  if (dependencyPackageJsonPath == null) {
67
- throw new Error(`Could not resolve ${dependency} from ${node.paths.rootDirectory}`);
83
+ throw new Error(
84
+ `Could not resolve ${dependency} from ${node.paths.rootDirectory}`,
85
+ );
68
86
  }
69
87
 
70
- node.dependencies.set(dependency, visit(dependencyPackageJsonPath, nextDepth));
88
+ node.dependencies.set(
89
+ dependency,
90
+ visit(dependencyPackageJsonPath, nextDepth),
91
+ );
71
92
  }
72
93
  }
73
94
 
@@ -80,14 +101,20 @@ export class PackageDependencyGraphService implements IPackageDependencyGraphSer
80
101
  /** Traverse a package dependency graph with an iterator. */
81
102
  public *traverse(
82
103
  root: IPackageDependencyGraphNode,
83
- opts = { traverseAllPaths: false }
84
- ): IterableIterator<IPackageDependencyGraphNode & { importPath: IPackageDependencyGraphNode[] }> {
104
+ opts = { traverseAllPaths: false },
105
+ ): IterableIterator<
106
+ IPackageDependencyGraphNode & { importPath: IPackageDependencyGraphNode[] }
107
+ > {
85
108
  const visited = new Set<IPackageDependencyGraphNode>();
86
109
 
87
110
  function* visit(
88
111
  node: IPackageDependencyGraphNode,
89
- importPath: IPackageDependencyGraphNode[] = []
90
- ): IterableIterator<IPackageDependencyGraphNode & { importPath: IPackageDependencyGraphNode[] }> {
112
+ importPath: IPackageDependencyGraphNode[] = [],
113
+ ): IterableIterator<
114
+ IPackageDependencyGraphNode & {
115
+ importPath: IPackageDependencyGraphNode[];
116
+ }
117
+ > {
91
118
  // Don't visit a package more than once unless explicitly asked to traverse all paths
92
119
  if (!opts.traverseAllPaths && visited.has(node)) {
93
120
  return;
@@ -0,0 +1,17 @@
1
+ import {
2
+ coverageConfigDefaults,
3
+ defaultExclude,
4
+ defineProject,
5
+ } from "vitest/config";
6
+
7
+ export default defineProject({
8
+ test: {
9
+ exclude: [...defaultExclude, "**/build/**"],
10
+ coverage: {
11
+ provider: "v8",
12
+ enabled: true,
13
+ pool: "forks",
14
+ exclude: [...coverageConfigDefaults.exclude, "vitest.config.*"],
15
+ },
16
+ },
17
+ });
package/jest.config.cjs DELETED
@@ -1,4 +0,0 @@
1
- // STOP!
2
- // WAIT!
3
- // Unless this is the version inside of "templates", you are editing a generated file.
4
- module.exports = require("../../jest.config.base");