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

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