@@ -19,7 +19,7 @@ import { WebSocket } from "partysocket";
1919import  {  ClientOptions ,  WebSocket  as  wsWebSocket  }  from  "ws" ; 
2020import  {  CliApiClient  }  from  "../apiClient.js" ; 
2121import  {  DevCommandOptions  }  from  "../commands/dev.js" ; 
22- import  {  chalkError ,  chalkTask  }  from  "../utilities/cliOutput.js" ; 
22+ import  {  chalkError ,  chalkTask ,   cliLink ,   prettyError  }  from  "../utilities/cliOutput.js" ; 
2323import  {  resolveDotEnvVars  }  from  "../utilities/dotEnv.js" ; 
2424import  {  eventBus  }  from  "../utilities/eventBus.js" ; 
2525import  {  logger  }  from  "../utilities/logger.js" ; 
@@ -189,10 +189,15 @@ class DevWorkerRuntime implements WorkerRuntime {
189189      throw  new  Error ( "Could not initialize worker" ) ; 
190190    } 
191191
192-     const  issues  =  validateWorkerManifest ( backgroundWorker . manifest ) ; 
192+     const  validationIssue  =  validateWorkerManifest ( backgroundWorker . manifest ) ; 
193+ 
194+     if  ( validationIssue )  { 
195+       prettyError ( 
196+         generationValidationIssueHeader ( validationIssue ) , 
197+         generateValidationIssueMessage ( validationIssue ,  backgroundWorker . manifest ! ,  manifest ) , 
198+         generateValidationIssueFooter ( validationIssue ) 
199+       ) ; 
193200
194-     if  ( issues . length  >  0 )  { 
195-       issues . forEach ( ( issue )  =>  logger . error ( issue ) ) ; 
196201      stop ( ) ; 
197202      return ; 
198203    } 
@@ -352,22 +357,90 @@ function gatherProcessEnv() {
352357  return  Object . fromEntries ( Object . entries ( $env ) . filter ( ( [ key ,  value ] )  =>  value  !==  undefined ) ) ; 
353358} 
354359
355- function  validateWorkerManifest ( manifest : WorkerManifest ) : string [ ]  { 
356-   const  issues : string [ ]  =  [ ] ; 
360+ type  ValidationIssue  = 
361+   |  { 
362+       type : "duplicateTaskId" ; 
363+       duplicationTaskIds : string [ ] ; 
364+     } 
365+   |  { 
366+       type : "noTasksDefined" ; 
367+     } ; 
368+ 
369+ function  validateWorkerManifest ( manifest : WorkerManifest ) : ValidationIssue  |  undefined  { 
370+   const  issues : ValidationIssue [ ]  =  [ ] ; 
357371
358372  if  ( ! manifest . tasks  ||  manifest . tasks . length  ===  0 )  { 
359-     issues . push ( "No tasks defined. Make sure you are exporting tasks." ) ; 
373+     return   {   type :  "noTasksDefined"   } ; 
360374  } 
361375
362376  // Check for any duplicate task ids 
363377  const  taskIds  =  manifest . tasks . map ( ( task )  =>  task . id ) ; 
364378  const  duplicateTaskIds  =  taskIds . filter ( ( id ,  index )  =>  taskIds . indexOf ( id )  !==  index ) ; 
365379
366380  if  ( duplicateTaskIds . length  >  0 )  { 
367-     issues . push ( createDuplicateTaskIdOutputErrorMessage ( duplicateTaskIds ,  manifest . tasks ) ) ; 
381+     return  {  type : "duplicateTaskId" ,  duplicationTaskIds : duplicateTaskIds  } ; 
382+   } 
383+ 
384+   return  undefined ; 
385+ } 
386+ 
387+ function  generationValidationIssueHeader ( issue : ValidationIssue )  { 
388+   switch  ( issue . type )  { 
389+     case  "duplicateTaskId" : { 
390+       return  `Duplicate task ids detected` ; 
391+     } 
392+     case  "noTasksDefined" : { 
393+       return  `No tasks exported from your trigger files` ; 
394+     } 
368395  } 
396+ } 
369397
370-   return  issues ; 
398+ function  generateValidationIssueFooter ( issue : ValidationIssue )  { 
399+   switch  ( issue . type )  { 
400+     case  "duplicateTaskId" : { 
401+       return  cliLink ( "View the task docs" ,  "https://trigger.dev/docs/tasks/overview" ) ; 
402+     } 
403+     case  "noTasksDefined" : { 
404+       return  cliLink ( "View the task docs" ,  "https://trigger.dev/docs/tasks/overview" ) ; 
405+     } 
406+   } 
407+ } 
408+ 
409+ function  generateValidationIssueMessage ( 
410+   issue : ValidationIssue , 
411+   manifest : WorkerManifest , 
412+   buildManifest : BuildManifest 
413+ )  { 
414+   switch  ( issue . type )  { 
415+     case  "duplicateTaskId" : { 
416+       return  createDuplicateTaskIdOutputErrorMessage ( issue . duplicationTaskIds ,  manifest . tasks ) ; 
417+     } 
418+     case  "noTasksDefined" : { 
419+       return  `         
420+         Files: 
421+         ${ buildManifest . files . map ( ( file )  =>  file . entry ) . join ( "\n" ) }  
422+ 
423+         Make sure you have at least one task exported from your trigger files. 
424+ 
425+         You may have defined a task and forgot to add the export statement: 
426+ 
427+         \`\`\`ts 
428+         import { task } from "@trigger.dev/sdk/v3"; 
429+ 
430+         👇 Don't forget this 
431+         export const myTask = task({ 
432+           id: "myTask", 
433+           async run() { 
434+             // Your task logic here 
435+           } 
436+         }); 
437+         \`\`\` 
438+       ` . replace ( / ^   { 8 } / gm,  "" ) ; 
439+     } 
440+     default : { 
441+       return  `Unknown validation issue: ${ issue }  ` ; 
442+     } 
443+   } 
371444} 
372445
373446function  createDuplicateTaskIdOutputErrorMessage ( 
0 commit comments