@sarj/eslint-plugin 16.2.2 → 16.2.4
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/dist/index.cjs +17 -10
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +17 -10
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -356,7 +356,7 @@ var REQUIRE_EXPLICIT_CONTRACT_IMPLEMENTATION_DOCUMENTATION = {
|
|
|
356
356
|
autofix: "none",
|
|
357
357
|
limitations: [
|
|
358
358
|
"Only class instances whose concrete class and selected constructor parameter resolve through the TypeScript checker are checked.",
|
|
359
|
-
"Object literals, casts, any, unresolved heritage, dynamic factories, and third-party classes are excluded."
|
|
359
|
+
"Object literals, casts, any, callback-valued data properties, unresolved heritage, dynamic factories, and third-party classes are excluded."
|
|
360
360
|
],
|
|
361
361
|
examples: [
|
|
362
362
|
{
|
|
@@ -415,14 +415,20 @@ var REQUIRE_EXPLICIT_CONTRACT_IMPLEMENTATION_DOCUMENTATION = {
|
|
|
415
415
|
}
|
|
416
416
|
]
|
|
417
417
|
};
|
|
418
|
-
function
|
|
419
|
-
if (
|
|
418
|
+
function behavioralContract(checker, type) {
|
|
419
|
+
if (type.isUnion()) {
|
|
420
|
+
const substantive = type.types.filter((member) => (member.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) === 0);
|
|
421
|
+
if (substantive.length !== 1) return null;
|
|
422
|
+
return behavioralContract(checker, substantive[0]);
|
|
423
|
+
}
|
|
424
|
+
if ((type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0) return null;
|
|
420
425
|
const declaration = type.getSymbol()?.declarations?.find((item) => ts.isInterfaceDeclaration(item) || ts.isTypeAliasDeclaration(item) || ts.isClassDeclaration(item) && item.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.AbstractKeyword));
|
|
421
|
-
if (declaration === void 0) return
|
|
426
|
+
if (declaration === void 0) return null;
|
|
422
427
|
return checker.getPropertiesOfType(type).some((property) => {
|
|
428
|
+
if (!property.declarations?.some((member) => ts.isMethodSignature(member) || ts.isMethodDeclaration(member))) return false;
|
|
423
429
|
const propertyType = checker.getTypeOfSymbolAtLocation(property, declaration);
|
|
424
430
|
return propertyType.getCallSignatures().length > 0;
|
|
425
|
-
});
|
|
431
|
+
}) ? type : null;
|
|
426
432
|
}
|
|
427
433
|
function ownedClass(type) {
|
|
428
434
|
if ((type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0) return null;
|
|
@@ -450,7 +456,7 @@ function explicitlyImplements(checker, declaration, target, seen) {
|
|
|
450
456
|
unknown = true;
|
|
451
457
|
continue;
|
|
452
458
|
}
|
|
453
|
-
const relationship = explicitlyImplements(checker, inherited, target, seen);
|
|
459
|
+
const relationship = explicitlyImplements(checker, inherited, target, new Set(seen));
|
|
454
460
|
if (relationship === true) return true;
|
|
455
461
|
unknown ||= relationship === null;
|
|
456
462
|
}
|
|
@@ -489,12 +495,13 @@ var require_explicit_contract_implementation_default = createRule({
|
|
|
489
495
|
const parameter = parameters[index];
|
|
490
496
|
if (parameter === void 0) continue;
|
|
491
497
|
const parameterType = checker.getTypeOfSymbolAtLocation(parameter, tsNode);
|
|
492
|
-
|
|
493
|
-
|
|
498
|
+
const contractType = behavioralContract(checker, parameterType);
|
|
499
|
+
if (contractType === null) continue;
|
|
500
|
+
const contractSymbol = contractType.getSymbol();
|
|
494
501
|
if (contractSymbol === void 0) continue;
|
|
495
502
|
const tsArgument = services.esTreeNodeToTSNodeMap.get(argument);
|
|
496
503
|
const actualType = checker.getTypeAtLocation(tsArgument);
|
|
497
|
-
if (!checker.isTypeAssignableTo(actualType,
|
|
504
|
+
if (!checker.isTypeAssignableTo(actualType, contractType)) continue;
|
|
498
505
|
const implementation = ownedClass(actualType);
|
|
499
506
|
if (implementation === null) continue;
|
|
500
507
|
const relationship = explicitlyImplements(checker, implementation, contractSymbol, /* @__PURE__ */ new Set());
|
|
@@ -23801,7 +23808,7 @@ var RULES = {
|
|
|
23801
23808
|
};
|
|
23802
23809
|
var meta = {
|
|
23803
23810
|
name: "@sarj/eslint-plugin",
|
|
23804
|
-
version: "16.2.
|
|
23811
|
+
version: "16.2.4"
|
|
23805
23812
|
};
|
|
23806
23813
|
var APPLICATION_ONLY_RULES = [];
|
|
23807
23814
|
var LIBRARY_IMPORT_POLICY = ["error", {
|
package/dist/index.d.cts
CHANGED
|
@@ -922,7 +922,7 @@ type FlatPreset = {
|
|
|
922
922
|
declare const PLUGIN: {
|
|
923
923
|
readonly meta: {
|
|
924
924
|
readonly name: "@sarj/eslint-plugin";
|
|
925
|
-
readonly version: "16.2.
|
|
925
|
+
readonly version: "16.2.4";
|
|
926
926
|
};
|
|
927
927
|
readonly rules: {
|
|
928
928
|
readonly "require-explicit-contract-implementation": DocumentedRule<readonly [], "declareActualContract">;
|
package/dist/index.d.ts
CHANGED
|
@@ -922,7 +922,7 @@ type FlatPreset = {
|
|
|
922
922
|
declare const PLUGIN: {
|
|
923
923
|
readonly meta: {
|
|
924
924
|
readonly name: "@sarj/eslint-plugin";
|
|
925
|
-
readonly version: "16.2.
|
|
925
|
+
readonly version: "16.2.4";
|
|
926
926
|
};
|
|
927
927
|
readonly rules: {
|
|
928
928
|
readonly "require-explicit-contract-implementation": DocumentedRule<readonly [], "declareActualContract">;
|
package/dist/index.js
CHANGED
|
@@ -305,7 +305,7 @@ var REQUIRE_EXPLICIT_CONTRACT_IMPLEMENTATION_DOCUMENTATION = {
|
|
|
305
305
|
autofix: "none",
|
|
306
306
|
limitations: [
|
|
307
307
|
"Only class instances whose concrete class and selected constructor parameter resolve through the TypeScript checker are checked.",
|
|
308
|
-
"Object literals, casts, any, unresolved heritage, dynamic factories, and third-party classes are excluded."
|
|
308
|
+
"Object literals, casts, any, callback-valued data properties, unresolved heritage, dynamic factories, and third-party classes are excluded."
|
|
309
309
|
],
|
|
310
310
|
examples: [
|
|
311
311
|
{
|
|
@@ -364,14 +364,20 @@ var REQUIRE_EXPLICIT_CONTRACT_IMPLEMENTATION_DOCUMENTATION = {
|
|
|
364
364
|
}
|
|
365
365
|
]
|
|
366
366
|
};
|
|
367
|
-
function
|
|
368
|
-
if (
|
|
367
|
+
function behavioralContract(checker, type) {
|
|
368
|
+
if (type.isUnion()) {
|
|
369
|
+
const substantive = type.types.filter((member) => (member.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) === 0);
|
|
370
|
+
if (substantive.length !== 1) return null;
|
|
371
|
+
return behavioralContract(checker, substantive[0]);
|
|
372
|
+
}
|
|
373
|
+
if ((type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0) return null;
|
|
369
374
|
const declaration = type.getSymbol()?.declarations?.find((item) => ts.isInterfaceDeclaration(item) || ts.isTypeAliasDeclaration(item) || ts.isClassDeclaration(item) && item.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.AbstractKeyword));
|
|
370
|
-
if (declaration === void 0) return
|
|
375
|
+
if (declaration === void 0) return null;
|
|
371
376
|
return checker.getPropertiesOfType(type).some((property) => {
|
|
377
|
+
if (!property.declarations?.some((member) => ts.isMethodSignature(member) || ts.isMethodDeclaration(member))) return false;
|
|
372
378
|
const propertyType = checker.getTypeOfSymbolAtLocation(property, declaration);
|
|
373
379
|
return propertyType.getCallSignatures().length > 0;
|
|
374
|
-
});
|
|
380
|
+
}) ? type : null;
|
|
375
381
|
}
|
|
376
382
|
function ownedClass(type) {
|
|
377
383
|
if ((type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0) return null;
|
|
@@ -399,7 +405,7 @@ function explicitlyImplements(checker, declaration, target, seen) {
|
|
|
399
405
|
unknown = true;
|
|
400
406
|
continue;
|
|
401
407
|
}
|
|
402
|
-
const relationship = explicitlyImplements(checker, inherited, target, seen);
|
|
408
|
+
const relationship = explicitlyImplements(checker, inherited, target, new Set(seen));
|
|
403
409
|
if (relationship === true) return true;
|
|
404
410
|
unknown ||= relationship === null;
|
|
405
411
|
}
|
|
@@ -438,12 +444,13 @@ var require_explicit_contract_implementation_default = createRule({
|
|
|
438
444
|
const parameter = parameters[index];
|
|
439
445
|
if (parameter === void 0) continue;
|
|
440
446
|
const parameterType = checker.getTypeOfSymbolAtLocation(parameter, tsNode);
|
|
441
|
-
|
|
442
|
-
|
|
447
|
+
const contractType = behavioralContract(checker, parameterType);
|
|
448
|
+
if (contractType === null) continue;
|
|
449
|
+
const contractSymbol = contractType.getSymbol();
|
|
443
450
|
if (contractSymbol === void 0) continue;
|
|
444
451
|
const tsArgument = services.esTreeNodeToTSNodeMap.get(argument);
|
|
445
452
|
const actualType = checker.getTypeAtLocation(tsArgument);
|
|
446
|
-
if (!checker.isTypeAssignableTo(actualType,
|
|
453
|
+
if (!checker.isTypeAssignableTo(actualType, contractType)) continue;
|
|
447
454
|
const implementation = ownedClass(actualType);
|
|
448
455
|
if (implementation === null) continue;
|
|
449
456
|
const relationship = explicitlyImplements(checker, implementation, contractSymbol, /* @__PURE__ */ new Set());
|
|
@@ -23822,7 +23829,7 @@ var RULES = {
|
|
|
23822
23829
|
};
|
|
23823
23830
|
var meta = {
|
|
23824
23831
|
name: "@sarj/eslint-plugin",
|
|
23825
|
-
version: "16.2.
|
|
23832
|
+
version: "16.2.4"
|
|
23826
23833
|
};
|
|
23827
23834
|
var APPLICATION_ONLY_RULES = [];
|
|
23828
23835
|
var LIBRARY_IMPORT_POLICY = ["error", {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sarj/eslint-plugin",
|
|
3
|
-
"version": "16.2.
|
|
3
|
+
"version": "16.2.4",
|
|
4
4
|
"packageManager": "npm@12.1.0",
|
|
5
5
|
"description": "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
|
|
6
6
|
"type": "module",
|
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
"@eslint/js": "10.0.1",
|
|
65
65
|
"@shadcn/lint": "0.2.0",
|
|
66
66
|
"@types/node": "26.6.2",
|
|
67
|
+
"@typescript/native": "npm:typescript@7.0.2",
|
|
67
68
|
"@typescript-eslint/parser": "8.70.1",
|
|
68
69
|
"@typescript-eslint/rule-tester": "8.70.1",
|
|
69
70
|
"@typescript-eslint/utils": "8.70.1",
|
|
@@ -84,7 +85,7 @@
|
|
|
84
85
|
"eslint-plugin-unicorn": "^76.0.0",
|
|
85
86
|
"eslint-plugin-zod": "^4.14.2",
|
|
86
87
|
"tsup": "latest",
|
|
87
|
-
"typescript": "6.0.
|
|
88
|
+
"typescript": "npm:@typescript/typescript6@6.0.2",
|
|
88
89
|
"typescript-eslint": "^8.70.1",
|
|
89
90
|
"vitest": "5.0.1"
|
|
90
91
|
},
|