trigger.dev 0.0.0-prerelease-20240418145424 → 0.0.0-v2-prerelease-20240524135558

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
@@ -777,31 +777,31 @@ var require_retry2 = __commonJS({
777
777
  import { Command as Command2 } from "commander";
778
778
 
779
779
  // src/commands/deploy.ts
780
- import { intro as intro3, log as log3, outro as outro3 } from "@clack/prompts";
780
+ import { intro as intro4, log as log5, outro as outro5 } from "@clack/prompts";
781
781
  import { depot } from "@depot/cli";
782
782
  import { context, trace as trace2 } from "@opentelemetry/api";
783
783
  import {
784
784
  TaskMetadataFailedToParseData,
785
785
  detectDependencyVersion,
786
- flattenAttributes as flattenAttributes2,
787
- recordSpanException as recordSpanException4
786
+ flattenAttributes as flattenAttributes3
788
787
  } from "@trigger.dev/core/v3";
789
- import chalk5 from "chalk";
788
+ import { recordSpanException as recordSpanException5 } from "@trigger.dev/core/v3/workers";
790
789
  import { Option as CommandOption } from "commander";
791
790
  import { build as build2 } from "esbuild";
792
791
  import { execa as execa2 } from "execa";
793
792
  import { createHash } from "node:crypto";
794
793
  import { readFileSync as readFileSync2 } from "node:fs";
795
794
  import { copyFile, mkdir, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
796
- import { dirname, join as join5, relative as relative3, posix } from "node:path";
795
+ import { dirname, join as join6, posix, relative as relative3 } from "node:path";
797
796
  import { setTimeout as setTimeout2 } from "node:timers/promises";
798
- import terminalLink from "terminal-link";
797
+ import terminalLink2 from "terminal-link";
799
798
  import invariant from "tiny-invariant";
800
799
  import { z as z4 } from "zod";
801
800
 
802
801
  // package.json
803
- var version = "0.0.0-prerelease-20240418145424";
802
+ var version = "3.0.0-beta.33";
804
803
  var dependencies = {
804
+ "@anatine/esbuild-decorators": "^0.2.19",
805
805
  "@clack/prompts": "^0.7.0",
806
806
  "@depot/cli": "0.0.1-cli.2.55.0",
807
807
  "@opentelemetry/api": "^1.8.0",
@@ -816,7 +816,7 @@ var dependencies = {
816
816
  "@opentelemetry/sdk-trace-base": "^1.22.0",
817
817
  "@opentelemetry/sdk-trace-node": "^1.22.0",
818
818
  "@opentelemetry/semantic-conventions": "^1.22.0",
819
- "@trigger.dev/core": "workspace:0.0.0-prerelease-20240418145424",
819
+ "@trigger.dev/core": "workspace:3.0.0-beta.33",
820
820
  "@types/degit": "^2.8.3",
821
821
  chalk: "^5.2.0",
822
822
  chokidar: "^3.5.3",
@@ -826,7 +826,7 @@ var dependencies = {
826
826
  dotenv: "^16.4.4",
827
827
  esbuild: "^0.19.11",
828
828
  evt: "^2.4.13",
829
- execa: "^8.0.0",
829
+ execa: "^9.1.0",
830
830
  "find-up": "^7.0.0",
831
831
  glob: "^10.3.10",
832
832
  "gradient-string": "^2.0.2",
@@ -837,7 +837,6 @@ var dependencies = {
837
837
  "mock-fs": "^5.2.0",
838
838
  nanoid: "^4.0.2",
839
839
  "node-fetch": "^3.3.0",
840
- "npm-check-updates": "^16.12.2",
841
840
  "object-hash": "^3.0.0",
842
841
  "p-debounce": "^4.0.0",
843
842
  "p-throttle": "^6.1.0",
@@ -856,7 +855,8 @@ var dependencies = {
856
855
  url: "^0.11.1",
857
856
  ws: "^8.12.0",
858
857
  zod: "3.22.3",
859
- "zod-validation-error": "^1.5.0"
858
+ "zod-validation-error": "^1.5.0",
859
+ typescript: "^5.4.0"
860
860
  };
861
861
  var package_default = {
862
862
  name: "trigger.dev",
@@ -948,7 +948,8 @@ import {
948
948
  InitializeDeploymentResponseBody,
949
949
  GetDeploymentResponseBody,
950
950
  GetProjectsResponseBody,
951
- GetProjectResponseBody
951
+ GetProjectResponseBody,
952
+ EnvironmentVariableResponseBody
952
953
  } from "@trigger.dev/core/v3";
953
954
  var CliApiClient = class {
954
955
  constructor(apiURL, accessToken) {
@@ -1052,6 +1053,23 @@ var CliApiClient = class {
1052
1053
  }
1053
1054
  );
1054
1055
  }
1056
+ async importEnvVars(projectRef, slug, params) {
1057
+ if (!this.accessToken) {
1058
+ throw new Error("importEnvVars: No access token");
1059
+ }
1060
+ return zodfetch(
1061
+ EnvironmentVariableResponseBody,
1062
+ `${this.apiURL}/api/v1/projects/${projectRef}/envvars/${slug}/import`,
1063
+ {
1064
+ method: "POST",
1065
+ headers: {
1066
+ Authorization: `Bearer ${this.accessToken}`,
1067
+ "Content-Type": "application/json"
1068
+ },
1069
+ body: JSON.stringify(params)
1070
+ }
1071
+ );
1072
+ }
1055
1073
  async initializeDeployment(body) {
1056
1074
  if (!this.accessToken) {
1057
1075
  throw new Error("initializeDeployment: No access token");
@@ -1141,7 +1159,8 @@ async function zodfetch(schema, url, requestInit) {
1141
1159
  }
1142
1160
 
1143
1161
  // src/cli/common.ts
1144
- import { flattenAttributes, recordSpanException } from "@trigger.dev/core/v3";
1162
+ import { flattenAttributes } from "@trigger.dev/core/v3";
1163
+ import { recordSpanException } from "@trigger.dev/core/v3/workers";
1145
1164
  import { z } from "zod";
1146
1165
 
1147
1166
  // src/telemetry/tracing.ts
@@ -1151,6 +1170,10 @@ import { Resource, detectResourcesSync, processDetectorSync } from "@opentelemet
1151
1170
  import { NodeTracerProvider, SimpleSpanProcessor } from "@opentelemetry/sdk-trace-node";
1152
1171
  import { FetchInstrumentation } from "@opentelemetry/instrumentation-fetch";
1153
1172
  import { DiagConsoleLogger, DiagLogLevel, diag, trace } from "@opentelemetry/api";
1173
+ import {
1174
+ SEMRESATTRS_SERVICE_NAME,
1175
+ SEMRESATTRS_SERVICE_VERSION
1176
+ } from "@opentelemetry/semantic-conventions";
1154
1177
  function initializeTracing() {
1155
1178
  if (process.argv.includes("--skip-telemetry") || process.env.TRIGGER_DEV_SKIP_TELEMETRY) {
1156
1179
  return;
@@ -1162,7 +1185,8 @@ function initializeTracing() {
1162
1185
  detectors: [processDetectorSync]
1163
1186
  }).merge(
1164
1187
  new Resource({
1165
- service: "trigger.dev cli v3"
1188
+ [SEMRESATTRS_SERVICE_NAME]: "trigger.dev cli v3",
1189
+ [SEMRESATTRS_SERVICE_VERSION]: version
1166
1190
  })
1167
1191
  );
1168
1192
  const traceProvider = new NodeTracerProvider({
@@ -1179,10 +1203,9 @@ function initializeTracing() {
1179
1203
  });
1180
1204
  const spanExporter = new OTLPTraceExporter({
1181
1205
  url: "https://otel.baselime.io/v1",
1182
- timeoutMillis: 500,
1206
+ timeoutMillis: 5e3,
1183
1207
  headers: {
1184
- "x-api-key": "e9f963244f8b092850d42e34a5339b2d5e68070b".split("").reverse().join("")
1185
- // this is a joke
1208
+ "x-api-key": "b6e0fbbaf8dc2524773d2152ae2e9eb5c7fbaa52"
1186
1209
  }
1187
1210
  });
1188
1211
  const spanProcessor = new SimpleSpanProcessor(spanExporter);
@@ -1195,7 +1218,7 @@ function initializeTracing() {
1195
1218
  }
1196
1219
  var provider = initializeTracing();
1197
1220
  function getTracer() {
1198
- return trace.getTracer("trigger.dev cli", version);
1221
+ return trace.getTracer("trigger.dev cli v3", version);
1199
1222
  }
1200
1223
 
1201
1224
  // src/cli/common.ts
@@ -1318,6 +1341,7 @@ var logger = new Logger();
1318
1341
  import { outro } from "@clack/prompts";
1319
1342
 
1320
1343
  // src/utilities/cliOutput.ts
1344
+ import { log } from "@clack/prompts";
1321
1345
  import chalk2 from "chalk";
1322
1346
  var green = "#4FFF54";
1323
1347
  var purple = "#735BF3";
@@ -1366,6 +1390,30 @@ function prettyPrintDate(date = /* @__PURE__ */ new Date()) {
1366
1390
  formattedDate += "." + ("00" + date.getMilliseconds()).slice(-3);
1367
1391
  return formattedDate;
1368
1392
  }
1393
+ function prettyError(header, body, footer) {
1394
+ const prefix = "Error: ";
1395
+ const indent = Array(prefix.length).fill(" ").join("");
1396
+ const spacing = "\n\n";
1397
+ const prettyPrefix = chalkError(prefix);
1398
+ const withIndents = (text3) => text3?.split("\n").map((line) => `${indent}${line}`).join("\n");
1399
+ const prettyBody = withIndents(body);
1400
+ const prettyFooter = withIndents(footer);
1401
+ log.error(
1402
+ `${prettyPrefix}${header}${prettyBody ? `${spacing}${prettyBody}` : ""}${prettyFooter ? `${spacing}${prettyFooter}` : ""}`
1403
+ );
1404
+ }
1405
+ function prettyWarning(header, body, footer) {
1406
+ const prefix = "Warning: ";
1407
+ const indent = Array(prefix.length).fill(" ").join("");
1408
+ const spacing = "\n\n";
1409
+ const prettyPrefix = chalkWarning(prefix);
1410
+ const withIndents = (text3) => text3?.split("\n").map((line) => `${indent}${line}`).join("\n");
1411
+ const prettyBody = withIndents(body);
1412
+ const prettyFooter = withIndents(footer);
1413
+ log.warn(
1414
+ `${prettyPrefix}${header}${prettyBody ? `${spacing}${prettyBody}` : ""}${prettyFooter ? `${spacing}${prettyFooter}` : ""}`
1415
+ );
1416
+ }
1369
1417
 
1370
1418
  // src/cli/common.ts
1371
1419
  var CommonCommandOptions = z.object({
@@ -1474,6 +1522,9 @@ async function createFile(path7, contents) {
1474
1522
  async function pathExists(path7) {
1475
1523
  return fsSync.existsSync(path7);
1476
1524
  }
1525
+ async function removeFile(path7) {
1526
+ await fsModule.unlink(path7);
1527
+ }
1477
1528
  async function readFile(path7) {
1478
1529
  return await fsModule.readFile(path7, "utf8");
1479
1530
  }
@@ -1481,8 +1532,8 @@ async function readJSONFile(path7) {
1481
1532
  const fileContents = await fsModule.readFile(path7, "utf8");
1482
1533
  return JSON.parse(fileContents);
1483
1534
  }
1484
- async function writeJSONFile(path7, json) {
1485
- await writeFile(path7, JSON.stringify(json), "utf8");
1535
+ async function writeJSONFile(path7, json, pretty = false) {
1536
+ await writeFile(path7, JSON.stringify(json, void 0, pretty ? 2 : void 0), "utf8");
1486
1537
  }
1487
1538
  function readJSONFileSync(path7) {
1488
1539
  const fileContents = fsSync.readFileSync(path7, "utf8");
@@ -1513,14 +1564,23 @@ function createTaskFileImports(taskFiles) {
1513
1564
  async function gatherTaskFiles(config) {
1514
1565
  const taskFiles = [];
1515
1566
  for (const triggerDir of config.triggerDirectories) {
1516
- const files = await fs2.promises.readdir(triggerDir, { withFileTypes: true });
1517
- for (const file of files) {
1518
- if (!file.isFile())
1519
- continue;
1567
+ const files = await gatherTaskFilesFromDir(triggerDir, triggerDir, config);
1568
+ taskFiles.push(...files);
1569
+ }
1570
+ return taskFiles;
1571
+ }
1572
+ async function gatherTaskFilesFromDir(dirPath, triggerDir, config) {
1573
+ const taskFiles = [];
1574
+ const files = await fs2.promises.readdir(dirPath, { withFileTypes: true });
1575
+ for (const file of files) {
1576
+ if (!file.isFile()) {
1577
+ const fullPath = join(dirPath, file.name);
1578
+ taskFiles.push(...await gatherTaskFilesFromDir(fullPath, triggerDir, config));
1579
+ } else {
1520
1580
  if (!file.name.endsWith(".js") && !file.name.endsWith(".ts") && !file.name.endsWith(".jsx") && !file.name.endsWith(".tsx")) {
1521
1581
  continue;
1522
1582
  }
1523
- const fullPath = join(triggerDir, file.name);
1583
+ const fullPath = join(dirPath, file.name);
1524
1584
  const filePath = relative(config.projectDir, fullPath);
1525
1585
  const importName = filePath.replace(/\..+$/, "").replace(/[^a-zA-Z0-9_$]/g, "_");
1526
1586
  const importPath = filePath.replace(/\\/g, "/");
@@ -1540,9 +1600,12 @@ async function getTriggerDirectories(dirPath) {
1540
1600
  const entries = await fs2.promises.readdir(dirPath, { withFileTypes: true });
1541
1601
  const triggerDirectories = [];
1542
1602
  for (const entry of entries) {
1543
- if (!entry.isDirectory() || IGNORED_DIRS.includes(entry.name))
1603
+ if (!entry.isDirectory() || IGNORED_DIRS.includes(entry.name) || entry.name.startsWith("."))
1544
1604
  continue;
1545
1605
  const fullPath = join(dirPath, entry.name);
1606
+ if (fullPath.endsWith("app/api/trigger")) {
1607
+ continue;
1608
+ }
1546
1609
  if (entry.name === "trigger") {
1547
1610
  triggerDirectories.push(fullPath);
1548
1611
  }
@@ -1553,6 +1616,7 @@ async function getTriggerDirectories(dirPath) {
1553
1616
 
1554
1617
  // src/utilities/configFiles.ts
1555
1618
  import { build } from "esbuild";
1619
+ import { esbuildDecorators } from "@anatine/esbuild-decorators";
1556
1620
  function getGlobalConfigFolderPath() {
1557
1621
  const configDir = mod_esm_default("trigger").config();
1558
1622
  return configDir;
@@ -1616,16 +1680,25 @@ async function getConfigPath(dir, fileName) {
1616
1680
  });
1617
1681
  return await findUp(fileName ? [fileName] : CONFIG_FILES, { cwd: dir });
1618
1682
  }
1683
+ async function findFilePath(dir, fileName) {
1684
+ const result = await findUp([fileName], { cwd: dir });
1685
+ logger.debug("Searched for the file", {
1686
+ dir,
1687
+ fileName,
1688
+ result
1689
+ });
1690
+ return result;
1691
+ }
1619
1692
  async function readConfig(dir, options) {
1620
1693
  const absoluteDir = path2.resolve(process.cwd(), dir);
1621
1694
  const configPath = await getConfigPath(dir, options?.configFile);
1622
1695
  if (!configPath) {
1623
1696
  if (options?.projectRef) {
1624
- const rawConfig2 = await normalizeConfig({ project: options.projectRef });
1625
- const config2 = Config.parse(rawConfig2);
1697
+ const rawConfig = await normalizeConfig({ project: options.projectRef });
1698
+ const config = Config.parse(rawConfig);
1626
1699
  return {
1627
1700
  status: "in-memory",
1628
- config: await resolveConfig(absoluteDir, config2)
1701
+ config: await resolveConfig(absoluteDir, config)
1629
1702
  };
1630
1703
  } else {
1631
1704
  throw new Error(`Config file not found in ${absoluteDir} or any parent directory.`);
@@ -1649,25 +1722,49 @@ async function readConfig(dir, options) {
1649
1722
  platform: "node",
1650
1723
  target: ["es2018", "node18"],
1651
1724
  outfile: builtConfigFilePath,
1652
- logLevel: "silent"
1725
+ logLevel: "silent",
1726
+ plugins: [
1727
+ esbuildDecorators({
1728
+ cwd: absoluteDir,
1729
+ tsx: false,
1730
+ force: false
1731
+ }),
1732
+ {
1733
+ name: "native-node-modules",
1734
+ setup(build3) {
1735
+ const opts = build3.initialOptions;
1736
+ opts.loader = opts.loader || {};
1737
+ opts.loader[".node"] = "copy";
1738
+ }
1739
+ }
1740
+ ]
1653
1741
  });
1654
- const userConfigModule = await import(builtConfigFileHref);
1655
- const rawConfig = await normalizeConfig(
1656
- userConfigModule?.config,
1657
- options?.projectRef ? { project: options?.projectRef } : void 0
1658
- );
1659
- const config = Config.parse(rawConfig);
1660
- return {
1661
- status: "file",
1662
- config: await resolveConfig(absoluteDir, config),
1663
- path: configPath
1664
- };
1742
+ try {
1743
+ const userConfigModule = await import(builtConfigFileHref);
1744
+ const rawConfig = await normalizeConfig(
1745
+ userConfigModule?.config,
1746
+ options?.projectRef ? { project: options?.projectRef } : void 0
1747
+ );
1748
+ const config = Config.parse(rawConfig);
1749
+ return {
1750
+ status: "file",
1751
+ config: await resolveConfig(absoluteDir, config),
1752
+ path: configPath,
1753
+ module: userConfigModule
1754
+ };
1755
+ } catch (error) {
1756
+ return {
1757
+ status: "error",
1758
+ error
1759
+ };
1760
+ }
1665
1761
  }
1666
1762
  async function resolveConfig(path7, config) {
1667
1763
  if (!config.triggerDirectories) {
1668
1764
  config.triggerDirectories = await findTriggerDirectories(path7);
1669
1765
  }
1670
1766
  config.triggerDirectories = resolveTriggerDirectories(config.triggerDirectories);
1767
+ logger.debug("Resolved trigger directories", { triggerDirectories: config.triggerDirectories });
1671
1768
  if (!config.triggerUrl) {
1672
1769
  config.triggerUrl = CLOUD_API_URL;
1673
1770
  }
@@ -1675,7 +1772,7 @@ async function resolveConfig(path7, config) {
1675
1772
  config.projectDir = path7;
1676
1773
  }
1677
1774
  if (!config.tsconfigPath) {
1678
- config.tsconfigPath = await getConfigPath(path7, "tsconfig.json");
1775
+ config.tsconfigPath = await findFilePath(path7, "tsconfig.json");
1679
1776
  }
1680
1777
  return config;
1681
1778
  }
@@ -1701,29 +1798,29 @@ function getVersion() {
1701
1798
  }
1702
1799
 
1703
1800
  // src/utilities/windows.ts
1704
- import { log, spinner as clackSpinner } from "@clack/prompts";
1801
+ import { log as log2, spinner as clackSpinner } from "@clack/prompts";
1705
1802
  var isWindows = process.platform === "win32";
1706
1803
  function escapeImportPath(path7) {
1707
1804
  return isWindows ? path7.replaceAll("\\", "\\\\") : path7;
1708
1805
  }
1709
1806
  var ballmerSpinner = () => ({
1710
1807
  start: (msg) => {
1711
- log.step(msg ?? "");
1808
+ log2.step(msg ?? "");
1712
1809
  },
1713
1810
  stop: (msg, code) => {
1714
- log.message(msg ?? "");
1811
+ log2.message(msg ?? "");
1715
1812
  },
1716
1813
  message: (msg) => {
1717
- log.message(msg ?? "");
1814
+ log2.message(msg ?? "");
1718
1815
  }
1719
1816
  });
1720
1817
  var spinner = () => isWindows ? ballmerSpinner() : clackSpinner();
1721
1818
 
1722
1819
  // src/utilities/initialBanner.ts
1723
1820
  async function printInitialBanner(performUpdateCheck = true) {
1724
- const packageVersion = getVersion();
1821
+ const cliVersion = getVersion();
1725
1822
  const text3 = `
1726
- ${logo()} ${chalkGrey(`(${packageVersion})`)}
1823
+ ${logo()} ${chalkGrey(`(${cliVersion})`)}
1727
1824
  `;
1728
1825
  logger.info(text3);
1729
1826
  let maybeNewVersion;
@@ -1733,7 +1830,7 @@ ${logo()} ${chalkGrey(`(${packageVersion})`)}
1733
1830
  maybeNewVersion = await updateCheck();
1734
1831
  if (maybeNewVersion !== void 0) {
1735
1832
  loadingSpinner.stop(`Update available ${chalk3.green(maybeNewVersion)}`);
1736
- const currentMajor = parseInt(packageVersion.split(".")[0]);
1833
+ const currentMajor = parseInt(cliVersion.split(".")[0]);
1737
1834
  const newMajor = parseInt(maybeNewVersion.split(".")[0]);
1738
1835
  if (newMajor > currentMajor) {
1739
1836
  logger.warn(
@@ -1748,18 +1845,26 @@ After installation, run Trigger.dev with \`npx trigger.dev\`.`
1748
1845
  }
1749
1846
  }
1750
1847
  async function printStandloneInitialBanner(performUpdateCheck = true) {
1751
- const packageVersion = getVersion();
1752
- logger.log(`
1753
- ${logo()} ${chalkGrey("(v3 Developer Preview)")}`);
1848
+ const cliVersion = getVersion();
1754
1849
  if (performUpdateCheck) {
1755
1850
  const maybeNewVersion = await updateCheck();
1756
1851
  if (maybeNewVersion !== void 0) {
1757
- logger.log(`Update available ${chalk3.green(maybeNewVersion)}`);
1852
+ logger.log(`
1853
+ ${logo()} ${chalkGrey(`(${cliVersion} -> ${chalk3.green(maybeNewVersion)})`)}`);
1854
+ } else {
1855
+ logger.log(`
1856
+ ${logo()} ${chalkGrey(`(${cliVersion})`)}`);
1758
1857
  }
1858
+ } else {
1859
+ logger.log(`
1860
+ ${logo()} ${chalkGrey(`(${cliVersion})`)}`);
1759
1861
  }
1760
1862
  logger.log(`${chalkGrey("-".repeat(54))}`);
1761
1863
  }
1762
- function printDevBanner() {
1864
+ function printDevBanner(printTopBorder = true) {
1865
+ if (printTopBorder) {
1866
+ logger.log(chalkGrey("-".repeat(54)));
1867
+ }
1763
1868
  logger.log(
1764
1869
  `${chalkGrey("Key:")} ${chalkWorker("Version")} ${chalkGrey("|")} ${chalkTask(
1765
1870
  "Task"
@@ -1771,7 +1876,7 @@ async function doUpdateCheck() {
1771
1876
  let update = null;
1772
1877
  try {
1773
1878
  update = await checkForUpdate(package_default, {
1774
- distTag: package_default.version.startsWith("0.0.0") ? "beta" : "latest"
1879
+ distTag: package_default.version.startsWith("3.0.0-beta") ? "beta" : "latest"
1775
1880
  });
1776
1881
  } catch (err) {
1777
1882
  }
@@ -1809,14 +1914,27 @@ function stripWorkspaceFromVersion(version2) {
1809
1914
  return version2.replace(/^workspace:/, "");
1810
1915
  }
1811
1916
  function parsePackageName(packageSpecifier) {
1812
- const parts = packageSpecifier.split("@");
1813
- if (parts.length === 1 && typeof parts[0] === "string") {
1814
- return { name: parts[0] };
1917
+ let name;
1918
+ let version2;
1919
+ if (packageSpecifier.startsWith("@")) {
1920
+ const atIndex = packageSpecifier.indexOf("@", 1);
1921
+ if (atIndex !== -1) {
1922
+ name = packageSpecifier.slice(0, atIndex);
1923
+ version2 = packageSpecifier.slice(atIndex + 1);
1924
+ } else {
1925
+ name = packageSpecifier;
1926
+ }
1927
+ } else {
1928
+ const [packageName, packageVersion] = packageSpecifier.split("@");
1929
+ if (typeof packageName === "string") {
1930
+ name = packageName;
1931
+ }
1932
+ version2 = packageVersion;
1815
1933
  }
1816
- if (parts.length === 2 && typeof parts[0] === "string" && typeof parts[1] === "string") {
1817
- return { name: parts[0], version: parts[1] };
1934
+ if (!name) {
1935
+ return { name: packageSpecifier };
1818
1936
  }
1819
- return { name: packageSpecifier };
1937
+ return { name, version: version2 };
1820
1938
  }
1821
1939
  async function setPackageJsonDeps(path7, deps) {
1822
1940
  try {
@@ -1840,8 +1958,8 @@ async function setPackageJsonDeps(path7, deps) {
1840
1958
  }
1841
1959
 
1842
1960
  // src/commands/login.ts
1843
- import { intro as intro2, log as log2, outro as outro2, select } from "@clack/prompts";
1844
- import { recordSpanException as recordSpanException3 } from "@trigger.dev/core/v3";
1961
+ import { intro as intro2, log as log3, outro as outro3, select } from "@clack/prompts";
1962
+ import { recordSpanException as recordSpanException3 } from "@trigger.dev/core/v3/workers";
1845
1963
 
1846
1964
  // ../../node_modules/.pnpm/open@10.0.3/node_modules/open/index.js
1847
1965
  import process6 from "node:process";
@@ -2211,14 +2329,14 @@ var baseOpen = async (options) => {
2211
2329
  }
2212
2330
  const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
2213
2331
  if (options.wait) {
2214
- return new Promise((resolve4, reject) => {
2332
+ return new Promise((resolve6, reject) => {
2215
2333
  subprocess.once("error", reject);
2216
2334
  subprocess.once("close", (exitCode) => {
2217
2335
  if (!options.allowNonzeroExitCode && exitCode > 0) {
2218
2336
  reject(new Error(`Exited with code ${exitCode}`));
2219
2337
  return;
2220
2338
  }
2221
- resolve4(subprocess);
2339
+ resolve6(subprocess);
2222
2340
  });
2223
2341
  });
2224
2342
  }
@@ -2335,7 +2453,7 @@ var decorateErrorWithCounts = (error, attemptNumber, options) => {
2335
2453
  return error;
2336
2454
  };
2337
2455
  async function pRetry(input, options) {
2338
- return new Promise((resolve4, reject) => {
2456
+ return new Promise((resolve6, reject) => {
2339
2457
  options = {
2340
2458
  onFailedAttempt() {
2341
2459
  },
@@ -2358,7 +2476,7 @@ async function pRetry(input, options) {
2358
2476
  try {
2359
2477
  const result = await input(attemptNumber);
2360
2478
  cleanUp();
2361
- resolve4(result);
2479
+ resolve6(result);
2362
2480
  } catch (error) {
2363
2481
  try {
2364
2482
  if (!(error instanceof Error)) {
@@ -2388,10 +2506,10 @@ async function pRetry(input, options) {
2388
2506
  import { z as z3 } from "zod";
2389
2507
 
2390
2508
  // src/commands/whoami.ts
2391
- import { intro, note } from "@clack/prompts";
2509
+ import { intro, note, outro as outro2 } from "@clack/prompts";
2392
2510
 
2393
2511
  // src/utilities/session.ts
2394
- import { recordSpanException as recordSpanException2 } from "@trigger.dev/core/v3";
2512
+ import { recordSpanException as recordSpanException2 } from "@trigger.dev/core/v3/workers";
2395
2513
  var tracer2 = getTracer();
2396
2514
  async function isLoggedIn(profile = "default") {
2397
2515
  return await tracer2.startActiveSpan("isLoggedIn", async (span) => {
@@ -2473,9 +2591,16 @@ async function whoAmI(options, embedded = false) {
2473
2591
  if (authentication.error === "fetch failed") {
2474
2592
  loadingSpinner.stop("Fetch failed. Platform down?");
2475
2593
  } else {
2476
- loadingSpinner.stop(
2477
- `You must login first. Use \`trigger.dev login --profile ${options?.profile ?? "default"}\` to login.`
2478
- );
2594
+ if (embedded) {
2595
+ loadingSpinner.stop(
2596
+ `Failed to check account details. You may want to run \`trigger.dev logout --profile ${options?.profile ?? "default"}\` and try again.`
2597
+ );
2598
+ } else {
2599
+ loadingSpinner.stop(
2600
+ `You must login first. Use \`trigger.dev login --profile ${options?.profile ?? "default"}\` to login.`
2601
+ );
2602
+ outro2("Whoami failed");
2603
+ }
2479
2604
  }
2480
2605
  return {
2481
2606
  success: false,
@@ -2571,10 +2696,18 @@ async function login(options) {
2571
2696
  skipTelemetry: !span.isRecording(),
2572
2697
  logLevel: logger.loggerLevel
2573
2698
  },
2574
- opts.embedded
2699
+ true
2575
2700
  );
2576
2701
  if (!whoAmIResult.success) {
2577
- throw new Error(whoAmIResult.error);
2702
+ prettyError("Unable to validate existing personal access token", whoAmIResult.error);
2703
+ if (!opts.embedded) {
2704
+ outro3(
2705
+ `Login failed using stored token. To fix, first logout using \`trigger.dev logout${options?.profile ? ` --profile ${options.profile}` : ""}\` and then try again.`
2706
+ );
2707
+ throw new SkipLoggingError(whoAmIResult.error);
2708
+ } else {
2709
+ throw new Error(whoAmIResult.error);
2710
+ }
2578
2711
  } else {
2579
2712
  if (!opts.embedded) {
2580
2713
  const continueOption = await select({
@@ -2592,7 +2725,7 @@ async function login(options) {
2592
2725
  initialValue: false
2593
2726
  });
2594
2727
  if (continueOption !== true) {
2595
- outro2("Already logged in");
2728
+ outro3("Already logged in");
2596
2729
  span.setAttributes({
2597
2730
  "cli.userId": whoAmIResult.data.userId,
2598
2731
  "cli.email": whoAmIResult.data.email,
@@ -2633,11 +2766,11 @@ async function login(options) {
2633
2766
  }
2634
2767
  }
2635
2768
  if (opts.embedded) {
2636
- log2.step("You must login to continue.");
2769
+ log3.step("You must login to continue.");
2637
2770
  }
2638
2771
  const apiClient2 = new CliApiClient(authConfig?.apiUrl ?? opts.defaultApiUrl);
2639
2772
  const authorizationCodeResult = await createAuthorizationCode(apiClient2);
2640
- log2.step(
2773
+ log3.step(
2641
2774
  `Please visit the following URL to login:
2642
2775
  ${chalkLink(authorizationCodeResult.url)}`
2643
2776
  );
@@ -2671,9 +2804,9 @@ ${chalkLink(authorizationCodeResult.url)}`
2671
2804
  throw new Error(whoAmIResult.error);
2672
2805
  }
2673
2806
  if (opts.embedded) {
2674
- log2.step("Logged in successfully");
2807
+ log3.step("Logged in successfully");
2675
2808
  } else {
2676
- outro2("Logged in successfully");
2809
+ outro3("Logged in successfully");
2677
2810
  }
2678
2811
  span.end();
2679
2812
  return {
@@ -2690,7 +2823,7 @@ ${chalkLink(authorizationCodeResult.url)}`
2690
2823
  } catch (e) {
2691
2824
  getPersonalAccessTokenSpinner.stop(`Failed to get access token`);
2692
2825
  if (e instanceof AbortError) {
2693
- log2.error(e.message);
2826
+ log3.error(e.message);
2694
2827
  }
2695
2828
  recordSpanException3(span, e);
2696
2829
  span.end();
@@ -2740,7 +2873,7 @@ async function createAuthorizationCode(apiClient2) {
2740
2873
  return await tracer.startActiveSpan("createAuthorizationCode", async (span) => {
2741
2874
  try {
2742
2875
  const createAuthCodeSpinner = spinner();
2743
- createAuthCodeSpinner.start("Creating authorition code");
2876
+ createAuthCodeSpinner.start("Creating authorization code");
2744
2877
  const authorizationCodeResult = await apiClient2.createAuthorizationCode();
2745
2878
  if (!authorizationCodeResult.success) {
2746
2879
  createAuthCodeSpinner.stop(
@@ -2764,18 +2897,45 @@ ${authorizationCodeResult.error}`
2764
2897
  }
2765
2898
 
2766
2899
  // src/commands/deploy.ts
2900
+ import { esbuildDecorators as esbuildDecorators2 } from "@anatine/esbuild-decorators";
2767
2901
  import { Glob } from "glob";
2768
2902
 
2769
2903
  // src/utilities/build.ts
2770
2904
  import { readFileSync } from "node:fs";
2771
2905
  import { extname, isAbsolute } from "node:path";
2772
2906
  import tsConfigPaths from "tsconfig-paths";
2907
+ function mockServerOnlyPlugin() {
2908
+ return {
2909
+ name: "trigger-mock-server-only",
2910
+ setup(build3) {
2911
+ build3.onResolve({ filter: /server-only/ }, (args) => {
2912
+ if (args.path !== "server-only") {
2913
+ return void 0;
2914
+ }
2915
+ logger.debug(`[trigger-mock-server-only] Bundling ${args.path}`, {
2916
+ ...args
2917
+ });
2918
+ return {
2919
+ path: args.path,
2920
+ external: false,
2921
+ namespace: "server-only-mock"
2922
+ };
2923
+ });
2924
+ build3.onLoad({ filter: /server-only/, namespace: "server-only-mock" }, (args) => {
2925
+ return {
2926
+ contents: `export default true;`,
2927
+ loader: "js"
2928
+ };
2929
+ });
2930
+ }
2931
+ };
2932
+ }
2773
2933
  function bundleTriggerDevCore(buildIdentifier, tsconfigPath) {
2774
2934
  return {
2775
2935
  name: "trigger-bundle-core",
2776
2936
  setup(build3) {
2777
2937
  build3.onResolve({ filter: /.*/ }, (args) => {
2778
- if (args.path !== "@trigger.dev/core/v3") {
2938
+ if (!args.path.startsWith("@trigger.dev/core/v3")) {
2779
2939
  return void 0;
2780
2940
  }
2781
2941
  const triggerSdkPath = __require.resolve("@trigger.dev/sdk/v3", { paths: [process.cwd()] });
@@ -2783,17 +2943,14 @@ function bundleTriggerDevCore(buildIdentifier, tsconfigPath) {
2783
2943
  ...args,
2784
2944
  triggerSdkPath
2785
2945
  });
2786
- const resolvedPath = __require.resolve("@trigger.dev/core/v3", {
2946
+ const resolvedPath = __require.resolve(args.path, {
2787
2947
  paths: [triggerSdkPath]
2788
2948
  });
2789
- logger.debug(
2790
- `[${buildIdentifier}][trigger-bundle-core] Externalizing @trigger.dev/core/v3`,
2791
- {
2792
- ...args,
2793
- triggerSdkPath,
2794
- resolvedPath
2795
- }
2796
- );
2949
+ logger.debug(`[${buildIdentifier}][trigger-bundle-core] Externalizing ${args.path}`, {
2950
+ ...args,
2951
+ triggerSdkPath,
2952
+ resolvedPath
2953
+ });
2797
2954
  return {
2798
2955
  path: resolvedPath,
2799
2956
  external: false
@@ -2862,7 +3019,7 @@ function bundleDependenciesPlugin(buildIdentifier, dependenciesToBundle, tsconfi
2862
3019
  return void 0;
2863
3020
  }
2864
3021
  }
2865
- logger.ignore(`[${buildIdentifier}] Externalizing ${args.path}`, {
3022
+ logger.debug(`[${buildIdentifier}] Externalizing ${args.path}`, {
2866
3023
  ...args
2867
3024
  });
2868
3025
  return {
@@ -2954,6 +3111,20 @@ function getLoaderForFile(file) {
2954
3111
  import chalk4 from "chalk";
2955
3112
  import { relative as relative2 } from "node:path";
2956
3113
  import { groupTaskMetadataIssuesByTask } from "@trigger.dev/core/v3";
3114
+ import terminalLink from "terminal-link";
3115
+
3116
+ // src/utilities/links.ts
3117
+ var docs = {
3118
+ config: {
3119
+ home: "https://trigger.dev/docs/v3/trigger-config",
3120
+ esm: "https://trigger.dev/docs/v3/trigger-config#esm-only-packages",
3121
+ prisma: "https://trigger.dev/docs/v3/trigger-config#prisma-and-other-generators",
3122
+ additionalPackages: "https://trigger.dev/docs/v3/trigger-config#prisma-and-other-generators"
3123
+ }
3124
+ };
3125
+ var getInTouch = "https://trigger.dev/contact";
3126
+
3127
+ // src/utilities/deployErrors.ts
2957
3128
  function errorIsErrorLike(error) {
2958
3129
  return error instanceof Error || typeof error === "object" && error !== null && "message" in error;
2959
3130
  }
@@ -3019,6 +3190,10 @@ ${chalkGrey("\u25CB")} Dynamically import the module in your code: ${chalkGrey(
3019
3190
  `
3020
3191
  );
3021
3192
  }
3193
+ logger.log(
3194
+ `${chalkGrey("\u25CB")} For more info see the ${terminalLink("relevant docs", docs.config.esm)}.
3195
+ `
3196
+ );
3022
3197
  }
3023
3198
  function parseNpmInstallError(error) {
3024
3199
  if (typeof error === "string") {
@@ -3081,25 +3256,19 @@ ${chalkError("X Error:")} Failed to start. The following ${zodIssues.length ===
3081
3256
  }
3082
3257
  }
3083
3258
 
3084
- // src/utilities/safeJsonParse.ts
3085
- function safeJsonParse(json) {
3086
- if (!json) {
3087
- return void 0;
3088
- }
3089
- try {
3090
- return JSON.parse(json);
3091
- } catch {
3092
- return void 0;
3093
- }
3094
- }
3095
-
3096
3259
  // src/utilities/javascriptProject.ts
3097
3260
  import { $ } from "execa";
3098
3261
  import { join as join4 } from "node:path";
3099
3262
 
3100
3263
  // src/utilities/getUserPackageManager.ts
3101
3264
  import { findUp as findUp2 } from "find-up";
3265
+ import { basename } from "path";
3102
3266
  async function getUserPackageManager(path7) {
3267
+ const packageManager = await detectPackageManager(path7);
3268
+ logger.debug("Detected package manager", { packageManager });
3269
+ return packageManager;
3270
+ }
3271
+ async function detectPackageManager(path7) {
3103
3272
  try {
3104
3273
  return await detectPackageManagerFromArtifacts(path7);
3105
3274
  } catch (error) {
@@ -3121,63 +3290,39 @@ function detectPackageManagerFromCurrentCommand() {
3121
3290
  }
3122
3291
  }
3123
3292
  async function detectPackageManagerFromArtifacts(path7) {
3124
- const packageFiles = [
3125
- { name: "yarn.lock", pm: "yarn" },
3126
- { name: "pnpm-lock.yaml", pm: "pnpm" },
3127
- { name: "package-lock.json", pm: "npm" },
3128
- { name: "npm-shrinkwrap.json", pm: "npm" }
3129
- ];
3130
- for (const { name, pm } of packageFiles) {
3131
- const foundPath = await findUp2(name, { cwd: path7 });
3132
- if (typeof foundPath === "string") {
3133
- return pm;
3134
- }
3293
+ const artifacts = {
3294
+ yarn: "yarn.lock",
3295
+ pnpm: "pnpm-lock.yaml",
3296
+ npm: "package-lock.json",
3297
+ npmShrinkwrap: "npm-shrinkwrap.json"
3298
+ };
3299
+ const foundPath = await findUp2(Object.values(artifacts), { cwd: path7 });
3300
+ if (!foundPath) {
3301
+ throw new Error("Could not detect package manager from artifacts");
3302
+ }
3303
+ logger.debug("Found path from package manager artifacts", { foundPath });
3304
+ switch (basename(foundPath)) {
3305
+ case artifacts.yarn:
3306
+ return "yarn";
3307
+ case artifacts.pnpm:
3308
+ return "pnpm";
3309
+ case artifacts.npm:
3310
+ case artifacts.npmShrinkwrap:
3311
+ return "npm";
3312
+ default:
3313
+ throw new Error(`Unhandled package manager detection path: ${foundPath}`);
3135
3314
  }
3136
- throw new Error("Could not detect package manager from artifacts");
3315
+ }
3316
+
3317
+ // src/utilities/assertExhaustive.ts
3318
+ function assertExhaustive(x) {
3319
+ throw new Error("Unexpected object: " + x);
3137
3320
  }
3138
3321
 
3139
3322
  // src/utilities/javascriptProject.ts
3140
- var BuiltInModules = /* @__PURE__ */ new Set([
3141
- "assert",
3142
- "async_hooks",
3143
- "buffer",
3144
- "child_process",
3145
- "cluster",
3146
- "console",
3147
- "constants",
3148
- "crypto",
3149
- "dgram",
3150
- "dns",
3151
- "domain",
3152
- "events",
3153
- "fs",
3154
- "http",
3155
- "http2",
3156
- "https",
3157
- "inspector",
3158
- "module",
3159
- "net",
3160
- "os",
3161
- "path",
3162
- "perf_hooks",
3163
- "process",
3164
- "punycode",
3165
- "querystring",
3166
- "readline",
3167
- "repl",
3168
- "stream",
3169
- "string_decoder",
3170
- "timers",
3171
- "tls",
3172
- "trace_events",
3173
- "tty",
3174
- "url",
3175
- "util",
3176
- "v8",
3177
- "vm",
3178
- "worker_threads",
3179
- "zlib"
3180
- ]);
3323
+ import { builtinModules } from "node:module";
3324
+ import { recordSpanException as recordSpanException4 } from "@trigger.dev/core/v3/otel";
3325
+ import { flattenAttributes as flattenAttributes2 } from "@trigger.dev/core/v3";
3181
3326
  var JavascriptProject = class {
3182
3327
  constructor(projectPath) {
3183
3328
  this.projectPath = projectPath;
@@ -3192,36 +3337,107 @@ var JavascriptProject = class {
3192
3337
  }
3193
3338
  get scripts() {
3194
3339
  return {
3195
- postinstall: this.packageJson.scripts?.postinstall
3340
+ postinstall: this.packageJson.scripts?.postinstall ?? ""
3196
3341
  };
3197
3342
  }
3343
+ async install() {
3344
+ const command = await this.#getCommand();
3345
+ try {
3346
+ await command.installDependencies({
3347
+ cwd: this.projectPath
3348
+ });
3349
+ } catch (error) {
3350
+ logger.debug(`Failed to install dependencies using ${command.name}`, {
3351
+ error
3352
+ });
3353
+ }
3354
+ }
3355
+ async resolveAll(packageNames, options) {
3356
+ return tracer.startActiveSpan("JavascriptProject.resolveAll", async (span) => {
3357
+ const externalPackages = packageNames.filter((packageName) => !isBuiltInModule(packageName));
3358
+ const opts = { allowDev: false, ...options };
3359
+ const command = await this.#getCommand();
3360
+ span.setAttributes({
3361
+ externalPackages,
3362
+ packageManager: command.name
3363
+ });
3364
+ try {
3365
+ const versions = await command.resolveDependencyVersions(externalPackages, {
3366
+ cwd: this.projectPath
3367
+ });
3368
+ if (versions) {
3369
+ logger.debug(`Resolved [${externalPackages.join(", ")}] version using ${command.name}`, {
3370
+ versions
3371
+ });
3372
+ span.setAttributes({
3373
+ ...flattenAttributes2(versions, "versions")
3374
+ });
3375
+ }
3376
+ const missingPackages = externalPackages.filter((packageName) => !versions[packageName]);
3377
+ const missingPackageVersions = {};
3378
+ for (const packageName of missingPackages) {
3379
+ const packageJsonVersion = this.packageJson.dependencies?.[packageName];
3380
+ if (typeof packageJsonVersion === "string") {
3381
+ logger.debug(`Resolved ${packageName} version using package.json`, {
3382
+ packageJsonVersion
3383
+ });
3384
+ missingPackageVersions[packageName] = packageJsonVersion;
3385
+ }
3386
+ if (opts.allowDev) {
3387
+ const devPackageJsonVersion = this.packageJson.devDependencies?.[packageName];
3388
+ if (typeof devPackageJsonVersion === "string") {
3389
+ logger.debug(`Resolved ${packageName} version using devDependencies`, {
3390
+ devPackageJsonVersion
3391
+ });
3392
+ missingPackageVersions[packageName] = devPackageJsonVersion;
3393
+ }
3394
+ }
3395
+ }
3396
+ span.setAttributes({
3397
+ ...flattenAttributes2(missingPackageVersions, "missingPackageVersions"),
3398
+ missingPackages
3399
+ });
3400
+ span.end();
3401
+ return { ...versions, ...missingPackageVersions };
3402
+ } catch (error) {
3403
+ recordSpanException4(span, error);
3404
+ span.end();
3405
+ logger.debug(`Failed to resolve dependency versions using ${command.name}`, {
3406
+ packageNames,
3407
+ error
3408
+ });
3409
+ return {};
3410
+ }
3411
+ });
3412
+ }
3198
3413
  async resolve(packageName, options) {
3199
- if (BuiltInModules.has(packageName)) {
3414
+ if (isBuiltInModule(packageName)) {
3200
3415
  return void 0;
3201
3416
  }
3202
- if (!this._packageManager) {
3203
- this._packageManager = await getUserPackageManager(this.projectPath);
3204
- }
3205
- const packageManager = this._packageManager;
3206
3417
  const opts = { allowDev: false, ...options };
3207
- const packageJsonVersion = this.packageJson.dependencies?.[packageName];
3208
- if (typeof packageJsonVersion === "string") {
3209
- return packageJsonVersion;
3210
- }
3211
- if (opts.allowDev) {
3212
- const devPackageJsonVersion = this.packageJson.devDependencies?.[packageName];
3213
- if (typeof devPackageJsonVersion === "string") {
3214
- return devPackageJsonVersion;
3215
- }
3216
- }
3217
- const command = packageManager === "npm" ? new NPMCommands() : packageManager === "pnpm" ? new PNPMCommands() : new YarnCommands();
3418
+ const command = await this.#getCommand();
3218
3419
  try {
3219
3420
  const version2 = await command.resolveDependencyVersion(packageName, {
3220
3421
  cwd: this.projectPath
3221
3422
  });
3222
3423
  if (version2) {
3424
+ logger.debug(`Resolved ${packageName} version using ${command.name}`, { version: version2 });
3223
3425
  return version2;
3224
3426
  }
3427
+ const packageJsonVersion = this.packageJson.dependencies?.[packageName];
3428
+ if (typeof packageJsonVersion === "string") {
3429
+ logger.debug(`Resolved ${packageName} version using package.json`, { packageJsonVersion });
3430
+ return packageJsonVersion;
3431
+ }
3432
+ if (opts.allowDev) {
3433
+ const devPackageJsonVersion = this.packageJson.devDependencies?.[packageName];
3434
+ if (typeof devPackageJsonVersion === "string") {
3435
+ logger.debug(`Resolved ${packageName} version using devDependencies`, {
3436
+ devPackageJsonVersion
3437
+ });
3438
+ return devPackageJsonVersion;
3439
+ }
3440
+ }
3225
3441
  } catch (error) {
3226
3442
  logger.debug(`Failed to resolve dependency version using ${command.name}`, {
3227
3443
  packageName,
@@ -3229,16 +3445,41 @@ var JavascriptProject = class {
3229
3445
  });
3230
3446
  }
3231
3447
  }
3448
+ async #getCommand() {
3449
+ const packageManager = await this.getPackageManager();
3450
+ switch (packageManager) {
3451
+ case "npm":
3452
+ return new NPMCommands();
3453
+ case "pnpm":
3454
+ return new PNPMCommands();
3455
+ case "yarn":
3456
+ return new YarnCommands();
3457
+ default:
3458
+ assertExhaustive(packageManager);
3459
+ }
3460
+ }
3461
+ async getPackageManager() {
3462
+ if (!this._packageManager) {
3463
+ this._packageManager = await getUserPackageManager(this.projectPath);
3464
+ }
3465
+ return this._packageManager;
3466
+ }
3232
3467
  };
3233
3468
  var PNPMCommands = class {
3234
3469
  get name() {
3235
3470
  return "pnpm";
3236
3471
  }
3472
+ get cmd() {
3473
+ return process.platform === "win32" ? "pnpm.cmd" : "pnpm";
3474
+ }
3475
+ async installDependencies(options) {
3476
+ const { stdout, stderr } = await $({ cwd: options.cwd })`${this.cmd} install`;
3477
+ logger.debug(`Installing dependencies using ${this.name}`, { stdout, stderr });
3478
+ }
3237
3479
  async resolveDependencyVersion(packageName, options) {
3238
- const cmd = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
3239
- const { stdout } = await $({ cwd: options.cwd })`${cmd} list ${packageName} -r --json`;
3480
+ const { stdout } = await $({ cwd: options.cwd })`${this.cmd} list ${packageName} -r --json`;
3240
3481
  const result = JSON.parse(stdout);
3241
- logger.debug(`Resolving ${packageName} version using pnpm`, { result });
3482
+ logger.debug(`Resolving ${packageName} version using ${this.name}`);
3242
3483
  for (const dep of result) {
3243
3484
  const dependency = dep.dependencies?.[packageName];
3244
3485
  if (dependency) {
@@ -3246,18 +3487,74 @@ var PNPMCommands = class {
3246
3487
  }
3247
3488
  }
3248
3489
  }
3490
+ async resolveDependencyVersions(packageNames, options) {
3491
+ const result = await this.#listDependencies(packageNames, options);
3492
+ logger.debug(`Resolving ${packageNames.join(" ")} version using ${this.name}`);
3493
+ const results = {};
3494
+ for (const dep of result) {
3495
+ for (const packageName of packageNames) {
3496
+ const dependency = dep.dependencies?.[packageName];
3497
+ if (dependency) {
3498
+ results[packageName] = dependency.version;
3499
+ }
3500
+ }
3501
+ }
3502
+ return results;
3503
+ }
3504
+ async #listDependencies(packageNames, options) {
3505
+ const childProcess2 = await $({
3506
+ cwd: options.cwd,
3507
+ reject: false
3508
+ })`${this.cmd} list ${packageNames} -r --json`;
3509
+ if (childProcess2.failed) {
3510
+ logger.debug("Failed to list dependencies, using stdout anyway...", {
3511
+ error: childProcess2.stderr
3512
+ });
3513
+ }
3514
+ return JSON.parse(childProcess2.stdout);
3515
+ }
3249
3516
  };
3250
3517
  var NPMCommands = class {
3251
3518
  get name() {
3252
3519
  return "npm";
3253
3520
  }
3521
+ get cmd() {
3522
+ return process.platform === "win32" ? "npm.cmd" : "npm";
3523
+ }
3524
+ async installDependencies(options) {
3525
+ const { stdout, stderr } = await $({ cwd: options.cwd })`${this.cmd} install`;
3526
+ logger.debug(`Installing dependencies using ${this.name}`, { stdout, stderr });
3527
+ }
3254
3528
  async resolveDependencyVersion(packageName, options) {
3255
- const cmd = process.platform === "win32" ? "npm.cmd" : "npm";
3256
- const { stdout } = await $({ cwd: options.cwd })`${cmd} list ${packageName} --json`;
3529
+ const { stdout } = await $({ cwd: options.cwd })`${this.cmd} list ${packageName} --json`;
3257
3530
  const output = JSON.parse(stdout);
3258
- logger.debug(`Resolving ${packageName} version using npm`, { output });
3531
+ logger.debug(`Resolving ${packageName} version using ${this.name}`, { output });
3259
3532
  return this.#recursivelySearchDependencies(output.dependencies, packageName);
3260
3533
  }
3534
+ async resolveDependencyVersions(packageNames, options) {
3535
+ const output = await this.#listDependencies(packageNames, options);
3536
+ logger.debug(`Resolving ${packageNames.join(" ")} version using ${this.name}`, { output });
3537
+ const results = {};
3538
+ for (const packageName of packageNames) {
3539
+ const version2 = this.#recursivelySearchDependencies(output.dependencies, packageName);
3540
+ if (version2) {
3541
+ results[packageName] = version2;
3542
+ }
3543
+ }
3544
+ return results;
3545
+ }
3546
+ async #listDependencies(packageNames, options) {
3547
+ const childProcess2 = await $({
3548
+ cwd: options.cwd,
3549
+ reject: false
3550
+ })`${this.cmd} list ${packageNames} --json`;
3551
+ if (childProcess2.failed) {
3552
+ logger.debug("Failed to list dependencies, using stdout anyway...", {
3553
+ error: childProcess2.stderr
3554
+ });
3555
+ }
3556
+ return JSON.parse(childProcess2.stdout);
3557
+ }
3261
3558
  #recursivelySearchDependencies(dependencies2, packageName) {
3262
3559
  for (const [name, dependency] of Object.entries(dependencies2)) {
3263
3560
  if (name === packageName) {
@@ -3276,11 +3573,17 @@ var YarnCommands = class {
3276
3573
  get name() {
3277
3574
  return "yarn";
3278
3575
  }
3576
+ get cmd() {
3577
+ return process.platform === "win32" ? "yarn.cmd" : "yarn";
3578
+ }
3579
+ async installDependencies(options) {
3580
+ const { stdout, stderr } = await $({ cwd: options.cwd })`${this.cmd} install`;
3581
+ logger.debug(`Installing dependencies using ${this.name}`, { stdout, stderr });
3582
+ }
3279
3583
  async resolveDependencyVersion(packageName, options) {
3280
- const cmd = process.platform === "win32" ? "yarn.cmd" : "yarn";
3281
- const { stdout } = await $({ cwd: options.cwd })`${cmd} info ${packageName} --json`;
3584
+ const { stdout } = await $({ cwd: options.cwd })`${this.cmd} info ${packageName} --json`;
3282
3585
  const lines = stdout.split("\n");
3283
- logger.debug(`Resolving ${packageName} version using yarn`, { lines });
3586
+ logger.debug(`Resolving ${packageName} version using ${this.name}`);
3284
3587
  for (const line of lines) {
3285
3588
  const json = JSON.parse(line);
3286
3589
  if (json.value === packageName) {
@@ -3288,22 +3591,318 @@ var YarnCommands = class {
3288
3591
  }
3289
3592
  }
3290
3593
  }
3291
- };
3292
-
3293
- // src/utilities/resolveInternalFilePath.ts
3294
- import path5 from "path";
3295
- import { fileURLToPath as fileURLToPath3 } from "url";
3296
- function cliRootPath() {
3297
- const __filename2 = fileURLToPath3(import.meta.url);
3298
- const __dirname2 = path5.dirname(__filename2);
3299
- return __dirname2;
3594
+ async resolveDependencyVersions(packageNames, options) {
3595
+ const stdout = await this.#listDependencies(packageNames, options);
3596
+ const lines = stdout.split("\n");
3597
+ logger.debug(`Resolving ${packageNames.join(" ")} version using ${this.name}`);
3598
+ const results = {};
3599
+ for (const line of lines) {
3600
+ const json = JSON.parse(line);
3601
+ const packageName = this.#parseYarnValueIntoPackageName(json.value);
3602
+ if (packageNames.includes(packageName)) {
3603
+ results[packageName] = json.children.Version;
3604
+ }
3605
+ }
3606
+ return results;
3607
+ }
3608
+ async #listDependencies(packageNames, options) {
3609
+ const childProcess2 = await $({
3610
+ cwd: options.cwd,
3611
+ reject: false
3612
+ })`${this.cmd} info ${packageNames} --json`;
3613
+ if (childProcess2.failed) {
3614
+ logger.debug("Failed to list dependencies, using stdout anyway...", {
3615
+ error: childProcess2.stderr
3616
+ });
3617
+ }
3618
+ return childProcess2.stdout;
3619
+ }
3620
+ // The "value" when doing yarn info is formatted like this:
3621
+ // "package-name@npm:version" or "package-name@workspace:version"
3622
+ // This function will parse the value into just the package name.
3623
+ // This correctly handles scoped packages as well e.g. @scope/package-name@npm:version
3624
+ #parseYarnValueIntoPackageName(value) {
3625
+ const parts = value.split("@");
3626
+ if (parts.length === 3) {
3627
+ return parts[1];
3628
+ }
3629
+ return parts[0];
3630
+ }
3631
+ };
3632
+ function isBuiltInModule(module) {
3633
+ if (module.startsWith("node:")) {
3634
+ return true;
3635
+ }
3636
+ return builtinModules.includes(module);
3637
+ }
3638
+
3639
+ // src/utilities/resolveInternalFilePath.ts
3640
+ import path5 from "path";
3641
+ import { fileURLToPath as fileURLToPath3 } from "url";
3642
+ function cliRootPath() {
3643
+ const __filename2 = fileURLToPath3(import.meta.url);
3644
+ const __dirname2 = path5.dirname(__filename2);
3645
+ return __dirname2;
3646
+ }
3647
+
3648
+ // src/utilities/safeJsonParse.ts
3649
+ function safeJsonParse(json) {
3650
+ if (!json) {
3651
+ return void 0;
3652
+ }
3653
+ try {
3654
+ return JSON.parse(json);
3655
+ } catch {
3656
+ return void 0;
3657
+ }
3658
+ }
3659
+
3660
+ // src/commands/update.ts
3661
+ import { confirm, intro as intro3, isCancel, log as log4, outro as outro4 } from "@clack/prompts";
3662
+ import { join as join5, resolve as resolve2 } from "path";
3663
+ var UpdateCommandOptions = CommonCommandOptions.pick({
3664
+ logLevel: true,
3665
+ skipTelemetry: true
3666
+ });
3667
+ function configureUpdateCommand(program2) {
3668
+ return program2.command("update").description("Updates all @trigger.dev/* packages to match the CLI version").argument("[path]", "The path to the directory that contains the package.json file", ".").option(
3669
+ "-l, --log-level <level>",
3670
+ "The CLI log level to use (debug, info, log, warn, error, none). This does not effect the log level of your trigger.dev tasks.",
3671
+ "log"
3672
+ ).option("--skip-telemetry", "Opt-out of sending telemetry").action(async (path7, options) => {
3673
+ wrapCommandAction("dev", UpdateCommandOptions, options, async (opts) => {
3674
+ await printStandloneInitialBanner(true);
3675
+ await updateCommand(path7, opts);
3676
+ });
3677
+ });
3678
+ }
3679
+ var triggerPackageFilter = /^@trigger\.dev/;
3680
+ async function updateCommand(dir, options) {
3681
+ await updateTriggerPackages(dir, options);
3682
+ }
3683
+ async function updateTriggerPackages(dir, options, embedded, requireUpdate) {
3684
+ let hasOutput = false;
3685
+ if (!embedded) {
3686
+ intro3("Updating packages");
3687
+ }
3688
+ const projectPath = resolve2(process.cwd(), dir);
3689
+ const { packageJson, readonlyPackageJson, packageJsonPath } = await getPackageJson(projectPath);
3690
+ if (!packageJson) {
3691
+ log4.error("Failed to load package.json. Try to re-run with `-l debug` to see what's going on.");
3692
+ return false;
3693
+ }
3694
+ const cliVersion = getVersion();
3695
+ const newCliVersion = await updateCheck();
3696
+ if (newCliVersion) {
3697
+ prettyWarning(
3698
+ "You're not running the latest CLI version, please consider updating ASAP",
3699
+ `Current: ${cliVersion}
3700
+ Latest: ${newCliVersion}`,
3701
+ "Run latest: npx trigger.dev@beta"
3702
+ );
3703
+ hasOutput = true;
3704
+ }
3705
+ const triggerDependencies = getTriggerDependencies(packageJson);
3706
+ function getVersionMismatches(deps, targetVersion) {
3707
+ const mismatches = [];
3708
+ for (const dep of deps) {
3709
+ if (dep.version === targetVersion) {
3710
+ continue;
3711
+ }
3712
+ mismatches.push(dep);
3713
+ }
3714
+ return mismatches;
3715
+ }
3716
+ const versionMismatches = getVersionMismatches(triggerDependencies, cliVersion);
3717
+ if (versionMismatches.length === 0) {
3718
+ if (!embedded) {
3719
+ outro4(`Nothing to do${newCliVersion ? " ..but you should really update your CLI!" : ""}`);
3720
+ return hasOutput;
3721
+ }
3722
+ return hasOutput;
3723
+ }
3724
+ prettyWarning(
3725
+ "Mismatch between your CLI version and installed packages",
3726
+ "We recommend pinned versions for guaranteed compatibility"
3727
+ );
3728
+ if (!process.stdout.isTTY) {
3729
+ outro4("Deploy failed");
3730
+ console.log(
3731
+ `ERROR: Version mismatch detected while running in CI. This won't end well. Aborting.
3732
+
3733
+ Please run the dev command locally and check that your CLI version matches the one printed below. Additionally, all \`@trigger.dev/*\` packages also need to match this version.
3734
+
3735
+ If your local CLI version doesn't match the one below, you may want to pin the CLI version in this CI step. To do that, just replace \`trigger.dev@beta\` with \`trigger.dev@<FULL_VERSION>\`, for example: \`npx trigger.dev@3.0.0-beta.17 deploy\`
3736
+
3737
+ CLI version: ${cliVersion}
3738
+
3739
+ Current package versions that don't match the CLI:
3740
+ ${versionMismatches.map((dep) => `- ${dep.name}@${dep.version}`).join("\n")}
3741
+ `
3742
+ );
3743
+ process.exit(1);
3744
+ }
3745
+ log4.message("");
3746
+ const userWantsToUpdate = await updateConfirmation(versionMismatches, cliVersion);
3747
+ if (isCancel(userWantsToUpdate)) {
3748
+ throw new OutroCommandError();
3749
+ }
3750
+ if (!userWantsToUpdate) {
3751
+ if (requireUpdate) {
3752
+ outro4("You shall not pass!");
3753
+ logger.log(
3754
+ `${chalkError(
3755
+ "X Error:"
3756
+ )} Update required: Version mismatches are a common source of bugs and errors. Please update or use \`--skip-update-check\` at your own risk.
3757
+ `
3758
+ );
3759
+ process.exit(1);
3760
+ }
3761
+ if (!embedded) {
3762
+ outro4("You've been warned!");
3763
+ }
3764
+ return hasOutput;
3765
+ }
3766
+ const installSpinner = spinner();
3767
+ installSpinner.start("Writing new package.json file");
3768
+ const packageJsonBackupPath = `${packageJsonPath}.bak`;
3769
+ await writeJSONFile(packageJsonBackupPath, readonlyPackageJson, true);
3770
+ const exitHandler = async (sig) => {
3771
+ log4.warn(
3772
+ `You may have to manually roll back any package.json changes. Backup written to ${packageJsonBackupPath}`
3773
+ );
3774
+ };
3775
+ process.prependOnceListener("exit", exitHandler);
3776
+ mutatePackageJsonWithUpdatedPackages(packageJson, versionMismatches, cliVersion);
3777
+ await writeJSONFile(packageJsonPath, packageJson, true);
3778
+ async function revertPackageJsonChanges() {
3779
+ await writeJSONFile(packageJsonPath, readonlyPackageJson, true);
3780
+ await removeFile(packageJsonBackupPath);
3781
+ }
3782
+ installSpinner.message("Installing new package versions");
3783
+ const jsProject = new JavascriptProject(projectPath);
3784
+ let packageManager;
3785
+ try {
3786
+ packageManager = await jsProject.getPackageManager();
3787
+ installSpinner.message(`Installing new package versions with ${packageManager}`);
3788
+ await jsProject.install();
3789
+ } catch (error) {
3790
+ installSpinner.stop(
3791
+ `Failed to install new package versions${packageManager ? ` with ${packageManager}` : ""}`
3792
+ );
3793
+ process.removeListener("exit", exitHandler);
3794
+ await revertPackageJsonChanges();
3795
+ throw error;
3796
+ }
3797
+ installSpinner.stop("Installed new package versions");
3798
+ process.removeListener("exit", exitHandler);
3799
+ await removeFile(packageJsonBackupPath);
3800
+ if (!embedded) {
3801
+ outro4(
3802
+ `Packages updated${newCliVersion ? " ..but you should really update your CLI too!" : ""}`
3803
+ );
3804
+ }
3805
+ return hasOutput;
3806
+ }
3807
+ function getTriggerDependencies(packageJson) {
3808
+ const deps = [];
3809
+ for (const type of ["dependencies", "devDependencies"]) {
3810
+ for (const [name, version2] of Object.entries(packageJson[type] ?? {})) {
3811
+ if (!version2) {
3812
+ continue;
3813
+ }
3814
+ if (version2.startsWith("workspace")) {
3815
+ continue;
3816
+ }
3817
+ if (!triggerPackageFilter.test(name)) {
3818
+ continue;
3819
+ }
3820
+ const ignoredPackages = ["@trigger.dev/companyicons"];
3821
+ if (ignoredPackages.includes(name)) {
3822
+ continue;
3823
+ }
3824
+ deps.push({ type, name, version: version2 });
3825
+ }
3826
+ }
3827
+ return deps;
3828
+ }
3829
+ function mutatePackageJsonWithUpdatedPackages(packageJson, depsToUpdate, targetVersion) {
3830
+ for (const { type, name, version: version2 } of depsToUpdate) {
3831
+ if (!packageJson[type]) {
3832
+ throw new Error(
3833
+ `No ${type} entry found in package.json. Please try to upgrade manually instead.`
3834
+ );
3835
+ }
3836
+ packageJson[type][name] = targetVersion;
3837
+ }
3838
+ }
3839
+ function printUpdateTable(depsToUpdate, targetVersion) {
3840
+ log4.message("Suggested updates");
3841
+ const tableData = depsToUpdate.map((dep) => ({
3842
+ package: dep.name,
3843
+ old: dep.version,
3844
+ new: targetVersion
3845
+ }));
3846
+ logger.table(tableData);
3847
+ }
3848
+ async function updateConfirmation(depsToUpdate, targetVersion) {
3849
+ printUpdateTable(depsToUpdate, targetVersion);
3850
+ let confirmMessage = "Would you like to apply those updates?";
3851
+ return await confirm({
3852
+ message: confirmMessage
3853
+ });
3854
+ }
3855
+ async function getPackageJson(absoluteProjectPath) {
3856
+ const packageJsonPath = join5(absoluteProjectPath, "package.json");
3857
+ const readonlyPackageJson = Object.freeze(await readJSONFile(packageJsonPath));
3858
+ const packageJson = structuredClone(readonlyPackageJson);
3859
+ return { packageJson, readonlyPackageJson, packageJsonPath };
3860
+ }
3861
+
3862
+ // src/utilities/resolveEnvVars.ts
3863
+ async function callResolveEnvVars(configModule, env, environment, projectRef) {
3864
+ if (configModule && configModule.resolveEnvVars && typeof configModule.resolveEnvVars === "function") {
3865
+ let resolvedEnvVars2 = {};
3866
+ try {
3867
+ let result = await configModule.resolveEnvVars({
3868
+ projectRef,
3869
+ environment,
3870
+ env
3871
+ });
3872
+ if (!result) {
3873
+ return;
3874
+ }
3875
+ result = await result;
3876
+ if (typeof result === "object" && result !== null && "variables" in result) {
3877
+ const variables = result.variables;
3878
+ if (Array.isArray(variables)) {
3879
+ for (const item of variables) {
3880
+ if (typeof item === "object" && item !== null && "name" in item && "value" in item && typeof item.name === "string" && typeof item.value === "string") {
3881
+ resolvedEnvVars2[item.name] = item.value;
3882
+ }
3883
+ }
3884
+ } else if (typeof variables === "object") {
3885
+ for (const [key, value] of Object.entries(variables)) {
3886
+ if (typeof key === "string" && typeof value === "string") {
3887
+ resolvedEnvVars2[key] = value;
3888
+ }
3889
+ }
3890
+ }
3891
+ }
3892
+ return {
3893
+ variables: resolvedEnvVars2,
3894
+ override: result.override
3895
+ };
3896
+ } catch (error) {
3897
+ logger.error(error);
3898
+ }
3899
+ }
3300
3900
  }
3301
3901
 
3302
3902
  // src/commands/deploy.ts
3303
3903
  var DeployCommandOptions = CommonCommandOptions.extend({
3304
3904
  skipTypecheck: z4.boolean().default(false),
3305
3905
  skipDeploy: z4.boolean().default(false),
3306
- ignoreEnvVarCheck: z4.boolean().default(false),
3307
3906
  env: z4.enum(["prod", "staging"]),
3308
3907
  loadImage: z4.boolean().default(false),
3309
3908
  buildPlatform: z4.enum(["linux/amd64", "linux/arm64"]).default("linux/amd64"),
@@ -3313,7 +3912,10 @@ var DeployCommandOptions = CommonCommandOptions.extend({
3313
3912
  config: z4.string().optional(),
3314
3913
  projectRef: z4.string().optional(),
3315
3914
  outputMetafile: z4.string().optional(),
3316
- apiUrl: z4.string().optional()
3915
+ apiUrl: z4.string().optional(),
3916
+ saveLogs: z4.boolean().default(false),
3917
+ skipUpdateCheck: z4.boolean().default(false),
3918
+ noCache: z4.boolean().default(false)
3317
3919
  });
3318
3920
  function configureDeployCommand(program2) {
3319
3921
  return commonOptions(
@@ -3321,10 +3923,7 @@ function configureDeployCommand(program2) {
3321
3923
  "-e, --env <env>",
3322
3924
  "Deploy to a specific environment (currently only prod and staging are supported)",
3323
3925
  "prod"
3324
- ).option("--skip-typecheck", "Whether to skip the pre-build typecheck").option(
3325
- "--ignore-env-var-check",
3326
- "Detected missing environment variables won't block deployment"
3327
- ).option("-c, --config <config file>", "The name of the config file, found at [path]").option(
3926
+ ).option("--skip-typecheck", "Whether to skip the pre-build typecheck").option("--skip-update-check", "Skip checking for @trigger.dev package updates").option("-c, --config <config file>", "The name of the config file, found at [path]").option(
3328
3927
  "-p, --project-ref <project ref>",
3329
3928
  "The project ref. Required if there is no config file. This will override the project specified in the config file."
3330
3929
  )
@@ -3333,6 +3932,11 @@ function configureDeployCommand(program2) {
3333
3932
  "--self-hosted",
3334
3933
  "Build and load the image using your local Docker. Use the --registry option to specify the registry to push the image to when using --self-hosted, or just use --push-image to push to the default registry."
3335
3934
  ).hideHelp()
3935
+ ).addOption(
3936
+ new CommandOption(
3937
+ "--no-cache",
3938
+ "Do not use the cache when building the image. This will slow down the build process but can be useful if you are experiencing issues with the cache."
3939
+ ).hideHelp()
3336
3940
  ).addOption(
3337
3941
  new CommandOption(
3338
3942
  "--push",
@@ -3348,6 +3952,11 @@ function configureDeployCommand(program2) {
3348
3952
  "--tag <tag>",
3349
3953
  "(Coming soon) Specify the tag to use when pushing the image to the registry"
3350
3954
  ).hideHelp()
3955
+ ).addOption(
3956
+ new CommandOption(
3957
+ "--ignore-env-var-check",
3958
+ "(deprecated) Detected missing environment variables won't block deployment"
3959
+ ).hideHelp()
3351
3960
  ).addOption(new CommandOption("-D, --skip-deploy", "Skip deploying the image").hideHelp()).addOption(
3352
3961
  new CommandOption("--load-image", "Load the built image into your local docker").hideHelp()
3353
3962
  ).addOption(
@@ -3360,6 +3969,11 @@ function configureDeployCommand(program2) {
3360
3969
  "--output-metafile <path>",
3361
3970
  "If provided, will save the esbuild metafile for the build to the specified path"
3362
3971
  ).hideHelp()
3972
+ ).addOption(
3973
+ new CommandOption(
3974
+ "--save-logs",
3975
+ "If provided, will save logs even for successful builds"
3976
+ ).hideHelp()
3363
3977
  ).action(async (path7, options) => {
3364
3978
  await handleTelemetry(async () => {
3365
3979
  await printStandloneInitialBanner(true);
@@ -3374,7 +3988,10 @@ async function deployCommand(dir, options) {
3374
3988
  }
3375
3989
  async function _deployCommand(dir, options) {
3376
3990
  const span = trace2.getSpan(context.active());
3377
- intro3("Deploying project");
3991
+ intro4("Deploying project");
3992
+ if (!options.skipUpdateCheck) {
3993
+ await updateTriggerPackages(dir, { ...options }, true, true);
3994
+ }
3378
3995
  const authorization = await login({
3379
3996
  embedded: true,
3380
3997
  defaultApiUrl: options.apiUrl,
@@ -3398,6 +4015,11 @@ async function _deployCommand(dir, options) {
3398
4015
  configFile: options.config,
3399
4016
  projectRef: options.projectRef
3400
4017
  });
4018
+ if (resolvedConfig.status === "error") {
4019
+ logger.error("Failed to read config:", resolvedConfig.error);
4020
+ span && recordSpanException5(span, resolvedConfig.error);
4021
+ throw new SkipLoggingError("Failed to read config");
4022
+ }
3401
4023
  logger.debug("Resolved config", { resolvedConfig });
3402
4024
  span?.setAttributes({
3403
4025
  "resolvedConfig.status": resolvedConfig.status,
@@ -3406,7 +4028,7 @@ async function _deployCommand(dir, options) {
3406
4028
  "resolvedConfig.config.projectDir": resolvedConfig.config.projectDir,
3407
4029
  "resolvedConfig.config.triggerUrl": resolvedConfig.config.triggerUrl,
3408
4030
  "resolvedConfig.config.triggerDirectories": resolvedConfig.config.triggerDirectories,
3409
- ...flattenAttributes2(resolvedConfig.config.retries, "resolvedConfig.config.retries")
4031
+ ...flattenAttributes3(resolvedConfig.config.retries, "resolvedConfig.config.retries")
3410
4032
  });
3411
4033
  const apiClient2 = new CliApiClient(authorization.auth.apiUrl, authorization.auth.accessToken);
3412
4034
  const deploymentEnv = await apiClient2.getProjectEnv({
@@ -3417,7 +4039,7 @@ async function _deployCommand(dir, options) {
3417
4039
  throw new Error(deploymentEnv.error);
3418
4040
  }
3419
4041
  const environmentClient = new CliApiClient(authorization.auth.apiUrl, deploymentEnv.data.apiKey);
3420
- log3.step(
4042
+ log5.step(
3421
4043
  `Preparing to deploy "${deploymentEnv.data.name}" (${resolvedConfig.config.project}) to ${options.env}`
3422
4044
  );
3423
4045
  const compilation = await compileProject(
@@ -3426,15 +4048,7 @@ async function _deployCommand(dir, options) {
3426
4048
  resolvedConfig.status === "file" ? resolvedConfig.path : void 0
3427
4049
  );
3428
4050
  logger.debug("Compilation result", { compilation });
3429
- if (compilation.envVars.length > 0) {
3430
- await checkEnvVars(
3431
- compilation.envVars ?? [],
3432
- resolvedConfig.config,
3433
- options,
3434
- environmentClient,
3435
- authorization.dashboardUrl
3436
- );
3437
- }
4051
+ await resolveEnvironmentVariables(resolvedConfig, environmentClient, options);
3438
4052
  const deploymentResponse = await environmentClient.initializeDeployment({
3439
4053
  contentHash: compilation.contentHash,
3440
4054
  userId: authorization.userId
@@ -3465,7 +4079,8 @@ async function _deployCommand(dir, options) {
3465
4079
  projectRef: resolvedConfig.config.project,
3466
4080
  buildPlatform: options.buildPlatform,
3467
4081
  pushImage: options.push,
3468
- selfHostedRegistry: !!options.registry
4082
+ selfHostedRegistry: !!options.registry,
4083
+ noCache: options.noCache
3469
4084
  });
3470
4085
  }
3471
4086
  if (!deploymentResponse.data.externalBuildData) {
@@ -3488,25 +4103,42 @@ async function _deployCommand(dir, options) {
3488
4103
  contentHash: deploymentResponse.data.contentHash,
3489
4104
  projectRef: resolvedConfig.config.project,
3490
4105
  loadImage: options.loadImage,
3491
- buildPlatform: options.buildPlatform
4106
+ buildPlatform: options.buildPlatform,
4107
+ noCache: options.noCache
3492
4108
  },
3493
4109
  deploymentSpinner
3494
4110
  );
3495
4111
  };
3496
4112
  const image = await buildImage();
4113
+ const warnings = checkLogsForWarnings(image.logs);
4114
+ if (!warnings.ok) {
4115
+ await failDeploy(
4116
+ deploymentResponse.data.shortCode,
4117
+ warnings.summary,
4118
+ image.logs,
4119
+ deploymentSpinner,
4120
+ warnings.warnings,
4121
+ warnings.errors
4122
+ );
4123
+ throw new SkipLoggingError(`Failed to build project image: ${warnings.summary}`);
4124
+ }
3497
4125
  if (!image.ok) {
3498
- deploymentSpinner.stop(`Failed to build project.`);
3499
- if (image.logs.trim() !== "") {
3500
- const logPath = join5(await createTempDir(), `build-${deploymentResponse.data.shortCode}.log`);
3501
- await writeFile2(logPath, image.logs);
3502
- logger.log(
3503
- `${chalkError("X Error:")} ${image.error}. Full build logs have been saved to ${logPath})`
3504
- );
3505
- } else {
3506
- logger.log(`${chalkError("X Error:")} ${image.error}.`);
3507
- }
4126
+ await failDeploy(
4127
+ deploymentResponse.data.shortCode,
4128
+ image.error,
4129
+ image.logs,
4130
+ deploymentSpinner,
4131
+ warnings.warnings
4132
+ );
3508
4133
  throw new SkipLoggingError(`Failed to build project image: ${image.error}`);
3509
4134
  }
4135
+ const preExitTasks = async () => {
4136
+ printWarnings(warnings.warnings);
4137
+ if (options.saveLogs) {
4138
+ const logPath = await saveLogs(deploymentResponse.data.shortCode, image.logs);
4139
+ log5.info(`Build logs have been saved to ${logPath}`);
4140
+ }
4141
+ };
3510
4142
  const imageReference = options.selfHosted ? `${selfHostedRegistryHost ? `${selfHostedRegistryHost}/` : ""}${image.image}${image.digest ? `@${image.digest}` : ""}` : `${registryHost}/${image.image}${image.digest ? `@${image.digest}` : ""}`;
3511
4143
  span?.setAttributes({
3512
4144
  "image.reference": imageReference
@@ -3515,6 +4147,7 @@ async function _deployCommand(dir, options) {
3515
4147
  deploymentSpinner.stop(
3516
4148
  `Project image built: ${imageReference}. Skipping deployment as requested`
3517
4149
  );
4150
+ await preExitTasks();
3518
4151
  throw new SkipCommandError("Skipping deployment as requested");
3519
4152
  }
3520
4153
  deploymentSpinner.message(
@@ -3524,11 +4157,13 @@ async function _deployCommand(dir, options) {
3524
4157
  const startIndexingResponse = await environmentClient.startDeploymentIndexing(
3525
4158
  deploymentResponse.data.id,
3526
4159
  {
3527
- imageReference
4160
+ imageReference,
4161
+ selfHosted: options.selfHosted
3528
4162
  }
3529
4163
  );
3530
4164
  if (!startIndexingResponse.success) {
3531
4165
  deploymentSpinner.stop(`Failed to start indexing: ${startIndexingResponse.error}`);
4166
+ await preExitTasks();
3532
4167
  throw new SkipLoggingError(`Failed to start indexing: ${startIndexingResponse.error}`);
3533
4168
  }
3534
4169
  const finishedDeployment = await waitForDeploymentToFinish(
@@ -3537,26 +4172,33 @@ async function _deployCommand(dir, options) {
3537
4172
  );
3538
4173
  if (!finishedDeployment) {
3539
4174
  deploymentSpinner.stop(`Deployment failed to complete`);
4175
+ await preExitTasks();
3540
4176
  throw new SkipLoggingError("Deployment failed to complete: unknown issue");
3541
4177
  }
3542
4178
  if (typeof finishedDeployment === "string") {
3543
4179
  deploymentSpinner.stop(`Deployment failed to complete: ${finishedDeployment}`);
4180
+ await preExitTasks();
3544
4181
  throw new SkipLoggingError(`Deployment failed to complete: ${finishedDeployment}`);
3545
4182
  }
3546
- const deploymentLink = terminalLink(
4183
+ const deploymentLink = terminalLink2(
3547
4184
  "View deployment",
3548
4185
  `${authorization.dashboardUrl}/projects/v3/${resolvedConfig.config.project}/deployments/${finishedDeployment.shortCode}`
3549
4186
  );
3550
4187
  switch (finishedDeployment.status) {
3551
4188
  case "DEPLOYED": {
3552
- deploymentSpinner.stop("Deployment completed");
4189
+ if (warnings.warnings.length > 0) {
4190
+ deploymentSpinner.stop("Deployment completed with warnings");
4191
+ } else {
4192
+ deploymentSpinner.stop("Deployment completed");
4193
+ }
4194
+ await preExitTasks();
3553
4195
  const taskCount = finishedDeployment.worker?.tasks.length ?? 0;
3554
4196
  if (taskCount === 0) {
3555
- outro3(
4197
+ outro5(
3556
4198
  `Version ${version2} deployed with no detected tasks. Please make sure you are exporting tasks in your project. ${deploymentLink}`
3557
4199
  );
3558
4200
  } else {
3559
- outro3(
4201
+ outro5(
3560
4202
  `Version ${version2} deployed with ${taskCount} detected task${taskCount === 1 ? "" : "s"} ${deploymentLink}`
3561
4203
  );
3562
4204
  }
@@ -3571,6 +4213,7 @@ async function _deployCommand(dir, options) {
3571
4213
  if (parsedError2.success) {
3572
4214
  deploymentSpinner.stop(`Deployment encountered an error. ${deploymentLink}`);
3573
4215
  logTaskMetadataParseError(parsedError2.data.zodIssues, parsedError2.data.tasks);
4216
+ await preExitTasks();
3574
4217
  throw new SkipLoggingError(
3575
4218
  `Deployment encountered an error: ${finishedDeployment.errorData.name}`
3576
4219
  );
@@ -3585,6 +4228,7 @@ async function _deployCommand(dir, options) {
3585
4228
  deploymentSpinner.stop(`Deployment encountered an error. ${deploymentLink}`);
3586
4229
  logESMRequireError(parsedError, resolvedConfig);
3587
4230
  }
4231
+ await preExitTasks();
3588
4232
  throw new SkipLoggingError(
3589
4233
  `Deployment encountered an error: ${finishedDeployment.errorData.name}`
3590
4234
  );
@@ -3592,62 +4236,132 @@ async function _deployCommand(dir, options) {
3592
4236
  deploymentSpinner.stop(
3593
4237
  `Deployment failed with an unknown error. Please contact eric@trigger.dev for help. ${deploymentLink}`
3594
4238
  );
4239
+ await preExitTasks();
3595
4240
  throw new SkipLoggingError("Deployment failed with an unknown error");
3596
4241
  }
3597
4242
  }
3598
4243
  case "CANCELED": {
3599
4244
  deploymentSpinner.stop(`Deployment was canceled. ${deploymentLink}`);
4245
+ await preExitTasks();
3600
4246
  throw new SkipLoggingError("Deployment was canceled");
3601
4247
  }
3602
4248
  case "TIMED_OUT": {
3603
4249
  deploymentSpinner.stop(`Deployment timed out. ${deploymentLink}`);
4250
+ await preExitTasks();
3604
4251
  throw new SkipLoggingError("Deployment timed out");
3605
4252
  }
3606
4253
  }
3607
4254
  }
3608
- async function checkEnvVars(envVars, config, options, environmentClient, apiUrl) {
3609
- return await tracer.startActiveSpan("detectEnvVars", async (span) => {
3610
- try {
3611
- span.setAttribute("envVars.check", envVars);
3612
- const environmentVariablesSpinner = spinner();
3613
- environmentVariablesSpinner.start("Checking environment variables");
3614
- const environmentVariables = await environmentClient.getEnvironmentVariables(config.project);
3615
- if (!environmentVariables.success) {
3616
- environmentVariablesSpinner.stop(`Failed to fetch environment variables, skipping check`);
3617
- } else {
3618
- const missingEnvironmentVariables = envVars.filter(
3619
- (envVar) => environmentVariables.data.variables[envVar] === void 0
3620
- );
3621
- if (missingEnvironmentVariables.length > 0) {
3622
- environmentVariablesSpinner.stop(
3623
- `Found missing env vars in ${options.env}: ${arrayToSentence(
3624
- missingEnvironmentVariables
3625
- )}. ${options.ignoreEnvVarCheck ? "Continuing deployment because of --ignore-env-var-check. " : "Aborting deployment. "}${chalk5.bgBlueBright(
3626
- terminalLink(
3627
- "Manage env vars",
3628
- `${apiUrl}/projects/v3/${config.project}/environment-variables`
3629
- )
3630
- )}`
3631
- );
3632
- span.setAttributes({
3633
- "envVars.missing": missingEnvironmentVariables
3634
- });
3635
- if (!options.ignoreEnvVarCheck) {
3636
- throw new SkipLoggingError("Found missing environment variables");
3637
- } else {
3638
- span.end();
3639
- return;
3640
- }
3641
- }
3642
- environmentVariablesSpinner.stop(`Environment variable check passed`);
3643
- }
3644
- span.end();
3645
- } catch (e) {
3646
- recordSpanException4(span, e);
3647
- span.end();
3648
- throw e;
4255
+ function printErrors(errors) {
4256
+ for (const error of errors ?? []) {
4257
+ log5.error(`${chalkError("Error:")} ${error}`);
4258
+ }
4259
+ }
4260
+ function printWarnings(warnings) {
4261
+ for (const warning of warnings ?? []) {
4262
+ log5.warn(`${chalkWarning("Warning:")} ${warning}`);
4263
+ }
4264
+ }
4265
+ function checkLogsForWarnings(logs) {
4266
+ const warnings = [
4267
+ {
4268
+ regex: /prisma:warn We could not find your Prisma schema/,
4269
+ message: `Prisma generate failed to find the default schema. Did you include it in config.additionalFiles? ${terminalLink2(
4270
+ "Config docs",
4271
+ docs.config.prisma
4272
+ )}
4273
+ Custom schema paths require a postinstall script like this: \`prisma generate --schema=./custom/path/to/schema.prisma\``,
4274
+ shouldFail: true
3649
4275
  }
3650
- });
4276
+ ];
4277
+ const errorMessages2 = [];
4278
+ const warningMessages = [];
4279
+ let shouldFail = false;
4280
+ for (const warning of warnings) {
4281
+ const matches = logs.match(warning.regex);
4282
+ if (!matches) {
4283
+ continue;
4284
+ }
4285
+ const message = getMessageFromTemplate(warning.message, matches.groups);
4286
+ if (warning.shouldFail) {
4287
+ shouldFail = true;
4288
+ errorMessages2.push(message);
4289
+ } else {
4290
+ warningMessages.push(message);
4291
+ }
4292
+ }
4293
+ if (shouldFail) {
4294
+ return {
4295
+ ok: false,
4296
+ summary: "Build succeeded with critical warnings. Will not proceed",
4297
+ warnings: warningMessages,
4298
+ errors: errorMessages2
4299
+ };
4300
+ }
4301
+ return {
4302
+ ok: true,
4303
+ warnings: warningMessages
4304
+ };
4305
+ }
4306
+ function checkLogsForErrors(logs) {
4307
+ const errors = [
4308
+ {
4309
+ regex: /Error: Provided --schema at (?<schema>.*) doesn't exist/,
4310
+ message: `Prisma generate failed to find the specified schema at "$schema".
4311
+ Did you include it in config.additionalFiles? ${terminalLink2(
4312
+ "Config docs",
4313
+ docs.config.prisma
4314
+ )}`
4315
+ },
4316
+ {
4317
+ regex: /sh: 1: (?<packageOrBinary>.*): not found/,
4318
+ message: `$packageOrBinary not found
4319
+
4320
+ If it's a package: Include it in ${terminalLink2(
4321
+ "config.additionalPackages",
4322
+ docs.config.prisma
4323
+ )}
4324
+ If it's a binary: Please ${terminalLink2(
4325
+ "get in touch",
4326
+ getInTouch
4327
+ )} and we'll see what we can do!`
4328
+ }
4329
+ ];
4330
+ for (const error of errors) {
4331
+ const matches = logs.match(error.regex);
4332
+ if (!matches) {
4333
+ continue;
4334
+ }
4335
+ const message = getMessageFromTemplate(error.message, matches.groups);
4336
+ log5.error(`${chalkError("Error:")} ${message}`);
4337
+ break;
4338
+ }
4339
+ }
4340
+ function getMessageFromTemplate(template, replacer) {
4341
+ let message = template;
4342
+ if (replacer) {
4343
+ for (const [key, value] of Object.entries(replacer)) {
4344
+ message = message.replaceAll(`$${key}`, value);
4345
+ }
4346
+ }
4347
+ return message;
4348
+ }
4349
+ async function saveLogs(shortCode, logs) {
4350
+ const logPath = join6(await createTempDir(), `build-${shortCode}.log`);
4351
+ await writeFile2(logPath, logs);
4352
+ return logPath;
4353
+ }
4354
+ async function failDeploy(shortCode, errorSummary, logs, deploymentSpinner, warnings, errors) {
4355
+ deploymentSpinner.stop(`Failed to deploy project`);
4356
+ if (logs.trim() !== "") {
4357
+ const logPath = await saveLogs(shortCode, logs);
4358
+ printWarnings(warnings);
4359
+ printErrors(errors);
4360
+ checkLogsForErrors(logs);
4361
+ outro5(`${chalkError("Error:")} ${errorSummary}. Full build logs have been saved to ${logPath}`);
4362
+ } else {
4363
+ outro5(`${chalkError("Error:")} ${errorSummary}.`);
4364
+ }
3651
4365
  }
3652
4366
  async function waitForDeploymentToFinish(deploymentId, client, timeoutInSeconds = 60) {
3653
4367
  return tracer.startActiveSpan("waitForDeploymentToFinish", async (span) => {
@@ -3677,7 +4391,7 @@ async function waitForDeploymentToFinish(deploymentId, client, timeoutInSeconds
3677
4391
  await setTimeout2(1e3);
3678
4392
  }
3679
4393
  } catch (error) {
3680
- recordSpanException4(span, error);
4394
+ recordSpanException5(span, error);
3681
4395
  span.end();
3682
4396
  return error instanceof Error ? error.message : JSON.stringify(error);
3683
4397
  }
@@ -3704,6 +4418,7 @@ async function buildAndPushImage(options, updater) {
3704
4418
  "build",
3705
4419
  "-f",
3706
4420
  "Containerfile",
4421
+ options.noCache ? "--no-cache" : void 0,
3707
4422
  "--platform",
3708
4423
  options.buildPlatform,
3709
4424
  "--provenance",
@@ -3769,7 +4484,7 @@ async function buildAndPushImage(options, updater) {
3769
4484
  digest
3770
4485
  };
3771
4486
  } catch (e) {
3772
- recordSpanException4(span, e);
4487
+ recordSpanException5(span, e);
3773
4488
  span.end();
3774
4489
  return {
3775
4490
  ok: false,
@@ -3795,6 +4510,7 @@ async function buildAndPushSelfHostedImage(options) {
3795
4510
  "build",
3796
4511
  "-f",
3797
4512
  "Containerfile",
4513
+ options.noCache ? "--no-cache" : void 0,
3798
4514
  "--platform",
3799
4515
  options.buildPlatform,
3800
4516
  "--build-arg",
@@ -3812,7 +4528,9 @@ async function buildAndPushSelfHostedImage(options) {
3812
4528
  "."
3813
4529
  // The build context
3814
4530
  ].filter(Boolean);
3815
- logger.debug(`docker ${buildArgs.join(" ")}`);
4531
+ logger.debug(`docker ${buildArgs.join(" ")}`, {
4532
+ cwd: options.cwd
4533
+ });
3816
4534
  span.setAttribute("docker.command.build", `docker ${buildArgs.join(" ")}`);
3817
4535
  const buildProcess = execa2("docker", buildArgs, {
3818
4536
  cwd: options.cwd
@@ -3841,7 +4559,7 @@ async function buildAndPushSelfHostedImage(options) {
3841
4559
  "image.digest": digest
3842
4560
  });
3843
4561
  } catch (e) {
3844
- recordSpanException4(span, e);
4562
+ recordSpanException5(span, e);
3845
4563
  span.end();
3846
4564
  return {
3847
4565
  ok: false,
@@ -3878,7 +4596,7 @@ async function buildAndPushSelfHostedImage(options) {
3878
4596
  }
3879
4597
  span.end();
3880
4598
  } catch (e) {
3881
- recordSpanException4(span, e);
4599
+ recordSpanException5(span, e);
3882
4600
  span.end();
3883
4601
  return {
3884
4602
  ok: false,
@@ -3923,13 +4641,15 @@ async function compileProject(config, options, configPath) {
3923
4641
  compileSpinner.start(`Building project in ${config.projectDir}`);
3924
4642
  const taskFiles = await gatherTaskFiles(config);
3925
4643
  const workerFacade = readFileSync2(
3926
- join5(cliRootPath(), "workers", "prod", "worker-facade.js"),
4644
+ join6(cliRootPath(), "workers", "prod", "worker-facade.js"),
3927
4645
  "utf-8"
3928
4646
  );
3929
- const workerSetupPath = join5(cliRootPath(), "workers", "dev", "worker-setup.js");
4647
+ const workerSetupPath = join6(cliRootPath(), "workers", "prod", "worker-setup.js");
3930
4648
  let workerContents = workerFacade.replace("__TASKS__", createTaskFileImports(taskFiles)).replace(
3931
4649
  "__WORKER_SETUP__",
3932
- `import { tracingSDK } from "${escapeImportPath(workerSetupPath)}";`
4650
+ `import { tracingSDK, otelTracer, otelLogger } from "${escapeImportPath(
4651
+ workerSetupPath
4652
+ )}";`
3933
4653
  );
3934
4654
  if (configPath) {
3935
4655
  logger.debug("Importing project config from", { configPath });
@@ -3963,17 +4683,26 @@ async function compileProject(config, options, configPath) {
3963
4683
  // This is needed to support opentelemetry instrumentation that uses module patching
3964
4684
  target: ["node18", "es2020"],
3965
4685
  outdir: "out",
4686
+ banner: {
4687
+ js: `process.on("uncaughtException", function(error, origin) { if (error instanceof Error) { process.send && process.send({ type: "EVENT", message: { type: "UNCAUGHT_EXCEPTION", payload: { error: { name: error.name, message: error.message, stack: error.stack }, origin }, version: "v1" } }); } else { process.send && process.send({ type: "EVENT", message: { type: "UNCAUGHT_EXCEPTION", payload: { error: { name: "Error", message: typeof error === "string" ? error : JSON.stringify(error) }, origin }, version: "v1" } }); } });`
4688
+ },
3966
4689
  define: {
3967
4690
  TRIGGER_API_URL: `"${config.triggerUrl}"`,
3968
4691
  __PROJECT_CONFIG__: JSON.stringify(config)
3969
4692
  },
3970
4693
  plugins: [
4694
+ mockServerOnlyPlugin(),
3971
4695
  bundleDependenciesPlugin(
3972
4696
  "workerFacade",
3973
4697
  config.dependenciesToBundle,
3974
4698
  config.tsconfigPath
3975
4699
  ),
3976
- workerSetupImportConfigPlugin(configPath)
4700
+ workerSetupImportConfigPlugin(configPath),
4701
+ esbuildDecorators2({
4702
+ tsconfig: config.tsconfigPath,
4703
+ tsx: true,
4704
+ force: false
4705
+ })
3977
4706
  ]
3978
4707
  });
3979
4708
  if (result.errors.length > 0) {
@@ -3986,10 +4715,10 @@ async function compileProject(config, options, configPath) {
3986
4715
  throw new Error("Build failed, aborting deployment");
3987
4716
  }
3988
4717
  if (options.outputMetafile) {
3989
- await writeJSONFile(join5(options.outputMetafile, "worker.json"), result.metafile);
4718
+ await writeJSONFile(join6(options.outputMetafile, "worker.json"), result.metafile);
3990
4719
  }
3991
4720
  const entryPointContents = readFileSync2(
3992
- join5(cliRootPath(), "workers", "prod", "entry-point.js"),
4721
+ join6(cliRootPath(), "workers", "prod", "entry-point.js"),
3993
4722
  "utf-8"
3994
4723
  );
3995
4724
  const entryPointResult = await build2({
@@ -4032,7 +4761,7 @@ async function compileProject(config, options, configPath) {
4032
4761
  }
4033
4762
  if (options.outputMetafile) {
4034
4763
  await writeJSONFile(
4035
- join5(options.outputMetafile, "entry-point.json"),
4764
+ join6(options.outputMetafile, "entry-point.json"),
4036
4765
  entryPointResult.metafile
4037
4766
  );
4038
4767
  }
@@ -4043,31 +4772,32 @@ async function compileProject(config, options, configPath) {
4043
4772
  const entryPointMetaOutput = entryPointResult.metafile.outputs[posix.join("out", "stdin.js")];
4044
4773
  invariant(entryPointMetaOutput, "Meta output for the entryPoint build is missing");
4045
4774
  const workerOutputFile = result.outputFiles.find(
4046
- (file) => file.path === join5(config.projectDir, "out", "stdin.js")
4775
+ (file) => file.path === join6(config.projectDir, "out", "stdin.js")
4047
4776
  );
4048
4777
  invariant(workerOutputFile, "Output file for the result build is missing");
4049
4778
  const workerSourcemapFile = result.outputFiles.find(
4050
- (file) => file.path === join5(config.projectDir, "out", "stdin.js.map")
4779
+ (file) => file.path === join6(config.projectDir, "out", "stdin.js.map")
4051
4780
  );
4052
4781
  invariant(workerSourcemapFile, "Sourcemap file for the result build is missing");
4053
4782
  const entryPointOutputFile = entryPointResult.outputFiles.find(
4054
- (file) => file.path === join5(config.projectDir, "out", "stdin.js")
4783
+ (file) => file.path === join6(config.projectDir, "out", "stdin.js")
4055
4784
  );
4056
4785
  invariant(entryPointOutputFile, "Output file for the entryPoint build is missing");
4057
4786
  await writeFile2(
4058
- join5(tempDir, "worker.js"),
4787
+ join6(tempDir, "worker.js"),
4059
4788
  `${workerOutputFile.text}
4060
4789
  //# sourceMappingURL=worker.js.map`
4061
4790
  );
4062
- await writeFile2(join5(tempDir, "worker.js.map"), workerSourcemapFile.text);
4063
- await writeFile2(join5(tempDir, "index.js"), entryPointOutputFile.text);
4791
+ await writeFile2(join6(tempDir, "worker.js.map"), workerSourcemapFile.text);
4792
+ await writeFile2(join6(tempDir, "index.js"), entryPointOutputFile.text);
4064
4793
  logger.debug("Getting the imports for the worker and entryPoint builds", {
4065
4794
  workerImports: metaOutput.imports,
4066
4795
  entryPointImports: entryPointMetaOutput.imports
4067
4796
  });
4068
4797
  const allImports = [...metaOutput.imports, ...entryPointMetaOutput.imports];
4069
4798
  const javascriptProject = new JavascriptProject(config.projectDir);
4070
- const dependencies2 = await gatherRequiredDependencies(allImports, config, javascriptProject);
4799
+ const dependencies2 = await resolveRequiredDependencies(allImports, config, javascriptProject);
4800
+ logger.debug("gatherRequiredDependencies()", { dependencies: dependencies2 });
4071
4801
  const packageJsonContents = {
4072
4802
  name: "trigger-worker",
4073
4803
  version: "0.0.0",
@@ -4077,9 +4807,26 @@ async function compileProject(config, options, configPath) {
4077
4807
  ...javascriptProject.scripts
4078
4808
  }
4079
4809
  };
4080
- await writeJSONFile(join5(tempDir, "package.json"), packageJsonContents);
4081
- await copyAdditionalFiles(config, tempDir);
4082
- compileSpinner.stop("Project built successfully");
4810
+ span.setAttributes({
4811
+ ...flattenAttributes3(packageJsonContents, "packageJson.contents")
4812
+ });
4813
+ await writeJSONFile(join6(tempDir, "package.json"), packageJsonContents);
4814
+ const copyResult = await copyAdditionalFiles(config, tempDir);
4815
+ if (!copyResult.ok) {
4816
+ compileSpinner.stop("Project built with warnings");
4817
+ log5.warn(
4818
+ `No additionalFiles matches for:
4819
+
4820
+ ${copyResult.noMatches.map((glob) => `- "${glob}"`).join("\n")}
4821
+
4822
+ If this is unexpected you should check your ${terminalLink2(
4823
+ "glob patterns",
4824
+ "https://github.com/isaacs/node-glob?tab=readme-ov-file#glob-primer"
4825
+ )} are valid.`
4826
+ );
4827
+ } else {
4828
+ compileSpinner.stop("Project built successfully");
4829
+ }
4083
4830
  const resolvingDependenciesResult = await resolveDependencies(
4084
4831
  tempDir,
4085
4832
  packageJsonContents,
@@ -4089,32 +4836,96 @@ async function compileProject(config, options, configPath) {
4089
4836
  if (!resolvingDependenciesResult) {
4090
4837
  throw new SkipLoggingError("Failed to resolve dependencies");
4091
4838
  }
4092
- const containerFilePath = join5(cliRootPath(), "Containerfile.prod");
4093
- await copyFile(containerFilePath, join5(tempDir, "Containerfile"));
4839
+ const containerFilePath = join6(cliRootPath(), "Containerfile.prod");
4840
+ let containerFileContents = readFileSync2(containerFilePath, "utf-8");
4841
+ if (config.postInstall) {
4842
+ containerFileContents = containerFileContents.replace(
4843
+ "__POST_INSTALL__",
4844
+ `RUN ${config.postInstall}`
4845
+ );
4846
+ } else {
4847
+ containerFileContents = containerFileContents.replace("__POST_INSTALL__", "");
4848
+ }
4849
+ await writeFile2(join6(tempDir, "Containerfile"), containerFileContents);
4094
4850
  const contentHasher = createHash("sha256");
4095
4851
  contentHasher.update(Buffer.from(entryPointOutputFile.text));
4096
4852
  contentHasher.update(Buffer.from(workerOutputFile.text));
4097
4853
  contentHasher.update(Buffer.from(JSON.stringify(dependencies2)));
4098
4854
  const contentHash = contentHasher.digest("hex");
4099
- const workerSetupEnvVars = await findAllEnvironmentVariableReferencesInFile(workerSetupPath);
4100
- const workerFacadeEnvVars = findAllEnvironmentVariableReferences(workerContents);
4101
- const envVars = findAllEnvironmentVariableReferences(workerOutputFile.text);
4102
- const finalEnvVars = envVars.filter(
4103
- (envVar) => !workerFacadeEnvVars.includes(envVar) && !workerSetupEnvVars.includes(envVar)
4104
- );
4105
4855
  span.setAttributes({
4106
- contentHash,
4107
- envVars: finalEnvVars
4856
+ contentHash
4108
4857
  });
4109
4858
  span.end();
4110
- return { path: tempDir, contentHash, envVars: finalEnvVars };
4859
+ return { path: tempDir, contentHash };
4111
4860
  } catch (e) {
4112
- recordSpanException4(span, e);
4861
+ recordSpanException5(span, e);
4113
4862
  span.end();
4114
4863
  throw e;
4115
4864
  }
4116
4865
  });
4117
4866
  }
4867
+ async function resolveEnvironmentVariables(config, apiClient2, options) {
4868
+ if (config.status !== "file") {
4869
+ return;
4870
+ }
4871
+ if (!config.module || typeof config.module.resolveEnvVars !== "function") {
4872
+ return;
4873
+ }
4874
+ const projectConfig = config.config;
4875
+ return await tracer.startActiveSpan("resolveEnvironmentVariables", async (span) => {
4876
+ try {
4877
+ const $spinner = spinner();
4878
+ $spinner.start("Resolving environment variables");
4879
+ let processEnv = {
4880
+ ...process.env
4881
+ };
4882
+ const environmentVariables = await apiClient2.getEnvironmentVariables(projectConfig.project);
4883
+ if (environmentVariables.success) {
4884
+ processEnv = {
4885
+ ...processEnv,
4886
+ ...environmentVariables.data.variables
4887
+ };
4888
+ }
4889
+ logger.debug("Existing environment variables", {
4890
+ keys: Object.keys(processEnv)
4891
+ });
4892
+ const resolvedEnvVars2 = await callResolveEnvVars(
4893
+ config.module,
4894
+ processEnv,
4895
+ options.env,
4896
+ projectConfig.project
4897
+ );
4898
+ if (resolvedEnvVars2) {
4899
+ const total = Object.keys(resolvedEnvVars2.variables).length;
4900
+ logger.debug("Resolved env vars", {
4901
+ keys: Object.keys(resolvedEnvVars2.variables)
4902
+ });
4903
+ if (total > 0) {
4904
+ $spinner.message(
4905
+ `Syncing ${total} environment variable${total > 1 ? "s" : ""} with the server`
4906
+ );
4907
+ const uploadResult = await apiClient2.importEnvVars(projectConfig.project, options.env, {
4908
+ variables: resolvedEnvVars2.variables,
4909
+ override: typeof resolvedEnvVars2.override === "boolean" ? resolvedEnvVars2.override : true
4910
+ });
4911
+ if (uploadResult.success) {
4912
+ $spinner.stop(`${total} environment variable${total > 1 ? "s" : ""} synced`);
4913
+ } else {
4914
+ $spinner.stop("Failed to sync environment variables");
4915
+ throw new Error(uploadResult.error);
4916
+ }
4917
+ } else {
4918
+ $spinner.stop("No environment variables to sync");
4919
+ }
4920
+ }
4921
+ } catch (e) {
4922
+ recordSpanException5(span, e);
4923
+ throw e;
4924
+ } finally {
4925
+ span.end();
4926
+ }
4927
+ });
4928
+ }
4118
4929
  async function resolveDependencies(projectDir, packageJsonContents, config, options) {
4119
4930
  return await tracer.startActiveSpan("resolveDependencies", async (span) => {
4120
4931
  const resolvingDepsSpinner = spinner();
@@ -4122,17 +4933,17 @@ async function resolveDependencies(projectDir, packageJsonContents, config, opti
4122
4933
  const hasher = createHash("sha256");
4123
4934
  hasher.update(JSON.stringify(packageJsonContents));
4124
4935
  const digest = hasher.digest("hex").slice(0, 16);
4125
- const cacheDir = join5(config.projectDir, ".trigger", "cache");
4126
- const cachePath = join5(cacheDir, `${digest}.json`);
4936
+ const cacheDir = join6(config.projectDir, ".trigger", "cache");
4937
+ const cachePath = join6(cacheDir, `${digest}.json`);
4127
4938
  span.setAttributes({
4128
4939
  "packageJson.digest": digest,
4129
4940
  "cache.path": cachePath,
4130
- ...flattenAttributes2(packageJsonContents, "packageJson.contents")
4941
+ ...flattenAttributes3(packageJsonContents, "packageJson.contents")
4131
4942
  });
4132
4943
  try {
4133
4944
  const cachedPackageLock = await readFile2(cachePath, "utf-8");
4134
4945
  logger.debug(`Using cached package-lock.json for ${digest}`);
4135
- await writeFile2(join5(projectDir, "package-lock.json"), cachedPackageLock);
4946
+ await writeFile2(join6(projectDir, "package-lock.json"), cachedPackageLock);
4136
4947
  span.setAttributes({
4137
4948
  "cache.hit": true
4138
4949
  });
@@ -4151,20 +4962,39 @@ async function resolveDependencies(projectDir, packageJsonContents, config, opti
4151
4962
  });
4152
4963
  logger.debug(`No cached package-lock.json found for ${digest}`);
4153
4964
  try {
4154
- await execa2("npm", ["install", "--package-lock-only", "--ignore-scripts", "--no-audit"], {
4155
- cwd: projectDir,
4156
- stdio: logger.loggerLevel === "debug" ? "inherit" : "pipe"
4157
- });
4158
- const packageLockContents = await readFile2(join5(projectDir, "package-lock.json"), "utf-8");
4965
+ if (logger.loggerLevel === "debug") {
4966
+ const childProcess2 = await execa2("npm", ["config", "list"], {
4967
+ cwd: projectDir,
4968
+ stdio: "inherit"
4969
+ });
4970
+ logger.debug("npm config list");
4971
+ console.log(childProcess2.stdout);
4972
+ }
4973
+ await execa2(
4974
+ "npm",
4975
+ [
4976
+ "install",
4977
+ "--package-lock-only",
4978
+ "--ignore-scripts",
4979
+ "--no-audit",
4980
+ "--legacy-peer-deps=false",
4981
+ "--strict-peer-deps=false"
4982
+ ],
4983
+ {
4984
+ cwd: projectDir,
4985
+ stdio: logger.loggerLevel === "debug" ? "inherit" : "pipe"
4986
+ }
4987
+ );
4988
+ const packageLockContents = await readFile2(join6(projectDir, "package-lock.json"), "utf-8");
4159
4989
  logger.debug(`Writing package-lock.json to cache for ${digest}`);
4160
4990
  await mkdir(cacheDir, { recursive: true });
4161
4991
  await writeFile2(cachePath, packageLockContents);
4162
- await writeFile2(join5(projectDir, "package-lock.json"), packageLockContents);
4992
+ await writeFile2(join6(projectDir, "package-lock.json"), packageLockContents);
4163
4993
  span.end();
4164
4994
  resolvingDepsSpinner.stop("Dependencies resolved");
4165
4995
  return true;
4166
4996
  } catch (installError) {
4167
- recordSpanException4(span, installError);
4997
+ recordSpanException5(span, installError);
4168
4998
  span.end();
4169
4999
  const parsedError = parseNpmInstallError(installError);
4170
5000
  if (typeof parsedError === "string") {
@@ -4211,8 +5041,8 @@ async function typecheckProject(config, options) {
4211
5041
  tscTypecheck.stdout?.on("data", (chunk) => stdouts.push(chunk.toString()));
4212
5042
  tscTypecheck.stderr?.on("data", (chunk) => stderrs.push(chunk.toString()));
4213
5043
  try {
4214
- await new Promise((resolve4, reject) => {
4215
- tscTypecheck.addListener("exit", (code) => code === 0 ? resolve4(code) : reject(code));
5044
+ await new Promise((resolve6, reject) => {
5045
+ tscTypecheck.addListener("exit", (code) => code === 0 ? resolve6(code) : reject(code));
4216
5046
  });
4217
5047
  } catch (error) {
4218
5048
  typecheckSpinner.stop(
@@ -4230,64 +5060,100 @@ async function typecheckProject(config, options) {
4230
5060
  span.end();
4231
5061
  return true;
4232
5062
  } catch (e) {
4233
- recordSpanException4(span, e);
5063
+ recordSpanException5(span, e);
4234
5064
  span.end();
4235
5065
  return false;
4236
5066
  }
4237
5067
  });
4238
5068
  }
4239
- async function gatherRequiredDependencies(imports, config, project) {
4240
- const dependencies2 = {};
4241
- for (const file of imports) {
4242
- if (file.kind !== "require-call" && file.kind !== "dynamic-import" || !file.external) {
4243
- continue;
4244
- }
4245
- const packageName = detectPackageNameFromImportPath(file.path);
4246
- if (dependencies2[packageName]) {
4247
- continue;
4248
- }
4249
- const externalDependencyVersion = await project.resolve(packageName);
4250
- if (externalDependencyVersion) {
4251
- dependencies2[packageName] = stripWorkspaceFromVersion(externalDependencyVersion);
4252
- continue;
4253
- }
4254
- const internalDependencyVersion = dependencies[packageName] ?? detectDependencyVersion(packageName);
4255
- if (internalDependencyVersion) {
4256
- dependencies2[packageName] = stripWorkspaceFromVersion(internalDependencyVersion);
4257
- }
4258
- }
4259
- if (config.additionalPackages) {
4260
- for (const packageName of config.additionalPackages) {
4261
- if (dependencies2[packageName]) {
5069
+ async function resolveRequiredDependencies(imports, config, project) {
5070
+ return await tracer.startActiveSpan("resolveRequiredDependencies", async (span) => {
5071
+ const resolvablePackageNames = /* @__PURE__ */ new Set();
5072
+ for (const file of imports) {
5073
+ if (file.kind !== "require-call" && file.kind !== "dynamic-import" || !file.external) {
4262
5074
  continue;
4263
5075
  }
4264
- const packageParts = parsePackageName(packageName);
4265
- if (packageParts.version) {
4266
- dependencies2[packageParts.name] = packageParts.version;
5076
+ const packageName = detectPackageNameFromImportPath(file.path);
5077
+ if (!packageName) {
4267
5078
  continue;
4268
- } else {
4269
- const externalDependencyVersion = await project.resolve(packageParts.name, {
4270
- allowDev: true
4271
- });
4272
- if (externalDependencyVersion) {
4273
- dependencies2[packageParts.name] = externalDependencyVersion;
5079
+ }
5080
+ resolvablePackageNames.add(packageName);
5081
+ }
5082
+ span.setAttribute("resolvablePackageNames", Array.from(resolvablePackageNames));
5083
+ const resolvedPackageVersions = await project.resolveAll(Array.from(resolvablePackageNames));
5084
+ const missingPackages = Array.from(resolvablePackageNames).filter(
5085
+ (packageName) => !resolvedPackageVersions[packageName]
5086
+ );
5087
+ span.setAttributes({
5088
+ ...flattenAttributes3(resolvedPackageVersions, "resolvedPackageVersions")
5089
+ });
5090
+ span.setAttribute("missingPackages", missingPackages);
5091
+ const dependencies2 = {};
5092
+ for (const missingPackage of missingPackages) {
5093
+ const internalDependencyVersion = dependencies[missingPackage] ?? detectDependencyVersion(missingPackage);
5094
+ if (internalDependencyVersion) {
5095
+ dependencies2[missingPackage] = stripWorkspaceFromVersion(internalDependencyVersion);
5096
+ }
5097
+ }
5098
+ for (const [packageName, version2] of Object.entries(resolvedPackageVersions)) {
5099
+ dependencies2[packageName] = version2;
5100
+ }
5101
+ if (config.additionalPackages) {
5102
+ span.setAttribute("additionalPackages", config.additionalPackages);
5103
+ for (const packageName of config.additionalPackages) {
5104
+ if (dependencies2[packageName]) {
5105
+ continue;
5106
+ }
5107
+ const packageParts = parsePackageName(packageName);
5108
+ if (packageParts.version) {
5109
+ dependencies2[packageParts.name] = packageParts.version;
4274
5110
  continue;
4275
5111
  } else {
4276
- logger.log(
4277
- `${chalkWarning("X Warning:")} Could not find version for package ${chalkPurple(
4278
- packageName
4279
- )}, add a version specifier to the package name (e.g. ${packageParts.name}@latest) or add it to your project's package.json`
4280
- );
5112
+ const externalDependencyVersion = await project.resolve(packageParts.name, {
5113
+ allowDev: true
5114
+ });
5115
+ if (externalDependencyVersion) {
5116
+ dependencies2[packageParts.name] = externalDependencyVersion;
5117
+ continue;
5118
+ } else {
5119
+ logger.log(
5120
+ `${chalkWarning("X Warning:")} Could not find version for package ${chalkPurple(
5121
+ packageName
5122
+ )}, add a version specifier to the package name (e.g. ${packageParts.name}@latest) or add it to your project's package.json`
5123
+ );
5124
+ }
4281
5125
  }
4282
5126
  }
4283
5127
  }
4284
- }
4285
- return Object.fromEntries(Object.entries(dependencies2).sort(([a], [b]) => a.localeCompare(b)));
5128
+ if (!dependencies2["@trigger.dev/sdk"]) {
5129
+ logger.debug("Adding missing @trigger.dev/sdk dependency", {
5130
+ version
5131
+ });
5132
+ span.setAttribute("addingMissingSDK", version);
5133
+ dependencies2["@trigger.dev/sdk"] = version;
5134
+ }
5135
+ if (!dependencies2["@trigger.dev/core"]) {
5136
+ logger.debug("Adding missing @trigger.dev/core dependency", {
5137
+ version
5138
+ });
5139
+ span.setAttribute("addingMissingCore", version);
5140
+ dependencies2["@trigger.dev/core"] = version;
5141
+ }
5142
+ const result = Object.fromEntries(
5143
+ Object.entries(dependencies2).sort(([a], [b]) => a.localeCompare(b))
5144
+ );
5145
+ span.setAttributes({
5146
+ ...flattenAttributes3(result, "dependencies")
5147
+ });
5148
+ span.end();
5149
+ return result;
5150
+ });
4286
5151
  }
4287
5152
  async function copyAdditionalFiles(config, tempDir) {
4288
5153
  const additionalFiles = config.additionalFiles ?? [];
5154
+ const noMatches = [];
4289
5155
  if (additionalFiles.length === 0) {
4290
- return;
5156
+ return { ok: true };
4291
5157
  }
4292
5158
  return await tracer.startActiveSpan(
4293
5159
  "copyAdditionalFiles",
@@ -4301,24 +5167,57 @@ async function copyAdditionalFiles(config, tempDir) {
4301
5167
  logger.debug(`Copying files to ${tempDir}`, {
4302
5168
  additionalFiles
4303
5169
  });
4304
- const glob = new Glob(additionalFiles, {
5170
+ const globOptions = {
4305
5171
  withFileTypes: true,
4306
5172
  ignore: ["node_modules"],
4307
5173
  cwd: config.projectDir,
4308
5174
  nodir: true
4309
- });
4310
- for await (const file of glob) {
4311
- const relativeDestinationPath = join5(
4312
- tempDir,
4313
- relative3(config.projectDir, file.fullpath())
4314
- );
4315
- logger.debug(`Copying file ${file.fullpath()} to ${relativeDestinationPath}`);
4316
- await mkdir(dirname(relativeDestinationPath), { recursive: true });
4317
- await copyFile(file.fullpath(), relativeDestinationPath);
5175
+ };
5176
+ const globs = [];
5177
+ let i = 0;
5178
+ for (const additionalFile of additionalFiles) {
5179
+ let glob;
5180
+ if (i === 0) {
5181
+ glob = new Glob(additionalFile, globOptions);
5182
+ } else {
5183
+ const previousGlob = globs[i - 1];
5184
+ if (!previousGlob) {
5185
+ logger.error("No previous glob, this shouldn't happen", { i, additionalFiles });
5186
+ continue;
5187
+ }
5188
+ glob = new Glob(additionalFile, previousGlob);
5189
+ }
5190
+ if (!(Symbol.asyncIterator in glob)) {
5191
+ logger.error("Glob should be an async iterator", { glob });
5192
+ throw new Error("Unrecoverable error while copying additional files");
5193
+ }
5194
+ let matches = 0;
5195
+ for await (const file of glob) {
5196
+ matches++;
5197
+ const pathInsideTempDir = relative3(config.projectDir, file.fullpath()).split(posix.sep).filter((p) => p !== "..").join(posix.sep);
5198
+ const relativeDestinationPath = join6(tempDir, pathInsideTempDir);
5199
+ logger.debug(`Copying file ${file.fullpath()} to ${relativeDestinationPath}`);
5200
+ await mkdir(dirname(relativeDestinationPath), { recursive: true });
5201
+ await copyFile(file.fullpath(), relativeDestinationPath);
5202
+ }
5203
+ if (matches === 0) {
5204
+ noMatches.push(additionalFile);
5205
+ }
5206
+ globs[i] = glob;
5207
+ i++;
4318
5208
  }
4319
5209
  span.end();
5210
+ if (noMatches.length > 0) {
5211
+ return {
5212
+ ok: false,
5213
+ noMatches
5214
+ };
5215
+ }
5216
+ return {
5217
+ ok: true
5218
+ };
4320
5219
  } catch (error) {
4321
- recordSpanException4(span, error);
5220
+ recordSpanException5(span, error);
4322
5221
  span.end();
4323
5222
  throw error;
4324
5223
  }
@@ -4327,7 +5226,7 @@ async function copyAdditionalFiles(config, tempDir) {
4327
5226
  }
4328
5227
  async function ensureLoggedIntoDockerRegistry(registryHost, auth) {
4329
5228
  const tmpDir = await createTempDir();
4330
- const dockerConfigPath = join5(tmpDir, "config.json");
5229
+ const dockerConfigPath = join6(tmpDir, "config.json");
4331
5230
  await writeJSONFile(dockerConfigPath, {
4332
5231
  auths: {
4333
5232
  [registryHost]: {
@@ -4338,42 +5237,20 @@ async function ensureLoggedIntoDockerRegistry(registryHost, auth) {
4338
5237
  logger.debug(`Writing docker config to ${dockerConfigPath}`);
4339
5238
  return tmpDir;
4340
5239
  }
4341
- async function findAllEnvironmentVariableReferencesInFile(filePath) {
4342
- const fileContents = await readFile2(filePath, "utf-8");
4343
- return findAllEnvironmentVariableReferences(fileContents);
4344
- }
4345
- var IGNORED_ENV_VARS = ["NODE_ENV", "SHELL", "HOME", "PWD", "LOGNAME", "USER", "PATH", "DEBUG"];
4346
- function findAllEnvironmentVariableReferences(code) {
4347
- const regex = /\bprocess\.env\.([a-zA-Z_][a-zA-Z0-9_]*)\b/g;
4348
- const matches = code.matchAll(regex);
4349
- const matchesArray = Array.from(matches, (match) => match[1]).filter(Boolean);
4350
- const filteredMatches = matchesArray.filter((match) => !IGNORED_ENV_VARS.includes(match));
4351
- return Array.from(new Set(filteredMatches));
4352
- }
4353
- function arrayToSentence(items) {
4354
- if (items.length === 1 && typeof items[0] === "string") {
4355
- return items[0];
4356
- }
4357
- if (items.length === 2) {
4358
- return `${items[0]} and ${items[1]}`;
4359
- }
4360
- return `${items.slice(0, -1).join(", ")}, and ${items[items.length - 1]}`;
4361
- }
4362
5240
 
4363
5241
  // src/commands/dev.tsx
4364
5242
  import {
4365
- ZodMessageHandler as ZodMessageHandler2,
4366
- ZodMessageSender as ZodMessageSender2,
4367
5243
  clientWebsocketMessages,
4368
5244
  detectDependencyVersion as detectDependencyVersion2,
4369
5245
  serverWebsocketMessages
4370
5246
  } from "@trigger.dev/core/v3";
5247
+ import { ZodMessageHandler as ZodMessageHandler2, ZodMessageSender as ZodMessageSender2 } from "@trigger.dev/core/v3/zodMessageHandler";
4371
5248
  import { watch } from "chokidar";
4372
5249
  import { context as context2 } from "esbuild";
4373
5250
  import { render, useInput } from "ink";
4374
5251
  import { createHash as createHash2 } from "node:crypto";
4375
5252
  import fs7, { readFileSync as readFileSync3 } from "node:fs";
4376
- import { basename, dirname as dirname3, join as join6, normalize } from "node:path";
5253
+ import { basename as basename2, dirname as dirname3, join as join7, normalize } from "node:path";
4377
5254
  import pDebounce from "p-debounce";
4378
5255
  import { WebSocket } from "partysocket";
4379
5256
  import React, { Suspense, useEffect } from "react";
@@ -4402,18 +5279,17 @@ var TaskMetadataParseError = class extends Error {
4402
5279
  import {
4403
5280
  SemanticInternalAttributes,
4404
5281
  TaskRunErrorCodes,
4405
- ZodMessageHandler,
4406
- ZodMessageSender,
4407
5282
  childToWorkerMessages,
4408
5283
  correctErrorStackTrace,
4409
5284
  formatDurationMilliseconds,
4410
5285
  workerToChildMessages
4411
5286
  } from "@trigger.dev/core/v3";
5287
+ import { ZodMessageHandler, ZodMessageSender } from "@trigger.dev/core/v3/zodMessageHandler";
4412
5288
  import dotenv from "dotenv";
4413
5289
  import { Evt } from "evt";
4414
5290
  import { fork } from "node:child_process";
4415
- import { dirname as dirname2, resolve as resolve2 } from "node:path";
4416
- import terminalLink2 from "terminal-link";
5291
+ import { dirname as dirname2, resolve as resolve4 } from "node:path";
5292
+ import terminalLink3 from "terminal-link";
4417
5293
  var BackgroundWorkerCoordinator = class {
4418
5294
  constructor(baseURL) {
4419
5295
  this.baseURL = baseURL;
@@ -4498,7 +5374,7 @@ var BackgroundWorkerCoordinator = class {
4498
5374
  const logsUrl = `${this.baseURL}/runs/${execution.run.id}`;
4499
5375
  const pipe = chalkGrey("|");
4500
5376
  const bullet = chalkGrey("\u25CB");
4501
- const link = chalkLink(terminalLink2("View logs", logsUrl));
5377
+ const link = chalkLink(terminalLink3("View logs", logsUrl));
4502
5378
  let timestampPrefix = chalkGrey(prettyPrintDate(payload.execution.attempt.startedAt));
4503
5379
  const workerPrefix = chalkWorker(record.version);
4504
5380
  const taskPrefix = chalkTask(execution.task.id);
@@ -4585,6 +5461,7 @@ var BackgroundWorker = class {
4585
5461
  metadata;
4586
5462
  _taskRunProcesses = /* @__PURE__ */ new Map();
4587
5463
  _closed = false;
5464
+ _fullEnv = {};
4588
5465
  close() {
4589
5466
  if (this._closed) {
4590
5467
  return;
@@ -4607,12 +5484,24 @@ var BackgroundWorker = class {
4607
5484
  }
4608
5485
  let resolved = false;
4609
5486
  const cwd = dirname2(this.path);
4610
- const fullEnv = {
5487
+ this._fullEnv = {
4611
5488
  ...this.params.env,
4612
- ...this.#readEnvVars()
5489
+ ...this.#readEnvVars(),
5490
+ ...this.params.debugOtel ? { OTEL_LOG_LEVEL: "debug" } : {}
5491
+ };
5492
+ let resolvedEnvVars2 = {};
5493
+ if (this.params.resolveEnvVariables) {
5494
+ const resolvedEnv = await this.params.resolveEnvVariables(this._fullEnv, this);
5495
+ if (resolvedEnv) {
5496
+ resolvedEnvVars2 = resolvedEnv;
5497
+ }
5498
+ }
5499
+ this._fullEnv = {
5500
+ ...this._fullEnv,
5501
+ ...resolvedEnvVars2
4613
5502
  };
4614
- logger.debug("Initializing worker", { path: this.path, cwd, fullEnv });
4615
- this.tasks = await new Promise((resolve4, reject) => {
5503
+ logger.debug("Initializing worker", { path: this.path, cwd, fullEnv: this._fullEnv });
5504
+ this.tasks = await new Promise((resolve6, reject) => {
4616
5505
  const child = fork(this.path, {
4617
5506
  stdio: [
4618
5507
  /*stdin*/
@@ -4624,7 +5513,7 @@ var BackgroundWorker = class {
4624
5513
  "ipc"
4625
5514
  ],
4626
5515
  cwd,
4627
- env: fullEnv
5516
+ env: this._fullEnv
4628
5517
  });
4629
5518
  const timeout = setTimeout(() => {
4630
5519
  if (resolved) {
@@ -4639,7 +5528,7 @@ var BackgroundWorker = class {
4639
5528
  if (message.type === "TASKS_READY" && !resolved) {
4640
5529
  clearTimeout(timeout);
4641
5530
  resolved = true;
4642
- resolve4(message.payload.tasks);
5531
+ resolve6(message.payload.tasks);
4643
5532
  child.kill();
4644
5533
  } else if (message.type === "UNCAUGHT_EXCEPTION") {
4645
5534
  clearTimeout(timeout);
@@ -4682,9 +5571,8 @@ var BackgroundWorker = class {
4682
5571
  payload.execution,
4683
5572
  this.path,
4684
5573
  {
4685
- ...this.params.env,
4686
- ...payload.environment ?? {},
4687
- ...this.#readEnvVars()
5574
+ ...this._fullEnv,
5575
+ ...payload.environment ?? {}
4688
5576
  },
4689
5577
  this.metadata,
4690
5578
  this.params
@@ -4774,7 +5662,7 @@ var BackgroundWorker = class {
4774
5662
  const result = {};
4775
5663
  dotenv.config({
4776
5664
  processEnv: result,
4777
- path: [".env", ".env.local", ".env.development.local"].map((p) => resolve2(process.cwd(), p))
5665
+ path: [".env", ".env.local", ".env.development.local"].map((p) => resolve4(process.cwd(), p))
4778
5666
  });
4779
5667
  process.env.TRIGGER_API_URL && (result.TRIGGER_API_URL = process.env.TRIGGER_API_URL);
4780
5668
  delete result.TRIGGER_API_URL;
@@ -4865,12 +5753,18 @@ var TaskRunProcess = class {
4865
5753
  kill
4866
5754
  });
4867
5755
  this._isBeingKilled = kill;
5756
+ setTimeout(() => {
5757
+ if (this._child && !this._child.killed) {
5758
+ logger.debug(`[${this.execution.run.id}] killing task run process after timeout`);
5759
+ this._child.kill();
5760
+ }
5761
+ }, 5e3);
4868
5762
  }
4869
5763
  async executeTaskRun(payload) {
4870
5764
  let resolver;
4871
5765
  let rejecter;
4872
- const promise = new Promise((resolve4, reject) => {
4873
- resolver = resolve4;
5766
+ const promise = new Promise((resolve6, reject) => {
5767
+ resolver = resolve6;
4874
5768
  rejecter = reject;
4875
5769
  });
4876
5770
  this._attemptStatuses.set(payload.execution.attempt.id, "PENDING");
@@ -4921,6 +5815,7 @@ var TaskRunProcess = class {
4921
5815
  break;
4922
5816
  }
4923
5817
  case "READY_TO_DISPOSE": {
5818
+ logger.debug(`[${this.execution.run.id}] task run process is ready to dispose`);
4924
5819
  this.#kill();
4925
5820
  break;
4926
5821
  }
@@ -4983,6 +5878,7 @@ var TaskRunProcess = class {
4983
5878
  }
4984
5879
  #kill() {
4985
5880
  if (this._child && !this._child.killed) {
5881
+ logger.debug(`[${this.execution.run.id}] killing task run process`);
4986
5882
  this._child?.kill();
4987
5883
  }
4988
5884
  }
@@ -5009,19 +5905,21 @@ function runtimeCheck(minimumMajor, minimumMinor) {
5009
5905
 
5010
5906
  // src/commands/dev.tsx
5011
5907
  import { findUp as findUp3, pathExists as pathExists2 } from "find-up";
5908
+ import { esbuildDecorators as esbuildDecorators3 } from "@anatine/esbuild-decorators";
5012
5909
  var apiClient;
5013
5910
  var DevCommandOptions = CommonCommandOptions.extend({
5014
5911
  debugger: z5.boolean().default(false),
5015
5912
  debugOtel: z5.boolean().default(false),
5016
5913
  config: z5.string().optional(),
5017
- projectRef: z5.string().optional()
5914
+ projectRef: z5.string().optional(),
5915
+ skipUpdateCheck: z5.boolean().default(false)
5018
5916
  });
5019
5917
  function configureDevCommand(program2) {
5020
5918
  return commonOptions(
5021
5919
  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(
5022
5920
  "-p, --project-ref <project ref>",
5023
5921
  "The project ref. Required if there is no config file."
5024
- ).option("--debugger", "Enable the debugger").option("--debug-otel", "Enable OpenTelemetry debugging")
5922
+ ).option("--debugger", "Enable the debugger").option("--debug-otel", "Enable OpenTelemetry debugging").option("--skip-update-check", "Skip checking for @trigger.dev package updates")
5025
5923
  ).action(async (path7, options) => {
5026
5924
  wrapCommandAction("dev", DevCommandOptions, options, async (opts) => {
5027
5925
  await devCommand(path7, opts);
@@ -5063,29 +5961,37 @@ async function startDev(dir, options, authorization, dashboardUrl) {
5063
5961
  logger.loggerLevel = options.logLevel;
5064
5962
  }
5065
5963
  await printStandloneInitialBanner(true);
5066
- printDevBanner();
5964
+ let displayedUpdateMessage = false;
5965
+ if (!options.skipUpdateCheck) {
5966
+ displayedUpdateMessage = await updateTriggerPackages(dir, { ...options }, true, true);
5967
+ }
5968
+ printDevBanner(displayedUpdateMessage);
5067
5969
  logger.debug("Starting dev session", { dir, options, authorization });
5068
5970
  let config = await readConfig(dir, {
5069
5971
  projectRef: options.projectRef,
5070
5972
  configFile: options.config
5071
5973
  });
5072
5974
  logger.debug("Initial config", { config });
5073
- async function getDevReactElement(configParam, authorization2, configPath) {
5975
+ if (config.status === "error") {
5976
+ logger.error("Failed to read config", config.error);
5977
+ process.exit(1);
5978
+ }
5979
+ async function getDevReactElement(configParam, authorization2, configPath, configModule) {
5074
5980
  const accessToken = authorization2.accessToken;
5075
5981
  const apiUrl = authorization2.apiUrl;
5076
5982
  apiClient = new CliApiClient(apiUrl, accessToken);
5077
5983
  const devEnv = await apiClient.getProjectEnv({
5078
- projectRef: config.config.project,
5984
+ projectRef: configParam.project,
5079
5985
  env: "dev"
5080
5986
  });
5081
5987
  if (!devEnv.success) {
5082
5988
  if (devEnv.error === "Project not found") {
5083
5989
  logger.error(
5084
- `Project not found: ${config.config.project}. Ensure you are using the correct project ref and CLI profile (use --profile). Currently using the "${options.profile}" profile, which points to ${authorization2.apiUrl}`
5990
+ `Project not found: ${configParam.project}. Ensure you are using the correct project ref and CLI profile (use --profile). Currently using the "${options.profile}" profile, which points to ${authorization2.apiUrl}`
5085
5991
  );
5086
5992
  } else {
5087
5993
  logger.error(
5088
- `Failed to initialize dev environment: ${devEnv.error}. Using project ref ${config.config.project}`
5994
+ `Failed to initialize dev environment: ${devEnv.error}. Using project ref ${configParam.project}`
5089
5995
  );
5090
5996
  }
5091
5997
  process.exit(1);
@@ -5102,7 +6008,8 @@ async function startDev(dir, options, authorization, dashboardUrl) {
5102
6008
  projectName: devEnv.data.name,
5103
6009
  debuggerOn: options.debugger,
5104
6010
  debugOtel: options.debugOtel,
5105
- configPath
6011
+ configPath,
6012
+ configModule
5106
6013
  }
5107
6014
  );
5108
6015
  }
@@ -5110,7 +6017,8 @@ async function startDev(dir, options, authorization, dashboardUrl) {
5110
6017
  await getDevReactElement(
5111
6018
  config.config,
5112
6019
  authorization,
5113
- config.status === "file" ? config.path : void 0
6020
+ config.status === "file" ? config.path : void 0,
6021
+ config.status === "file" ? config.module : void 0
5114
6022
  )
5115
6023
  );
5116
6024
  rerender = devReactElement.rerender;
@@ -5133,7 +6041,8 @@ function useDev({
5133
6041
  projectName,
5134
6042
  debuggerOn,
5135
6043
  debugOtel,
5136
- configPath
6044
+ configPath,
6045
+ configModule
5137
6046
  }) {
5138
6047
  useEffect(() => {
5139
6048
  const websocketUrl = new URL(apiUrl);
@@ -5222,18 +6131,21 @@ function useDev({
5222
6131
  await messageHandler.handleMessage(data);
5223
6132
  });
5224
6133
  let ctx;
6134
+ let firstBuild = true;
5225
6135
  async function runBuild() {
5226
6136
  if (ctx) {
5227
6137
  await ctx.dispose();
5228
6138
  }
5229
6139
  let latestWorkerContentHash;
5230
6140
  const taskFiles = await gatherTaskFiles(config);
5231
- const workerFacadePath = join6(cliRootPath(), "workers", "dev", "worker-facade.js");
6141
+ const workerFacadePath = join7(cliRootPath(), "workers", "dev", "worker-facade.js");
5232
6142
  const workerFacade = readFileSync3(workerFacadePath, "utf-8");
5233
- const workerSetupPath = join6(cliRootPath(), "workers", "dev", "worker-setup.js");
6143
+ const workerSetupPath = join7(cliRootPath(), "workers", "dev", "worker-setup.js");
5234
6144
  let entryPointContents = workerFacade.replace("__TASKS__", createTaskFileImports(taskFiles)).replace(
5235
6145
  "__WORKER_SETUP__",
5236
- `import { tracingSDK, sender } from "${escapeImportPath(workerSetupPath)}";`
6146
+ `import { tracingSDK, otelTracer, otelLogger, sender } from "${escapeImportPath(
6147
+ workerSetupPath
6148
+ )}";`
5237
6149
  );
5238
6150
  if (configPath) {
5239
6151
  configPath = normalize(configPath);
@@ -5250,7 +6162,6 @@ function useDev({
5250
6162
  `const importedConfig = undefined; const handleError = undefined;`
5251
6163
  );
5252
6164
  }
5253
- let firstBuild = true;
5254
6165
  logger.log(chalkGrey("\u25CB Building background worker\u2026"));
5255
6166
  ctx = await context2({
5256
6167
  stdin: {
@@ -5258,6 +6169,9 @@ function useDev({
5258
6169
  resolveDir: process.cwd(),
5259
6170
  sourcefile: "__entryPoint.ts"
5260
6171
  },
6172
+ banner: {
6173
+ js: `process.on("uncaughtException", function(error, origin) { if (error instanceof Error) { process.send && process.send({ type: "UNCAUGHT_EXCEPTION", payload: { error: { name: error.name, message: error.message, stack: error.stack }, origin }, version: "v1" }); } else { process.send && process.send({ type: "UNCAUGHT_EXCEPTION", payload: { error: { name: "Error", message: typeof error === "string" ? error : JSON.stringify(error) }, origin }, version: "v1" }); } });`
6174
+ },
5261
6175
  bundle: true,
5262
6176
  metafile: true,
5263
6177
  write: false,
@@ -5275,6 +6189,7 @@ function useDev({
5275
6189
  __PROJECT_CONFIG__: JSON.stringify(config)
5276
6190
  },
5277
6191
  plugins: [
6192
+ mockServerOnlyPlugin(),
5278
6193
  bundleTriggerDevCore("workerFacade", config.tsconfigPath),
5279
6194
  bundleDependenciesPlugin(
5280
6195
  "workerFacade",
@@ -5282,6 +6197,11 @@ function useDev({
5282
6197
  config.tsconfigPath
5283
6198
  ),
5284
6199
  workerSetupImportConfigPlugin(configPath),
6200
+ esbuildDecorators3({
6201
+ tsconfig: config.tsconfigPath,
6202
+ tsx: true,
6203
+ force: false
6204
+ }),
5285
6205
  {
5286
6206
  name: "trigger.dev v3",
5287
6207
  setup(build3) {
@@ -5295,22 +6215,19 @@ function useDev({
5295
6215
  if (!firstBuild) {
5296
6216
  logger.log(chalkGrey("\u25CB Building background worker\u2026"));
5297
6217
  }
5298
- const metaOutputKey = join6("out", `stdin.js`).replace(/\\/g, "/");
5299
- logger.debug("Metafile", {
5300
- metafileOutputs: JSON.stringify(result.metafile?.outputs)
5301
- });
6218
+ const metaOutputKey = join7("out", `stdin.js`).replace(/\\/g, "/");
5302
6219
  const metaOutput = result.metafile.outputs[metaOutputKey];
5303
6220
  if (!metaOutput) {
5304
6221
  throw new Error(`Could not find metafile`);
5305
6222
  }
5306
- const outputFileKey = join6(config.projectDir, metaOutputKey);
6223
+ const outputFileKey = join7(config.projectDir, metaOutputKey);
5307
6224
  const outputFile = result.outputFiles.find((file) => file.path === outputFileKey);
5308
6225
  if (!outputFile) {
5309
6226
  throw new Error(
5310
6227
  `Could not find output file for entry point ${metaOutput.entryPoint}`
5311
6228
  );
5312
6229
  }
5313
- const sourceMapFileKey = join6(config.projectDir, `${metaOutputKey}.map`);
6230
+ const sourceMapFileKey = join7(config.projectDir, `${metaOutputKey}.map`);
5314
6231
  const sourceMapFile = result.outputFiles.find(
5315
6232
  (file) => file.path === sourceMapFileKey
5316
6233
  );
@@ -5321,14 +6238,14 @@ function useDev({
5321
6238
  logger.log(chalkGrey("\u25CB No changes detected, skipping build\u2026"));
5322
6239
  return;
5323
6240
  }
5324
- const fullPath = join6(config.projectDir, ".trigger", `${contentHash}.js`);
6241
+ const fullPath = join7(config.projectDir, ".trigger", `${contentHash}.js`);
5325
6242
  const sourceMapPath = `${fullPath}.map`;
5326
6243
  const outputFileWithSourceMap = `${outputFile.text}
5327
- //# sourceMappingURL=${basename(sourceMapPath)}`;
6244
+ //# sourceMappingURL=${basename2(sourceMapPath)}`;
5328
6245
  await fs7.promises.mkdir(dirname3(fullPath), { recursive: true });
5329
6246
  await fs7.promises.writeFile(fullPath, outputFileWithSourceMap);
5330
6247
  logger.debug(`Wrote background worker to ${fullPath}`);
5331
- const dependencies2 = await gatherRequiredDependencies2(metaOutput, config);
6248
+ const dependencies2 = await gatherRequiredDependencies(metaOutput, config);
5332
6249
  if (sourceMapFile) {
5333
6250
  const sourceMapPath2 = `${fullPath}.map`;
5334
6251
  await fs7.promises.writeFile(sourceMapPath2, sourceMapFile.text);
@@ -5345,15 +6262,23 @@ function useDev({
5345
6262
  ...environmentVariablesResponse.success ? environmentVariablesResponse.data.variables : {}
5346
6263
  },
5347
6264
  debuggerOn,
5348
- debugOtel
6265
+ debugOtel,
6266
+ resolveEnvVariables: createResolveEnvironmentVariablesFunction(configModule)
5349
6267
  });
5350
6268
  try {
5351
6269
  await backgroundWorker.initialize();
5352
6270
  latestWorkerContentHash = contentHash;
5353
6271
  let packageVersion;
5354
6272
  const taskResources = [];
5355
- if (!backgroundWorker.tasks) {
5356
- throw new Error(`Background Worker started without tasks`);
6273
+ if (!backgroundWorker.tasks || backgroundWorker.tasks.length === 0) {
6274
+ logger.log(
6275
+ `${chalkError(
6276
+ "X Error:"
6277
+ )} Worker failed to build: no tasks found. Searched in ${config.triggerDirectories.join(
6278
+ ", "
6279
+ )}`
6280
+ );
6281
+ return;
5357
6282
  }
5358
6283
  for (const task of backgroundWorker.tasks) {
5359
6284
  taskResources.push(task);
@@ -5372,6 +6297,9 @@ function useDev({
5372
6297
  );
5373
6298
  return;
5374
6299
  }
6300
+ logger.debug("Creating background worker with tasks", {
6301
+ tasks: taskResources
6302
+ });
5375
6303
  const backgroundWorkerBody = {
5376
6304
  localOnly: true,
5377
6305
  metadata: {
@@ -5415,10 +6343,10 @@ function useDev({
5415
6343
  return;
5416
6344
  } else {
5417
6345
  }
5418
- if (e.originalError.stack) {
6346
+ if (e.originalError.message || e.originalError.stack) {
5419
6347
  logger.log(
5420
6348
  `${chalkError("X Error:")} Worker failed to start`,
5421
- e.originalError.stack
6349
+ e.originalError.stack ?? e.originalError.message
5422
6350
  );
5423
6351
  }
5424
6352
  return;
@@ -5458,7 +6386,7 @@ ${chalkError("X Error:")} The package ${chalkPurple(
5458
6386
  }
5459
6387
  const throttledRebuild = pDebounce(runBuild, 250, { before: true });
5460
6388
  const taskFileWatcher = watch(
5461
- config.triggerDirectories.map((triggerDir) => `${triggerDir}/*.ts`),
6389
+ config.triggerDirectories.map((triggerDir) => `${triggerDir}/**/*.ts`),
5462
6390
  {
5463
6391
  ignoreInitial: true
5464
6392
  }
@@ -5509,7 +6437,7 @@ function WebsocketFactory(apiKey) {
5509
6437
  }
5510
6438
  };
5511
6439
  }
5512
- async function gatherRequiredDependencies2(outputMeta, config) {
6440
+ async function gatherRequiredDependencies(outputMeta, config) {
5513
6441
  const dependencies2 = {};
5514
6442
  logger.debug("Gathering required dependencies from imports", {
5515
6443
  imports: outputMeta.imports
@@ -5528,7 +6456,7 @@ async function gatherRequiredDependencies2(outputMeta, config) {
5528
6456
  }
5529
6457
  }
5530
6458
  if (config.additionalPackages) {
5531
- const projectPackageJson = await readJSONFile(join6(config.projectDir, "package.json"));
6459
+ const projectPackageJson = await readJSONFile(join7(config.projectDir, "package.json"));
5532
6460
  for (const packageName of config.additionalPackages) {
5533
6461
  if (dependencies2[packageName]) {
5534
6462
  continue;
@@ -5598,7 +6526,7 @@ async function amendNodePathWithPnpmNodeModules(nodePath) {
5598
6526
  async function findPnpmNodeModulesPath() {
5599
6527
  return await findUp3(
5600
6528
  async (directory) => {
5601
- const pnpmModules = join6(directory, "node_modules", ".pnpm", "node_modules");
6529
+ const pnpmModules = join7(directory, "node_modules", ".pnpm", "node_modules");
5602
6530
  const hasPnpmNodeModules = await pathExists2(pnpmModules);
5603
6531
  if (hasPnpmNodeModules) {
5604
6532
  return pnpmModules;
@@ -5607,20 +6535,38 @@ async function findPnpmNodeModulesPath() {
5607
6535
  { type: "directory" }
5608
6536
  );
5609
6537
  }
6538
+ var hasResolvedEnvVars = false;
6539
+ var resolvedEnvVars = {};
6540
+ function createResolveEnvironmentVariablesFunction(configModule) {
6541
+ return async (env, worker) => {
6542
+ if (hasResolvedEnvVars) {
6543
+ return resolvedEnvVars;
6544
+ }
6545
+ const $resolvedEnvVars = await callResolveEnvVars(
6546
+ configModule,
6547
+ env,
6548
+ "dev",
6549
+ worker.params.projectConfig.project
6550
+ );
6551
+ if ($resolvedEnvVars) {
6552
+ resolvedEnvVars = $resolvedEnvVars.variables;
6553
+ hasResolvedEnvVars = true;
6554
+ }
6555
+ return resolvedEnvVars;
6556
+ };
6557
+ }
5610
6558
 
5611
6559
  // src/commands/init.ts
5612
- import { intro as intro4, isCancel, log as log4, outro as outro4, select as select2, text } from "@clack/prompts";
6560
+ import { intro as intro5, isCancel as isCancel2, log as log6, outro as outro6, select as select2, text } from "@clack/prompts";
5613
6561
  import { context as context3, trace as trace3 } from "@opentelemetry/api";
5614
- import {
5615
- flattenAttributes as flattenAttributes3,
5616
- recordSpanException as recordSpanException5
5617
- } from "@trigger.dev/core/v3";
5618
- import chalk6 from "chalk";
6562
+ import { flattenAttributes as flattenAttributes4 } from "@trigger.dev/core/v3";
6563
+ import { recordSpanException as recordSpanException6 } from "@trigger.dev/core/v3/workers";
6564
+ import chalk5 from "chalk";
5619
6565
  import { execa as execa3 } from "execa";
5620
- import { applyEdits, modify } from "jsonc-parser";
6566
+ import { applyEdits, modify, findNodeAtLocation, parseTree, getNodeValue } from "jsonc-parser";
5621
6567
  import { writeFile as writeFile3 } from "node:fs/promises";
5622
- import { join as join7, relative as relative4, resolve as resolve3 } from "node:path";
5623
- import terminalLink3 from "terminal-link";
6568
+ import { join as join8, relative as relative4, resolve as resolve5 } from "node:path";
6569
+ import terminalLink4 from "terminal-link";
5624
6570
  import { z as z6 } from "zod";
5625
6571
 
5626
6572
  // src/utilities/createFileFromTemplate.ts
@@ -5695,7 +6641,7 @@ async function initCommand(dir, options) {
5695
6641
  }
5696
6642
  async function _initCommand(dir, options) {
5697
6643
  const span = trace3.getSpan(context3.active());
5698
- intro4("Initializing project");
6644
+ intro5("Initializing project");
5699
6645
  const authorization = await login({
5700
6646
  embedded: true,
5701
6647
  defaultApiUrl: options.apiUrl,
@@ -5719,7 +6665,7 @@ async function _initCommand(dir, options) {
5719
6665
  if (!options.overrideConfig) {
5720
6666
  try {
5721
6667
  const result = await readConfig(dir);
5722
- outro4(
6668
+ outro6(
5723
6669
  result.status === "file" ? `Project already initialized: Found config file at ${result.path}. Pass --override-config to override` : "Project already initialized"
5724
6670
  );
5725
6671
  return;
@@ -5733,58 +6679,58 @@ async function _initCommand(dir, options) {
5733
6679
  options.projectRef
5734
6680
  );
5735
6681
  span?.setAttributes({
5736
- ...flattenAttributes3(selectedProject, "cli.project")
6682
+ ...flattenAttributes4(selectedProject, "cli.project")
5737
6683
  });
5738
6684
  logger.debug("Selected project", selectedProject);
5739
- log4.step(`Configuring project "${selectedProject.name}" (${selectedProject.externalRef})`);
6685
+ log6.step(`Configuring project "${selectedProject.name}" (${selectedProject.externalRef})`);
5740
6686
  if (!options.skipPackageInstall) {
5741
6687
  await installPackages2(dir, options);
5742
6688
  } else {
5743
- log4.info("Skipping package installation");
6689
+ log6.info("Skipping package installation");
5744
6690
  }
5745
6691
  const triggerDir = await createTriggerDir(dir, options);
5746
6692
  await writeConfigFile(dir, selectedProject, options, triggerDir);
5747
6693
  await addConfigFileToTsConfig(dir, options);
5748
6694
  await gitIgnoreDotTriggerDir(dir, options);
5749
- const projectDashboard = terminalLink3(
6695
+ const projectDashboard = terminalLink4(
5750
6696
  "project dashboard",
5751
6697
  `${authorization.dashboardUrl}/projects/v3/${selectedProject.externalRef}`
5752
6698
  );
5753
- log4.success("Successfully initialized project for Trigger.dev v3 \u{1FAE1}");
5754
- log4.info("Next steps:");
5755
- log4.info(
5756
- ` 1. To start developing, run ${chalk6.green(
6699
+ log6.success("Successfully initialized project for Trigger.dev v3 \u{1FAE1}");
6700
+ log6.info("Next steps:");
6701
+ log6.info(
6702
+ ` 1. To start developing, run ${chalk5.green(
5757
6703
  `npx trigger.dev@${options.tag} dev`
5758
6704
  )} in your project directory`
5759
6705
  );
5760
- log4.info(` 2. Visit your ${projectDashboard} to view your newly created tasks.`);
5761
- log4.info(
5762
- ` 3. Head over to our ${terminalLink3(
6706
+ log6.info(` 2. Visit your ${projectDashboard} to view your newly created tasks.`);
6707
+ log6.info(
6708
+ ` 3. Head over to our ${terminalLink4(
5763
6709
  "v3 docs",
5764
6710
  "https://trigger.dev/docs/v3"
5765
6711
  )} to learn more.`
5766
6712
  );
5767
- log4.info(
5768
- ` 4. Need help? Join our ${terminalLink3(
6713
+ log6.info(
6714
+ ` 4. Need help? Join our ${terminalLink4(
5769
6715
  "Discord community",
5770
6716
  "https://trigger.dev/discord"
5771
- )} or email us at ${chalk6.cyan("help@trigger.dev")}`
6717
+ )} or email us at ${chalk5.cyan("help@trigger.dev")}`
5772
6718
  );
5773
- outro4(`Project initialized successfully. Happy coding!`);
6719
+ outro6(`Project initialized successfully. Happy coding!`);
5774
6720
  }
5775
6721
  async function createTriggerDir(dir, options) {
5776
6722
  return await tracer.startActiveSpan("createTriggerDir", async (span) => {
5777
6723
  try {
5778
- const defaultValue = join7(dir, "src", "trigger");
6724
+ const defaultValue = join8(dir, "src", "trigger");
5779
6725
  const location = await text({
5780
6726
  message: "Where would you like to create the Trigger.dev directory?",
5781
6727
  defaultValue,
5782
6728
  placeholder: defaultValue
5783
6729
  });
5784
- if (isCancel(location)) {
6730
+ if (isCancel2(location)) {
5785
6731
  throw new OutroCommandError();
5786
6732
  }
5787
- const triggerDir = resolve3(process.cwd(), location);
6733
+ const triggerDir = resolve5(process.cwd(), location);
5788
6734
  logger.debug({ triggerDir });
5789
6735
  span.setAttributes({
5790
6736
  "cli.triggerDir": triggerDir
@@ -5803,7 +6749,7 @@ async function createTriggerDir(dir, options) {
5803
6749
  }
5804
6750
  ]
5805
6751
  });
5806
- if (isCancel(exampleSelection)) {
6752
+ if (isCancel2(exampleSelection)) {
5807
6753
  throw new OutroCommandError();
5808
6754
  }
5809
6755
  const example = exampleSelection;
@@ -5811,25 +6757,25 @@ async function createTriggerDir(dir, options) {
5811
6757
  "cli.example": example
5812
6758
  });
5813
6759
  if (example === "none") {
5814
- await createFile(join7(triggerDir, ".gitkeep"), "");
5815
- log4.step(`Created directory at ${location}`);
6760
+ await createFile(join8(triggerDir, ".gitkeep"), "");
6761
+ log6.step(`Created directory at ${location}`);
5816
6762
  span.end();
5817
6763
  return { location, isCustomValue: location !== defaultValue };
5818
6764
  }
5819
- const templatePath = join7(cliRootPath(), "templates", "examples", `${example}.ts.template`);
5820
- const outputPath = join7(triggerDir, "example.ts");
6765
+ const templatePath = join8(cliRootPath(), "templates", "examples", `${example}.ts.template`);
6766
+ const outputPath = join8(triggerDir, "example.ts");
5821
6767
  await createFileFromTemplate({
5822
6768
  templatePath,
5823
6769
  outputPath,
5824
6770
  replacements: {}
5825
6771
  });
5826
6772
  const relativeOutputPath = relative4(process.cwd(), outputPath);
5827
- log4.step(`Created example file at ${relativeOutputPath}`);
6773
+ log6.step(`Created example file at ${relativeOutputPath}`);
5828
6774
  span.end();
5829
6775
  return { location, isCustomValue: location !== defaultValue };
5830
6776
  } catch (e) {
5831
6777
  if (!(e instanceof SkipCommandError)) {
5832
- recordSpanException5(span, e);
6778
+ recordSpanException6(span, e);
5833
6779
  }
5834
6780
  span.end();
5835
6781
  throw e;
@@ -5839,15 +6785,15 @@ async function createTriggerDir(dir, options) {
5839
6785
  async function gitIgnoreDotTriggerDir(dir, options) {
5840
6786
  return await tracer.startActiveSpan("gitIgnoreDotTriggerDir", async (span) => {
5841
6787
  try {
5842
- const projectDir = resolve3(process.cwd(), dir);
5843
- const gitIgnorePath = join7(projectDir, ".gitignore");
6788
+ const projectDir = resolve5(process.cwd(), dir);
6789
+ const gitIgnorePath = join8(projectDir, ".gitignore");
5844
6790
  span.setAttributes({
5845
6791
  "cli.projectDir": projectDir,
5846
6792
  "cli.gitIgnorePath": gitIgnorePath
5847
6793
  });
5848
6794
  if (!await pathExists(gitIgnorePath)) {
5849
6795
  await createFile(gitIgnorePath, ".trigger");
5850
- log4.step(`Added .trigger to .gitignore`);
6796
+ log6.step(`Added .trigger to .gitignore`);
5851
6797
  span.end();
5852
6798
  return;
5853
6799
  }
@@ -5859,11 +6805,11 @@ async function gitIgnoreDotTriggerDir(dir, options) {
5859
6805
  const newGitIgnoreContent = `${gitIgnoreContent}
5860
6806
  .trigger`;
5861
6807
  await writeFile3(gitIgnorePath, newGitIgnoreContent, "utf-8");
5862
- log4.step(`Added .trigger to .gitignore`);
6808
+ log6.step(`Added .trigger to .gitignore`);
5863
6809
  span.end();
5864
6810
  } catch (e) {
5865
6811
  if (!(e instanceof SkipCommandError)) {
5866
- recordSpanException5(span, e);
6812
+ recordSpanException6(span, e);
5867
6813
  }
5868
6814
  span.end();
5869
6815
  throw e;
@@ -5873,14 +6819,30 @@ async function gitIgnoreDotTriggerDir(dir, options) {
5873
6819
  async function addConfigFileToTsConfig(dir, options) {
5874
6820
  return await tracer.startActiveSpan("createTriggerDir", async (span) => {
5875
6821
  try {
5876
- const projectDir = resolve3(process.cwd(), dir);
5877
- const tsconfigPath = join7(projectDir, "tsconfig.json");
6822
+ const projectDir = resolve5(process.cwd(), dir);
6823
+ const tsconfigPath = join8(projectDir, "tsconfig.json");
5878
6824
  span.setAttributes({
5879
6825
  "cli.projectDir": projectDir,
5880
6826
  "cli.tsconfigPath": tsconfigPath
5881
6827
  });
5882
6828
  const tsconfigContent = await readFile(tsconfigPath);
5883
- const edits = modify(tsconfigContent, ["include", -1], "trigger.config.ts", {
6829
+ const tsconfigContentTree = parseTree(tsconfigContent, void 0);
6830
+ if (!tsconfigContentTree) {
6831
+ span.end();
6832
+ return;
6833
+ }
6834
+ const tsconfigIncludeOption = findNodeAtLocation(tsconfigContentTree, ["include"]);
6835
+ if (!tsconfigIncludeOption) {
6836
+ span.end();
6837
+ return;
6838
+ }
6839
+ const tsConfigFileName = "trigger.config.ts";
6840
+ const tsconfigIncludeOptionValue = getNodeValue(tsconfigIncludeOption);
6841
+ if (tsconfigIncludeOptionValue.includes(tsConfigFileName)) {
6842
+ span.end();
6843
+ return;
6844
+ }
6845
+ const edits = modify(tsconfigContent, ["include", -1], tsConfigFileName, {
5884
6846
  isArrayInsertion: true,
5885
6847
  formattingOptions: {
5886
6848
  tabSize: 2,
@@ -5892,11 +6854,11 @@ async function addConfigFileToTsConfig(dir, options) {
5892
6854
  const newTsconfigContent = applyEdits(tsconfigContent, edits);
5893
6855
  logger.debug("new tsconfig.json content", { newTsconfigContent });
5894
6856
  await writeFile3(tsconfigPath, newTsconfigContent, "utf-8");
5895
- log4.step(`Added trigger.config.ts to tsconfig.json`);
6857
+ log6.step(`Added trigger.config.ts to tsconfig.json`);
5896
6858
  span.end();
5897
6859
  } catch (e) {
5898
6860
  if (!(e instanceof SkipCommandError)) {
5899
- recordSpanException5(span, e);
6861
+ recordSpanException6(span, e);
5900
6862
  }
5901
6863
  span.end();
5902
6864
  throw e;
@@ -5907,7 +6869,7 @@ async function installPackages2(dir, options) {
5907
6869
  return await tracer.startActiveSpan("installPackages", async (span) => {
5908
6870
  const installSpinner = spinner();
5909
6871
  try {
5910
- const projectDir = resolve3(process.cwd(), dir);
6872
+ const projectDir = resolve5(process.cwd(), dir);
5911
6873
  const pkgManager = await getUserPackageManager(projectDir);
5912
6874
  span.setAttributes({
5913
6875
  "cli.projectDir": projectDir,
@@ -5947,7 +6909,7 @@ async function installPackages2(dir, options) {
5947
6909
  `Failed to install @trigger.dev/sdk@${options.tag}. Rerun command with --log-level debug for more details.`
5948
6910
  );
5949
6911
  if (!(e instanceof SkipCommandError)) {
5950
- recordSpanException5(span, e);
6912
+ recordSpanException6(span, e);
5951
6913
  }
5952
6914
  span.end();
5953
6915
  throw e;
@@ -5959,9 +6921,9 @@ async function writeConfigFile(dir, project, options, triggerDir) {
5959
6921
  try {
5960
6922
  const spnnr = spinner();
5961
6923
  spnnr.start("Creating config file");
5962
- const projectDir = resolve3(process.cwd(), dir);
5963
- const templatePath = join7(cliRootPath(), "templates", "trigger.config.ts.template");
5964
- const outputPath = join7(projectDir, "trigger.config.ts");
6924
+ const projectDir = resolve5(process.cwd(), dir);
6925
+ const templatePath = join8(cliRootPath(), "templates", "trigger.config.ts.template");
6926
+ const outputPath = join8(projectDir, "trigger.config.ts");
5965
6927
  span.setAttributes({
5966
6928
  "cli.projectDir": projectDir,
5967
6929
  "cli.templatePath": templatePath,
@@ -5988,7 +6950,7 @@ async function writeConfigFile(dir, project, options, triggerDir) {
5988
6950
  return result.success;
5989
6951
  } catch (e) {
5990
6952
  if (!(e instanceof SkipCommandError)) {
5991
- recordSpanException5(span, e);
6953
+ recordSpanException6(span, e);
5992
6954
  }
5993
6955
  span.end();
5994
6956
  throw e;
@@ -6001,13 +6963,13 @@ async function selectProject(apiClient2, dashboardUrl, projectRef) {
6001
6963
  if (projectRef) {
6002
6964
  const projectResponse = await apiClient2.getProject(projectRef);
6003
6965
  if (!projectResponse.success) {
6004
- log4.error(
6966
+ log6.error(
6005
6967
  `--project-ref ${projectRef} is not a valid project ref. Request to fetch data resulted in: ${projectResponse.error}`
6006
6968
  );
6007
6969
  throw new SkipCommandError(projectResponse.error);
6008
6970
  }
6009
6971
  span.setAttributes({
6010
- ...flattenAttributes3(projectResponse.data, "cli.project")
6972
+ ...flattenAttributes4(projectResponse.data, "cli.project")
6011
6973
  });
6012
6974
  span.end();
6013
6975
  return projectResponse.data;
@@ -6017,11 +6979,11 @@ async function selectProject(apiClient2, dashboardUrl, projectRef) {
6017
6979
  throw new Error(`Failed to get projects: ${projectsResponse.error}`);
6018
6980
  }
6019
6981
  if (projectsResponse.data.length === 0) {
6020
- const newProjectLink = terminalLink3(
6982
+ const newProjectLink = terminalLink4(
6021
6983
  "Create new project",
6022
6984
  `${dashboardUrl}/projects/new?version=v3`
6023
6985
  );
6024
- outro4(`You don't have any projects yet. ${newProjectLink}`);
6986
+ outro6(`You don't have any projects yet. ${newProjectLink}`);
6025
6987
  throw new SkipCommandError();
6026
6988
  }
6027
6989
  const selectedProject = await select2({
@@ -6032,7 +6994,7 @@ async function selectProject(apiClient2, dashboardUrl, projectRef) {
6032
6994
  hint: project.organization.title
6033
6995
  }))
6034
6996
  });
6035
- if (isCancel(selectedProject)) {
6997
+ if (isCancel2(selectedProject)) {
6036
6998
  throw new OutroCommandError();
6037
6999
  }
6038
7000
  const projectData = projectsResponse.data.find(
@@ -6042,13 +7004,13 @@ async function selectProject(apiClient2, dashboardUrl, projectRef) {
6042
7004
  throw new Error("Invalid project ref");
6043
7005
  }
6044
7006
  span.setAttributes({
6045
- ...flattenAttributes3(projectData, "cli.project")
7007
+ ...flattenAttributes4(projectData, "cli.project")
6046
7008
  });
6047
7009
  span.end();
6048
7010
  return projectData;
6049
7011
  } catch (e) {
6050
7012
  if (!(e instanceof SkipCommandError)) {
6051
- recordSpanException5(span, e);
7013
+ recordSpanException6(span, e);
6052
7014
  }
6053
7015
  span.end();
6054
7016
  throw e;
@@ -6084,7 +7046,7 @@ async function logout(options) {
6084
7046
  }
6085
7047
 
6086
7048
  // src/commands/list-profiles.ts
6087
- import { log as log5, outro as outro5 } from "@clack/prompts";
7049
+ import { log as log7, outro as outro7 } from "@clack/prompts";
6088
7050
  var ListProfilesOptions = CommonCommandOptions;
6089
7051
  function configureListProfilesCommand(program2) {
6090
7052
  return program2.command("list-profiles").description("List all of your CLI profiles").option(
@@ -6110,12 +7072,12 @@ async function listProfiles(options) {
6110
7072
  return;
6111
7073
  }
6112
7074
  const profiles = Object.keys(authConfig);
6113
- log5.message("Profiles:");
7075
+ log7.message("Profiles:");
6114
7076
  for (const profile of profiles) {
6115
7077
  const profileConfig = authConfig[profile];
6116
- log5.info(`${profile}${profileConfig?.apiUrl ? ` - ${chalkGrey(profileConfig.apiUrl)}` : ""}`);
7078
+ log7.info(`${profile}${profileConfig?.apiUrl ? ` - ${chalkGrey(profileConfig.apiUrl)}` : ""}`);
6117
7079
  }
6118
- outro5("Retrieve account info by running whoami --profile <profile>");
7080
+ outro7("Retrieve account info by running whoami --profile <profile>");
6119
7081
  }
6120
7082
 
6121
7083
  // src/cli/index.ts
@@ -6128,6 +7090,7 @@ configureDeployCommand(program);
6128
7090
  configureWhoamiCommand(program);
6129
7091
  configureLogoutCommand(program);
6130
7092
  configureListProfilesCommand(program);
7093
+ configureUpdateCommand(program);
6131
7094
 
6132
7095
  // src/index.ts
6133
7096
  var main = async () => {