@sarj/eslint-plugin 8.0.0 → 9.1.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/README.md CHANGED
@@ -21,7 +21,7 @@ rename moves them.
21
21
 
22
22
  Presets: `recommended` (warn-first), `strict` (every rule at error), `style-guide` (formatting/naming subset).
23
23
 
24
- ## Renamed in 7.0.0 (breaking)
24
+ ## Renamed in 7.0.0, aliases deleted in 9.0.0 (breaking)
25
25
 
26
26
  | Old name | New name |
27
27
  | --- | --- |
@@ -30,18 +30,21 @@ Presets: `recommended` (warn-first), `strict` (every rule at error), `style-guid
30
30
  | `@sarj/strict-test-assertions` | `@sarj/prefer-whole-object-assertion` |
31
31
  | `@sarj/trailing-value-narration` | `@sarj/no-trailing-value-narration` |
32
32
 
33
- Every old name is still REGISTERED, as a deprecated alias of the same rule, so a
34
- config entry, an `eslint-disable` comment or a suppressions baseline naming it
35
- keeps working while you migrate; ESLint reports the deprecation and names the
36
- replacement. Neither preset wires an alias, so nothing double-reports. The map is
33
+ 7.0.0 kept each old name registered as a deprecated alias. 9.0.0 deletes them, so
34
+ the new names are the only names — and an old name left in a config, an
35
+ `eslint-disable` comment or a suppressions baseline now makes ESLint exit 2 with
36
+ `Could not find "@sarj/<rule>" in plugin "@sarj"` before it reads a file.
37
+
38
+ Run `sarj-lint-configs doctor` before upgrading: it reads the shipped rule ledger
39
+ and names every file holding an old name, with the replacement. The map is also
37
40
  exported for codemods:
38
41
 
39
42
  ```js
40
43
  import { renamedRules } from "@sarj/eslint-plugin";
