trigger.dev 0.0.0-v3-prerelease-20240624161326 → 0.0.0-v3-prerelease-20240628145956

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 = "0.0.0-v3-prerelease-20240624161326";
801
+ var version = "0.0.0-v3-prerelease-20240628145956";
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:0.0.0-v3-prerelease-20240624161326",
818
+ "@trigger.dev/core": "workspace:0.0.0-v3-prerelease-20240628145956",
820
819
  "@types/degit": "^2.8.3",
821
820
  chalk: "^5.2.0",
822
821
  chokidar: "^3.5.3",
@@ -832,7 +831,7 @@ var dependencies = {
832
831
  "gradient-string": "^2.0.2",
833
832
  "import-meta-resolve": "^4.0.0",
834
833
  ink: "^4.4.1",
835
- "jsonc-parser": "^3.2.1",
834
+ "jsonc-parser": "3.2.1",
836
835
  liquidjs: "^10.9.2",
837
836
  "mock-fs": "^5.2.0",
838
837
  nanoid: "^4.0.2",
@@ -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 = {
@@ -3148,13 +3153,9 @@ function parseBuildErrorStack(error) {
3148
3153
  }
3149
3154
  if (errorIsErrorLike(error)) {
3150
3155
  if (typeof error.stack === "string") {
3151
- const isErrRequireEsm = error.stack.includes("ERR_REQUIRE_ESM");
3152
- let moduleName = null;
3153
- if (isErrRequireEsm) {
3154
- const moduleRegex = /node_modules\/(@[^\/]+\/[^\/]+|[^\/]+)\/[^\/]+\s/;
3155
- const match = moduleRegex.exec(error.stack);
3156
- if (match) {
3157
- moduleName = match[1];
3156
+ if (error.stack.includes("ERR_REQUIRE_ESM")) {
3157
+ const moduleName = getPackageNameFromEsmRequireError(error.stack);
3158
+ if (moduleName) {
3158
3159
  return {
3159
3160
  type: "esm-require-error",
3160
3161
  moduleName
@@ -3166,6 +3167,27 @@ function parseBuildErrorStack(error) {
3166
3167
  }
3167
3168
  }
3168
3169
  }
3170
+ function getPackageNameFromEsmRequireError(stack) {
3171
+ const pathRegex = /require\(\) of ES Module (.*) from/;
3172
+ const pathMatch = pathRegex.exec(stack);
3173
+ if (!pathMatch) {
3174
+ return;
3175
+ }
3176
+ const filePath = pathMatch[1];
3177
+ if (!filePath) {
3178
+ return;
3179
+ }
3180
+ const lastPart = filePath.split("node_modules/").pop();
3181
+ if (!lastPart) {
3182
+ return;
3183
+ }
3184
+ const moduleRegex = /(@[^\/]+\/[^\/]+|[^\/]+)/;
3185
+ const match = moduleRegex.exec(lastPart);
3186
+ if (!match) {
3187
+ return;
3188
+ }
3189
+ return match[1];
3190
+ }
3169
3191
  function logESMRequireError(parsedError, resolvedConfig) {
3170
3192
  logger.log(
3171
3193
  `
@@ -3205,7 +3227,7 @@ ${chalkGrey("\u25CB")} Dynamically import the module in your code: ${chalkGrey(
3205
3227
  );
3206
3228
  }
3207
3229
  logger.log(
3208
- `${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)}.
3209
3231
  `
3210
3232
  );
3211
3233
  }
@@ -3277,6 +3299,13 @@ import { join as join4 } from "node:path";
3277
3299
  // src/utilities/getUserPackageManager.ts
3278
3300
  import { findUp as findUp2 } from "find-up";
3279
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
+ };
3280
3309
  async function getUserPackageManager(path7) {
3281
3310
  const packageManager = await detectPackageManager(path7);
3282
3311
  logger.debug("Detected package manager", { packageManager });
@@ -3304,24 +3333,23 @@ function detectPackageManagerFromCurrentCommand() {
3304
3333
  }
3305
3334
  }
3306
3335
  async function detectPackageManagerFromArtifacts(path7) {
3307
- const artifacts = {
3308
- yarn: "yarn.lock",
3309
- pnpm: "pnpm-lock.yaml",
3310
- npm: "package-lock.json",
3311
- npmShrinkwrap: "npm-shrinkwrap.json"
3312
- };
3313
- const foundPath = await findUp2(Object.values(artifacts), { cwd: path7 });
3336
+ const foundPath = await findUp2(Object.values(LOCKFILES), { cwd: path7 });
3314
3337
  if (!foundPath) {
3315
3338
  throw new Error("Could not detect package manager from artifacts");
3316
3339
  }
3317
3340
  logger.debug("Found path from package manager artifacts", { foundPath });
3318
3341
  switch (basename(foundPath)) {
3319
- case artifacts.yarn:
3342
+ case LOCKFILES.yarn:
3343
+ logger.debug("Found yarn artifact", { foundPath });
3320
3344
  return "yarn";
3321
- case artifacts.pnpm:
3345
+ case LOCKFILES.pnpm:
3346
+ logger.debug("Found pnpm artifact", { foundPath });
3322
3347
  return "pnpm";
3323
- case artifacts.npm:
3324
- case artifacts.npmShrinkwrap:
3348
+ case LOCKFILES.npm:
3349
+ case LOCKFILES.npmShrinkwrap:
3350
+ logger.debug("Found npm artifact", { foundPath });
3351
+ case LOCKFILES.bun:
3352
+ logger.debug("Found bun artifact", { foundPath });
3325
3353
  return "npm";
3326
3354
  default:
3327
3355
  throw new Error(`Unhandled package manager detection path: ${foundPath}`);
@@ -3718,27 +3746,49 @@ Latest: ${newCliVersion}`,
3718
3746
  }
3719
3747
  const triggerDependencies = getTriggerDependencies(packageJson);
3720
3748
  function getVersionMismatches(deps, targetVersion) {
3721
- const mismatches = [];
3749
+ const mismatches2 = [];
3722
3750
  for (const dep of deps) {
3723
3751
  if (dep.version === targetVersion) {
3724
3752
  continue;
3725
3753
  }
3726
- mismatches.push(dep);
3754
+ mismatches2.push(dep);
3727
3755
  }
3728
- return mismatches;
3756
+ const extractRelease = (version2) => {
3757
+ const release = Number(version2.split("3.0.0-beta.")[1]);
3758
+ return release || void 0;
3759
+ };
3760
+ let isDowngrade2 = false;
3761
+ const targetRelease = extractRelease(targetVersion);
3762
+ if (targetRelease) {
3763
+ isDowngrade2 = mismatches2.some((dep) => {
3764
+ const depRelease = extractRelease(dep.version);
3765
+ if (!depRelease) {
3766
+ return false;
3767
+ }
3768
+ return depRelease > targetRelease;
3769
+ });
3770
+ }
3771
+ return {
3772
+ mismatches: mismatches2,
3773
+ isDowngrade: isDowngrade2
3774
+ };
3729
3775
  }
3730
- const versionMismatches = getVersionMismatches(triggerDependencies, cliVersion);
3731
- if (versionMismatches.length === 0) {
3776
+ const { mismatches, isDowngrade } = getVersionMismatches(triggerDependencies, cliVersion);
3777
+ if (mismatches.length === 0) {
3732
3778
  if (!embedded) {
3733
3779
  outro4(`Nothing to do${newCliVersion ? " ..but you should really update your CLI!" : ""}`);
3734
3780
  return hasOutput;
3735
3781
  }
3736
3782
  return hasOutput;
3737
3783
  }
3738
- prettyWarning(
3739
- "Mismatch between your CLI version and installed packages",
3740
- "We recommend pinned versions for guaranteed compatibility"
3741
- );
3784
+ if (isDowngrade) {
3785
+ prettyError("Some of the installed @trigger.dev packages are newer than your CLI version");
3786
+ } else {
3787
+ prettyWarning(
3788
+ "Mismatch between your CLI version and installed packages",
3789
+ "We recommend pinned versions for guaranteed compatibility"
3790
+ );
3791
+ }
3742
3792
  if (!process.stdout.isTTY) {
3743
3793
  outro4("Deploy failed");
3744
3794
  console.log(
@@ -3751,13 +3801,24 @@ Latest: ${newCliVersion}`,
3751
3801
  CLI version: ${cliVersion}
3752
3802
 
3753
3803
  Current package versions that don't match the CLI:
3754
- ${versionMismatches.map((dep) => `- ${dep.name}@${dep.version}`).join("\n")}
3804
+ ${mismatches.map((dep) => `- ${dep.name}@${dep.version}`).join("\n")}
3805
+ `
3806
+ );
3807
+ process.exit(1);
3808
+ }
3809
+ if (isDowngrade) {
3810
+ printUpdateTable("Versions", mismatches, cliVersion, "installed", "CLI");
3811
+ outro4("CLI update required!");
3812
+ logger.log(
3813
+ `${chalkError(
3814
+ "X Error:"
3815
+ )} Please update your CLI. Alternatively, use \`--skip-update-check\` at your own risk.
3755
3816
  `
3756
3817
  );
3757
3818
  process.exit(1);
3758
3819
  }
3759
3820
  log4.message("");
3760
- const userWantsToUpdate = await updateConfirmation(versionMismatches, cliVersion);
3821
+ const userWantsToUpdate = await updateConfirmation(mismatches, cliVersion);
3761
3822
  if (isCancel(userWantsToUpdate)) {
3762
3823
  throw new OutroCommandError();
3763
3824
  }
@@ -3787,7 +3848,7 @@ Latest: ${newCliVersion}`,
3787
3848
  );
3788
3849
  };
3789
3850
  process.prependOnceListener("exit", exitHandler);
3790
- mutatePackageJsonWithUpdatedPackages(packageJson, versionMismatches, cliVersion);
3851
+ mutatePackageJsonWithUpdatedPackages(packageJson, mismatches, cliVersion);
3791
3852
  await writeJSONFile(packageJsonPath, packageJson, true);
3792
3853
  async function revertPackageJsonChanges() {
3793
3854
  await writeJSONFile(packageJsonPath, readonlyPackageJson, true);
@@ -3850,17 +3911,17 @@ function mutatePackageJsonWithUpdatedPackages(packageJson, depsToUpdate, targetV
3850
3911
  packageJson[type][name] = targetVersion;
3851
3912
  }
3852
3913
  }
3853
- function printUpdateTable(depsToUpdate, targetVersion) {
3854
- log4.message("Suggested updates");
3914
+ function printUpdateTable(heading, depsToUpdate, targetVersion, oldColumn = "old", newColumn = "new") {
3915
+ log4.message(heading);
3855
3916
  const tableData = depsToUpdate.map((dep) => ({
3856
3917
  package: dep.name,
3857
- old: dep.version,
3858
- new: targetVersion
3918
+ [oldColumn]: dep.version,
3919
+ [newColumn]: targetVersion
3859
3920
  }));
3860
3921
  logger.table(tableData);
3861
3922
  }
3862
3923
  async function updateConfirmation(depsToUpdate, targetVersion) {
3863
- printUpdateTable(depsToUpdate, targetVersion);
3924
+ printUpdateTable("Suggested updates", depsToUpdate, targetVersion);
3864
3925
  let confirmMessage = "Would you like to apply those updates?";
3865
3926
  return await confirm({
3866
3927
  message: confirmMessage
@@ -4198,7 +4259,7 @@ ${authorization.error}`
4198
4259
  await preExitTasks();
4199
4260
  throw new SkipLoggingError(`Deployment failed to complete: ${finishedDeployment}`);
4200
4261
  }
4201
- const deploymentLink = terminalLink2(
4262
+ const deploymentLink = cliLink(
4202
4263
  "View deployment",
4203
4264
  `${authorization.dashboardUrl}/projects/v3/${resolvedConfig.config.project}/deployments/${finishedDeployment.shortCode}`
4204
4265
  );
@@ -4288,7 +4349,7 @@ function checkLogsForWarnings(logs) {
4288
4349
  const warnings = [
4289
4350
  {
4290
4351
  regex: /prisma:warn We could not find your Prisma schema/,
4291
- message: `Prisma generate failed to find the default schema. Did you include it in config.additionalFiles? ${terminalLink2(
4352
+ message: `Prisma generate failed to find the default schema. Did you include it in config.additionalFiles? ${cliLink(
4292
4353
  "Config docs",
4293
4354
  docs.config.prisma
4294
4355
  )}
@@ -4330,7 +4391,7 @@ function checkLogsForErrors(logs) {
4330
4391
  {
4331
4392
  regex: /Error: Provided --schema at (?<schema>.*) doesn't exist/,
4332
4393
  message: `Prisma generate failed to find the specified schema at "$schema".
4333
- Did you include it in config.additionalFiles? ${terminalLink2(
4394
+ Did you include it in config.additionalFiles? ${cliLink(
4334
4395
  "Config docs",
4335
4396
  docs.config.prisma
4336
4397
  )}`
@@ -4339,11 +4400,11 @@ Did you include it in config.additionalFiles? ${terminalLink2(
4339
4400
  regex: /sh: 1: (?<packageOrBinary>.*): not found/,
4340
4401
  message: `$packageOrBinary not found
4341
4402
 
4342
- If it's a package: Include it in ${terminalLink2(
4403
+ If it's a package: Include it in ${cliLink(
4343
4404
  "config.additionalPackages",
4344
4405
  docs.config.prisma
4345
4406
  )}
4346
- If it's a binary: Please ${terminalLink2(
4407
+ If it's a binary: Please ${cliLink(
4347
4408
  "get in touch",
4348
4409
  getInTouch
4349
4410
  )} and we'll see what we can do!`
@@ -4826,7 +4887,8 @@ async function compileProject(config, options, configPath) {
4826
4887
  description: "",
4827
4888
  dependencies: dependencies2,
4828
4889
  scripts: {
4829
- ...javascriptProject.scripts
4890
+ ...javascriptProject.scripts,
4891
+ ...typeof config.postInstall === "string" ? { postinstall: config.postInstall } : {}
4830
4892
  }
4831
4893
  };
4832
4894
  span.setAttributes({
@@ -4841,7 +4903,7 @@ async function compileProject(config, options, configPath) {
4841
4903
 
4842
4904
  ${copyResult.noMatches.map((glob) => `- "${glob}"`).join("\n")}
4843
4905
 
4844
- If this is unexpected you should check your ${terminalLink2(
4906
+ If this is unexpected you should check your ${cliLink(
4845
4907
  "glob patterns",
4846
4908
  "https://github.com/isaacs/node-glob?tab=readme-ov-file#glob-primer"
4847
4909
  )} are valid.`
@@ -4859,14 +4921,6 @@ If this is unexpected you should check your ${terminalLink2(
4859
4921
  }
4860
4922
  const containerFilePath = join6(cliRootPath(), "Containerfile.prod");
4861
4923
  let containerFileContents = readFileSync2(containerFilePath, "utf-8");
4862
- if (config.postInstall) {
4863
- containerFileContents = containerFileContents.replace(
4864
- "__POST_INSTALL__",
4865
- `RUN ${config.postInstall}`
4866
- );
4867
- } else {
4868
- containerFileContents = containerFileContents.replace("__POST_INSTALL__", "");
4869
- }
4870
4924
  await writeFile2(join6(tempDir, "Containerfile"), containerFileContents);
4871
4925
  const contentHasher = createHash("sha256");
4872
4926
  contentHasher.update(Buffer.from(entryPointOutputFile.text));
@@ -5299,9 +5353,11 @@ var TaskMetadataParseError = class extends Error {
5299
5353
  }
5300
5354
  };
5301
5355
  var UnexpectedExitError = class extends Error {
5302
- constructor(code) {
5356
+ constructor(code, signal, stderr) {
5303
5357
  super(`Unexpected exit with code ${code}`);
5304
5358
  this.code = code;
5359
+ this.signal = signal;
5360
+ this.stderr = stderr;
5305
5361
  this.name = "UnexpectedExitError";
5306
5362
  }
5307
5363
  };
@@ -5323,6 +5379,21 @@ var SigKillTimeoutProcessError = class extends Error {
5323
5379
  this.name = "SigKillTimeoutProcessError";
5324
5380
  }
5325
5381
  };
5382
+ function getFriendlyErrorMessage(code, signal, stderr) {
5383
+ const message = (text3) => {
5384
+ if (signal) {
5385
+ return `[${signal}] ${text3}`;
5386
+ } else {
5387
+ return text3;
5388
+ }
5389
+ };
5390
+ if (code === 137 || stderr?.includes("OOMErrorHandler")) {
5391
+ return message(
5392
+ "Process ran out of memory! Try choosing a machine preset with more memory for this task."
5393
+ );
5394
+ }
5395
+ return message(`Process exited with code ${code}.`);
5396
+ }
5326
5397
 
5327
5398
  // src/workers/dev/backgroundWorker.ts
5328
5399
  import {
@@ -5338,7 +5409,6 @@ import dotenv from "dotenv";
5338
5409
  import { Evt } from "evt";
5339
5410
  import { fork } from "node:child_process";
5340
5411
  import { dirname as dirname2, resolve as resolve4 } from "node:path";
5341
- import terminalLink3 from "terminal-link";
5342
5412
  var BackgroundWorkerCoordinator = class {
5343
5413
  constructor(baseURL) {
5344
5414
  this.baseURL = baseURL;
@@ -5575,7 +5645,7 @@ var BackgroundWorker = class {
5575
5645
  resolved = true;
5576
5646
  child.kill();
5577
5647
  reject(new Error("Worker timed out"));
5578
- }, 5e3);
5648
+ }, 2e4);
5579
5649
  child.on("message", async (msg) => {
5580
5650
  const message = this._handler.parseMessage(msg);
5581
5651
  if (message.type === "TASKS_READY" && !resolved) {
@@ -5745,7 +5815,7 @@ var BackgroundWorker = class {
5745
5815
  const logsUrl = `${baseURL}/runs/${execution.run.id}`;
5746
5816
  const pipe = chalkGrey("|");
5747
5817
  const bullet = chalkGrey("\u25CB");
5748
- const link = chalkLink(terminalLink3("View logs", logsUrl));
5818
+ const link = chalkLink(cliLink("View logs", logsUrl));
5749
5819
  let timestampPrefix = chalkGrey(prettyPrintDate(payload.execution.attempt.startedAt));
5750
5820
  const workerPrefix = chalkWorker(this.metadata.version);
5751
5821
  const taskPrefix = chalkTask(execution.task.id);
@@ -5822,7 +5892,9 @@ var BackgroundWorker = class {
5822
5892
  retry: void 0,
5823
5893
  error: {
5824
5894
  type: "INTERNAL_ERROR",
5825
- code: TaskRunErrorCodes.TASK_PROCESS_EXITED_WITH_NON_ZERO_CODE
5895
+ code: TaskRunErrorCodes.TASK_PROCESS_EXITED_WITH_NON_ZERO_CODE,
5896
+ message: getFriendlyErrorMessage(e.code, e.signal, e.stderr),
5897
+ stackTrace: e.stderr
5826
5898
  }
5827
5899
  };
5828
5900
  }
@@ -5884,6 +5956,7 @@ var TaskRunProcess = class {
5884
5956
  _currentExecution;
5885
5957
  _isBeingKilled = false;
5886
5958
  _isBeingCancelled = false;
5959
+ _stderr = [];
5887
5960
  /**
5888
5961
  * @deprecated use onTaskRunHeartbeat instead
5889
5962
  */
@@ -6043,7 +6116,13 @@ var TaskRunProcess = class {
6043
6116
  } else if (this._isBeingKilled) {
6044
6117
  rejecter(new CleanupProcessError());
6045
6118
  } else {
6046
- rejecter(new UnexpectedExitError(code ?? -1));
6119
+ rejecter(
6120
+ new UnexpectedExitError(
6121
+ code ?? -1,
6122
+ signal,
6123
+ this._stderr.length ? this._stderr.join("\n") : void 0
6124
+ )
6125
+ );
6047
6126
  }
6048
6127
  }
6049
6128
  }
@@ -6072,9 +6151,14 @@ var TaskRunProcess = class {
6072
6151
  const runId = chalkRun(
6073
6152
  `${this._currentExecution.run.id}.${this._currentExecution.attempt.number}`
6074
6153
  );
6154
+ const errorLine = data.toString();
6075
6155
  logger.log(
6076
- `${chalkError("\u25CB")} ${chalkGrey(prettyPrintDate(/* @__PURE__ */ new Date()))} ${runId} ${data.toString()}`
6156
+ `${chalkError("\u25CB")} ${chalkGrey(prettyPrintDate(/* @__PURE__ */ new Date()))} ${runId} ${errorLine}`
6077
6157
  );
6158
+ if (this._stderr.length > 100) {
6159
+ this._stderr.shift();
6160
+ }
6161
+ this._stderr.push(errorLine);
6078
6162
  }
6079
6163
  #kill() {
6080
6164
  logger.debug(`[${this.runId}] #kill()`, { pid: this.pid });
@@ -6594,12 +6678,18 @@ function useDev({
6594
6678
  throw new Error(backgroundWorkerRecord.error);
6595
6679
  }
6596
6680
  backgroundWorker.metadata = backgroundWorkerRecord.data;
6681
+ backgroundWorker;
6682
+ const testUrl = `${dashboardUrl}/projects/v3/${config.project}/test?environment=dev`;
6683
+ const runsUrl = `${dashboardUrl}/projects/v3/${config.project}/runs?envSlug=dev`;
6684
+ const pipe = chalkGrey("|");
6685
+ const bullet = chalkGrey("\u25CB");
6686
+ const arrow = chalkGrey("->");
6687
+ const testLink = chalkLink(cliLink("Test tasks", testUrl));
6688
+ const runsLink = chalkLink(cliLink("View runs", runsUrl));
6689
+ const workerStarted = chalkGrey("Background worker started");
6690
+ const workerVersion = chalkWorker(backgroundWorkerRecord.data.version);
6597
6691
  logger.log(
6598
- `${chalkGrey(
6599
- `\u25CB Background worker started -> ${chalkWorker(
6600
- backgroundWorkerRecord.data.version
6601
- )}`
6602
- )}`
6692
+ `${bullet} ${workerStarted} ${arrow} ${workerVersion} ${pipe} ${testLink} ${pipe} ${runsLink}`
6603
6693
  );
6604
6694
  firstBuild = false;
6605
6695
  await backgroundWorkerCoordinator.registerWorker(
@@ -6607,6 +6697,9 @@ function useDev({
6607
6697
  backgroundWorker
6608
6698
  );
6609
6699
  } catch (e) {
6700
+ logger.debug("Error starting background worker", {
6701
+ error: e
6702
+ });
6610
6703
  if (e instanceof TaskMetadataParseError) {
6611
6704
  logTaskMetadataParseError(e.zodIssues, e.tasks);
6612
6705
  return;
@@ -6837,11 +6930,10 @@ import { context as context3, trace as trace3 } from "@opentelemetry/api";
6837
6930
  import { flattenAttributes as flattenAttributes4 } from "@trigger.dev/core/v3";
6838
6931
  import { recordSpanException as recordSpanException6 } from "@trigger.dev/core/v3/workers";
6839
6932
  import chalk5 from "chalk";
6840
- import { execa as execa3 } from "execa";
6841
- import jsoncParser from "jsonc-parser";
6933
+ import { ExecaError as ExecaError2, execa as execa3 } from "execa";
6934
+ import { applyEdits, modify, findNodeAtLocation, parseTree, getNodeValue } from "jsonc-parser";
6842
6935
  import { writeFile as writeFile3 } from "node:fs/promises";
6843
6936
  import { join as join8, relative as relative4, resolve as resolve5 } from "node:path";
6844
- import terminalLink4 from "terminal-link";
6845
6937
  import { z as z6 } from "zod";
6846
6938
 
6847
6939
  // src/utilities/createFileFromTemplate.ts
@@ -6886,12 +6978,12 @@ function replaceAll(input, replacements) {
6886
6978
  }
6887
6979
 
6888
6980
  // src/commands/init.ts
6889
- var { applyEdits, modify, findNodeAtLocation, parseTree, getNodeValue } = jsoncParser;
6890
6981
  var InitCommandOptions = CommonCommandOptions.extend({
6891
6982
  projectRef: z6.string().optional(),
6892
6983
  overrideConfig: z6.boolean().default(false),
6893
6984
  tag: z6.string().default("beta"),
6894
- skipPackageInstall: z6.boolean().default(false)
6985
+ skipPackageInstall: z6.boolean().default(false),
6986
+ pkgArgs: z6.string().optional()
6895
6987
  });
6896
6988
  function configureInitCommand(program2) {
6897
6989
  return commonOptions(
@@ -6902,7 +6994,10 @@ function configureInitCommand(program2) {
6902
6994
  "-t, --tag <package tag>",
6903
6995
  "The version of the @trigger.dev/sdk package to install",
6904
6996
  version
6905
- ).option("--skip-package-install", "Skip installing the @trigger.dev/sdk package").option("--override-config", "Override the existing config file if it exists")
6997
+ ).option("--skip-package-install", "Skip installing the @trigger.dev/sdk package").option("--override-config", "Override the existing config file if it exists").option(
6998
+ "--pkg-args <args>",
6999
+ "Additional arguments to pass to the package manager, accepts CSV for multiple args"
7000
+ )
6906
7001
  ).action(async (path7, options) => {
6907
7002
  await handleTelemetry(async () => {
6908
7003
  await printStandloneInitialBanner(true);
@@ -6918,6 +7013,7 @@ async function initCommand(dir, options) {
6918
7013
  async function _initCommand(dir, options) {
6919
7014
  const span = trace3.getSpan(context3.active());
6920
7015
  intro5("Initializing project");
7016
+ await detectTsConfig(dir, options);
6921
7017
  const authorization = await login({
6922
7018
  embedded: true,
6923
7019
  defaultApiUrl: options.apiUrl,
@@ -6968,7 +7064,7 @@ async function _initCommand(dir, options) {
6968
7064
  await writeConfigFile(dir, selectedProject, options, triggerDir);
6969
7065
  await addConfigFileToTsConfig(dir, options);
6970
7066
  await gitIgnoreDotTriggerDir(dir, options);
6971
- const projectDashboard = terminalLink4(
7067
+ const projectDashboard = cliLink(
6972
7068
  "project dashboard",
6973
7069
  `${authorization.dashboardUrl}/projects/v3/${selectedProject.externalRef}`
6974
7070
  );
@@ -6981,13 +7077,10 @@ async function _initCommand(dir, options) {
6981
7077
  );
6982
7078
  log6.info(` 2. Visit your ${projectDashboard} to view your newly created tasks.`);
6983
7079
  log6.info(
6984
- ` 3. Head over to our ${terminalLink4(
6985
- "v3 docs",
6986
- "https://trigger.dev/docs/v3"
6987
- )} to learn more.`
7080
+ ` 3. Head over to our ${cliLink("v3 docs", "https://trigger.dev/docs/v3")} to learn more.`
6988
7081
  );
6989
7082
  log6.info(
6990
- ` 4. Need help? Join our ${terminalLink4(
7083
+ ` 4. Need help? Join our ${cliLink(
6991
7084
  "Discord community",
6992
7085
  "https://trigger.dev/discord"
6993
7086
  )} or email us at ${chalk5.cyan("help@trigger.dev")}`
@@ -7092,8 +7185,39 @@ async function gitIgnoreDotTriggerDir(dir, options) {
7092
7185
  }
7093
7186
  });
7094
7187
  }
7188
+ async function detectTsConfig(dir, options) {
7189
+ return await tracer.startActiveSpan("detectTsConfig", async (span) => {
7190
+ try {
7191
+ const projectDir = resolve5(process.cwd(), dir);
7192
+ const tsconfigPath = join8(projectDir, "tsconfig.json");
7193
+ span.setAttributes({
7194
+ "cli.projectDir": projectDir,
7195
+ "cli.tsconfigPath": tsconfigPath
7196
+ });
7197
+ const tsconfigExists = await pathExists(tsconfigPath);
7198
+ if (!tsconfigExists) {
7199
+ prettyError(
7200
+ "No tsconfig.json found",
7201
+ `The init command needs to be run in a TypeScript project. You can create one like this:`,
7202
+ `npm install typescript --save-dev
7203
+ npx tsc --init
7204
+ `
7205
+ );
7206
+ throw new Error("TypeScript required");
7207
+ }
7208
+ logger.debug("tsconfig.json exists", { tsconfigPath });
7209
+ span.end();
7210
+ } catch (e) {
7211
+ if (!(e instanceof SkipCommandError)) {
7212
+ recordSpanException6(span, e);
7213
+ }
7214
+ span.end();
7215
+ throw e;
7216
+ }
7217
+ });
7218
+ }
7095
7219
  async function addConfigFileToTsConfig(dir, options) {
7096
- return await tracer.startActiveSpan("createTriggerDir", async (span) => {
7220
+ return await tracer.startActiveSpan("addConfigFileToTsConfig", async (span) => {
7097
7221
  try {
7098
7222
  const projectDir = resolve5(process.cwd(), dir);
7099
7223
  const tsconfigPath = join8(projectDir, "tsconfig.json");
@@ -7144,49 +7268,58 @@ async function addConfigFileToTsConfig(dir, options) {
7144
7268
  async function installPackages2(dir, options) {
7145
7269
  return await tracer.startActiveSpan("installPackages", async (span) => {
7146
7270
  const installSpinner = spinner();
7271
+ let pkgManager;
7147
7272
  try {
7148
7273
  const projectDir = resolve5(process.cwd(), dir);
7149
- const pkgManager = await getUserPackageManager(projectDir);
7274
+ pkgManager = await getUserPackageManager(projectDir);
7150
7275
  span.setAttributes({
7151
7276
  "cli.projectDir": projectDir,
7152
7277
  "cli.packageManager": pkgManager,
7153
7278
  "cli.tag": options.tag
7154
7279
  });
7280
+ const userArgs = options.pkgArgs?.split(",") ?? [];
7281
+ const execaOptions = { cwd: projectDir };
7282
+ let installProcess;
7283
+ let args;
7155
7284
  switch (pkgManager) {
7156
7285
  case "npm": {
7157
- installSpinner.start(`Running npm install @trigger.dev/sdk@${options.tag}`);
7158
- await execa3("npm", ["install", "--save-exact", `@trigger.dev/sdk@${options.tag}`], {
7159
- cwd: projectDir,
7160
- stdio: options.logLevel === "debug" ? "inherit" : "ignore"
7161
- });
7162
- break;
7163
- }
7164
- case "pnpm": {
7165
- installSpinner.start(`Running pnpm add @trigger.dev/sdk@${options.tag}`);
7166
- await execa3("pnpm", ["add", `@trigger.dev/sdk@${options.tag}`], {
7167
- cwd: projectDir,
7168
- stdio: options.logLevel === "debug" ? "inherit" : "ignore"
7169
- });
7286
+ args = ["install", "--save-exact", ...userArgs, `@trigger.dev/sdk@${options.tag}`];
7170
7287
  break;
7171
7288
  }
7289
+ case "pnpm":
7172
7290
  case "yarn": {
7173
- installSpinner.start(`Running yarn add @trigger.dev/sdk@${options.tag}`);
7174
- await execa3("yarn", ["add", `@trigger.dev/sdk@${options.tag}`], {
7175
- cwd: projectDir,
7176
- stdio: options.logLevel === "debug" ? "inherit" : "ignore"
7177
- });
7291
+ args = ["add", ...userArgs, `@trigger.dev/sdk@${options.tag}`];
7178
7292
  break;
7179
7293
  }
7180
7294
  }
7295
+ installSpinner.start(`Running ${pkgManager} ${args.join(" ")}`);
7296
+ installProcess = execa3(pkgManager, args, execaOptions);
7297
+ const handleProcessOutput = (data) => {
7298
+ logger.debug(data.toString());
7299
+ };
7300
+ installProcess.stderr?.on("data", handleProcessOutput);
7301
+ installProcess.stdout?.on("data", handleProcessOutput);
7302
+ await installProcess;
7181
7303
  installSpinner.stop(`@trigger.dev/sdk@${options.tag} installed`);
7182
7304
  span.end();
7183
7305
  } catch (e) {
7184
- installSpinner.stop(
7185
- `Failed to install @trigger.dev/sdk@${options.tag}. Rerun command with --log-level debug for more details.`
7186
- );
7306
+ if (options.logLevel === "debug") {
7307
+ installSpinner.stop(`Failed to install @trigger.dev/sdk@${options.tag}.`);
7308
+ } else {
7309
+ installSpinner.stop(
7310
+ `Failed to install @trigger.dev/sdk@${options.tag}. Rerun command with --log-level debug for more details.`
7311
+ );
7312
+ }
7187
7313
  if (!(e instanceof SkipCommandError)) {
7188
7314
  recordSpanException6(span, e);
7189
7315
  }
7316
+ if (e instanceof ExecaError2) {
7317
+ if (pkgManager) {
7318
+ e.message += `
7319
+
7320
+ Note: You can pass additional args to ${pkgManager} by using --pkg-args. For example: trigger.dev init --pkg-args="--workspace-root"`;
7321
+ }
7322
+ }
7190
7323
  span.end();
7191
7324
  throw e;
7192
7325
  }
@@ -7255,7 +7388,7 @@ async function selectProject(apiClient2, dashboardUrl, projectRef) {
7255
7388
  throw new Error(`Failed to get projects: ${projectsResponse.error}`);
7256
7389
  }
7257
7390
  if (projectsResponse.data.length === 0) {
7258
- const newProjectLink = terminalLink4(
7391
+ const newProjectLink = cliLink(
7259
7392
  "Create new project",
7260
7393
  `${dashboardUrl}/projects/new?version=v3`
7261
7394
  );