@reasonabletech/eslint-config 0.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/CHANGELOG.md +9 -0
- package/README.md +89 -0
- package/dist/src/base-configs.d.ts +53 -0
- package/dist/src/base-configs.js +105 -0
- package/dist/src/custom-rules/architecture-patterns.d.ts +193 -0
- package/dist/src/custom-rules/architecture-patterns.js +344 -0
- package/dist/src/custom-rules/code-quality.d.ts +201 -0
- package/dist/src/custom-rules/code-quality.js +388 -0
- package/dist/src/custom-rules/error-handling.d.ts +103 -0
- package/dist/src/custom-rules/error-handling.js +349 -0
- package/dist/src/custom-rules/index.d.ts +79 -0
- package/dist/src/custom-rules/index.js +119 -0
- package/dist/src/custom-rules/null-undefined-checks.d.ts +20 -0
- package/dist/src/custom-rules/null-undefined-checks.js +153 -0
- package/dist/src/custom-rules/platform-conventions.d.ts +115 -0
- package/dist/src/custom-rules/platform-conventions.js +249 -0
- package/dist/src/custom-rules/test-quality.d.ts +38 -0
- package/dist/src/custom-rules/test-quality.js +68 -0
- package/dist/src/custom-rules/type-safety.d.ts +71 -0
- package/dist/src/custom-rules/type-safety.js +121 -0
- package/dist/src/custom-rules/ui-library-imports.d.ts +21 -0
- package/dist/src/custom-rules/ui-library-imports.js +31 -0
- package/dist/src/custom-rules/utils.d.ts +95 -0
- package/dist/src/custom-rules/utils.js +146 -0
- package/dist/src/index.d.ts +73 -0
- package/dist/src/index.js +80 -0
- package/dist/src/next/config.d.ts +26 -0
- package/dist/src/next/config.js +76 -0
- package/dist/src/next/ignores.d.ts +37 -0
- package/dist/src/next/ignores.js +69 -0
- package/dist/src/next/plugins.d.ts +44 -0
- package/dist/src/next/plugins.js +104 -0
- package/dist/src/next/rules.d.ts +39 -0
- package/dist/src/next/rules.js +48 -0
- package/dist/src/next/settings.d.ts +41 -0
- package/dist/src/next/settings.js +45 -0
- package/dist/src/next.d.ts +33 -0
- package/dist/src/next.js +74 -0
- package/dist/src/plugin.d.ts +48 -0
- package/dist/src/plugin.js +30 -0
- package/dist/src/react/config.d.ts +30 -0
- package/dist/src/react/config.js +40 -0
- package/dist/src/react/plugins.d.ts +24 -0
- package/dist/src/react/plugins.js +46 -0
- package/dist/src/react/rules.d.ts +30 -0
- package/dist/src/react/rules.js +35 -0
- package/dist/src/react.d.ts +27 -0
- package/dist/src/react.js +35 -0
- package/dist/src/shared/parser-options.d.ts +3 -0
- package/dist/src/shared/parser-options.js +19 -0
- package/dist/src/shared/plugin-utils.d.ts +8 -0
- package/dist/src/shared/plugin-utils.js +23 -0
- package/dist/src/shared/react-rules.d.ts +97 -0
- package/dist/src/shared/react-rules.js +126 -0
- package/dist/src/shared/strict-rules.d.ts +27 -0
- package/dist/src/shared/strict-rules.js +54 -0
- package/dist/src/shared-ignores.d.ts +15 -0
- package/dist/src/shared-ignores.js +68 -0
- package/dist/src/shared-rules.d.ts +29 -0
- package/dist/src/shared-rules.js +163 -0
- package/package.json +122 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type safety rule definitions for ReasonableTech projects
|
|
3
|
+
*
|
|
4
|
+
* These rules prevent type system bypasses and enforce safe type handling
|
|
5
|
+
* patterns, particularly around Result types and type assertions.
|
|
6
|
+
*/
|
|
7
|
+
import { AST_NODE_TYPES, ESLintUtils, } from "@typescript-eslint/utils";
|
|
8
|
+
/**
|
|
9
|
+
* Custom ESLint rule that prevents `as any` and `<any>` type casts
|
|
10
|
+
*
|
|
11
|
+
* This rule detects all forms of casting to `any`, including:
|
|
12
|
+
* - `expr as any`
|
|
13
|
+
* - `<any>expr`
|
|
14
|
+
* - Double casts through any: `(expr as any) as T`
|
|
15
|
+
*
|
|
16
|
+
* Each variant produces a distinct, descriptive error message rather than the
|
|
17
|
+
* generic "no-restricted-syntax" label that the previous AST-selector approach
|
|
18
|
+
* showed in editors.
|
|
19
|
+
*/
|
|
20
|
+
export const noAsAnyRule = ESLintUtils.RuleCreator(() => "docs/standards/typescript-standards.md")({
|
|
21
|
+
name: "no-as-any",
|
|
22
|
+
meta: {
|
|
23
|
+
type: "problem",
|
|
24
|
+
docs: {
|
|
25
|
+
description: "Prevents 'as any' and '<any>' type casts that bypass TypeScript's type checking",
|
|
26
|
+
},
|
|
27
|
+
messages: {
|
|
28
|
+
asAny: "Never use 'as any' casts. Use proper type assertions or type guards instead.",
|
|
29
|
+
angleAny: "Never use '<any>' casts. Use proper type assertions or type guards instead.",
|
|
30
|
+
doubleCast: "Never use double casts through 'as any'. Use proper type guards instead.",
|
|
31
|
+
},
|
|
32
|
+
schema: [],
|
|
33
|
+
},
|
|
34
|
+
defaultOptions: [],
|
|
35
|
+
create(context) {
|
|
36
|
+
/**
|
|
37
|
+
* Checks whether a TSAnyKeyword is a direct child of a TSAsExpression
|
|
38
|
+
* and, if so, whether the cast is part of a double-cast pattern.
|
|
39
|
+
* @param node The TSAsExpression node to check
|
|
40
|
+
*/
|
|
41
|
+
function checkAsExpression(node) {
|
|
42
|
+
if (node.typeAnnotation.type !== AST_NODE_TYPES.TSAnyKeyword) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
// Double-cast pattern: (expr as any) as T — the inner `as any` lives
|
|
46
|
+
// inside an outer TSAsExpression.
|
|
47
|
+
const parent = node.parent;
|
|
48
|
+
if (parent.type === AST_NODE_TYPES.TSAsExpression &&
|
|
49
|
+
parent.expression === node) {
|
|
50
|
+
context.report({ node: node.typeAnnotation, messageId: "doubleCast" });
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
context.report({ node: node.typeAnnotation, messageId: "asAny" });
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Checks whether a TSTypeAssertion (angle-bracket syntax) casts to any.
|
|
57
|
+
* @param node The TSTypeAssertion node to check
|
|
58
|
+
*/
|
|
59
|
+
function checkTypeAssertion(node) {
|
|
60
|
+
if (node.typeAnnotation.type !== AST_NODE_TYPES.TSAnyKeyword) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
context.report({ node: node.typeAnnotation, messageId: "angleAny" });
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
TSAsExpression: checkAsExpression,
|
|
67
|
+
TSTypeAssertion: checkTypeAssertion,
|
|
68
|
+
};
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
/**
|
|
72
|
+
* Creates rules that prevent `as any` type casts
|
|
73
|
+
*
|
|
74
|
+
* These rules block the use of `as any` type assertions, which bypass
|
|
75
|
+
* TypeScript's type checking and create type safety holes.
|
|
76
|
+
*
|
|
77
|
+
* ❌ FORBIDDEN:
|
|
78
|
+
* ```typescript
|
|
79
|
+
* const data = response as any; // Bypasses type checking
|
|
80
|
+
* const x = (response as any) as User; // Double cast through any
|
|
81
|
+
* ```
|
|
82
|
+
*
|
|
83
|
+
* ✅ CORRECT:
|
|
84
|
+
* ```typescript
|
|
85
|
+
* const data = parseResponse(response); // Proper typed parsing
|
|
86
|
+
* const user = data.result.user; // Type-safe access
|
|
87
|
+
* ```
|
|
88
|
+
* @param _options Configuration options for type safety rules (reserved for future use)
|
|
89
|
+
* @returns ESLint rules that prevent `as any` casts
|
|
90
|
+
*/
|
|
91
|
+
export function createNoAnyRules(_options = {}) {
|
|
92
|
+
return {
|
|
93
|
+
"@typescript-eslint/no-explicit-any": "error",
|
|
94
|
+
"@reasonabletech/no-as-any": "error",
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Creates a complete set of type safety rules
|
|
99
|
+
*
|
|
100
|
+
* This is the main function that combines all type safety rules
|
|
101
|
+
* into a single configuration object.
|
|
102
|
+
* @param options Configuration options for type safety rules
|
|
103
|
+
* @returns Complete set of type safety ESLint rules
|
|
104
|
+
*/
|
|
105
|
+
export function createTypeSafetyRules(options = {}) {
|
|
106
|
+
return createNoAnyRules(options);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Preset for Platform-specific type safety rules
|
|
110
|
+
*
|
|
111
|
+
* This preset provides all type safety rules configured specifically
|
|
112
|
+
* for platform project conventions and documentation structure.
|
|
113
|
+
* @returns ESLint rules configured for platform projects
|
|
114
|
+
*/
|
|
115
|
+
export function createPlatformTypeSafetyRules() {
|
|
116
|
+
return createTypeSafetyRules({
|
|
117
|
+
docBaseUrl: "docs/standards/typescript-standards.md",
|
|
118
|
+
allowInTests: false,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=type-safety.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Linter } from "eslint";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration options for UI library import boundary rules.
|
|
4
|
+
*/
|
|
5
|
+
export interface UILibraryImportRuleOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Whether to enforce subpath-only imports for `@lovelace-ai/ui`.
|
|
8
|
+
* @default true
|
|
9
|
+
*/
|
|
10
|
+
discourageUILibraryBarrelImports?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Creates rules that enforce subpath imports for the configured UI library.
|
|
14
|
+
*
|
|
15
|
+
* This enforces separation of responsibilities for shared UI code by preventing
|
|
16
|
+
* broad barrel imports from the package root.
|
|
17
|
+
* @param options Configuration for UI library import boundaries
|
|
18
|
+
* @returns ESLint rules for UI import boundaries
|
|
19
|
+
*/
|
|
20
|
+
export declare function createUILibraryImportRules(options?: UILibraryImportRuleOptions): Linter.RulesRecord;
|
|
21
|
+
//# sourceMappingURL=ui-library-imports.d.ts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const DEFAULT_UI_LIBRARY_OPTIONS = {
|
|
2
|
+
discourageUILibraryBarrelImports: true,
|
|
3
|
+
};
|
|
4
|
+
const LOVELACE_UI_PACKAGE_NAME = "@lovelace-ai/ui";
|
|
5
|
+
function escapeSelectorLiteral(value) {
|
|
6
|
+
return value.replaceAll("\\", "\\\\").replaceAll("'", "\\'");
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Creates rules that enforce subpath imports for the configured UI library.
|
|
10
|
+
*
|
|
11
|
+
* This enforces separation of responsibilities for shared UI code by preventing
|
|
12
|
+
* broad barrel imports from the package root.
|
|
13
|
+
* @param options Configuration for UI library import boundaries
|
|
14
|
+
* @returns ESLint rules for UI import boundaries
|
|
15
|
+
*/
|
|
16
|
+
export function createUILibraryImportRules(options = {}) {
|
|
17
|
+
const config = { ...DEFAULT_UI_LIBRARY_OPTIONS, ...options };
|
|
18
|
+
if (!config.discourageUILibraryBarrelImports) {
|
|
19
|
+
return {};
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
"no-restricted-syntax": [
|
|
23
|
+
"error",
|
|
24
|
+
{
|
|
25
|
+
selector: `ImportDeclaration[source.value='${escapeSelectorLiteral(LOVELACE_UI_PACKAGE_NAME)}'] ImportSpecifier`,
|
|
26
|
+
message: `❌ FORBIDDEN: Never use barrel imports from ${LOVELACE_UI_PACKAGE_NAME}. Use default imports from specific subpaths instead. Example: import Button from "${LOVELACE_UI_PACKAGE_NAME}/button";`,
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=ui-library-imports.js.map
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for custom ESLint rules
|
|
3
|
+
*
|
|
4
|
+
* These utilities help with rule configuration, AST selectors,
|
|
5
|
+
* and other common patterns used across custom rules.
|
|
6
|
+
*/
|
|
7
|
+
import type { Linter } from "eslint";
|
|
8
|
+
/**
|
|
9
|
+
* Base configuration interface for all custom rules
|
|
10
|
+
*/
|
|
11
|
+
export interface BaseRuleOptions {
|
|
12
|
+
/** Base URL for documentation references */
|
|
13
|
+
docBaseUrl?: string;
|
|
14
|
+
/** Whether to enable this rule set (default: true) */
|
|
15
|
+
enabled?: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Merges rule configurations, handling the no-restricted-syntax rule specially
|
|
19
|
+
*
|
|
20
|
+
* Since multiple rule creators may want to add patterns to no-restricted-syntax,
|
|
21
|
+
* this function properly merges them into a single rule configuration.
|
|
22
|
+
* @param ruleConfigs Multiple ESLint rule configuration objects to merge
|
|
23
|
+
* @returns Merged ESLint rule configuration
|
|
24
|
+
*/
|
|
25
|
+
export declare function mergeRuleConfigurations(...ruleConfigs: Linter.RulesRecord[]): Linter.RulesRecord;
|
|
26
|
+
/**
|
|
27
|
+
* Creates a rule configuration that can be conditionally enabled
|
|
28
|
+
* @param ruleFactory Function that creates the rules to conditionally apply
|
|
29
|
+
* @param options Options that determine whether to apply the rules
|
|
30
|
+
* @returns ESLint rules or empty object based on conditions
|
|
31
|
+
*/
|
|
32
|
+
export declare function createConditionalRules(ruleFactory: () => Linter.RulesRecord, options: BaseRuleOptions): Linter.RulesRecord;
|
|
33
|
+
/**
|
|
34
|
+
* Common AST selector patterns for TypeScript constructs
|
|
35
|
+
*/
|
|
36
|
+
export declare const AST_SELECTORS: {
|
|
37
|
+
readonly ERROR_MESSAGE_ACCESS: "[callee.object.property.name='message']";
|
|
38
|
+
readonly EXPORTED_TYPE_ALIAS: "ExportNamedDeclaration > TSTypeAliasDeclaration";
|
|
39
|
+
readonly TYPE_REFERENCE: "TSTypeReference";
|
|
40
|
+
readonly UNION_TYPE_WITH_LITERALS: "TSUnionType:has(TSLiteralType)";
|
|
41
|
+
readonly STRING_INCLUDES: "[callee.property.name='includes']";
|
|
42
|
+
readonly STRING_STARTS_WITH: "[callee.property.name='startsWith']";
|
|
43
|
+
readonly STRING_ENDS_WITH: "[callee.property.name='endsWith']";
|
|
44
|
+
readonly REGEX_MATCH: "[callee.property.name='match']";
|
|
45
|
+
readonly REGEX_TEST: "[callee.property.name='test']";
|
|
46
|
+
readonly STRICT_EQUALITY: "BinaryExpression[operator='===']";
|
|
47
|
+
readonly LOOSE_EQUALITY: "BinaryExpression[operator='==']";
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Creates an AST selector for exported type aliases matching a pattern
|
|
51
|
+
* @param namePattern Regular expression pattern for type names
|
|
52
|
+
* @returns AST selector string for matching exported types
|
|
53
|
+
*/
|
|
54
|
+
export declare function createExportedTypeSelector(namePattern: string): string;
|
|
55
|
+
/**
|
|
56
|
+
* Creates an AST selector for type references with specific type names
|
|
57
|
+
* @param typeName Name of the type to select references for
|
|
58
|
+
* @returns AST selector string for type references
|
|
59
|
+
*/
|
|
60
|
+
export declare function createTypeReferenceSelector(typeName: string): string;
|
|
61
|
+
/**
|
|
62
|
+
* Creates an AST selector for Result type inline unions
|
|
63
|
+
* @param resultTypeName Name of the Result type to check
|
|
64
|
+
* @returns AST selector string for inline unions in Result types
|
|
65
|
+
*/
|
|
66
|
+
export declare function createResultInlineUnionSelector(resultTypeName?: string): string;
|
|
67
|
+
/**
|
|
68
|
+
* Creates an AST selector for Promise<Result<T, E>> inline unions
|
|
69
|
+
* @param resultTypeName Name of the Result type to check within Promise
|
|
70
|
+
* @returns AST selector string for inline unions in Promise<Result> types
|
|
71
|
+
*/
|
|
72
|
+
export declare function createPromiseResultInlineUnionSelector(resultTypeName?: string): string;
|
|
73
|
+
/**
|
|
74
|
+
* Standard error messages for common violations
|
|
75
|
+
*/
|
|
76
|
+
export declare const ERROR_MESSAGES: {
|
|
77
|
+
readonly NO_ERROR_MESSAGE_PARSING: "❌ FORBIDDEN: Never parse error messages. Use error.code, error.status, or instanceof checks instead.";
|
|
78
|
+
readonly NO_INLINE_ERROR_UNIONS: "❌ FORBIDDEN: Never use inline error unions. Extract to a documented named type.";
|
|
79
|
+
readonly REQUIRE_ERROR_TYPE_DOCS: "❌ REQUIRED: All error types must have comprehensive JSDoc documentation.";
|
|
80
|
+
readonly FOLLOW_NAMING_CONVENTION: "❌ REQUIRED: Follow established naming conventions for error types and codes.";
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Creates a documentation reference URL
|
|
84
|
+
* @param baseUrl Base URL for the documentation
|
|
85
|
+
* @param section Optional section anchor to append
|
|
86
|
+
* @returns Complete documentation URL with optional section
|
|
87
|
+
*/
|
|
88
|
+
export declare function createDocReference(baseUrl: string, section?: string): string;
|
|
89
|
+
/**
|
|
90
|
+
* Type guard to check if a rule config is enabled
|
|
91
|
+
* @param ruleConfig ESLint rule configuration entry
|
|
92
|
+
* @returns True if the rule is enabled, false otherwise
|
|
93
|
+
*/
|
|
94
|
+
export declare function isRuleEnabled(ruleConfig: Linter.RuleEntry | undefined): boolean;
|
|
95
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for custom ESLint rules
|
|
3
|
+
*
|
|
4
|
+
* These utilities help with rule configuration, AST selectors,
|
|
5
|
+
* and other common patterns used across custom rules.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Merges rule configurations, handling the no-restricted-syntax rule specially
|
|
9
|
+
*
|
|
10
|
+
* Since multiple rule creators may want to add patterns to no-restricted-syntax,
|
|
11
|
+
* this function properly merges them into a single rule configuration.
|
|
12
|
+
* @param ruleConfigs Multiple ESLint rule configuration objects to merge
|
|
13
|
+
* @returns Merged ESLint rule configuration
|
|
14
|
+
*/
|
|
15
|
+
export function mergeRuleConfigurations(...ruleConfigs) {
|
|
16
|
+
const merged = {};
|
|
17
|
+
const restrictedSyntaxPatterns = [];
|
|
18
|
+
let highestSeverity = "warn";
|
|
19
|
+
for (const config of ruleConfigs) {
|
|
20
|
+
for (const [ruleName, ruleConfig] of Object.entries(config)) {
|
|
21
|
+
if (ruleName === "no-restricted-syntax" && Array.isArray(ruleConfig)) {
|
|
22
|
+
// Extract patterns from no-restricted-syntax rules
|
|
23
|
+
const [level, ...patterns] = ruleConfig;
|
|
24
|
+
if (level === "error" || level === "warn") {
|
|
25
|
+
if (level === "error") {
|
|
26
|
+
highestSeverity = "error";
|
|
27
|
+
}
|
|
28
|
+
restrictedSyntaxPatterns.push(...patterns);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
// For other rules, last one wins (allows overrides)
|
|
33
|
+
merged[ruleName] = ruleConfig;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Deduplicate patterns by selector (last occurrence wins for override semantics).
|
|
38
|
+
// ESLint 9.x rejects configs with duplicate no-restricted-syntax selectors.
|
|
39
|
+
const deduplicatedPatterns = [
|
|
40
|
+
...new Map(restrictedSyntaxPatterns.map((p) => [p.selector, p])).values(),
|
|
41
|
+
];
|
|
42
|
+
// Add the merged no-restricted-syntax rule if we have patterns
|
|
43
|
+
if (deduplicatedPatterns.length > 0) {
|
|
44
|
+
merged["no-restricted-syntax"] = [highestSeverity, ...deduplicatedPatterns];
|
|
45
|
+
}
|
|
46
|
+
return merged;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Creates a rule configuration that can be conditionally enabled
|
|
50
|
+
* @param ruleFactory Function that creates the rules to conditionally apply
|
|
51
|
+
* @param options Options that determine whether to apply the rules
|
|
52
|
+
* @returns ESLint rules or empty object based on conditions
|
|
53
|
+
*/
|
|
54
|
+
export function createConditionalRules(ruleFactory, options) {
|
|
55
|
+
if (options.enabled === false) {
|
|
56
|
+
return {};
|
|
57
|
+
}
|
|
58
|
+
return ruleFactory();
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Common AST selector patterns for TypeScript constructs
|
|
62
|
+
*/
|
|
63
|
+
export const AST_SELECTORS = {
|
|
64
|
+
// Error-related selectors
|
|
65
|
+
ERROR_MESSAGE_ACCESS: "[callee.object.property.name='message']",
|
|
66
|
+
EXPORTED_TYPE_ALIAS: "ExportNamedDeclaration > TSTypeAliasDeclaration",
|
|
67
|
+
TYPE_REFERENCE: "TSTypeReference",
|
|
68
|
+
UNION_TYPE_WITH_LITERALS: "TSUnionType:has(TSLiteralType)",
|
|
69
|
+
// Method call selectors
|
|
70
|
+
STRING_INCLUDES: "[callee.property.name='includes']",
|
|
71
|
+
STRING_STARTS_WITH: "[callee.property.name='startsWith']",
|
|
72
|
+
STRING_ENDS_WITH: "[callee.property.name='endsWith']",
|
|
73
|
+
REGEX_MATCH: "[callee.property.name='match']",
|
|
74
|
+
REGEX_TEST: "[callee.property.name='test']",
|
|
75
|
+
// Binary operation selectors
|
|
76
|
+
STRICT_EQUALITY: "BinaryExpression[operator='===']",
|
|
77
|
+
LOOSE_EQUALITY: "BinaryExpression[operator='==']",
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Creates an AST selector for exported type aliases matching a pattern
|
|
81
|
+
* @param namePattern Regular expression pattern for type names
|
|
82
|
+
* @returns AST selector string for matching exported types
|
|
83
|
+
*/
|
|
84
|
+
export function createExportedTypeSelector(namePattern) {
|
|
85
|
+
return `${AST_SELECTORS.EXPORTED_TYPE_ALIAS}[id.name=/${namePattern}/]`;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Creates an AST selector for type references with specific type names
|
|
89
|
+
* @param typeName Name of the type to select references for
|
|
90
|
+
* @returns AST selector string for type references
|
|
91
|
+
*/
|
|
92
|
+
export function createTypeReferenceSelector(typeName) {
|
|
93
|
+
return `${AST_SELECTORS.TYPE_REFERENCE}[typeName.name='${typeName}']`;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Creates an AST selector for Result type inline unions
|
|
97
|
+
* @param resultTypeName Name of the Result type to check
|
|
98
|
+
* @returns AST selector string for inline unions in Result types
|
|
99
|
+
*/
|
|
100
|
+
export function createResultInlineUnionSelector(resultTypeName = "Result") {
|
|
101
|
+
return `${createTypeReferenceSelector(resultTypeName)} ${AST_SELECTORS.UNION_TYPE_WITH_LITERALS}`;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Creates an AST selector for Promise<Result<T, E>> inline unions
|
|
105
|
+
* @param resultTypeName Name of the Result type to check within Promise
|
|
106
|
+
* @returns AST selector string for inline unions in Promise<Result> types
|
|
107
|
+
*/
|
|
108
|
+
export function createPromiseResultInlineUnionSelector(resultTypeName = "Result") {
|
|
109
|
+
return `${createTypeReferenceSelector("Promise")} TSTypeParameterInstantiation ${createTypeReferenceSelector(resultTypeName)} ${AST_SELECTORS.UNION_TYPE_WITH_LITERALS}`;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Standard error messages for common violations
|
|
113
|
+
*/
|
|
114
|
+
export const ERROR_MESSAGES = {
|
|
115
|
+
NO_ERROR_MESSAGE_PARSING: "❌ FORBIDDEN: Never parse error messages. Use error.code, error.status, or instanceof checks instead.",
|
|
116
|
+
NO_INLINE_ERROR_UNIONS: "❌ FORBIDDEN: Never use inline error unions. Extract to a documented named type.",
|
|
117
|
+
REQUIRE_ERROR_TYPE_DOCS: "❌ REQUIRED: All error types must have comprehensive JSDoc documentation.",
|
|
118
|
+
FOLLOW_NAMING_CONVENTION: "❌ REQUIRED: Follow established naming conventions for error types and codes.",
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* Creates a documentation reference URL
|
|
122
|
+
* @param baseUrl Base URL for the documentation
|
|
123
|
+
* @param section Optional section anchor to append
|
|
124
|
+
* @returns Complete documentation URL with optional section
|
|
125
|
+
*/
|
|
126
|
+
export function createDocReference(baseUrl, section) {
|
|
127
|
+
if (section !== undefined && section !== "") {
|
|
128
|
+
return `${baseUrl}#${section}`;
|
|
129
|
+
}
|
|
130
|
+
return baseUrl;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Type guard to check if a rule config is enabled
|
|
134
|
+
* @param ruleConfig ESLint rule configuration entry
|
|
135
|
+
* @returns True if the rule is enabled, false otherwise
|
|
136
|
+
*/
|
|
137
|
+
export function isRuleEnabled(ruleConfig) {
|
|
138
|
+
if (ruleConfig === undefined) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
if (Array.isArray(ruleConfig)) {
|
|
142
|
+
return ruleConfig[0] === "error" || ruleConfig[0] === "warn";
|
|
143
|
+
}
|
|
144
|
+
return ruleConfig === "error" || ruleConfig === "warn";
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { Linter } from "eslint";
|
|
2
|
+
export { sharedReactComponentRules } from "./shared/react-rules.js";
|
|
3
|
+
/**
|
|
4
|
+
* Creates a comprehensive type-aware ESLint configuration for TypeScript projects.
|
|
5
|
+
*
|
|
6
|
+
* This is the **mandatory base configuration** for all projects.
|
|
7
|
+
* It provides essential TypeScript linting rules that ensure code quality, type safety,
|
|
8
|
+
* and consistency across the entire monorepo.
|
|
9
|
+
*
|
|
10
|
+
* ## Key Features
|
|
11
|
+
*
|
|
12
|
+
* - **Type-aware analysis**: Leverages TypeScript's type checker for advanced linting
|
|
13
|
+
* - **Strict type safety**: Enforces patterns that prevent runtime type errors
|
|
14
|
+
* - **AI code compatibility**: Optimized for AI-generated code validation
|
|
15
|
+
* - **Monorepo consistency**: Standardized rules across all packages
|
|
16
|
+
* - **Performance optimized**: Configured for fast incremental type checking
|
|
17
|
+
*
|
|
18
|
+
* ## Usage Patterns
|
|
19
|
+
*
|
|
20
|
+
* **Standalone TypeScript projects:**
|
|
21
|
+
* ```typescript
|
|
22
|
+
* import { createTypeAwareConfig } from "@reasonabletech/eslint-config";
|
|
23
|
+
* export default createTypeAwareConfig(import.meta.dirname);
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* **Extended configurations:**
|
|
27
|
+
* ```typescript
|
|
28
|
+
* import { createTypeAwareConfig } from "@reasonabletech/eslint-config";
|
|
29
|
+
* import { createTypeAwareReactConfig } from "@reasonabletech/eslint-config/react";
|
|
30
|
+
*
|
|
31
|
+
* // React config automatically extends this base config
|
|
32
|
+
* export default createTypeAwareReactConfig(import.meta.dirname);
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* ## Configuration Details
|
|
36
|
+
*
|
|
37
|
+
* The configuration includes:
|
|
38
|
+
* - TypeScript ESLint parser with type information
|
|
39
|
+
* - Recommended TypeScript ESLint rules
|
|
40
|
+
* - JSDoc documentation requirements
|
|
41
|
+
* - Import/export validation
|
|
42
|
+
* - Strict null checks and type assertions
|
|
43
|
+
* - Performance-optimized type checking
|
|
44
|
+
* @param projectDir - The absolute path to the directory containing the TypeScript project.
|
|
45
|
+
* This is used for TypeScript's project service and type checking.
|
|
46
|
+
* @returns A complete ESLint configuration array optimized for TypeScript development
|
|
47
|
+
* @see {@link https://typescript-eslint.io/getting-started | TypeScript ESLint Documentation}
|
|
48
|
+
* @see {@link ../../README.md | Package README} for complete usage examples
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* // Basic usage in eslint.config.mjs
|
|
52
|
+
* import { createTypeAwareConfig } from "@reasonabletech/eslint-config";
|
|
53
|
+
*
|
|
54
|
+
* export default createTypeAwareConfig(import.meta.dirname);
|
|
55
|
+
* ```
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* // Extending with custom rules
|
|
59
|
+
* import { createTypeAwareConfig } from "@reasonabletech/eslint-config";
|
|
60
|
+
*
|
|
61
|
+
* export default [
|
|
62
|
+
* ...createTypeAwareConfig(import.meta.dirname),
|
|
63
|
+
* {
|
|
64
|
+
* rules: {
|
|
65
|
+
* // Project-specific overrides
|
|
66
|
+
* "@typescript-eslint/no-unused-vars": "warn",
|
|
67
|
+
* },
|
|
68
|
+
* },
|
|
69
|
+
* ];
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export declare function createTypeAwareConfig(projectDir: string): Linter.Config[];
|
|
73
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { createTypeAwareBaseConfig } from "./base-configs.js";
|
|
3
|
+
// Re-export shared React component rules for use in root config
|
|
4
|
+
export { sharedReactComponentRules } from "./shared/react-rules.js";
|
|
5
|
+
/**
|
|
6
|
+
* Creates a comprehensive type-aware ESLint configuration for TypeScript projects.
|
|
7
|
+
*
|
|
8
|
+
* This is the **mandatory base configuration** for all projects.
|
|
9
|
+
* It provides essential TypeScript linting rules that ensure code quality, type safety,
|
|
10
|
+
* and consistency across the entire monorepo.
|
|
11
|
+
*
|
|
12
|
+
* ## Key Features
|
|
13
|
+
*
|
|
14
|
+
* - **Type-aware analysis**: Leverages TypeScript's type checker for advanced linting
|
|
15
|
+
* - **Strict type safety**: Enforces patterns that prevent runtime type errors
|
|
16
|
+
* - **AI code compatibility**: Optimized for AI-generated code validation
|
|
17
|
+
* - **Monorepo consistency**: Standardized rules across all packages
|
|
18
|
+
* - **Performance optimized**: Configured for fast incremental type checking
|
|
19
|
+
*
|
|
20
|
+
* ## Usage Patterns
|
|
21
|
+
*
|
|
22
|
+
* **Standalone TypeScript projects:**
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { createTypeAwareConfig } from "@reasonabletech/eslint-config";
|
|
25
|
+
* export default createTypeAwareConfig(import.meta.dirname);
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* **Extended configurations:**
|
|
29
|
+
* ```typescript
|
|
30
|
+
* import { createTypeAwareConfig } from "@reasonabletech/eslint-config";
|
|
31
|
+
* import { createTypeAwareReactConfig } from "@reasonabletech/eslint-config/react";
|
|
32
|
+
*
|
|
33
|
+
* // React config automatically extends this base config
|
|
34
|
+
* export default createTypeAwareReactConfig(import.meta.dirname);
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* ## Configuration Details
|
|
38
|
+
*
|
|
39
|
+
* The configuration includes:
|
|
40
|
+
* - TypeScript ESLint parser with type information
|
|
41
|
+
* - Recommended TypeScript ESLint rules
|
|
42
|
+
* - JSDoc documentation requirements
|
|
43
|
+
* - Import/export validation
|
|
44
|
+
* - Strict null checks and type assertions
|
|
45
|
+
* - Performance-optimized type checking
|
|
46
|
+
* @param projectDir - The absolute path to the directory containing the TypeScript project.
|
|
47
|
+
* This is used for TypeScript's project service and type checking.
|
|
48
|
+
* @returns A complete ESLint configuration array optimized for TypeScript development
|
|
49
|
+
* @see {@link https://typescript-eslint.io/getting-started | TypeScript ESLint Documentation}
|
|
50
|
+
* @see {@link ../../README.md | Package README} for complete usage examples
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* // Basic usage in eslint.config.mjs
|
|
54
|
+
* import { createTypeAwareConfig } from "@reasonabletech/eslint-config";
|
|
55
|
+
*
|
|
56
|
+
* export default createTypeAwareConfig(import.meta.dirname);
|
|
57
|
+
* ```
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* // Extending with custom rules
|
|
61
|
+
* import { createTypeAwareConfig } from "@reasonabletech/eslint-config";
|
|
62
|
+
*
|
|
63
|
+
* export default [
|
|
64
|
+
* ...createTypeAwareConfig(import.meta.dirname),
|
|
65
|
+
* {
|
|
66
|
+
* rules: {
|
|
67
|
+
* // Project-specific overrides
|
|
68
|
+
* "@typescript-eslint/no-unused-vars": "warn",
|
|
69
|
+
* },
|
|
70
|
+
* },
|
|
71
|
+
* ];
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export function createTypeAwareConfig(projectDir) {
|
|
75
|
+
const baseDir = path.isAbsolute(projectDir)
|
|
76
|
+
? projectDir
|
|
77
|
+
: path.resolve(projectDir);
|
|
78
|
+
return createTypeAwareBaseConfig(baseDir);
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Linter } from "eslint";
|
|
2
|
+
/**
|
|
3
|
+
* Complete Next.js ESLint configuration builder.
|
|
4
|
+
*
|
|
5
|
+
* This module orchestrates all Next.js-specific ESLint configurations
|
|
6
|
+
* including ignores, plugins, rules, and settings into a coherent
|
|
7
|
+
* configuration array.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Creates the complete Next.js ESLint configuration.
|
|
11
|
+
*
|
|
12
|
+
* This function combines all Next.js-specific configurations and handles
|
|
13
|
+
* the complex logic of plugin availability, fallbacks, and conditional
|
|
14
|
+
* rule application.
|
|
15
|
+
*
|
|
16
|
+
* Configuration includes:
|
|
17
|
+
* - Next.js ESLint plugins (core-web-vitals, TypeScript)
|
|
18
|
+
* - TypeScript parser configuration for type-aware rules
|
|
19
|
+
* - React and React Hooks plugin setup
|
|
20
|
+
* - Next.js-optimized rules using shared React patterns
|
|
21
|
+
* - File-specific rule overrides for React components
|
|
22
|
+
* @param projectDir - The root directory of the Next.js project
|
|
23
|
+
* @returns Array of ESLint configurations for Next.js projects
|
|
24
|
+
*/
|
|
25
|
+
export declare const createNextjsConfigs: (projectDir: string) => Linter.Config[];
|
|
26
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { createNextjsIgnoreConfig } from "./ignores.js";
|
|
3
|
+
import { createNextjsRulesConfig } from "./rules.js";
|
|
4
|
+
import { createNextjsSettingsConfig } from "./settings.js";
|
|
5
|
+
import { createSharedReactComponentFileConfig } from "../shared/react-rules.js";
|
|
6
|
+
import { createStrictBooleanExpressionsConfig } from "../shared/strict-rules.js";
|
|
7
|
+
import { loadNextjsConfigs } from "./plugins.js";
|
|
8
|
+
/**
|
|
9
|
+
* Complete Next.js ESLint configuration builder.
|
|
10
|
+
*
|
|
11
|
+
* This module orchestrates all Next.js-specific ESLint configurations
|
|
12
|
+
* including ignores, plugins, rules, and settings into a coherent
|
|
13
|
+
* configuration array.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Creates the complete Next.js ESLint configuration.
|
|
17
|
+
*
|
|
18
|
+
* This function combines all Next.js-specific configurations and handles
|
|
19
|
+
* the complex logic of plugin availability, fallbacks, and conditional
|
|
20
|
+
* rule application.
|
|
21
|
+
*
|
|
22
|
+
* Configuration includes:
|
|
23
|
+
* - Next.js ESLint plugins (core-web-vitals, TypeScript)
|
|
24
|
+
* - TypeScript parser configuration for type-aware rules
|
|
25
|
+
* - React and React Hooks plugin setup
|
|
26
|
+
* - Next.js-optimized rules using shared React patterns
|
|
27
|
+
* - File-specific rule overrides for React components
|
|
28
|
+
* @param projectDir - The root directory of the Next.js project
|
|
29
|
+
* @returns Array of ESLint configurations for Next.js projects
|
|
30
|
+
*/
|
|
31
|
+
export const createNextjsConfigs = (projectDir) => {
|
|
32
|
+
const baseDir = path.isAbsolute(projectDir)
|
|
33
|
+
? projectDir
|
|
34
|
+
: path.resolve(projectDir);
|
|
35
|
+
const nextCompatConfigs = loadNextjsConfigs(baseDir);
|
|
36
|
+
const configs = [
|
|
37
|
+
// Global ignores must be first - standardized Next.js ignore patterns
|
|
38
|
+
createNextjsIgnoreConfig(),
|
|
39
|
+
// Next.js base configurations (includes React, TypeScript plugins)
|
|
40
|
+
...nextCompatConfigs,
|
|
41
|
+
// TypeScript parser options - REQUIRED for type-aware rules (exclude config files)
|
|
42
|
+
{
|
|
43
|
+
files: [
|
|
44
|
+
"**/*.ts",
|
|
45
|
+
"**/*.tsx",
|
|
46
|
+
"**/*.js",
|
|
47
|
+
"**/*.jsx",
|
|
48
|
+
"instrumentation.ts", // Include instrumentation script
|
|
49
|
+
"instrumentation-client.ts", // Include client instrumentation
|
|
50
|
+
"sentry.*.config.ts", // Include Sentry config files
|
|
51
|
+
],
|
|
52
|
+
ignores: ["**/*.config.*", "**/eslint.config.*", "!sentry.*.config.ts"],
|
|
53
|
+
languageOptions: {
|
|
54
|
+
parserOptions: {
|
|
55
|
+
tsconfigRootDir: projectDir,
|
|
56
|
+
ecmaFeatures: {
|
|
57
|
+
jsx: true,
|
|
58
|
+
globalReturn: true,
|
|
59
|
+
},
|
|
60
|
+
requireConfigFile: false,
|
|
61
|
+
allowImportExportEverywhere: true,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
// Settings configuration (React detection, Next.js root directory)
|
|
66
|
+
createNextjsSettingsConfig(baseDir),
|
|
67
|
+
// Rules configuration - React Hooks now handled by Next.js
|
|
68
|
+
createNextjsRulesConfig(),
|
|
69
|
+
// Strict boolean expressions rule (rules-only, no plugin conflicts)
|
|
70
|
+
createStrictBooleanExpressionsConfig(baseDir),
|
|
71
|
+
// File-specific configurations for React components (shared with React config)
|
|
72
|
+
createSharedReactComponentFileConfig(),
|
|
73
|
+
].filter(Boolean); // Remove any undefined/null configs
|
|
74
|
+
return configs;
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=config.js.map
|