trigger.dev 3.0.0-beta.1 → 3.0.0-beta.10

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 join5, 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.1";
804
+ var version = "3.0.0-beta.10";
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.0",
820
+ "@trigger.dev/core": "workspace:^3.0.0-beta.7",
820
821
  "@types/degit": "^2.8.3",
821
822
  chalk: "^5.2.0",
822
823
  chokidar: "^3.5.3",
@@ -833,7 +834,6 @@ var dependencies = {
833
834
  "import-meta-resolve": "^4.0.0",
834
835
  ink: "^4.4.1",
835
836
  "jsonc-parser": "^3.2.1",
836
- jsonlines: "^0.1.1",
837
837
  liquidjs: "^10.9.2",
838
838
  "mock-fs": "^5.2.0",
839
839
  nanoid: "^4.0.2",
@@ -850,7 +850,6 @@ var dependencies = {
850
850
  "simple-git": "^3.19.0",
851
851
  "socket.io-client": "^4.7.4",
852
852
  "source-map-support": "^0.5.21",
853
- "supports-color": "^9.4.0",
854
853
  "terminal-link": "^3.0.0",
855
854
  "tiny-invariant": "^1.2.0",
856
855
  "tsconfig-paths": "^4.2.0",
@@ -894,13 +893,12 @@ var package_default = {
894
893
  type: "module",
895
894
  exports: "./dist/index.js",
896
895
  bin: {
897
- "trigger.dev": "./dist/index.js"
896
+ triggerdev: "./dist/index.js"
898
897
  },
899
898
  devDependencies: {
900
899
  "@trigger.dev/core-apps": "workspace:*",
901
900
  "@trigger.dev/tsconfig": "workspace:*",
902
901
  "@types/gradient-string": "^1.1.2",
903
- "@types/jsonlines": "^0.1.5",
904
902
  "@types/mock-fs": "^4.13.1",
905
903
  "@types/node": "18",
906
904
  "@types/object-hash": "^3.0.6",
@@ -1307,7 +1305,7 @@ var Logger = class {
1307
1305
  const kind = LOGGER_LEVEL_FORMAT_TYPE_MAP[level];
1308
1306
  if (kind) {
1309
1307
  const [firstLine, ...otherLines] = message.split("\n");
1310
- const notes = otherLines.length > 0 ? otherLines.map((text2) => ({ text: text2 })) : void 0;
1308
+ const notes = otherLines.length > 0 ? otherLines.map((text3) => ({ text: text3 })) : void 0;
1311
1309
  return formatMessagesSync([{ text: firstLine, notes }], {
1312
1310
  color: true,
1313
1311
  kind,
@@ -1322,6 +1320,58 @@ var logger = new Logger();
1322
1320
 
1323
1321
  // src/cli/common.ts
1324
1322
  import { outro } from "@clack/prompts";
1323
+
1324
+ // src/utilities/cliOutput.ts
1325
+ import chalk2 from "chalk";
1326
+ var green = "#4FFF54";
1327
+ var purple = "#735BF3";
1328
+ function chalkGreen(text3) {
1329
+ return chalk2.hex(green)(text3);
1330
+ }
1331
+ function chalkPurple(text3) {
1332
+ return chalk2.hex(purple)(text3);
1333
+ }
1334
+ function chalkGrey(text3) {
1335
+ return chalk2.hex("#878C99")(text3);
1336
+ }
1337
+ function chalkError(text3) {
1338
+ return chalk2.hex("#E11D48")(text3);
1339
+ }
1340
+ function chalkWarning(text3) {
1341
+ return chalk2.yellow(text3);
1342
+ }
1343
+ function chalkSuccess(text3) {
1344
+ return chalk2.hex("#28BF5C")(text3);
1345
+ }
1346
+ function chalkLink(text3) {
1347
+ return chalk2.underline.hex("#D7D9DD")(text3);
1348
+ }
1349
+ function chalkWorker(text3) {
1350
+ return chalk2.hex("#FFFF89")(text3);
1351
+ }
1352
+ function chalkTask(text3) {
1353
+ return chalk2.hex("#60A5FA")(text3);
1354
+ }
1355
+ function chalkRun(text3) {
1356
+ return chalk2.hex("#A78BFA")(text3);
1357
+ }
1358
+ function logo() {
1359
+ return `${chalk2.hex(green).bold("Trigger")}${chalk2.hex(purple).bold(".dev")}`;
1360
+ }
1361
+ function prettyPrintDate(date = /* @__PURE__ */ new Date()) {
1362
+ let formattedDate = new Intl.DateTimeFormat("en-US", {
1363
+ month: "short",
1364
+ day: "2-digit",
1365
+ hour: "2-digit",
1366
+ minute: "2-digit",
1367
+ second: "2-digit",
1368
+ hour12: false
1369
+ }).format(date);
1370
+ formattedDate += "." + ("00" + date.getMilliseconds()).slice(-3);
1371
+ return formattedDate;
1372
+ }
1373
+
1374
+ // src/cli/common.ts
1325
1375
  var CommonCommandOptions = z.object({
1326
1376
  apiUrl: z.string().optional(),
1327
1377
  logLevel: z.enum(["debug", "info", "log", "warn", "error", "none"]).default("log"),
@@ -1331,7 +1381,7 @@ var CommonCommandOptions = z.object({
1331
1381
  function commonOptions(command) {
1332
1382
  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
1383
  "-l, --log-level <level>",
1334
- "The log level to use (debug, info, log, warn, error, none)",
1384
+ "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
1385
  "log"
1336
1386
  ).option("--skip-telemetry", "Opt-out of sending telemetry");
1337
1387
  }
@@ -1377,7 +1427,7 @@ async function wrapCommandAction(name, schema, options, action) {
1377
1427
  } else if (e instanceof SkipCommandError) {
1378
1428
  } else {
1379
1429
  recordSpanException(span, e);
1380
- logger.error(e instanceof Error ? e.message : String(e));
1430
+ logger.log(`${chalkError("X Error:")} ${e instanceof Error ? e.message : String(e)}`);
1381
1431
  }
1382
1432
  span.end();
1383
1433
  throw e;
@@ -1535,6 +1585,11 @@ function readAuthConfigProfile(profile = "default") {
1535
1585
  return void 0;
1536
1586
  }
1537
1587
  }
1588
+ function deleteAuthConfigProfile(profile = "default") {
1589
+ const existingConfig = readAuthConfigFile() || {};
1590
+ delete existingConfig[profile];
1591
+ writeAuthConfigFile(existingConfig);
1592
+ }
1538
1593
  function readAuthConfigFile() {
1539
1594
  try {
1540
1595
  const authConfigFilePath = getAuthConfigFilePath();
@@ -1636,56 +1691,8 @@ async function normalizeConfig(config) {
1636
1691
  // src/utilities/initialBanner.ts
1637
1692
  import { spinner } from "@clack/prompts";
1638
1693
  import chalk3 from "chalk";
1639
- import supportsColor from "supports-color";
1640
1694
  import checkForUpdate from "update-check";
1641
1695
 
1642
- // src/utilities/cliOutput.ts
1643
- import chalk2 from "chalk";
1644
- var green = "#4FFF54";
1645
- var purple = "#735BF3";
1646
- function chalkPurple(text2) {
1647
- return chalk2.hex(purple)(text2);
1648
- }
1649
- function chalkGrey(text2) {
1650
- return chalk2.hex("#878C99")(text2);
1651
- }
1652
- function chalkError(text2) {
1653
- return chalk2.hex("#E11D48")(text2);
1654
- }
1655
- function chalkWarning(text2) {
1656
- return chalk2.yellow(text2);
1657
- }
1658
- function chalkSuccess(text2) {
1659
- return chalk2.hex("#28BF5C")(text2);
1660
- }
1661
- function chalkLink(text2) {
1662
- return chalk2.underline.hex("#D7D9DD")(text2);
1663
- }
1664
- function chalkWorker(text2) {
1665
- return chalk2.hex("#FFFF89")(text2);
1666
- }
1667
- function chalkTask(text2) {
1668
- return chalk2.hex("#60A5FA")(text2);
1669
- }
1670
- function chalkRun(text2) {
1671
- return chalk2.hex("#A78BFA")(text2);
1672
- }
1673
- function logo() {
1674
- return `${chalk2.hex(green).bold("Trigger")}${chalk2.hex(purple).bold(".dev")}`;
1675
- }
1676
- function prettyPrintDate(date = /* @__PURE__ */ new Date()) {
1677
- let formattedDate = new Intl.DateTimeFormat("en-US", {
1678
- month: "short",
1679
- day: "2-digit",
1680
- hour: "2-digit",
1681
- minute: "2-digit",
1682
- second: "2-digit",
1683
- hour12: false
1684
- }).format(date);
1685
- formattedDate += "." + ("00" + date.getMilliseconds()).slice(-3);
1686
- return formattedDate;
1687
- }
1688
-
1689
1696
  // src/utilities/getVersion.ts
1690
1697
  import path3 from "path";
1691
1698
  function getVersion() {
@@ -1697,10 +1704,10 @@ function getVersion() {
1697
1704
  // src/utilities/initialBanner.ts
1698
1705
  async function printInitialBanner(performUpdateCheck = true) {
1699
1706
  const packageVersion = getVersion();
1700
- const text2 = `
1707
+ const text3 = `
1701
1708
  ${logo()} ${chalkGrey(`(${packageVersion})`)}
1702
1709
  `;
1703
- logger.info(text2);
1710
+ logger.info(text3);
1704
1711
  let maybeNewVersion;
1705
1712
  if (performUpdateCheck) {
1706
1713
  const loadingSpinner = spinner();
@@ -1724,19 +1731,19 @@ After installation, run Trigger.dev with \`npx trigger.dev\`.`
1724
1731
  }
1725
1732
  async function printStandloneInitialBanner(performUpdateCheck = true) {
1726
1733
  const packageVersion = getVersion();
1727
- let text2 = `
1734
+ let text3 = `
1728
1735
  ${logo()} ${chalkGrey("(v3 Developer Preview)")}`;
1729
1736
  if (performUpdateCheck) {
1730
1737
  const maybeNewVersion = await updateCheck();
1731
1738
  if (maybeNewVersion !== void 0) {
1732
- text2 = `${text2} (update available ${chalk3.green(maybeNewVersion)})`;
1739
+ text3 = `${text3} (update available ${chalk3.green(maybeNewVersion)})`;
1733
1740
  }
1734
1741
  }
1735
- logger.log(text2 + "\n" + (supportsColor.stdout ? chalkGrey("-".repeat(54)) : "-".repeat(54)));
1742
+ logger.log(text3 + "\n" + chalkGrey("-".repeat(54)));
1736
1743
  }
1737
1744
  function printDevBanner() {
1738
1745
  logger.log(
1739
- `${chalkGrey("Key:")} ${chalkWorker("Worker")} ${chalkGrey("|")} ${chalkTask(
1746
+ `${chalkGrey("Key:")} ${chalkWorker("Version")} ${chalkGrey("|")} ${chalkTask(
1740
1747
  "Task"
1741
1748
  )} ${chalkGrey("|")} ${chalkRun("Run")}`
1742
1749
  );
@@ -1764,20 +1771,14 @@ async function installPackages(packages, options) {
1764
1771
  const cwd = options?.cwd ?? process.cwd();
1765
1772
  logger.debug("Installing packages", { packages });
1766
1773
  await setPackageJsonDeps(join3(cwd, "package.json"), packages);
1767
- const childProcess2 = execa(
1774
+ await execa(
1768
1775
  "npm",
1769
1776
  ["install", "--install-strategy", "nested", "--ignore-scripts", "--no-audit", "--no-fund"],
1770
1777
  {
1771
1778
  cwd,
1772
- stderr: "inherit"
1779
+ stderr: "pipe"
1773
1780
  }
1774
1781
  );
1775
- await new Promise((res, rej) => {
1776
- childProcess2.on("error", (e) => rej(e));
1777
- childProcess2.on("close", () => res());
1778
- });
1779
- await childProcess2;
1780
- return;
1781
1782
  }
1782
1783
  function detectPackageNameFromImportPath(path6) {
1783
1784
  if (path6.startsWith("@")) {
@@ -2521,6 +2522,29 @@ async function login(options) {
2521
2522
  if (!opts.embedded) {
2522
2523
  intro2("Logging in to Trigger.dev");
2523
2524
  }
2525
+ const accessTokenFromEnv = process.env.TRIGGER_ACCESS_TOKEN;
2526
+ if (accessTokenFromEnv) {
2527
+ const auth = {
2528
+ accessToken: accessTokenFromEnv,
2529
+ apiUrl: process.env.TRIGGER_API_URL ?? "https://api.trigger.dev"
2530
+ };
2531
+ const apiClient3 = new CliApiClient(auth.apiUrl, auth.accessToken);
2532
+ const userData = await apiClient3.whoAmI();
2533
+ if (!userData.success) {
2534
+ throw new Error(userData.error);
2535
+ }
2536
+ return {
2537
+ ok: true,
2538
+ profile: options?.profile ?? "default",
2539
+ userId: userData.data.userId,
2540
+ email: userData.data.email,
2541
+ dashboardUrl: userData.data.dashboardUrl,
2542
+ auth: {
2543
+ accessToken: auth.accessToken,
2544
+ apiUrl: auth.apiUrl
2545
+ }
2546
+ };
2547
+ }
2524
2548
  const authConfig = readAuthConfigProfile(options?.profile);
2525
2549
  if (authConfig && authConfig.accessToken) {
2526
2550
  const whoAmIResult = await whoAmI(
@@ -2721,10 +2745,45 @@ ${authorizationCodeResult.error}`
2721
2745
  });
2722
2746
  }
2723
2747
 
2748
+ // src/commands/deploy.ts
2749
+ import { Glob } from "glob";
2750
+
2724
2751
  // src/utilities/build.ts
2752
+ import { readFileSync } from "node:fs";
2725
2753
  import { extname, isAbsolute } from "node:path";
2726
2754
  import tsConfigPaths from "tsconfig-paths";
2727
- import { readFileSync } from "node:fs";
2755
+ function bundleTriggerDevCore(buildIdentifier, tsconfigPath) {
2756
+ return {
2757
+ name: "trigger-bundle-core",
2758
+ setup(build3) {
2759
+ build3.onResolve({ filter: /.*/ }, (args) => {
2760
+ if (args.path !== "@trigger.dev/core/v3") {
2761
+ return void 0;
2762
+ }
2763
+ const triggerSdkPath = __require.resolve("@trigger.dev/sdk/v3", { paths: [process.cwd()] });
2764
+ logger.debug(`[${buildIdentifier}][trigger-bundle-core] Resolved @trigger.dev/sdk/v3`, {
2765
+ ...args,
2766
+ triggerSdkPath
2767
+ });
2768
+ const resolvedPath = __require.resolve("@trigger.dev/core/v3", {
2769
+ paths: [triggerSdkPath]
2770
+ });
2771
+ logger.debug(
2772
+ `[${buildIdentifier}][trigger-bundle-core] Externalizing @trigger.dev/core/v3`,
2773
+ {
2774
+ ...args,
2775
+ triggerSdkPath,
2776
+ resolvedPath
2777
+ }
2778
+ );
2779
+ return {
2780
+ path: resolvedPath,
2781
+ external: false
2782
+ };
2783
+ });
2784
+ }
2785
+ };
2786
+ }
2728
2787
  function workerSetupImportConfigPlugin(configPath) {
2729
2788
  return {
2730
2789
  name: "trigger-worker-setup",
@@ -2751,8 +2810,8 @@ function workerSetupImportConfigPlugin(configPath) {
2751
2810
  }
2752
2811
  };
2753
2812
  }
2754
- function bundleDependenciesPlugin(config) {
2755
- const matchPath = config.tsconfigPath ? createMatchPath(config.tsconfigPath) : void 0;
2813
+ function bundleDependenciesPlugin(buildIdentifier, dependenciesToBundle, tsconfigPath) {
2814
+ const matchPath = tsconfigPath ? createMatchPath(tsconfigPath) : void 0;
2756
2815
  function resolvePath(id) {
2757
2816
  if (!matchPath) {
2758
2817
  return id;
@@ -2764,26 +2823,7 @@ function bundleDependenciesPlugin(config) {
2764
2823
  setup(build3) {
2765
2824
  build3.onResolve({ filter: /.*/ }, (args) => {
2766
2825
  const resolvedPath = resolvePath(args.path);
2767
- logger.ignore(`Checking if ${args.path} should be bundled or external`, {
2768
- ...args,
2769
- resolvedPath
2770
- });
2771
2826
  if (!isBareModuleId(resolvedPath)) {
2772
- logger.ignore(`Bundling ${args.path} because its not a bareModuleId`, {
2773
- ...args
2774
- });
2775
- return void 0;
2776
- }
2777
- if (args.path.startsWith("@trigger.dev/")) {
2778
- logger.ignore(`Bundling ${args.path} because its a trigger.dev package`, {
2779
- ...args
2780
- });
2781
- return void 0;
2782
- }
2783
- if (args.path === "superjson" || args.path === "copy-anything" || args.path === "is-what") {
2784
- logger.debug(`Bundling ${args.path} because its superjson/copy-anything/is-what`, {
2785
- ...args
2786
- });
2787
2827
  return void 0;
2788
2828
  }
2789
2829
  let loader;
@@ -2797,12 +2837,12 @@ function bundleDependenciesPlugin(config) {
2797
2837
  if (loader === "file") {
2798
2838
  return void 0;
2799
2839
  }
2800
- for (let pattern of config.dependenciesToBundle ?? []) {
2840
+ for (let pattern of dependenciesToBundle ?? []) {
2801
2841
  if (typeof pattern === "string" ? args.path === pattern : pattern.test(args.path)) {
2802
2842
  return void 0;
2803
2843
  }
2804
2844
  }
2805
- logger.ignore(`Externalizing ${args.path}`, {
2845
+ logger.ignore(`[${buildIdentifier}] Externalizing ${args.path}`, {
2806
2846
  ...args
2807
2847
  });
2808
2848
  return {
@@ -2890,8 +2930,347 @@ function getLoaderForFile(file) {
2890
2930
  throw new Error(`Cannot get loader for file ${file}`);
2891
2931
  }
2892
2932
 
2933
+ // src/utilities/deployErrors.ts
2934
+ import chalk4 from "chalk";
2935
+ import { relative as relative2 } from "node:path";
2936
+ import { groupTaskMetadataIssuesByTask } from "@trigger.dev/core/v3";
2937
+ function errorIsErrorLike(error) {
2938
+ return error instanceof Error || typeof error === "object" && error !== null && "message" in error;
2939
+ }
2940
+ function parseBuildErrorStack(error) {
2941
+ if (typeof error === "string") {
2942
+ return error;
2943
+ }
2944
+ if (errorIsErrorLike(error)) {
2945
+ if (typeof error.stack === "string") {
2946
+ const isErrRequireEsm = error.stack.includes("ERR_REQUIRE_ESM");
2947
+ let moduleName = null;
2948
+ if (isErrRequireEsm) {
2949
+ const moduleRegex = /node_modules\/(@[^\/]+\/[^\/]+|[^\/]+)\/[^\/]+\s/;
2950
+ const match = moduleRegex.exec(error.stack);
2951
+ if (match) {
2952
+ moduleName = match[1];
2953
+ return {
2954
+ type: "esm-require-error",
2955
+ moduleName
2956
+ };
2957
+ }
2958
+ }
2959
+ } else {
2960
+ return error.message;
2961
+ }
2962
+ }
2963
+ }
2964
+ function logESMRequireError(parsedError, resolvedConfig) {
2965
+ logger.log(
2966
+ `
2967
+ ${chalkError("X Error:")} The ${chalkPurple(
2968
+ parsedError.moduleName
2969
+ )} module is being required even though it's ESM only, and builds only support CommonJS. There are two ${chalk4.underline(
2970
+ "possible"
2971
+ )} ways to fix this:`
2972
+ );
2973
+ logger.log(
2974
+ `
2975
+ ${chalkGrey("\u25CB")} Dynamically import the module in your code: ${chalkGrey(
2976
+ `const myModule = await import("${parsedError.moduleName}");`
2977
+ )}`
2978
+ );
2979
+ if (resolvedConfig.status === "file") {
2980
+ const relativePath = relative2(resolvedConfig.config.projectDir, resolvedConfig.path).replace(
2981
+ /\\/g,
2982
+ "/"
2983
+ );
2984
+ logger.log(
2985
+ `${chalkGrey("\u25CB")} ${chalk4.underline("Or")} add ${chalkPurple(
2986
+ parsedError.moduleName
2987
+ )} to the ${chalkGreen("dependenciesToBundle")} array in your config file ${chalkGrey(
2988
+ `(${relativePath})`
2989
+ )}. This will bundle the module with your code.
2990
+ `
2991
+ );
2992
+ } else {
2993
+ logger.log(
2994
+ `${chalkGrey("\u25CB")} ${chalk4.underline("Or")} add ${chalkPurple(
2995
+ parsedError.moduleName
2996
+ )} to the ${chalkGreen("dependenciesToBundle")} array in your config file ${chalkGrey(
2997
+ "(you'll need to create one)"
2998
+ )}. This will bundle the module with your code.
2999
+ `
3000
+ );
3001
+ }
3002
+ }
3003
+ function parseNpmInstallError(error) {
3004
+ if (typeof error === "string") {
3005
+ return error;
3006
+ }
3007
+ if (error instanceof Error) {
3008
+ if (typeof error.stack === "string") {
3009
+ const isPackageNotFoundError = error.stack.includes("ERR! 404 Not Found") && error.stack.includes("is not in this registry");
3010
+ let packageName = null;
3011
+ if (isPackageNotFoundError) {
3012
+ const packageNameRegex = /'([^']+)' is not in this registry/;
3013
+ const match = packageNameRegex.exec(error.stack);
3014
+ if (match) {
3015
+ packageName = match[1];
3016
+ }
3017
+ }
3018
+ if (packageName) {
3019
+ return {
3020
+ type: "package-not-found-error",
3021
+ packageName
3022
+ };
3023
+ }
3024
+ const noMatchingVersionRegex = /No matching version found for ([^\s]+)\s/;
3025
+ const noMatchingVersionMatch = noMatchingVersionRegex.exec(error.stack);
3026
+ if (noMatchingVersionMatch) {
3027
+ return {
3028
+ type: "no-matching-version-error",
3029
+ packageName: noMatchingVersionMatch[1].replace(/.$/, "")
3030
+ };
3031
+ }
3032
+ return error.message;
3033
+ } else {
3034
+ return error.message;
3035
+ }
3036
+ }
3037
+ return "Unknown error";
3038
+ }
3039
+ function logTaskMetadataParseError(zodIssues, tasks) {
3040
+ logger.log(
3041
+ `
3042
+ ${chalkError("X Error:")} Failed to start. The following ${zodIssues.length === 1 ? "task issue was" : "task issues were"} found:`
3043
+ );
3044
+ const groupedIssues = groupTaskMetadataIssuesByTask(tasks, zodIssues);
3045
+ for (const key in groupedIssues) {
3046
+ const taskWithIssues = groupedIssues[key];
3047
+ if (!taskWithIssues) {
3048
+ continue;
3049
+ }
3050
+ logger.log(
3051
+ `
3052
+ ${chalkWarning("\u276F")} ${taskWithIssues.exportName} ${chalkGrey("in")} ${taskWithIssues.filePath}`
3053
+ );
3054
+ for (const issue of taskWithIssues.issues) {
3055
+ if (issue.path) {
3056
+ logger.log(` ${chalkError("x")} ${issue.path} ${chalkGrey(issue.message)}`);
3057
+ } else {
3058
+ logger.log(` ${chalkError("x")} ${chalkGrey(issue.message)}`);
3059
+ }
3060
+ }
3061
+ }
3062
+ }
3063
+
3064
+ // src/utilities/safeJsonParse.ts
3065
+ function safeJsonParse(json) {
3066
+ if (!json) {
3067
+ return void 0;
3068
+ }
3069
+ try {
3070
+ return JSON.parse(json);
3071
+ } catch {
3072
+ return void 0;
3073
+ }
3074
+ }
3075
+
3076
+ // src/utilities/javascriptProject.ts
3077
+ import { $ } from "execa";
3078
+ import { join as join4 } from "node:path";
3079
+
3080
+ // src/utilities/getUserPackageManager.ts
3081
+ import { findUp as findUp2 } from "find-up";
3082
+ async function getUserPackageManager(path6) {
3083
+ try {
3084
+ return await detectPackageManagerFromArtifacts(path6);
3085
+ } catch (error) {
3086
+ return detectPackageManagerFromCurrentCommand();
3087
+ }
3088
+ }
3089
+ function detectPackageManagerFromCurrentCommand() {
3090
+ const userAgent = process.env.npm_config_user_agent;
3091
+ if (userAgent) {
3092
+ if (userAgent.startsWith("yarn")) {
3093
+ return "yarn";
3094
+ } else if (userAgent.startsWith("pnpm")) {
3095
+ return "pnpm";
3096
+ } else {
3097
+ return "npm";
3098
+ }
3099
+ } else {
3100
+ return "npm";
3101
+ }
3102
+ }
3103
+ async function detectPackageManagerFromArtifacts(path6) {
3104
+ const packageFiles = [
3105
+ { name: "yarn.lock", pm: "yarn" },
3106
+ { name: "pnpm-lock.yaml", pm: "pnpm" },
3107
+ { name: "package-lock.json", pm: "npm" },
3108
+ { name: "npm-shrinkwrap.json", pm: "npm" }
3109
+ ];
3110
+ for (const { name, pm } of packageFiles) {
3111
+ const foundPath = await findUp2(name, { cwd: path6 });
3112
+ if (typeof foundPath === "string") {
3113
+ return pm;
3114
+ }
3115
+ }
3116
+ throw new Error("Could not detect package manager from artifacts");
3117
+ }
3118
+
3119
+ // src/utilities/javascriptProject.ts
3120
+ var BuiltInModules = /* @__PURE__ */ new Set([
3121
+ "assert",
3122
+ "async_hooks",
3123
+ "buffer",
3124
+ "child_process",
3125
+ "cluster",
3126
+ "console",
3127
+ "constants",
3128
+ "crypto",
3129
+ "dgram",
3130
+ "dns",
3131
+ "domain",
3132
+ "events",
3133
+ "fs",
3134
+ "http",
3135
+ "http2",
3136
+ "https",
3137
+ "inspector",
3138
+ "module",
3139
+ "net",
3140
+ "os",
3141
+ "path",
3142
+ "perf_hooks",
3143
+ "process",
3144
+ "punycode",
3145
+ "querystring",
3146
+ "readline",
3147
+ "repl",
3148
+ "stream",
3149
+ "string_decoder",
3150
+ "timers",
3151
+ "tls",
3152
+ "trace_events",
3153
+ "tty",
3154
+ "url",
3155
+ "util",
3156
+ "v8",
3157
+ "vm",
3158
+ "worker_threads",
3159
+ "zlib"
3160
+ ]);
3161
+ var JavascriptProject = class {
3162
+ constructor(projectPath) {
3163
+ this.projectPath = projectPath;
3164
+ }
3165
+ _packageJson;
3166
+ _packageManager;
3167
+ get packageJson() {
3168
+ if (!this._packageJson) {
3169
+ this._packageJson = readJSONFileSync(join4(this.projectPath, "package.json"));
3170
+ }
3171
+ return this._packageJson;
3172
+ }
3173
+ get scripts() {
3174
+ return {
3175
+ postinstall: this.packageJson.scripts?.postinstall
3176
+ };
3177
+ }
3178
+ async resolve(packageName, options) {
3179
+ if (BuiltInModules.has(packageName)) {
3180
+ return void 0;
3181
+ }
3182
+ if (!this._packageManager) {
3183
+ this._packageManager = await getUserPackageManager(this.projectPath);
3184
+ }
3185
+ const packageManager = this._packageManager;
3186
+ const opts = { allowDev: false, ...options };
3187
+ const packageJsonVersion = this.packageJson.dependencies?.[packageName];
3188
+ if (typeof packageJsonVersion === "string") {
3189
+ return packageJsonVersion;
3190
+ }
3191
+ if (opts.allowDev) {
3192
+ const devPackageJsonVersion = this.packageJson.devDependencies?.[packageName];
3193
+ if (typeof devPackageJsonVersion === "string") {
3194
+ return devPackageJsonVersion;
3195
+ }
3196
+ }
3197
+ const command = packageManager === "npm" ? new NPMCommands() : packageManager === "pnpm" ? new PNPMCommands() : new YarnCommands();
3198
+ try {
3199
+ const version2 = await command.resolveDependencyVersion(packageName, {
3200
+ cwd: this.projectPath
3201
+ });
3202
+ if (version2) {
3203
+ return version2;
3204
+ }
3205
+ } catch (error) {
3206
+ logger.debug(`Failed to resolve dependency version using ${command.name}`, {
3207
+ packageName,
3208
+ error
3209
+ });
3210
+ }
3211
+ }
3212
+ };
3213
+ var PNPMCommands = class {
3214
+ get name() {
3215
+ return "pnpm";
3216
+ }
3217
+ async resolveDependencyVersion(packageName, options) {
3218
+ const cmd = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
3219
+ const { stdout } = await $({ cwd: options.cwd })`${cmd} list ${packageName} -r --json`;
3220
+ const result = JSON.parse(stdout);
3221
+ logger.debug(`Resolving ${packageName} version using pnpm`, { result });
3222
+ for (const dep of result) {
3223
+ const dependency = dep.dependencies?.[packageName];
3224
+ if (dependency) {
3225
+ return dependency.version;
3226
+ }
3227
+ }
3228
+ }
3229
+ };
3230
+ var NPMCommands = class {
3231
+ get name() {
3232
+ return "npm";
3233
+ }
3234
+ async resolveDependencyVersion(packageName, options) {
3235
+ const cmd = process.platform === "win32" ? "npm.cmd" : "npm";
3236
+ const { stdout } = await $({ cwd: options.cwd })`${cmd} list ${packageName} --json`;
3237
+ const output = JSON.parse(stdout);
3238
+ logger.debug(`Resolving ${packageName} version using npm`, { output });
3239
+ return this.#recursivelySearchDependencies(output.dependencies, packageName);
3240
+ }
3241
+ #recursivelySearchDependencies(dependencies2, packageName) {
3242
+ for (const [name, dependency] of Object.entries(dependencies2)) {
3243
+ if (name === packageName) {
3244
+ return dependency.version;
3245
+ }
3246
+ if (dependency.dependencies) {
3247
+ const result = this.#recursivelySearchDependencies(dependency.dependencies, packageName);
3248
+ if (result) {
3249
+ return result;
3250
+ }
3251
+ }
3252
+ }
3253
+ }
3254
+ };
3255
+ var YarnCommands = class {
3256
+ get name() {
3257
+ return "yarn";
3258
+ }
3259
+ async resolveDependencyVersion(packageName, options) {
3260
+ const cmd = process.platform === "win32" ? "yarn.cmd" : "yarn";
3261
+ const { stdout } = await $({ cwd: options.cwd })`${cmd} info ${packageName} --json`;
3262
+ const lines = stdout.split("\n");
3263
+ logger.debug(`Resolving ${packageName} version using yarn`, { lines });
3264
+ for (const line of lines) {
3265
+ const json = JSON.parse(line);
3266
+ if (json.value === packageName) {
3267
+ return json.children.Version;
3268
+ }
3269
+ }
3270
+ }
3271
+ };
3272
+
2893
3273
  // src/commands/deploy.ts
2894
- import { Glob } from "glob";
2895
3274
  var DeployCommandOptions = CommonCommandOptions.extend({
2896
3275
  skipTypecheck: z4.boolean().default(false),
2897
3276
  skipDeploy: z4.boolean().default(false),
@@ -3065,26 +3444,38 @@ async function _deployCommand(dir, options) {
3065
3444
  "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."
3066
3445
  );
3067
3446
  }
3068
- return buildAndPushImage({
3069
- registryHost,
3070
- auth: authorization.auth.accessToken,
3071
- imageTag: deploymentResponse.data.imageTag,
3072
- buildId: deploymentResponse.data.externalBuildData.buildId,
3073
- buildToken: deploymentResponse.data.externalBuildData.buildToken,
3074
- buildProjectId: deploymentResponse.data.externalBuildData.projectId,
3075
- cwd: compilation.path,
3076
- projectId: resolvedConfig.config.project,
3077
- deploymentId: deploymentResponse.data.id,
3078
- deploymentVersion: deploymentResponse.data.version,
3079
- contentHash: deploymentResponse.data.contentHash,
3080
- projectRef: resolvedConfig.config.project,
3081
- loadImage: options.loadImage,
3082
- buildPlatform: options.buildPlatform
3083
- });
3447
+ return buildAndPushImage(
3448
+ {
3449
+ registryHost,
3450
+ auth: authorization.auth.accessToken,
3451
+ imageTag: deploymentResponse.data.imageTag,
3452
+ buildId: deploymentResponse.data.externalBuildData.buildId,
3453
+ buildToken: deploymentResponse.data.externalBuildData.buildToken,
3454
+ buildProjectId: deploymentResponse.data.externalBuildData.projectId,
3455
+ cwd: compilation.path,
3456
+ projectId: resolvedConfig.config.project,
3457
+ deploymentId: deploymentResponse.data.id,
3458
+ deploymentVersion: deploymentResponse.data.version,
3459
+ contentHash: deploymentResponse.data.contentHash,
3460
+ projectRef: resolvedConfig.config.project,
3461
+ loadImage: options.loadImage,
3462
+ buildPlatform: options.buildPlatform
3463
+ },
3464
+ deploymentSpinner
3465
+ );
3084
3466
  };
3085
3467
  const image = await buildImage();
3086
3468
  if (!image.ok) {
3087
- deploymentSpinner.stop(`Failed to build project image: ${image.error}`);
3469
+ deploymentSpinner.stop(`Failed to build project.`);
3470
+ if (image.logs.trim() !== "") {
3471
+ const logPath = join5(await createTempDir(), `build-${deploymentResponse.data.shortCode}.log`);
3472
+ await writeFile2(logPath, image.logs);
3473
+ logger.log(
3474
+ `${chalkError("X Error:")} ${image.error}. Full build logs have been saved to ${logPath})`
3475
+ );
3476
+ } else {
3477
+ logger.log(`${chalkError("X Error:")} ${image.error}.`);
3478
+ }
3088
3479
  throw new SkipLoggingError(`Failed to build project image: ${image.error}`);
3089
3480
  }
3090
3481
  const imageReference = options.selfHosted ? `${selfHostedRegistryHost ? `${selfHostedRegistryHost}/` : ""}${image.image}${image.digest ? `@${image.digest}` : ""}` : `${registryHost}/${image.image}${image.digest ? `@${image.digest}` : ""}`;
@@ -3144,10 +3535,27 @@ async function _deployCommand(dir, options) {
3144
3535
  }
3145
3536
  case "FAILED": {
3146
3537
  if (finishedDeployment.errorData) {
3147
- deploymentSpinner.stop(
3148
- `Deployment encountered an error: ${finishedDeployment.errorData.name}. ${deploymentLink}`
3149
- );
3150
- logger.error(finishedDeployment.errorData.stack);
3538
+ if (finishedDeployment.errorData.name === "TaskMetadataParseError") {
3539
+ const errorJson = safeJsonParse(finishedDeployment.errorData.stack);
3540
+ if (errorJson) {
3541
+ const parsedError2 = TaskMetadataFailedToParseData.safeParse(errorJson);
3542
+ if (parsedError2.success) {
3543
+ deploymentSpinner.stop(`Deployment encountered an error. ${deploymentLink}`);
3544
+ logTaskMetadataParseError(parsedError2.data.zodIssues, parsedError2.data.tasks);
3545
+ throw new SkipLoggingError(
3546
+ `Deployment encountered an error: ${finishedDeployment.errorData.name}`
3547
+ );
3548
+ }
3549
+ }
3550
+ }
3551
+ const parsedError = finishedDeployment.errorData.stack ? parseBuildErrorStack(finishedDeployment.errorData) ?? finishedDeployment.errorData.message : finishedDeployment.errorData.message;
3552
+ if (typeof parsedError === "string") {
3553
+ deploymentSpinner.stop(`Deployment encountered an error. ${deploymentLink}`);
3554
+ logger.log(`${chalkError("X Error:")} ${parsedError}`);
3555
+ } else {
3556
+ deploymentSpinner.stop(`Deployment encountered an error. ${deploymentLink}`);
3557
+ logESMRequireError(parsedError, resolvedConfig);
3558
+ }
3151
3559
  throw new SkipLoggingError(
3152
3560
  `Deployment encountered an error: ${finishedDeployment.errorData.name}`
3153
3561
  );
@@ -3185,7 +3593,7 @@ async function checkEnvVars(envVars, config, options, environmentClient, apiUrl)
3185
3593
  environmentVariablesSpinner.stop(
3186
3594
  `Found missing env vars in ${options.env}: ${arrayToSentence(
3187
3595
  missingEnvironmentVariables
3188
- )}. ${options.ignoreEnvVarCheck ? "Continuing deployment because of --ignore-env-var-check. " : "Aborting deployment. "}${chalk4.bgBlueBright(
3596
+ )}. ${options.ignoreEnvVarCheck ? "Continuing deployment because of --ignore-env-var-check. " : "Aborting deployment. "}${chalk5.bgBlueBright(
3189
3597
  terminalLink(
3190
3598
  "Manage env vars",
3191
3599
  `${apiUrl}/projects/v3/${config.project}/environment-variables`
@@ -3246,7 +3654,7 @@ async function waitForDeploymentToFinish(deploymentId, client, timeoutInSeconds
3246
3654
  }
3247
3655
  });
3248
3656
  }
3249
- async function buildAndPushImage(options) {
3657
+ async function buildAndPushImage(options, updater) {
3250
3658
  return tracer.startActiveSpan("buildAndPushImage", async (span) => {
3251
3659
  span.setAttributes({
3252
3660
  "options.registryHost": options.registryHost,
@@ -3302,15 +3710,23 @@ async function buildAndPushImage(options) {
3302
3710
  });
3303
3711
  const errors = [];
3304
3712
  try {
3305
- await new Promise((res, rej) => {
3713
+ const processCode = await new Promise((res, rej) => {
3306
3714
  childProcess2.stderr?.on("data", (data) => {
3307
- const text2 = data.toString();
3308
- errors.push(text2);
3309
- logger.debug(text2);
3715
+ const text3 = data.toString();
3716
+ errors.push(text3);
3717
+ logger.debug(text3);
3310
3718
  });
3311
3719
  childProcess2.on("error", (e) => rej(e));
3312
- childProcess2.on("close", () => res());
3720
+ childProcess2.on("close", (code) => res(code));
3313
3721
  });
3722
+ const logs = extractLogs(errors);
3723
+ if (processCode !== 0) {
3724
+ return {
3725
+ ok: false,
3726
+ error: `Error building image`,
3727
+ logs
3728
+ };
3729
+ }
3314
3730
  const digest = extractImageDigest(errors);
3315
3731
  span.setAttributes({
3316
3732
  "image.digest": digest
@@ -3319,6 +3735,7 @@ async function buildAndPushImage(options) {
3319
3735
  return {
3320
3736
  ok: true,
3321
3737
  image: options.imageTag,
3738
+ logs,
3322
3739
  digest
3323
3740
  };
3324
3741
  } catch (e) {
@@ -3326,7 +3743,8 @@ async function buildAndPushImage(options) {
3326
3743
  span.end();
3327
3744
  return {
3328
3745
  ok: false,
3329
- error: e instanceof Error ? e.message : JSON.stringify(e)
3746
+ error: e instanceof Error ? e.message : JSON.stringify(e),
3747
+ logs: extractLogs(errors)
3330
3748
  };
3331
3749
  }
3332
3750
  });
@@ -3372,15 +3790,22 @@ async function buildAndPushSelfHostedImage(options) {
3372
3790
  const errors = [];
3373
3791
  let digest;
3374
3792
  try {
3375
- await new Promise((res, rej) => {
3793
+ const processCode = await new Promise((res, rej) => {
3376
3794
  buildProcess.stderr?.on("data", (data) => {
3377
- const text2 = data.toString();
3378
- errors.push(text2);
3379
- logger.debug(text2);
3795
+ const text3 = data.toString();
3796
+ errors.push(text3);
3797
+ logger.debug(text3);
3380
3798
  });
3381
3799
  buildProcess.on("error", (e) => rej(e));
3382
- buildProcess.on("close", () => res());
3800
+ buildProcess.on("close", (code) => res(code));
3383
3801
  });
3802
+ if (processCode !== 0) {
3803
+ return {
3804
+ ok: false,
3805
+ error: "Error building image",
3806
+ logs: extractLogs(errors)
3807
+ };
3808
+ }
3384
3809
  digest = extractImageDigest(errors);
3385
3810
  span.setAttributes({
3386
3811
  "image.digest": digest
@@ -3390,7 +3815,8 @@ async function buildAndPushSelfHostedImage(options) {
3390
3815
  span.end();
3391
3816
  return {
3392
3817
  ok: false,
3393
- error: e instanceof Error ? e.message : JSON.stringify(e)
3818
+ error: e instanceof Error ? e.message : JSON.stringify(e),
3819
+ logs: extractLogs(errors)
3394
3820
  };
3395
3821
  }
3396
3822
  const pushArgs = ["push", imageRef].filter(Boolean);
@@ -3401,25 +3827,33 @@ async function buildAndPushSelfHostedImage(options) {
3401
3827
  cwd: options.cwd
3402
3828
  });
3403
3829
  try {
3404
- await new Promise((res, rej) => {
3830
+ const processCode = await new Promise((res, rej) => {
3405
3831
  pushProcess.stdout?.on("data", (data) => {
3406
- const text2 = data.toString();
3407
- logger.debug(text2);
3832
+ const text3 = data.toString();
3833
+ logger.debug(text3);
3408
3834
  });
3409
3835
  pushProcess.stderr?.on("data", (data) => {
3410
- const text2 = data.toString();
3411
- logger.debug(text2);
3836
+ const text3 = data.toString();
3837
+ logger.debug(text3);
3412
3838
  });
3413
3839
  pushProcess.on("error", (e) => rej(e));
3414
- pushProcess.on("close", () => res());
3840
+ pushProcess.on("close", (code) => res(code));
3415
3841
  });
3842
+ if (processCode !== 0) {
3843
+ return {
3844
+ ok: false,
3845
+ error: "Error pushing image",
3846
+ logs: extractLogs(errors)
3847
+ };
3848
+ }
3416
3849
  span.end();
3417
3850
  } catch (e) {
3418
3851
  recordSpanException4(span, e);
3419
3852
  span.end();
3420
3853
  return {
3421
3854
  ok: false,
3422
- error: e instanceof Error ? e.message : JSON.stringify(e)
3855
+ error: e instanceof Error ? e.message : JSON.stringify(e),
3856
+ logs: extractLogs(errors)
3423
3857
  };
3424
3858
  }
3425
3859
  }
@@ -3427,7 +3861,8 @@ async function buildAndPushSelfHostedImage(options) {
3427
3861
  return {
3428
3862
  ok: true,
3429
3863
  image: options.imageTag,
3430
- digest
3864
+ digest,
3865
+ logs: extractLogs(errors)
3431
3866
  };
3432
3867
  });
3433
3868
  }
@@ -3442,6 +3877,10 @@ function extractImageDigest(outputs) {
3442
3877
  }
3443
3878
  }
3444
3879
  }
3880
+ function extractLogs(outputs) {
3881
+ const cleanedOutputs = outputs.map((line) => line.trim()).filter((line) => line !== "");
3882
+ return cleanedOutputs.map((line) => line.trim()).join("\n");
3883
+ }
3445
3884
  async function compileProject(config, options, configPath) {
3446
3885
  return await tracer.startActiveSpan("compileProject", async (span) => {
3447
3886
  try {
@@ -3499,7 +3938,14 @@ async function compileProject(config, options, configPath) {
3499
3938
  TRIGGER_API_URL: `"${config.triggerUrl}"`,
3500
3939
  __PROJECT_CONFIG__: JSON.stringify(config)
3501
3940
  },
3502
- plugins: [bundleDependenciesPlugin(config), workerSetupImportConfigPlugin(configPath)]
3941
+ plugins: [
3942
+ bundleDependenciesPlugin(
3943
+ "workerFacade",
3944
+ config.dependenciesToBundle,
3945
+ config.tsconfigPath
3946
+ ),
3947
+ workerSetupImportConfigPlugin(configPath)
3948
+ ]
3503
3949
  });
3504
3950
  if (result.errors.length > 0) {
3505
3951
  compileSpinner.stop("Build failed, aborting deployment");
@@ -3511,7 +3957,7 @@ async function compileProject(config, options, configPath) {
3511
3957
  throw new Error("Build failed, aborting deployment");
3512
3958
  }
3513
3959
  if (options.outputMetafile) {
3514
- await writeJSONFile(join4(options.outputMetafile, "worker.json"), result.metafile);
3960
+ await writeJSONFile(join5(options.outputMetafile, "worker.json"), result.metafile);
3515
3961
  }
3516
3962
  const entryPointContents = readFileSync2(
3517
3963
  new URL(importResolve("./workers/prod/entry-point.js", import.meta.url)).href.replace(
@@ -3531,17 +3977,23 @@ async function compileProject(config, options, configPath) {
3531
3977
  write: false,
3532
3978
  minify: false,
3533
3979
  sourcemap: false,
3534
- packages: "external",
3535
- // https://esbuild.github.io/api/#packages
3536
3980
  logLevel: "error",
3537
3981
  platform: "node",
3982
+ packages: "external",
3538
3983
  format: "cjs",
3539
3984
  // This is needed to support opentelemetry instrumentation that uses module patching
3540
3985
  target: ["node18", "es2020"],
3541
3986
  outdir: "out",
3542
3987
  define: {
3543
3988
  __PROJECT_CONFIG__: JSON.stringify(config)
3544
- }
3989
+ },
3990
+ plugins: [
3991
+ bundleDependenciesPlugin(
3992
+ "entryPoint.ts",
3993
+ config.dependenciesToBundle,
3994
+ config.tsconfigPath
3995
+ )
3996
+ ]
3545
3997
  });
3546
3998
  if (entryPointResult.errors.length > 0) {
3547
3999
  compileSpinner.stop("Build failed, aborting deployment");
@@ -3554,52 +4006,52 @@ async function compileProject(config, options, configPath) {
3554
4006
  }
3555
4007
  if (options.outputMetafile) {
3556
4008
  await writeJSONFile(
3557
- join4(options.outputMetafile, "entry-point.json"),
4009
+ join5(options.outputMetafile, "entry-point.json"),
3558
4010
  entryPointResult.metafile
3559
4011
  );
3560
4012
  }
3561
4013
  const tempDir = await createTempDir();
3562
4014
  logger.debug(`Writing compiled files to ${tempDir}`);
3563
- const metaOutput = result.metafile.outputs[join4("out", "stdin.js")];
4015
+ const metaOutput = result.metafile.outputs[join5("out", "stdin.js")];
3564
4016
  invariant(metaOutput, "Meta output for the result build is missing");
3565
- const entryPointMetaOutput = entryPointResult.metafile.outputs[join4("out", "stdin.js")];
4017
+ const entryPointMetaOutput = entryPointResult.metafile.outputs[join5("out", "stdin.js")];
3566
4018
  invariant(entryPointMetaOutput, "Meta output for the entryPoint build is missing");
3567
4019
  const workerOutputFile = result.outputFiles.find(
3568
- (file) => file.path === join4(config.projectDir, "out", "stdin.js")
4020
+ (file) => file.path === join5(config.projectDir, "out", "stdin.js")
3569
4021
  );
3570
4022
  invariant(workerOutputFile, "Output file for the result build is missing");
3571
4023
  const workerSourcemapFile = result.outputFiles.find(
3572
- (file) => file.path === join4(config.projectDir, "out", "stdin.js.map")
4024
+ (file) => file.path === join5(config.projectDir, "out", "stdin.js.map")
3573
4025
  );
3574
4026
  invariant(workerSourcemapFile, "Sourcemap file for the result build is missing");
3575
4027
  const entryPointOutputFile = entryPointResult.outputFiles.find(
3576
- (file) => file.path === join4(config.projectDir, "out", "stdin.js")
4028
+ (file) => file.path === join5(config.projectDir, "out", "stdin.js")
3577
4029
  );
3578
4030
  invariant(entryPointOutputFile, "Output file for the entryPoint build is missing");
3579
4031
  await writeFile2(
3580
- join4(tempDir, "worker.js"),
4032
+ join5(tempDir, "worker.js"),
3581
4033
  `${workerOutputFile.text}
3582
4034
  //# sourceMappingURL=worker.js.map`
3583
4035
  );
3584
- await writeFile2(join4(tempDir, "worker.js.map"), workerSourcemapFile.text);
3585
- await writeFile2(join4(tempDir, "index.js"), entryPointOutputFile.text);
4036
+ await writeFile2(join5(tempDir, "worker.js.map"), workerSourcemapFile.text);
4037
+ await writeFile2(join5(tempDir, "index.js"), entryPointOutputFile.text);
4038
+ logger.debug("Getting the imports for the worker and entryPoint builds", {
4039
+ workerImports: metaOutput.imports,
4040
+ entryPointImports: entryPointMetaOutput.imports
4041
+ });
3586
4042
  const allImports = [...metaOutput.imports, ...entryPointMetaOutput.imports];
3587
- const externalPackageJson = await readJSONFile(join4(config.projectDir, "package.json"));
3588
- const dependencies2 = await gatherRequiredDependencies(
3589
- allImports,
3590
- config,
3591
- externalPackageJson
3592
- );
4043
+ const javascriptProject = new JavascriptProject(config.projectDir);
4044
+ const dependencies2 = await gatherRequiredDependencies(allImports, config, javascriptProject);
3593
4045
  const packageJsonContents = {
3594
4046
  name: "trigger-worker",
3595
4047
  version: "0.0.0",
3596
4048
  description: "",
3597
4049
  dependencies: dependencies2,
3598
4050
  scripts: {
3599
- postinstall: externalPackageJson?.scripts?.postinstall
4051
+ ...javascriptProject.scripts
3600
4052
  }
3601
4053
  };
3602
- await writeJSONFile(join4(tempDir, "package.json"), packageJsonContents);
4054
+ await writeJSONFile(join5(tempDir, "package.json"), packageJsonContents);
3603
4055
  await copyAdditionalFiles(config, tempDir);
3604
4056
  compileSpinner.stop("Project built successfully");
3605
4057
  const resolvingDependenciesResult = await resolveDependencies(
@@ -3609,12 +4061,12 @@ async function compileProject(config, options, configPath) {
3609
4061
  options
3610
4062
  );
3611
4063
  if (!resolvingDependenciesResult) {
3612
- throw new Error("Failed to resolve dependencies");
4064
+ throw new SkipLoggingError("Failed to resolve dependencies");
3613
4065
  }
3614
4066
  const containerFilePath = new URL(
3615
4067
  importResolve("./Containerfile.prod", import.meta.url)
3616
4068
  ).href.replace("file://", "");
3617
- await copyFile(containerFilePath, join4(tempDir, "Containerfile"));
4069
+ await copyFile(containerFilePath, join5(tempDir, "Containerfile"));
3618
4070
  const contentHasher = createHash("sha256");
3619
4071
  contentHasher.update(Buffer.from(entryPointOutputFile.text));
3620
4072
  contentHasher.update(Buffer.from(workerOutputFile.text));
@@ -3646,8 +4098,8 @@ async function resolveDependencies(projectDir, packageJsonContents, config, opti
3646
4098
  const hasher = createHash("sha256");
3647
4099
  hasher.update(JSON.stringify(packageJsonContents));
3648
4100
  const digest = hasher.digest("hex").slice(0, 16);
3649
- const cacheDir = join4(config.projectDir, ".trigger", "cache");
3650
- const cachePath = join4(cacheDir, `${digest}.json`);
4101
+ const cacheDir = join5(config.projectDir, ".trigger", "cache");
4102
+ const cachePath = join5(cacheDir, `${digest}.json`);
3651
4103
  span.setAttributes({
3652
4104
  "packageJson.digest": digest,
3653
4105
  "cache.path": cachePath,
@@ -3656,7 +4108,7 @@ async function resolveDependencies(projectDir, packageJsonContents, config, opti
3656
4108
  try {
3657
4109
  const cachedPackageLock = await readFile2(cachePath, "utf-8");
3658
4110
  logger.debug(`Using cached package-lock.json for ${digest}`);
3659
- await writeFile2(join4(projectDir, "package-lock.json"), cachedPackageLock);
4111
+ await writeFile2(join5(projectDir, "package-lock.json"), cachedPackageLock);
3660
4112
  span.setAttributes({
3661
4113
  "cache.hit": true
3662
4114
  });
@@ -3679,21 +4131,44 @@ async function resolveDependencies(projectDir, packageJsonContents, config, opti
3679
4131
  cwd: projectDir,
3680
4132
  stdio: logger.loggerLevel === "debug" ? "inherit" : "pipe"
3681
4133
  });
3682
- const packageLockContents = await readFile2(join4(projectDir, "package-lock.json"), "utf-8");
4134
+ const packageLockContents = await readFile2(join5(projectDir, "package-lock.json"), "utf-8");
3683
4135
  logger.debug(`Writing package-lock.json to cache for ${digest}`);
3684
4136
  await mkdir(cacheDir, { recursive: true });
3685
4137
  await writeFile2(cachePath, packageLockContents);
3686
- await writeFile2(join4(projectDir, "package-lock.json"), packageLockContents);
4138
+ await writeFile2(join5(projectDir, "package-lock.json"), packageLockContents);
3687
4139
  span.end();
3688
4140
  resolvingDepsSpinner.stop("Dependencies resolved");
3689
4141
  return true;
3690
4142
  } catch (installError) {
3691
- logger.debug(`Failed to resolve dependencies: ${JSON.stringify(installError)}`);
3692
4143
  recordSpanException4(span, installError);
3693
4144
  span.end();
3694
- resolvingDepsSpinner.stop(
3695
- "Failed to resolve dependencies. Rerun with --log-level=debug for more information"
3696
- );
4145
+ const parsedError = parseNpmInstallError(installError);
4146
+ if (typeof parsedError === "string") {
4147
+ resolvingDepsSpinner.stop(`Failed to resolve dependencies: ${parsedError}`);
4148
+ } else {
4149
+ switch (parsedError.type) {
4150
+ case "package-not-found-error": {
4151
+ resolvingDepsSpinner.stop(`Failed to resolve dependencies`);
4152
+ logger.log(
4153
+ `
4154
+ ${chalkError("X Error:")} The package ${chalkPurple(
4155
+ parsedError.packageName
4156
+ )} could not be found in the npm registry.`
4157
+ );
4158
+ break;
4159
+ }
4160
+ case "no-matching-version-error": {
4161
+ resolvingDepsSpinner.stop(`Failed to resolve dependencies`);
4162
+ logger.log(
4163
+ `
4164
+ ${chalkError("X Error:")} The package ${chalkPurple(
4165
+ parsedError.packageName
4166
+ )} could not resolve because the version doesn't exist`
4167
+ );
4168
+ break;
4169
+ }
4170
+ }
4171
+ }
3697
4172
  return false;
3698
4173
  }
3699
4174
  }
@@ -3737,17 +4212,17 @@ async function typecheckProject(config, options) {
3737
4212
  }
3738
4213
  });
3739
4214
  }
3740
- async function gatherRequiredDependencies(imports, config, projectPackageJson) {
4215
+ async function gatherRequiredDependencies(imports, config, project) {
3741
4216
  const dependencies2 = {};
3742
4217
  for (const file of imports) {
3743
- if (file.kind !== "require-call" || !file.external) {
4218
+ if (file.kind !== "require-call" && file.kind !== "dynamic-import" || !file.external) {
3744
4219
  continue;
3745
4220
  }
3746
4221
  const packageName = detectPackageNameFromImportPath(file.path);
3747
4222
  if (dependencies2[packageName]) {
3748
4223
  continue;
3749
4224
  }
3750
- const externalDependencyVersion = (projectPackageJson?.dependencies ?? {})[packageName];
4225
+ const externalDependencyVersion = await project.resolve(packageName);
3751
4226
  if (externalDependencyVersion) {
3752
4227
  dependencies2[packageName] = stripWorkspaceFromVersion(externalDependencyVersion);
3753
4228
  continue;
@@ -3767,16 +4242,17 @@ async function gatherRequiredDependencies(imports, config, projectPackageJson) {
3767
4242
  dependencies2[packageParts.name] = packageParts.version;
3768
4243
  continue;
3769
4244
  } else {
3770
- const externalDependencyVersion = {
3771
- ...projectPackageJson?.devDependencies,
3772
- ...projectPackageJson?.dependencies
3773
- }[packageName];
4245
+ const externalDependencyVersion = await project.resolve(packageParts.name, {
4246
+ allowDev: true
4247
+ });
3774
4248
  if (externalDependencyVersion) {
3775
4249
  dependencies2[packageParts.name] = externalDependencyVersion;
3776
4250
  continue;
3777
4251
  } else {
3778
- logger.warn(
3779
- `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`
4252
+ logger.log(
4253
+ `${chalkWarning("X Warning:")} Could not find version for package ${chalkPurple(
4254
+ packageName
4255
+ )}, add a version specifier to the package name (e.g. ${packageParts.name}@latest) or add it to your project's package.json`
3780
4256
  );
3781
4257
  }
3782
4258
  }
@@ -3808,9 +4284,9 @@ async function copyAdditionalFiles(config, tempDir) {
3808
4284
  nodir: true
3809
4285
  });
3810
4286
  for await (const file of glob) {
3811
- const relativeDestinationPath = join4(
4287
+ const relativeDestinationPath = join5(
3812
4288
  tempDir,
3813
- relative2(config.projectDir, file.fullpath())
4289
+ relative3(config.projectDir, file.fullpath())
3814
4290
  );
3815
4291
  logger.debug(`Copying file ${file.fullpath()} to ${relativeDestinationPath}`);
3816
4292
  await mkdir(dirname(relativeDestinationPath), { recursive: true });
@@ -3827,7 +4303,7 @@ async function copyAdditionalFiles(config, tempDir) {
3827
4303
  }
3828
4304
  async function ensureLoggedIntoDockerRegistry(registryHost, auth) {
3829
4305
  const tmpDir = await createTempDir();
3830
- const dockerConfigPath = join4(tmpDir, "config.json");
4306
+ const dockerConfigPath = join5(tmpDir, "config.json");
3831
4307
  await writeJSONFile(dockerConfigPath, {
3832
4308
  auths: {
3833
4309
  [registryHost]: {
@@ -3842,7 +4318,7 @@ async function findAllEnvironmentVariableReferencesInFile(filePath) {
3842
4318
  const fileContents = await readFile2(filePath, "utf-8");
3843
4319
  return findAllEnvironmentVariableReferences(fileContents);
3844
4320
  }
3845
- var IGNORED_ENV_VARS = ["NODE_ENV", "SHELL", "HOME", "PWD", "LOGNAME", "USER", "PATH"];
4321
+ var IGNORED_ENV_VARS = ["NODE_ENV", "SHELL", "HOME", "PWD", "LOGNAME", "USER", "PATH", "DEBUG"];
3846
4322
  function findAllEnvironmentVariableReferences(code) {
3847
4323
  const regex = /\bprocess\.env\.([a-zA-Z_][a-zA-Z0-9_]*)\b/g;
3848
4324
  const matches = code.matchAll(regex);
@@ -3874,7 +4350,7 @@ import { resolve as importResolve2 } from "import-meta-resolve";
3874
4350
  import { render, useInput } from "ink";
3875
4351
  import { createHash as createHash2 } from "node:crypto";
3876
4352
  import fs7, { readFileSync as readFileSync3 } from "node:fs";
3877
- import { basename, dirname as dirname3, join as join5 } from "node:path";
4353
+ import { basename, dirname as dirname3, join as join6 } from "node:path";
3878
4354
  import pDebounce from "p-debounce";
3879
4355
  import { WebSocket } from "partysocket";
3880
4356
  import React, { Suspense, useEffect } from "react";
@@ -3890,6 +4366,14 @@ var UncaughtExceptionError = class extends Error {
3890
4366
  this.name = "UncaughtExceptionError";
3891
4367
  }
3892
4368
  };
4369
+ var TaskMetadataParseError = class extends Error {
4370
+ constructor(zodIssues, tasks) {
4371
+ super(`Failed to parse task metadata`);
4372
+ this.zodIssues = zodIssues;
4373
+ this.tasks = tasks;
4374
+ this.name = "TaskMetadataParseError";
4375
+ }
4376
+ };
3893
4377
 
3894
4378
  // src/workers/dev/backgroundWorker.ts
3895
4379
  import {
@@ -4099,6 +4583,12 @@ var BackgroundWorker = class {
4099
4583
  await installPackages(this.params.dependencies, { cwd: dirname2(this.path) });
4100
4584
  }
4101
4585
  let resolved = false;
4586
+ const cwd = dirname2(this.path);
4587
+ const fullEnv = {
4588
+ ...this.params.env,
4589
+ ...this.#readEnvVars()
4590
+ };
4591
+ logger.debug("Initializing worker", { path: this.path, cwd, fullEnv });
4102
4592
  this.tasks = await new Promise((resolve4, reject) => {
4103
4593
  const child = fork(this.path, {
4104
4594
  stdio: [
@@ -4110,10 +4600,8 @@ var BackgroundWorker = class {
4110
4600
  "pipe",
4111
4601
  "ipc"
4112
4602
  ],
4113
- env: {
4114
- ...this.params.env,
4115
- ...this.#readEnvVars()
4116
- }
4603
+ cwd,
4604
+ env: fullEnv
4117
4605
  });
4118
4606
  const timeout = setTimeout(() => {
4119
4607
  if (resolved) {
@@ -4135,6 +4623,11 @@ var BackgroundWorker = class {
4135
4623
  resolved = true;
4136
4624
  reject(new UncaughtExceptionError(message.payload.error, message.payload.origin));
4137
4625
  child.kill();
4626
+ } else if (message.type === "TASKS_FAILED_TO_PARSE") {
4627
+ clearTimeout(timeout);
4628
+ resolved = true;
4629
+ reject(new TaskMetadataParseError(message.payload.zodIssues, message.payload.tasks));
4630
+ child.kill();
4138
4631
  }
4139
4632
  });
4140
4633
  child.on("exit", (code) => {
@@ -4160,7 +4653,7 @@ var BackgroundWorker = class {
4160
4653
  }
4161
4654
  if (!this._taskRunProcesses.has(payload.execution.run.id)) {
4162
4655
  const taskRunProcess = new TaskRunProcess(
4163
- payload.execution.run.id,
4656
+ payload.execution,
4164
4657
  this.path,
4165
4658
  {
4166
4659
  ...this.params.env,
@@ -4270,8 +4763,8 @@ var BackgroundWorker = class {
4270
4763
  }
4271
4764
  };
4272
4765
  var TaskRunProcess = class {
4273
- constructor(runId, path6, env, metadata, worker) {
4274
- this.runId = runId;
4766
+ constructor(execution, path6, env, metadata, worker) {
4767
+ this.execution = execution;
4275
4768
  this.path = path6;
4276
4769
  this.env = env;
4277
4770
  this.metadata = metadata;
@@ -4302,9 +4795,20 @@ var TaskRunProcess = class {
4302
4795
  await this.cleanup(true);
4303
4796
  }
4304
4797
  async initialize() {
4305
- logger.debug(`[${this.runId}] initializing task run process`, {
4306
- env: this.env,
4307
- path: this.path
4798
+ const fullEnv = {
4799
+ ...this.execution.run.isTest ? { TRIGGER_LOG_LEVEL: "debug" } : {},
4800
+ ...this.env,
4801
+ OTEL_RESOURCE_ATTRIBUTES: JSON.stringify({
4802
+ [SemanticInternalAttributes.PROJECT_DIR]: this.worker.projectConfig.projectDir
4803
+ }),
4804
+ OTEL_EXPORTER_OTLP_COMPRESSION: "none",
4805
+ ...this.worker.debugOtel ? { OTEL_LOG_LEVEL: "debug" } : {}
4806
+ };
4807
+ const cwd = dirname2(this.path);
4808
+ logger.debug(`[${this.execution.run.id}] initializing task run process`, {
4809
+ env: fullEnv,
4810
+ path: this.path,
4811
+ cwd
4308
4812
  });
4309
4813
  this._child = fork(this.path, {
4310
4814
  stdio: [
@@ -4316,15 +4820,8 @@ var TaskRunProcess = class {
4316
4820
  "pipe",
4317
4821
  "ipc"
4318
4822
  ],
4319
- cwd: dirname2(this.path),
4320
- env: {
4321
- ...this.env,
4322
- OTEL_RESOURCE_ATTRIBUTES: JSON.stringify({
4323
- [SemanticInternalAttributes.PROJECT_DIR]: this.worker.projectConfig.projectDir
4324
- }),
4325
- OTEL_EXPORTER_OTLP_COMPRESSION: "none",
4326
- ...this.worker.debugOtel ? { OTEL_LOG_LEVEL: "debug" } : {}
4327
- },
4823
+ cwd,
4824
+ env: fullEnv,
4328
4825
  execArgv: this.worker.debuggerOn ? ["--inspect-brk", "--trace-uncaught", "--no-warnings=ExperimentalWarning"] : ["--trace-uncaught", "--no-warnings=ExperimentalWarning"]
4329
4826
  });
4330
4827
  this._child.on("message", this.#handleMessage.bind(this));
@@ -4336,7 +4833,7 @@ var TaskRunProcess = class {
4336
4833
  if (kill && this._isBeingKilled) {
4337
4834
  return;
4338
4835
  }
4339
- logger.debug(`[${this.runId}] cleaning up task run process`, { kill });
4836
+ logger.debug(`[${this.execution.run.id}] cleaning up task run process`, { kill });
4340
4837
  await this._sender.send("CLEANUP", {
4341
4838
  flush: true,
4342
4839
  kill
@@ -4367,10 +4864,13 @@ var TaskRunProcess = class {
4367
4864
  if (!completion.ok && typeof completion.retry !== "undefined") {
4368
4865
  return;
4369
4866
  }
4370
- if (execution.run.id === this.runId) {
4867
+ if (execution.run.id === this.execution.run.id) {
4371
4868
  return;
4372
4869
  }
4373
- logger.debug(`[${this.runId}] task run completed notification`, { completion, execution });
4870
+ logger.debug(`[${this.execution.run.id}] task run completed notification`, {
4871
+ completion,
4872
+ execution
4873
+ });
4374
4874
  this._sender.send("TASK_RUN_COMPLETED_NOTIFICATION", {
4375
4875
  completion,
4376
4876
  execution
@@ -4408,7 +4908,7 @@ var TaskRunProcess = class {
4408
4908
  }
4409
4909
  }
4410
4910
  async #handleExit(code) {
4411
- logger.debug(`[${this.runId}] task run process exiting`, { code });
4911
+ logger.debug(`[${this.execution.run.id}] task run process exiting`, { code });
4412
4912
  for (const [id, status] of this._attemptStatuses.entries()) {
4413
4913
  if (status === "PENDING") {
4414
4914
  this._attemptStatuses.set(id, "REJECTED");
@@ -4455,7 +4955,27 @@ var TaskRunProcess = class {
4455
4955
  }
4456
4956
  };
4457
4957
 
4958
+ // src/utilities/runtimeCheck.ts
4959
+ function runtimeCheck(minimumMajor, minimumMinor) {
4960
+ if (typeof process === "undefined") {
4961
+ throw "The dev CLI can only be run in a Node.js compatible environment";
4962
+ }
4963
+ const [major = 0, minor = 0] = process.versions.node.split(".").map(Number);
4964
+ const isBun = typeof process.versions.bun === "string";
4965
+ if (major < minimumMajor || major === minimumMajor && minor < minimumMinor) {
4966
+ if (isBun) {
4967
+ 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}`;
4968
+ } else {
4969
+ throw `The dev CLI requires at least Node.js ${minimumMajor}.${minimumMinor}. You are running Node.js ${process.versions.node}`;
4970
+ }
4971
+ }
4972
+ logger.debug(
4973
+ `Node.js version: ${process.versions.node}${isBun ? ` (Bun ${process.versions.bun})` : ""}`
4974
+ );
4975
+ }
4976
+
4458
4977
  // src/commands/dev.tsx
4978
+ import { findUp as findUp3, pathExists as pathExists2 } from "find-up";
4459
4979
  var apiClient;
4460
4980
  var DevCommandOptions = CommonCommandOptions.extend({
4461
4981
  debugger: z5.boolean().default(false),
@@ -4465,7 +4985,7 @@ var DevCommandOptions = CommonCommandOptions.extend({
4465
4985
  });
4466
4986
  function configureDevCommand(program2) {
4467
4987
  return commonOptions(
4468
- 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(
4988
+ 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(
4469
4989
  "-p, --project-ref <project ref>",
4470
4990
  "The project ref. Required if there is no config file."
4471
4991
  ).option("--debugger", "Enable the debugger").option("--debug-otel", "Enable OpenTelemetry debugging")
@@ -4475,22 +4995,35 @@ function configureDevCommand(program2) {
4475
4995
  });
4476
4996
  });
4477
4997
  }
4998
+ var MINIMUM_NODE_MAJOR = 18;
4999
+ var MINIMUM_NODE_MINOR = 16;
4478
5000
  async function devCommand(dir, options) {
5001
+ try {
5002
+ runtimeCheck(MINIMUM_NODE_MAJOR, MINIMUM_NODE_MINOR);
5003
+ } catch (e) {
5004
+ logger.log(`${chalkError("X Error:")} ${e}`);
5005
+ process.exitCode = 1;
5006
+ return;
5007
+ }
4479
5008
  const authorization = await isLoggedIn(options.profile);
4480
5009
  if (!authorization.ok) {
4481
5010
  if (authorization.error === "fetch failed") {
4482
- logger.error("Fetch failed. Platform down?");
5011
+ logger.log(
5012
+ `${chalkError(
5013
+ "X Error:"
5014
+ )} Connecting to the server failed. Please check your internet connection or contact eric@trigger.dev for help.`
5015
+ );
4483
5016
  } else {
4484
- logger.error("You must login first. Use `trigger.dev login` to login.");
5017
+ logger.log(`${chalkError("X Error:")} You must login first. Use the \`login\` CLI command.`);
4485
5018
  }
4486
5019
  process.exitCode = 1;
4487
5020
  return;
4488
5021
  }
4489
- const devInstance = await startDev(dir, options, authorization.auth);
5022
+ const devInstance = await startDev(dir, options, authorization.auth, authorization.dashboardUrl);
4490
5023
  const { waitUntilExit } = devInstance.devReactElement;
4491
5024
  await waitUntilExit();
4492
5025
  }
4493
- async function startDev(dir, options, authorization) {
5026
+ async function startDev(dir, options, authorization, dashboardUrl) {
4494
5027
  let rerender;
4495
5028
  try {
4496
5029
  if (options.logLevel) {
@@ -4528,6 +5061,7 @@ async function startDev(dir, options, authorization) {
4528
5061
  return /* @__PURE__ */ React.createElement(
4529
5062
  DevUI,
4530
5063
  {
5064
+ dashboardUrl,
4531
5065
  config: configParam,
4532
5066
  apiUrl,
4533
5067
  apiKey: devEnv.data.apiKey,
@@ -4559,6 +5093,7 @@ async function startDev(dir, options, authorization) {
4559
5093
  }
4560
5094
  function useDev({
4561
5095
  config,
5096
+ dashboardUrl,
4562
5097
  apiUrl,
4563
5098
  apiKey,
4564
5099
  environmentClient,
@@ -4588,7 +5123,7 @@ function useDev({
4588
5123
  }
4589
5124
  });
4590
5125
  const backgroundWorkerCoordinator = new BackgroundWorkerCoordinator(
4591
- `${apiUrl}/projects/v3/${config.project}`
5126
+ `${dashboardUrl}/projects/v3/${config.project}`
4592
5127
  );
4593
5128
  websocket.addEventListener("open", async (event) => {
4594
5129
  });
@@ -4708,7 +5243,12 @@ function useDev({
4708
5243
  __PROJECT_CONFIG__: JSON.stringify(config)
4709
5244
  },
4710
5245
  plugins: [
4711
- bundleDependenciesPlugin(config),
5246
+ bundleTriggerDevCore("workerFacade", config.tsconfigPath),
5247
+ bundleDependenciesPlugin(
5248
+ "workerFacade",
5249
+ (config.dependenciesToBundle ?? []).concat([/^@trigger.dev/]),
5250
+ config.tsconfigPath
5251
+ ),
4712
5252
  workerSetupImportConfigPlugin(configPath),
4713
5253
  {
4714
5254
  name: "trigger.dev v3",
@@ -4723,19 +5263,19 @@ function useDev({
4723
5263
  if (!firstBuild) {
4724
5264
  logger.log(chalkGrey("\u25CB Building background worker\u2026"));
4725
5265
  }
4726
- const metaOutputKey = join5("out", `stdin.js`);
5266
+ const metaOutputKey = join6("out", `stdin.js`);
4727
5267
  const metaOutput = result.metafile.outputs[metaOutputKey];
4728
5268
  if (!metaOutput) {
4729
5269
  throw new Error(`Could not find metafile`);
4730
5270
  }
4731
- const outputFileKey = join5(config.projectDir, metaOutputKey);
5271
+ const outputFileKey = join6(config.projectDir, metaOutputKey);
4732
5272
  const outputFile = result.outputFiles.find((file) => file.path === outputFileKey);
4733
5273
  if (!outputFile) {
4734
5274
  throw new Error(
4735
5275
  `Could not find output file for entry point ${metaOutput.entryPoint}`
4736
5276
  );
4737
5277
  }
4738
- const sourceMapFileKey = join5(config.projectDir, `${metaOutputKey}.map`);
5278
+ const sourceMapFileKey = join6(config.projectDir, `${metaOutputKey}.map`);
4739
5279
  const sourceMapFile = result.outputFiles.find(
4740
5280
  (file) => file.path === sourceMapFileKey
4741
5281
  );
@@ -4746,7 +5286,7 @@ function useDev({
4746
5286
  logger.log(chalkGrey("\u25CB No changes detected, skipping build\u2026"));
4747
5287
  return;
4748
5288
  }
4749
- const fullPath = join5(config.projectDir, ".trigger", `${contentHash}.js`);
5289
+ const fullPath = join6(config.projectDir, ".trigger", `${contentHash}.js`);
4750
5290
  const sourceMapPath = `${fullPath}.map`;
4751
5291
  const outputFileWithSourceMap = `${outputFile.text}
4752
5292
  //# sourceMappingURL=${basename(sourceMapPath)}`;
@@ -4759,7 +5299,7 @@ function useDev({
4759
5299
  await fs7.promises.writeFile(sourceMapPath2, sourceMapFile.text);
4760
5300
  }
4761
5301
  const environmentVariablesResponse = await environmentClient.getEnvironmentVariables(config.project);
4762
- const processEnv = gatherProcessEnv();
5302
+ const processEnv = await gatherProcessEnv();
4763
5303
  const backgroundWorker = new BackgroundWorker(fullPath, {
4764
5304
  projectConfig: config,
4765
5305
  dependencies: dependencies2,
@@ -4827,17 +5367,52 @@ function useDev({
4827
5367
  backgroundWorker
4828
5368
  );
4829
5369
  } catch (e) {
4830
- if (e instanceof UncaughtExceptionError) {
5370
+ if (e instanceof TaskMetadataParseError) {
5371
+ logTaskMetadataParseError(e.zodIssues, e.tasks);
5372
+ return;
5373
+ } else if (e instanceof UncaughtExceptionError) {
5374
+ const parsedBuildError = parseBuildErrorStack(e.originalError);
5375
+ if (parsedBuildError && typeof parsedBuildError !== "string") {
5376
+ logESMRequireError(
5377
+ parsedBuildError,
5378
+ configPath ? { status: "file", path: configPath, config } : { status: "in-memory", config }
5379
+ );
5380
+ return;
5381
+ } else {
5382
+ }
4831
5383
  if (e.originalError.stack) {
4832
- logger.error("Background worker failed to start", e.originalError.stack);
5384
+ logger.log(
5385
+ `${chalkError("X Error:")} Worker failed to start`,
5386
+ e.originalError.stack
5387
+ );
4833
5388
  }
4834
5389
  return;
4835
5390
  }
4836
- if (e instanceof Error) {
4837
- logger.error(`Background worker failed to start`, e.stack);
4838
- return;
5391
+ const parsedError = parseNpmInstallError(e);
5392
+ if (typeof parsedError === "string") {
5393
+ logger.log(`${chalkError("X Error:")} ${parsedError}`);
5394
+ } else {
5395
+ switch (parsedError.type) {
5396
+ case "package-not-found-error": {
5397
+ logger.log(
5398
+ `
5399
+ ${chalkError("X Error:")} The package ${chalkPurple(
5400
+ parsedError.packageName
5401
+ )} could not be found in the npm registry.`
5402
+ );
5403
+ break;
5404
+ }
5405
+ case "no-matching-version-error": {
5406
+ logger.log(
5407
+ `
5408
+ ${chalkError("X Error:")} The package ${chalkPurple(
5409
+ parsedError.packageName
5410
+ )} could not resolve because the version doesn't exist`
5411
+ );
5412
+ break;
5413
+ }
5414
+ }
4839
5415
  }
4840
- logger.error(`Background worker failed to start: ${e}`);
4841
5416
  }
4842
5417
  });
4843
5418
  }
@@ -4901,8 +5476,11 @@ function WebsocketFactory(apiKey) {
4901
5476
  }
4902
5477
  async function gatherRequiredDependencies2(outputMeta, config) {
4903
5478
  const dependencies2 = {};
5479
+ logger.debug("Gathering required dependencies from imports", {
5480
+ imports: outputMeta.imports
5481
+ });
4904
5482
  for (const file of outputMeta.imports) {
4905
- if (file.kind !== "require-call" || !file.external) {
5483
+ if (file.kind !== "require-call" && file.kind !== "dynamic-import" || !file.external) {
4906
5484
  continue;
4907
5485
  }
4908
5486
  const packageName = detectPackageNameFromImportPath(file.path);
@@ -4915,7 +5493,7 @@ async function gatherRequiredDependencies2(outputMeta, config) {
4915
5493
  }
4916
5494
  }
4917
5495
  if (config.additionalPackages) {
4918
- const projectPackageJson = await readJSONFile(join5(config.projectDir, "package.json"));
5496
+ const projectPackageJson = await readJSONFile(join6(config.projectDir, "package.json"));
4919
5497
  for (const packageName of config.additionalPackages) {
4920
5498
  if (dependencies2[packageName]) {
4921
5499
  continue;
@@ -4945,16 +5523,14 @@ async function gatherRequiredDependencies2(outputMeta, config) {
4945
5523
  function createDuplicateTaskIdOutputErrorMessage(duplicateTaskIds, taskResources) {
4946
5524
  const duplicateTable = duplicateTaskIds.map((id) => {
4947
5525
  const tasks = taskResources.filter((task) => task.id === id);
4948
- return `id "${chalkPurple(id)}" was found in:
4949
- ${tasks.map((task) => `${task.filePath} -> ${task.exportName}`).join("\n")}`;
4950
- }).join("\n\n");
4951
- return `Duplicate task ids detected:
5526
+ return `
4952
5527
 
4953
- ${duplicateTable}
4954
-
4955
- `;
5528
+ ${chalkTask(id)} was found in:${tasks.map((task) => `
5529
+ ${task.filePath} -> ${task.exportName}`).join("")}`;
5530
+ }).join("");
5531
+ return `Duplicate ${chalkTask("task id")} detected:${duplicateTable}`;
4956
5532
  }
4957
- function gatherProcessEnv() {
5533
+ async function gatherProcessEnv() {
4958
5534
  const env = {
4959
5535
  NODE_ENV: process.env.NODE_ENV ?? "development",
4960
5536
  PATH: process.env.PATH,
@@ -4965,12 +5541,37 @@ function gatherProcessEnv() {
4965
5541
  NVM_BIN: process.env.NVM_BIN,
4966
5542
  LANG: process.env.LANG,
4967
5543
  TERM: process.env.TERM,
4968
- NODE_PATH: process.env.NODE_PATH,
5544
+ NODE_PATH: await amendNodePathWithPnpmNodeModules(process.env.NODE_PATH),
4969
5545
  HOME: process.env.HOME,
4970
5546
  BUN_INSTALL: process.env.BUN_INSTALL
4971
5547
  };
4972
5548
  return Object.fromEntries(Object.entries(env).filter(([key, value]) => value !== void 0));
4973
5549
  }
5550
+ async function amendNodePathWithPnpmNodeModules(nodePath) {
5551
+ const pnpmModulesPath = await findPnpmNodeModulesPath();
5552
+ if (!pnpmModulesPath) {
5553
+ return nodePath;
5554
+ }
5555
+ if (nodePath) {
5556
+ if (nodePath.includes(pnpmModulesPath)) {
5557
+ return nodePath;
5558
+ }
5559
+ return `${nodePath}:${pnpmModulesPath}`;
5560
+ }
5561
+ return pnpmModulesPath;
5562
+ }
5563
+ async function findPnpmNodeModulesPath() {
5564
+ return await findUp3(
5565
+ async (directory) => {
5566
+ const pnpmModules = join6(directory, "node_modules", ".pnpm", "node_modules");
5567
+ const hasPnpmNodeModules = await pathExists2(pnpmModules);
5568
+ if (hasPnpmNodeModules) {
5569
+ return pnpmModules;
5570
+ }
5571
+ },
5572
+ { type: "directory" }
5573
+ );
5574
+ }
4974
5575
 
4975
5576
  // src/commands/init.ts
4976
5577
  import { intro as intro4, isCancel, log as log3, outro as outro4, select as select2, spinner as spinner5, text } from "@clack/prompts";
@@ -4979,11 +5580,11 @@ import {
4979
5580
  flattenAttributes as flattenAttributes3,
4980
5581
  recordSpanException as recordSpanException5
4981
5582
  } from "@trigger.dev/core/v3";
4982
- import chalk5 from "chalk";
5583
+ import chalk6 from "chalk";
4983
5584
  import { execa as execa3 } from "execa";
4984
5585
  import { applyEdits, modify } from "jsonc-parser";
4985
5586
  import { writeFile as writeFile3 } from "node:fs/promises";
4986
- import { join as join6, relative as relative3, resolve as resolve3 } from "node:path";
5587
+ import { join as join7, relative as relative4, resolve as resolve3 } from "node:path";
4987
5588
  import terminalLink3 from "terminal-link";
4988
5589
  import { z as z6 } from "zod";
4989
5590
 
@@ -5028,45 +5629,6 @@ function replaceAll(input, replacements) {
5028
5629
  return output;
5029
5630
  }
5030
5631
 
5031
- // src/utilities/getUserPackageManager.ts
5032
- import pathModule2 from "path";
5033
- async function getUserPackageManager(path6) {
5034
- try {
5035
- return await detectPackageManagerFromArtifacts(path6);
5036
- } catch (error) {
5037
- return detectPackageManagerFromCurrentCommand();
5038
- }
5039
- }
5040
- function detectPackageManagerFromCurrentCommand() {
5041
- const userAgent = process.env.npm_config_user_agent;
5042
- if (userAgent) {
5043
- if (userAgent.startsWith("yarn")) {
5044
- return "yarn";
5045
- } else if (userAgent.startsWith("pnpm")) {
5046
- return "pnpm";
5047
- } else {
5048
- return "npm";
5049
- }
5050
- } else {
5051
- return "npm";
5052
- }
5053
- }
5054
- async function detectPackageManagerFromArtifacts(path6) {
5055
- const packageFiles = [
5056
- { name: "yarn.lock", pm: "yarn" },
5057
- { name: "pnpm-lock.yaml", pm: "pnpm" },
5058
- { name: "package-lock.json", pm: "npm" },
5059
- { name: "npm-shrinkwrap.json", pm: "npm" }
5060
- ];
5061
- for (const { name, pm } of packageFiles) {
5062
- const exists = await pathExists(pathModule2.join(path6, name));
5063
- if (exists) {
5064
- return pm;
5065
- }
5066
- }
5067
- throw new Error("Could not detect package manager from artifacts");
5068
- }
5069
-
5070
5632
  // src/utilities/resolveInternalFilePath.ts
5071
5633
  import { resolve as importResolve3 } from "import-meta-resolve";
5072
5634
  function resolveInternalFilePath(filePath) {
@@ -5162,7 +5724,7 @@ async function _initCommand(dir, options) {
5162
5724
  log3.success("Successfully initialized project for Trigger.dev v3 \u{1FAE1}");
5163
5725
  log3.info("Next steps:");
5164
5726
  log3.info(
5165
- ` 1. To start developing, run ${chalk5.green(
5727
+ ` 1. To start developing, run ${chalk6.green(
5166
5728
  `npx trigger.dev@${options.tag} dev`
5167
5729
  )} in your project directory`
5168
5730
  );
@@ -5177,7 +5739,7 @@ async function _initCommand(dir, options) {
5177
5739
  ` 4. Need help? Join our ${terminalLink3(
5178
5740
  "Discord community",
5179
5741
  "https://trigger.dev/discord"
5180
- )} or email us at ${chalk5.cyan("help@trigger.dev")}`
5742
+ )} or email us at ${chalk6.cyan("help@trigger.dev")}`
5181
5743
  );
5182
5744
  outro4(`Project initialized successfully. Happy coding!`);
5183
5745
  }
@@ -5219,19 +5781,19 @@ async function createTriggerDir(dir, options) {
5219
5781
  "cli.example": example
5220
5782
  });
5221
5783
  if (example === "none") {
5222
- await createFile(join6(triggerDir, ".gitkeep"), "");
5784
+ await createFile(join7(triggerDir, ".gitkeep"), "");
5223
5785
  log3.step(`Created directory at ${location}`);
5224
5786
  span.end();
5225
5787
  return { location, isCustomValue: location !== defaultValue };
5226
5788
  }
5227
5789
  const exampleFile = resolveInternalFilePath(`./templates/examples/${example}.ts.template`);
5228
- const outputPath = join6(triggerDir, "example.ts");
5790
+ const outputPath = join7(triggerDir, "example.ts");
5229
5791
  await createFileFromTemplate({
5230
5792
  templatePath: exampleFile,
5231
5793
  outputPath,
5232
5794
  replacements: {}
5233
5795
  });
5234
- const relativeOutputPath = relative3(process.cwd(), outputPath);
5796
+ const relativeOutputPath = relative4(process.cwd(), outputPath);
5235
5797
  log3.step(`Created example file at ${relativeOutputPath}`);
5236
5798
  span.end();
5237
5799
  return { location, isCustomValue: location !== defaultValue };
@@ -5248,7 +5810,7 @@ async function gitIgnoreDotTriggerDir(dir, options) {
5248
5810
  return await tracer.startActiveSpan("gitIgnoreDotTriggerDir", async (span) => {
5249
5811
  try {
5250
5812
  const projectDir = resolve3(process.cwd(), dir);
5251
- const gitIgnorePath = join6(projectDir, ".gitignore");
5813
+ const gitIgnorePath = join7(projectDir, ".gitignore");
5252
5814
  span.setAttributes({
5253
5815
  "cli.projectDir": projectDir,
5254
5816
  "cli.gitIgnorePath": gitIgnorePath
@@ -5282,7 +5844,7 @@ async function addConfigFileToTsConfig(dir, options) {
5282
5844
  return await tracer.startActiveSpan("createTriggerDir", async (span) => {
5283
5845
  try {
5284
5846
  const projectDir = resolve3(process.cwd(), dir);
5285
- const tsconfigPath = join6(projectDir, "tsconfig.json");
5847
+ const tsconfigPath = join7(projectDir, "tsconfig.json");
5286
5848
  span.setAttributes({
5287
5849
  "cli.projectDir": projectDir,
5288
5850
  "cli.tsconfigPath": tsconfigPath
@@ -5369,7 +5931,7 @@ async function writeConfigFile(dir, project, options, triggerDir) {
5369
5931
  spnnr.start("Creating config file");
5370
5932
  const projectDir = resolve3(process.cwd(), dir);
5371
5933
  const templatePath = resolveInternalFilePath("./templates/trigger.config.ts.template");
5372
- const outputPath = join6(projectDir, "trigger.config.ts");
5934
+ const outputPath = join7(projectDir, "trigger.config.ts");
5373
5935
  span.setAttributes({
5374
5936
  "cli.projectDir": projectDir,
5375
5937
  "cli.templatePath": templatePath,
@@ -5385,7 +5947,7 @@ async function writeConfigFile(dir, project, options, triggerDir) {
5385
5947
  outputPath,
5386
5948
  override: options.overrideConfig
5387
5949
  });
5388
- const relativePathToOutput = relative3(process.cwd(), outputPath);
5950
+ const relativePathToOutput = relative4(process.cwd(), outputPath);
5389
5951
  spnnr.stop(
5390
5952
  result.success ? `Config file created at ${relativePathToOutput}` : `Failed to create config file: ${result.error}`
5391
5953
  );
@@ -5467,12 +6029,14 @@ async function selectProject(apiClient2, dashboardUrl, projectRef) {
5467
6029
  // src/commands/logout.ts
5468
6030
  var LogoutCommandOptions = CommonCommandOptions;
5469
6031
  function configureLogoutCommand(program2) {
5470
- return commonOptions(program2.command("logout").description("Logout of Trigger.dev")).action(async (options) => {
5471
- await handleTelemetry(async () => {
5472
- await printInitialBanner(false);
5473
- await logoutCommand(options);
5474
- });
5475
- });
6032
+ return commonOptions(program2.command("logout").description("Logout of Trigger.dev")).action(
6033
+ async (options) => {
6034
+ await handleTelemetry(async () => {
6035
+ await printInitialBanner(false);
6036
+ await logoutCommand(options);
6037
+ });
6038
+ }
6039
+ );
5476
6040
  }
5477
6041
  async function logoutCommand(options) {
5478
6042
  return await wrapCommandAction("logoutCommand", LogoutCommandOptions, options, async (opts) => {
@@ -5482,11 +6046,46 @@ async function logoutCommand(options) {
5482
6046
  async function logout(options) {
5483
6047
  const config = readAuthConfigProfile(options.profile);
5484
6048
  if (!config?.accessToken) {
5485
- logger.info(`You are already logged out [${options.profile ?? "default"}]`);
6049
+ logger.info(`You are already logged out [${options.profile}]`);
6050
+ return;
6051
+ }
6052
+ deleteAuthConfigProfile(options.profile);
6053
+ logger.info(`Logged out of Trigger.dev [${options.profile}]`);
6054
+ }
6055
+
6056
+ // src/commands/list-profiles.ts
6057
+ import { log as log4, outro as outro5 } from "@clack/prompts";
6058
+ var ListProfilesOptions = CommonCommandOptions;
6059
+ function configureListProfilesCommand(program2) {
6060
+ return program2.command("list-profiles").description("List all of your CLI profiles").option(
6061
+ "-l, --log-level <level>",
6062
+ "The CLI log level to use (debug, info, log, warn, error, none). This does not effect the log level of your trigger.dev tasks.",
6063
+ "log"
6064
+ ).option("--skip-telemetry", "Opt-out of sending telemetry").action(async (options) => {
6065
+ await handleTelemetry(async () => {
6066
+ await printInitialBanner(true);
6067
+ await listProfilesCommand(options);
6068
+ });
6069
+ });
6070
+ }
6071
+ async function listProfilesCommand(options) {
6072
+ return await wrapCommandAction("listProfiles", ListProfilesOptions, options, async (opts) => {
6073
+ return await listProfiles(opts);
6074
+ });
6075
+ }
6076
+ async function listProfiles(options) {
6077
+ const authConfig = readAuthConfigFile();
6078
+ if (!authConfig) {
6079
+ logger.info("No profiles found");
5486
6080
  return;
5487
6081
  }
5488
- writeAuthConfigProfile({ ...config, accessToken: void 0, apiUrl: void 0 }, options.profile);
5489
- logger.info(`Logged out of Trigger.dev [${options.profile ?? "default"}]`);
6082
+ const profiles = Object.keys(authConfig);
6083
+ log4.message("Profiles:");
6084
+ for (const profile of profiles) {
6085
+ const profileConfig = authConfig[profile];
6086
+ log4.info(`${profile}${profileConfig?.apiUrl ? ` - ${chalkGrey(profileConfig.apiUrl)}` : ""}`);
6087
+ }
6088
+ outro5("Retrieve account info by running whoami --profile <profile>");
5490
6089
  }
5491
6090
 
5492
6091
  // src/cli/index.ts
@@ -5498,6 +6097,7 @@ configureDevCommand(program);
5498
6097
  configureDeployCommand(program);
5499
6098
  configureWhoamiCommand(program);
5500
6099
  configureLogoutCommand(program);
6100
+ configureListProfilesCommand(program);
5501
6101
 
5502
6102
  // src/index.ts
5503
6103
  var main = async () => {