41
44
  ```
42
45
 
43
- Migration steps, the reasoning behind each name, and why the old keys are kept
44
- rather than dropped: [`docs/rules/_renames.md`](../../docs/rules/_renames.md).
46
+ Migration steps, the reasoning behind each name, and why the aliases went:
47
+ [`docs/rules/_renames.md`](../../docs/rules/_renames.md).
45
48
 
46
49
  ## New in 4.1.0 — `no-hand-rolled-sleep`
47
50
 
package/dist/index.cjs CHANGED
@@ -8764,26 +8764,111 @@ var import_utils56 = require("@typescript-eslint/utils");
8764
8764
  var CONFIGISH_TYPE_RE = /(?:Options|Opts|Config|Configuration|Settings|Params|Props|Args|Env|Environment|Callbacks|Flags)$/;
8765
8765
  var CONFIGISH_NAME_RE = /^(?:options|opts|config|configuration|settings|params|props|args|env|environment|callbacks|flags|logger|log|clock)$/i;
8766
8766
  var HTTP_TRANSPORT_TYPE_RE = /^(?:KyInstance|AxiosInstance|Session)$/;
8767
+ var BUILTIN_CONTAINER_TYPE_RE = /^(?:Record|Map|WeakMap|Set|WeakSet|Array|ReadonlyArray|ReadonlyMap|ReadonlySet|Promise|Partial|Required|Readonly|Pick|Omit|Exclude|Extract|NonNullable|Awaited|Parameters|ReturnType|InstanceType)$/;
8767
8768
  var TRANSPORT_WRAPPER_NAME_RE = /Client$/;
8768
8769
  var ROUTER_FACTORY_NAME = "Router";
8769
8770
  var FRAMEWORK_HTTP_TYPES = /* @__PURE__ */ new Set(["Request", "Response", "NextFunction"]);
8770
8771
  var isExportedClass = (node) => node.parent.type === import_utils56.AST_NODE_TYPES.ExportNamedDeclaration || node.parent.type === import_utils56.AST_NODE_TYPES.ExportDefaultDeclaration;
8771
8772
  var qualifiedName = (name) => name.type === import_utils56.AST_NODE_TYPES.Identifier ? name.name : name.type === import_utils56.AST_NODE_TYPES.TSQualifiedName ? `${qualifiedName(name.left)}.${name.right.name}` : "";
8772
- var typeReferenceName = (annotated) => {
8773
+ var readTypeReference = (annotation) => {
8774
+ if (annotation === void 0 || annotation.type !== import_utils56.AST_NODE_TYPES.TSTypeReference) return null;
8775
+ const { typeName } = annotation;
8776
+ const rightmost = typeName.type === import_utils56.AST_NODE_TYPES.Identifier ? typeName.name : typeName.type === import_utils56.AST_NODE_TYPES.TSQualifiedName ? typeName.right.name : null;
8777
+ if (rightmost === null) return null;
8778
+ return { typeName: rightmost, display: qualifiedName(typeName) };
8779
+ };
8780
+ var namedParameterCollaborator = (annotated) => {
8773
8781
  let target = annotated;
8774
8782
  if (target.type === import_utils56.AST_NODE_TYPES.TSParameterProperty) target = target.parameter;
8775
8783
  if (target.type === import_utils56.AST_NODE_TYPES.AssignmentPattern) target = target.left;
8776
8784
  if (target.type !== import_utils56.AST_NODE_TYPES.Identifier) return null;
8777
- const annotation = target.typeAnnotation?.typeAnnotation;
8778
- if (annotation === void 0 || annotation.type !== import_utils56.AST_NODE_TYPES.TSTypeReference) {
8785
+ const reference = readTypeReference(target.typeAnnotation?.typeAnnotation);
8786
+ if (reference === null) return null;
8787
+ return { name: target.name, ...reference };
8788
+ };
8789
+ var propertySignatureTypes = (members) => {
8790
+ const types = /* @__PURE__ */ new Map();
8791
+ for (const member of members) {
8792
+ if (member.type !== import_utils56.AST_NODE_TYPES.TSPropertySignature) continue;
8793
+ if (member.computed || member.key.type !== import_utils56.AST_NODE_TYPES.Identifier) continue;
8794
+ const reference = readTypeReference(member.typeAnnotation?.typeAnnotation);
8795
+ if (reference === null) continue;
8796
+ types.set(member.key.name, reference);
8797
+ }
8798
+ return types;
8799
+ };
8800
+ var fileTypeIndex = (program) => {
8801
+ const objects = /* @__PURE__ */ new Map();
8802
+ const functionAliases = /* @__PURE__ */ new Set();
8803
+ for (const statement of program.body) {
8804
+ const declaration = statement.type === import_utils56.AST_NODE_TYPES.ExportNamedDeclaration ? statement.declaration : statement;
8805
+ if (declaration?.type === import_utils56.AST_NODE_TYPES.TSInterfaceDeclaration) {
8806
+ objects.set(declaration.id.name, propertySignatureTypes(declaration.body.body));
8807
+ continue;
8808
+ }
8809
+ if (declaration?.type !== import_utils56.AST_NODE_TYPES.TSTypeAliasDeclaration) continue;
8810
+ const aliased = declaration.typeAnnotation;
8811
+ if (aliased.type === import_utils56.AST_NODE_TYPES.TSFunctionType || aliased.type === import_utils56.AST_NODE_TYPES.TSConstructorType) {
8812
+ functionAliases.add(declaration.id.name);
8813
+ continue;
8814
+ }
8815
+ const literals = aliased.type === import_utils56.AST_NODE_TYPES.TSTypeLiteral ? [aliased] : aliased.type === import_utils56.AST_NODE_TYPES.TSIntersectionType ? aliased.types.filter((part) => part.type === import_utils56.AST_NODE_TYPES.TSTypeLiteral) : [];
8816
+ if (literals.length === 0) continue;
8817
+ const merged = /* @__PURE__ */ new Map();
8818
+ for (const literal of literals) {
8819
+ for (const [name, reference] of propertySignatureTypes(literal.members)) {
8820
+ merged.set(name, reference);
8821
+ }
8822
+ }
8823
+ objects.set(declaration.id.name, merged);
8824
+ }
8825
+ return { objects, functionAliases };
8826
+ };
8827
+ var bagMemberTypes = (annotation, declared) => {
8828
+ if (annotation.type === import_utils56.AST_NODE_TYPES.TSTypeLiteral) {
8829
+ return propertySignatureTypes(annotation.members);
8830
+ }
8831
+ if (annotation.type !== import_utils56.AST_NODE_TYPES.TSTypeReference || annotation.typeName.type !== import_utils56.AST_NODE_TYPES.Identifier) {
8779
8832
  return null;
8780
8833
  }
8781
- const { typeName } = annotation;
8782
- const rightmost = typeName.type === import_utils56.AST_NODE_TYPES.Identifier ? typeName.name : typeName.type === import_utils56.AST_NODE_TYPES.TSQualifiedName ? typeName.right.name : null;
8783
- if (rightmost === null) return null;
8784
- return { name: target.name, typeName: rightmost, display: qualifiedName(typeName) };
8834
+ return declared().objects.get(annotation.typeName.name) ?? null;
8835
+ };
8836
+ var objectPatternCollaborators = (pattern, declared) => {
8837
+ const annotation = pattern.typeAnnotation?.typeAnnotation;
8838
+ if (annotation === void 0) return [];
8839
+ const members = bagMemberTypes(annotation, declared);
8840
+ if (members === null) return [];
8841
+ const collaborators = [];
8842
+ for (const property of pattern.properties) {
8843
+ if (property.type !== import_utils56.AST_NODE_TYPES.Property || property.computed) continue;
8844
+ if (property.key.type !== import_utils56.AST_NODE_TYPES.Identifier) continue;
8845
+ const key = property.key.name;
8846
+ const bound = property.value.type === import_utils56.AST_NODE_TYPES.AssignmentPattern ? property.value.left : property.value;
8847
+ if (bound.type !== import_utils56.AST_NODE_TYPES.Identifier) continue;
8848
+ if (CONFIGISH_NAME_RE.test(key)) continue;
8849
+ const reference = members.get(key);
8850
+ if (reference === void 0) continue;
8851
+ collaborators.push({ name: bound.name, ...reference });
8852
+ }
8853
+ return collaborators;
8854
+ };
8855
+ var parameterCollaborators = (parameter, declared) => {
8856
+ let target = parameter;
8857
+ if (target.type === import_utils56.AST_NODE_TYPES.AssignmentPattern) target = target.left;
8858
+ if (target.type === import_utils56.AST_NODE_TYPES.ObjectPattern) {
8859
+ return objectPatternCollaborators(target, declared);
8860
+ }
8861
+ const named2 = namedParameterCollaborator(parameter);
8862
+ return named2 === null ? [] : [named2];
8863
+ };
8864
+ var typeParameterNames = (...declarations) => {
8865
+ const names = /* @__PURE__ */ new Set();
8866
+ for (const declaration of declarations) {
8867
+ for (const parameter of declaration?.params ?? []) names.add(parameter.name.name);
8868
+ }
8869
+ return names;
8785
8870
  };
8786
- var readConstructor = (ctor) => {
8871
+ var readConstructor = (ctor, declared, typeParameters) => {
8787
8872
  const body = ctor.value.body;
8788
8873
  const storedFrom = /* @__PURE__ */ new Set();
8789
8874
  let constructedFields = 0;
@@ -8806,13 +8891,16 @@ var readConstructor = (ctor) => {
8806
8891
  }
8807
8892
  const collaborators = [];
8808
8893
  for (const parameter of ctor.value.params) {
8809
- const reference = typeReferenceName(parameter);
8810
- if (reference === null) continue;
8811
- const stored = parameter.type === import_utils56.AST_NODE_TYPES.TSParameterProperty || storedFrom.has(reference.name);
8812
- if (!stored) continue;
8813
- if (CONFIGISH_TYPE_RE.test(reference.typeName)) continue;
8814
- if (CONFIGISH_NAME_RE.test(reference.name)) continue;
8815
- collaborators.push(reference);
8894
+ for (const reference of parameterCollaborators(parameter, declared)) {
8895
+ const stored = parameter.type === import_utils56.AST_NODE_TYPES.TSParameterProperty || storedFrom.has(reference.name);
8896
+ if (!stored) continue;
8897
+ if (CONFIGISH_TYPE_RE.test(reference.typeName)) continue;
8898
+ if (CONFIGISH_NAME_RE.test(reference.name)) continue;
8899
+ if (typeParameters.has(reference.typeName)) continue;
8900
+ if (BUILTIN_CONTAINER_TYPE_RE.test(reference.typeName)) continue;
8901
+ if (declared().functionAliases.has(reference.typeName)) continue;
8902
+ collaborators.push(reference);
8903
+ }
8816
8904
  }
8817
8905
  return { collaborators, constructedFields };
8818
8906
  };
@@ -8894,6 +8982,8 @@ var require_interface_for_injected_service_default = createRule({
8894
8982
  const { filename } = context;
8895
8983
  if (isTestFile(filename) || isStoryFile(filename) || isScriptFile(filename)) return {};
8896
8984
  if (isGeneratedFile(filename, context.sourceCode.getText())) return {};
8985
+ let declaredTypes = null;
8986
+ const objectTypes = () => declaredTypes ??= fileTypeIndex(context.sourceCode.ast);
8897
8987
  return {
8898
8988
  ClassDeclaration(node) {
8899
8989
  if (node.id === null) return;
@@ -8906,7 +8996,11 @@ var require_interface_for_injected_service_default = createRule({
8906
8996
  (member) => member.type === import_utils56.AST_NODE_TYPES.MethodDefinition && member.kind === "constructor"
8907
8997
  );
8908
8998
  if (ctor === void 0) return;
8909
- const { collaborators, constructedFields } = readConstructor(ctor);
8999
+ const { collaborators, constructedFields } = readConstructor(
9000
+ ctor,
9001
+ objectTypes,
9002
+ typeParameterNames(node.typeParameters, ctor.value.typeParameters)
9003
+ );
8910
9004
  if (collaborators.length === 0) return;
8911
9005
  if (constructedFields > collaborators.length) return;
8912
9006
  if (isFrameworkWiring(node.body)) return;
@@ -9289,29 +9383,8 @@ var rules = {
9289
9383
  };
9290
9384
  var meta = {
9291
9385
  name: "@sarj/eslint-plugin",
9292
- version: "8.0.0"
9386
+ version: "9.1.0"
9293
9387
  };
9294
- var renames = renamedRules;
9295
- var deprecatedAliases = Object.fromEntries(
9296
- Object.entries(renames).map(([from, to]) => {
9297
- const rule = rules[to];
9298
- return [
9299
- from,
9300
- {
9301
- ...rule,
9302
- meta: {
9303
- ...rule.meta,
9304
- deprecated: {
9305
- message: `Renamed to \`@sarj/${to}\`.`,
9306
- replacedBy: [{ rule: { name: `@sarj/${to}` } }],
9307
- deprecatedSince: meta.version
9308
- }
9309
- }
9310
- }
9311
- ];
9312
- })
9313
- );
9314
- var allRules = { ...rules, ...deprecatedAliases };
9315
9388
  var recommendedRules = {
9316
9389
  "@sarj/enforce-file-structure": "warn",
9317
9390
  "@sarj/no-async-callback-in-wait-for": "warn",
@@ -9418,7 +9491,7 @@ var strictRules = {
9418
9491
  };
9419
9492
  var plugin = {
9420
9493
  meta,
9421
- rules: allRules,
9494
+ rules,
9422
9495
  // Withdrawn names travel WITH the plugin so a consumer's migration script and
9423
9496
  // this repo's gates read one map, not two. See src/rules/_retired.ts.
9424
9497
  retiredRules,