@jterrazz/typescript 9.3.0 → 10.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 +20 -16
- package/bin/commands/check.sh +387 -146
- package/bin/find-tsc.sh +30 -0
- package/bin/typescript.sh +79 -1
- package/lib/check-architecture.js +89 -0
- package/lib/check-baseline.js +144 -0
- package/lib/check-docs.js +4 -3
- package/lib/check-drift.js +209 -0
- package/lib/check-gitignore.js +4 -4
- package/lib/check-markdown.js +279 -0
- package/lib/check-names.js +125 -0
- package/lib/check-publish.js +150 -0
- package/lib/check-secrets.js +115 -0
- package/lib/check-suppressions.js +355 -0
- package/lib/doctor.js +185 -0
- package/lib/entry-points.js +91 -0
- package/lib/merge-knip-config.js +57 -25
- package/lib/tracked-files.js +165 -0
- package/lib/unsafe-fixers.js +25 -0
- package/lib/workspace-members.js +5 -6
- package/package.json +36 -13
- package/presets/oxfmt/index.js +49 -5
- package/presets/oxlint/profiles/astro.js +10 -0
- package/presets/oxlint/profiles/bun.js +7 -0
- package/presets/oxlint/profiles/expo.js +7 -0
- package/presets/oxlint/profiles/library.js +16 -0
- package/presets/oxlint/profiles/next.js +7 -0
- package/presets/oxlint/profiles/node.js +7 -0
- package/presets/oxlint/profiles/react.js +7 -0
- package/presets/prettier/astro.json +6 -0
- package/presets/tsconfig/astro.json +25 -0
- package/presets/tsconfig/expo.json +16 -6
- package/presets/tsconfig/library.json +17 -0
- package/presets/tsconfig/next.json +12 -2
- package/presets/tsconfig/node.json +18 -4
- package/presets/tsconfig/react.json +33 -0
- package/presets/tsdown/build.d.ts +13 -0
- package/presets/tsdown/bundle.d.ts +13 -0
- package/presets/tsdown/bundle.js +10 -1
- package/rules/README.md +23 -0
- package/rules/_contract.js +207 -0
- package/rules/_contract.test.ts +81 -0
- package/rules/a11y.js +51 -0
- package/rules/architecture/hexagonal.js +56 -0
- package/rules/architecture/layers.js +75 -0
- package/rules/astro.js +56 -0
- package/rules/bundler.js +19 -0
- package/rules/catalog.js +166 -0
- package/rules/catalog.test.ts +98 -0
- package/rules/compile.js +125 -0
- package/rules/core/eslint.js +234 -0
- package/rules/core/import.js +117 -0
- package/rules/core/jsdoc.js +52 -0
- package/rules/core/node.js +36 -0
- package/rules/core/oxc.js +54 -0
- package/rules/core/promise.js +39 -0
- package/rules/core/typescript.js +223 -0
- package/rules/core/unicorn.js +210 -0
- package/rules/next.js +53 -0
- package/rules/profiles.js +95 -0
- package/rules/react-native.js +48 -0
- package/rules/react.js +155 -0
- package/rules/sorted.js +41 -0
- package/rules/vitest.js +178 -0
- package/src/docs.d.ts +4 -4
- package/src/docs.js +75 -57
- package/src/docs.test.ts +43 -31
- package/src/index.d.ts +14 -9
- package/src/index.js +17 -8
- package/src/oxfmt.d.ts +15 -2
- package/src/oxfmt.test.ts +10 -0
- package/src/oxlint.d.ts +59 -10
- package/src/oxlint.js +36 -50
- package/src/oxlint.test.ts +82 -28
- package/presets/oxlint/architectures/hexagonal-rules.js +0 -39
- package/presets/oxlint/architectures/hexagonal.js +0 -13
- package/presets/oxlint/base.js +0 -145
- package/presets/oxlint/expo.js +0 -36
- package/presets/oxlint/next.js +0 -43
- package/presets/oxlint/node.js +0 -14
- package/presets/oxlint/plugins/codestyle.js +0 -231
package/src/oxlint.test.ts
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import { expect, test } from 'vitest';
|
|
2
2
|
|
|
3
|
-
import { compose, defineConfig,
|
|
3
|
+
import { compose, defineConfig, hexagonal, layers } from './oxlint.js';
|
|
4
4
|
|
|
5
5
|
test('concatenates and dedupes plugin lists', () => {
|
|
6
|
-
// Given - two
|
|
6
|
+
// Given - two configs sharing one jsPlugin
|
|
7
7
|
const merged = compose(
|
|
8
8
|
{ jsPlugins: ['a', 'b'], plugins: ['typescript'] },
|
|
9
9
|
{ jsPlugins: ['b', 'c'], plugins: ['typescript', 'import'] },
|
|
10
10
|
);
|
|
11
11
|
|
|
12
12
|
// Then - order preserved, duplicates dropped
|
|
13
|
-
expect(merged.jsPlugins).
|
|
14
|
-
expect(merged.plugins).
|
|
13
|
+
expect(merged.jsPlugins).toStrictEqual(['a', 'b', 'c']);
|
|
14
|
+
expect(merged.plugins).toStrictEqual(['typescript', 'import']);
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
test('shallow-merges rules with last
|
|
18
|
-
// Given - two
|
|
17
|
+
test('shallow-merges rules with the last config winning', () => {
|
|
18
|
+
// Given - two configs disagreeing on one rule
|
|
19
19
|
const merged = compose(
|
|
20
20
|
{ rules: { curly: 'error', 'no-ternary': 'off' } },
|
|
21
21
|
{ rules: { curly: 'off', 'jterrazz/b4-given-then': 'error' } },
|
|
22
22
|
);
|
|
23
23
|
|
|
24
|
-
// Then - the later
|
|
25
|
-
expect(merged.rules).
|
|
24
|
+
// Then - the later config wins per key, others survive
|
|
25
|
+
expect(merged.rules).toStrictEqual({
|
|
26
26
|
curly: 'off',
|
|
27
27
|
'jterrazz/b4-given-then': 'error',
|
|
28
28
|
'no-ternary': 'off',
|
|
@@ -30,13 +30,13 @@ test('shallow-merges rules with last fragment winning', () => {
|
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
test('concatenates overrides in order without deduping', () => {
|
|
33
|
-
// Given - two
|
|
33
|
+
// Given - two configs each shipping an override
|
|
34
34
|
const first = { files: ['**/*.specification.ts'], rules: {} };
|
|
35
35
|
const second = { files: ['src/**'], rules: {} };
|
|
36
36
|
const merged = compose({ overrides: [first] }, { overrides: [second] });
|
|
37
37
|
|
|
38
38
|
// Then - both overrides survive, in composition order
|
|
39
|
-
expect(merged.overrides).
|
|
39
|
+
expect(merged.overrides).toStrictEqual([first, second]);
|
|
40
40
|
});
|
|
41
41
|
|
|
42
42
|
test('concatenates and dedupes ignorePatterns', () => {
|
|
@@ -47,40 +47,94 @@ test('concatenates and dedupes ignorePatterns', () => {
|
|
|
47
47
|
);
|
|
48
48
|
|
|
49
49
|
// Then - one entry each
|
|
50
|
-
expect(merged.ignorePatterns).
|
|
50
|
+
expect(merged.ignorePatterns).toStrictEqual(['dist/**', 'node_modules/**', '**/_fixtures/**']);
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
-
test('takes
|
|
54
|
-
// Given -
|
|
55
|
-
const merged = compose(
|
|
53
|
+
test('takes a key the merge tables do not name from the last config that sets it', () => {
|
|
54
|
+
// Given - configs disagreeing on `categories`, a key the merge tables leave out
|
|
55
|
+
const merged = compose(
|
|
56
|
+
{ categories: { correctness: 'off' } },
|
|
57
|
+
{ categories: { correctness: 'error' } },
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
/*
|
|
61
|
+
* No config this package SHIPS carries a `categories` — every rule is
|
|
62
|
+
* decided by name — and that is exactly why it is the key available here.
|
|
63
|
+
*/
|
|
56
64
|
|
|
57
|
-
// Then - last wins
|
|
58
|
-
expect(merged.
|
|
65
|
+
// Then - last wins, which is the rule for every key the three tables leave out
|
|
66
|
+
expect(merged.categories).toStrictEqual({ correctness: 'error' });
|
|
59
67
|
});
|
|
60
68
|
|
|
61
|
-
test('ignores null and undefined
|
|
62
|
-
// Given - a composition with holes (conditional
|
|
69
|
+
test('ignores null and undefined configs', () => {
|
|
70
|
+
// Given - a composition with holes (a conditional fragment)
|
|
63
71
|
const merged = compose(
|
|
64
|
-
|
|
72
|
+
// @ts-expect-error - a conditional fragment is undefined at runtime, which the merge must survive
|
|
73
|
+
undefined,
|
|
65
74
|
{ rules: { curly: 'error' } },
|
|
66
|
-
null
|
|
75
|
+
null,
|
|
67
76
|
);
|
|
68
77
|
|
|
69
78
|
// Then - the holes contribute nothing
|
|
70
|
-
expect(merged.rules).
|
|
79
|
+
expect(merged.rules).toStrictEqual({ curly: 'error' });
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test('gives a layer map one override per layer, complete', () => {
|
|
83
|
+
// Given - a two-layer map
|
|
84
|
+
const fragment = layers({
|
|
85
|
+
map: [
|
|
86
|
+
{
|
|
87
|
+
deny: ['**/adapters/**'],
|
|
88
|
+
files: ['**/core/**'],
|
|
89
|
+
message: 'the core is pure',
|
|
90
|
+
name: 'core',
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Then - the layer's whole pattern list sits inside its own override,
|
|
96
|
+
// Because an oxlint override REPLACES the base entry and never merges it
|
|
97
|
+
expect(fragment.overrides).toStrictEqual([
|
|
98
|
+
{
|
|
99
|
+
files: ['**/core/**'],
|
|
100
|
+
rules: {
|
|
101
|
+
'no-restricted-imports': [
|
|
102
|
+
'error',
|
|
103
|
+
{
|
|
104
|
+
patterns: [{ group: ['**/adapters/**'], message: 'the core is pure' }],
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
]);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
/** A map whose two layers claim the same files — the shape `layers()` refuses. */
|
|
113
|
+
function buildOverlappingMap() {
|
|
114
|
+
return layers({
|
|
115
|
+
map: [
|
|
116
|
+
{ deny: ['**/a/**'], files: ['**/same/**'], message: 'a', name: 'first' },
|
|
117
|
+
{ deny: ['**/b/**'], files: ['**/same/**'], message: 'b', name: 'second' },
|
|
118
|
+
],
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
test('refuses a layer map where one glob belongs to two layers', () => {
|
|
123
|
+
// Given - two layers claiming the same files
|
|
124
|
+
// Then - the map is refused rather than silently losing one of the two
|
|
125
|
+
expect(buildOverlappingMap).toThrow(/belongs to both/u);
|
|
71
126
|
});
|
|
72
127
|
|
|
73
|
-
test('
|
|
74
|
-
// Given - the
|
|
75
|
-
// Then -
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
128
|
+
test('ships the hexagonal map as six complete overrides', () => {
|
|
129
|
+
// Given - the default map
|
|
130
|
+
// Then - one override per layer, and the features carve-out is a negated glob
|
|
131
|
+
expect(hexagonal.overrides).toHaveLength(6);
|
|
132
|
+
expect(JSON.stringify(hexagonal.overrides)).toContain('!**/presentation/features/common/**');
|
|
79
133
|
});
|
|
80
134
|
|
|
81
135
|
test("re-exports oxlint's own defineConfig", () => {
|
|
82
136
|
// Given - a config a consumer would write, with oxlint declared nowhere in its project
|
|
83
|
-
const config = { rules: { curly: 'error' } };
|
|
137
|
+
const config = { rules: { curly: 'error' } } as const;
|
|
84
138
|
|
|
85
139
|
// Then - the entry carries the tool's helper, which returns the config unchanged
|
|
86
140
|
expect(defineConfig(config)).toBe(config);
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
export default [
|
|
2
|
-
{
|
|
3
|
-
from: '/domain/',
|
|
4
|
-
disallow: [
|
|
5
|
-
'/application/',
|
|
6
|
-
'/infrastructure/',
|
|
7
|
-
'/presentation/',
|
|
8
|
-
'/di/',
|
|
9
|
-
'/config/',
|
|
10
|
-
'/generated/',
|
|
11
|
-
],
|
|
12
|
-
message: 'Domain layer must be pure - cannot import from other layers',
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
from: '/application/use-cases/',
|
|
16
|
-
disallow: ['/infrastructure/', '/presentation/', '/di/'],
|
|
17
|
-
message: 'Use cases can only depend on domain and ports',
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
from: '/application/ports/',
|
|
21
|
-
disallow: ['/infrastructure/', '/presentation/', '/di/'],
|
|
22
|
-
message: 'Ports are interfaces - cannot depend on implementations',
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
from: '/infrastructure/inbound/',
|
|
26
|
-
disallow: ['/infrastructure/outbound/'],
|
|
27
|
-
message: 'Inbound adapters should not import outbound adapters - use DI',
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
from: '/presentation/ui/(atoms|molecules)/',
|
|
31
|
-
disallow: ['/navigation/'],
|
|
32
|
-
message: 'Atoms and molecules must be pure - no navigation imports',
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
from: '/presentation/features/',
|
|
36
|
-
disallow: ['/presentation/features/(?!common)'],
|
|
37
|
-
message: 'Features should be independent - use shared code in features/common',
|
|
38
|
-
},
|
|
39
|
-
];
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { resolve } from 'node:path';
|
|
2
|
-
import { defineConfig } from 'oxlint';
|
|
3
|
-
|
|
4
|
-
import defaultRules from './hexagonal-rules.js';
|
|
5
|
-
|
|
6
|
-
const pluginPath = resolve(import.meta.dirname, '../plugins/codestyle.js');
|
|
7
|
-
|
|
8
|
-
export default defineConfig({
|
|
9
|
-
jsPlugins: [pluginPath],
|
|
10
|
-
rules: {
|
|
11
|
-
'codestyle/arch-hexagonal': ['error', { rules: defaultRules }],
|
|
12
|
-
},
|
|
13
|
-
});
|
package/presets/oxlint/base.js
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import { createRequire } from 'node:module';
|
|
2
|
-
import { defineConfig } from 'oxlint';
|
|
3
|
-
|
|
4
|
-
const require = createRequire(import.meta.url);
|
|
5
|
-
const perfectionistPath = require.resolve('eslint-plugin-perfectionist');
|
|
6
|
-
|
|
7
|
-
/*
|
|
8
|
-
* Base lint preset — tooling rules only. Wiring is EXPLICIT: this preset never
|
|
9
|
-
* auto-detects other jterrazz packages. A project using @jterrazz/test composes
|
|
10
|
-
* its `testing` fragment itself:
|
|
11
|
-
*
|
|
12
|
-
* import { testing } from '@jterrazz/test/oxlint';
|
|
13
|
-
* import { compose, node } from '@jterrazz/typescript/oxlint';
|
|
14
|
-
*
|
|
15
|
-
* export default compose(node, testing);
|
|
16
|
-
*
|
|
17
|
-
* (The @jterrazz/test plugin is ESM-only: a CommonJS oxlint config silently
|
|
18
|
-
* drops it — `typescript check` still warns loudly about that pitfall.)
|
|
19
|
-
*/
|
|
20
|
-
export default defineConfig({
|
|
21
|
-
plugins: ['typescript', 'import', 'oxc', 'unicorn'],
|
|
22
|
-
jsPlugins: [perfectionistPath],
|
|
23
|
-
categories: {
|
|
24
|
-
correctness: 'error',
|
|
25
|
-
suspicious: 'error',
|
|
26
|
-
perf: 'error',
|
|
27
|
-
pedantic: 'off',
|
|
28
|
-
style: 'error',
|
|
29
|
-
nursery: 'off',
|
|
30
|
-
},
|
|
31
|
-
rules: {
|
|
32
|
-
// ============================================
|
|
33
|
-
// ENABLED RULES
|
|
34
|
-
// ============================================
|
|
35
|
-
|
|
36
|
-
'no-unused-vars': 'error',
|
|
37
|
-
|
|
38
|
-
// -- TypeScript --
|
|
39
|
-
'typescript/consistent-type-imports': [
|
|
40
|
-
'error',
|
|
41
|
-
{
|
|
42
|
-
disallowTypeAnnotations: true,
|
|
43
|
-
fixStyle: 'inline-type-imports',
|
|
44
|
-
prefer: 'type-imports',
|
|
45
|
-
},
|
|
46
|
-
],
|
|
47
|
-
'typescript/no-unused-expressions': [
|
|
48
|
-
'error',
|
|
49
|
-
{
|
|
50
|
-
allowShortCircuit: true,
|
|
51
|
-
allowTernary: true,
|
|
52
|
-
allowTaggedTemplates: true,
|
|
53
|
-
},
|
|
54
|
-
],
|
|
55
|
-
|
|
56
|
-
// -- Perfectionist (sorting/ordering) --
|
|
57
|
-
'perfectionist/sort-heritage-clauses': ['error', { type: 'natural' }],
|
|
58
|
-
'perfectionist/sort-intersection-types': ['error', { type: 'natural' }],
|
|
59
|
-
'perfectionist/sort-jsx-props': ['error', { type: 'natural' }],
|
|
60
|
-
'perfectionist/sort-named-exports': ['error', { type: 'natural' }],
|
|
61
|
-
'perfectionist/sort-named-imports': ['error', { type: 'natural' }],
|
|
62
|
-
'perfectionist/sort-union-types': ['error', { type: 'natural' }],
|
|
63
|
-
'perfectionist/sort-imports': [
|
|
64
|
-
'error',
|
|
65
|
-
{
|
|
66
|
-
type: 'alphabetical',
|
|
67
|
-
order: 'asc',
|
|
68
|
-
ignoreCase: true,
|
|
69
|
-
newlinesBetween: 1,
|
|
70
|
-
groups: [
|
|
71
|
-
['builtin', 'external'],
|
|
72
|
-
'internal',
|
|
73
|
-
['parent', 'sibling', 'index'],
|
|
74
|
-
'style',
|
|
75
|
-
'unknown',
|
|
76
|
-
],
|
|
77
|
-
},
|
|
78
|
-
],
|
|
79
|
-
|
|
80
|
-
// ============================================
|
|
81
|
-
// DISABLED - Conflicts with perfectionist
|
|
82
|
-
// ============================================
|
|
83
|
-
|
|
84
|
-
'sort-keys': 'off',
|
|
85
|
-
'sort-imports': 'off',
|
|
86
|
-
|
|
87
|
-
// ============================================
|
|
88
|
-
// DISABLED - Too strict / opinionated
|
|
89
|
-
// ============================================
|
|
90
|
-
|
|
91
|
-
'func-style': 'off',
|
|
92
|
-
'no-magic-numbers': 'off',
|
|
93
|
-
'no-ternary': 'off',
|
|
94
|
-
'init-declarations': 'off',
|
|
95
|
-
'id-length': 'off',
|
|
96
|
-
'max-statements': 'off',
|
|
97
|
-
'max-params': 'off',
|
|
98
|
-
'no-continue': 'off',
|
|
99
|
-
'arrow-body-style': 'off',
|
|
100
|
-
'prefer-destructuring': 'off',
|
|
101
|
-
'new-cap': 'off',
|
|
102
|
-
'no-await-in-loop': 'off',
|
|
103
|
-
'typescript/consistent-type-definitions': 'off',
|
|
104
|
-
'typescript/array-type': 'off',
|
|
105
|
-
'typescript/no-inferrable-types': 'off',
|
|
106
|
-
'unicorn/no-null': 'off',
|
|
107
|
-
'unicorn/no-array-sort': 'off',
|
|
108
|
-
'import/no-unassigned-import': 'off',
|
|
109
|
-
'import/no-named-default': 'off',
|
|
110
|
-
'import/no-nodejs-modules': 'off',
|
|
111
|
-
// Exports-at-end fights how these files actually read everywhere in
|
|
112
|
-
// The ecosystem — three repos had disabled it locally (jterrazz-web,
|
|
113
|
-
// Package-test, package-attestation) before it moved here.
|
|
114
|
-
'import/exports-last': 'off',
|
|
115
|
-
|
|
116
|
-
// ============================================
|
|
117
|
-
// ENABLED - Code style enforcement
|
|
118
|
-
// ============================================
|
|
119
|
-
|
|
120
|
-
'capitalized-comments': 'error',
|
|
121
|
-
curly: 'error',
|
|
122
|
-
'no-nested-ternary': 'error',
|
|
123
|
-
'unicorn/catch-error-name': 'error',
|
|
124
|
-
'unicorn/numeric-separators-style': 'error',
|
|
125
|
-
|
|
126
|
-
// ============================================
|
|
127
|
-
// DISABLED - Conflicts with other rules
|
|
128
|
-
// ============================================
|
|
129
|
-
|
|
130
|
-
'import/no-named-export': 'off',
|
|
131
|
-
'import/consistent-type-specifier-style': 'off',
|
|
132
|
-
'import/prefer-default-export': 'off',
|
|
133
|
-
'import/no-default-export': 'off',
|
|
134
|
-
'import/group-exports': 'off',
|
|
135
|
-
'import/no-anonymous-default-export': 'off',
|
|
136
|
-
|
|
137
|
-
// ============================================
|
|
138
|
-
// ENABLED - Clean imports
|
|
139
|
-
// ============================================
|
|
140
|
-
|
|
141
|
-
'import/first': 'error',
|
|
142
|
-
'import/no-namespace': 'error',
|
|
143
|
-
},
|
|
144
|
-
ignorePatterns: ['dist/**', 'node_modules/**'],
|
|
145
|
-
});
|
package/presets/oxlint/expo.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { resolve } from 'node:path';
|
|
2
|
-
import { defineConfig } from 'oxlint';
|
|
3
|
-
|
|
4
|
-
import base from './base.js';
|
|
5
|
-
|
|
6
|
-
const pluginPath = resolve(import.meta.dirname, 'plugins/codestyle.js');
|
|
7
|
-
|
|
8
|
-
export default defineConfig({
|
|
9
|
-
extends: [base],
|
|
10
|
-
plugins: ['typescript', 'import', 'react'],
|
|
11
|
-
jsPlugins: [pluginPath],
|
|
12
|
-
// `.expo/` is the toolchain cache and `assets/` is scaffolded by Expo
|
|
13
|
-
// Itself (icons, splash, fonts) — never source.
|
|
14
|
-
ignorePatterns: ['dist/**', 'node_modules/**', '.expo/**', 'assets/**'],
|
|
15
|
-
rules: {
|
|
16
|
-
'typescript/no-require-imports': [
|
|
17
|
-
'error',
|
|
18
|
-
{
|
|
19
|
-
allow: [
|
|
20
|
-
String.raw`\.png$`,
|
|
21
|
-
String.raw`\.jpg$`,
|
|
22
|
-
String.raw`\.jpeg$`,
|
|
23
|
-
String.raw`\.gif$`,
|
|
24
|
-
String.raw`\.webp$`,
|
|
25
|
-
],
|
|
26
|
-
},
|
|
27
|
-
],
|
|
28
|
-
'codestyle/imports-without-ext': 'error',
|
|
29
|
-
'react/react-in-jsx-scope': 'off',
|
|
30
|
-
'react/jsx-props-no-spreading': 'off',
|
|
31
|
-
'react/jsx-boolean-value': 'off',
|
|
32
|
-
'react/jsx-handler-names': 'off',
|
|
33
|
-
'react/jsx-curly-brace-presence': 'off',
|
|
34
|
-
'unicorn/no-nested-ternary': 'off',
|
|
35
|
-
},
|
|
36
|
-
});
|
package/presets/oxlint/next.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { resolve } from 'node:path';
|
|
2
|
-
import { defineConfig } from 'oxlint';
|
|
3
|
-
|
|
4
|
-
import base from './base.js';
|
|
5
|
-
|
|
6
|
-
const pluginPath = resolve(import.meta.dirname, 'plugins/codestyle.js');
|
|
7
|
-
|
|
8
|
-
export default defineConfig({
|
|
9
|
-
extends: [base],
|
|
10
|
-
plugins: ['typescript', 'import', 'react', 'nextjs'],
|
|
11
|
-
jsPlugins: [pluginPath],
|
|
12
|
-
// `public/` is Next's static dir and `assets/` is the stack's convention
|
|
13
|
-
// For content trees (jterrazz-web: signed attestation bytes live there —
|
|
14
|
-
// A formatter pass would invalidate every proof). Neither is source.
|
|
15
|
-
ignorePatterns: [
|
|
16
|
-
'dist/**',
|
|
17
|
-
'node_modules/**',
|
|
18
|
-
'.next/**',
|
|
19
|
-
'next-env.d.ts',
|
|
20
|
-
'assets/**',
|
|
21
|
-
'public/**',
|
|
22
|
-
],
|
|
23
|
-
rules: {
|
|
24
|
-
'codestyle/imports-without-ext': 'error',
|
|
25
|
-
'react/react-in-jsx-scope': 'off',
|
|
26
|
-
'react/jsx-props-no-spreading': 'off',
|
|
27
|
-
'react/jsx-boolean-value': 'off',
|
|
28
|
-
'react/jsx-handler-names': 'off',
|
|
29
|
-
'react/jsx-curly-brace-presence': 'off',
|
|
30
|
-
'react/jsx-max-depth': 'off',
|
|
31
|
-
'unicorn/no-nested-ternary': 'off',
|
|
32
|
-
// -- Rules that fight the Next idiom itself, not bad code --
|
|
33
|
-
// (import/exports-last is off in base: it fights the whole ecosystem.)
|
|
34
|
-
// Immutable serialization maps (`.map((x) => ({ ...x, url }))`) are
|
|
35
|
-
// The dominant React idiom; the Object.assign form is strictly worse
|
|
36
|
-
// For the build-time collection sizes a site actually maps over.
|
|
37
|
-
'oxc/no-map-spread': 'off',
|
|
38
|
-
// Client components are browser-only code that means `window`;
|
|
39
|
-
// Asking them to say `globalThis` trades clarity for portability
|
|
40
|
-
// They will never need.
|
|
41
|
-
'unicorn/prefer-global-this': 'off',
|
|
42
|
-
},
|
|
43
|
-
});
|
package/presets/oxlint/node.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { resolve } from 'node:path';
|
|
2
|
-
import { defineConfig } from 'oxlint';
|
|
3
|
-
|
|
4
|
-
import base from './base.js';
|
|
5
|
-
|
|
6
|
-
const pluginPath = resolve(import.meta.dirname, 'plugins/codestyle.js');
|
|
7
|
-
|
|
8
|
-
export default defineConfig({
|
|
9
|
-
extends: [base],
|
|
10
|
-
jsPlugins: [pluginPath],
|
|
11
|
-
rules: {
|
|
12
|
-
'codestyle/imports-with-ext': 'error',
|
|
13
|
-
},
|
|
14
|
-
});
|