trigger.dev 3.0.0-beta.44 → 3.0.0-beta.45

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/dist/index.js CHANGED
@@ -794,12 +794,11 @@ import { readFileSync as readFileSync2 } from "node:fs";
794
794
  import { copyFile, mkdir, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
795
795
  import { dirname, join as join6, posix, relative as relative3 } from "node:path";
796
796
  import { setTimeout as setTimeout2 } from "node:timers/promises";
797
- import terminalLink2 from "terminal-link";
798
797
  import invariant from "tiny-invariant";
799
798
  import { z as z4 } from "zod";
800
799
 
801
800
  // package.json
802
- var version = "3.0.0-beta.44";
801
+ var version = "3.0.0-beta.45";
803
802
  var dependencies = {
804
803
  "@anatine/esbuild-decorators": "^0.2.19",
805
804
  "@clack/prompts": "^0.7.0",
@@ -816,7 +815,7 @@ var dependencies = {
816
815
  "@opentelemetry/sdk-trace-base": "^1.22.0",
817
816
  "@opentelemetry/sdk-trace-node": "^1.22.0",
818
817
  "@opentelemetry/semantic-conventions": "^1.22.0",
819
- "@trigger.dev/core": "workspace:3.0.0-beta.44",
818
+ "@trigger.dev/core": "workspace:3.0.0-beta.45",
820
819
  "@types/degit": "^2.8.3",
821
820
  chalk: "^5.2.0",
822
821
  chokidar: "^3.5.3",
@@ -851,12 +850,12 @@ var dependencies = {
851
850
  "terminal-link": "^3.0.0",
852
851
  "tiny-invariant": "^1.2.0",
853
852
  "tsconfig-paths": "^4.2.0",
853
+ typescript: "^5.4.0",
854
854
  "update-check": "^1.5.4",
855
855
  url: "^0.11.1",
856
856
  ws: "^8.12.0",
857
857
  zod: "3.22.3",
858
- "zod-validation-error": "^1.5.0",
859
- typescript: "^5.4.0"
858
+ "zod-validation-error": "^1.5.0"
860
859
  };
861
860
  var package_default = {
862
861
  name: "trigger.dev",
@@ -909,7 +908,7 @@ var package_default = {
909
908
  "npm-run-all": "^4.1.5",
910
909
  open: "^10.0.3",
911
910
  "p-retry": "^6.1.0",
912
- rimraf: "^3.0.2",
911
+ rimraf: "^5.0.7",
913
912
  tsup: "^8.0.1",
914
913
  "type-fest": "^3.6.0",
915
914
  typescript: "^5.3.3",
@@ -1357,6 +1356,7 @@ import { outro } from "@clack/prompts";
1357
1356
  // src/utilities/cliOutput.ts
1358
1357
  import { log } from "@clack/prompts";
1359
1358
  import chalk2 from "chalk";
1359
+ import terminalLink from "terminal-link";
1360
1360
  var green = "#4FFF54";
1361
1361
  var purple = "#735BF3";
1362
1362
  function chalkGreen(text3) {
@@ -1428,6 +1428,12 @@ function prettyWarning(header, body, footer) {
1428
1428
  `${prettyPrefix}${header}${prettyBody ? `${spacing}${prettyBody}` : ""}${prettyFooter ? `${spacing}${prettyFooter}` : ""}`
1429
1429
  );
1430
1430
  }
1431
+ function cliLink(text3, url, options) {
1432
+ return terminalLink(text3, url, {
1433
+ fallback: (text4, url2) => `${text4} ${url2}`,
1434
+ ...options
1435
+ });
1436
+ }
1431
1437
 
1432
1438
  // src/cli/common.ts
1433
1439
  var CommonCommandOptions = z.object({
@@ -3125,7 +3131,6 @@ function getLoaderForFile(file) {
3125
3131
  import chalk4 from "chalk";
3126
3132
  import { relative as relative2 } from "node:path";
3127
3133
  import { groupTaskMetadataIssuesByTask } from "@trigger.dev/core/v3";
3128
- import terminalLink from "terminal-link";
3129
3134
 
3130
3135
  // src/utilities/links.ts
3131
3136
  var docs = {
@@ -3222,7 +3227,7 @@ ${chalkGrey("\u25CB")} Dynamically import the module in your code: ${chalkGrey(
3222
3227
  );
3223
3228
  }
3224
3229
  logger.log(
3225
- `${chalkGrey("\u25CB")} For more info see the ${terminalLink("relevant docs", docs.config.esm)}.
3230
+ `${chalkGrey("\u25CB")} For more info see the ${cliLink("relevant docs", docs.config.esm)}.
3226
3231
  `
3227
3232
  );
3228
3233
  }
@@ -3294,6 +3299,13 @@ import { join as join4 } from "node:path";
3294
3299
  // src/utilities/getUserPackageManager.ts
3295
3300
  import { findUp as findUp2 } from "find-up";
3296
3301
  import { basename } from "path";
3302
+ var LOCKFILES = {
3303
+ npm: "package-lock.json",
3304
+ npmShrinkwrap: "npm-shrinkwrap.json",
3305
+ pnpm: "pnpm-lock.yaml",
3306
+ yarn: "yarn.lock",
3307
+ bun: "bun.lockb"
3308
+ };
3297
3309
  async function getUserPackageManager(path7) {
3298
3310
  const packageManager = await detectPackageManager(path7);
3299
3311
  logger.debug("Detected package manager", { packageManager });
@@ -3321,24 +3333,24 @@ function detectPackageManagerFromCurrentCommand() {
3321
3333
  }
3322
3334
  }
3323
3335
  async function detectPackageManagerFromArtifacts(path7) {
3324
- const artifacts = {
3325
- yarn: "yarn.lock",
3326
- pnpm: "pnpm-lock.yaml",
3327
- npm: "package-lock.json",
3328
- npmShrinkwrap: "npm-shrinkwrap.json"
3329
- };
3330
- const foundPath = await findUp2(Object.values(artifacts), { cwd: path7 });
3336
+ const foundPath = await findUp2(Object.values(LOCKFILES), { cwd: path7 });
3331
3337
  if (!foundPath) {
3332
3338
  throw new Error("Could not detect package manager from artifacts");
3333
3339
  }
3334
3340
  logger.debug("Found path from package manager artifacts", { foundPath });
3335
3341
  switch (basename(foundPath)) {
3336
- case artifacts.yarn:
3342
+ case LOCKFILES.yarn:
3343
+ logger.debug("Found yarn artifact", { foundPath });
3337
3344
  return "yarn";
3338
- case artifacts.pnpm:
3345
+ case LOCKFILES.pnpm:
3346
+ logger.debug("Found pnpm artifact", { foundPath });
3339
3347
  return "pnpm";
3340
- case artifacts.npm:
3341
- case artifacts.npmShrinkwrap:
3348
+ case LOCKFILES.npm:
3349
+ case LOCKFILES.npmShrinkwrap:
3350
+ logger.debug("Found npm artifact", { foundPath });
3351
+ return "npm";
3352
+ case LOCKFILES.bun:
3353
+ logger.debug("Found bun artifact", { foundPath });
3342
3354
  return "npm";
3343
3355
  default:
3344
3356
  throw new Error(`Unhandled package manager detection path: ${foundPath}`);
@@ -3366,10 +3378,53 @@ var JavascriptProject = class {
3366
3378
  }
3367
3379
  return this._packageJson;
3368
3380
  }
3381
+ get allowedPackageJson() {
3382
+ const disallowedKeys = [
3383
+ "scripts",
3384
+ "devDependencies",
3385
+ "dependencies",
3386
+ "peerDependencies",
3387
+ "author",
3388
+ "contributors",
3389
+ "funding",
3390
+ "bugs",
3391
+ "files",
3392
+ "keywords",
3393
+ "main",
3394
+ "module",
3395
+ "type",
3396
+ "bin",
3397
+ "browser",
3398
+ "man",
3399
+ "directories",
3400
+ "repository",
3401
+ "peerDependenciesMeta",
3402
+ "optionalDependencies",
3403
+ "engines",
3404
+ "os",
3405
+ "cpu",
3406
+ "private",
3407
+ "publishConfig",
3408
+ "workspaces"
3409
+ ];
3410
+ return Object.keys(this.packageJson).reduce(
3411
+ (acc, key) => {
3412
+ if (!disallowedKeys.includes(key)) {
3413
+ acc[key] = this.packageJson[key];
3414
+ }
3415
+ return acc;
3416
+ },
3417
+ {}
3418
+ );
3419
+ }
3369
3420
  get scripts() {
3370
- return {
3371
- postinstall: this.packageJson.scripts?.postinstall ?? ""
3372
- };
3421
+ return this.#filterScripts();
3422
+ }
3423
+ #filterScripts() {
3424
+ if (!this.packageJson.scripts || typeof this.packageJson.scripts !== "object") {
3425
+ return {};
3426
+ }
3427
+ return this.packageJson.scripts;
3373
3428
  }
3374
3429
  async install() {
3375
3430
  const command = await this.#getCommand();
@@ -3735,27 +3790,49 @@ Latest: ${newCliVersion}`,
3735
3790
  }
3736
3791
  const triggerDependencies = getTriggerDependencies(packageJson);
3737
3792
  function getVersionMismatches(deps, targetVersion) {
3738
- const mismatches = [];
3793
+ const mismatches2 = [];
3739
3794
  for (const dep of deps) {
3740
3795
  if (dep.version === targetVersion) {
3741
3796
  continue;
3742
3797
  }
3743
- mismatches.push(dep);
3798
+ mismatches2.push(dep);
3744
3799
  }
3745
- return mismatches;
3800
+ const extractRelease = (version2) => {
3801
+ const release = Number(version2.split("3.0.0-beta.")[1]);
3802
+ return release || void 0;
3803
+ };
3804
+ let isDowngrade2 = false;
3805
+ const targetRelease = extractRelease(targetVersion);
3806
+ if (targetRelease) {
3807
+ isDowngrade2 = mismatches2.some((dep) => {
3808
+ const depRelease = extractRelease(dep.version);
3809
+ if (!depRelease) {
3810
+ return false;
3811
+ }
3812
+ return depRelease > targetRelease;
3813
+ });
3814
+ }
3815
+ return {
3816
+ mismatches: mismatches2,
3817
+ isDowngrade: isDowngrade2
3818
+ };
3746
3819
  }
3747
- const versionMismatches = getVersionMismatches(triggerDependencies, cliVersion);
3748
- if (versionMismatches.length === 0) {
3820
+ const { mismatches, isDowngrade } = getVersionMismatches(triggerDependencies, cliVersion);
3821
+ if (mismatches.length === 0) {
3749
3822
  if (!embedded) {
3750
3823
  outro4(`Nothing to do${newCliVersion ? " ..but you should really update your CLI!" : ""}`);
3751
3824
  return hasOutput;
3752
3825
  }
3753
3826
  return hasOutput;
3754
3827
  }
3755
- prettyWarning(
3756
- "Mismatch between your CLI version and installed packages",
3757
- "We recommend pinned versions for guaranteed compatibility"
3758
- );
3828
+ if (isDowngrade) {
3829
+ prettyError("Some of the installed @trigger.dev packages are newer than your CLI version");
3830
+ } else {
3831
+ prettyWarning(
3832
+ "Mismatch between your CLI version and installed packages",
3833
+ "We recommend pinned versions for guaranteed compatibility"
3834
+ );
3835
+ }
3759
3836
  if (!process.stdout.isTTY) {
3760
3837
  outro4("Deploy failed");
3761
3838
  console.log(
@@ -3768,13 +3845,24 @@ Latest: ${newCliVersion}`,
3768
3845
  CLI version: ${cliVersion}
3769
3846
 
3770
3847
  Current package versions that don't match the CLI:
3771
- ${versionMismatches.map((dep) => `- ${dep.name}@${dep.version}`).join("\n")}
3848
+ ${mismatches.map((dep) => `- ${dep.name}@${dep.version}`).join("\n")}
3849
+ `
3850
+ );
3851
+ process.exit(1);
3852
+ }
3853
+ if (isDowngrade) {
3854
+ printUpdateTable("Versions", mismatches, cliVersion, "installed", "CLI");
3855
+ outro4("CLI update required!");
3856
+ logger.log(
3857
+ `${chalkError(
3858
+ "X Error:"
3859
+ )} Please update your CLI. Alternatively, use \`--skip-update-check\` at your own risk.
3772
3860
  `
3773
3861
  );
3774
3862
  process.exit(1);
3775
3863
  }
3776
3864
  log4.message("");
3777
- const userWantsToUpdate = await updateConfirmation(versionMismatches, cliVersion);
3865
+ const userWantsToUpdate = await updateConfirmation(mismatches, cliVersion);
3778
3866
  if (isCancel(userWantsToUpdate)) {
3779
3867
  throw new OutroCommandError();
3780
3868
  }
@@ -3804,7 +3892,7 @@ Latest: ${newCliVersion}`,
3804
3892
  );
3805
3893
  };
3806
3894
  process.prependOnceListener("exit", exitHandler);
3807
- mutatePackageJsonWithUpdatedPackages(packageJson, versionMismatches, cliVersion);
3895
+ mutatePackageJsonWithUpdatedPackages(packageJson, mismatches, cliVersion);
3808
3896
  await writeJSONFile(packageJsonPath, packageJson, true);
3809
3897
  async function revertPackageJsonChanges() {
3810
3898
  await writeJSONFile(packageJsonPath, readonlyPackageJson, true);
@@ -3867,17 +3955,17 @@ function mutatePackageJsonWithUpdatedPackages(packageJson, depsToUpdate, targetV
3867
3955
  packageJson[type][name] = targetVersion;
3868
3956
  }
3869
3957
  }
3870
- function printUpdateTable(depsToUpdate, targetVersion) {
3871
- log4.message("Suggested updates");
3958
+ function printUpdateTable(heading, depsToUpdate, targetVersion, oldColumn = "old", newColumn = "new") {
3959
+ log4.message(heading);
3872
3960
  const tableData = depsToUpdate.map((dep) => ({
3873
3961
  package: dep.name,
3874
- old: dep.version,
3875
- new: targetVersion
3962
+ [oldColumn]: dep.version,
3963
+ [newColumn]: targetVersion
3876
3964
  }));
3877
3965
  logger.table(tableData);
3878
3966
  }
3879
3967
  async function updateConfirmation(depsToUpdate, targetVersion) {
3880
- printUpdateTable(depsToUpdate, targetVersion);
3968
+ printUpdateTable("Suggested updates", depsToUpdate, targetVersion);
3881
3969
  let confirmMessage = "Would you like to apply those updates?";
3882
3970
  return await confirm({
3883
3971
  message: confirmMessage
@@ -4215,10 +4303,14 @@ ${authorization.error}`
4215
4303
  await preExitTasks();
4216
4304
  throw new SkipLoggingError(`Deployment failed to complete: ${finishedDeployment}`);
4217
4305
  }
4218
- const deploymentLink = terminalLink2(
4306
+ const deploymentLink = cliLink(
4219
4307
  "View deployment",
4220
4308
  `${authorization.dashboardUrl}/projects/v3/${resolvedConfig.config.project}/deployments/${finishedDeployment.shortCode}`
4221
4309
  );
4310
+ const testLink = cliLink(
4311
+ "Test tasks",
4312
+ `${authorization.dashboardUrl}/projects/v3/${resolvedConfig.config.project}/test?environment=${options.env === "prod" ? "prod" : "stg"}`
4313
+ );
4222
4314
  switch (finishedDeployment.status) {
4223
4315
  case "DEPLOYED": {
4224
4316
  if (warnings.warnings.length > 0) {
@@ -4234,7 +4326,7 @@ ${authorization.error}`
4234
4326
  );
4235
4327
  } else {
4236
4328
  outro5(
4237
- `Version ${version2} deployed with ${taskCount} detected task${taskCount === 1 ? "" : "s"} ${deploymentLink}`
4329
+ `Version ${version2} deployed with ${taskCount} detected task${taskCount === 1 ? "" : "s"} | ${deploymentLink} | ${testLink}`
4238
4330
  );
4239
4331
  }
4240
4332
  break;
@@ -4305,7 +4397,7 @@ function checkLogsForWarnings(logs) {
4305
4397
  const warnings = [
4306
4398
  {
4307
4399
  regex: /prisma:warn We could not find your Prisma schema/,
4308
- message: `Prisma generate failed to find the default schema. Did you include it in config.additionalFiles? ${terminalLink2(
4400
+ message: `Prisma generate failed to find the default schema. Did you include it in config.additionalFiles? ${cliLink(
4309
4401
  "Config docs",
4310
4402
  docs.config.prisma
4311
4403
  )}
@@ -4347,7 +4439,7 @@ function checkLogsForErrors(logs) {
4347
4439
  {
4348
4440
  regex: /Error: Provided --schema at (?<schema>.*) doesn't exist/,
4349
4441
  message: `Prisma generate failed to find the specified schema at "$schema".
4350
- Did you include it in config.additionalFiles? ${terminalLink2(
4442
+ Did you include it in config.additionalFiles? ${cliLink(
4351
4443
  "Config docs",
4352
4444
  docs.config.prisma
4353
4445
  )}`
@@ -4356,11 +4448,11 @@ Did you include it in config.additionalFiles? ${terminalLink2(
4356
4448
  regex: /sh: 1: (?<packageOrBinary>.*): not found/,
4357
4449
  message: `$packageOrBinary not found
4358
4450
 
4359
- If it's a package: Include it in ${terminalLink2(
4451
+ If it's a package: Include it in ${cliLink(
4360
4452
  "config.additionalPackages",
4361
4453
  docs.config.prisma
4362
4454
  )}
4363
- If it's a binary: Please ${terminalLink2(
4455
+ If it's a binary: Please ${cliLink(
4364
4456
  "get in touch",
4365
4457
  getInTouch
4366
4458
  )} and we'll see what we can do!`
@@ -4838,12 +4930,11 @@ async function compileProject(config, options, configPath) {
4838
4930
  const dependencies2 = await resolveRequiredDependencies(allImports, config, javascriptProject);
4839
4931
  logger.debug("gatherRequiredDependencies()", { dependencies: dependencies2 });
4840
4932
  const packageJsonContents = {
4841
- name: "trigger-worker",
4842
- version: "0.0.0",
4843
- description: "",
4933
+ ...javascriptProject.allowedPackageJson,
4844
4934
  dependencies: dependencies2,
4845
4935
  scripts: {
4846
- ...javascriptProject.scripts
4936
+ ...javascriptProject.scripts,
4937
+ ...typeof config.postInstall === "string" ? { postinstall: config.postInstall } : {}
4847
4938
  }
4848
4939
  };
4849
4940
  span.setAttributes({
@@ -4858,7 +4949,7 @@ async function compileProject(config, options, configPath) {
4858
4949
 
4859
4950
  ${copyResult.noMatches.map((glob) => `- "${glob}"`).join("\n")}
4860
4951
 
4861
- If this is unexpected you should check your ${terminalLink2(
4952
+ If this is unexpected you should check your ${cliLink(
4862
4953
  "glob patterns",
4863
4954
  "https://github.com/isaacs/node-glob?tab=readme-ov-file#glob-primer"
4864
4955
  )} are valid.`
@@ -4876,14 +4967,6 @@ If this is unexpected you should check your ${terminalLink2(
4876
4967
  }
4877
4968
  const containerFilePath = join6(cliRootPath(), "Containerfile.prod");
4878
4969
  let containerFileContents = readFileSync2(containerFilePath, "utf-8");
4879
- if (config.postInstall) {
4880
- containerFileContents = containerFileContents.replace(
4881
- "__POST_INSTALL__",
4882
- `RUN ${config.postInstall}`
4883
- );
4884
- } else {
4885
- containerFileContents = containerFileContents.replace("__POST_INSTALL__", "");
4886
- }
4887
4970
  await writeFile2(join6(tempDir, "Containerfile"), containerFileContents);
4888
4971
  const contentHasher = createHash("sha256");
4889
4972
  contentHasher.update(Buffer.from(entryPointOutputFile.text));
@@ -5316,9 +5399,11 @@ var TaskMetadataParseError = class extends Error {
5316
5399
  }
5317
5400
  };
5318
5401
  var UnexpectedExitError = class extends Error {
5319
- constructor(code) {
5402
+ constructor(code, signal, stderr) {
5320
5403
  super(`Unexpected exit with code ${code}`);
5321
5404
  this.code = code;
5405
+ this.signal = signal;
5406
+ this.stderr = stderr;
5322
5407
  this.name = "UnexpectedExitError";
5323
5408
  }
5324
5409
  };
@@ -5340,6 +5425,32 @@ var SigKillTimeoutProcessError = class extends Error {
5340
5425
  this.name = "SigKillTimeoutProcessError";
5341
5426
  }
5342
5427
  };
5428
+ function getFriendlyErrorMessage(code, signal, stderr, dockerMode = true) {
5429
+ const message = (text3) => {
5430
+ if (signal) {
5431
+ return `[${signal}] ${text3}`;
5432
+ } else {
5433
+ return text3;
5434
+ }
5435
+ };
5436
+ if (code === 137) {
5437
+ if (dockerMode) {
5438
+ return message(
5439
+ "Process ran out of memory! Try choosing a machine preset with more memory for this task."
5440
+ );
5441
+ } else {
5442
+ return message(
5443
+ "Process most likely ran out of memory, but we can't be certain. Try choosing a machine preset with more memory for this task."
5444
+ );
5445
+ }
5446
+ }
5447
+ if (stderr?.includes("OOMErrorHandler")) {
5448
+ return message(
5449
+ "Process ran out of memory! Try choosing a machine preset with more memory for this task."
5450
+ );
5451
+ }
5452
+ return message(`Process exited with code ${code}.`);
5453
+ }
5343
5454
 
5344
5455
  // src/workers/dev/backgroundWorker.ts
5345
5456
  import {
@@ -5355,7 +5466,6 @@ import dotenv from "dotenv";
5355
5466
  import { Evt } from "evt";
5356
5467
  import { fork } from "node:child_process";
5357
5468
  import { dirname as dirname2, resolve as resolve4 } from "node:path";
5358
- import terminalLink3 from "terminal-link";
5359
5469
  var BackgroundWorkerCoordinator = class {
5360
5470
  constructor(baseURL) {
5361
5471
  this.baseURL = baseURL;
@@ -5592,7 +5702,7 @@ var BackgroundWorker = class {
5592
5702
  resolved = true;
5593
5703
  child.kill();
5594
5704
  reject(new Error("Worker timed out"));
5595
- }, 5e3);
5705
+ }, 2e4);
5596
5706
  child.on("message", async (msg) => {
5597
5707
  const message = this._handler.parseMessage(msg);
5598
5708
  if (message.type === "TASKS_READY" && !resolved) {
@@ -5762,7 +5872,7 @@ var BackgroundWorker = class {
5762
5872
  const logsUrl = `${baseURL}/runs/${execution.run.id}`;
5763
5873
  const pipe = chalkGrey("|");
5764
5874
  const bullet = chalkGrey("\u25CB");
5765
- const link = chalkLink(terminalLink3("View logs", logsUrl));
5875
+ const link = chalkLink(cliLink("View logs", logsUrl));
5766
5876
  let timestampPrefix = chalkGrey(prettyPrintDate(payload.execution.attempt.startedAt));
5767
5877
  const workerPrefix = chalkWorker(this.metadata.version);
5768
5878
  const taskPrefix = chalkTask(execution.task.id);
@@ -5839,7 +5949,9 @@ var BackgroundWorker = class {
5839
5949
  retry: void 0,
5840
5950
  error: {
5841
5951
  type: "INTERNAL_ERROR",
5842
- code: TaskRunErrorCodes.TASK_PROCESS_EXITED_WITH_NON_ZERO_CODE
5952
+ code: TaskRunErrorCodes.TASK_PROCESS_EXITED_WITH_NON_ZERO_CODE,
5953
+ message: getFriendlyErrorMessage(e.code, e.signal, e.stderr),
5954
+ stackTrace: e.stderr
5843
5955
  }
5844
5956
  };
5845
5957
  }
@@ -5901,6 +6013,7 @@ var TaskRunProcess = class {
5901
6013
  _currentExecution;
5902
6014
  _isBeingKilled = false;
5903
6015
  _isBeingCancelled = false;
6016
+ _stderr = [];
5904
6017
  /**
5905
6018
  * @deprecated use onTaskRunHeartbeat instead
5906
6019
  */
@@ -6060,7 +6173,13 @@ var TaskRunProcess = class {
6060
6173
  } else if (this._isBeingKilled) {
6061
6174
  rejecter(new CleanupProcessError());
6062
6175
  } else {
6063
- rejecter(new UnexpectedExitError(code ?? -1));
6176
+ rejecter(
6177
+ new UnexpectedExitError(
6178
+ code ?? -1,
6179
+ signal,
6180
+ this._stderr.length ? this._stderr.join("\n") : void 0
6181
+ )
6182
+ );
6064
6183
  }
6065
6184
  }
6066
6185
  }
@@ -6089,9 +6208,14 @@ var TaskRunProcess = class {
6089
6208
  const runId = chalkRun(
6090
6209
  `${this._currentExecution.run.id}.${this._currentExecution.attempt.number}`
6091
6210
  );
6211
+ const errorLine = data.toString();
6092
6212
  logger.log(
6093
- `${chalkError("\u25CB")} ${chalkGrey(prettyPrintDate(/* @__PURE__ */ new Date()))} ${runId} ${data.toString()}`
6213
+ `${chalkError("\u25CB")} ${chalkGrey(prettyPrintDate(/* @__PURE__ */ new Date()))} ${runId} ${errorLine}`
6094
6214
  );
6215
+ if (this._stderr.length > 100) {
6216
+ this._stderr.shift();
6217
+ }
6218
+ this._stderr.push(errorLine);
6095
6219
  }
6096
6220
  #kill() {
6097
6221
  logger.debug(`[${this.runId}] #kill()`, { pid: this.pid });
@@ -6611,12 +6735,18 @@ function useDev({
6611
6735
  throw new Error(backgroundWorkerRecord.error);
6612
6736
  }
6613
6737
  backgroundWorker.metadata = backgroundWorkerRecord.data;
6738
+ backgroundWorker;
6739
+ const testUrl = `${dashboardUrl}/projects/v3/${config.project}/test?environment=dev`;
6740
+ const runsUrl = `${dashboardUrl}/projects/v3/${config.project}/runs?envSlug=dev`;
6741
+ const pipe = chalkGrey("|");
6742
+ const bullet = chalkGrey("\u25CB");
6743
+ const arrow = chalkGrey("->");
6744
+ const testLink = chalkLink(cliLink("Test tasks", testUrl));
6745
+ const runsLink = chalkLink(cliLink("View runs", runsUrl));
6746
+ const workerStarted = chalkGrey("Background worker started");
6747
+ const workerVersion = chalkWorker(backgroundWorkerRecord.data.version);
6614
6748
  logger.log(
6615
- `${chalkGrey(
6616
- `\u25CB Background worker started -> ${chalkWorker(
6617
- backgroundWorkerRecord.data.version
6618
- )}`
6619
- )}`
6749
+ `${bullet} ${workerStarted} ${arrow} ${workerVersion} ${pipe} ${testLink} ${pipe} ${runsLink}`
6620
6750
  );
6621
6751
  firstBuild = false;
6622
6752
  await backgroundWorkerCoordinator.registerWorker(
@@ -6709,13 +6839,18 @@ ${stderr}`);
6709
6839
  logger.error(error);
6710
6840
  });
6711
6841
  return () => {
6712
- logger.debug(`Shutting down dev session for ${config.project}`);
6713
- taskFileWatcher.close();
6714
- websocket?.close();
6715
- backgroundWorkerCoordinator.close();
6716
- ctx?.dispose().catch((error) => {
6717
- console.error(error);
6718
- });
6842
+ const cleanup = async () => {
6843
+ logger.debug(`Shutting down dev session for ${config.project}`);
6844
+ const start = Date.now();
6845
+ await taskFileWatcher.close();
6846
+ websocket?.close();
6847
+ backgroundWorkerCoordinator.close();
6848
+ ctx?.dispose().catch((error) => {
6849
+ console.error(error);
6850
+ });
6851
+ logger.debug(`Shutdown completed in ${Date.now() - start}ms`);
6852
+ };
6853
+ cleanup();
6719
6854
  };
6720
6855
  }, [config, apiUrl, apiKey, environmentClient]);
6721
6856
  }
@@ -6857,11 +6992,10 @@ import { context as context3, trace as trace3 } from "@opentelemetry/api";
6857
6992
  import { flattenAttributes as flattenAttributes4 } from "@trigger.dev/core/v3";
6858
6993
  import { recordSpanException as recordSpanException6 } from "@trigger.dev/core/v3/workers";
6859
6994
  import chalk5 from "chalk";
6860
- import { execa as execa3 } from "execa";
6995
+ import { ExecaError as ExecaError2, execa as execa3 } from "execa";
6861
6996
  import { applyEdits, modify, findNodeAtLocation, parseTree, getNodeValue } from "jsonc-parser";
6862
6997
  import { writeFile as writeFile3 } from "node:fs/promises";
6863
6998
  import { join as join8, relative as relative4, resolve as resolve5 } from "node:path";
6864
- import terminalLink4 from "terminal-link";
6865
6999
  import { z as z6 } from "zod";
6866
7000
 
6867
7001
  // src/utilities/createFileFromTemplate.ts
@@ -6910,7 +7044,8 @@ var InitCommandOptions = CommonCommandOptions.extend({
6910
7044
  projectRef: z6.string().optional(),
6911
7045
  overrideConfig: z6.boolean().default(false),
6912
7046
  tag: z6.string().default("beta"),
6913
- skipPackageInstall: z6.boolean().default(false)
7047
+ skipPackageInstall: z6.boolean().default(false),
7048
+ pkgArgs: z6.string().optional()
6914
7049
  });
6915
7050
  function configureInitCommand(program2) {
6916
7051
  return commonOptions(
@@ -6921,7 +7056,10 @@ function configureInitCommand(program2) {
6921
7056
  "-t, --tag <package tag>",
6922
7057
  "The version of the @trigger.dev/sdk package to install",
6923
7058
  version
6924
- ).option("--skip-package-install", "Skip installing the @trigger.dev/sdk package").option("--override-config", "Override the existing config file if it exists")
7059
+ ).option("--skip-package-install", "Skip installing the @trigger.dev/sdk package").option("--override-config", "Override the existing config file if it exists").option(
7060
+ "--pkg-args <args>",
7061
+ "Additional arguments to pass to the package manager, accepts CSV for multiple args"
7062
+ )
6925
7063
  ).action(async (path7, options) => {
6926
7064
  await handleTelemetry(async () => {
6927
7065
  await printStandloneInitialBanner(true);
@@ -6937,6 +7075,7 @@ async function initCommand(dir, options) {
6937
7075
  async function _initCommand(dir, options) {
6938
7076
  const span = trace3.getSpan(context3.active());
6939
7077
  intro5("Initializing project");
7078
+ await detectTsConfig(dir, options);
6940
7079
  const authorization = await login({
6941
7080
  embedded: true,
6942
7081
  defaultApiUrl: options.apiUrl,
@@ -6987,7 +7126,7 @@ async function _initCommand(dir, options) {
6987
7126
  await writeConfigFile(dir, selectedProject, options, triggerDir);
6988
7127
  await addConfigFileToTsConfig(dir, options);
6989
7128
  await gitIgnoreDotTriggerDir(dir, options);
6990
- const projectDashboard = terminalLink4(
7129
+ const projectDashboard = cliLink(
6991
7130
  "project dashboard",
6992
7131
  `${authorization.dashboardUrl}/projects/v3/${selectedProject.externalRef}`
6993
7132
  );
@@ -7000,13 +7139,10 @@ async function _initCommand(dir, options) {
7000
7139
  );
7001
7140
  log6.info(` 2. Visit your ${projectDashboard} to view your newly created tasks.`);
7002
7141
  log6.info(
7003
- ` 3. Head over to our ${terminalLink4(
7004
- "v3 docs",
7005
- "https://trigger.dev/docs/v3"
7006
- )} to learn more.`
7142
+ ` 3. Head over to our ${cliLink("v3 docs", "https://trigger.dev/docs/v3")} to learn more.`
7007
7143
  );
7008
7144
  log6.info(
7009
- ` 4. Need help? Join our ${terminalLink4(
7145
+ ` 4. Need help? Join our ${cliLink(
7010
7146
  "Discord community",
7011
7147
  "https://trigger.dev/discord"
7012
7148
  )} or email us at ${chalk5.cyan("help@trigger.dev")}`
@@ -7111,8 +7247,39 @@ async function gitIgnoreDotTriggerDir(dir, options) {
7111
7247
  }
7112
7248
  });
7113
7249
  }
7250
+ async function detectTsConfig(dir, options) {
7251
+ return await tracer.startActiveSpan("detectTsConfig", async (span) => {
7252
+ try {
7253
+ const projectDir = resolve5(process.cwd(), dir);
7254
+ const tsconfigPath = join8(projectDir, "tsconfig.json");
7255
+ span.setAttributes({
7256
+ "cli.projectDir": projectDir,
7257
+ "cli.tsconfigPath": tsconfigPath
7258
+ });
7259
+ const tsconfigExists = await pathExists(tsconfigPath);
7260
+ if (!tsconfigExists) {
7261
+ prettyError(
7262
+ "No tsconfig.json found",
7263
+ `The init command needs to be run in a TypeScript project. You can create one like this:`,
7264
+ `npm install typescript --save-dev
7265
+ npx tsc --init
7266
+ `
7267
+ );
7268
+ throw new Error("TypeScript required");
7269
+ }
7270
+ logger.debug("tsconfig.json exists", { tsconfigPath });
7271
+ span.end();
7272
+ } catch (e) {
7273
+ if (!(e instanceof SkipCommandError)) {
7274
+ recordSpanException6(span, e);
7275
+ }
7276
+ span.end();
7277
+ throw e;
7278
+ }
7279
+ });
7280
+ }
7114
7281
  async function addConfigFileToTsConfig(dir, options) {
7115
- return await tracer.startActiveSpan("createTriggerDir", async (span) => {
7282
+ return await tracer.startActiveSpan("addConfigFileToTsConfig", async (span) => {
7116
7283
  try {
7117
7284
  const projectDir = resolve5(process.cwd(), dir);
7118
7285
  const tsconfigPath = join8(projectDir, "tsconfig.json");
@@ -7163,49 +7330,58 @@ async function addConfigFileToTsConfig(dir, options) {
7163
7330
  async function installPackages2(dir, options) {
7164
7331
  return await tracer.startActiveSpan("installPackages", async (span) => {
7165
7332
  const installSpinner = spinner();
7333
+ let pkgManager;
7166
7334
  try {
7167
7335
  const projectDir = resolve5(process.cwd(), dir);
7168
- const pkgManager = await getUserPackageManager(projectDir);
7336
+ pkgManager = await getUserPackageManager(projectDir);
7169
7337
  span.setAttributes({
7170
7338
  "cli.projectDir": projectDir,
7171
7339
  "cli.packageManager": pkgManager,
7172
7340
  "cli.tag": options.tag
7173
7341
  });
7342
+ const userArgs = options.pkgArgs?.split(",") ?? [];
7343
+ const execaOptions = { cwd: projectDir };
7344
+ let installProcess;
7345
+ let args;
7174
7346
  switch (pkgManager) {
7175
7347
  case "npm": {
7176
- installSpinner.start(`Running npm install @trigger.dev/sdk@${options.tag}`);
7177
- await execa3("npm", ["install", "--save-exact", `@trigger.dev/sdk@${options.tag}`], {
7178
- cwd: projectDir,
7179
- stdio: options.logLevel === "debug" ? "inherit" : "ignore"
7180
- });
7181
- break;
7182
- }
7183
- case "pnpm": {
7184
- installSpinner.start(`Running pnpm add @trigger.dev/sdk@${options.tag}`);
7185
- await execa3("pnpm", ["add", `@trigger.dev/sdk@${options.tag}`], {
7186
- cwd: projectDir,
7187
- stdio: options.logLevel === "debug" ? "inherit" : "ignore"
7188
- });
7348
+ args = ["install", "--save-exact", ...userArgs, `@trigger.dev/sdk@${options.tag}`];
7189
7349
  break;
7190
7350
  }
7351
+ case "pnpm":
7191
7352
  case "yarn": {
7192
- installSpinner.start(`Running yarn add @trigger.dev/sdk@${options.tag}`);
7193
- await execa3("yarn", ["add", `@trigger.dev/sdk@${options.tag}`], {
7194
- cwd: projectDir,
7195
- stdio: options.logLevel === "debug" ? "inherit" : "ignore"
7196
- });
7353
+ args = ["add", ...userArgs, `@trigger.dev/sdk@${options.tag}`];
7197
7354
  break;
7198
7355
  }
7199
7356
  }
7357
+ installSpinner.start(`Running ${pkgManager} ${args.join(" ")}`);
7358
+ installProcess = execa3(pkgManager, args, execaOptions);
7359
+ const handleProcessOutput = (data) => {
7360
+ logger.debug(data.toString());
7361
+ };
7362
+ installProcess.stderr?.on("data", handleProcessOutput);
7363
+ installProcess.stdout?.on("data", handleProcessOutput);
7364
+ await installProcess;
7200
7365
  installSpinner.stop(`@trigger.dev/sdk@${options.tag} installed`);
7201
7366
  span.end();
7202
7367
  } catch (e) {
7203
- installSpinner.stop(
7204
- `Failed to install @trigger.dev/sdk@${options.tag}. Rerun command with --log-level debug for more details.`
7205
- );
7368
+ if (options.logLevel === "debug") {
7369
+ installSpinner.stop(`Failed to install @trigger.dev/sdk@${options.tag}.`);
7370
+ } else {
7371
+ installSpinner.stop(
7372
+ `Failed to install @trigger.dev/sdk@${options.tag}. Rerun command with --log-level debug for more details.`
7373
+ );
7374
+ }
7206
7375
  if (!(e instanceof SkipCommandError)) {
7207
7376
  recordSpanException6(span, e);
7208
7377
  }
7378
+ if (e instanceof ExecaError2) {
7379
+ if (pkgManager) {
7380
+ e.message += `
7381
+
7382
+ Note: You can pass additional args to ${pkgManager} by using --pkg-args. For example: trigger.dev init --pkg-args="--workspace-root"`;
7383
+ }
7384
+ }
7209
7385
  span.end();
7210
7386
  throw e;
7211
7387
  }
@@ -7274,7 +7450,7 @@ async function selectProject(apiClient2, dashboardUrl, projectRef) {
7274
7450
  throw new Error(`Failed to get projects: ${projectsResponse.error}`);
7275
7451
  }
7276
7452
  if (projectsResponse.data.length === 0) {
7277
- const newProjectLink = terminalLink4(
7453
+ const newProjectLink = cliLink(
7278
7454
  "Create new project",
7279
7455
  `${dashboardUrl}/projects/new?version=v3`
7280
7456
  );