eslint-plugin-redux-sparse-kit 0.0.0-stage → 0.1.1
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.md +21 -0
- package/README.md +188 -2
- package/lib/index.d.ts +32 -0
- package/lib/index.js +52 -0
- package/lib/index.js.map +1 -0
- package/lib/rules/noDefineSegmentInRender.d.ts +5 -0
- package/lib/rules/noDefineSegmentInRender.js +71 -0
- package/lib/rules/noDefineSegmentInRender.js.map +1 -0
- package/lib/rules/noDuplicateSegments.d.ts +5 -0
- package/lib/rules/noDuplicateSegments.js +109 -0
- package/lib/rules/noDuplicateSegments.js.map +1 -0
- package/lib/rules/noStaticStateKey.d.ts +5 -0
- package/lib/rules/noStaticStateKey.js +76 -0
- package/lib/rules/noStaticStateKey.js.map +1 -0
- package/lib/rules/releaseAcquiredSegments.d.ts +5 -0
- package/lib/rules/releaseAcquiredSegments.js +45 -0
- package/lib/rules/releaseAcquiredSegments.js.map +1 -0
- package/lib/utils/isAcquireCall.d.ts +6 -0
- package/lib/utils/isAcquireCall.js +24 -0
- package/lib/utils/isAcquireCall.js.map +1 -0
- package/lib/utils/sparseApi.d.ts +23 -0
- package/lib/utils/sparseApi.js +115 -0
- package/lib/utils/sparseApi.js.map +1 -0
- package/package.json +70 -4
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Aleksandr Khizhnyi
|
|
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 all
|
|
13
|
+
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
CHANGED
|
@@ -1,3 +1,189 @@
|
|
|
1
|
-
#
|
|
1
|
+
# eslint-plugin-redux-sparse-kit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/eslint-plugin-redux-sparse-kit)
|
|
4
|
+
[](LICENSE.md)
|
|
5
|
+
|
|
6
|
+
ESLint rules for [redux-sparse-kit](https://github.com/veksa/redux-sparse-kit):
|
|
7
|
+
mistakes with segments and scopes that types cannot see, caught in the editor
|
|
8
|
+
instead of at runtime.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install --save-dev eslint-plugin-redux-sparse-kit
|
|
14
|
+
# or
|
|
15
|
+
yarn add --dev eslint-plugin-redux-sparse-kit
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Requires ESLint 8.57 or later. `no-static-state-key` needs type information,
|
|
19
|
+
which comes from `@typescript-eslint/parser` 8 and TypeScript 5.4 to 6.0.
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
`eslint.config.js`:
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
import { reduxSparseKitPlugin } from 'eslint-plugin-redux-sparse-kit';
|
|
27
|
+
|
|
28
|
+
export default [
|
|
29
|
+
// ...
|
|
30
|
+
...reduxSparseKitPlugin.configs.recommended,
|
|
31
|
+
];
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
With type information, use `recommended-type-checked`, which adds the rules
|
|
35
|
+
that need it:
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
import tseslint from 'typescript-eslint';
|
|
39
|
+
import { reduxSparseKitPlugin } from 'eslint-plugin-redux-sparse-kit';
|
|
40
|
+
|
|
41
|
+
export default [
|
|
42
|
+
{
|
|
43
|
+
languageOptions: {
|
|
44
|
+
parser: tseslint.parser,
|
|
45
|
+
parserOptions: { projectService: true, tsconfigRootDir: import.meta.dirname },
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
...reduxSparseKitPlugin.configs['recommended-type-checked'],
|
|
49
|
+
];
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
| Config | Rules |
|
|
53
|
+
| -------------------------- | ----------------------------------------------------------------------------------- |
|
|
54
|
+
| `recommended` | `no-define-segment-in-render`, `no-duplicate-segments`, `release-acquired-segments` |
|
|
55
|
+
| `recommended-type-checked` | the above and `no-static-state-key` |
|
|
56
|
+
|
|
57
|
+
The configs are flat config arrays. Under eslintrc, add the plugin and list the
|
|
58
|
+
rules:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"plugins": ["redux-sparse-kit"],
|
|
63
|
+
"rules": {
|
|
64
|
+
"redux-sparse-kit/no-define-segment-in-render": "error",
|
|
65
|
+
"redux-sparse-kit/no-duplicate-segments": "error",
|
|
66
|
+
"redux-sparse-kit/release-acquired-segments": "error"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Settings
|
|
72
|
+
|
|
73
|
+
The rules find redux-sparse-kit's API by its imports from `redux-sparse-kit`
|
|
74
|
+
and `redux-sparse-kit/react`, renamed or not, through namespace imports, and
|
|
75
|
+
through what `createSparseReact()` returns. When an application re-exports the
|
|
76
|
+
API from a module of its own, name that module:
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
{
|
|
80
|
+
settings: {
|
|
81
|
+
'redux-sparse-kit': { importSources: ['@app/state'] },
|
|
82
|
+
},
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Rules
|
|
87
|
+
|
|
88
|
+
### `no-define-segment-in-render`
|
|
89
|
+
|
|
90
|
+
A segment is identified by the object `defineSegment` returns. Defined inside a
|
|
91
|
+
component or a hook, it is a new segment on every render: scopes acquire it
|
|
92
|
+
again, and the store refuses a second segment under a key that is still
|
|
93
|
+
present.
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
// ✗
|
|
97
|
+
function OrdersPage() {
|
|
98
|
+
const orders = defineSegment({ key: 'orders', reducer });
|
|
99
|
+
return <SparseScope segments={[orders]} />;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ✓
|
|
103
|
+
const orders = defineSegment({ key: 'orders', reducer });
|
|
104
|
+
|
|
105
|
+
function OrdersPage() {
|
|
106
|
+
return <SparseScope segments={[orders]} />;
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Functions that are neither components nor hooks are left alone, so a factory
|
|
111
|
+
that defines segments at module scope is fine:
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
const createListSegment = (key: string) => defineSegment({ key, reducer: listReducer });
|
|
115
|
+
|
|
116
|
+
export const orders = createListSegment('orders');
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Components and hooks are told by their names: a function, or the variable or
|
|
120
|
+
wrapper call it is assigned to, named in PascalCase or `useSomething`, and
|
|
121
|
+
class `render` methods.
|
|
122
|
+
|
|
123
|
+
### `no-duplicate-segments`
|
|
124
|
+
|
|
125
|
+
Reports a segment listed twice in `deps`, in a `SparseScope`'s `segments`, in
|
|
126
|
+
`useSparseSegments([...])` and in `store.sparse.acquire(...)`, and two
|
|
127
|
+
segments defined with the same literal key in one file.
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
// ✗
|
|
131
|
+
defineSegment({ key: 'page', deps: [orders, prices, orders] });
|
|
132
|
+
<SparseScope segments={[orders, orders]} />;
|
|
133
|
+
|
|
134
|
+
export const a = defineSegment({ key: 'orders', reducer });
|
|
135
|
+
export const b = defineSegment({ key: 'orders', reducer: otherReducer });
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Segments are compared by their references, such as `orders` or
|
|
139
|
+
`segments.orders`; keys built at runtime are not compared.
|
|
140
|
+
|
|
141
|
+
### `release-acquired-segments`
|
|
142
|
+
|
|
143
|
+
`store.sparse.acquire(...)` returns the function that releases what it
|
|
144
|
+
acquired. Discarding it keeps the segments in the store for good.
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
// ✗
|
|
148
|
+
store.sparse.acquire(orders);
|
|
149
|
+
|
|
150
|
+
useEffect(() => {
|
|
151
|
+
store.sparse.acquire(orders);
|
|
152
|
+
}, []);
|
|
153
|
+
|
|
154
|
+
// ✓
|
|
155
|
+
const release = store.sparse.acquire(orders);
|
|
156
|
+
|
|
157
|
+
useEffect(() => store.sparse.acquire(orders), []);
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Calls are recognised as `<something>.sparse.acquire(...)` and
|
|
161
|
+
`sparse.acquire(...)`.
|
|
162
|
+
|
|
163
|
+
### `no-static-state-key`
|
|
164
|
+
|
|
165
|
+
_Needs type information._ A segment with a reducer cannot use a key of the
|
|
166
|
+
static state: the store refuses to acquire it. The rule reads the segment's key
|
|
167
|
+
and reducer from its type, and the static state from `StaticState` as the
|
|
168
|
+
application registers it:
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
declare module 'redux-sparse-kit' {
|
|
172
|
+
interface StaticState {
|
|
173
|
+
router: RouterState;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ✗
|
|
178
|
+
export const routing = defineSegment({ key: 'router', reducer: routingReducer });
|
|
179
|
+
|
|
180
|
+
// ✓ a segment without a reducer owns no slice
|
|
181
|
+
export const routing = defineSegment({ key: 'router', epics: [routingEpic] });
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Keys typed as a union of literals are checked one by one; keys typed as
|
|
185
|
+
`string` are not known and not checked.
|
|
186
|
+
|
|
187
|
+
## License
|
|
188
|
+
|
|
189
|
+
[MIT](LICENSE.md)
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { TSESLint } from '@typescript-eslint/utils';
|
|
2
|
+
declare const meta: {
|
|
3
|
+
name: string;
|
|
4
|
+
};
|
|
5
|
+
declare const rules: {
|
|
6
|
+
'no-define-segment-in-render': TSESLint.RuleModule<"define-segment-in-render", [], unknown, TSESLint.RuleListener>;
|
|
7
|
+
'no-duplicate-segments': TSESLint.RuleModule<"duplicate-segment" | "duplicate-key", [], unknown, TSESLint.RuleListener>;
|
|
8
|
+
'no-static-state-key': TSESLint.RuleModule<"static-state-key", [], unknown, TSESLint.RuleListener>;
|
|
9
|
+
'release-acquired-segments': TSESLint.RuleModule<"release-discarded", [], unknown, TSESLint.RuleListener>;
|
|
10
|
+
};
|
|
11
|
+
export declare const reduxSparseKitPlugin: {
|
|
12
|
+
meta: {
|
|
13
|
+
name: string;
|
|
14
|
+
};
|
|
15
|
+
rules: {
|
|
16
|
+
'no-define-segment-in-render': TSESLint.RuleModule<"define-segment-in-render", [], unknown, TSESLint.RuleListener>;
|
|
17
|
+
'no-duplicate-segments': TSESLint.RuleModule<"duplicate-segment" | "duplicate-key", [], unknown, TSESLint.RuleListener>;
|
|
18
|
+
'no-static-state-key': TSESLint.RuleModule<"static-state-key", [], unknown, TSESLint.RuleListener>;
|
|
19
|
+
'release-acquired-segments': TSESLint.RuleModule<"release-discarded", [], unknown, TSESLint.RuleListener>;
|
|
20
|
+
};
|
|
21
|
+
configs: {
|
|
22
|
+
recommended: TSESLint.FlatConfig.ConfigArray;
|
|
23
|
+
'recommended-type-checked': TSESLint.FlatConfig.ConfigArray;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* The eslintrc engine loads a plugin by name and looks the rules up on the
|
|
28
|
+
* module itself, so `plugins: ['redux-sparse-kit']` needs them exported here.
|
|
29
|
+
* Its configs are flat config arrays, so under eslintrc list the rules
|
|
30
|
+
* directly instead of extending them.
|
|
31
|
+
*/
|
|
32
|
+
export { meta, rules };
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rules = exports.meta = exports.reduxSparseKitPlugin = void 0;
|
|
4
|
+
const noDefineSegmentInRender_1 = require("./rules/noDefineSegmentInRender");
|
|
5
|
+
const noDuplicateSegments_1 = require("./rules/noDuplicateSegments");
|
|
6
|
+
const noStaticStateKey_1 = require("./rules/noStaticStateKey");
|
|
7
|
+
const releaseAcquiredSegments_1 = require("./rules/releaseAcquiredSegments");
|
|
8
|
+
const meta = {
|
|
9
|
+
name: 'redux-sparse-kit',
|
|
10
|
+
};
|
|
11
|
+
exports.meta = meta;
|
|
12
|
+
const rules = {
|
|
13
|
+
'no-define-segment-in-render': noDefineSegmentInRender_1.noDefineSegmentInRenderRule,
|
|
14
|
+
'no-duplicate-segments': noDuplicateSegments_1.noDuplicateSegmentsRule,
|
|
15
|
+
'no-static-state-key': noStaticStateKey_1.noStaticStateKeyRule,
|
|
16
|
+
'release-acquired-segments': releaseAcquiredSegments_1.releaseAcquiredSegmentsRule,
|
|
17
|
+
};
|
|
18
|
+
exports.rules = rules;
|
|
19
|
+
const plugin = { meta, rules };
|
|
20
|
+
/** The rules that need no type information. */
|
|
21
|
+
const recommended = [
|
|
22
|
+
{
|
|
23
|
+
name: 'redux-sparse-kit/recommended',
|
|
24
|
+
plugins: {
|
|
25
|
+
'redux-sparse-kit': plugin,
|
|
26
|
+
},
|
|
27
|
+
rules: {
|
|
28
|
+
'redux-sparse-kit/no-define-segment-in-render': 'error',
|
|
29
|
+
'redux-sparse-kit/no-duplicate-segments': 'error',
|
|
30
|
+
'redux-sparse-kit/release-acquired-segments': 'error',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
/** Every rule, for projects linted with type information. */
|
|
35
|
+
const recommendedTypeChecked = [
|
|
36
|
+
...recommended,
|
|
37
|
+
{
|
|
38
|
+
name: 'redux-sparse-kit/recommended-type-checked',
|
|
39
|
+
rules: {
|
|
40
|
+
'redux-sparse-kit/no-static-state-key': 'error',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
exports.reduxSparseKitPlugin = {
|
|
45
|
+
meta,
|
|
46
|
+
rules,
|
|
47
|
+
configs: {
|
|
48
|
+
recommended,
|
|
49
|
+
'recommended-type-checked': recommendedTypeChecked,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,6EAA8E;AAC9E,qEAAsE;AACtE,+DAAgE;AAChE,6EAA8E;AAE9E,MAAM,IAAI,GAAG;IACX,IAAI,EAAE,kBAAkB;CACzB,CAAC;AAoDO,oBAAI;AAlDb,MAAM,KAAK,GAAG;IACZ,6BAA6B,EAAE,qDAA2B;IAC1D,uBAAuB,EAAE,6CAAuB;IAChD,qBAAqB,EAAE,uCAAoB;IAC3C,2BAA2B,EAAE,qDAA2B;CACzD,CAAC;AA6Ca,sBAAK;AA3CpB,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAE/B,+CAA+C;AAC/C,MAAM,WAAW,GAAoC;IACnD;QACE,IAAI,EAAE,8BAA8B;QACpC,OAAO,EAAE;YACP,kBAAkB,EAAE,MAAM;SAC3B;QACD,KAAK,EAAE;YACL,8CAA8C,EAAE,OAAO;YACvD,wCAAwC,EAAE,OAAO;YACjD,4CAA4C,EAAE,OAAO;SACtD;KACF;CACF,CAAC;AAEF,6DAA6D;AAC7D,MAAM,sBAAsB,GAAoC;IAC9D,GAAG,WAAW;IACd;QACE,IAAI,EAAE,2CAA2C;QACjD,KAAK,EAAE;YACL,sCAAsC,EAAE,OAAO;SAChD;KACF;CACF,CAAC;AAEW,QAAA,oBAAoB,GAAG;IAClC,IAAI;IACJ,KAAK;IACL,OAAO,EAAE;QACP,WAAW;QACX,0BAA0B,EAAE,sBAAsB;KACnD;CACF,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.noDefineSegmentInRenderRule = void 0;
|
|
4
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
5
|
+
const sparseApi_1 = require("../utils/sparseApi");
|
|
6
|
+
const componentName = /^[A-Z]/;
|
|
7
|
+
const hookName = /^use[A-Z0-9]/;
|
|
8
|
+
const isFunction = (node) => node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
|
|
9
|
+
node.type === utils_1.AST_NODE_TYPES.FunctionDeclaration ||
|
|
10
|
+
node.type === utils_1.AST_NODE_TYPES.FunctionExpression;
|
|
11
|
+
/**
|
|
12
|
+
* The name a function is known by: its own, the variable or property it is
|
|
13
|
+
* assigned to, or the variable a wrapper such as `memo(...)` is assigned to.
|
|
14
|
+
*/
|
|
15
|
+
const getFunctionName = (node) => {
|
|
16
|
+
if (node.id) {
|
|
17
|
+
return node.id.name;
|
|
18
|
+
}
|
|
19
|
+
let parent = node.parent;
|
|
20
|
+
while (parent.type === utils_1.AST_NODE_TYPES.CallExpression) {
|
|
21
|
+
parent = parent.parent;
|
|
22
|
+
}
|
|
23
|
+
if (parent.type === utils_1.AST_NODE_TYPES.VariableDeclarator &&
|
|
24
|
+
parent.id.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
25
|
+
return parent.id.name;
|
|
26
|
+
}
|
|
27
|
+
if ((parent.type === utils_1.AST_NODE_TYPES.Property || parent.type === utils_1.AST_NODE_TYPES.MethodDefinition) &&
|
|
28
|
+
parent.key.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
29
|
+
return parent.key.name;
|
|
30
|
+
}
|
|
31
|
+
return undefined;
|
|
32
|
+
};
|
|
33
|
+
/** A component or hook: its body runs on every render. */
|
|
34
|
+
const rendersOnEveryCall = (node) => {
|
|
35
|
+
if (isFunction(node)) {
|
|
36
|
+
const name = getFunctionName(node);
|
|
37
|
+
return name !== undefined && (componentName.test(name) || hookName.test(name));
|
|
38
|
+
}
|
|
39
|
+
return (node.type === utils_1.AST_NODE_TYPES.MethodDefinition &&
|
|
40
|
+
node.key.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
41
|
+
node.key.name === 'render');
|
|
42
|
+
};
|
|
43
|
+
const meta = {
|
|
44
|
+
docs: {
|
|
45
|
+
description: 'Disallow defining segments in components and hooks.',
|
|
46
|
+
},
|
|
47
|
+
messages: {
|
|
48
|
+
'define-segment-in-render': 'Define segments at module scope: a segment defined in a component or hook is a new segment on every render.',
|
|
49
|
+
},
|
|
50
|
+
schema: [],
|
|
51
|
+
type: 'problem',
|
|
52
|
+
};
|
|
53
|
+
const create = (context) => {
|
|
54
|
+
const api = (0, sparseApi_1.getSparseApi)(context);
|
|
55
|
+
return {
|
|
56
|
+
CallExpression(node) {
|
|
57
|
+
if (api.resolve(node.callee) !== 'defineSegment') {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (context.sourceCode.getAncestors(node).some(rendersOnEveryCall)) {
|
|
61
|
+
context.report({ messageId: 'define-segment-in-render', node });
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
exports.noDefineSegmentInRenderRule = {
|
|
67
|
+
defaultOptions: [],
|
|
68
|
+
meta,
|
|
69
|
+
create,
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=noDefineSegmentInRender.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noDefineSegmentInRender.js","sourceRoot":"","sources":["../../src/rules/noDefineSegmentInRender.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.noDuplicateSegmentsRule = void 0;
|
|
4
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
5
|
+
const isAcquireCall_1 = require("../utils/isAcquireCall");
|
|
6
|
+
const sparseApi_1 = require("../utils/sparseApi");
|
|
7
|
+
/** A segment reference that can be compared by its text: `a` or `a.b.c`. */
|
|
8
|
+
const isReference = (node) => node.type === utils_1.AST_NODE_TYPES.Identifier ||
|
|
9
|
+
(node.type === utils_1.AST_NODE_TYPES.MemberExpression && !node.computed && isReference(node.object));
|
|
10
|
+
/** The value of a string literal or of a template literal without expressions. */
|
|
11
|
+
const getStaticString = (node) => {
|
|
12
|
+
if (node.type === utils_1.AST_NODE_TYPES.Literal && typeof node.value === 'string') {
|
|
13
|
+
return node.value;
|
|
14
|
+
}
|
|
15
|
+
if (node.type === utils_1.AST_NODE_TYPES.TemplateLiteral && node.expressions.length === 0) {
|
|
16
|
+
// Only a tagged template can leave an escape uncooked.
|
|
17
|
+
return node.quasis[0].value.cooked;
|
|
18
|
+
}
|
|
19
|
+
return undefined;
|
|
20
|
+
};
|
|
21
|
+
const getProperty = (node, name) => {
|
|
22
|
+
if ((node === null || node === void 0 ? void 0 : node.type) !== utils_1.AST_NODE_TYPES.ObjectExpression) {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
for (const property of node.properties) {
|
|
26
|
+
if (property.type === utils_1.AST_NODE_TYPES.Property &&
|
|
27
|
+
!property.computed &&
|
|
28
|
+
((property.key.type === utils_1.AST_NODE_TYPES.Identifier && property.key.name === name) ||
|
|
29
|
+
getStaticString(property.key) === name)) {
|
|
30
|
+
return property.value;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
};
|
|
35
|
+
const meta = {
|
|
36
|
+
docs: {
|
|
37
|
+
description: 'Disallow listing a segment twice, and defining two segments with the same key in a file.',
|
|
38
|
+
},
|
|
39
|
+
messages: {
|
|
40
|
+
'duplicate-segment': '`{{name}}` is already listed.',
|
|
41
|
+
'duplicate-key': 'A segment with the key "{{key}}" is already defined in this file.',
|
|
42
|
+
},
|
|
43
|
+
schema: [],
|
|
44
|
+
type: 'problem',
|
|
45
|
+
};
|
|
46
|
+
const create = (context) => {
|
|
47
|
+
const api = (0, sparseApi_1.getSparseApi)(context);
|
|
48
|
+
const definedKeys = new Set();
|
|
49
|
+
const checkList = (items) => {
|
|
50
|
+
const seen = new Set();
|
|
51
|
+
for (const item of items) {
|
|
52
|
+
if (item && isReference(item)) {
|
|
53
|
+
const name = context.sourceCode.getText(item);
|
|
54
|
+
if (seen.has(name)) {
|
|
55
|
+
context.report({ messageId: 'duplicate-segment', node: item, data: { name } });
|
|
56
|
+
}
|
|
57
|
+
seen.add(name);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const checkArray = (node) => {
|
|
62
|
+
if ((node === null || node === void 0 ? void 0 : node.type) === utils_1.AST_NODE_TYPES.ArrayExpression) {
|
|
63
|
+
checkList(node.elements);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
return {
|
|
67
|
+
CallExpression(node) {
|
|
68
|
+
if ((0, isAcquireCall_1.isAcquireCall)(node)) {
|
|
69
|
+
checkList(node.arguments);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const name = api.resolve(node.callee);
|
|
73
|
+
if (name === 'useSparseSegments') {
|
|
74
|
+
checkArray(node.arguments[0]);
|
|
75
|
+
}
|
|
76
|
+
else if (name === 'defineSegment') {
|
|
77
|
+
const [options] = node.arguments;
|
|
78
|
+
checkArray(getProperty(options, 'deps'));
|
|
79
|
+
const keyNode = getProperty(options, 'key');
|
|
80
|
+
const key = keyNode && getStaticString(keyNode);
|
|
81
|
+
if (key !== undefined) {
|
|
82
|
+
if (definedKeys.has(key)) {
|
|
83
|
+
context.report({ messageId: 'duplicate-key', node: keyNode, data: { key } });
|
|
84
|
+
}
|
|
85
|
+
definedKeys.add(key);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
JSXOpeningElement(node) {
|
|
90
|
+
var _a;
|
|
91
|
+
if (api.resolve(node.name) !== 'SparseScope') {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
for (const attribute of node.attributes) {
|
|
95
|
+
if (attribute.type === utils_1.AST_NODE_TYPES.JSXAttribute &&
|
|
96
|
+
attribute.name.name === 'segments' &&
|
|
97
|
+
((_a = attribute.value) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.JSXExpressionContainer) {
|
|
98
|
+
checkArray(attribute.value.expression);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
exports.noDuplicateSegmentsRule = {
|
|
105
|
+
defaultOptions: [],
|
|
106
|
+
meta,
|
|
107
|
+
create,
|
|
108
|
+
};
|
|
109
|
+
//# sourceMappingURL=noDuplicateSegments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noDuplicateSegments.js","sourceRoot":"","sources":["../../src/rules/noDuplicateSegments.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.noStaticStateKeyRule = void 0;
|
|
7
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
8
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
9
|
+
const sparseApi_1 = require("../utils/sparseApi");
|
|
10
|
+
/**
|
|
11
|
+
* The `StaticState` interface declared next to the type of the segment, with
|
|
12
|
+
* the augmentations the program adds to it. Read from the segment rather than
|
|
13
|
+
* from the function called, so that a function wrapping `defineSegment` is
|
|
14
|
+
* checked too.
|
|
15
|
+
*/
|
|
16
|
+
const getStaticState = (segment, checker) => {
|
|
17
|
+
// A type with a key and a reducer is declared somewhere.
|
|
18
|
+
const staticState = segment
|
|
19
|
+
.getSymbol()
|
|
20
|
+
.declarations[0].getSourceFile()
|
|
21
|
+
.statements.find((statement) => typescript_1.default.isInterfaceDeclaration(statement) && statement.name.text === 'StaticState');
|
|
22
|
+
return staticState && checker.getTypeAtLocation(staticState.name);
|
|
23
|
+
};
|
|
24
|
+
/** The string literal types a key type allows. */
|
|
25
|
+
const getKeys = (type) => (type.isUnion() ? type.types : [type])
|
|
26
|
+
.filter((member) => member.isStringLiteral())
|
|
27
|
+
.map((member) => member.value);
|
|
28
|
+
const meta = {
|
|
29
|
+
docs: {
|
|
30
|
+
description: 'Disallow segments with a reducer under a key of the static state.',
|
|
31
|
+
},
|
|
32
|
+
messages: {
|
|
33
|
+
'static-state-key': 'Segment key "{{key}}" is a key of the static state: acquiring a segment with a reducer under it throws.',
|
|
34
|
+
},
|
|
35
|
+
schema: [],
|
|
36
|
+
type: 'problem',
|
|
37
|
+
};
|
|
38
|
+
const create = (context) => {
|
|
39
|
+
const api = (0, sparseApi_1.getSparseApi)(context);
|
|
40
|
+
const { esTreeNodeToTSNodeMap, program } = utils_1.ESLintUtils.getParserServices(context);
|
|
41
|
+
const checker = program.getTypeChecker();
|
|
42
|
+
return {
|
|
43
|
+
CallExpression(node) {
|
|
44
|
+
if (api.resolve(node.callee) !== 'defineSegment') {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const call = esTreeNodeToTSNodeMap.get(node);
|
|
48
|
+
const segment = checker.getTypeAtLocation(call);
|
|
49
|
+
const key = segment.getProperty('key');
|
|
50
|
+
const reducer = segment.getProperty('reducer');
|
|
51
|
+
if (!key || !reducer) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const reducerType = checker.getTypeOfSymbolAtLocation(reducer, call);
|
|
55
|
+
if (reducerType.flags & typescript_1.default.TypeFlags.Undefined) {
|
|
56
|
+
// A segment without a reducer owns no slice.
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const staticState = getStaticState(segment, checker);
|
|
60
|
+
if (!staticState) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
for (const name of getKeys(checker.getTypeOfSymbolAtLocation(key, call))) {
|
|
64
|
+
if (staticState.getProperty(name)) {
|
|
65
|
+
context.report({ messageId: 'static-state-key', node, data: { key: name } });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
exports.noStaticStateKeyRule = {
|
|
72
|
+
defaultOptions: [],
|
|
73
|
+
meta,
|
|
74
|
+
create,
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=noStaticStateKey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noStaticStateKey.js","sourceRoot":"","sources":["../../src/rules/noStaticStateKey.ts"],"names":[],"mappings":";;;;;;AAAA,oDAAiE;AACjE,4DAA4B;AAC5B,kDAAkD;AAMlD;;;;;GAKG;AACH,MAAM,cAAc,GAAG,CAAC,OAAgB,EAAE,OAAuB,EAAuB,EAAE;IACxF,yDAAyD;IACzD,MAAM,WAAW,GAAG,OAAO;SACxB,SAAS,EAAG;SACZ,YAAa,CAAC,CAAC,CAAE,CAAC,aAAa,EAAE;SACjC,UAAU,CAAC,IAAI,CACd,CAAC,SAAS,EAAwC,EAAE,CAClD,oBAAE,CAAC,sBAAsB,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,KAAK,aAAa,CAChF,CAAC;IAEJ,OAAO,WAAW,IAAI,OAAO,CAAC,iBAAiB,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;AACpE,CAAC,CAAC;AAEF,kDAAkD;AAClD,MAAM,OAAO,GAAG,CAAC,IAAa,EAAY,EAAE,CAC1C,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;KACnC,MAAM,CAAC,CAAC,MAAM,EAAkC,EAAE,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC;KAC5E,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAEnC,MAAM,IAAI,GAAiB;IACzB,IAAI,EAAE;QACJ,WAAW,EAAE,mEAAmE;KACjF;IACD,QAAQ,EAAE;QACR,kBAAkB,EAChB,yGAAyG;KAC5G;IACD,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,SAAS;CAChB,CAAC;AAEF,MAAM,MAAM,GAAmB,CAAC,OAAO,EAAE,EAAE;IACzC,MAAM,GAAG,GAAG,IAAA,wBAAY,EAAC,OAAO,CAAC,CAAC;IAClC,MAAM,EAAE,qBAAqB,EAAE,OAAO,EAAE,GAAG,mBAAW,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAClF,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAEzC,OAAO;QACL,cAAc,CAAC,IAAI;YACjB,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,eAAe,EAAE,CAAC;gBACjD,OAAO;YACT,CAAC;YAED,MAAM,IAAI,GAAG,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC7C,MAAM,OAAO,GAAG,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAChD,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YACvC,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;YAE/C,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;gBACrB,OAAO;YACT,CAAC;YAED,MAAM,WAAW,GAAG,OAAO,CAAC,yBAAyB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACrE,IAAI,WAAW,CAAC,KAAK,GAAG,oBAAE,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC;gBAC/C,6CAA6C;gBAC7C,OAAO;YACT,CAAC;YAED,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACrD,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,OAAO;YACT,CAAC;YAED,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;gBACzE,IAAI,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;oBAClC,OAAO,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;gBAC/E,CAAC;YACH,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AAEW,QAAA,oBAAoB,GAAS;IACxC,cAAc,EAAE,EAAE;IAClB,IAAI;IACJ,MAAM;CACP,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.releaseAcquiredSegmentsRule = void 0;
|
|
4
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
5
|
+
const isAcquireCall_1 = require("../utils/isAcquireCall");
|
|
6
|
+
/** Whether the value of `node` is thrown away. */
|
|
7
|
+
const isDiscarded = (node) => {
|
|
8
|
+
// Never the program itself: a call or an expression around it.
|
|
9
|
+
const parent = node.parent;
|
|
10
|
+
switch (parent.type) {
|
|
11
|
+
case utils_1.AST_NODE_TYPES.ChainExpression:
|
|
12
|
+
return isDiscarded(parent);
|
|
13
|
+
case utils_1.AST_NODE_TYPES.ExpressionStatement:
|
|
14
|
+
return true;
|
|
15
|
+
case utils_1.AST_NODE_TYPES.UnaryExpression:
|
|
16
|
+
return parent.operator === 'void';
|
|
17
|
+
case utils_1.AST_NODE_TYPES.SequenceExpression:
|
|
18
|
+
return parent.expressions[parent.expressions.length - 1] !== node || isDiscarded(parent);
|
|
19
|
+
default:
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const meta = {
|
|
24
|
+
docs: {
|
|
25
|
+
description: 'Require keeping the release function that acquire returns.',
|
|
26
|
+
},
|
|
27
|
+
messages: {
|
|
28
|
+
'release-discarded': 'The release function acquire returns is discarded, so the segments are held for good. Keep it and call it once they are no longer needed.',
|
|
29
|
+
},
|
|
30
|
+
schema: [],
|
|
31
|
+
type: 'problem',
|
|
32
|
+
};
|
|
33
|
+
const create = (context) => ({
|
|
34
|
+
CallExpression(node) {
|
|
35
|
+
if ((0, isAcquireCall_1.isAcquireCall)(node) && isDiscarded(node)) {
|
|
36
|
+
context.report({ messageId: 'release-discarded', node });
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
exports.releaseAcquiredSegmentsRule = {
|
|
41
|
+
defaultOptions: [],
|
|
42
|
+
meta,
|
|
43
|
+
create,
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=releaseAcquiredSegments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"releaseAcquiredSegments.js","sourceRoot":"","sources":["../../src/rules/releaseAcquiredSegments.ts"],"names":[],"mappings":";;;AAAA,oDAA8E;AAC9E,0DAAuD;AAMvD,kDAAkD;AAClD,MAAM,WAAW,GAAG,CAAC,IAAmB,EAAW,EAAE;IACnD,+DAA+D;IAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAO,CAAC;IAE5B,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,sBAAc,CAAC,eAAe;YACjC,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC;QAC7B,KAAK,sBAAc,CAAC,mBAAmB;YACrC,OAAO,IAAI,CAAC;QACd,KAAK,sBAAc,CAAC,eAAe;YACjC,OAAO,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC;QACpC,KAAK,sBAAc,CAAC,kBAAkB;YACpC,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,IAAI,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;QAC3F;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,IAAI,GAAiB;IACzB,IAAI,EAAE;QACJ,WAAW,EAAE,4DAA4D;KAC1E;IACD,QAAQ,EAAE;QACR,mBAAmB,EACjB,2IAA2I;KAC9I;IACD,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,SAAS;CAChB,CAAC;AAEF,MAAM,MAAM,GAAmB,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC3C,cAAc,CAAC,IAAI;QACjB,IAAI,IAAA,6BAAa,EAAC,IAAI,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7C,OAAO,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;CACF,CAAC,CAAC;AAEU,QAAA,2BAA2B,GAAS;IAC/C,cAAc,EAAE,EAAE;IAClB,IAAI;IACJ,MAAM;CACP,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { TSESTree } from '@typescript-eslint/utils';
|
|
2
|
+
/**
|
|
3
|
+
* A call to the sparse controller's `acquire`: `store.sparse.acquire(...)`,
|
|
4
|
+
* or `sparse.acquire(...)` on a controller taken out of the store.
|
|
5
|
+
*/
|
|
6
|
+
export declare const isAcquireCall: (node: TSESTree.CallExpression) => boolean;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isAcquireCall = void 0;
|
|
4
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
5
|
+
const isNamed = (node, name) => node.type === utils_1.AST_NODE_TYPES.Identifier && node.name === name;
|
|
6
|
+
/**
|
|
7
|
+
* A call to the sparse controller's `acquire`: `store.sparse.acquire(...)`,
|
|
8
|
+
* or `sparse.acquire(...)` on a controller taken out of the store.
|
|
9
|
+
*/
|
|
10
|
+
const isAcquireCall = (node) => {
|
|
11
|
+
const { callee } = node;
|
|
12
|
+
if (callee.type !== utils_1.AST_NODE_TYPES.MemberExpression ||
|
|
13
|
+
callee.computed ||
|
|
14
|
+
!isNamed(callee.property, 'acquire')) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
const { object } = callee;
|
|
18
|
+
return (isNamed(object, 'sparse') ||
|
|
19
|
+
(object.type === utils_1.AST_NODE_TYPES.MemberExpression &&
|
|
20
|
+
!object.computed &&
|
|
21
|
+
isNamed(object.property, 'sparse')));
|
|
22
|
+
};
|
|
23
|
+
exports.isAcquireCall = isAcquireCall;
|
|
24
|
+
//# sourceMappingURL=isAcquireCall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isAcquireCall.js","sourceRoot":"","sources":["../../src/utils/isAcquireCall.ts"],"names":[],"mappings":";;;AAAA,oDAAoE;AAEpE,MAAM,OAAO,GAAG,CAAC,IAAmB,EAAE,IAAY,EAAW,EAAE,CAC7D,IAAI,CAAC,IAAI,KAAK,sBAAc,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC;AAEhE;;;GAGG;AACI,MAAM,aAAa,GAAG,CAAC,IAA6B,EAAW,EAAE;IACtE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAExB,IACE,MAAM,CAAC,IAAI,KAAK,sBAAc,CAAC,gBAAgB;QAC/C,MAAM,CAAC,QAAQ;QACf,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,EACpC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAE1B,OAAO,CACL,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC;QACzB,CAAC,MAAM,CAAC,IAAI,KAAK,sBAAc,CAAC,gBAAgB;YAC9C,CAAC,MAAM,CAAC,QAAQ;YAChB,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CACtC,CAAC;AACJ,CAAC,CAAC;AAnBW,QAAA,aAAa,iBAmBxB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { TSESLint, TSESTree } from '@typescript-eslint/utils';
|
|
2
|
+
/** The redux-sparse-kit exports the rules recognise. */
|
|
3
|
+
export type SparseExport = 'defineSegment' | 'createSparseReact' | 'SparseScope' | 'useSparseSegments';
|
|
4
|
+
/** The modules redux-sparse-kit's API is imported from by default. */
|
|
5
|
+
export declare const defaultImportSources: readonly string[];
|
|
6
|
+
/** Shared settings: `settings['redux-sparse-kit']` in an ESLint config. */
|
|
7
|
+
export interface SparseSettings {
|
|
8
|
+
/**
|
|
9
|
+
* Further modules that re-export redux-sparse-kit's API, such as an
|
|
10
|
+
* application's own barrel module.
|
|
11
|
+
*/
|
|
12
|
+
importSources?: string[];
|
|
13
|
+
}
|
|
14
|
+
export interface SparseApi {
|
|
15
|
+
/** Which export `node` refers to, if any. */
|
|
16
|
+
resolve(node: TSESTree.Node): SparseExport | undefined;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Finds the names a file binds to redux-sparse-kit's API: named imports, with
|
|
20
|
+
* or without an alias, namespace imports, and the members of the bindings
|
|
21
|
+
* `createSparseReact()` returns.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getSparseApi(context: Readonly<TSESLint.RuleContext<string, unknown[]>>): SparseApi;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultImportSources = void 0;
|
|
4
|
+
exports.getSparseApi = getSparseApi;
|
|
5
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
6
|
+
/** The modules redux-sparse-kit's API is imported from by default. */
|
|
7
|
+
exports.defaultImportSources = [
|
|
8
|
+
'redux-sparse-kit',
|
|
9
|
+
'redux-sparse-kit/react',
|
|
10
|
+
];
|
|
11
|
+
const sparseExports = new Set([
|
|
12
|
+
'defineSegment',
|
|
13
|
+
'createSparseReact',
|
|
14
|
+
'SparseScope',
|
|
15
|
+
'useSparseSegments',
|
|
16
|
+
]);
|
|
17
|
+
const isSparseExport = (name) => sparseExports.has(name);
|
|
18
|
+
/** The members of `createSparseReact`'s result. */
|
|
19
|
+
const reactMembers = new Set(['SparseScope', 'useSparseSegments']);
|
|
20
|
+
/**
|
|
21
|
+
* Finds the names a file binds to redux-sparse-kit's API: named imports, with
|
|
22
|
+
* or without an alias, namespace imports, and the members of the bindings
|
|
23
|
+
* `createSparseReact()` returns.
|
|
24
|
+
*/
|
|
25
|
+
function getSparseApi(context) {
|
|
26
|
+
var _a;
|
|
27
|
+
const settings = context.settings['redux-sparse-kit'];
|
|
28
|
+
const sources = new Set([...exports.defaultImportSources, ...((_a = settings === null || settings === void 0 ? void 0 : settings.importSources) !== null && _a !== void 0 ? _a : [])]);
|
|
29
|
+
// Local names bound to an export.
|
|
30
|
+
const named = new Map();
|
|
31
|
+
// Local names bound to the whole module, or to a `createSparseReact()` result.
|
|
32
|
+
const namespaces = new Set();
|
|
33
|
+
const isReactFactoryCall = (node) => (node === null || node === void 0 ? void 0 : node.type) === utils_1.AST_NODE_TYPES.CallExpression && resolve(node.callee) === 'createSparseReact';
|
|
34
|
+
const resolve = (node) => {
|
|
35
|
+
if (node.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
36
|
+
return named.get(node.name);
|
|
37
|
+
}
|
|
38
|
+
if (node.type === utils_1.AST_NODE_TYPES.MemberExpression &&
|
|
39
|
+
!node.computed &&
|
|
40
|
+
node.property.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
41
|
+
isSparseExport(node.property.name)) {
|
|
42
|
+
const { object } = node;
|
|
43
|
+
if (object.type === utils_1.AST_NODE_TYPES.Identifier && namespaces.has(object.name)) {
|
|
44
|
+
return node.property.name;
|
|
45
|
+
}
|
|
46
|
+
if (isReactFactoryCall(object) && reactMembers.has(node.property.name)) {
|
|
47
|
+
return node.property.name;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (node.type === utils_1.AST_NODE_TYPES.JSXMemberExpression &&
|
|
51
|
+
node.object.type === utils_1.AST_NODE_TYPES.JSXIdentifier &&
|
|
52
|
+
namespaces.has(node.object.name) &&
|
|
53
|
+
node.property.name === 'SparseScope') {
|
|
54
|
+
return 'SparseScope';
|
|
55
|
+
}
|
|
56
|
+
if (node.type === utils_1.AST_NODE_TYPES.JSXIdentifier) {
|
|
57
|
+
return named.get(node.name);
|
|
58
|
+
}
|
|
59
|
+
return undefined;
|
|
60
|
+
};
|
|
61
|
+
for (const statement of context.sourceCode.ast.body) {
|
|
62
|
+
if (statement.type !== utils_1.AST_NODE_TYPES.ImportDeclaration ||
|
|
63
|
+
!sources.has(statement.source.value)) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
for (const specifier of statement.specifiers) {
|
|
67
|
+
if (specifier.type === utils_1.AST_NODE_TYPES.ImportNamespaceSpecifier) {
|
|
68
|
+
namespaces.add(specifier.local.name);
|
|
69
|
+
}
|
|
70
|
+
else if (specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier) {
|
|
71
|
+
const imported = specifier.imported.type === utils_1.AST_NODE_TYPES.Identifier
|
|
72
|
+
? specifier.imported.name
|
|
73
|
+
: specifier.imported.value;
|
|
74
|
+
if (isSparseExport(imported)) {
|
|
75
|
+
named.set(specifier.local.name, imported);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Bindings made from `createSparseReact()`: `const custom = ...` and
|
|
81
|
+
// `const { SparseScope, useSparseSegments: useSegments } = ...`.
|
|
82
|
+
const visit = (node) => {
|
|
83
|
+
if (node.type === utils_1.AST_NODE_TYPES.VariableDeclarator && isReactFactoryCall(node.init)) {
|
|
84
|
+
if (node.id.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
85
|
+
namespaces.add(node.id.name);
|
|
86
|
+
}
|
|
87
|
+
else if (node.id.type === utils_1.AST_NODE_TYPES.ObjectPattern) {
|
|
88
|
+
for (const property of node.id.properties) {
|
|
89
|
+
if (property.type === utils_1.AST_NODE_TYPES.Property &&
|
|
90
|
+
property.key.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
91
|
+
reactMembers.has(property.key.name) &&
|
|
92
|
+
property.value.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
93
|
+
named.set(property.value.name, property.key.name);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// The parser knows the keys of every node it produces; they lead to
|
|
99
|
+
// nodes, arrays of nodes, or nothing.
|
|
100
|
+
for (const key of context.sourceCode.visitorKeys[node.type]) {
|
|
101
|
+
const child = node[key];
|
|
102
|
+
for (const item of Array.isArray(child) ? child : [child]) {
|
|
103
|
+
if (item) {
|
|
104
|
+
visit(item);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
// Only worth a walk when the factory is in reach.
|
|
110
|
+
if ([...named.values()].includes('createSparseReact') || namespaces.size > 0) {
|
|
111
|
+
visit(context.sourceCode.ast);
|
|
112
|
+
}
|
|
113
|
+
return { resolve };
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=sparseApi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sparseApi.js","sourceRoot":"","sources":["../../src/utils/sparseApi.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,72 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-redux-sparse-kit",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "ESLint rules for redux-sparse-kit segments and scopes",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"dynamic-reducers",
|
|
7
|
+
"eslint",
|
|
8
|
+
"eslintplugin",
|
|
9
|
+
"redux",
|
|
10
|
+
"redux-sparse-kit"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://github.com/veksa/redux-sparse-kit-eslint-plugin#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/veksa/redux-sparse-kit-eslint-plugin/issues"
|
|
15
|
+
},
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"author": {
|
|
18
|
+
"name": "Aleksandr Khizhnyi",
|
|
19
|
+
"email": "mendler88@gmail.com"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/veksa/redux-sparse-kit-eslint-plugin.git"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"lib/"
|
|
27
|
+
],
|
|
28
|
+
"sideEffects": false,
|
|
29
|
+
"main": "./lib/index.js",
|
|
30
|
+
"types": "./lib/index.d.ts",
|
|
31
|
+
"exports": {
|
|
32
|
+
"./package.json": "./package.json",
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./lib/index.d.ts",
|
|
35
|
+
"default": "./lib/index.js"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"compile": "tsc --noEmit",
|
|
40
|
+
"lint": "oxlint src/",
|
|
41
|
+
"fmt": "oxfmt",
|
|
42
|
+
"fmt:check": "oxfmt --check",
|
|
43
|
+
"test": "jest",
|
|
44
|
+
"test:coverage": "jest --coverage",
|
|
45
|
+
"build": "shx rm -rf lib && tsc --outDir lib -m node16 --moduleResolution node16 --declaration",
|
|
46
|
+
"prepack": "yarn build"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@typescript-eslint/utils": "^8.66.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/jest": "^30.0.0",
|
|
53
|
+
"@types/node": "^24.0.3",
|
|
54
|
+
"@typescript-eslint/parser": "^8.66.0",
|
|
55
|
+
"@typescript-eslint/rule-tester": "^8.66.0",
|
|
56
|
+
"eslint": "^10.8.1",
|
|
57
|
+
"jest": "^30.4.2",
|
|
58
|
+
"oxfmt": "^0.63.0",
|
|
59
|
+
"oxlint": "^1.78.0",
|
|
60
|
+
"redux": "^5.0.1",
|
|
61
|
+
"redux-sparse-kit": "0.1.0",
|
|
62
|
+
"shx": "^0.4.0",
|
|
63
|
+
"ts-jest": "^29.4.12",
|
|
64
|
+
"typescript": "6.0.3"
|
|
65
|
+
},
|
|
66
|
+
"peerDependencies": {
|
|
67
|
+
"@typescript-eslint/parser": "^8.44.1",
|
|
68
|
+
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
|
|
69
|
+
"typescript": ">=5.4 <6.1"
|
|
70
|
+
},
|
|
71
|
+
"packageManager": "yarn@4.18.0"
|
|
72
|
+
}
|