trigger.dev 3.0.0-beta.3 → 3.0.0-beta.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.
package/dist/index.js CHANGED
@@ -781,11 +781,12 @@ import { intro as intro3, log as log2, outro as outro3, spinner as spinner4 } fr
781
781
  import { depot } from "@depot/cli";
782
782
  import { context, trace as trace2 } from "@opentelemetry/api";
783
783
  import {
784
+ TaskMetadataFailedToParseData,
784
785
  detectDependencyVersion,
785
786
  flattenAttributes as flattenAttributes2,
786
787
  recordSpanException as recordSpanException4
787
788
  } from "@trigger.dev/core/v3";
788
- import chalk4 from "chalk";
789
+ import chalk5 from "chalk";
789
790
  import { Option as CommandOption } from "commander";
790
791
  import { build as build2 } from "esbuild";
791
792
  import { execa as execa2 } from "execa";
@@ -793,14 +794,14 @@ import { resolve as importResolve } from "import-meta-resolve";
793
794
  import { createHash } from "node:crypto";
794
795
  import { readFileSync as readFileSync2 } from "node:fs";
795
796
  import { copyFile, mkdir, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
796
- import { dirname, join as join4, relative as relative2 } from "node:path";
797
+ import { dirname, join as join4, relative as relative3 } from "node:path";
797
798
  import { setTimeout as setTimeout2 } from "node:timers/promises";
798
799
  import terminalLink from "terminal-link";
799
800
  import invariant from "tiny-invariant";
800
801
  import { z as z4 } from "zod";
801
802
 
802
803
  // package.json
803
- var version = "3.0.0-beta.3";
804
+ var version = "3.0.0-beta.5";
804
805
  var dependencies = {
805
806
  "@clack/prompts": "^0.7.0",
806
807
  "@depot/cli": "0.0.1-cli.2.55.0",
@@ -816,7 +817,7 @@ var dependencies = {
816
817
  "@opentelemetry/sdk-trace-base": "^1.22.0",
817
818
  "@opentelemetry/sdk-trace-node": "^1.22.0",
818
819
  "@opentelemetry/semantic-conventions": "^1.22.0",
819
- "@trigger.dev/core": "workspace:^3.0.0-beta.2",
820
+ "@trigger.dev/core": "workspace:^3.0.0-beta.5",
820
821
  "@types/degit": "^2.8.3",
821
822
  chalk: "^5.2.0",
822
823
  chokidar: "^3.5.3",
@@ -1307,7 +1308,7 @@ var Logger = class {
1307
1308
  const kind = LOGGER_LEVEL_FORMAT_TYPE_MAP[level];
1308
1309
  if (kind) {
1309
1310
  const [firstLine, ...otherLines] = message.split("\n");
1310
- const notes = otherLines.length > 0 ? otherLines.map((text2) => ({ text: text2 })) : void 0;
1311
+ const notes = otherLines.length > 0 ? otherLines.map((text3) => ({ text: text3 })) : void 0;
1311
1312
  return formatMessagesSync([{ text: firstLine, notes }], {
1312
1313
  color: true,
1313
1314
  kind,
@@ -1322,6 +1323,58 @@ var logger = new Logger();
1322
1323
 
1323
1324
  // src/cli/common.ts
1324
1325
  import { outro } from "@clack/prompts";
1326
+
1327
+ // src/utilities/cliOutput.ts
1328
+ import chalk2 from "chalk";
1329
+ var green = "#4FFF54";
1330
+ var purple = "#735BF3";
1331
+ function chalkGreen(text3) {
1332
+ return chalk2.hex(green)(text3);
1333
+ }
1334
+ function chalkPurple(text3) {
1335
+ return chalk2.hex(purple)(text3);
1336
+ }
1337
+ function chalkGrey(text3) {
1338
+ return chalk2.hex("#878C99")(text3);
1339
+ }
1340
+ function chalkError(text3) {
1341
+ return chalk2.hex("#E11D48")(text3);
1342
+ }
1343
+ function chalkWarning(text3) {
1344
+ return chalk2.yellow(text3);
1345
+ }
1346
+ function chalkSuccess(text3) {
1347
+ return chalk2.hex("#28BF5C")(text3);
1348
+ }
1349
+ function chalkLink(text3) {
1350
+ return chalk2.underline.hex("#D7D9DD")(text3);
1351
+ }
1352
+ function chalkWorker(text3) {
1353
+ return chalk2.hex("#FFFF89")(text3);
1354
+ }
1355
+ function chalkTask(text3) {
1356
+ return chalk2.hex("#60A5FA")(text3);
1357
+ }
1358
+ function chalkRun(text3) {
1359
+ return chalk2.hex("#A78BFA")(text3);
1360
+ }
1361
+ function logo() {
1362
+ return `${chalk2.hex(green).bold("Trigger")}${chalk2.hex(purple).bold(".dev")}`;
1363
+ }
1364
+ function prettyPrintDate(date = /* @__PURE__ */ new Date()) {
1365
+ let formattedDate = new Intl.DateTimeFormat("en-US", {
1366
+ month: "short",
1367
+ day: "2-digit",
1368
+ hour: "2-digit",
1369
+ minute: "2-digit",
1370
+ second: "2-digit",
1371
+ hour12: false
1372
+ }).format(date);
1373
+ formattedDate += "." + ("00" + date.getMilliseconds()).slice(-3);
1374
+ return formattedDate;
1375
+ }
1376
+
1377
+ // src/cli/common.ts
1325
1378
  var CommonCommandOptions = z.object({
1326
1379
  apiUrl: z.string().optional(),
1327
1380
  logLevel: z.enum(["debug", "info", "log", "warn", "error", "none"]).default("log"),
@@ -1331,7 +1384,7 @@ var CommonCommandOptions = z.object({
1331
1384
  function commonOptions(command) {
1332
1385
  return command.option("--profile <profile>", "The login profile to use", "default").option("-a, --api-url <value>", "Override the API URL", "https://api.trigger.dev").option(
1333
1386
  "-l, --log-level <level>",
1334
- "The log level to use (debug, info, log, warn, error, none)",
1387
+ "The CLI log level to use (debug, info, log, warn, error, none). This does not effect the log level of your trigger.dev tasks.",
1335
1388
  "log"
1336
1389
  ).option("--skip-telemetry", "Opt-out of sending telemetry");
1337
1390
  }
@@ -1377,7 +1430,7 @@ async function wrapCommandAction(name, schema, options, action) {
1377
1430
  } else if (e instanceof SkipCommandError) {
1378
1431
  } else {
1379
1432
  recordSpanException(span, e);
1380
- logger.error(e instanceof Error ? e.message : String(e));
1433
+ logger.log(`${chalkError("X Error:")} ${e instanceof Error ? e.message : String(e)}`);
1381
1434
  }
1382
1435
  span.end();
1383
1436
  throw e;
@@ -1535,6 +1588,11 @@ function readAuthConfigProfile(profile = "default") {
1535
1588
  return void 0;
1536
1589
  }
1537
1590
  }
1591
+ function deleteAuthConfigProfile(profile = "default") {
1592
+ const existingConfig = readAuthConfigFile() || {};
1593
+ delete existingConfig[profile];
1594
+ writeAuthConfigFile(existingConfig);
1595
+ }
1538
1596
  function readAuthConfigFile() {
1539
1597
  try {
1540
1598
  const authConfigFilePath = getAuthConfigFilePath();
@@ -1639,50 +1697,6 @@ import chalk3 from "chalk";
1639
1697
  import supportsColor from "supports-color";
1640
1698
  import checkForUpdate from "update-check";
1641
1699
 
1642
- // src/utilities/cliOutput.ts
1643
- import chalk2 from "chalk";
1644
- var green = "#4FFF54";
1645
- var purple = "#735BF3";
1646
- function chalkGrey(text2) {
1647
- return chalk2.hex("#878C99")(text2);
1648
- }
1649
- function chalkError(text2) {
1650
- return chalk2.hex("#E11D48")(text2);
1651
- }
1652
- function chalkWarning(text2) {
1653
- return chalk2.yellow(text2);
1654
- }
1655
- function chalkSuccess(text2) {
1656
- return chalk2.hex("#28BF5C")(text2);
1657
- }
1658
- function chalkLink(text2) {
1659
- return chalk2.underline.hex("#D7D9DD")(text2);
1660
- }
1661
- function chalkWorker(text2) {
1662
- return chalk2.hex("#FFFF89")(text2);
1663
- }
1664
- function chalkTask(text2) {
1665
- return chalk2.hex("#60A5FA")(text2);
1666
- }
1667
- function chalkRun(text2) {
1668
- return chalk2.hex("#A78BFA")(text2);
1669
- }
1670
- function logo() {
1671
- return `${chalk2.hex(green).bold("Trigger")}${chalk2.hex(purple).bold(".dev")}`;
1672
- }
1673
- function prettyPrintDate(date = /* @__PURE__ */ new Date()) {
1674
- let formattedDate = new Intl.DateTimeFormat("en-US", {
1675
- month: "short",
1676
- day: "2-digit",
1677
- hour: "2-digit",
1678
- minute: "2-digit",
1679
- second: "2-digit",
1680
- hour12: false
1681
- }).format(date);
1682
- formattedDate += "." + ("00" + date.getMilliseconds()).slice(-3);
1683
- return formattedDate;
1684
- }
1685
-
1686
1700
  // src/utilities/getVersion.ts
1687
1701
  import path3 from "path";
1688
1702
  function getVersion() {
@@ -1694,10 +1708,10 @@ function getVersion() {
1694
1708
  // src/utilities/initialBanner.ts
1695
1709
  async function printInitialBanner(performUpdateCheck = true) {
1696
1710
  const packageVersion = getVersion();
1697
- const text2 = `
1711
+ const text3 = `
1698
1712
  ${logo()} ${chalkGrey(`(${packageVersion})`)}
1699
1713
  `;
1700
- logger.info(text2);
1714
+ logger.info(text3);
1701
1715
  let maybeNewVersion;
1702
1716
  if (performUpdateCheck) {
1703
1717
  const loadingSpinner = spinner();
@@ -1721,15 +1735,15 @@ After installation, run Trigger.dev with \`npx trigger.dev\`.`
1721
1735
  }
1722
1736
  async function printStandloneInitialBanner(performUpdateCheck = true) {
1723
1737
  const packageVersion = getVersion();
1724
- let text2 = `
1738
+ let text3 = `
1725
1739
  ${logo()} ${chalkGrey("(v3 Developer Preview)")}`;
1726
1740
  if (performUpdateCheck) {
1727
1741
  const maybeNewVersion = await updateCheck();
1728
1742
  if (maybeNewVersion !== void 0) {
1729
- text2 = `${text2} (update available ${chalk3.green(maybeNewVersion)})`;
1743
+ text3 = `${text3} (update available ${chalk3.green(maybeNewVersion)})`;
1730
1744
  }
1731
1745
  }
1732
- logger.log(text2 + "\n" + (supportsColor.stdout ? chalkGrey("-".repeat(54)) : "-".repeat(54)));
1746
+ logger.log(text3 + "\n" + (supportsColor.stdout ? chalkGrey("-".repeat(54)) : "-".repeat(54)));
1733
1747
  }
1734
1748
  function printDevBanner() {
1735
1749
  logger.log(
@@ -1761,20 +1775,14 @@ async function installPackages(packages, options) {
1761
1775
  const cwd = options?.cwd ?? process.cwd();
1762
1776
  logger.debug("Installing packages", { packages });
1763
1777
  await setPackageJsonDeps(join3(cwd, "package.json"), packages);
1764
- const childProcess2 = execa(
1778
+ await execa(
1765
1779
  "npm",
1766
1780
  ["install", "--install-strategy", "nested", "--ignore-scripts", "--no-audit", "--no-fund"],
1767
1781
  {
1768
1782
  cwd,
1769
- stderr: "inherit"
1783
+ stderr: "pipe"
1770
1784
  }
1771
1785
  );
1772
- await new Promise((res, rej) => {
1773
- childProcess2.on("error", (e) => rej(e));
1774
- childProcess2.on("close", () => res());
1775
- });
1776
- await childProcess2;
1777
- return;
1778
1786
  }
1779
1787
  function detectPackageNameFromImportPath(path6) {
1780
1788
  if (path6.startsWith("@")) {
@@ -2718,6 +2726,9 @@ ${authorizationCodeResult.error}`
2718
2726
  });
2719
2727
  }
2720
2728
 
2729
+ // src/commands/deploy.ts
2730
+ import { Glob } from "glob";
2731
+
2721
2732
  // src/utilities/build.ts
2722
2733
  import { readFileSync } from "node:fs";
2723
2734
  import { extname, isAbsolute } from "node:path";
@@ -2868,8 +2879,151 @@ function getLoaderForFile(file) {
2868
2879
  throw new Error(`Cannot get loader for file ${file}`);
2869
2880
  }
2870
2881
 
2882
+ // src/utilities/deployErrors.ts
2883
+ import chalk4 from "chalk";
2884
+ import { relative as relative2 } from "node:path";
2885
+ import { groupTaskMetadataIssuesByTask } from "@trigger.dev/core/v3";
2886
+ function errorIsErrorLike(error) {
2887
+ return error instanceof Error || typeof error === "object" && error !== null && "message" in error;
2888
+ }
2889
+ function parseBuildErrorStack(error) {
2890
+ if (typeof error === "string") {
2891
+ return error;
2892
+ }
2893
+ if (errorIsErrorLike(error)) {
2894
+ if (typeof error.stack === "string") {
2895
+ const isErrRequireEsm = error.stack.includes("ERR_REQUIRE_ESM");
2896
+ let moduleName = null;
2897
+ if (isErrRequireEsm) {
2898
+ const moduleRegex = /node_modules\/(@[^\/]+\/[^\/]+|[^\/]+)\/[^\/]+\s/;
2899
+ const match = moduleRegex.exec(error.stack);
2900
+ if (match) {
2901
+ moduleName = match[1];
2902
+ return {
2903
+ type: "esm-require-error",
2904
+ moduleName
2905
+ };
2906
+ }
2907
+ }
2908
+ } else {
2909
+ return error.message;
2910
+ }
2911
+ }
2912
+ return "Unknown error";
2913
+ }
2914
+ function logESMRequireError(parsedError, resolvedConfig) {
2915
+ logger.log(
2916
+ `
2917
+ ${chalkError("X Error:")} The ${chalkPurple(
2918
+ parsedError.moduleName
2919
+ )} module is being required even though it's ESM only, and builds only support CommonJS. There are two ${chalk4.underline(
2920
+ "possible"
2921
+ )} ways to fix this:`
2922
+ );
2923
+ logger.log(
2924
+ `
2925
+ ${chalkGrey("\u25CB")} Dynamically import the module in your code: ${chalkGrey(
2926
+ `const myModule = await import("${parsedError.moduleName}");`
2927
+ )}`
2928
+ );
2929
+ if (resolvedConfig.status === "file") {
2930
+ const relativePath = relative2(resolvedConfig.config.projectDir, resolvedConfig.path).replace(
2931
+ /\\/g,
2932
+ "/"
2933
+ );
2934
+ logger.log(
2935
+ `${chalkGrey("\u25CB")} ${chalk4.underline("Or")} add ${chalkPurple(
2936
+ parsedError.moduleName
2937
+ )} to the ${chalkGreen("dependenciesToBundle")} array in your config file ${chalkGrey(
2938
+ `(${relativePath})`
2939
+ )}. This will bundle the module with your code.
2940
+ `
2941
+ );
2942
+ } else {
2943
+ logger.log(
2944
+ `${chalkGrey("\u25CB")} ${chalk4.underline("Or")} add ${chalkPurple(
2945
+ parsedError.moduleName
2946
+ )} to the ${chalkGreen("dependenciesToBundle")} array in your config file ${chalkGrey(
2947
+ "(you'll need to create one)"
2948
+ )}. This will bundle the module with your code.
2949
+ `
2950
+ );
2951
+ }
2952
+ }
2953
+ function parseNpmInstallError(error) {
2954
+ if (typeof error === "string") {
2955
+ return error;
2956
+ }
2957
+ if (error instanceof Error) {
2958
+ if (typeof error.stack === "string") {
2959
+ const isPackageNotFoundError = error.stack.includes("ERR! 404 Not Found") && error.stack.includes("is not in this registry");
2960
+ let packageName = null;
2961
+ if (isPackageNotFoundError) {
2962
+ const packageNameRegex = /'([^']+)' is not in this registry/;
2963
+ const match = packageNameRegex.exec(error.stack);
2964
+ if (match) {
2965
+ packageName = match[1];
2966
+ }
2967
+ }
2968
+ if (packageName) {
2969
+ return {
2970
+ type: "package-not-found-error",
2971
+ packageName
2972
+ };
2973
+ }
2974
+ const noMatchingVersionRegex = /No matching version found for ([^\s]+)\s/;
2975
+ const noMatchingVersionMatch = noMatchingVersionRegex.exec(error.stack);
2976
+ if (noMatchingVersionMatch) {
2977
+ return {
2978
+ type: "no-matching-version-error",
2979
+ packageName: noMatchingVersionMatch[1].replace(/.$/, "")
2980
+ };
2981
+ }
2982
+ return error.message;
2983
+ } else {
2984
+ return error.message;
2985
+ }
2986
+ }
2987
+ return "Unknown error";
2988
+ }
2989
+ function logTaskMetadataParseError(zodIssues, tasks) {
2990
+ logger.log(
2991
+ `
2992
+ ${chalkError("X Error:")} Failed to start. The following ${zodIssues.length === 1 ? "task issue was" : "task issues were"} found:`
2993
+ );
2994
+ const groupedIssues = groupTaskMetadataIssuesByTask(tasks, zodIssues);
2995
+ for (const key in groupedIssues) {
2996
+ const taskWithIssues = groupedIssues[key];
2997
+ if (!taskWithIssues) {
2998
+ continue;
2999
+ }
3000
+ logger.log(
3001
+ `
3002
+ ${chalkWarning("\u276F")} ${taskWithIssues.exportName} ${chalkGrey("in")} ${taskWithIssues.filePath}`
3003
+ );
3004
+ for (const issue of taskWithIssues.issues) {
3005
+ if (issue.path) {
3006
+ logger.log(` ${chalkError("x")} ${issue.path} ${chalkGrey(issue.message)}`);
3007
+ } else {
3008
+ logger.log(` ${chalkError("x")} ${chalkGrey(issue.message)}`);
3009
+ }
3010
+ }
3011
+ }
3012
+ }
3013
+
3014
+ // src/utilities/safeJsonParse.ts
3015
+ function safeJsonParse(json) {
3016
+ if (!json) {
3017
+ return void 0;
3018
+ }
3019
+ try {
3020
+ return JSON.parse(json);
3021
+ } catch {
3022
+ return void 0;
3023
+ }
3024
+ }
3025
+
2871
3026
  // src/commands/deploy.ts
2872
- import { Glob } from "glob";
2873
3027
  var DeployCommandOptions = CommonCommandOptions.extend({
2874
3028
  skipTypecheck: z4.boolean().default(false),
2875
3029
  skipDeploy: z4.boolean().default(false),
@@ -3043,26 +3197,38 @@ async function _deployCommand(dir, options) {
3043
3197
  "Failed to initialize deployment. The deployment does not have any external build data. To deploy this project, you must use the --self-hosted flag to build and push the image yourself."
3044
3198
  );
3045
3199
  }
3046
- return buildAndPushImage({
3047
- registryHost,
3048
- auth: authorization.auth.accessToken,
3049
- imageTag: deploymentResponse.data.imageTag,
3050
- buildId: deploymentResponse.data.externalBuildData.buildId,
3051
- buildToken: deploymentResponse.data.externalBuildData.buildToken,
3052
- buildProjectId: deploymentResponse.data.externalBuildData.projectId,
3053
- cwd: compilation.path,
3054
- projectId: resolvedConfig.config.project,
3055
- deploymentId: deploymentResponse.data.id,
3056
- deploymentVersion: deploymentResponse.data.version,
3057
- contentHash: deploymentResponse.data.contentHash,
3058
- projectRef: resolvedConfig.config.project,
3059
- loadImage: options.loadImage,
3060
- buildPlatform: options.buildPlatform
3061
- });
3200
+ return buildAndPushImage(
3201
+ {
3202
+ registryHost,
3203
+ auth: authorization.auth.accessToken,
3204
+ imageTag: deploymentResponse.data.imageTag,
3205
+ buildId: deploymentResponse.data.externalBuildData.buildId,
3206
+ buildToken: deploymentResponse.data.externalBuildData.buildToken,
3207
+ buildProjectId: deploymentResponse.data.externalBuildData.projectId,
3208
+ cwd: compilation.path,
3209
+ projectId: resolvedConfig.config.project,
3210
+ deploymentId: deploymentResponse.data.id,
3211
+ deploymentVersion: deploymentResponse.data.version,
3212
+ contentHash: deploymentResponse.data.contentHash,
3213
+ projectRef: resolvedConfig.config.project,
3214
+ loadImage: options.loadImage,
3215
+ buildPlatform: options.buildPlatform
3216
+ },
3217
+ deploymentSpinner
3218
+ );
3062
3219
  };
3063
3220
  const image = await buildImage();
3064
3221
  if (!image.ok) {
3065
- deploymentSpinner.stop(`Failed to build project image: ${image.error}`);
3222
+ deploymentSpinner.stop(`Failed to build project.`);
3223
+ if (image.logs.trim() !== "") {
3224
+ const logPath = join4(await createTempDir(), `build-${deploymentResponse.data.shortCode}.log`);
3225
+ await writeFile2(logPath, image.logs);
3226
+ logger.log(
3227
+ `${chalkError("X Error:")} ${image.error}. Full build logs have been saved to ${logPath})`
3228
+ );
3229
+ } else {
3230
+ logger.log(`${chalkError("X Error:")} ${image.error}.`);
3231
+ }
3066
3232
  throw new SkipLoggingError(`Failed to build project image: ${image.error}`);
3067
3233
  }
3068
3234
  const imageReference = options.selfHosted ? `${selfHostedRegistryHost ? `${selfHostedRegistryHost}/` : ""}${image.image}${image.digest ? `@${image.digest}` : ""}` : `${registryHost}/${image.image}${image.digest ? `@${image.digest}` : ""}`;
@@ -3122,10 +3288,27 @@ async function _deployCommand(dir, options) {
3122
3288
  }
3123
3289
  case "FAILED": {
3124
3290
  if (finishedDeployment.errorData) {
3125
- deploymentSpinner.stop(
3126
- `Deployment encountered an error: ${finishedDeployment.errorData.name}. ${deploymentLink}`
3127
- );
3128
- logger.error(finishedDeployment.errorData.stack);
3291
+ if (finishedDeployment.errorData.name === "TaskMetadataParseError") {
3292
+ const errorJson = safeJsonParse(finishedDeployment.errorData.stack);
3293
+ if (errorJson) {
3294
+ const parsedError2 = TaskMetadataFailedToParseData.safeParse(errorJson);
3295
+ if (parsedError2.success) {
3296
+ deploymentSpinner.stop(`Deployment encountered an error. ${deploymentLink}`);
3297
+ logTaskMetadataParseError(parsedError2.data.zodIssues, parsedError2.data.tasks);
3298
+ throw new SkipLoggingError(
3299
+ `Deployment encountered an error: ${finishedDeployment.errorData.name}`
3300
+ );
3301
+ }
3302
+ }
3303
+ }
3304
+ const parsedError = finishedDeployment.errorData.stack ? parseBuildErrorStack(finishedDeployment.errorData) : finishedDeployment.errorData.message;
3305
+ if (typeof parsedError === "string") {
3306
+ deploymentSpinner.stop(`Deployment encountered an error. ${deploymentLink}`);
3307
+ logger.log(`${chalkError("X Error:")} ${parsedError}`);
3308
+ } else {
3309
+ deploymentSpinner.stop(`Deployment encountered an error. ${deploymentLink}`);
3310
+ logESMRequireError(parsedError, resolvedConfig);
3311
+ }
3129
3312
  throw new SkipLoggingError(
3130
3313
  `Deployment encountered an error: ${finishedDeployment.errorData.name}`
3131
3314
  );
@@ -3163,7 +3346,7 @@ async function checkEnvVars(envVars, config, options, environmentClient, apiUrl)
3163
3346
  environmentVariablesSpinner.stop(
3164
3347
  `Found missing env vars in ${options.env}: ${arrayToSentence(
3165
3348
  missingEnvironmentVariables
3166
- )}. ${options.ignoreEnvVarCheck ? "Continuing deployment because of --ignore-env-var-check. " : "Aborting deployment. "}${chalk4.bgBlueBright(
3349
+ )}. ${options.ignoreEnvVarCheck ? "Continuing deployment because of --ignore-env-var-check. " : "Aborting deployment. "}${chalk5.bgBlueBright(
3167
3350
  terminalLink(
3168
3351
  "Manage env vars",
3169
3352
  `${apiUrl}/projects/v3/${config.project}/environment-variables`
@@ -3224,7 +3407,7 @@ async function waitForDeploymentToFinish(deploymentId, client, timeoutInSeconds
3224
3407
  }
3225
3408
  });
3226
3409
  }
3227
- async function buildAndPushImage(options) {
3410
+ async function buildAndPushImage(options, updater) {
3228
3411
  return tracer.startActiveSpan("buildAndPushImage", async (span) => {
3229
3412
  span.setAttributes({
3230
3413
  "options.registryHost": options.registryHost,
@@ -3280,15 +3463,23 @@ async function buildAndPushImage(options) {
3280
3463
  });
3281
3464
  const errors = [];
3282
3465
  try {
3283
- await new Promise((res, rej) => {
3466
+ const processCode = await new Promise((res, rej) => {
3284
3467
  childProcess2.stderr?.on("data", (data) => {
3285
- const text2 = data.toString();
3286
- errors.push(text2);
3287
- logger.debug(text2);
3468
+ const text3 = data.toString();
3469
+ errors.push(text3);
3470
+ logger.debug(text3);
3288
3471
  });
3289
3472
  childProcess2.on("error", (e) => rej(e));
3290
- childProcess2.on("close", () => res());
3473
+ childProcess2.on("close", (code) => res(code));
3291
3474
  });
3475
+ const logs = extractLogs(errors);
3476
+ if (processCode !== 0) {
3477
+ return {
3478
+ ok: false,
3479
+ error: `Error building image`,
3480
+ logs
3481
+ };
3482
+ }
3292
3483
  const digest = extractImageDigest(errors);
3293
3484
  span.setAttributes({
3294
3485
  "image.digest": digest
@@ -3297,6 +3488,7 @@ async function buildAndPushImage(options) {
3297
3488
  return {
3298
3489
  ok: true,
3299
3490
  image: options.imageTag,
3491
+ logs,
3300
3492
  digest
3301
3493
  };
3302
3494
  } catch (e) {
@@ -3304,7 +3496,8 @@ async function buildAndPushImage(options) {
3304
3496
  span.end();
3305
3497
  return {
3306
3498
  ok: false,
3307
- error: e instanceof Error ? e.message : JSON.stringify(e)
3499
+ error: e instanceof Error ? e.message : JSON.stringify(e),
3500
+ logs: extractLogs(errors)
3308
3501
  };
3309
3502
  }
3310
3503
  });
@@ -3352,9 +3545,9 @@ async function buildAndPushSelfHostedImage(options) {
3352
3545
  try {
3353
3546
  await new Promise((res, rej) => {
3354
3547
  buildProcess.stderr?.on("data", (data) => {
3355
- const text2 = data.toString();
3356
- errors.push(text2);
3357
- logger.debug(text2);
3548
+ const text3 = data.toString();
3549
+ errors.push(text3);
3550
+ logger.debug(text3);
3358
3551
  });
3359
3552
  buildProcess.on("error", (e) => rej(e));
3360
3553
  buildProcess.on("close", () => res());
@@ -3368,7 +3561,8 @@ async function buildAndPushSelfHostedImage(options) {
3368
3561
  span.end();
3369
3562
  return {
3370
3563
  ok: false,
3371
- error: e instanceof Error ? e.message : JSON.stringify(e)
3564
+ error: e instanceof Error ? e.message : JSON.stringify(e),
3565
+ logs: extractLogs(errors)
3372
3566
  };
3373
3567
  }
3374
3568
  const pushArgs = ["push", imageRef].filter(Boolean);
@@ -3381,12 +3575,12 @@ async function buildAndPushSelfHostedImage(options) {
3381
3575
  try {
3382
3576
  await new Promise((res, rej) => {
3383
3577
  pushProcess.stdout?.on("data", (data) => {
3384
- const text2 = data.toString();
3385
- logger.debug(text2);
3578
+ const text3 = data.toString();
3579
+ logger.debug(text3);
3386
3580
  });
3387
3581
  pushProcess.stderr?.on("data", (data) => {
3388
- const text2 = data.toString();
3389
- logger.debug(text2);
3582
+ const text3 = data.toString();
3583
+ logger.debug(text3);
3390
3584
  });
3391
3585
  pushProcess.on("error", (e) => rej(e));
3392
3586
  pushProcess.on("close", () => res());
@@ -3397,7 +3591,8 @@ async function buildAndPushSelfHostedImage(options) {
3397
3591
  span.end();
3398
3592
  return {
3399
3593
  ok: false,
3400
- error: e instanceof Error ? e.message : JSON.stringify(e)
3594
+ error: e instanceof Error ? e.message : JSON.stringify(e),
3595
+ logs: extractLogs(errors)
3401
3596
  };
3402
3597
  }
3403
3598
  }
@@ -3405,7 +3600,8 @@ async function buildAndPushSelfHostedImage(options) {
3405
3600
  return {
3406
3601
  ok: true,
3407
3602
  image: options.imageTag,
3408
- digest
3603
+ digest,
3604
+ logs: extractLogs(errors)
3409
3605
  };
3410
3606
  });
3411
3607
  }
@@ -3420,6 +3616,10 @@ function extractImageDigest(outputs) {
3420
3616
  }
3421
3617
  }
3422
3618
  }
3619
+ function extractLogs(outputs) {
3620
+ const cleanedOutputs = outputs.map((line) => line.trim()).filter((line) => line !== "");
3621
+ return cleanedOutputs.map((line) => line.trim()).join("\n");
3622
+ }
3423
3623
  async function compileProject(config, options, configPath) {
3424
3624
  return await tracer.startActiveSpan("compileProject", async (span) => {
3425
3625
  try {
@@ -3604,7 +3804,7 @@ async function compileProject(config, options, configPath) {
3604
3804
  options
3605
3805
  );
3606
3806
  if (!resolvingDependenciesResult) {
3607
- throw new Error("Failed to resolve dependencies");
3807
+ throw new SkipLoggingError("Failed to resolve dependencies");
3608
3808
  }
3609
3809
  const containerFilePath = new URL(
3610
3810
  importResolve("./Containerfile.prod", import.meta.url)
@@ -3683,12 +3883,35 @@ async function resolveDependencies(projectDir, packageJsonContents, config, opti
3683
3883
  resolvingDepsSpinner.stop("Dependencies resolved");
3684
3884
  return true;
3685
3885
  } catch (installError) {
3686
- logger.debug(`Failed to resolve dependencies: ${JSON.stringify(installError)}`);
3687
3886
  recordSpanException4(span, installError);
3688
3887
  span.end();
3689
- resolvingDepsSpinner.stop(
3690
- "Failed to resolve dependencies. Rerun with --log-level=debug for more information"
3691
- );
3888
+ const parsedError = parseNpmInstallError(installError);
3889
+ if (typeof parsedError === "string") {
3890
+ resolvingDepsSpinner.stop(`Failed to resolve dependencies: ${parsedError}`);
3891
+ } else {
3892
+ switch (parsedError.type) {
3893
+ case "package-not-found-error": {
3894
+ resolvingDepsSpinner.stop(`Failed to resolve dependencies`);
3895
+ logger.log(
3896
+ `
3897
+ ${chalkError("X Error:")} The package ${chalkPurple(
3898
+ parsedError.packageName
3899
+ )} could not be found in the npm registry.`
3900
+ );
3901
+ break;
3902
+ }
3903
+ case "no-matching-version-error": {
3904
+ resolvingDepsSpinner.stop(`Failed to resolve dependencies`);
3905
+ logger.log(
3906
+ `
3907
+ ${chalkError("X Error:")} The package ${chalkPurple(
3908
+ parsedError.packageName
3909
+ )} could not resolve because the version doesn't exist`
3910
+ );
3911
+ break;
3912
+ }
3913
+ }
3914
+ }
3692
3915
  return false;
3693
3916
  }
3694
3917
  }
@@ -3770,8 +3993,10 @@ async function gatherRequiredDependencies(imports, config, projectPackageJson) {
3770
3993
  dependencies2[packageParts.name] = externalDependencyVersion;
3771
3994
  continue;
3772
3995
  } else {
3773
- logger.warn(
3774
- `Could not find version for package ${packageName}, add a version specifier to the package name (e.g. ${packageParts.name}@latest) or add it to your project's package.json`
3996
+ logger.log(
3997
+ `${chalkWarning("X Warning:")} Could not find version for package ${chalkPurple(
3998
+ packageName
3999
+ )}, add a version specifier to the package name (e.g. ${packageParts.name}@latest) or add it to your project's package.json`
3775
4000
  );
3776
4001
  }
3777
4002
  }
@@ -3805,7 +4030,7 @@ async function copyAdditionalFiles(config, tempDir) {
3805
4030
  for await (const file of glob) {
3806
4031
  const relativeDestinationPath = join4(
3807
4032
  tempDir,
3808
- relative2(config.projectDir, file.fullpath())
4033
+ relative3(config.projectDir, file.fullpath())
3809
4034
  );
3810
4035
  logger.debug(`Copying file ${file.fullpath()} to ${relativeDestinationPath}`);
3811
4036
  await mkdir(dirname(relativeDestinationPath), { recursive: true });
@@ -3885,6 +4110,14 @@ var UncaughtExceptionError = class extends Error {
3885
4110
  this.name = "UncaughtExceptionError";
3886
4111
  }
3887
4112
  };
4113
+ var TaskMetadataParseError = class extends Error {
4114
+ constructor(zodIssues, tasks) {
4115
+ super(`Failed to parse task metadata`);
4116
+ this.zodIssues = zodIssues;
4117
+ this.tasks = tasks;
4118
+ this.name = "TaskMetadataParseError";
4119
+ }
4120
+ };
3888
4121
 
3889
4122
  // src/workers/dev/backgroundWorker.ts
3890
4123
  import {
@@ -4130,6 +4363,11 @@ var BackgroundWorker = class {
4130
4363
  resolved = true;
4131
4364
  reject(new UncaughtExceptionError(message.payload.error, message.payload.origin));
4132
4365
  child.kill();
4366
+ } else if (message.type === "TASKS_FAILED_TO_PARSE") {
4367
+ clearTimeout(timeout);
4368
+ resolved = true;
4369
+ reject(new TaskMetadataParseError(message.payload.zodIssues, message.payload.tasks));
4370
+ child.kill();
4133
4371
  }
4134
4372
  });
4135
4373
  child.on("exit", (code) => {
@@ -4155,7 +4393,7 @@ var BackgroundWorker = class {
4155
4393
  }
4156
4394
  if (!this._taskRunProcesses.has(payload.execution.run.id)) {
4157
4395
  const taskRunProcess = new TaskRunProcess(
4158
- payload.execution.run.id,
4396
+ payload.execution,
4159
4397
  this.path,
4160
4398
  {
4161
4399
  ...this.params.env,
@@ -4265,8 +4503,8 @@ var BackgroundWorker = class {
4265
4503
  }
4266
4504
  };
4267
4505
  var TaskRunProcess = class {
4268
- constructor(runId, path6, env, metadata, worker) {
4269
- this.runId = runId;
4506
+ constructor(execution, path6, env, metadata, worker) {
4507
+ this.execution = execution;
4270
4508
  this.path = path6;
4271
4509
  this.env = env;
4272
4510
  this.metadata = metadata;
@@ -4297,8 +4535,17 @@ var TaskRunProcess = class {
4297
4535
  await this.cleanup(true);
4298
4536
  }
4299
4537
  async initialize() {
4300
- logger.debug(`[${this.runId}] initializing task run process`, {
4301
- env: this.env,
4538
+ const fullEnv = {
4539
+ ...this.execution.run.isTest ? { TRIGGER_LOG_LEVEL: "debug" } : {},
4540
+ ...this.env,
4541
+ OTEL_RESOURCE_ATTRIBUTES: JSON.stringify({
4542
+ [SemanticInternalAttributes.PROJECT_DIR]: this.worker.projectConfig.projectDir
4543
+ }),
4544
+ OTEL_EXPORTER_OTLP_COMPRESSION: "none",
4545
+ ...this.worker.debugOtel ? { OTEL_LOG_LEVEL: "debug" } : {}
4546
+ };
4547
+ logger.debug(`[${this.execution.run.id}] initializing task run process`, {
4548
+ env: fullEnv,
4302
4549
  path: this.path
4303
4550
  });
4304
4551
  this._child = fork(this.path, {
@@ -4312,14 +4559,7 @@ var TaskRunProcess = class {
4312
4559
  "ipc"
4313
4560
  ],
4314
4561
  cwd: dirname2(this.path),
4315
- env: {
4316
- ...this.env,
4317
- OTEL_RESOURCE_ATTRIBUTES: JSON.stringify({
4318
- [SemanticInternalAttributes.PROJECT_DIR]: this.worker.projectConfig.projectDir
4319
- }),
4320
- OTEL_EXPORTER_OTLP_COMPRESSION: "none",
4321
- ...this.worker.debugOtel ? { OTEL_LOG_LEVEL: "debug" } : {}
4322
- },
4562
+ env: fullEnv,
4323
4563
  execArgv: this.worker.debuggerOn ? ["--inspect-brk", "--trace-uncaught", "--no-warnings=ExperimentalWarning"] : ["--trace-uncaught", "--no-warnings=ExperimentalWarning"]
4324
4564
  });
4325
4565
  this._child.on("message", this.#handleMessage.bind(this));
@@ -4331,7 +4571,7 @@ var TaskRunProcess = class {
4331
4571
  if (kill && this._isBeingKilled) {
4332
4572
  return;
4333
4573
  }
4334
- logger.debug(`[${this.runId}] cleaning up task run process`, { kill });
4574
+ logger.debug(`[${this.execution.run.id}] cleaning up task run process`, { kill });
4335
4575
  await this._sender.send("CLEANUP", {
4336
4576
  flush: true,
4337
4577
  kill
@@ -4362,10 +4602,13 @@ var TaskRunProcess = class {
4362
4602
  if (!completion.ok && typeof completion.retry !== "undefined") {
4363
4603
  return;
4364
4604
  }
4365
- if (execution.run.id === this.runId) {
4605
+ if (execution.run.id === this.execution.run.id) {
4366
4606
  return;
4367
4607
  }
4368
- logger.debug(`[${this.runId}] task run completed notification`, { completion, execution });
4608
+ logger.debug(`[${this.execution.run.id}] task run completed notification`, {
4609
+ completion,
4610
+ execution
4611
+ });
4369
4612
  this._sender.send("TASK_RUN_COMPLETED_NOTIFICATION", {
4370
4613
  completion,
4371
4614
  execution
@@ -4403,7 +4646,7 @@ var TaskRunProcess = class {
4403
4646
  }
4404
4647
  }
4405
4648
  async #handleExit(code) {
4406
- logger.debug(`[${this.runId}] task run process exiting`, { code });
4649
+ logger.debug(`[${this.execution.run.id}] task run process exiting`, { code });
4407
4650
  for (const [id, status] of this._attemptStatuses.entries()) {
4408
4651
  if (status === "PENDING") {
4409
4652
  this._attemptStatuses.set(id, "REJECTED");
@@ -4450,6 +4693,25 @@ var TaskRunProcess = class {
4450
4693
  }
4451
4694
  };
4452
4695
 
4696
+ // src/utilities/runtimeCheck.ts
4697
+ function runtimeCheck(minimumMajor, minimumMinor) {
4698
+ if (typeof process === "undefined") {
4699
+ throw "The dev CLI can only be run in a Node.js compatible environment";
4700
+ }
4701
+ const [major = 0, minor = 0] = process.versions.node.split(".").map(Number);
4702
+ const isBun = typeof process.versions.bun === "string";
4703
+ if (major < minimumMajor || major === minimumMajor && minor < minimumMinor) {
4704
+ if (isBun) {
4705
+ throw `The dev CLI requires at least Node.js ${minimumMajor}.${minimumMinor}. You are running Bun ${process.versions.bun}, which is compatible with Node.js ${process.versions.node}`;
4706
+ } else {
4707
+ throw `The dev CLI requires at least Node.js ${minimumMajor}.${minimumMinor}. You are running Node.js ${process.versions.node}`;
4708
+ }
4709
+ }
4710
+ logger.debug(
4711
+ `Node.js version: ${process.versions.node}${isBun ? ` (Bun ${process.versions.bun})` : ""}`
4712
+ );
4713
+ }
4714
+
4453
4715
  // src/commands/dev.tsx
4454
4716
  var apiClient;
4455
4717
  var DevCommandOptions = CommonCommandOptions.extend({
@@ -4460,7 +4722,7 @@ var DevCommandOptions = CommonCommandOptions.extend({
4460
4722
  });
4461
4723
  function configureDevCommand(program2) {
4462
4724
  return commonOptions(
4463
- program2.command("dev").description("Run your Trigger.dev tasks locally").argument("[path]", "The path to the project", ".").option("-c, --config <config file>", "The name of the config file, found at [path]").option(
4725
+ program2.command("dev").description("Run your Trigger.dev tasks locally").argument("[path]", "The path to the project", ".").option("-c, --config <config file>", "The name of the config file, found at [path].").option(
4464
4726
  "-p, --project-ref <project ref>",
4465
4727
  "The project ref. Required if there is no config file."
4466
4728
  ).option("--debugger", "Enable the debugger").option("--debug-otel", "Enable OpenTelemetry debugging")
@@ -4470,7 +4732,16 @@ function configureDevCommand(program2) {
4470
4732
  });
4471
4733
  });
4472
4734
  }
4735
+ var MINIMUM_NODE_MAJOR = 18;
4736
+ var MINIMUM_NODE_MINOR = 16;
4473
4737
  async function devCommand(dir, options) {
4738
+ try {
4739
+ runtimeCheck(MINIMUM_NODE_MAJOR, MINIMUM_NODE_MINOR);
4740
+ } catch (e) {
4741
+ logger.log(`${chalkError("X Error:")} ${e}`);
4742
+ process.exitCode = 1;
4743
+ return;
4744
+ }
4474
4745
  const authorization = await isLoggedIn(options.profile);
4475
4746
  if (!authorization.ok) {
4476
4747
  if (authorization.error === "fetch failed") {
@@ -4830,17 +5101,52 @@ function useDev({
4830
5101
  backgroundWorker
4831
5102
  );
4832
5103
  } catch (e) {
4833
- if (e instanceof UncaughtExceptionError) {
5104
+ if (e instanceof TaskMetadataParseError) {
5105
+ logTaskMetadataParseError(e.zodIssues, e.tasks);
5106
+ return;
5107
+ } else if (e instanceof UncaughtExceptionError) {
5108
+ const parsedBuildError = parseBuildErrorStack(e.originalError);
5109
+ if (typeof parsedBuildError !== "string") {
5110
+ logESMRequireError(
5111
+ parsedBuildError,
5112
+ configPath ? { status: "file", path: configPath, config } : { status: "in-memory", config }
5113
+ );
5114
+ return;
5115
+ } else {
5116
+ }
4834
5117
  if (e.originalError.stack) {
4835
- logger.error("Background worker failed to start", e.originalError.stack);
5118
+ logger.log(
5119
+ `${chalkError("X Error:")} Worker failed to start`,
5120
+ e.originalError.stack
5121
+ );
4836
5122
  }
4837
5123
  return;
4838
5124
  }
4839
- if (e instanceof Error) {
4840
- logger.error(`Background worker failed to start`, e.stack);
4841
- return;
5125
+ const parsedError = parseNpmInstallError(e);
5126
+ if (typeof parsedError === "string") {
5127
+ logger.log(`${chalkError("X Error:")} ${parsedError}`);
5128
+ } else {
5129
+ switch (parsedError.type) {
5130
+ case "package-not-found-error": {
5131
+ logger.log(
5132
+ `
5133
+ ${chalkError("X Error:")} The package ${chalkPurple(
5134
+ parsedError.packageName
5135
+ )} could not be found in the npm registry.`
5136
+ );
5137
+ break;
5138
+ }
5139
+ case "no-matching-version-error": {
5140
+ logger.log(
5141
+ `
5142
+ ${chalkError("X Error:")} The package ${chalkPurple(
5143
+ parsedError.packageName
5144
+ )} could not resolve because the version doesn't exist`
5145
+ );
5146
+ break;
5147
+ }
5148
+ }
4842
5149
  }
4843
- logger.error(`Background worker failed to start: ${e}`);
4844
5150
  }
4845
5151
  });
4846
5152
  }
@@ -4983,11 +5289,11 @@ import {
4983
5289
  flattenAttributes as flattenAttributes3,
4984
5290
  recordSpanException as recordSpanException5
4985
5291
  } from "@trigger.dev/core/v3";
4986
- import chalk5 from "chalk";
5292
+ import chalk6 from "chalk";
4987
5293
  import { execa as execa3 } from "execa";
4988
5294
  import { applyEdits, modify } from "jsonc-parser";
4989
5295
  import { writeFile as writeFile3 } from "node:fs/promises";
4990
- import { join as join6, relative as relative3, resolve as resolve3 } from "node:path";
5296
+ import { join as join6, relative as relative4, resolve as resolve3 } from "node:path";
4991
5297
  import terminalLink3 from "terminal-link";
4992
5298
  import { z as z6 } from "zod";
4993
5299
 
@@ -5166,7 +5472,7 @@ async function _initCommand(dir, options) {
5166
5472
  log3.success("Successfully initialized project for Trigger.dev v3 \u{1FAE1}");
5167
5473
  log3.info("Next steps:");
5168
5474
  log3.info(
5169
- ` 1. To start developing, run ${chalk5.green(
5475
+ ` 1. To start developing, run ${chalk6.green(
5170
5476
  `npx trigger.dev@${options.tag} dev`
5171
5477
  )} in your project directory`
5172
5478
  );
@@ -5181,7 +5487,7 @@ async function _initCommand(dir, options) {
5181
5487
  ` 4. Need help? Join our ${terminalLink3(
5182
5488
  "Discord community",
5183
5489
  "https://trigger.dev/discord"
5184
- )} or email us at ${chalk5.cyan("help@trigger.dev")}`
5490
+ )} or email us at ${chalk6.cyan("help@trigger.dev")}`
5185
5491
  );
5186
5492
  outro4(`Project initialized successfully. Happy coding!`);
5187
5493
  }
@@ -5235,7 +5541,7 @@ async function createTriggerDir(dir, options) {
5235
5541
  outputPath,
5236
5542
  replacements: {}
5237
5543
  });
5238
- const relativeOutputPath = relative3(process.cwd(), outputPath);
5544
+ const relativeOutputPath = relative4(process.cwd(), outputPath);
5239
5545
  log3.step(`Created example file at ${relativeOutputPath}`);
5240
5546
  span.end();
5241
5547
  return { location, isCustomValue: location !== defaultValue };
@@ -5389,7 +5695,7 @@ async function writeConfigFile(dir, project, options, triggerDir) {
5389
5695
  outputPath,
5390
5696
  override: options.overrideConfig
5391
5697
  });
5392
- const relativePathToOutput = relative3(process.cwd(), outputPath);
5698
+ const relativePathToOutput = relative4(process.cwd(), outputPath);
5393
5699
  spnnr.stop(
5394
5700
  result.success ? `Config file created at ${relativePathToOutput}` : `Failed to create config file: ${result.error}`
5395
5701
  );
@@ -5471,12 +5777,14 @@ async function selectProject(apiClient2, dashboardUrl, projectRef) {
5471
5777
  // src/commands/logout.ts
5472
5778
  var LogoutCommandOptions = CommonCommandOptions;
5473
5779
  function configureLogoutCommand(program2) {
5474
- return commonOptions(program2.command("logout").description("Logout of Trigger.dev")).action(async (options) => {
5475
- await handleTelemetry(async () => {
5476
- await printInitialBanner(false);
5477
- await logoutCommand(options);
5478
- });
5479
- });
5780
+ return commonOptions(program2.command("logout").description("Logout of Trigger.dev")).action(
5781
+ async (options) => {
5782
+ await handleTelemetry(async () => {
5783
+ await printInitialBanner(false);
5784
+ await logoutCommand(options);
5785
+ });
5786
+ }
5787
+ );
5480
5788
  }
5481
5789
  async function logoutCommand(options) {
5482
5790
  return await wrapCommandAction("logoutCommand", LogoutCommandOptions, options, async (opts) => {
@@ -5486,11 +5794,46 @@ async function logoutCommand(options) {
5486
5794
  async function logout(options) {
5487
5795
  const config = readAuthConfigProfile(options.profile);
5488
5796
  if (!config?.accessToken) {
5489
- logger.info(`You are already logged out [${options.profile ?? "default"}]`);
5797
+ logger.info(`You are already logged out [${options.profile}]`);
5490
5798
  return;
5491
5799
  }
5492
- writeAuthConfigProfile({ ...config, accessToken: void 0, apiUrl: void 0 }, options.profile);
5493
- logger.info(`Logged out of Trigger.dev [${options.profile ?? "default"}]`);
5800
+ deleteAuthConfigProfile(options.profile);
5801
+ logger.info(`Logged out of Trigger.dev [${options.profile}]`);
5802
+ }
5803
+
5804
+ // src/commands/list-profiles.ts
5805
+ import { log as log4, outro as outro5 } from "@clack/prompts";
5806
+ var ListProfilesOptions = CommonCommandOptions;
5807
+ function configureListProfilesCommand(program2) {
5808
+ return program2.command("list-profiles").description("List all of your CLI profiles").option(
5809
+ "-l, --log-level <level>",
5810
+ "The CLI log level to use (debug, info, log, warn, error, none). This does not effect the log level of your trigger.dev tasks.",
5811
+ "log"
5812
+ ).option("--skip-telemetry", "Opt-out of sending telemetry").action(async (options) => {
5813
+ await handleTelemetry(async () => {
5814
+ await printInitialBanner(true);
5815
+ await listProfilesCommand(options);
5816
+ });
5817
+ });
5818
+ }
5819
+ async function listProfilesCommand(options) {
5820
+ return await wrapCommandAction("listProfiles", ListProfilesOptions, options, async (opts) => {
5821
+ return await listProfiles(opts);
5822
+ });
5823
+ }
5824
+ async function listProfiles(options) {
5825
+ const authConfig = readAuthConfigFile();
5826
+ if (!authConfig) {
5827
+ logger.info("No profiles found");
5828
+ return;
5829
+ }
5830
+ const profiles = Object.keys(authConfig);
5831
+ log4.message("Profiles:");
5832
+ for (const profile of profiles) {
5833
+ const profileConfig = authConfig[profile];
5834
+ log4.info(`${profile}${profileConfig?.apiUrl ? ` - ${chalkGrey(profileConfig.apiUrl)}` : ""}`);
5835
+ }
5836
+ outro5("Retrieve account info by running whoami --profile <profile>");
5494
5837
  }
5495
5838
 
5496
5839
  // src/cli/index.ts
@@ -5502,6 +5845,7 @@ configureDevCommand(program);
5502
5845
  configureDeployCommand(program);
5503
5846
  configureWhoamiCommand(program);
5504
5847
  configureLogoutCommand(program);
5848
+ configureListProfilesCommand(program);
5505
5849
 
5506
5850
  // src/index.ts
5507
5851
  var main = async () => {