eslint-plugin-effector-units-order 0.0.2 → 0.0.3
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 +166 -14
- package/dist/package.json.js +1 -1
- package/dist/rules/keep-units-order.js +99 -3
- package/dist/types/config.d.ts +6 -1
- package/dist/utils/detect-unit-type.d.ts +11 -3
- package/dist/utils/detect-unit-type.js +48 -14
- package/dist/utils/normalize-config.js +52 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -90,23 +90,63 @@ export default [
|
|
|
90
90
|
|
|
91
91
|
## ⚙️ Options
|
|
92
92
|
|
|
93
|
-
| Option | Type | Default | Description
|
|
94
|
-
| ------------------------- | ---------- | ------------------------------------------------------- |
|
|
95
|
-
| `order` | `string[]` | `['domain', 'events', 'effects', 'stores', 'computed']` | Defines the order of unit groups
|
|
96
|
-
| `emptyLinesBetweenGroups` | `number` | `1` | Number of empty lines between groups (0-3)
|
|
97
|
-
| `groups` | `object` | See below | Custom group definitions and
|
|
98
|
-
| `customFactories` | `object` | `{}` | Maps custom factory functions to specific groups
|
|
99
|
-
| `packages` | `string[]` | `['effector', 'patronum']` | Packages to detect imports from
|
|
93
|
+
| Option | Type | Default | Description |
|
|
94
|
+
| ------------------------- | ---------- | ------------------------------------------------------- | ----------------------------------------------------------- |
|
|
95
|
+
| `order` | `string[]` | `['domain', 'events', 'effects', 'stores', 'computed']` | Defines the order of unit groups |
|
|
96
|
+
| `emptyLinesBetweenGroups` | `number` | `1` | Number of empty lines between groups (0-3) |
|
|
97
|
+
| `groups` | `object` | See below | Custom group definitions with factories and derived methods |
|
|
98
|
+
| `customFactories` | `object` | `{}` | Maps custom factory functions to specific groups |
|
|
99
|
+
| `packages` | `string[]` | `['effector', 'patronum']` | Packages to detect imports from |
|
|
100
|
+
|
|
101
|
+
**Group Options:**
|
|
102
|
+
|
|
103
|
+
Each group in `groups` can have:
|
|
104
|
+
|
|
105
|
+
- `factories: string[]` — Factory functions that create units of this type (e.g., `['createStore']`)
|
|
106
|
+
- `derivedMethods?: string[]` — Methods and properties that create derived units (e.g., `['stores.map', 'effects.pending']`)
|
|
100
107
|
|
|
101
108
|
### Default Groups
|
|
102
109
|
|
|
103
110
|
```javascript
|
|
104
111
|
{
|
|
105
|
-
domain: {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
112
|
+
domain: {
|
|
113
|
+
factories: ['createDomain']
|
|
114
|
+
},
|
|
115
|
+
events: {
|
|
116
|
+
factories: ['createEvent'],
|
|
117
|
+
derivedMethods: [
|
|
118
|
+
'events.prepend',
|
|
119
|
+
'events.map',
|
|
120
|
+
'events.filter',
|
|
121
|
+
'events.filterMap',
|
|
122
|
+
'stores.updates',
|
|
123
|
+
'stores.reinit',
|
|
124
|
+
'effects.done',
|
|
125
|
+
'effects.doneData',
|
|
126
|
+
'effects.fail',
|
|
127
|
+
'effects.failData',
|
|
128
|
+
'effects.finally'
|
|
129
|
+
]
|
|
130
|
+
},
|
|
131
|
+
effects: {
|
|
132
|
+
factories: ['createEffect'],
|
|
133
|
+
derivedMethods: [
|
|
134
|
+
'effects.map',
|
|
135
|
+
'effects.prepend',
|
|
136
|
+
'effects.filterMap'
|
|
137
|
+
]
|
|
138
|
+
},
|
|
139
|
+
stores: {
|
|
140
|
+
factories: ['createStore']
|
|
141
|
+
},
|
|
142
|
+
computed: {
|
|
143
|
+
factories: ['or', 'combine', 'merge', 'attach', 'forward'],
|
|
144
|
+
derivedMethods: [
|
|
145
|
+
'stores.map',
|
|
146
|
+
'effects.pending',
|
|
147
|
+
'effects.inFlight'
|
|
148
|
+
]
|
|
149
|
+
}
|
|
110
150
|
}
|
|
111
151
|
```
|
|
112
152
|
|
|
@@ -153,10 +193,10 @@ export const $user = userDomain.createStore(null);
|
|
|
153
193
|
|
|
154
194
|
### Computed Stores
|
|
155
195
|
|
|
156
|
-
Computed stores using `combine()` and `or()` from patronum are properly recognized:
|
|
196
|
+
Computed stores using `combine()`, `merge()`, `attach()`, `forward()`, and `or()` from patronum are properly recognized:
|
|
157
197
|
|
|
158
198
|
```typescript
|
|
159
|
-
import { createStore, combine } from "effector";
|
|
199
|
+
import { createStore, combine, merge, attach, forward } from "effector";
|
|
160
200
|
import { or } from "patronum";
|
|
161
201
|
|
|
162
202
|
export const $isLoading = createStore(false);
|
|
@@ -169,6 +209,65 @@ export const $state = combine({
|
|
|
169
209
|
});
|
|
170
210
|
```
|
|
171
211
|
|
|
212
|
+
### Derived Units
|
|
213
|
+
|
|
214
|
+
The plugin automatically recognizes derived stores and events created from existing units:
|
|
215
|
+
|
|
216
|
+
#### Derived Stores
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
import { createStore, createEffect } from "effector";
|
|
220
|
+
|
|
221
|
+
export const $products = createStore([]);
|
|
222
|
+
export const fetchProductsFx = createEffect();
|
|
223
|
+
|
|
224
|
+
export const $enrichedProducts = $products.map((products) =>
|
|
225
|
+
products.map((p) => ({ ...p, priceWithTax: p.price * 1.2 }))
|
|
226
|
+
);
|
|
227
|
+
export const $loading = fetchProductsFx.pending;
|
|
228
|
+
export const $isLoading = $loading.map((loading) => loading);
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
#### Derived Events
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
import { createEvent, createEffect, createStore } from "effector";
|
|
235
|
+
|
|
236
|
+
export const userLogin = createEvent();
|
|
237
|
+
export const fetchUserFx = createEffect();
|
|
238
|
+
export const $user = createStore(null);
|
|
239
|
+
|
|
240
|
+
export const loginWithEmail = userLogin.map((email) => ({ email })); /
|
|
241
|
+
export const fetchSucceeded = fetchUserFx.done;
|
|
242
|
+
export const fetchFailed = fetchUserFx.fail;
|
|
243
|
+
export const userUpdated = $user.updates;
|
|
244
|
+
export const resetUser = $user.reinit;
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
#### ❌ Incorrect Order (Auto-fixed)
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
import { createStore, createEffect } from "effector";
|
|
251
|
+
|
|
252
|
+
export const $loading = fetchProductsFx.pending;
|
|
253
|
+
export const fetchProductsFx = createEffect();
|
|
254
|
+
export const $products = createStore([]);
|
|
255
|
+
export const $enriched = $products.map((p) => p);
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
#### ✅ Correct Order (After auto-fix)
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
import { createStore, createEffect } from "effector";
|
|
262
|
+
|
|
263
|
+
export const fetchProductsFx = createEffect();
|
|
264
|
+
|
|
265
|
+
export const $products = createStore([]);
|
|
266
|
+
|
|
267
|
+
export const $loading = fetchProductsFx.pending;
|
|
268
|
+
export const $enriched = $products.map((p) => p);
|
|
269
|
+
```
|
|
270
|
+
|
|
172
271
|
### Custom Factories
|
|
173
272
|
|
|
174
273
|
You can map custom factory functions to specific groups:
|
|
@@ -219,6 +318,59 @@ export default [
|
|
|
219
318
|
];
|
|
220
319
|
```
|
|
221
320
|
|
|
321
|
+
### Custom Derived Methods
|
|
322
|
+
|
|
323
|
+
You can configure which methods and properties create derived units:
|
|
324
|
+
|
|
325
|
+
```javascript
|
|
326
|
+
// eslint.config.js
|
|
327
|
+
export default [
|
|
328
|
+
{
|
|
329
|
+
plugins: { "effector-order": effectorOrder },
|
|
330
|
+
rules: {
|
|
331
|
+
"effector-order/keep-units-order": [
|
|
332
|
+
"error",
|
|
333
|
+
{
|
|
334
|
+
order: ["domain", "events", "effects", "stores", "computed"],
|
|
335
|
+
groups: {
|
|
336
|
+
events: {
|
|
337
|
+
factories: ["createEvent"],
|
|
338
|
+
// Configure which methods create derived events
|
|
339
|
+
derivedMethods: [
|
|
340
|
+
"events.map",
|
|
341
|
+
"events.prepend",
|
|
342
|
+
"effects.done",
|
|
343
|
+
"stores.updates",
|
|
344
|
+
],
|
|
345
|
+
},
|
|
346
|
+
effects: {
|
|
347
|
+
factories: ["createEffect"],
|
|
348
|
+
derivedMethods: ["effects.map", "effects.prepend"],
|
|
349
|
+
},
|
|
350
|
+
computed: {
|
|
351
|
+
factories: ["combine", "merge", "attach", "forward"],
|
|
352
|
+
// Configure which methods create derived stores
|
|
353
|
+
derivedMethods: [
|
|
354
|
+
"stores.map",
|
|
355
|
+
"effects.pending",
|
|
356
|
+
"effects.inFlight",
|
|
357
|
+
],
|
|
358
|
+
},
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
],
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
];
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
**Format for `derivedMethods`:**
|
|
368
|
+
|
|
369
|
+
- `"unitType.methodName"` — for methods like `$store.map()`, `event.prepend()`
|
|
370
|
+
- `"unitType.property"` — for properties like `effect.pending`, `store.updates`
|
|
371
|
+
|
|
372
|
+
Where `unitType` is the type of the parent unit (`stores`, `events`, `effects`, `computed`), and the result will be categorized into the group that contains this `derivedMethod` in its configuration.
|
|
373
|
+
|
|
222
374
|
### No Empty Lines Between Groups
|
|
223
375
|
|
|
224
376
|
You can disable empty lines between groups by setting `emptyLinesBetweenGroups` to `0`:
|
package/dist/package.json.js
CHANGED
|
@@ -17,19 +17,62 @@ const keepUnitsOrder = createESLintRule({
|
|
|
17
17
|
return {
|
|
18
18
|
"Program:exit": () => {
|
|
19
19
|
let units = [];
|
|
20
|
+
let unitsMap = /* @__PURE__ */ new Map();
|
|
21
|
+
let processedNames = /* @__PURE__ */ new Set();
|
|
22
|
+
let isBaseUnitType = (type) =>
|
|
23
|
+
["effects", "domain", "events", "stores"].includes(type);
|
|
20
24
|
for (let potentialUnit of potentialUnits) {
|
|
25
|
+
if (!potentialUnit.name || processedNames.has(potentialUnit.name)) {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (potentialUnit.node.init?.type !== "CallExpression") {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
let unitType = detectUnitType({
|
|
32
|
+
importMap: importedFromEffector,
|
|
33
|
+
node: potentialUnit.node.init,
|
|
34
|
+
unitsMap: /* @__PURE__ */ new Map(),
|
|
35
|
+
// Empty for base units detection
|
|
36
|
+
domainMap,
|
|
37
|
+
config,
|
|
38
|
+
});
|
|
39
|
+
if (!unitType || !isBaseUnitType(unitType)) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
unitsMap.set(potentialUnit.name, unitType);
|
|
43
|
+
processedNames.add(potentialUnit.name);
|
|
44
|
+
units.push({
|
|
45
|
+
statement: potentialUnit.statement,
|
|
46
|
+
node: potentialUnit.node,
|
|
47
|
+
line: potentialUnit.line,
|
|
48
|
+
name: potentialUnit.name,
|
|
49
|
+
type: unitType,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
for (let potentialUnit of potentialUnits) {
|
|
53
|
+
if (!potentialUnit.name || processedNames.has(potentialUnit.name)) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
21
56
|
if (potentialUnit.node.init?.type !== "CallExpression") {
|
|
22
57
|
continue;
|
|
23
58
|
}
|
|
59
|
+
let { callee } = potentialUnit.node.init;
|
|
60
|
+
if (callee.type !== "Identifier") {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
24
63
|
let unitType = detectUnitType({
|
|
25
64
|
importMap: importedFromEffector,
|
|
26
65
|
node: potentialUnit.node.init,
|
|
27
66
|
domainMap,
|
|
67
|
+
unitsMap,
|
|
68
|
+
// Now we have base units
|
|
28
69
|
config,
|
|
29
70
|
});
|
|
30
|
-
if (!unitType) {
|
|
71
|
+
if (!unitType || unitType !== "computed") {
|
|
31
72
|
continue;
|
|
32
73
|
}
|
|
74
|
+
unitsMap.set(potentialUnit.name, unitType);
|
|
75
|
+
processedNames.add(potentialUnit.name);
|
|
33
76
|
units.push({
|
|
34
77
|
statement: potentialUnit.statement,
|
|
35
78
|
node: potentialUnit.node,
|
|
@@ -38,6 +81,52 @@ const keepUnitsOrder = createESLintRule({
|
|
|
38
81
|
type: unitType,
|
|
39
82
|
});
|
|
40
83
|
}
|
|
84
|
+
for (let potentialUnit of potentialUnits) {
|
|
85
|
+
if (!potentialUnit.name || processedNames.has(potentialUnit.name)) {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (potentialUnit.node.init?.type === "CallExpression") {
|
|
89
|
+
let unitType = detectUnitType({
|
|
90
|
+
importMap: importedFromEffector,
|
|
91
|
+
node: potentialUnit.node.init,
|
|
92
|
+
domainMap,
|
|
93
|
+
unitsMap,
|
|
94
|
+
config,
|
|
95
|
+
});
|
|
96
|
+
if (unitType) {
|
|
97
|
+
unitsMap.set(potentialUnit.name, unitType);
|
|
98
|
+
processedNames.add(potentialUnit.name);
|
|
99
|
+
units.push({
|
|
100
|
+
statement: potentialUnit.statement,
|
|
101
|
+
node: potentialUnit.node,
|
|
102
|
+
line: potentialUnit.line,
|
|
103
|
+
name: potentialUnit.name,
|
|
104
|
+
type: unitType,
|
|
105
|
+
});
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (potentialUnit.node.init?.type === "MemberExpression") {
|
|
110
|
+
let unitType = detectUnitType({
|
|
111
|
+
importMap: importedFromEffector,
|
|
112
|
+
node: potentialUnit.node.init,
|
|
113
|
+
domainMap,
|
|
114
|
+
unitsMap,
|
|
115
|
+
config,
|
|
116
|
+
});
|
|
117
|
+
if (unitType) {
|
|
118
|
+
unitsMap.set(potentialUnit.name, unitType);
|
|
119
|
+
processedNames.add(potentialUnit.name);
|
|
120
|
+
units.push({
|
|
121
|
+
statement: potentialUnit.statement,
|
|
122
|
+
node: potentialUnit.node,
|
|
123
|
+
line: potentialUnit.line,
|
|
124
|
+
name: potentialUnit.name,
|
|
125
|
+
type: unitType,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
41
130
|
let usedDomains = /* @__PURE__ */ new Set();
|
|
42
131
|
for (let unit of units) {
|
|
43
132
|
if (
|
|
@@ -55,6 +144,7 @@ const keepUnitsOrder = createESLintRule({
|
|
|
55
144
|
unit.isUsedByOthers = usedDomains.has(unit.name);
|
|
56
145
|
}
|
|
57
146
|
}
|
|
147
|
+
units.sort((a, b) => a.line - b.line);
|
|
58
148
|
let violations = validateOrder({ config, units });
|
|
59
149
|
if (violations.length === 0) {
|
|
60
150
|
return;
|
|
@@ -80,10 +170,16 @@ const keepUnitsOrder = createESLintRule({
|
|
|
80
170
|
},
|
|
81
171
|
VariableDeclaration: (declarationNode) => {
|
|
82
172
|
for (let node of declarationNode.declarations) {
|
|
83
|
-
if (
|
|
173
|
+
if (
|
|
174
|
+
node.init?.type !== "CallExpression" &&
|
|
175
|
+
node.init?.type !== "MemberExpression"
|
|
176
|
+
) {
|
|
84
177
|
continue;
|
|
85
178
|
}
|
|
86
|
-
if (
|
|
179
|
+
if (
|
|
180
|
+
node.init.type === "CallExpression" &&
|
|
181
|
+
node.init.callee.type === "Identifier"
|
|
182
|
+
) {
|
|
87
183
|
let functionName = node.init.callee.name;
|
|
88
184
|
if (importedFromEffector.has(functionName)) {
|
|
89
185
|
for (let [groupName, groupOptions] of Object.entries(
|
package/dist/types/config.d.ts
CHANGED
|
@@ -17,7 +17,6 @@ export interface EffectorOrderOptions {
|
|
|
17
17
|
/**
|
|
18
18
|
* Number of empty lines between groups.
|
|
19
19
|
* @default 1
|
|
20
|
-
* @minimum 0
|
|
21
20
|
*/
|
|
22
21
|
emptyLinesBetweenGroups?: number;
|
|
23
22
|
/**
|
|
@@ -36,6 +35,12 @@ export interface EffectorOrderOptions {
|
|
|
36
35
|
* Options for a unit group.
|
|
37
36
|
*/
|
|
38
37
|
export interface GroupOptions {
|
|
38
|
+
/**
|
|
39
|
+
* Methods and properties that create units of this type.
|
|
40
|
+
* Format: "unitType.methodOrProperty".
|
|
41
|
+
* @example ['stores.map', 'effects.pending', 'computed.restore']
|
|
42
|
+
*/
|
|
43
|
+
derivedMethods?: string[];
|
|
39
44
|
/**
|
|
40
45
|
* List of factories that belong to this group.
|
|
41
46
|
* @example ['authFactory', 'apiFactory']
|
|
@@ -12,19 +12,26 @@ interface Parameters {
|
|
|
12
12
|
* Map of imported names to package names.
|
|
13
13
|
*/
|
|
14
14
|
importMap: Map<string, string>;
|
|
15
|
-
node: TSESTree.CallExpression;
|
|
15
|
+
node: TSESTree.CallExpression | TSESTree.MemberExpression;
|
|
16
16
|
/**
|
|
17
17
|
* Normalized configuration with groups and factories.
|
|
18
18
|
*/
|
|
19
19
|
config: NormalizedConfig;
|
|
20
|
+
/**
|
|
21
|
+
* Map of unit names to their types
|
|
22
|
+
* Key: unit variable name (e.g., '$store', 'event', 'effectFx')
|
|
23
|
+
* Value: unit type (e.g., 'stores', 'events', 'effects')
|
|
24
|
+
*/
|
|
25
|
+
unitsMap: Map<string, UnitType>;
|
|
20
26
|
}
|
|
21
27
|
/**
|
|
22
|
-
* Detects the unit type from a CallExpression node.
|
|
28
|
+
* Detects the unit type from a CallExpression or MemberExpression node.
|
|
23
29
|
*
|
|
24
30
|
* Handles:
|
|
25
31
|
* - Direct calls: `createEvent()`, `createStore()`, etc.
|
|
26
32
|
* - Domain calls: `domain.createEvent()`, `domain.createStore()`, etc.
|
|
27
|
-
* - Computed: `or()`, `combine()`.
|
|
33
|
+
* - Computed: `or()`, `combine()`, `merge()`, `attach()`, `forward()`, `restore()`.
|
|
34
|
+
* - Derived units: `$store.map()`, `effect.pending`, `event.map()`, etc.
|
|
28
35
|
*
|
|
29
36
|
* @param params - Parameters for detection.
|
|
30
37
|
* @returns UnitType if detected, null otherwise.
|
|
@@ -34,5 +41,6 @@ export declare function detectUnitType({
|
|
|
34
41
|
domainMap,
|
|
35
42
|
config,
|
|
36
43
|
node,
|
|
44
|
+
unitsMap,
|
|
37
45
|
}: Parameters): UnitType | null;
|
|
38
46
|
export {};
|
|
@@ -1,32 +1,66 @@
|
|
|
1
|
-
function detectUnitType({ importMap, domainMap, config, node }) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
function detectUnitType({ importMap, domainMap, config, node, unitsMap }) {
|
|
2
|
+
if (node.type === "CallExpression") {
|
|
3
|
+
let { callee } = node;
|
|
4
|
+
if (callee.type === "Identifier") {
|
|
5
|
+
let functionName = callee.name;
|
|
6
|
+
if (!importMap.has(functionName)) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
for (let [groupName, groupOptions] of Object.entries(config.groups)) {
|
|
10
|
+
if (groupOptions.factories.includes(functionName)) {
|
|
11
|
+
return groupName;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
6
14
|
return null;
|
|
7
15
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
16
|
+
if (callee.type === "MemberExpression") {
|
|
17
|
+
let { property, object } = callee;
|
|
18
|
+
if (object.type !== "Identifier") {
|
|
19
|
+
return null;
|
|
11
20
|
}
|
|
21
|
+
if (property.type !== "Identifier") {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
let objectName = object.name;
|
|
25
|
+
let methodName = property.name;
|
|
26
|
+
if (domainMap.get(objectName)) {
|
|
27
|
+
for (let [groupName, groupOptions] of Object.entries(config.groups)) {
|
|
28
|
+
if (groupOptions.factories.includes(methodName)) {
|
|
29
|
+
return groupName;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
let unitType = unitsMap.get(objectName);
|
|
35
|
+
if (unitType) {
|
|
36
|
+
let derivedMethodKey = `${unitType}.${methodName}`;
|
|
37
|
+
for (let [groupName, groupOptions] of Object.entries(config.groups)) {
|
|
38
|
+
if (groupOptions.derivedMethods?.includes(derivedMethodKey)) {
|
|
39
|
+
return groupName;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
12
44
|
}
|
|
13
45
|
return null;
|
|
14
46
|
}
|
|
15
|
-
if (
|
|
16
|
-
let { property, object } =
|
|
47
|
+
if (node.type === "MemberExpression") {
|
|
48
|
+
let { property, object } = node;
|
|
17
49
|
if (object.type !== "Identifier") {
|
|
18
50
|
return null;
|
|
19
51
|
}
|
|
20
52
|
if (property.type !== "Identifier") {
|
|
21
53
|
return null;
|
|
22
54
|
}
|
|
23
|
-
let
|
|
24
|
-
let
|
|
25
|
-
|
|
55
|
+
let unitName = object.name;
|
|
56
|
+
let propertyName = property.name;
|
|
57
|
+
let unitType = unitsMap.get(unitName);
|
|
58
|
+
if (!unitType) {
|
|
26
59
|
return null;
|
|
27
60
|
}
|
|
61
|
+
let derivedMethodKey = `${unitType}.${propertyName}`;
|
|
28
62
|
for (let [groupName, groupOptions] of Object.entries(config.groups)) {
|
|
29
|
-
if (groupOptions.
|
|
63
|
+
if (groupOptions.derivedMethods?.includes(derivedMethodKey)) {
|
|
30
64
|
return groupName;
|
|
31
65
|
}
|
|
32
66
|
}
|
|
@@ -1,15 +1,62 @@
|
|
|
1
1
|
const DEFAULT_GROUPS = {
|
|
2
2
|
computed: {
|
|
3
|
-
factories: ["or", "combine"],
|
|
3
|
+
factories: ["or", "combine", "merge", "attach", "forward"],
|
|
4
|
+
derivedMethods: [
|
|
5
|
+
// Derived stores (идут после базовых stores)
|
|
6
|
+
"stores.map",
|
|
7
|
+
// $store.map() → computed store
|
|
8
|
+
"effects.pending",
|
|
9
|
+
// effect.pending → computed store
|
|
10
|
+
"effects.inFlight",
|
|
11
|
+
// effect.inFlight → computed store
|
|
12
|
+
// Derived events на computed тоже идут в computed
|
|
13
|
+
"computed.map",
|
|
14
|
+
// merge([...]).map() → computed
|
|
15
|
+
],
|
|
4
16
|
},
|
|
5
17
|
effects: {
|
|
6
18
|
factories: ["createEffect"],
|
|
19
|
+
derivedMethods: [
|
|
20
|
+
"effects.map",
|
|
21
|
+
// effect.map() → effect
|
|
22
|
+
"effects.prepend",
|
|
23
|
+
// effect.prepend() → effect
|
|
24
|
+
"effects.filterMap",
|
|
25
|
+
// effect.filterMap() → effect
|
|
26
|
+
],
|
|
7
27
|
},
|
|
8
28
|
domain: {
|
|
9
29
|
factories: ["createDomain"],
|
|
10
30
|
},
|
|
11
31
|
events: {
|
|
12
32
|
factories: ["createEvent"],
|
|
33
|
+
derivedMethods: [
|
|
34
|
+
// Event Methods, которые создают derived events
|
|
35
|
+
"events.prepend",
|
|
36
|
+
// event.prepend() → event
|
|
37
|
+
"events.map",
|
|
38
|
+
// event.map() → event
|
|
39
|
+
"events.filter",
|
|
40
|
+
// event.filter() → event
|
|
41
|
+
"events.filterMap",
|
|
42
|
+
// event.filterMap() → event
|
|
43
|
+
// Store Properties, которые возвращают events
|
|
44
|
+
"stores.updates",
|
|
45
|
+
// store.updates → event
|
|
46
|
+
"stores.reinit",
|
|
47
|
+
// store.reinit → event
|
|
48
|
+
// Effect Properties, которые возвращают events
|
|
49
|
+
"effects.done",
|
|
50
|
+
// effect.done → event
|
|
51
|
+
"effects.doneData",
|
|
52
|
+
// effect.doneData → event
|
|
53
|
+
"effects.fail",
|
|
54
|
+
// effect.fail → event
|
|
55
|
+
"effects.failData",
|
|
56
|
+
// effect.failData → event
|
|
57
|
+
"effects.finally",
|
|
58
|
+
// effect.finally → event
|
|
59
|
+
],
|
|
13
60
|
},
|
|
14
61
|
stores: {
|
|
15
62
|
factories: ["createStore"],
|
|
@@ -33,6 +80,10 @@ function normalizeConfig(options = {}) {
|
|
|
33
80
|
...(groups[groupName]?.factories ?? []),
|
|
34
81
|
...groupOptions.factories,
|
|
35
82
|
],
|
|
83
|
+
derivedMethods: [
|
|
84
|
+
...(groups[groupName]?.derivedMethods ?? []),
|
|
85
|
+
...(groupOptions.derivedMethods ?? []),
|
|
86
|
+
],
|
|
36
87
|
};
|
|
37
88
|
}
|
|
38
89
|
}
|