Skip to content

Commit 060b650

Browse files
fix/TRI 1149/cover all duplicated cases (#398)
* feat: select node by property key name * feat: get `IfStatement`s recursively * refactor: make `getNodeBody` more readable * refactor: enshorter rule code * refactor: remove additional spaces * Create lovely-teachers-taste.md --------- Co-authored-by: Eric Allam <[email protected]>
1 parent 6186a14 commit 060b650

File tree

3 files changed

+121
-16
lines changed

3 files changed

+121
-16
lines changed

.changeset/lovely-teachers-taste.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@trigger.dev/eslint-plugin": patch
3+
---
4+
5+
Fixes #391, now handling jobs when using new Job instead of client.defineJob

packages/eslint-plugin/lib/rules/no-duplicated-task-keys.js

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,21 @@ module.exports = {
4949
return property.name;
5050
}
5151

52-
const groupExpressionsByTask = (ExpressionStatements, map = new Map()) => ExpressionStatements.reduce((acc, { expression }) => {
53-
const taskName = getTaskName(expression);
54-
const taskKey = getKey(expression);
55-
52+
const groupByTaskKeyAndName = (acc, { taskKey, taskName }) => {
5653
if (acc.has(taskName)) {
5754
acc.get(taskName).push(taskKey);
5855
} else {
5956
acc.set(taskName, [taskKey]);
6057
}
6158

6259
return acc;
60+
}
61+
62+
const groupExpressionsByTask = (ExpressionStatements, map = new Map()) => ExpressionStatements.reduce((acc, { expression }) => {
63+
const taskName = getTaskName(expression);
64+
const taskKey = getKey(expression);
65+
66+
return groupByTaskKeyAndName(acc, { taskKey, taskName });
6367
}, map);
6468

6569
const groupVariableDeclarationsByTask = VariableDeclarations => VariableDeclarations.reduce((acc, { declarations }) => {
@@ -70,30 +74,46 @@ module.exports = {
7074

7175
const taskKey = getKey(declaration.init);
7276

73-
if (acc.has(taskName)) {
74-
acc.get(taskName).push(taskKey);
75-
} else {
76-
acc.set(taskName, [taskKey]);
77-
}
77+
groupByTaskKeyAndName(acc, { taskKey, taskName });
7878
});
7979

8080
return acc;
8181
}, new Map());
8282

83-
return {
84-
"CallExpression[callee.property.name='defineJob'] ObjectExpression BlockStatement": (node) => {
85-
const VariableDeclarations = node.body.filter((arg) => arg.type === 'VariableDeclaration');
83+
const getInnerIfStatementBodies = (body) => body
84+
.filter((arg) => arg.type === 'IfStatement')
85+
.reduce((acc, arg) => {
86+
const consequent = arg.consequent.body;
8687

87-
const grouped = groupVariableDeclarationsByTask(VariableDeclarations);
88+
const AlternateBodies = getInnerIfStatementBodies(consequent);
89+
90+
const body = consequent.filter((arg) => arg.type !== 'IfStatement');
91+
92+
return acc.concat(body).concat(AlternateBodies);
93+
}, [])
94+
95+
const getNodeBody = (node) => {
96+
const body = node.value.body.body;
97+
98+
return body
99+
.filter((arg) => arg.type !== 'IfStatement')
100+
.concat(getInnerIfStatementBodies(body));
101+
}
88102

89-
const ExpressionStatements = node.body.filter((arg) => arg.type === 'ExpressionStatement');
103+
return {
104+
"Property[key.name='run']": (node) => {
105+
const body = getNodeBody(node);
90106

107+
const VariableDeclarations = body.filter((arg) => arg.type === 'VariableDeclaration');
108+
109+
const grouped = groupVariableDeclarationsByTask(VariableDeclarations);
110+
111+
const ExpressionStatements = body.filter((arg) => arg.type === 'ExpressionStatement');
112+
91113
// it'll be a map of taskName => [key1, key2, ...]
92114
const groupedByTask = groupExpressionsByTask(ExpressionStatements, grouped);
93-
94115
groupedByTask.forEach((keys) => {
95116
const duplicated = keys.find((key, index) => keys.indexOf(key) !== index);
96-
97117
if (duplicated) {
98118
context.report({
99119
node,

packages/eslint-plugin/tests/lib/rules/no-duplicated-task-keys.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,86 @@ ruleTester.run("no-duplicated-task-keys", rule, {
240240
{ message: "Task key 'Get Tag' is duplicated" },
241241
{ message: "Task key 'Tag ' is duplicated" },
242242
]
243+
},
244+
{
245+
code: `import { Job, eventTrigger } from "@trigger.dev/sdk";
246+
import { client } from "@/trigger";
247+
248+
// your first job
249+
new Job(client, {
250+
id: "example-job",
251+
name: "Example Job",
252+
version: "0.0.1",
253+
trigger: eventTrigger({
254+
name: "example.event",
255+
}),
256+
run: async (payload, io, ctx) => {
257+
await io.runTask("example.task", { name: "Task 1" }, async () => {});
258+
await io.runTask("example.task", { name: "Task 2" }, async () => {});
259+
},
260+
});`,
261+
errors: [
262+
{ message: "Task key 'example.task' is duplicated" },
263+
]
264+
},
265+
{
266+
code: `import { Job, eventTrigger } from "@trigger.dev/sdk";
267+
import { client } from "@/trigger";
268+
269+
// your first job
270+
new Job(client, {
271+
id: "example-job",
272+
name: "Example Job",
273+
version: "0.0.1",
274+
trigger: eventTrigger({
275+
name: "example.event",
276+
}),
277+
run: async (payload, io, ctx) => {
278+
await io.runTask("example.task", { name: "Task 1" }, async () => {});
279+
280+
await io.anotherTask("different task", { name: "Task 1" }, async () => {});
281+
282+
if (true) {
283+
await io.runTask("example.task", { name: "Task 2" }, async () => {});
284+
285+
if (true) {
286+
await io.runTask("example.task", { name: "Task 3" }, async () => {});
287+
await io.anotherTask("different task", { name: "Task 1" }, async () => {});
288+
}
289+
}
290+
},
291+
});`,
292+
errors: [
293+
{ message: "Task key 'example.task' is duplicated" },
294+
{ message: "Task key 'different task' is duplicated" },
295+
]
296+
},
297+
{
298+
code: `import { Job, eventTrigger } from "@trigger.dev/sdk";
299+
import { client } from "@/trigger";
300+
301+
// your first job
302+
new Job(client, {
303+
id: "example-job",
304+
name: "Example Job",
305+
version: "0.0.1",
306+
trigger: eventTrigger({
307+
name: "example.event",
308+
}),
309+
run: async (payload, io, ctx) => {
310+
if (true) {
311+
await io.runTask("example.task", { name: "Task 1" }, async () => {});
312+
313+
if (true) {
314+
await io.runTask("example.task", { name: "Task 2" }, async () => {});
315+
await io.anotherTask("different task", { name: "Task 1" }, async () => {});
316+
}
317+
}
318+
},
319+
});`,
320+
errors: [
321+
{ message: "Task key 'example.task' is duplicated" },
322+
]
243323
}
244324
]
245325
});

0 commit comments

Comments
 (0)