@neralabs/rerail-pack-vue 0.1.4 → 0.1.5

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.
@@ -0,0 +1,483 @@
1
+ {
2
+ "format": "rerail.policy/v1",
3
+ "id": "eslint-plugin-vue-no-watch-after-await",
4
+ "revision": 1,
5
+ "mode": "steer",
6
+ "description": "Call watch and watchEffect before any await in a Vue setup() function, or keep their stop handle; a watcher made after an await is not tied to the component and leaks.",
7
+ "scope": {
8
+ "include": [
9
+ "**/*.vue"
10
+ ],
11
+ "exclude": []
12
+ },
13
+ "clauses": [
14
+ {
15
+ "id": "shared",
16
+ "define": {
17
+ "language": "vue",
18
+ "utils": {
19
+ "in-script-setup": {
20
+ "inside": {
21
+ "stopBy": "end",
22
+ "follows": {
23
+ "stopBy": {
24
+ "kind": "empty_statement",
25
+ "host": {
26
+ "kind": "start_tag",
27
+ "regex": "^<script\\b"
28
+ }
29
+ },
30
+ "kind": "empty_statement",
31
+ "host": {
32
+ "kind": "start_tag",
33
+ "regex": "^<script(?:\\s+[^\\s\"'<>/=]+(?:\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s\"'<>=`]+))?)*\\s+setup(?:[\\s/>=]|$)"
34
+ }
35
+ }
36
+ }
37
+ },
38
+ "component-callee": {
39
+ "any": [
40
+ {
41
+ "kind": "member_expression",
42
+ "all": [
43
+ {
44
+ "has": {
45
+ "field": "object",
46
+ "kind": "identifier"
47
+ }
48
+ },
49
+ {
50
+ "has": {
51
+ "field": "property",
52
+ "regex": "^(?:component|mixin)$"
53
+ }
54
+ }
55
+ ]
56
+ },
57
+ {
58
+ "kind": "member_expression",
59
+ "all": [
60
+ {
61
+ "has": {
62
+ "field": "object",
63
+ "kind": "identifier",
64
+ "regex": "^Vue$"
65
+ }
66
+ },
67
+ {
68
+ "has": {
69
+ "field": "property",
70
+ "regex": "^extend$"
71
+ }
72
+ }
73
+ ]
74
+ },
75
+ {
76
+ "kind": "identifier",
77
+ "regex": "^defineNuxtComponent$"
78
+ },
79
+ {
80
+ "kind": "identifier",
81
+ "regex": "^(?:component|createApp|defineComponent)$",
82
+ "resolves": {
83
+ "binding": {
84
+ "site": {
85
+ "kind": "import_specifier",
86
+ "inside": {
87
+ "stopBy": "end",
88
+ "kind": "import_statement",
89
+ "has": {
90
+ "field": "source",
91
+ "kind": "string",
92
+ "value": {
93
+ "regex": "^(?:vue|@vue/composition-api|@nuxtjs/composition-api|#imports)$"
94
+ }
95
+ }
96
+ }
97
+ }
98
+ }
99
+ }
100
+ }
101
+ ]
102
+ },
103
+ "vue-object": {
104
+ "kind": "object",
105
+ "any": [
106
+ {
107
+ "all": [
108
+ {
109
+ "inside": {
110
+ "field": "value",
111
+ "stopBy": {
112
+ "not": {
113
+ "any": [
114
+ {
115
+ "kind": "parenthesized_expression"
116
+ },
117
+ {
118
+ "kind": "as_expression"
119
+ },
120
+ {
121
+ "kind": "satisfies_expression"
122
+ }
123
+ ]
124
+ }
125
+ },
126
+ "kind": "export_statement"
127
+ }
128
+ },
129
+ {
130
+ "not": {
131
+ "matches": "in-script-setup"
132
+ }
133
+ }
134
+ ]
135
+ },
136
+ {
137
+ "all": [
138
+ {
139
+ "nthChild": {
140
+ "position": 1,
141
+ "reverse": true
142
+ }
143
+ },
144
+ {
145
+ "inside": {
146
+ "stopBy": "neighbor",
147
+ "kind": "arguments",
148
+ "inside": {
149
+ "stopBy": "neighbor",
150
+ "kind": "call_expression",
151
+ "has": {
152
+ "field": "function",
153
+ "matches": "component-callee"
154
+ }
155
+ }
156
+ }
157
+ }
158
+ ]
159
+ },
160
+ {
161
+ "all": [
162
+ {
163
+ "nthChild": 1
164
+ },
165
+ {
166
+ "inside": {
167
+ "stopBy": "neighbor",
168
+ "kind": "arguments",
169
+ "inside": {
170
+ "stopBy": "neighbor",
171
+ "kind": "new_expression",
172
+ "has": {
173
+ "field": "constructor",
174
+ "kind": "identifier",
175
+ "regex": "^Vue$"
176
+ }
177
+ }
178
+ }
179
+ }
180
+ ]
181
+ }
182
+ ]
183
+ },
184
+ "setup-fn": {
185
+ "any": [
186
+ {
187
+ "kind": "method_definition",
188
+ "has": {
189
+ "field": "name",
190
+ "regex": "^(?:setup|'setup'|\"setup\")$"
191
+ },
192
+ "inside": {
193
+ "stopBy": "neighbor",
194
+ "kind": "object",
195
+ "matches": "vue-object"
196
+ }
197
+ },
198
+ {
199
+ "any": [
200
+ {
201
+ "kind": "function_expression"
202
+ },
203
+ {
204
+ "kind": "arrow_function"
205
+ }
206
+ ],
207
+ "inside": {
208
+ "stopBy": "neighbor",
209
+ "field": "value",
210
+ "kind": "pair",
211
+ "has": {
212
+ "field": "key",
213
+ "regex": "^(?:setup|'setup'|\"setup\")$"
214
+ },
215
+ "inside": {
216
+ "stopBy": "neighbor",
217
+ "kind": "object",
218
+ "matches": "vue-object"
219
+ }
220
+ }
221
+ }
222
+ ]
223
+ },
224
+ "watch-callee": {
225
+ "any": [
226
+ {
227
+ "kind": "identifier",
228
+ "resolves": {
229
+ "binding": {
230
+ "site": {
231
+ "kind": "import_specifier",
232
+ "has": {
233
+ "field": "name",
234
+ "regex": "^(?:watch|watchEffect)$"
235
+ },
236
+ "inside": {
237
+ "stopBy": "end",
238
+ "kind": "import_statement",
239
+ "has": {
240
+ "field": "source",
241
+ "kind": "string",
242
+ "value": {
243
+ "regex": "^(?:vue|@vue/composition-api|@nuxtjs/composition-api|#imports)$"
244
+ }
245
+ }
246
+ }
247
+ }
248
+ }
249
+ }
250
+ },
251
+ {
252
+ "kind": "member_expression",
253
+ "all": [
254
+ {
255
+ "has": {
256
+ "field": "property",
257
+ "regex": "^(?:watch|watchEffect)$"
258
+ }
259
+ },
260
+ {
261
+ "has": {
262
+ "field": "object",
263
+ "kind": "identifier",
264
+ "resolves": {
265
+ "binding": {
266
+ "site": {
267
+ "kind": "namespace_import",
268
+ "inside": {
269
+ "stopBy": "end",
270
+ "kind": "import_statement",
271
+ "has": {
272
+ "field": "source",
273
+ "kind": "string",
274
+ "value": {
275
+ "regex": "^(?:vue|@vue/composition-api|@nuxtjs/composition-api|#imports)$"
276
+ }
277
+ }
278
+ }
279
+ }
280
+ }
281
+ }
282
+ }
283
+ }
284
+ ]
285
+ }
286
+ ]
287
+ },
288
+ "setup-await": {
289
+ "kind": "await_expression",
290
+ "inside": {
291
+ "stopBy": {
292
+ "any": [
293
+ {
294
+ "kind": "function_declaration"
295
+ },
296
+ {
297
+ "kind": "function_expression"
298
+ },
299
+ {
300
+ "kind": "arrow_function"
301
+ },
302
+ {
303
+ "kind": "method_definition"
304
+ },
305
+ {
306
+ "kind": "generator_function"
307
+ },
308
+ {
309
+ "kind": "generator_function_declaration"
310
+ }
311
+ ]
312
+ },
313
+ "matches": "setup-fn"
314
+ }
315
+ },
316
+ "has-setup-await": {
317
+ "any": [
318
+ {
319
+ "matches": "setup-await"
320
+ },
321
+ {
322
+ "has": {
323
+ "stopBy": "end",
324
+ "matches": "setup-await"
325
+ }
326
+ }
327
+ ]
328
+ },
329
+ "after-await": {
330
+ "any": [
331
+ {
332
+ "follows": {
333
+ "stopBy": "end",
334
+ "matches": "has-setup-await"
335
+ }
336
+ },
337
+ {
338
+ "inside": {
339
+ "stopBy": {
340
+ "matches": "setup-fn"
341
+ },
342
+ "all": [
343
+ {
344
+ "not": {
345
+ "matches": "setup-fn"
346
+ }
347
+ },
348
+ {
349
+ "any": [
350
+ {
351
+ "matches": "setup-await"
352
+ },
353
+ {
354
+ "follows": {
355
+ "stopBy": "end",
356
+ "matches": "has-setup-await"
357
+ }
358
+ }
359
+ ]
360
+ }
361
+ ]
362
+ }
363
+ }
364
+ ]
365
+ }
366
+ }
367
+ }
368
+ },
369
+ {
370
+ "id": "watch-after-await",
371
+ "forbid": {
372
+ "ast": {
373
+ "language": "vue",
374
+ "embedded": "script-block",
375
+ "rule": {
376
+ "all": [
377
+ {
378
+ "kind": "call_expression"
379
+ },
380
+ {
381
+ "has": {
382
+ "field": "function",
383
+ "matches": "watch-callee"
384
+ }
385
+ },
386
+ {
387
+ "not": {
388
+ "inside": {
389
+ "stopBy": "end",
390
+ "kind": "statement_block",
391
+ "host": {
392
+ "kind": "template_element"
393
+ }
394
+ }
395
+ }
396
+ },
397
+ {
398
+ "inside": {
399
+ "stopBy": {
400
+ "any": [
401
+ {
402
+ "kind": "function_declaration"
403
+ },
404
+ {
405
+ "kind": "function_expression"
406
+ },
407
+ {
408
+ "kind": "arrow_function"
409
+ },
410
+ {
411
+ "kind": "method_definition"
412
+ },
413
+ {
414
+ "kind": "generator_function"
415
+ },
416
+ {
417
+ "kind": "generator_function_declaration"
418
+ }
419
+ ]
420
+ },
421
+ "matches": "setup-fn"
422
+ }
423
+ },
424
+ {
425
+ "matches": "after-await"
426
+ },
427
+ {
428
+ "not": {
429
+ "inside": {
430
+ "stopBy": {
431
+ "not": {
432
+ "kind": "parenthesized_expression"
433
+ }
434
+ },
435
+ "any": [
436
+ {
437
+ "kind": "variable_declarator"
438
+ },
439
+ {
440
+ "kind": "assignment_expression"
441
+ },
442
+ {
443
+ "kind": "augmented_assignment_expression"
444
+ },
445
+ {
446
+ "kind": "pair"
447
+ },
448
+ {
449
+ "kind": "array"
450
+ },
451
+ {
452
+ "kind": "call_expression"
453
+ },
454
+ {
455
+ "kind": "arguments",
456
+ "inside": {
457
+ "stopBy": "neighbor",
458
+ "kind": "call_expression"
459
+ }
460
+ }
461
+ ]
462
+ }
463
+ }
464
+ }
465
+ ]
466
+ }
467
+ }
468
+ },
469
+ "violation": {
470
+ "anchor": "witness.span",
471
+ "code": "vue/no-watch-after-await",
472
+ "message": "Move this watch call above the first await in setup(), or keep its stop handle and call it on unmount.",
473
+ "suppress": {
474
+ "eslint": {
475
+ "rules": [
476
+ "vue/no-watch-after-await"
477
+ ]
478
+ }
479
+ }
480
+ }
481
+ }
482
+ ]
483
+ }