@pragmatiks/lint 0.3.4 → 0.5.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 +18 -0
- package/README.md +141 -1
- package/dist/eslint-config/index.d.ts +28 -0
- package/dist/eslint-config/index.js +12 -6
- package/dist/eslint-config/index.js.map +1 -1
- package/dist/eslint-config/next/index.d.ts +44 -0
- package/dist/eslint-config/next/index.js +2610 -0
- package/dist/eslint-config/next/index.js.map +1 -0
- package/dist/index.js +12 -6
- package/dist/index.js.map +1 -1
- package/package.json +40 -6
- package/src/semgrep-rules/pra_no_abbreviations_python.yml +1 -1
package/dist/index.js
CHANGED
|
@@ -49,7 +49,7 @@ var PREVENT_ABBREVIATIONS_OPTS = {
|
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
// src/eslint-config/index.ts
|
|
52
|
-
var PRAGMATIKS_LINT_FILES = ["**/*.{ts,tsx,mts,cts
|
|
52
|
+
var PRAGMATIKS_LINT_FILES = ["**/*.{js,jsx,mjs,cjs,ts,tsx,mts,cts}"];
|
|
53
53
|
function findPackageRoot(start) {
|
|
54
54
|
let current = start;
|
|
55
55
|
for (; ; ) {
|
|
@@ -67,14 +67,14 @@ function semgrepRulesDirectory() {
|
|
|
67
67
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
68
68
|
return path.join(findPackageRoot(here), "src", "semgrep-rules");
|
|
69
69
|
}
|
|
70
|
-
function recommendedOrThrow(plugin,
|
|
70
|
+
function recommendedOrThrow(plugin, peer) {
|
|
71
71
|
const recommended = plugin.configs?.recommended;
|
|
72
72
|
if (!recommended) {
|
|
73
73
|
throw new Error(
|
|
74
|
-
|
|
74
|
+
`@pragmatiks/lint: ${peer.name} has no recommended flat-config preset (peer dependency major mismatch). To fix it, install ${peer.name} ${peer.range}.`
|
|
75
75
|
);
|
|
76
76
|
}
|
|
77
|
-
return recommended;
|
|
77
|
+
return { ...recommended, files: PRAGMATIKS_LINT_FILES };
|
|
78
78
|
}
|
|
79
79
|
function pragmatiksConfig() {
|
|
80
80
|
return defineConfig([
|
|
@@ -93,8 +93,14 @@ function pragmatiksConfig() {
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
},
|
|
96
|
-
recommendedOrThrow(sonarjs,
|
|
97
|
-
|
|
96
|
+
recommendedOrThrow(sonarjs, {
|
|
97
|
+
name: "eslint-plugin-sonarjs",
|
|
98
|
+
range: "^4.0.0"
|
|
99
|
+
}),
|
|
100
|
+
recommendedOrThrow(unicorn, {
|
|
101
|
+
name: "eslint-plugin-unicorn",
|
|
102
|
+
range: "^64.0.0"
|
|
103
|
+
}),
|
|
98
104
|
{
|
|
99
105
|
files: PRAGMATIKS_LINT_FILES,
|
|
100
106
|
rules: {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/eslint-config/options.ts","../src/eslint-config/index.ts"],"names":[],"mappings":";;;;;;;;;;;AAAO,IAAM,eAAA,GAAkB;AAExB,IAAM,2BAAA,GAA8B;AAAA,EACzC,GAAA,EAAK,EAAA;AAAA,EACL,cAAA,EAAgB,IAAA;AAAA,EAChB,YAAA,EAAc;AAChB;AAEO,IAAM,mBAAA,GAAsB;AAE5B,IAAM,cAAA,GAAiB;AAEvB,IAAM,eAAA,GAAkB;AAExB,IAAM,0BAAA,GAA6B;AAAA,EACxC,SAAA,EAAW;AAAA,IACT,EAAA,EAAI,IAAA;AAAA,IACJ,GAAA,EAAK,IAAA;AAAA,IACL,GAAA,EAAK,IAAA;AAAA,IACL,GAAA,EAAK,IAAA;AAAA,IACL,GAAA,EAAK,IAAA;AAAA,IACL,GAAA,EAAK,IAAA;AAAA,IACL,EAAA,EAAI,IAAA;AAAA,IACJ,EAAA,EAAI,IAAA;AAAA,IACJ,EAAA,EAAI,IAAA;AAAA,IACJ,GAAA,EAAK,IAAA;AAAA,IACL,GAAA,EAAK,IAAA;AAAA,IACL,GAAA,EAAK,IAAA;AAAA,IACL,IAAA,EAAM,IAAA;AAAA,IACN,IAAA,EAAM,IAAA;AAAA,IACN,IAAA,EAAM,IAAA;AAAA,IACN,GAAA,EAAK,IAAA;AAAA,IACL,GAAA,EAAK,IAAA;AAAA,IACL,GAAA,EAAK,IAAA;AAAA,IACL,GAAA,EAAK,IAAA;AAAA,IACL,GAAA,EAAK,IAAA;AAAA,IACL,GAAA,EAAK,IAAA;AAAA,IACL,EAAA,EAAI,IAAA;AAAA,IACJ,KAAA,EAAO,IAAA;AAAA,IACP,GAAA,EAAK,IAAA;AAAA,IACL,CAAA,EAAG;AAAA;AAEP;;;
|
|
1
|
+
{"version":3,"sources":["../src/eslint-config/options.ts","../src/eslint-config/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export const COMPLEXITY_OPTS = 10;\n\nexport const MAX_LINES_PER_FUNCTION_OPTS = {\n max: 50,\n skipBlankLines: true,\n skipComments: true,\n};\n\nexport const MAX_STATEMENTS_OPTS = 15;\n\nexport const MAX_DEPTH_OPTS = 4;\n\nexport const MAX_PARAMS_OPTS = 4;\n\nexport const PREVENT_ABBREVIATIONS_OPTS = {\n allowList: {\n id: true,\n url: true,\n uri: true,\n api: true,\n cli: true,\n sdk: true,\n os: true,\n io: true,\n ip: true,\n tls: true,\n ssl: true,\n jwt: true,\n json: true,\n yaml: true,\n html: true,\n css: true,\n dom: true,\n ast: true,\n gpu: true,\n cpu: true,\n ram: true,\n vm: true,\n props: true,\n ref: true,\n e: true,\n },\n};\n\n/**\n * `unicorn/filename-case` options for Next apps: kebab-case modules, PascalCase components and\n * camelCase hooks and utilities are all allowed.\n */\nexport const FILENAME_CASE_OPTIONS = {\n cases: {\n kebabCase: true,\n pascalCase: true,\n camelCase: true,\n },\n};\n\n/**\n * `unicorn/no-useless-undefined` options for React: explicit resets such as\n * `setState(undefined)` are meaningful arguments, so arguments are not checked.\n */\nexport const NO_USELESS_UNDEFINED_OPTIONS = { checkArguments: false };\n","import { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { type Config, defineConfig, globalIgnores } from \"eslint/config\";\nimport sonarjs from \"eslint-plugin-sonarjs\";\nimport unicorn from \"eslint-plugin-unicorn\";\nimport tseslint from \"typescript-eslint\";\n\nimport {\n COMPLEXITY_OPTS,\n MAX_DEPTH_OPTS,\n MAX_LINES_PER_FUNCTION_OPTS,\n MAX_PARAMS_OPTS,\n MAX_STATEMENTS_OPTS,\n PREVENT_ABBREVIATIONS_OPTS,\n} from \"./options.js\";\n\n/**\n * The files every Pragmatiks config object applies to: JavaScript and TypeScript, JSX included.\n */\nexport const PRAGMATIKS_LINT_FILES = [\"**/*.{js,jsx,mjs,cjs,ts,tsx,mts,cts}\"];\n\n/**\n * Finds the nearest directory at or above `start` that contains a `package.json`.\n *\n * @param start - The directory to start from.\n * @returns The first directory, walking up, that contains a `package.json`.\n * @throws Error when no directory up to the filesystem root contains one.\n */\nexport function findPackageRoot(start: string): string {\n let current = start;\n for (;;) {\n if (existsSync(path.join(current, \"package.json\"))) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n throw new Error(`package.json not found above ${start}`);\n }\n current = parent;\n }\n}\n\n/**\n * Locates the Semgrep rules shipped with this package.\n *\n * @returns The absolute path of the package's `src/semgrep-rules` directory.\n * @throws Error when the package root cannot be found above this module.\n */\nexport function semgrepRulesDirectory(): string {\n const here = path.dirname(fileURLToPath(import.meta.url));\n return path.join(findPackageRoot(here), \"src\", \"semgrep-rules\");\n}\n\n/**\n * Reads a plugin's recommended flat config and scopes it to `PRAGMATIKS_LINT_FILES`.\n *\n * @param plugin - An ESLint plugin that ships flat configs.\n * @param peer - The plugin's package name and the peer range this package supports, used in the\n * error message.\n * @returns The recommended config with its `files` replaced by `PRAGMATIKS_LINT_FILES`, so it never\n * applies to CSS or other languages composed alongside it.\n * @throws Error when the plugin has no `recommended` flat config, which means an unsupported major.\n */\nfunction recommendedOrThrow(\n plugin: { configs?: Record<string, unknown> },\n peer: { name: string; range: string },\n): Config {\n const recommended = plugin.configs?.recommended;\n if (!recommended) {\n throw new Error(\n `@pragmatiks/lint: ${peer.name} has no recommended flat-config preset (peer dependency major mismatch). To fix it, install ${peer.name} ${peer.range}.`,\n );\n }\n return { ...(recommended as Config), files: PRAGMATIKS_LINT_FILES };\n}\n\n/**\n * Builds the Pragmatiks base flat config for JavaScript and TypeScript files.\n *\n * Every object except the global ignores, the sonarjs and unicorn recommended presets included,\n * applies only to `PRAGMATIKS_LINT_FILES`, so the config composes with configs for other\n * languages such as CSS.\n *\n * @returns The flat config: the typescript-eslint parser, the sonarjs and unicorn recommended\n * presets, the Pragmatiks size and naming rules, and global ignores for build output.\n * @throws Error when the package root cannot be found, or when sonarjs or unicorn has no\n * recommended flat config.\n */\nexport function pragmatiksConfig() {\n return defineConfig([\n {\n files: PRAGMATIKS_LINT_FILES,\n languageOptions: {\n parser: tseslint.parser,\n parserOptions: {\n ecmaVersion: \"latest\",\n sourceType: \"module\",\n },\n },\n settings: {\n pragmatiksLint: {\n semgrepRulesDirectory: semgrepRulesDirectory(),\n },\n },\n },\n recommendedOrThrow(sonarjs, {\n name: \"eslint-plugin-sonarjs\",\n range: \"^4.0.0\",\n }),\n recommendedOrThrow(unicorn, {\n name: \"eslint-plugin-unicorn\",\n range: \"^64.0.0\",\n }),\n {\n files: PRAGMATIKS_LINT_FILES,\n rules: {\n complexity: [\"error\", COMPLEXITY_OPTS],\n \"max-lines-per-function\": [\"error\", MAX_LINES_PER_FUNCTION_OPTS],\n \"max-statements\": [\"error\", MAX_STATEMENTS_OPTS],\n \"max-depth\": [\"error\", MAX_DEPTH_OPTS],\n \"max-params\": [\"error\", MAX_PARAMS_OPTS],\n \"unicorn/prevent-abbreviations\": [\"error\", PREVENT_ABBREVIATIONS_OPTS],\n },\n },\n globalIgnores([\"dist/**\", \"node_modules/**\", \".next/**\", \".turbo/**\"]),\n ]);\n}\n\nexport default pragmatiksConfig;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pragmatiks/lint",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Pragmatiks engineering principles eslint config and bundled semgrep rules.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
"./eslint-config": {
|
|
15
15
|
"types": "./dist/eslint-config/index.d.ts",
|
|
16
16
|
"import": "./dist/eslint-config/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./eslint-config/next": {
|
|
19
|
+
"types": "./dist/eslint-config/next/index.d.ts",
|
|
20
|
+
"import": "./dist/eslint-config/next/index.js"
|
|
17
21
|
}
|
|
18
22
|
},
|
|
19
23
|
"files": [
|
|
@@ -29,26 +33,56 @@
|
|
|
29
33
|
"check": "eslint . && tsc --noEmit",
|
|
30
34
|
"test": "vitest run"
|
|
31
35
|
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@eslint/css-tree": "^4.0.5"
|
|
38
|
+
},
|
|
32
39
|
"peerDependencies": {
|
|
33
|
-
"eslint": "^
|
|
40
|
+
"@eslint/css": "^2.0.0",
|
|
41
|
+
"@tailwindcss/node": "~4.1.17",
|
|
42
|
+
"@tailwindcss/postcss": "~4.1.17",
|
|
43
|
+
"eslint": "^9.38.0",
|
|
44
|
+
"eslint-plugin-react-x": "^5.20.8",
|
|
34
45
|
"eslint-plugin-sonarjs": "^4.0.0",
|
|
35
46
|
"eslint-plugin-unicorn": "^64.0.0",
|
|
36
|
-
"
|
|
47
|
+
"tailwindcss": "~4.1.17",
|
|
48
|
+
"typescript-eslint": "^8.70.1"
|
|
49
|
+
},
|
|
50
|
+
"peerDependenciesMeta": {
|
|
51
|
+
"@eslint/css": {
|
|
52
|
+
"optional": true
|
|
53
|
+
},
|
|
54
|
+
"@tailwindcss/node": {
|
|
55
|
+
"optional": true
|
|
56
|
+
},
|
|
57
|
+
"@tailwindcss/postcss": {
|
|
58
|
+
"optional": true
|
|
59
|
+
},
|
|
60
|
+
"eslint-plugin-react-x": {
|
|
61
|
+
"optional": true
|
|
62
|
+
},
|
|
63
|
+
"tailwindcss": {
|
|
64
|
+
"optional": true
|
|
65
|
+
}
|
|
37
66
|
},
|
|
38
67
|
"devDependencies": {
|
|
68
|
+
"@eslint/css": "2.0.0",
|
|
69
|
+
"@tailwindcss/node": "4.1.17",
|
|
70
|
+
"@tailwindcss/postcss": "4.1.17",
|
|
39
71
|
"@types/node": "^24.0.0",
|
|
40
|
-
"eslint": "^9.
|
|
72
|
+
"eslint": "^9.38.0",
|
|
73
|
+
"eslint-config-next": "16.2.11",
|
|
74
|
+
"eslint-plugin-react-x": "5.20.8",
|
|
41
75
|
"eslint-plugin-sonarjs": "^4.0.3",
|
|
42
76
|
"eslint-plugin-unicorn": "^64.0.0",
|
|
43
77
|
"knip": "^6.12.1",
|
|
44
78
|
"prettier": "^3.4.2",
|
|
45
79
|
"tsup": "^8.3.5",
|
|
46
80
|
"typescript": "^5.7.3",
|
|
47
|
-
"typescript-eslint": "^8.
|
|
81
|
+
"typescript-eslint": "^8.70.1",
|
|
48
82
|
"vitest": "^2.1.8"
|
|
49
83
|
},
|
|
50
84
|
"engines": {
|
|
51
|
-
"node": ">=
|
|
85
|
+
"node": "^22.13.0 || >=24"
|
|
52
86
|
},
|
|
53
87
|
"publishConfig": {
|
|
54
88
|
"access": "public"
|
|
@@ -15,7 +15,7 @@ rules:
|
|
|
15
15
|
- pattern: self.$NAME = $VALUE
|
|
16
16
|
- metavariable-regex:
|
|
17
17
|
metavariable: $NAME
|
|
18
|
-
regex: '^(k8s|cfg|
|
|
18
|
+
regex: '^(k8s|cfg|req|res|ctx|tmp|pkg|svc|mgr|repo|usr|pwd|idx|cnt|msg|err|btn|txt|num|val)$|^_*db(_\w+)?$|^\w*_db$'
|
|
19
19
|
message: "principle #11 Abbreviated identifier hides meaning. Rename it with full words."
|
|
20
20
|
severity: WARNING
|
|
21
21
|
languages: [python]
|