@cascivo/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/LICENSE +21 -0
- package/README.md +29 -0
- package/package.json +45 -0
- package/src/index.d.ts +34 -0
- package/src/index.js +108 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) cascivo contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<!-- generated by scripts/readme/generate.ts — edit readme.body.md, not this file -->
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
<a href="https://cascivo.com"><img src="https://cascivo.com/favicon.svg" width="72" height="72" alt="cascivo logo"></a>
|
|
5
|
+
<h1>@cascivo/eslint-config</h1>
|
|
6
|
+
<p><strong>Flat ESLint config for apps using cascivo — reconciles the signal-based reactivity contract with eslint-plugin-react-hooks 7</strong></p>
|
|
7
|
+
|
|
8
|
+
[](https://www.npmjs.com/package/@cascivo/eslint-config)
|
|
9
|
+
[](https://www.npmjs.com/package/@cascivo/eslint-config)
|
|
10
|
+
[](https://github.com/cascivo/cascivo/blob/main/LICENSE)
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
[npm](https://www.npmjs.com/package/@cascivo/eslint-config) · [cascivo.com](https://cascivo.com) · [Docs](https://cascivo.com/docs) · [Storybook](https://storybook.cascivo.com) · [GitHub](https://github.com/cascivo/cascivo)
|
|
14
|
+
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
pnpm add @cascivo/eslint-config
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
[cascivo.com](https://cascivo.com) · [Docs](https://cascivo.com/docs) · [Storybook](https://storybook.cascivo.com) · [GitHub](https://github.com/cascivo/cascivo) · AI agents: read [`llms.txt`](https://cascivo.com/llms.txt) (install steps + component index, plain text) or use [`@cascivo/mcp`](https://github.com/cascivo/cascivo/tree/main/packages/mcp) and [`registry.json`](https://github.com/cascivo/cascivo/blob/main/registry.json) · MIT
|
|
28
|
+
|
|
29
|
+
<div align="center"><a href="https://cascivo.com"><img src="https://cascivo.com/favicon.svg" width="28" height="28" alt="cascivo"></a></div>
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cascivo/eslint-config",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Flat ESLint config for apps using cascivo — reconciles the signal-based reactivity contract with eslint-plugin-react-hooks 7",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"cascivo",
|
|
8
|
+
"design-system",
|
|
9
|
+
"eslint",
|
|
10
|
+
"eslint-config",
|
|
11
|
+
"react",
|
|
12
|
+
"react-hooks",
|
|
13
|
+
"signals"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://github.com/cascivo/cascivo/tree/main/packages/eslint-config#readme",
|
|
16
|
+
"bugs": "https://github.com/cascivo/cascivo/issues",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"author": "urbanisierung",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/cascivo/cascivo.git",
|
|
22
|
+
"directory": "packages/eslint-config"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"src/**/*.js",
|
|
26
|
+
"src/**/*.d.ts",
|
|
27
|
+
"!src/**/*.test.js"
|
|
28
|
+
],
|
|
29
|
+
"type": "module",
|
|
30
|
+
"exports": {
|
|
31
|
+
"./package.json": "./package.json",
|
|
32
|
+
".": {
|
|
33
|
+
"types": "./src/index.d.ts",
|
|
34
|
+
"default": "./src/index.js"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public",
|
|
39
|
+
"provenance": true
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "echo 'eslint-config: plain ESM, no build'",
|
|
43
|
+
"test": "node --test src/index.test.js"
|
|
44
|
+
}
|
|
45
|
+
}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flat-config fragments for apps using cascivo.
|
|
3
|
+
*
|
|
4
|
+
* Typed loosely on purpose: ESLint's flat-config object type lives in `eslint`, which this
|
|
5
|
+
* package deliberately does not depend on — it ships plain data, so it stays installable
|
|
6
|
+
* next to any ESLint 9+ without a version handshake.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** A single ESLint flat-config object. */
|
|
10
|
+
export interface CascadeFlatConfig {
|
|
11
|
+
name?: string
|
|
12
|
+
files?: string[]
|
|
13
|
+
rules?: Record<string, unknown>
|
|
14
|
+
linterOptions?: Record<string, unknown>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Turns off `react-hooks/immutability`, which reports cascivo's mandatory signal-write
|
|
19
|
+
* idiom (`signal.value = next`) as an error under `eslint-plugin-react-hooks@7`'s
|
|
20
|
+
* `recommended-latest`. Applies to all files — signal writes live in your own page code,
|
|
21
|
+
* not only in vendored source.
|
|
22
|
+
*/
|
|
23
|
+
export declare const cascivoSignals: CascadeFlatConfig
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Scopes host stylistic rules off source vendored by `cascivo add`. Copy-paste path only.
|
|
27
|
+
*
|
|
28
|
+
* @param glob Your `outputDir` from `cascivo.config.ts`. Defaults to `src/components/ui/**`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function cascivoVendoredSource(glob?: string): CascadeFlatConfig
|
|
31
|
+
|
|
32
|
+
/** Both fragments. Spread last in your flat config — last-wins. */
|
|
33
|
+
declare const cascivo: CascadeFlatConfig[]
|
|
34
|
+
export default cascivo
|
package/src/index.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@cascivo/eslint-config` — flat-config fragments for apps that use cascivo.
|
|
3
|
+
*
|
|
4
|
+
* ## Why this package exists
|
|
5
|
+
*
|
|
6
|
+
* `eslint-plugin-react-hooks@7` ships `react-hooks/immutability`, enabled by default in
|
|
7
|
+
* `recommended-latest`. It reports any write to a value returned from a hook — which is
|
|
8
|
+
* exactly cascivo's mandatory state idiom:
|
|
9
|
+
*
|
|
10
|
+
* ```
|
|
11
|
+
* error Error: This value cannot be modified
|
|
12
|
+
* Modifying a value returned from a hook is not allowed.
|
|
13
|
+
* onValueChange={(v) => (env.value = v)}
|
|
14
|
+
* ^^^ `env` cannot be modified
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* `docs/AI-RULES.md` says "Local state -> `useSignal(initial)` … Never `useState`", and
|
|
18
|
+
* `docs/HEADLESS.md`'s canonical example is `onClick={() => (open.value = !open.value)}`.
|
|
19
|
+
* So a stock 2026 React app lints the documented idiom as an error on every piece of state
|
|
20
|
+
* the adopter wrote. One reported build hit this 8 times across 3 files — every lint error
|
|
21
|
+
* in the app, and nothing else.
|
|
22
|
+
*
|
|
23
|
+
* ## Why the rule is turned off rather than narrowed
|
|
24
|
+
*
|
|
25
|
+
* A signal write through `.value` is a deliberate mutation of a live reactive cell; that is
|
|
26
|
+
* the whole point of the primitive. The rule cannot distinguish it from an accidental
|
|
27
|
+
* mutation of `useState` output, and it has no allowlist option for hook names. There is no
|
|
28
|
+
* narrower mechanism, so the honest thing is to turn it off and say what that costs:
|
|
29
|
+
* **you lose the rule's protection against genuinely mutating React state elsewhere in the
|
|
30
|
+
* file.** If that matters more to you than ergonomics, drop `cascivoSignals` and write
|
|
31
|
+
* `signal.value = x` behind a `// eslint-disable-next-line` at each site instead.
|
|
32
|
+
*
|
|
33
|
+
* ## Usage
|
|
34
|
+
*
|
|
35
|
+
* ```js
|
|
36
|
+
* // eslint.config.js
|
|
37
|
+
* import cascivo from '@cascivo/eslint-config'
|
|
38
|
+
*
|
|
39
|
+
* export default [
|
|
40
|
+
* // …your existing config…
|
|
41
|
+
* ...cascivo,
|
|
42
|
+
* ]
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* Spread it AFTER the configs it adjusts — flat config is last-wins.
|
|
46
|
+
*
|
|
47
|
+
* Prefer the pieces individually when you only vendor source, or only use the package:
|
|
48
|
+
*
|
|
49
|
+
* ```js
|
|
50
|
+
* import { cascivoSignals, cascivoVendoredSource } from '@cascivo/eslint-config'
|
|
51
|
+
* export default [...yourConfig, cascivoSignals, cascivoVendoredSource()]
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Reconciles `eslint-plugin-react-hooks@7` with cascivo's signal-based reactivity.
|
|
57
|
+
*
|
|
58
|
+
* Applies everywhere by default — signal writes live in *your* page and component code,
|
|
59
|
+
* not just in vendored files, so a directory-scoped override cannot cover them. That is
|
|
60
|
+
* precisely why the pre-existing `src/components/ui/**` recipe did not help prebuilt-path
|
|
61
|
+
* (Path B) adopters, who have no such directory at all.
|
|
62
|
+
*/
|
|
63
|
+
export const cascivoSignals = {
|
|
64
|
+
name: 'cascivo/signals',
|
|
65
|
+
rules: {
|
|
66
|
+
// See the module header for the full rationale and what turning this off costs.
|
|
67
|
+
'react-hooks/immutability': 'off',
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Host stylistic rules scoped off source you vendored with `cascivo add`.
|
|
73
|
+
*
|
|
74
|
+
* Only relevant on the copy-paste path (Path A). `cascivo update` re-copies these files, so
|
|
75
|
+
* any in-place style fixes are undone on the next update — scoping the rules off is the
|
|
76
|
+
* durable move. Correctness rules stay on.
|
|
77
|
+
*
|
|
78
|
+
* @param {string} [glob] Your `outputDir` from `cascivo.config.ts`, as a glob.
|
|
79
|
+
*/
|
|
80
|
+
export function cascivoVendoredSource(glob = 'src/components/ui/**') {
|
|
81
|
+
return {
|
|
82
|
+
name: 'cascivo/vendored-source',
|
|
83
|
+
files: [glob],
|
|
84
|
+
rules: {
|
|
85
|
+
// Style: `T[]` vs `Array<T>`, import ordering, generic-param naming (`Row` vs
|
|
86
|
+
// `TRow`), method-signature style — cascivo does not adopt these.
|
|
87
|
+
'@typescript-eslint/array-type': 'off',
|
|
88
|
+
'@typescript-eslint/naming-convention': 'off',
|
|
89
|
+
'@typescript-eslint/method-signature-style': 'off',
|
|
90
|
+
'sort-imports': 'off',
|
|
91
|
+
'import/order': 'off',
|
|
92
|
+
// Opinionated / misfires on legitimate cascivo patterns:
|
|
93
|
+
'react/no-array-index-key': 'off', // stable-content lists key by index intentionally
|
|
94
|
+
'no-shadow': 'off', // false-positives on TS declaration merging (compound components)
|
|
95
|
+
'no-control-regex': 'off', // e.g. the log viewer strips ANSI escapes (\x1b) on purpose
|
|
96
|
+
},
|
|
97
|
+
linterOptions: {
|
|
98
|
+
// cascivo's rule-scoped `eslint-disable` directives may target rule ids your config
|
|
99
|
+
// doesn't define — don't report them as "unused".
|
|
100
|
+
reportUnusedDisableDirectives: 'off',
|
|
101
|
+
},
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Both fragments, in the order flat config wants them. Spread last. */
|
|
106
|
+
const cascivo = [cascivoSignals, cascivoVendoredSource()]
|
|
107
|
+
|
|
108
|
+
export default cascivo
|