trigger.dev 0.0.0-prerelease-20240410151927 → 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
@@ -263,7 +263,7 @@ var require_OSPaths = __commonJS({
263
263
  return path_ ? adapter_.path.normalize(adapter_.path.join(path_, ".")) : void 0;
264
264
  }
265
265
  function home() {
266
- var posix = function() {
266
+ var posix2 = function() {
267
267
  return normalizePath((typeof os2.homedir === "function" ? os2.homedir() : void 0) || env.get("HOME"));
268
268
  };
269
269
  var windows = function() {
@@ -277,13 +277,13 @@ var require_OSPaths = __commonJS({
277
277
  return !isEmpty(v);
278
278
  }));
279
279
  };
280
- return isWinOS ? windows() : posix();
280
+ return isWinOS ? windows() : posix2();
281
281
  }
282
282
  function temp() {
283
283
  function joinPathToBase(base, segments) {
284
284
  return base ? path7.join.apply(path7, __spreadArray([base], segments)) : void 0;
285
285
  }
286
- function posix() {
286
+ function posix2() {
287
287
  var fallback = "/tmp";
288
288
  var priorityList = [
289
289
  typeof os2.tmpdir === "function" ? os2.tmpdir() : void 0,
@@ -331,7 +331,7 @@ var require_OSPaths = __commonJS({
331
331
  });
332
332
  return v && normalizePath(v()) || fallback;
333
333
  }
334
- return isWinOS ? windows() : posix();
334
+ return isWinOS ? windows() : posix2();
335
335
  }
336
336
  var OSPaths_ = /* @__PURE__ */ function() {
337
337
  function OSPaths_2() {
@@ -777,32 +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 log2, outro as outro3, spinner as spinner4 } 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
- import { resolve as importResolve } from "import-meta-resolve";
794
792
  import { createHash } from "node:crypto";
795
793
  import { readFileSync as readFileSync2 } from "node:fs";
796
794
  import { copyFile, mkdir, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
797
- import { dirname, join as join5, relative as relative3 } from "node:path";
795
+ import { dirname, join as join6, posix, relative as relative3 } from "node:path";
798
796
  import { setTimeout as setTimeout2 } from "node:timers/promises";
799
- import terminalLink from "terminal-link";
797
+ import terminalLink2 from "terminal-link";
800
798
  import invariant from "tiny-invariant";
801
799
  import { z as z4 } from "zod";
802
800
 
803
801
  // package.json
804
- var version = "0.0.0-prerelease-20240410151927";
802
+ var version = "3.0.0-beta.33";
805
803
  var dependencies = {
804
+ "@anatine/esbuild-decorators": "^0.2.19",
806
805
  "@clack/prompts": "^0.7.0",
807
806
  "@depot/cli": "0.0.1-cli.2.55.0",
808
807
  "@opentelemetry/api": "^1.8.0",
@@ -817,7 +816,7 @@ var dependencies = {
817
816
  "@opentelemetry/sdk-trace-base": "^1.22.0",
818
817
  "@opentelemetry/sdk-trace-node": "^1.22.0",
819
818
  "@opentelemetry/semantic-conventions": "^1.22.0",
820
- "@trigger.dev/core": "workspace:0.0.0-prerelease-20240410151927",
819
+ "@trigger.dev/core": "workspace:3.0.0-beta.33",
821
820
  "@types/degit": "^2.8.3",
822
821
  chalk: "^5.2.0",
823
822
  chokidar: "^3.5.3",
@@ -827,7 +826,7 @@ var dependencies = {
827
826
  dotenv: "^16.4.4",
828
827
  esbuild: "^0.19.11",
829
828
  evt: "^2.4.13",
830
- execa: "^8.0.0",
829
+ execa: "^9.1.0",
831
830
  "find-up": "^7.0.0",
832
831
  glob: "^10.3.10",
833
832
  "gradient-string": "^2.0.2",
@@ -838,7 +837,6 @@ var dependencies = {
838
837
  "mock-fs": "^5.2.0",
839
838
  nanoid: "^4.0.2",
840
839
  "node-fetch": "^3.3.0",
841
- "npm-check-updates": "^16.12.2",
842
840
  "object-hash": "^3.0.0",
843
841
  "p-debounce": "^4.0.0",
844
842
  "p-throttle": "^6.1.0",
@@ -857,7 +855,8 @@ var dependencies = {
857
855
  url: "^0.11.1",
858
856
  ws: "^8.12.0",
859
857
  zod: "3.22.3",
860
- "zod-validation-error": "^1.5.0"
858
+ "zod-validation-error": "^1.5.0",
859
+ typescript: "^5.4.0"
861
860
  };
862
861
  var package_default = {
863
862
  name: "trigger.dev",
@@ -906,8 +905,8 @@ var package_default = {
906
905
  "@types/semver": "^7.3.13",
907
906
  "@types/ws": "^8.5.3",
908
907
  "cpy-cli": "^5.0.0",
908
+ nodemon: "^3.0.1",
909
909
  "npm-run-all": "^4.1.5",
910
- "npm-watch": "^0.11.0",
911
910
  open: "^10.0.3",
912
911
  "p-retry": "^6.1.0",
913
912
  rimraf: "^3.0.2",
@@ -917,9 +916,6 @@ var package_default = {
917
916
  vitest: "^0.34.4",
918
917
  "xdg-app-paths": "^8.3.0"
919
918
  },
920
- watch: {
921
- "build:prod-containerfile": "src/Containerfile.prod"
922
- },
923
919
  scripts: {
924
920
  typecheck: "tsc -p tsconfig.check.json",
925
921
  build: "npm run clean && run-p build:**",
@@ -929,7 +925,7 @@ var package_default = {
929
925
  dev: "npm run clean && run-p dev:**",
930
926
  "dev:main": "tsup --watch",
931
927
  "dev:workers": "tsup --config tsup.workers.config.ts --watch",
932
- "dev:prod-containerfile": "npm-watch",
928
+ "dev:test": "nodemon -w src/Containerfile.prod -x npm run build:prod-containerfile",
933
929
  clean: "rimraf dist",
934
930
  start: "node dist/index.js",
935
931
  test: "vitest"
@@ -952,7 +948,8 @@ import {
952
948
  InitializeDeploymentResponseBody,
953
949
  GetDeploymentResponseBody,
954
950
  GetProjectsResponseBody,
955
- GetProjectResponseBody
951
+ GetProjectResponseBody,
952
+ EnvironmentVariableResponseBody
956
953
  } from "@trigger.dev/core/v3";
957
954
  var CliApiClient = class {
958
955
  constructor(apiURL, accessToken) {
@@ -1056,6 +1053,23 @@ var CliApiClient = class {
1056
1053
  }
1057
1054
  );
1058
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
+ }
1059
1073
  async initializeDeployment(body) {
1060
1074
  if (!this.accessToken) {
1061
1075
  throw new Error("initializeDeployment: No access token");
@@ -1145,7 +1159,8 @@ async function zodfetch(schema, url, requestInit) {
1145
1159
  }
1146
1160
 
1147
1161
  // src/cli/common.ts
1148
- 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";
1149
1164
  import { z } from "zod";
1150
1165
 
1151
1166
  // src/telemetry/tracing.ts
@@ -1155,6 +1170,10 @@ import { Resource, detectResourcesSync, processDetectorSync } from "@opentelemet
1155
1170
  import { NodeTracerProvider, SimpleSpanProcessor } from "@opentelemetry/sdk-trace-node";
1156
1171
  import { FetchInstrumentation } from "@opentelemetry/instrumentation-fetch";
1157
1172
  import { DiagConsoleLogger, DiagLogLevel, diag, trace } from "@opentelemetry/api";
1173
+ import {
1174
+ SEMRESATTRS_SERVICE_NAME,
1175
+ SEMRESATTRS_SERVICE_VERSION
1176
+ } from "@opentelemetry/semantic-conventions";
1158
1177
  function initializeTracing() {
1159
1178
  if (process.argv.includes("--skip-telemetry") || process.env.TRIGGER_DEV_SKIP_TELEMETRY) {
1160
1179
  return;
@@ -1166,7 +1185,8 @@ function initializeTracing() {
1166
1185
  detectors: [processDetectorSync]
1167
1186
  }).merge(
1168
1187
  new Resource({
1169
- service: "trigger.dev cli v3"
1188
+ [SEMRESATTRS_SERVICE_NAME]: "trigger.dev cli v3",
1189
+ [SEMRESATTRS_SERVICE_VERSION]: version
1170
1190
  })
1171
1191
  );
1172
1192
  const traceProvider = new NodeTracerProvider({
@@ -1183,10 +1203,9 @@ function initializeTracing() {
1183
1203
  });
1184
1204
  const spanExporter = new OTLPTraceExporter({
1185
1205
  url: "https://otel.baselime.io/v1",
1186
- timeoutMillis: 500,
1206
+ timeoutMillis: 5e3,
1187
1207
  headers: {
1188
- "x-api-key": "e9f963244f8b092850d42e34a5339b2d5e68070b".split("").reverse().join("")
1189
- // this is a joke
1208
+ "x-api-key": "b6e0fbbaf8dc2524773d2152ae2e9eb5c7fbaa52"
1190
1209
  }
1191
1210
  });
1192
1211
  const spanProcessor = new SimpleSpanProcessor(spanExporter);
@@ -1199,7 +1218,7 @@ function initializeTracing() {
1199
1218
  }
1200
1219
  var provider = initializeTracing();
1201
1220
  function getTracer() {
1202
- return trace.getTracer("trigger.dev cli", version);
1221
+ return trace.getTracer("trigger.dev cli v3", version);
1203
1222
  }
1204
1223
 
1205
1224
  // src/cli/common.ts
@@ -1322,6 +1341,7 @@ var logger = new Logger();
1322
1341
  import { outro } from "@clack/prompts";
1323
1342
 
1324
1343
  // src/utilities/cliOutput.ts
1344
+ import { log } from "@clack/prompts";
1325
1345
  import chalk2 from "chalk";
1326
1346
  var green = "#4FFF54";
1327
1347
  var purple = "#735BF3";
@@ -1370,6 +1390,30 @@ function prettyPrintDate(date = /* @__PURE__ */ new Date()) {
1370
1390
  formattedDate += "." + ("00" + date.getMilliseconds()).slice(-3);
1371
1391
  return formattedDate;
1372
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
+ }
1373
1417
 
1374
1418
  // src/cli/common.ts
1375
1419
  var CommonCommandOptions = z.object({
@@ -1478,6 +1522,9 @@ async function createFile(path7, contents) {
1478
1522
  async function pathExists(path7) {
1479
1523
  return fsSync.existsSync(path7);
1480
1524
  }
1525
+ async function removeFile(path7) {
1526
+ await fsModule.unlink(path7);
1527
+ }
1481
1528
  async function readFile(path7) {
1482
1529
  return await fsModule.readFile(path7, "utf8");
1483
1530
  }
@@ -1485,8 +1532,8 @@ async function readJSONFile(path7) {
1485
1532
  const fileContents = await fsModule.readFile(path7, "utf8");
1486
1533
  return JSON.parse(fileContents);
1487
1534
  }
1488
- async function writeJSONFile(path7, json) {
1489
- 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");
1490
1537
  }
1491
1538
  function readJSONFileSync(path7) {
1492
1539
  const fileContents = fsSync.readFileSync(path7, "utf8");
@@ -1517,14 +1564,23 @@ function createTaskFileImports(taskFiles) {
1517
1564
  async function gatherTaskFiles(config) {
1518
1565
  const taskFiles = [];
1519
1566
  for (const triggerDir of config.triggerDirectories) {
1520
- const files = await fs2.promises.readdir(triggerDir, { withFileTypes: true });
1521
- for (const file of files) {
1522
- if (!file.isFile())
1523
- 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 {
1524
1580
  if (!file.name.endsWith(".js") && !file.name.endsWith(".ts") && !file.name.endsWith(".jsx") && !file.name.endsWith(".tsx")) {
1525
1581
  continue;
1526
1582
  }
1527
- const fullPath = join(triggerDir, file.name);
1583
+ const fullPath = join(dirPath, file.name);
1528
1584
  const filePath = relative(config.projectDir, fullPath);
1529
1585
  const importName = filePath.replace(/\..+$/, "").replace(/[^a-zA-Z0-9_$]/g, "_");
1530
1586
  const importPath = filePath.replace(/\\/g, "/");
@@ -1544,9 +1600,12 @@ async function getTriggerDirectories(dirPath) {
1544
1600
  const entries = await fs2.promises.readdir(dirPath, { withFileTypes: true });
1545
1601
  const triggerDirectories = [];
1546
1602
  for (const entry of entries) {
1547
- if (!entry.isDirectory() || IGNORED_DIRS.includes(entry.name))
1603
+ if (!entry.isDirectory() || IGNORED_DIRS.includes(entry.name) || entry.name.startsWith("."))
1548
1604
  continue;
1549
1605
  const fullPath = join(dirPath, entry.name);
1606
+ if (fullPath.endsWith("app/api/trigger")) {
1607
+ continue;
1608
+ }
1550
1609
  if (entry.name === "trigger") {
1551
1610
  triggerDirectories.push(fullPath);
1552
1611
  }
@@ -1557,6 +1616,7 @@ async function getTriggerDirectories(dirPath) {
1557
1616
 
1558
1617
  // src/utilities/configFiles.ts
1559
1618
  import { build } from "esbuild";
1619
+ import { esbuildDecorators } from "@anatine/esbuild-decorators";
1560
1620
  function getGlobalConfigFolderPath() {
1561
1621
  const configDir = mod_esm_default("trigger").config();
1562
1622
  return configDir;
@@ -1620,16 +1680,25 @@ async function getConfigPath(dir, fileName) {
1620
1680
  });
1621
1681
  return await findUp(fileName ? [fileName] : CONFIG_FILES, { cwd: dir });
1622
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
+ }
1623
1692
  async function readConfig(dir, options) {
1624
1693
  const absoluteDir = path2.resolve(process.cwd(), dir);
1625
1694
  const configPath = await getConfigPath(dir, options?.configFile);
1626
1695
  if (!configPath) {
1627
1696
  if (options?.projectRef) {
1628
- const rawConfig2 = await normalizeConfig({ project: options.projectRef });
1629
- const config2 = Config.parse(rawConfig2);
1697
+ const rawConfig = await normalizeConfig({ project: options.projectRef });
1698
+ const config = Config.parse(rawConfig);
1630
1699
  return {
1631
1700
  status: "in-memory",
1632
- config: await resolveConfig(absoluteDir, config2)
1701
+ config: await resolveConfig(absoluteDir, config)
1633
1702
  };
1634
1703
  } else {
1635
1704
  throw new Error(`Config file not found in ${absoluteDir} or any parent directory.`);
@@ -1653,24 +1722,49 @@ async function readConfig(dir, options) {
1653
1722
  platform: "node",
1654
1723
  target: ["es2018", "node18"],
1655
1724
  outfile: builtConfigFilePath,
1656
- 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
+ ]
1657
1741
  });
1658
- const userConfigModule = await import(builtConfigFileHref);
1659
- const rawConfig = await normalizeConfig(
1660
- userConfigModule ? userConfigModule.config : { project: options?.projectRef }
1661
- );
1662
- const config = Config.parse(rawConfig);
1663
- return {
1664
- status: "file",
1665
- config: await resolveConfig(absoluteDir, config),
1666
- path: configPath
1667
- };
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
+ }
1668
1761
  }
1669
1762
  async function resolveConfig(path7, config) {
1670
1763
  if (!config.triggerDirectories) {
1671
1764
  config.triggerDirectories = await findTriggerDirectories(path7);
1672
1765
  }
1673
1766
  config.triggerDirectories = resolveTriggerDirectories(config.triggerDirectories);
1767
+ logger.debug("Resolved trigger directories", { triggerDirectories: config.triggerDirectories });
1674
1768
  if (!config.triggerUrl) {
1675
1769
  config.triggerUrl = CLOUD_API_URL;
1676
1770
  }
@@ -1678,19 +1772,20 @@ async function resolveConfig(path7, config) {
1678
1772
  config.projectDir = path7;
1679
1773
  }
1680
1774
  if (!config.tsconfigPath) {
1681
- config.tsconfigPath = await getConfigPath(path7, "tsconfig.json");
1775
+ config.tsconfigPath = await findFilePath(path7, "tsconfig.json");
1682
1776
  }
1683
1777
  return config;
1684
1778
  }
1685
- async function normalizeConfig(config) {
1779
+ async function normalizeConfig(config, overrides) {
1780
+ let normalized = config;
1686
1781
  if (typeof config === "function") {
1687
- config = config();
1782
+ normalized = await config();
1688
1783
  }
1689
- return await config;
1784
+ normalized = { ...normalized, ...overrides };
1785
+ return normalized;
1690
1786
  }
1691
1787
 
1692
1788
  // src/utilities/initialBanner.ts
1693
- import { spinner } from "@clack/prompts";
1694
1789
  import chalk3 from "chalk";
1695
1790
  import checkForUpdate from "update-check";
1696
1791
 
@@ -1702,11 +1797,30 @@ function getVersion() {
1702
1797
  return packageJsonContent.version ?? "1.0.0";
1703
1798
  }
1704
1799
 
1800
+ // src/utilities/windows.ts
1801
+ import { log as log2, spinner as clackSpinner } from "@clack/prompts";
1802
+ var isWindows = process.platform === "win32";
1803
+ function escapeImportPath(path7) {
1804
+ return isWindows ? path7.replaceAll("\\", "\\\\") : path7;
1805
+ }
1806
+ var ballmerSpinner = () => ({
1807
+ start: (msg) => {
1808
+ log2.step(msg ?? "");
1809
+ },
1810
+ stop: (msg, code) => {
1811
+ log2.message(msg ?? "");
1812
+ },
1813
+ message: (msg) => {
1814
+ log2.message(msg ?? "");
1815
+ }
1816
+ });
1817
+ var spinner = () => isWindows ? ballmerSpinner() : clackSpinner();
1818
+
1705
1819
  // src/utilities/initialBanner.ts
1706
1820
  async function printInitialBanner(performUpdateCheck = true) {
1707
- const packageVersion = getVersion();
1821
+ const cliVersion = getVersion();
1708
1822
  const text3 = `
1709
- ${logo()} ${chalkGrey(`(${packageVersion})`)}
1823
+ ${logo()} ${chalkGrey(`(${cliVersion})`)}
1710
1824
  `;
1711
1825
  logger.info(text3);
1712
1826
  let maybeNewVersion;
@@ -1716,7 +1830,7 @@ ${logo()} ${chalkGrey(`(${packageVersion})`)}
1716
1830
  maybeNewVersion = await updateCheck();
1717
1831
  if (maybeNewVersion !== void 0) {
1718
1832
  loadingSpinner.stop(`Update available ${chalk3.green(maybeNewVersion)}`);
1719
- const currentMajor = parseInt(packageVersion.split(".")[0]);
1833
+ const currentMajor = parseInt(cliVersion.split(".")[0]);
1720
1834
  const newMajor = parseInt(maybeNewVersion.split(".")[0]);
1721
1835
  if (newMajor > currentMajor) {
1722
1836
  logger.warn(
@@ -1731,18 +1845,26 @@ After installation, run Trigger.dev with \`npx trigger.dev\`.`
1731
1845
  }
1732
1846
  }
1733
1847
  async function printStandloneInitialBanner(performUpdateCheck = true) {
1734
- const packageVersion = getVersion();
1735
- logger.log(`
1736
- ${logo()} ${chalkGrey("(v3 Developer Preview)")}`);
1848
+ const cliVersion = getVersion();
1737
1849
  if (performUpdateCheck) {
1738
1850
  const maybeNewVersion = await updateCheck();
1739
1851
  if (maybeNewVersion !== void 0) {
1740
- 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})`)}`);
1741
1857
  }
1858
+ } else {
1859
+ logger.log(`
1860
+ ${logo()} ${chalkGrey(`(${cliVersion})`)}`);
1742
1861
  }
1743
1862
  logger.log(`${chalkGrey("-".repeat(54))}`);
1744
1863
  }
1745
- function printDevBanner() {
1864
+ function printDevBanner(printTopBorder = true) {
1865
+ if (printTopBorder) {
1866
+ logger.log(chalkGrey("-".repeat(54)));
1867
+ }
1746
1868
  logger.log(
1747
1869
  `${chalkGrey("Key:")} ${chalkWorker("Version")} ${chalkGrey("|")} ${chalkTask(
1748
1870
  "Task"
@@ -1754,7 +1876,7 @@ async function doUpdateCheck() {
1754
1876
  let update = null;
1755
1877
  try {
1756
1878
  update = await checkForUpdate(package_default, {
1757
- distTag: package_default.version.startsWith("0.0.0") ? "beta" : "latest"
1879
+ distTag: package_default.version.startsWith("3.0.0-beta") ? "beta" : "latest"
1758
1880
  });
1759
1881
  } catch (err) {
1760
1882
  }
@@ -1792,14 +1914,27 @@ function stripWorkspaceFromVersion(version2) {
1792
1914
  return version2.replace(/^workspace:/, "");
1793
1915
  }
1794
1916
  function parsePackageName(packageSpecifier) {
1795
- const parts = packageSpecifier.split("@");
1796
- if (parts.length === 1 && typeof parts[0] === "string") {
1797
- 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;
1798
1933
  }
1799
- if (parts.length === 2 && typeof parts[0] === "string" && typeof parts[1] === "string") {
1800
- return { name: parts[0], version: parts[1] };
1934
+ if (!name) {
1935
+ return { name: packageSpecifier };
1801
1936
  }
1802
- return { name: packageSpecifier };
1937
+ return { name, version: version2 };
1803
1938
  }
1804
1939
  async function setPackageJsonDeps(path7, deps) {
1805
1940
  try {
@@ -1823,8 +1958,8 @@ async function setPackageJsonDeps(path7, deps) {
1823
1958
  }
1824
1959
 
1825
1960
  // src/commands/login.ts
1826
- import { intro as intro2, log, outro as outro2, select, spinner as spinner3 } from "@clack/prompts";
1827
- 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";
1828
1963
 
1829
1964
  // ../../node_modules/.pnpm/open@10.0.3/node_modules/open/index.js
1830
1965
  import process6 from "node:process";
@@ -2194,14 +2329,14 @@ var baseOpen = async (options) => {
2194
2329
  }
2195
2330
  const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
2196
2331
  if (options.wait) {
2197
- return new Promise((resolve4, reject) => {
2332
+ return new Promise((resolve6, reject) => {
2198
2333
  subprocess.once("error", reject);
2199
2334
  subprocess.once("close", (exitCode) => {
2200
2335
  if (!options.allowNonzeroExitCode && exitCode > 0) {
2201
2336
  reject(new Error(`Exited with code ${exitCode}`));
2202
2337
  return;
2203
2338
  }
2204
- resolve4(subprocess);
2339
+ resolve6(subprocess);
2205
2340
  });
2206
2341
  });
2207
2342
  }
@@ -2318,7 +2453,7 @@ var decorateErrorWithCounts = (error, attemptNumber, options) => {
2318
2453
  return error;
2319
2454
  };
2320
2455
  async function pRetry(input, options) {
2321
- return new Promise((resolve4, reject) => {
2456
+ return new Promise((resolve6, reject) => {
2322
2457
  options = {
2323
2458
  onFailedAttempt() {
2324
2459
  },
@@ -2341,7 +2476,7 @@ async function pRetry(input, options) {
2341
2476
  try {
2342
2477
  const result = await input(attemptNumber);
2343
2478
  cleanUp();
2344
- resolve4(result);
2479
+ resolve6(result);
2345
2480
  } catch (error) {
2346
2481
  try {
2347
2482
  if (!(error instanceof Error)) {
@@ -2371,10 +2506,10 @@ async function pRetry(input, options) {
2371
2506
  import { z as z3 } from "zod";
2372
2507
 
2373
2508
  // src/commands/whoami.ts
2374
- import { intro, note, spinner as spinner2 } from "@clack/prompts";
2509
+ import { intro, note, outro as outro2 } from "@clack/prompts";
2375
2510
 
2376
2511
  // src/utilities/session.ts
2377
- import { recordSpanException as recordSpanException2 } from "@trigger.dev/core/v3";
2512
+ import { recordSpanException as recordSpanException2 } from "@trigger.dev/core/v3/workers";
2378
2513
  var tracer2 = getTracer();
2379
2514
  async function isLoggedIn(profile = "default") {
2380
2515
  return await tracer2.startActiveSpan("isLoggedIn", async (span) => {
@@ -2449,16 +2584,23 @@ async function whoAmI(options, embedded = false) {
2449
2584
  if (!embedded) {
2450
2585
  intro(`Displaying your account details [${options?.profile ?? "default"}]`);
2451
2586
  }
2452
- const loadingSpinner = spinner2();
2587
+ const loadingSpinner = spinner();
2453
2588
  loadingSpinner.start("Checking your account details");
2454
2589
  const authentication = await isLoggedIn(options?.profile);
2455
2590
  if (!authentication.ok) {
2456
2591
  if (authentication.error === "fetch failed") {
2457
2592
  loadingSpinner.stop("Fetch failed. Platform down?");
2458
2593
  } else {
2459
- loadingSpinner.stop(
2460
- `You must login first. Use \`trigger.dev login --profile ${options?.profile ?? "default"}\` to login.`
2461
- );
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
+ }
2462
2604
  }
2463
2605
  return {
2464
2606
  success: false,
@@ -2554,10 +2696,18 @@ async function login(options) {
2554
2696
  skipTelemetry: !span.isRecording(),
2555
2697
  logLevel: logger.loggerLevel
2556
2698
  },
2557
- opts.embedded
2699
+ true
2558
2700
  );
2559
2701
  if (!whoAmIResult.success) {
2560
- 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
+ }
2561
2711
  } else {
2562
2712
  if (!opts.embedded) {
2563
2713
  const continueOption = await select({
@@ -2575,7 +2725,7 @@ async function login(options) {
2575
2725
  initialValue: false
2576
2726
  });
2577
2727
  if (continueOption !== true) {
2578
- outro2("Already logged in");
2728
+ outro3("Already logged in");
2579
2729
  span.setAttributes({
2580
2730
  "cli.userId": whoAmIResult.data.userId,
2581
2731
  "cli.email": whoAmIResult.data.email,
@@ -2616,16 +2766,16 @@ async function login(options) {
2616
2766
  }
2617
2767
  }
2618
2768
  if (opts.embedded) {
2619
- log.step("You must login to continue.");
2769
+ log3.step("You must login to continue.");
2620
2770
  }
2621
2771
  const apiClient2 = new CliApiClient(authConfig?.apiUrl ?? opts.defaultApiUrl);
2622
2772
  const authorizationCodeResult = await createAuthorizationCode(apiClient2);
2623
- log.step(
2773
+ log3.step(
2624
2774
  `Please visit the following URL to login:
2625
2775
  ${chalkLink(authorizationCodeResult.url)}`
2626
2776
  );
2627
2777
  await open_default(authorizationCodeResult.url);
2628
- const getPersonalAccessTokenSpinner = spinner3();
2778
+ const getPersonalAccessTokenSpinner = spinner();
2629
2779
  getPersonalAccessTokenSpinner.start("Waiting for you to login");
2630
2780
  try {
2631
2781
  const indexResult = await pRetry(
@@ -2654,9 +2804,9 @@ ${chalkLink(authorizationCodeResult.url)}`
2654
2804
  throw new Error(whoAmIResult.error);
2655
2805
  }
2656
2806
  if (opts.embedded) {
2657
- log.step("Logged in successfully");
2807
+ log3.step("Logged in successfully");
2658
2808
  } else {
2659
- outro2("Logged in successfully");
2809
+ outro3("Logged in successfully");
2660
2810
  }
2661
2811
  span.end();
2662
2812
  return {
@@ -2673,7 +2823,7 @@ ${chalkLink(authorizationCodeResult.url)}`
2673
2823
  } catch (e) {
2674
2824
  getPersonalAccessTokenSpinner.stop(`Failed to get access token`);
2675
2825
  if (e instanceof AbortError) {
2676
- log.error(e.message);
2826
+ log3.error(e.message);
2677
2827
  }
2678
2828
  recordSpanException3(span, e);
2679
2829
  span.end();
@@ -2722,8 +2872,8 @@ async function getPersonalAccessToken(apiClient2, authorizationCode) {
2722
2872
  async function createAuthorizationCode(apiClient2) {
2723
2873
  return await tracer.startActiveSpan("createAuthorizationCode", async (span) => {
2724
2874
  try {
2725
- const createAuthCodeSpinner = spinner3();
2726
- createAuthCodeSpinner.start("Creating authorition code");
2875
+ const createAuthCodeSpinner = spinner();
2876
+ createAuthCodeSpinner.start("Creating authorization code");
2727
2877
  const authorizationCodeResult = await apiClient2.createAuthorizationCode();
2728
2878
  if (!authorizationCodeResult.success) {
2729
2879
  createAuthCodeSpinner.stop(
@@ -2747,18 +2897,45 @@ ${authorizationCodeResult.error}`
2747
2897
  }
2748
2898
 
2749
2899
  // src/commands/deploy.ts
2900
+ import { esbuildDecorators as esbuildDecorators2 } from "@anatine/esbuild-decorators";
2750
2901
  import { Glob } from "glob";
2751
2902
 
2752
2903
  // src/utilities/build.ts
2753
2904
  import { readFileSync } from "node:fs";
2754
2905
  import { extname, isAbsolute } from "node:path";
2755
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
+ }
2756
2933
  function bundleTriggerDevCore(buildIdentifier, tsconfigPath) {
2757
2934
  return {
2758
2935
  name: "trigger-bundle-core",
2759
2936
  setup(build3) {
2760
2937
  build3.onResolve({ filter: /.*/ }, (args) => {
2761
- if (args.path !== "@trigger.dev/core/v3") {
2938
+ if (!args.path.startsWith("@trigger.dev/core/v3")) {
2762
2939
  return void 0;
2763
2940
  }
2764
2941
  const triggerSdkPath = __require.resolve("@trigger.dev/sdk/v3", { paths: [process.cwd()] });
@@ -2766,17 +2943,14 @@ function bundleTriggerDevCore(buildIdentifier, tsconfigPath) {
2766
2943
  ...args,
2767
2944
  triggerSdkPath
2768
2945
  });
2769
- const resolvedPath = __require.resolve("@trigger.dev/core/v3", {
2946
+ const resolvedPath = __require.resolve(args.path, {
2770
2947
  paths: [triggerSdkPath]
2771
2948
  });
2772
- logger.debug(
2773
- `[${buildIdentifier}][trigger-bundle-core] Externalizing @trigger.dev/core/v3`,
2774
- {
2775
- ...args,
2776
- triggerSdkPath,
2777
- resolvedPath
2778
- }
2779
- );
2949
+ logger.debug(`[${buildIdentifier}][trigger-bundle-core] Externalizing ${args.path}`, {
2950
+ ...args,
2951
+ triggerSdkPath,
2952
+ resolvedPath
2953
+ });
2780
2954
  return {
2781
2955
  path: resolvedPath,
2782
2956
  external: false
@@ -2796,7 +2970,9 @@ function workerSetupImportConfigPlugin(configPath) {
2796
2970
  let workerSetupContents = readFileSync(args.path, "utf-8");
2797
2971
  workerSetupContents = workerSetupContents.replace(
2798
2972
  "__SETUP_IMPORTED_PROJECT_CONFIG__",
2799
- `import * as setupImportedConfigExports from "${configPath}"; const setupImportedConfig = setupImportedConfigExports.config;`
2973
+ `import * as setupImportedConfigExports from "${escapeImportPath(
2974
+ configPath
2975
+ )}"; const setupImportedConfig = setupImportedConfigExports.config;`
2800
2976
  );
2801
2977
  logger.debug("Loading worker setup", {
2802
2978
  args,
@@ -2843,7 +3019,7 @@ function bundleDependenciesPlugin(buildIdentifier, dependenciesToBundle, tsconfi
2843
3019
  return void 0;
2844
3020
  }
2845
3021
  }
2846
- logger.ignore(`[${buildIdentifier}] Externalizing ${args.path}`, {
3022
+ logger.debug(`[${buildIdentifier}] Externalizing ${args.path}`, {
2847
3023
  ...args
2848
3024
  });
2849
3025
  return {
@@ -2935,6 +3111,20 @@ function getLoaderForFile(file) {
2935
3111
  import chalk4 from "chalk";
2936
3112
  import { relative as relative2 } from "node:path";
2937
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
2938
3128
  function errorIsErrorLike(error) {
2939
3129
  return error instanceof Error || typeof error === "object" && error !== null && "message" in error;
2940
3130
  }
@@ -3000,6 +3190,10 @@ ${chalkGrey("\u25CB")} Dynamically import the module in your code: ${chalkGrey(
3000
3190
  `
3001
3191
  );
3002
3192
  }
3193
+ logger.log(
3194
+ `${chalkGrey("\u25CB")} For more info see the ${terminalLink("relevant docs", docs.config.esm)}.
3195
+ `
3196
+ );
3003
3197
  }
3004
3198
  function parseNpmInstallError(error) {
3005
3199
  if (typeof error === "string") {
@@ -3062,25 +3256,19 @@ ${chalkError("X Error:")} Failed to start. The following ${zodIssues.length ===
3062
3256
  }
3063
3257
  }
3064
3258
 
3065
- // src/utilities/safeJsonParse.ts
3066
- function safeJsonParse(json) {
3067
- if (!json) {
3068
- return void 0;
3069
- }
3070
- try {
3071
- return JSON.parse(json);
3072
- } catch {
3073
- return void 0;
3074
- }
3075
- }
3076
-
3077
3259
  // src/utilities/javascriptProject.ts
3078
3260
  import { $ } from "execa";
3079
3261
  import { join as join4 } from "node:path";
3080
3262
 
3081
3263
  // src/utilities/getUserPackageManager.ts
3082
3264
  import { findUp as findUp2 } from "find-up";
3265
+ import { basename } from "path";
3083
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) {
3084
3272
  try {
3085
3273
  return await detectPackageManagerFromArtifacts(path7);
3086
3274
  } catch (error) {
@@ -3102,63 +3290,39 @@ function detectPackageManagerFromCurrentCommand() {
3102
3290
  }
3103
3291
  }
3104
3292
  async function detectPackageManagerFromArtifacts(path7) {
3105
- const packageFiles = [
3106
- { name: "yarn.lock", pm: "yarn" },
3107
- { name: "pnpm-lock.yaml", pm: "pnpm" },
3108
- { name: "package-lock.json", pm: "npm" },
3109
- { name: "npm-shrinkwrap.json", pm: "npm" }
3110
- ];
3111
- for (const { name, pm } of packageFiles) {
3112
- const foundPath = await findUp2(name, { cwd: path7 });
3113
- if (typeof foundPath === "string") {
3114
- return pm;
3115
- }
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");
3116
3302
  }
3117
- throw new Error("Could not detect package manager from artifacts");
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}`);
3314
+ }
3315
+ }
3316
+
3317
+ // src/utilities/assertExhaustive.ts
3318
+ function assertExhaustive(x) {
3319
+ throw new Error("Unexpected object: " + x);
3118
3320
  }
3119
3321
 
3120
3322
  // src/utilities/javascriptProject.ts
3121
- var BuiltInModules = /* @__PURE__ */ new Set([
3122
- "assert",
3123
- "async_hooks",
3124
- "buffer",
3125
- "child_process",
3126
- "cluster",
3127
- "console",
3128
- "constants",
3129
- "crypto",
3130
- "dgram",
3131
- "dns",
3132
- "domain",
3133
- "events",
3134
- "fs",
3135
- "http",
3136
- "http2",
3137
- "https",
3138
- "inspector",
3139
- "module",
3140
- "net",
3141
- "os",
3142
- "path",
3143
- "perf_hooks",
3144
- "process",
3145
- "punycode",
3146
- "querystring",
3147
- "readline",
3148
- "repl",
3149
- "stream",
3150
- "string_decoder",
3151
- "timers",
3152
- "tls",
3153
- "trace_events",
3154
- "tty",
3155
- "url",
3156
- "util",
3157
- "v8",
3158
- "vm",
3159
- "worker_threads",
3160
- "zlib"
3161
- ]);
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";
3162
3326
  var JavascriptProject = class {
3163
3327
  constructor(projectPath) {
3164
3328
  this.projectPath = projectPath;
@@ -3173,36 +3337,107 @@ var JavascriptProject = class {
3173
3337
  }
3174
3338
  get scripts() {
3175
3339
  return {
3176
- postinstall: this.packageJson.scripts?.postinstall
3340
+ postinstall: this.packageJson.scripts?.postinstall ?? ""
3177
3341
  };
3178
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
+ }
3179
3413
  async resolve(packageName, options) {
3180
- if (BuiltInModules.has(packageName)) {
3414
+ if (isBuiltInModule(packageName)) {
3181
3415
  return void 0;
3182
3416
  }
3183
- if (!this._packageManager) {
3184
- this._packageManager = await getUserPackageManager(this.projectPath);
3185
- }
3186
- const packageManager = this._packageManager;
3187
3417
  const opts = { allowDev: false, ...options };
3188
- const packageJsonVersion = this.packageJson.dependencies?.[packageName];
3189
- if (typeof packageJsonVersion === "string") {
3190
- return packageJsonVersion;
3191
- }
3192
- if (opts.allowDev) {
3193
- const devPackageJsonVersion = this.packageJson.devDependencies?.[packageName];
3194
- if (typeof devPackageJsonVersion === "string") {
3195
- return devPackageJsonVersion;
3196
- }
3197
- }
3198
- const command = packageManager === "npm" ? new NPMCommands() : packageManager === "pnpm" ? new PNPMCommands() : new YarnCommands();
3418
+ const command = await this.#getCommand();
3199
3419
  try {
3200
3420
  const version2 = await command.resolveDependencyVersion(packageName, {
3201
3421
  cwd: this.projectPath
3202
3422
  });
3203
3423
  if (version2) {
3424
+ logger.debug(`Resolved ${packageName} version using ${command.name}`, { version: version2 });
3204
3425
  return version2;
3205
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
+ }
3206
3441
  } catch (error) {
3207
3442
  logger.debug(`Failed to resolve dependency version using ${command.name}`, {
3208
3443
  packageName,
@@ -3210,16 +3445,41 @@ var JavascriptProject = class {
3210
3445
  });
3211
3446
  }
3212
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
+ }
3213
3467
  };
3214
3468
  var PNPMCommands = class {
3215
3469
  get name() {
3216
3470
  return "pnpm";
3217
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
+ }
3218
3479
  async resolveDependencyVersion(packageName, options) {
3219
- const cmd = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
3220
- const { stdout } = await $({ cwd: options.cwd })`${cmd} list ${packageName} -r --json`;
3480
+ const { stdout } = await $({ cwd: options.cwd })`${this.cmd} list ${packageName} -r --json`;
3221
3481
  const result = JSON.parse(stdout);
3222
- logger.debug(`Resolving ${packageName} version using pnpm`, { result });
3482
+ logger.debug(`Resolving ${packageName} version using ${this.name}`);
3223
3483
  for (const dep of result) {
3224
3484
  const dependency = dep.dependencies?.[packageName];
3225
3485
  if (dependency) {
@@ -3227,18 +3487,74 @@ var PNPMCommands = class {
3227
3487
  }
3228
3488
  }
3229
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
+ }
3230
3516
  };
3231
3517
  var NPMCommands = class {
3232
3518
  get name() {
3233
3519
  return "npm";
3234
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
+ }
3235
3528
  async resolveDependencyVersion(packageName, options) {
3236
- const cmd = process.platform === "win32" ? "npm.cmd" : "npm";
3237
- const { stdout } = await $({ cwd: options.cwd })`${cmd} list ${packageName} --json`;
3529
+ const { stdout } = await $({ cwd: options.cwd })`${this.cmd} list ${packageName} --json`;
3238
3530
  const output = JSON.parse(stdout);
3239
- logger.debug(`Resolving ${packageName} version using npm`, { output });
3531
+ logger.debug(`Resolving ${packageName} version using ${this.name}`, { output });
3240
3532
  return this.#recursivelySearchDependencies(output.dependencies, packageName);
3241
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
+ }
3242
3558
  #recursivelySearchDependencies(dependencies2, packageName) {
3243
3559
  for (const [name, dependency] of Object.entries(dependencies2)) {
3244
3560
  if (name === packageName) {
@@ -3257,11 +3573,17 @@ var YarnCommands = class {
3257
3573
  get name() {
3258
3574
  return "yarn";
3259
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
+ }
3260
3583
  async resolveDependencyVersion(packageName, options) {
3261
- const cmd = process.platform === "win32" ? "yarn.cmd" : "yarn";
3262
- const { stdout } = await $({ cwd: options.cwd })`${cmd} info ${packageName} --json`;
3584
+ const { stdout } = await $({ cwd: options.cwd })`${this.cmd} info ${packageName} --json`;
3263
3585
  const lines = stdout.split("\n");
3264
- logger.debug(`Resolving ${packageName} version using yarn`, { lines });
3586
+ logger.debug(`Resolving ${packageName} version using ${this.name}`);
3265
3587
  for (const line of lines) {
3266
3588
  const json = JSON.parse(line);
3267
3589
  if (json.value === packageName) {
@@ -3269,13 +3591,318 @@ var YarnCommands = class {
3269
3591
  }
3270
3592
  }
3271
3593
  }
3272
- };
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
+ }
3900
+ }
3273
3901
 
3274
3902
  // src/commands/deploy.ts
3275
3903
  var DeployCommandOptions = CommonCommandOptions.extend({
3276
3904
  skipTypecheck: z4.boolean().default(false),
3277
3905
  skipDeploy: z4.boolean().default(false),
3278
- ignoreEnvVarCheck: z4.boolean().default(false),
3279
3906
  env: z4.enum(["prod", "staging"]),
3280
3907
  loadImage: z4.boolean().default(false),
3281
3908
  buildPlatform: z4.enum(["linux/amd64", "linux/arm64"]).default("linux/amd64"),
@@ -3285,7 +3912,10 @@ var DeployCommandOptions = CommonCommandOptions.extend({
3285
3912
  config: z4.string().optional(),
3286
3913
  projectRef: z4.string().optional(),
3287
3914
  outputMetafile: z4.string().optional(),
3288
- 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)
3289
3919
  });
3290
3920
  function configureDeployCommand(program2) {
3291
3921
  return commonOptions(
@@ -3293,18 +3923,20 @@ function configureDeployCommand(program2) {
3293
3923
  "-e, --env <env>",
3294
3924
  "Deploy to a specific environment (currently only prod and staging are supported)",
3295
3925
  "prod"
3296
- ).option("--skip-typecheck", "Whether to skip the pre-build typecheck").option(
3297
- "--ignore-env-var-check",
3298
- "Detected missing environment variables won't block deployment"
3299
- ).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(
3300
3927
  "-p, --project-ref <project ref>",
3301
- "The project ref. Required if there is no config file."
3928
+ "The project ref. Required if there is no config file. This will override the project specified in the config file."
3302
3929
  )
3303
3930
  ).addOption(
3304
3931
  new CommandOption(
3305
3932
  "--self-hosted",
3306
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."
3307
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()
3308
3940
  ).addOption(
3309
3941
  new CommandOption(
3310
3942
  "--push",
@@ -3320,6 +3952,11 @@ function configureDeployCommand(program2) {
3320
3952
  "--tag <tag>",
3321
3953
  "(Coming soon) Specify the tag to use when pushing the image to the registry"
3322
3954
  ).hideHelp()
3955
+ ).addOption(
3956
+ new CommandOption(
3957
+ "--ignore-env-var-check",
3958
+ "(deprecated) Detected missing environment variables won't block deployment"
3959
+ ).hideHelp()
3323
3960
  ).addOption(new CommandOption("-D, --skip-deploy", "Skip deploying the image").hideHelp()).addOption(
3324
3961
  new CommandOption("--load-image", "Load the built image into your local docker").hideHelp()
3325
3962
  ).addOption(
@@ -3332,6 +3969,11 @@ function configureDeployCommand(program2) {
3332
3969
  "--output-metafile <path>",
3333
3970
  "If provided, will save the esbuild metafile for the build to the specified path"
3334
3971
  ).hideHelp()
3972
+ ).addOption(
3973
+ new CommandOption(
3974
+ "--save-logs",
3975
+ "If provided, will save logs even for successful builds"
3976
+ ).hideHelp()
3335
3977
  ).action(async (path7, options) => {
3336
3978
  await handleTelemetry(async () => {
3337
3979
  await printStandloneInitialBanner(true);
@@ -3346,7 +3988,10 @@ async function deployCommand(dir, options) {
3346
3988
  }
3347
3989
  async function _deployCommand(dir, options) {
3348
3990
  const span = trace2.getSpan(context.active());
3349
- intro3("Deploying project");
3991
+ intro4("Deploying project");
3992
+ if (!options.skipUpdateCheck) {
3993
+ await updateTriggerPackages(dir, { ...options }, true, true);
3994
+ }
3350
3995
  const authorization = await login({
3351
3996
  embedded: true,
3352
3997
  defaultApiUrl: options.apiUrl,
@@ -3370,6 +4015,11 @@ async function _deployCommand(dir, options) {
3370
4015
  configFile: options.config,
3371
4016
  projectRef: options.projectRef
3372
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
+ }
3373
4023
  logger.debug("Resolved config", { resolvedConfig });
3374
4024
  span?.setAttributes({
3375
4025
  "resolvedConfig.status": resolvedConfig.status,
@@ -3378,7 +4028,7 @@ async function _deployCommand(dir, options) {
3378
4028
  "resolvedConfig.config.projectDir": resolvedConfig.config.projectDir,
3379
4029
  "resolvedConfig.config.triggerUrl": resolvedConfig.config.triggerUrl,
3380
4030
  "resolvedConfig.config.triggerDirectories": resolvedConfig.config.triggerDirectories,
3381
- ...flattenAttributes2(resolvedConfig.config.retries, "resolvedConfig.config.retries")
4031
+ ...flattenAttributes3(resolvedConfig.config.retries, "resolvedConfig.config.retries")
3382
4032
  });
3383
4033
  const apiClient2 = new CliApiClient(authorization.auth.apiUrl, authorization.auth.accessToken);
3384
4034
  const deploymentEnv = await apiClient2.getProjectEnv({
@@ -3389,7 +4039,7 @@ async function _deployCommand(dir, options) {
3389
4039
  throw new Error(deploymentEnv.error);
3390
4040
  }
3391
4041
  const environmentClient = new CliApiClient(authorization.auth.apiUrl, deploymentEnv.data.apiKey);
3392
- log2.step(
4042
+ log5.step(
3393
4043
  `Preparing to deploy "${deploymentEnv.data.name}" (${resolvedConfig.config.project}) to ${options.env}`
3394
4044
  );
3395
4045
  const compilation = await compileProject(
@@ -3398,15 +4048,7 @@ async function _deployCommand(dir, options) {
3398
4048
  resolvedConfig.status === "file" ? resolvedConfig.path : void 0
3399
4049
  );
3400
4050
  logger.debug("Compilation result", { compilation });
3401
- if (compilation.envVars.length > 0) {
3402
- await checkEnvVars(
3403
- compilation.envVars ?? [],
3404
- resolvedConfig.config,
3405
- options,
3406
- environmentClient,
3407
- authorization.dashboardUrl
3408
- );
3409
- }
4051
+ await resolveEnvironmentVariables(resolvedConfig, environmentClient, options);
3410
4052
  const deploymentResponse = await environmentClient.initializeDeployment({
3411
4053
  contentHash: compilation.contentHash,
3412
4054
  userId: authorization.userId
@@ -3420,7 +4062,7 @@ async function _deployCommand(dir, options) {
3420
4062
  );
3421
4063
  }
3422
4064
  const version2 = deploymentResponse.data.version;
3423
- const deploymentSpinner = spinner4();
4065
+ const deploymentSpinner = spinner();
3424
4066
  deploymentSpinner.start(`Deploying version ${version2}`);
3425
4067
  const selfHostedRegistryHost = deploymentResponse.data.registryHost ?? options.registry;
3426
4068
  const registryHost = selfHostedRegistryHost ?? "registry.trigger.dev";
@@ -3437,7 +4079,8 @@ async function _deployCommand(dir, options) {
3437
4079
  projectRef: resolvedConfig.config.project,
3438
4080
  buildPlatform: options.buildPlatform,
3439
4081
  pushImage: options.push,
3440
- selfHostedRegistry: !!options.registry
4082
+ selfHostedRegistry: !!options.registry,
4083
+ noCache: options.noCache
3441
4084
  });
3442
4085
  }
3443
4086
  if (!deploymentResponse.data.externalBuildData) {
@@ -3460,25 +4103,42 @@ async function _deployCommand(dir, options) {
3460
4103
  contentHash: deploymentResponse.data.contentHash,
3461
4104
  projectRef: resolvedConfig.config.project,
3462
4105
  loadImage: options.loadImage,
3463
- buildPlatform: options.buildPlatform
4106
+ buildPlatform: options.buildPlatform,
4107
+ noCache: options.noCache
3464
4108
  },
3465
4109
  deploymentSpinner
3466
4110
  );
3467
4111
  };
3468
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
+ }
3469
4125
  if (!image.ok) {
3470
- deploymentSpinner.stop(`Failed to build project.`);
3471
- if (image.logs.trim() !== "") {
3472
- const logPath = join5(await createTempDir(), `build-${deploymentResponse.data.shortCode}.log`);
3473
- await writeFile2(logPath, image.logs);
3474
- logger.log(
3475
- `${chalkError("X Error:")} ${image.error}. Full build logs have been saved to ${logPath})`
3476
- );
3477
- } else {
3478
- logger.log(`${chalkError("X Error:")} ${image.error}.`);
3479
- }
4126
+ await failDeploy(
4127
+ deploymentResponse.data.shortCode,
4128
+ image.error,
4129
+ image.logs,
4130
+ deploymentSpinner,
4131
+ warnings.warnings
4132
+ );
3480
4133
  throw new SkipLoggingError(`Failed to build project image: ${image.error}`);
3481
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
+ };
3482
4142
  const imageReference = options.selfHosted ? `${selfHostedRegistryHost ? `${selfHostedRegistryHost}/` : ""}${image.image}${image.digest ? `@${image.digest}` : ""}` : `${registryHost}/${image.image}${image.digest ? `@${image.digest}` : ""}`;
3483
4143
  span?.setAttributes({
3484
4144
  "image.reference": imageReference
@@ -3487,6 +4147,7 @@ async function _deployCommand(dir, options) {
3487
4147
  deploymentSpinner.stop(
3488
4148
  `Project image built: ${imageReference}. Skipping deployment as requested`
3489
4149
  );
4150
+ await preExitTasks();
3490
4151
  throw new SkipCommandError("Skipping deployment as requested");
3491
4152
  }
3492
4153
  deploymentSpinner.message(
@@ -3496,11 +4157,13 @@ async function _deployCommand(dir, options) {
3496
4157
  const startIndexingResponse = await environmentClient.startDeploymentIndexing(
3497
4158
  deploymentResponse.data.id,
3498
4159
  {
3499
- imageReference
4160
+ imageReference,
4161
+ selfHosted: options.selfHosted
3500
4162
  }
3501
4163
  );
3502
4164
  if (!startIndexingResponse.success) {
3503
4165
  deploymentSpinner.stop(`Failed to start indexing: ${startIndexingResponse.error}`);
4166
+ await preExitTasks();
3504
4167
  throw new SkipLoggingError(`Failed to start indexing: ${startIndexingResponse.error}`);
3505
4168
  }
3506
4169
  const finishedDeployment = await waitForDeploymentToFinish(
@@ -3509,26 +4172,33 @@ async function _deployCommand(dir, options) {
3509
4172
  );
3510
4173
  if (!finishedDeployment) {
3511
4174
  deploymentSpinner.stop(`Deployment failed to complete`);
4175
+ await preExitTasks();
3512
4176
  throw new SkipLoggingError("Deployment failed to complete: unknown issue");
3513
4177
  }
3514
4178
  if (typeof finishedDeployment === "string") {
3515
4179
  deploymentSpinner.stop(`Deployment failed to complete: ${finishedDeployment}`);
4180
+ await preExitTasks();
3516
4181
  throw new SkipLoggingError(`Deployment failed to complete: ${finishedDeployment}`);
3517
4182
  }
3518
- const deploymentLink = terminalLink(
4183
+ const deploymentLink = terminalLink2(
3519
4184
  "View deployment",
3520
4185
  `${authorization.dashboardUrl}/projects/v3/${resolvedConfig.config.project}/deployments/${finishedDeployment.shortCode}`
3521
4186
  );
3522
4187
  switch (finishedDeployment.status) {
3523
4188
  case "DEPLOYED": {
3524
- 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();
3525
4195
  const taskCount = finishedDeployment.worker?.tasks.length ?? 0;
3526
4196
  if (taskCount === 0) {
3527
- outro3(
4197
+ outro5(
3528
4198
  `Version ${version2} deployed with no detected tasks. Please make sure you are exporting tasks in your project. ${deploymentLink}`
3529
4199
  );
3530
4200
  } else {
3531
- outro3(
4201
+ outro5(
3532
4202
  `Version ${version2} deployed with ${taskCount} detected task${taskCount === 1 ? "" : "s"} ${deploymentLink}`
3533
4203
  );
3534
4204
  }
@@ -3543,6 +4213,7 @@ async function _deployCommand(dir, options) {
3543
4213
  if (parsedError2.success) {
3544
4214
  deploymentSpinner.stop(`Deployment encountered an error. ${deploymentLink}`);
3545
4215
  logTaskMetadataParseError(parsedError2.data.zodIssues, parsedError2.data.tasks);
4216
+ await preExitTasks();
3546
4217
  throw new SkipLoggingError(
3547
4218
  `Deployment encountered an error: ${finishedDeployment.errorData.name}`
3548
4219
  );
@@ -3557,6 +4228,7 @@ async function _deployCommand(dir, options) {
3557
4228
  deploymentSpinner.stop(`Deployment encountered an error. ${deploymentLink}`);
3558
4229
  logESMRequireError(parsedError, resolvedConfig);
3559
4230
  }
4231
+ await preExitTasks();
3560
4232
  throw new SkipLoggingError(
3561
4233
  `Deployment encountered an error: ${finishedDeployment.errorData.name}`
3562
4234
  );
@@ -3564,62 +4236,132 @@ async function _deployCommand(dir, options) {
3564
4236
  deploymentSpinner.stop(
3565
4237
  `Deployment failed with an unknown error. Please contact eric@trigger.dev for help. ${deploymentLink}`
3566
4238
  );
4239
+ await preExitTasks();
3567
4240
  throw new SkipLoggingError("Deployment failed with an unknown error");
3568
4241
  }
3569
4242
  }
3570
4243
  case "CANCELED": {
3571
4244
  deploymentSpinner.stop(`Deployment was canceled. ${deploymentLink}`);
4245
+ await preExitTasks();
3572
4246
  throw new SkipLoggingError("Deployment was canceled");
3573
4247
  }
3574
4248
  case "TIMED_OUT": {
3575
4249
  deploymentSpinner.stop(`Deployment timed out. ${deploymentLink}`);
4250
+ await preExitTasks();
3576
4251
  throw new SkipLoggingError("Deployment timed out");
3577
4252
  }
3578
4253
  }
3579
4254
  }
3580
- async function checkEnvVars(envVars, config, options, environmentClient, apiUrl) {
3581
- return await tracer.startActiveSpan("detectEnvVars", async (span) => {
3582
- try {
3583
- span.setAttribute("envVars.check", envVars);
3584
- const environmentVariablesSpinner = spinner4();
3585
- environmentVariablesSpinner.start("Checking environment variables");
3586
- const environmentVariables = await environmentClient.getEnvironmentVariables(config.project);
3587
- if (!environmentVariables.success) {
3588
- environmentVariablesSpinner.stop(`Failed to fetch environment variables, skipping check`);
3589
- } else {
3590
- const missingEnvironmentVariables = envVars.filter(
3591
- (envVar) => environmentVariables.data.variables[envVar] === void 0
3592
- );
3593
- if (missingEnvironmentVariables.length > 0) {
3594
- environmentVariablesSpinner.stop(
3595
- `Found missing env vars in ${options.env}: ${arrayToSentence(
3596
- missingEnvironmentVariables
3597
- )}. ${options.ignoreEnvVarCheck ? "Continuing deployment because of --ignore-env-var-check. " : "Aborting deployment. "}${chalk5.bgBlueBright(
3598
- terminalLink(
3599
- "Manage env vars",
3600
- `${apiUrl}/projects/v3/${config.project}/environment-variables`
3601
- )
3602
- )}`
3603
- );
3604
- span.setAttributes({
3605
- "envVars.missing": missingEnvironmentVariables
3606
- });
3607
- if (!options.ignoreEnvVarCheck) {
3608
- throw new SkipLoggingError("Found missing environment variables");
3609
- } else {
3610
- span.end();
3611
- return;
3612
- }
3613
- }
3614
- environmentVariablesSpinner.stop(`Environment variable check passed`);
3615
- }
3616
- span.end();
3617
- } catch (e) {
3618
- recordSpanException4(span, e);
3619
- span.end();
3620
- 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
3621
4275
  }
3622
- });
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
+ }
3623
4365
  }
3624
4366
  async function waitForDeploymentToFinish(deploymentId, client, timeoutInSeconds = 60) {
3625
4367
  return tracer.startActiveSpan("waitForDeploymentToFinish", async (span) => {
@@ -3649,7 +4391,7 @@ async function waitForDeploymentToFinish(deploymentId, client, timeoutInSeconds
3649
4391
  await setTimeout2(1e3);
3650
4392
  }
3651
4393
  } catch (error) {
3652
- recordSpanException4(span, error);
4394
+ recordSpanException5(span, error);
3653
4395
  span.end();
3654
4396
  return error instanceof Error ? error.message : JSON.stringify(error);
3655
4397
  }
@@ -3676,6 +4418,7 @@ async function buildAndPushImage(options, updater) {
3676
4418
  "build",
3677
4419
  "-f",
3678
4420
  "Containerfile",
4421
+ options.noCache ? "--no-cache" : void 0,
3679
4422
  "--platform",
3680
4423
  options.buildPlatform,
3681
4424
  "--provenance",
@@ -3714,7 +4457,8 @@ async function buildAndPushImage(options, updater) {
3714
4457
  const processCode = await new Promise((res, rej) => {
3715
4458
  childProcess2.stderr?.on("data", (data) => {
3716
4459
  const text3 = data.toString();
3717
- errors.push(text3);
4460
+ const lines = text3.split("\n").filter(Boolean);
4461
+ errors.push(...lines);
3718
4462
  logger.debug(text3);
3719
4463
  });
3720
4464
  childProcess2.on("error", (e) => rej(e));
@@ -3740,7 +4484,7 @@ async function buildAndPushImage(options, updater) {
3740
4484
  digest
3741
4485
  };
3742
4486
  } catch (e) {
3743
- recordSpanException4(span, e);
4487
+ recordSpanException5(span, e);
3744
4488
  span.end();
3745
4489
  return {
3746
4490
  ok: false,
@@ -3766,6 +4510,7 @@ async function buildAndPushSelfHostedImage(options) {
3766
4510
  "build",
3767
4511
  "-f",
3768
4512
  "Containerfile",
4513
+ options.noCache ? "--no-cache" : void 0,
3769
4514
  "--platform",
3770
4515
  options.buildPlatform,
3771
4516
  "--build-arg",
@@ -3783,7 +4528,9 @@ async function buildAndPushSelfHostedImage(options) {
3783
4528
  "."
3784
4529
  // The build context
3785
4530
  ].filter(Boolean);
3786
- logger.debug(`docker ${buildArgs.join(" ")}`);
4531
+ logger.debug(`docker ${buildArgs.join(" ")}`, {
4532
+ cwd: options.cwd
4533
+ });
3787
4534
  span.setAttribute("docker.command.build", `docker ${buildArgs.join(" ")}`);
3788
4535
  const buildProcess = execa2("docker", buildArgs, {
3789
4536
  cwd: options.cwd
@@ -3812,7 +4559,7 @@ async function buildAndPushSelfHostedImage(options) {
3812
4559
  "image.digest": digest
3813
4560
  });
3814
4561
  } catch (e) {
3815
- recordSpanException4(span, e);
4562
+ recordSpanException5(span, e);
3816
4563
  span.end();
3817
4564
  return {
3818
4565
  ok: false,
@@ -3849,7 +4596,7 @@ async function buildAndPushSelfHostedImage(options) {
3849
4596
  }
3850
4597
  span.end();
3851
4598
  } catch (e) {
3852
- recordSpanException4(span, e);
4599
+ recordSpanException5(span, e);
3853
4600
  span.end();
3854
4601
  return {
3855
4602
  ok: false,
@@ -3868,13 +4615,12 @@ async function buildAndPushSelfHostedImage(options) {
3868
4615
  });
3869
4616
  }
3870
4617
  function extractImageDigest(outputs) {
3871
- const imageDigestRegex = /sha256:[a-f0-9]{64}/;
4618
+ const imageDigestRegex = /pushing manifest for .+(?<digest>sha256:[a-f0-9]{64})/;
3872
4619
  for (const line of outputs) {
3873
- if (line.includes("pushing manifest")) {
3874
- const imageDigestMatch = line.match(imageDigestRegex);
3875
- if (imageDigestMatch) {
3876
- return imageDigestMatch[0];
3877
- }
4620
+ const imageDigestMatch = line.match(imageDigestRegex);
4621
+ const digest = imageDigestMatch?.groups?.digest;
4622
+ if (digest) {
4623
+ return digest;
3878
4624
  }
3879
4625
  }
3880
4626
  }
@@ -3891,25 +4637,27 @@ async function compileProject(config, options, configPath) {
3891
4637
  throw new Error("Typecheck failed, aborting deployment");
3892
4638
  }
3893
4639
  }
3894
- const compileSpinner = spinner4();
4640
+ const compileSpinner = spinner();
3895
4641
  compileSpinner.start(`Building project in ${config.projectDir}`);
3896
4642
  const taskFiles = await gatherTaskFiles(config);
3897
4643
  const workerFacade = readFileSync2(
3898
- new URL(importResolve("./workers/prod/worker-facade.js", import.meta.url)).href.replace(
3899
- "file://",
3900
- ""
3901
- ),
4644
+ join6(cliRootPath(), "workers", "prod", "worker-facade.js"),
3902
4645
  "utf-8"
3903
4646
  );
3904
- const workerSetupPath = new URL(
3905
- importResolve("./workers/prod/worker-setup.js", import.meta.url)
3906
- ).href.replace("file://", "");
3907
- let workerContents = workerFacade.replace("__TASKS__", createTaskFileImports(taskFiles)).replace("__WORKER_SETUP__", `import { tracingSDK } from "${workerSetupPath}";`);
4647
+ const workerSetupPath = join6(cliRootPath(), "workers", "prod", "worker-setup.js");
4648
+ let workerContents = workerFacade.replace("__TASKS__", createTaskFileImports(taskFiles)).replace(
4649
+ "__WORKER_SETUP__",
4650
+ `import { tracingSDK, otelTracer, otelLogger } from "${escapeImportPath(
4651
+ workerSetupPath
4652
+ )}";`
4653
+ );
3908
4654
  if (configPath) {
3909
4655
  logger.debug("Importing project config from", { configPath });
3910
4656
  workerContents = workerContents.replace(
3911
4657
  "__IMPORTED_PROJECT_CONFIG__",
3912
- `import * as importedConfigExports from "${configPath}"; const importedConfig = importedConfigExports.config; const handleError = importedConfigExports.handleError;`
4658
+ `import * as importedConfigExports from "${escapeImportPath(
4659
+ configPath
4660
+ )}"; const importedConfig = importedConfigExports.config; const handleError = importedConfigExports.handleError;`
3913
4661
  );
3914
4662
  } else {
3915
4663
  workerContents = workerContents.replace(
@@ -3935,17 +4683,26 @@ async function compileProject(config, options, configPath) {
3935
4683
  // This is needed to support opentelemetry instrumentation that uses module patching
3936
4684
  target: ["node18", "es2020"],
3937
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
+ },
3938
4689
  define: {
3939
4690
  TRIGGER_API_URL: `"${config.triggerUrl}"`,
3940
4691
  __PROJECT_CONFIG__: JSON.stringify(config)
3941
4692
  },
3942
4693
  plugins: [
4694
+ mockServerOnlyPlugin(),
3943
4695
  bundleDependenciesPlugin(
3944
4696
  "workerFacade",
3945
4697
  config.dependenciesToBundle,
3946
4698
  config.tsconfigPath
3947
4699
  ),
3948
- workerSetupImportConfigPlugin(configPath)
4700
+ workerSetupImportConfigPlugin(configPath),
4701
+ esbuildDecorators2({
4702
+ tsconfig: config.tsconfigPath,
4703
+ tsx: true,
4704
+ force: false
4705
+ })
3949
4706
  ]
3950
4707
  });
3951
4708
  if (result.errors.length > 0) {
@@ -3958,13 +4715,10 @@ async function compileProject(config, options, configPath) {
3958
4715
  throw new Error("Build failed, aborting deployment");
3959
4716
  }
3960
4717
  if (options.outputMetafile) {
3961
- await writeJSONFile(join5(options.outputMetafile, "worker.json"), result.metafile);
4718
+ await writeJSONFile(join6(options.outputMetafile, "worker.json"), result.metafile);
3962
4719
  }
3963
4720
  const entryPointContents = readFileSync2(
3964
- new URL(importResolve("./workers/prod/entry-point.js", import.meta.url)).href.replace(
3965
- "file://",
3966
- ""
3967
- ),
4721
+ join6(cliRootPath(), "workers", "prod", "entry-point.js"),
3968
4722
  "utf-8"
3969
4723
  );
3970
4724
  const entryPointResult = await build2({
@@ -4007,42 +4761,43 @@ async function compileProject(config, options, configPath) {
4007
4761
  }
4008
4762
  if (options.outputMetafile) {
4009
4763
  await writeJSONFile(
4010
- join5(options.outputMetafile, "entry-point.json"),
4764
+ join6(options.outputMetafile, "entry-point.json"),
4011
4765
  entryPointResult.metafile
4012
4766
  );
4013
4767
  }
4014
4768
  const tempDir = await createTempDir();
4015
4769
  logger.debug(`Writing compiled files to ${tempDir}`);
4016
- const metaOutput = result.metafile.outputs[join5("out", "stdin.js")];
4770
+ const metaOutput = result.metafile.outputs[posix.join("out", "stdin.js")];
4017
4771
  invariant(metaOutput, "Meta output for the result build is missing");
4018
- const entryPointMetaOutput = entryPointResult.metafile.outputs[join5("out", "stdin.js")];
4772
+ const entryPointMetaOutput = entryPointResult.metafile.outputs[posix.join("out", "stdin.js")];
4019
4773
  invariant(entryPointMetaOutput, "Meta output for the entryPoint build is missing");
4020
4774
  const workerOutputFile = result.outputFiles.find(
4021
- (file) => file.path === join5(config.projectDir, "out", "stdin.js")
4775
+ (file) => file.path === join6(config.projectDir, "out", "stdin.js")
4022
4776
  );
4023
4777
  invariant(workerOutputFile, "Output file for the result build is missing");
4024
4778
  const workerSourcemapFile = result.outputFiles.find(
4025
- (file) => file.path === join5(config.projectDir, "out", "stdin.js.map")
4779
+ (file) => file.path === join6(config.projectDir, "out", "stdin.js.map")
4026
4780
  );
4027
4781
  invariant(workerSourcemapFile, "Sourcemap file for the result build is missing");
4028
4782
  const entryPointOutputFile = entryPointResult.outputFiles.find(
4029
- (file) => file.path === join5(config.projectDir, "out", "stdin.js")
4783
+ (file) => file.path === join6(config.projectDir, "out", "stdin.js")
4030
4784
  );
4031
4785
  invariant(entryPointOutputFile, "Output file for the entryPoint build is missing");
4032
4786
  await writeFile2(
4033
- join5(tempDir, "worker.js"),
4787
+ join6(tempDir, "worker.js"),
4034
4788
  `${workerOutputFile.text}
4035
4789
  //# sourceMappingURL=worker.js.map`
4036
4790
  );
4037
- await writeFile2(join5(tempDir, "worker.js.map"), workerSourcemapFile.text);
4038
- 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);
4039
4793
  logger.debug("Getting the imports for the worker and entryPoint builds", {
4040
4794
  workerImports: metaOutput.imports,
4041
4795
  entryPointImports: entryPointMetaOutput.imports
4042
4796
  });
4043
4797
  const allImports = [...metaOutput.imports, ...entryPointMetaOutput.imports];
4044
4798
  const javascriptProject = new JavascriptProject(config.projectDir);
4045
- const dependencies2 = await gatherRequiredDependencies(allImports, config, javascriptProject);
4799
+ const dependencies2 = await resolveRequiredDependencies(allImports, config, javascriptProject);
4800
+ logger.debug("gatherRequiredDependencies()", { dependencies: dependencies2 });
4046
4801
  const packageJsonContents = {
4047
4802
  name: "trigger-worker",
4048
4803
  version: "0.0.0",
@@ -4052,9 +4807,26 @@ async function compileProject(config, options, configPath) {
4052
4807
  ...javascriptProject.scripts
4053
4808
  }
4054
4809
  };
4055
- await writeJSONFile(join5(tempDir, "package.json"), packageJsonContents);
4056
- await copyAdditionalFiles(config, tempDir);
4057
- 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
+ }
4058
4830
  const resolvingDependenciesResult = await resolveDependencies(
4059
4831
  tempDir,
4060
4832
  packageJsonContents,
@@ -4064,52 +4836,114 @@ async function compileProject(config, options, configPath) {
4064
4836
  if (!resolvingDependenciesResult) {
4065
4837
  throw new SkipLoggingError("Failed to resolve dependencies");
4066
4838
  }
4067
- const containerFilePath = new URL(
4068
- importResolve("./Containerfile.prod", import.meta.url)
4069
- ).href.replace("file://", "");
4070
- 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);
4071
4850
  const contentHasher = createHash("sha256");
4072
4851
  contentHasher.update(Buffer.from(entryPointOutputFile.text));
4073
4852
  contentHasher.update(Buffer.from(workerOutputFile.text));
4074
4853
  contentHasher.update(Buffer.from(JSON.stringify(dependencies2)));
4075
4854
  const contentHash = contentHasher.digest("hex");
4076
- const workerSetupEnvVars = await findAllEnvironmentVariableReferencesInFile(workerSetupPath);
4077
- const workerFacadeEnvVars = findAllEnvironmentVariableReferences(workerContents);
4078
- const envVars = findAllEnvironmentVariableReferences(workerOutputFile.text);
4079
- const finalEnvVars = envVars.filter(
4080
- (envVar) => !workerFacadeEnvVars.includes(envVar) && !workerSetupEnvVars.includes(envVar)
4081
- );
4082
4855
  span.setAttributes({
4083
- contentHash,
4084
- envVars: finalEnvVars
4856
+ contentHash
4085
4857
  });
4086
4858
  span.end();
4087
- return { path: tempDir, contentHash, envVars: finalEnvVars };
4859
+ return { path: tempDir, contentHash };
4088
4860
  } catch (e) {
4089
- recordSpanException4(span, e);
4861
+ recordSpanException5(span, e);
4090
4862
  span.end();
4091
4863
  throw e;
4092
4864
  }
4093
4865
  });
4094
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
+ }
4095
4929
  async function resolveDependencies(projectDir, packageJsonContents, config, options) {
4096
4930
  return await tracer.startActiveSpan("resolveDependencies", async (span) => {
4097
- const resolvingDepsSpinner = spinner4();
4931
+ const resolvingDepsSpinner = spinner();
4098
4932
  resolvingDepsSpinner.start("Resolving dependencies");
4099
4933
  const hasher = createHash("sha256");
4100
4934
  hasher.update(JSON.stringify(packageJsonContents));
4101
4935
  const digest = hasher.digest("hex").slice(0, 16);
4102
- const cacheDir = join5(config.projectDir, ".trigger", "cache");
4103
- const cachePath = join5(cacheDir, `${digest}.json`);
4936
+ const cacheDir = join6(config.projectDir, ".trigger", "cache");
4937
+ const cachePath = join6(cacheDir, `${digest}.json`);
4104
4938
  span.setAttributes({
4105
4939
  "packageJson.digest": digest,
4106
4940
  "cache.path": cachePath,
4107
- ...flattenAttributes2(packageJsonContents, "packageJson.contents")
4941
+ ...flattenAttributes3(packageJsonContents, "packageJson.contents")
4108
4942
  });
4109
4943
  try {
4110
4944
  const cachedPackageLock = await readFile2(cachePath, "utf-8");
4111
4945
  logger.debug(`Using cached package-lock.json for ${digest}`);
4112
- await writeFile2(join5(projectDir, "package-lock.json"), cachedPackageLock);
4946
+ await writeFile2(join6(projectDir, "package-lock.json"), cachedPackageLock);
4113
4947
  span.setAttributes({
4114
4948
  "cache.hit": true
4115
4949
  });
@@ -4128,20 +4962,39 @@ async function resolveDependencies(projectDir, packageJsonContents, config, opti
4128
4962
  });
4129
4963
  logger.debug(`No cached package-lock.json found for ${digest}`);
4130
4964
  try {
4131
- await execa2("npm", ["install", "--package-lock-only", "--ignore-scripts", "--no-audit"], {
4132
- cwd: projectDir,
4133
- stdio: logger.loggerLevel === "debug" ? "inherit" : "pipe"
4134
- });
4135
- 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");
4136
4989
  logger.debug(`Writing package-lock.json to cache for ${digest}`);
4137
4990
  await mkdir(cacheDir, { recursive: true });
4138
4991
  await writeFile2(cachePath, packageLockContents);
4139
- await writeFile2(join5(projectDir, "package-lock.json"), packageLockContents);
4992
+ await writeFile2(join6(projectDir, "package-lock.json"), packageLockContents);
4140
4993
  span.end();
4141
4994
  resolvingDepsSpinner.stop("Dependencies resolved");
4142
4995
  return true;
4143
4996
  } catch (installError) {
4144
- recordSpanException4(span, installError);
4997
+ recordSpanException5(span, installError);
4145
4998
  span.end();
4146
4999
  const parsedError = parseNpmInstallError(installError);
4147
5000
  if (typeof parsedError === "string") {
@@ -4178,7 +5031,7 @@ ${chalkError("X Error:")} The package ${chalkPurple(
4178
5031
  async function typecheckProject(config, options) {
4179
5032
  return await tracer.startActiveSpan("typecheckProject", async (span) => {
4180
5033
  try {
4181
- const typecheckSpinner = spinner4();
5034
+ const typecheckSpinner = spinner();
4182
5035
  typecheckSpinner.start("Typechecking project");
4183
5036
  const tscTypecheck = execa2("npm", ["exec", "tsc", "--", "--noEmit"], {
4184
5037
  cwd: config.projectDir
@@ -4188,8 +5041,8 @@ async function typecheckProject(config, options) {
4188
5041
  tscTypecheck.stdout?.on("data", (chunk) => stdouts.push(chunk.toString()));
4189
5042
  tscTypecheck.stderr?.on("data", (chunk) => stderrs.push(chunk.toString()));
4190
5043
  try {
4191
- await new Promise((resolve4, reject) => {
4192
- 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));
4193
5046
  });
4194
5047
  } catch (error) {
4195
5048
  typecheckSpinner.stop(
@@ -4207,64 +5060,100 @@ async function typecheckProject(config, options) {
4207
5060
  span.end();
4208
5061
  return true;
4209
5062
  } catch (e) {
4210
- recordSpanException4(span, e);
5063
+ recordSpanException5(span, e);
4211
5064
  span.end();
4212
5065
  return false;
4213
5066
  }
4214
5067
  });
4215
5068
  }
4216
- async function gatherRequiredDependencies(imports, config, project) {
4217
- const dependencies2 = {};
4218
- for (const file of imports) {
4219
- if (file.kind !== "require-call" && file.kind !== "dynamic-import" || !file.external) {
4220
- continue;
4221
- }
4222
- const packageName = detectPackageNameFromImportPath(file.path);
4223
- if (dependencies2[packageName]) {
4224
- continue;
4225
- }
4226
- const externalDependencyVersion = await project.resolve(packageName);
4227
- if (externalDependencyVersion) {
4228
- dependencies2[packageName] = stripWorkspaceFromVersion(externalDependencyVersion);
4229
- continue;
4230
- }
4231
- const internalDependencyVersion = dependencies[packageName] ?? detectDependencyVersion(packageName);
4232
- if (internalDependencyVersion) {
4233
- dependencies2[packageName] = stripWorkspaceFromVersion(internalDependencyVersion);
4234
- }
4235
- }
4236
- if (config.additionalPackages) {
4237
- for (const packageName of config.additionalPackages) {
4238
- 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) {
4239
5074
  continue;
4240
5075
  }
4241
- const packageParts = parsePackageName(packageName);
4242
- if (packageParts.version) {
4243
- dependencies2[packageParts.name] = packageParts.version;
5076
+ const packageName = detectPackageNameFromImportPath(file.path);
5077
+ if (!packageName) {
4244
5078
  continue;
4245
- } else {
4246
- const externalDependencyVersion = await project.resolve(packageParts.name, {
4247
- allowDev: true
4248
- });
4249
- if (externalDependencyVersion) {
4250
- 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;
4251
5110
  continue;
4252
5111
  } else {
4253
- logger.log(
4254
- `${chalkWarning("X Warning:")} Could not find version for package ${chalkPurple(
4255
- packageName
4256
- )}, add a version specifier to the package name (e.g. ${packageParts.name}@latest) or add it to your project's package.json`
4257
- );
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
+ }
4258
5125
  }
4259
5126
  }
4260
5127
  }
4261
- }
4262
- 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
+ });
4263
5151
  }
4264
5152
  async function copyAdditionalFiles(config, tempDir) {
4265
5153
  const additionalFiles = config.additionalFiles ?? [];
5154
+ const noMatches = [];
4266
5155
  if (additionalFiles.length === 0) {
4267
- return;
5156
+ return { ok: true };
4268
5157
  }
4269
5158
  return await tracer.startActiveSpan(
4270
5159
  "copyAdditionalFiles",
@@ -4278,24 +5167,57 @@ async function copyAdditionalFiles(config, tempDir) {
4278
5167
  logger.debug(`Copying files to ${tempDir}`, {
4279
5168
  additionalFiles
4280
5169
  });
4281
- const glob = new Glob(additionalFiles, {
5170
+ const globOptions = {
4282
5171
  withFileTypes: true,
4283
5172
  ignore: ["node_modules"],
4284
5173
  cwd: config.projectDir,
4285
5174
  nodir: true
4286
- });
4287
- for await (const file of glob) {
4288
- const relativeDestinationPath = join5(
4289
- tempDir,
4290
- relative3(config.projectDir, file.fullpath())
4291
- );
4292
- logger.debug(`Copying file ${file.fullpath()} to ${relativeDestinationPath}`);
4293
- await mkdir(dirname(relativeDestinationPath), { recursive: true });
4294
- 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++;
4295
5208
  }
4296
5209
  span.end();
5210
+ if (noMatches.length > 0) {
5211
+ return {
5212
+ ok: false,
5213
+ noMatches
5214
+ };
5215
+ }
5216
+ return {
5217
+ ok: true
5218
+ };
4297
5219
  } catch (error) {
4298
- recordSpanException4(span, error);
5220
+ recordSpanException5(span, error);
4299
5221
  span.end();
4300
5222
  throw error;
4301
5223
  }
@@ -4304,7 +5226,7 @@ async function copyAdditionalFiles(config, tempDir) {
4304
5226
  }
4305
5227
  async function ensureLoggedIntoDockerRegistry(registryHost, auth) {
4306
5228
  const tmpDir = await createTempDir();
4307
- const dockerConfigPath = join5(tmpDir, "config.json");
5229
+ const dockerConfigPath = join6(tmpDir, "config.json");
4308
5230
  await writeJSONFile(dockerConfigPath, {
4309
5231
  auths: {
4310
5232
  [registryHost]: {
@@ -4315,42 +5237,20 @@ async function ensureLoggedIntoDockerRegistry(registryHost, auth) {
4315
5237
  logger.debug(`Writing docker config to ${dockerConfigPath}`);
4316
5238
  return tmpDir;
4317
5239
  }
4318
- async function findAllEnvironmentVariableReferencesInFile(filePath) {
4319
- const fileContents = await readFile2(filePath, "utf-8");
4320
- return findAllEnvironmentVariableReferences(fileContents);
4321
- }
4322
- var IGNORED_ENV_VARS = ["NODE_ENV", "SHELL", "HOME", "PWD", "LOGNAME", "USER", "PATH", "DEBUG"];
4323
- function findAllEnvironmentVariableReferences(code) {
4324
- const regex = /\bprocess\.env\.([a-zA-Z_][a-zA-Z0-9_]*)\b/g;
4325
- const matches = code.matchAll(regex);
4326
- const matchesArray = Array.from(matches, (match) => match[1]).filter(Boolean);
4327
- const filteredMatches = matchesArray.filter((match) => !IGNORED_ENV_VARS.includes(match));
4328
- return Array.from(new Set(filteredMatches));
4329
- }
4330
- function arrayToSentence(items) {
4331
- if (items.length === 1 && typeof items[0] === "string") {
4332
- return items[0];
4333
- }
4334
- if (items.length === 2) {
4335
- return `${items[0]} and ${items[1]}`;
4336
- }
4337
- return `${items.slice(0, -1).join(", ")}, and ${items[items.length - 1]}`;
4338
- }
4339
5240
 
4340
5241
  // src/commands/dev.tsx
4341
5242
  import {
4342
- ZodMessageHandler as ZodMessageHandler2,
4343
- ZodMessageSender as ZodMessageSender2,
4344
5243
  clientWebsocketMessages,
4345
5244
  detectDependencyVersion as detectDependencyVersion2,
4346
5245
  serverWebsocketMessages
4347
5246
  } from "@trigger.dev/core/v3";
5247
+ import { ZodMessageHandler as ZodMessageHandler2, ZodMessageSender as ZodMessageSender2 } from "@trigger.dev/core/v3/zodMessageHandler";
4348
5248
  import { watch } from "chokidar";
4349
5249
  import { context as context2 } from "esbuild";
4350
5250
  import { render, useInput } from "ink";
4351
5251
  import { createHash as createHash2 } from "node:crypto";
4352
5252
  import fs7, { readFileSync as readFileSync3 } from "node:fs";
4353
- 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";
4354
5254
  import pDebounce from "p-debounce";
4355
5255
  import { WebSocket } from "partysocket";
4356
5256
  import React, { Suspense, useEffect } from "react";
@@ -4379,18 +5279,17 @@ var TaskMetadataParseError = class extends Error {
4379
5279
  import {
4380
5280
  SemanticInternalAttributes,
4381
5281
  TaskRunErrorCodes,
4382
- ZodMessageHandler,
4383
- ZodMessageSender,
4384
5282
  childToWorkerMessages,
4385
5283
  correctErrorStackTrace,
4386
5284
  formatDurationMilliseconds,
4387
5285
  workerToChildMessages
4388
5286
  } from "@trigger.dev/core/v3";
5287
+ import { ZodMessageHandler, ZodMessageSender } from "@trigger.dev/core/v3/zodMessageHandler";
4389
5288
  import dotenv from "dotenv";
4390
5289
  import { Evt } from "evt";
4391
5290
  import { fork } from "node:child_process";
4392
- import { dirname as dirname2, resolve as resolve2 } from "node:path";
4393
- import terminalLink2 from "terminal-link";
5291
+ import { dirname as dirname2, resolve as resolve4 } from "node:path";
5292
+ import terminalLink3 from "terminal-link";
4394
5293
  var BackgroundWorkerCoordinator = class {
4395
5294
  constructor(baseURL) {
4396
5295
  this.baseURL = baseURL;
@@ -4475,7 +5374,7 @@ var BackgroundWorkerCoordinator = class {
4475
5374
  const logsUrl = `${this.baseURL}/runs/${execution.run.id}`;
4476
5375
  const pipe = chalkGrey("|");
4477
5376
  const bullet = chalkGrey("\u25CB");
4478
- const link = chalkLink(terminalLink2("View logs", logsUrl));
5377
+ const link = chalkLink(terminalLink3("View logs", logsUrl));
4479
5378
  let timestampPrefix = chalkGrey(prettyPrintDate(payload.execution.attempt.startedAt));
4480
5379
  const workerPrefix = chalkWorker(record.version);
4481
5380
  const taskPrefix = chalkTask(execution.task.id);
@@ -4562,6 +5461,7 @@ var BackgroundWorker = class {
4562
5461
  metadata;
4563
5462
  _taskRunProcesses = /* @__PURE__ */ new Map();
4564
5463
  _closed = false;
5464
+ _fullEnv = {};
4565
5465
  close() {
4566
5466
  if (this._closed) {
4567
5467
  return;
@@ -4584,12 +5484,24 @@ var BackgroundWorker = class {
4584
5484
  }
4585
5485
  let resolved = false;
4586
5486
  const cwd = dirname2(this.path);
4587
- const fullEnv = {
5487
+ this._fullEnv = {
4588
5488
  ...this.params.env,
4589
- ...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
4590
5502
  };
4591
- logger.debug("Initializing worker", { path: this.path, cwd, fullEnv });
4592
- 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) => {
4593
5505
  const child = fork(this.path, {
4594
5506
  stdio: [
4595
5507
  /*stdin*/
@@ -4601,7 +5513,7 @@ var BackgroundWorker = class {
4601
5513
  "ipc"
4602
5514
  ],
4603
5515
  cwd,
4604
- env: fullEnv
5516
+ env: this._fullEnv
4605
5517
  });
4606
5518
  const timeout = setTimeout(() => {
4607
5519
  if (resolved) {
@@ -4616,7 +5528,7 @@ var BackgroundWorker = class {
4616
5528
  if (message.type === "TASKS_READY" && !resolved) {
4617
5529
  clearTimeout(timeout);
4618
5530
  resolved = true;
4619
- resolve4(message.payload.tasks);
5531
+ resolve6(message.payload.tasks);
4620
5532
  child.kill();
4621
5533
  } else if (message.type === "UNCAUGHT_EXCEPTION") {
4622
5534
  clearTimeout(timeout);
@@ -4637,6 +5549,9 @@ var BackgroundWorker = class {
4637
5549
  reject(new Error(`Worker exited with code ${code}`));
4638
5550
  }
4639
5551
  });
5552
+ child.stdout?.on("data", (data) => {
5553
+ logger.log(data.toString());
5554
+ });
4640
5555
  });
4641
5556
  this._initialized = true;
4642
5557
  }
@@ -4656,9 +5571,8 @@ var BackgroundWorker = class {
4656
5571
  payload.execution,
4657
5572
  this.path,
4658
5573
  {
4659
- ...this.params.env,
4660
- ...payload.environment ?? {},
4661
- ...this.#readEnvVars()
5574
+ ...this._fullEnv,
5575
+ ...payload.environment ?? {}
4662
5576
  },
4663
5577
  this.metadata,
4664
5578
  this.params
@@ -4748,7 +5662,7 @@ var BackgroundWorker = class {
4748
5662
  const result = {};
4749
5663
  dotenv.config({
4750
5664
  processEnv: result,
4751
- 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))
4752
5666
  });
4753
5667
  process.env.TRIGGER_API_URL && (result.TRIGGER_API_URL = process.env.TRIGGER_API_URL);
4754
5668
  delete result.TRIGGER_API_URL;
@@ -4839,12 +5753,18 @@ var TaskRunProcess = class {
4839
5753
  kill
4840
5754
  });
4841
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);
4842
5762
  }
4843
5763
  async executeTaskRun(payload) {
4844
5764
  let resolver;
4845
5765
  let rejecter;
4846
- const promise = new Promise((resolve4, reject) => {
4847
- resolver = resolve4;
5766
+ const promise = new Promise((resolve6, reject) => {
5767
+ resolver = resolve6;
4848
5768
  rejecter = reject;
4849
5769
  });
4850
5770
  this._attemptStatuses.set(payload.execution.attempt.id, "PENDING");
@@ -4895,6 +5815,7 @@ var TaskRunProcess = class {
4895
5815
  break;
4896
5816
  }
4897
5817
  case "READY_TO_DISPOSE": {
5818
+ logger.debug(`[${this.execution.run.id}] task run process is ready to dispose`);
4898
5819
  this.#kill();
4899
5820
  break;
4900
5821
  }
@@ -4930,10 +5851,14 @@ var TaskRunProcess = class {
4930
5851
  }
4931
5852
  #handleLog(data) {
4932
5853
  if (!this._currentExecution) {
5854
+ logger.log(`${chalkGrey("\u25CB")} ${chalkGrey(prettyPrintDate(/* @__PURE__ */ new Date()))} ${data.toString()}`);
4933
5855
  return;
4934
5856
  }
5857
+ const runId = chalkRun(
5858
+ `${this._currentExecution.run.id}.${this._currentExecution.attempt.number}`
5859
+ );
4935
5860
  logger.log(
4936
- `[${this.metadata.version}][${this._currentExecution.run.id}.${this._currentExecution.attempt.number}] ${data.toString()}`
5861
+ `${chalkGrey("\u25CB")} ${chalkGrey(prettyPrintDate(/* @__PURE__ */ new Date()))} ${runId} ${data.toString()}`
4937
5862
  );
4938
5863
  }
4939
5864
  #handleStdErr(data) {
@@ -4941,15 +5866,19 @@ var TaskRunProcess = class {
4941
5866
  return;
4942
5867
  }
4943
5868
  if (!this._currentExecution) {
4944
- logger.error(`[${this.metadata.version}] ${data.toString()}`);
5869
+ logger.log(`${chalkError("\u25CB")} ${chalkGrey(prettyPrintDate(/* @__PURE__ */ new Date()))} ${data.toString()}`);
4945
5870
  return;
4946
5871
  }
4947
- logger.error(
4948
- `[${this.metadata.version}][${this._currentExecution.run.id}.${this._currentExecution.attempt.number}] ${data.toString()}`
5872
+ const runId = chalkRun(
5873
+ `${this._currentExecution.run.id}.${this._currentExecution.attempt.number}`
5874
+ );
5875
+ logger.log(
5876
+ `${chalkError("\u25CB")} ${chalkGrey(prettyPrintDate(/* @__PURE__ */ new Date()))} ${runId} ${data.toString()}`
4949
5877
  );
4950
5878
  }
4951
5879
  #kill() {
4952
5880
  if (this._child && !this._child.killed) {
5881
+ logger.debug(`[${this.execution.run.id}] killing task run process`);
4953
5882
  this._child?.kill();
4954
5883
  }
4955
5884
  }
@@ -4976,30 +5905,21 @@ function runtimeCheck(minimumMajor, minimumMinor) {
4976
5905
 
4977
5906
  // src/commands/dev.tsx
4978
5907
  import { findUp as findUp3, pathExists as pathExists2 } from "find-up";
4979
-
4980
- // src/utilities/resolveInternalFilePath.ts
4981
- import path5 from "path";
4982
- import { fileURLToPath as fileURLToPath3 } from "url";
4983
- function cliRootPath() {
4984
- const __filename2 = fileURLToPath3(import.meta.url);
4985
- const __dirname2 = path5.dirname(__filename2);
4986
- return __dirname2;
4987
- }
4988
-
4989
- // src/commands/dev.tsx
5908
+ import { esbuildDecorators as esbuildDecorators3 } from "@anatine/esbuild-decorators";
4990
5909
  var apiClient;
4991
5910
  var DevCommandOptions = CommonCommandOptions.extend({
4992
5911
  debugger: z5.boolean().default(false),
4993
5912
  debugOtel: z5.boolean().default(false),
4994
5913
  config: z5.string().optional(),
4995
- projectRef: z5.string().optional()
5914
+ projectRef: z5.string().optional(),
5915
+ skipUpdateCheck: z5.boolean().default(false)
4996
5916
  });
4997
5917
  function configureDevCommand(program2) {
4998
5918
  return commonOptions(
4999
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(
5000
5920
  "-p, --project-ref <project ref>",
5001
5921
  "The project ref. Required if there is no config file."
5002
- ).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")
5003
5923
  ).action(async (path7, options) => {
5004
5924
  wrapCommandAction("dev", DevCommandOptions, options, async (opts) => {
5005
5925
  await devCommand(path7, opts);
@@ -5041,29 +5961,37 @@ async function startDev(dir, options, authorization, dashboardUrl) {
5041
5961
  logger.loggerLevel = options.logLevel;
5042
5962
  }
5043
5963
  await printStandloneInitialBanner(true);
5044
- printDevBanner();
5964
+ let displayedUpdateMessage = false;
5965
+ if (!options.skipUpdateCheck) {
5966
+ displayedUpdateMessage = await updateTriggerPackages(dir, { ...options }, true, true);
5967
+ }
5968
+ printDevBanner(displayedUpdateMessage);
5045
5969
  logger.debug("Starting dev session", { dir, options, authorization });
5046
5970
  let config = await readConfig(dir, {
5047
5971
  projectRef: options.projectRef,
5048
5972
  configFile: options.config
5049
5973
  });
5050
5974
  logger.debug("Initial config", { config });
5051
- 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) {
5052
5980
  const accessToken = authorization2.accessToken;
5053
5981
  const apiUrl = authorization2.apiUrl;
5054
5982
  apiClient = new CliApiClient(apiUrl, accessToken);
5055
5983
  const devEnv = await apiClient.getProjectEnv({
5056
- projectRef: config.config.project,
5984
+ projectRef: configParam.project,
5057
5985
  env: "dev"
5058
5986
  });
5059
5987
  if (!devEnv.success) {
5060
5988
  if (devEnv.error === "Project not found") {
5061
5989
  logger.error(
5062
- `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}`
5063
5991
  );
5064
5992
  } else {
5065
5993
  logger.error(
5066
- `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}`
5067
5995
  );
5068
5996
  }
5069
5997
  process.exit(1);
@@ -5080,7 +6008,8 @@ async function startDev(dir, options, authorization, dashboardUrl) {
5080
6008
  projectName: devEnv.data.name,
5081
6009
  debuggerOn: options.debugger,
5082
6010
  debugOtel: options.debugOtel,
5083
- configPath
6011
+ configPath,
6012
+ configModule
5084
6013
  }
5085
6014
  );
5086
6015
  }
@@ -5088,7 +6017,8 @@ async function startDev(dir, options, authorization, dashboardUrl) {
5088
6017
  await getDevReactElement(
5089
6018
  config.config,
5090
6019
  authorization,
5091
- config.status === "file" ? config.path : void 0
6020
+ config.status === "file" ? config.path : void 0,
6021
+ config.status === "file" ? config.module : void 0
5092
6022
  )
5093
6023
  );
5094
6024
  rerender = devReactElement.rerender;
@@ -5111,7 +6041,8 @@ function useDev({
5111
6041
  projectName,
5112
6042
  debuggerOn,
5113
6043
  debugOtel,
5114
- configPath
6044
+ configPath,
6045
+ configModule
5115
6046
  }) {
5116
6047
  useEffect(() => {
5117
6048
  const websocketUrl = new URL(apiUrl);
@@ -5200,22 +6131,30 @@ function useDev({
5200
6131
  await messageHandler.handleMessage(data);
5201
6132
  });
5202
6133
  let ctx;
6134
+ let firstBuild = true;
5203
6135
  async function runBuild() {
5204
6136
  if (ctx) {
5205
6137
  await ctx.dispose();
5206
6138
  }
5207
6139
  let latestWorkerContentHash;
5208
6140
  const taskFiles = await gatherTaskFiles(config);
5209
- const workerFacadePath = join6(cliRootPath(), "workers", "dev", "worker-facade.js");
6141
+ const workerFacadePath = join7(cliRootPath(), "workers", "dev", "worker-facade.js");
5210
6142
  const workerFacade = readFileSync3(workerFacadePath, "utf-8");
5211
- const workerSetupPath = join6(cliRootPath(), "workers", "dev", "worker-setup.js");
5212
- let entryPointContents = workerFacade.replace("__TASKS__", createTaskFileImports(taskFiles)).replace("__WORKER_SETUP__", `import { tracingSDK, sender } from "${workerSetupPath}";`);
6143
+ const workerSetupPath = join7(cliRootPath(), "workers", "dev", "worker-setup.js");
6144
+ let entryPointContents = workerFacade.replace("__TASKS__", createTaskFileImports(taskFiles)).replace(
6145
+ "__WORKER_SETUP__",
6146
+ `import { tracingSDK, otelTracer, otelLogger, sender } from "${escapeImportPath(
6147
+ workerSetupPath
6148
+ )}";`
6149
+ );
5213
6150
  if (configPath) {
5214
6151
  configPath = normalize(configPath);
5215
6152
  logger.debug("Importing project config from", { configPath });
5216
6153
  entryPointContents = entryPointContents.replace(
5217
6154
  "__IMPORTED_PROJECT_CONFIG__",
5218
- `import * as importedConfigExports from "${configPath}"; const importedConfig = importedConfigExports.config; const handleError = importedConfigExports.handleError;`
6155
+ `import * as importedConfigExports from "${escapeImportPath(
6156
+ configPath
6157
+ )}"; const importedConfig = importedConfigExports.config; const handleError = importedConfigExports.handleError;`
5219
6158
  );
5220
6159
  } else {
5221
6160
  entryPointContents = entryPointContents.replace(
@@ -5223,15 +6162,16 @@ function useDev({
5223
6162
  `const importedConfig = undefined; const handleError = undefined;`
5224
6163
  );
5225
6164
  }
5226
- let firstBuild = true;
5227
6165
  logger.log(chalkGrey("\u25CB Building background worker\u2026"));
5228
- logger.debug("entryPointContents before esbuild", { entryPointContents });
5229
6166
  ctx = await context2({
5230
6167
  stdin: {
5231
6168
  contents: entryPointContents,
5232
6169
  resolveDir: process.cwd(),
5233
6170
  sourcefile: "__entryPoint.ts"
5234
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
+ },
5235
6175
  bundle: true,
5236
6176
  metafile: true,
5237
6177
  write: false,
@@ -5249,6 +6189,7 @@ function useDev({
5249
6189
  __PROJECT_CONFIG__: JSON.stringify(config)
5250
6190
  },
5251
6191
  plugins: [
6192
+ mockServerOnlyPlugin(),
5252
6193
  bundleTriggerDevCore("workerFacade", config.tsconfigPath),
5253
6194
  bundleDependenciesPlugin(
5254
6195
  "workerFacade",
@@ -5256,6 +6197,11 @@ function useDev({
5256
6197
  config.tsconfigPath
5257
6198
  ),
5258
6199
  workerSetupImportConfigPlugin(configPath),
6200
+ esbuildDecorators3({
6201
+ tsconfig: config.tsconfigPath,
6202
+ tsx: true,
6203
+ force: false
6204
+ }),
5259
6205
  {
5260
6206
  name: "trigger.dev v3",
5261
6207
  setup(build3) {
@@ -5269,20 +6215,19 @@ function useDev({
5269
6215
  if (!firstBuild) {
5270
6216
  logger.log(chalkGrey("\u25CB Building background worker\u2026"));
5271
6217
  }
5272
- const metaOutputKey = join6("out", `stdin.js`).replace(/\\/g, "/");
5273
- logger.debug("Metafile", { metafileOutputs: result.metafile?.outputs });
6218
+ const metaOutputKey = join7("out", `stdin.js`).replace(/\\/g, "/");
5274
6219
  const metaOutput = result.metafile.outputs[metaOutputKey];
5275
6220
  if (!metaOutput) {
5276
6221
  throw new Error(`Could not find metafile`);
5277
6222
  }
5278
- const outputFileKey = join6(config.projectDir, metaOutputKey);
6223
+ const outputFileKey = join7(config.projectDir, metaOutputKey);
5279
6224
  const outputFile = result.outputFiles.find((file) => file.path === outputFileKey);
5280
6225
  if (!outputFile) {
5281
6226
  throw new Error(
5282
6227
  `Could not find output file for entry point ${metaOutput.entryPoint}`
5283
6228
  );
5284
6229
  }
5285
- const sourceMapFileKey = join6(config.projectDir, `${metaOutputKey}.map`);
6230
+ const sourceMapFileKey = join7(config.projectDir, `${metaOutputKey}.map`);
5286
6231
  const sourceMapFile = result.outputFiles.find(
5287
6232
  (file) => file.path === sourceMapFileKey
5288
6233
  );
@@ -5293,14 +6238,14 @@ function useDev({
5293
6238
  logger.log(chalkGrey("\u25CB No changes detected, skipping build\u2026"));
5294
6239
  return;
5295
6240
  }
5296
- const fullPath = join6(config.projectDir, ".trigger", `${contentHash}.js`);
6241
+ const fullPath = join7(config.projectDir, ".trigger", `${contentHash}.js`);
5297
6242
  const sourceMapPath = `${fullPath}.map`;
5298
6243
  const outputFileWithSourceMap = `${outputFile.text}
5299
- //# sourceMappingURL=${basename(sourceMapPath)}`;
6244
+ //# sourceMappingURL=${basename2(sourceMapPath)}`;
5300
6245
  await fs7.promises.mkdir(dirname3(fullPath), { recursive: true });
5301
6246
  await fs7.promises.writeFile(fullPath, outputFileWithSourceMap);
5302
6247
  logger.debug(`Wrote background worker to ${fullPath}`);
5303
- const dependencies2 = await gatherRequiredDependencies2(metaOutput, config);
6248
+ const dependencies2 = await gatherRequiredDependencies(metaOutput, config);
5304
6249
  if (sourceMapFile) {
5305
6250
  const sourceMapPath2 = `${fullPath}.map`;
5306
6251
  await fs7.promises.writeFile(sourceMapPath2, sourceMapFile.text);
@@ -5317,15 +6262,23 @@ function useDev({
5317
6262
  ...environmentVariablesResponse.success ? environmentVariablesResponse.data.variables : {}
5318
6263
  },
5319
6264
  debuggerOn,
5320
- debugOtel
6265
+ debugOtel,
6266
+ resolveEnvVariables: createResolveEnvironmentVariablesFunction(configModule)
5321
6267
  });
5322
6268
  try {
5323
6269
  await backgroundWorker.initialize();
5324
6270
  latestWorkerContentHash = contentHash;
5325
6271
  let packageVersion;
5326
6272
  const taskResources = [];
5327
- if (!backgroundWorker.tasks) {
5328
- 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;
5329
6282
  }
5330
6283
  for (const task of backgroundWorker.tasks) {
5331
6284
  taskResources.push(task);
@@ -5344,6 +6297,9 @@ function useDev({
5344
6297
  );
5345
6298
  return;
5346
6299
  }
6300
+ logger.debug("Creating background worker with tasks", {
6301
+ tasks: taskResources
6302
+ });
5347
6303
  const backgroundWorkerBody = {
5348
6304
  localOnly: true,
5349
6305
  metadata: {
@@ -5387,10 +6343,10 @@ function useDev({
5387
6343
  return;
5388
6344
  } else {
5389
6345
  }
5390
- if (e.originalError.stack) {
6346
+ if (e.originalError.message || e.originalError.stack) {
5391
6347
  logger.log(
5392
6348
  `${chalkError("X Error:")} Worker failed to start`,
5393
- e.originalError.stack
6349
+ e.originalError.stack ?? e.originalError.message
5394
6350
  );
5395
6351
  }
5396
6352
  return;
@@ -5430,7 +6386,7 @@ ${chalkError("X Error:")} The package ${chalkPurple(
5430
6386
  }
5431
6387
  const throttledRebuild = pDebounce(runBuild, 250, { before: true });
5432
6388
  const taskFileWatcher = watch(
5433
- config.triggerDirectories.map((triggerDir) => `${triggerDir}/*.ts`),
6389
+ config.triggerDirectories.map((triggerDir) => `${triggerDir}/**/*.ts`),
5434
6390
  {
5435
6391
  ignoreInitial: true
5436
6392
  }
@@ -5481,7 +6437,7 @@ function WebsocketFactory(apiKey) {
5481
6437
  }
5482
6438
  };
5483
6439
  }
5484
- async function gatherRequiredDependencies2(outputMeta, config) {
6440
+ async function gatherRequiredDependencies(outputMeta, config) {
5485
6441
  const dependencies2 = {};
5486
6442
  logger.debug("Gathering required dependencies from imports", {
5487
6443
  imports: outputMeta.imports
@@ -5500,7 +6456,7 @@ async function gatherRequiredDependencies2(outputMeta, config) {
5500
6456
  }
5501
6457
  }
5502
6458
  if (config.additionalPackages) {
5503
- const projectPackageJson = await readJSONFile(join6(config.projectDir, "package.json"));
6459
+ const projectPackageJson = await readJSONFile(join7(config.projectDir, "package.json"));
5504
6460
  for (const packageName of config.additionalPackages) {
5505
6461
  if (dependencies2[packageName]) {
5506
6462
  continue;
@@ -5570,7 +6526,7 @@ async function amendNodePathWithPnpmNodeModules(nodePath) {
5570
6526
  async function findPnpmNodeModulesPath() {
5571
6527
  return await findUp3(
5572
6528
  async (directory) => {
5573
- const pnpmModules = join6(directory, "node_modules", ".pnpm", "node_modules");
6529
+ const pnpmModules = join7(directory, "node_modules", ".pnpm", "node_modules");
5574
6530
  const hasPnpmNodeModules = await pathExists2(pnpmModules);
5575
6531
  if (hasPnpmNodeModules) {
5576
6532
  return pnpmModules;
@@ -5579,20 +6535,38 @@ async function findPnpmNodeModulesPath() {
5579
6535
  { type: "directory" }
5580
6536
  );
5581
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
+ }
5582
6558
 
5583
6559
  // src/commands/init.ts
5584
- import { intro as intro4, isCancel, log as log3, outro as outro4, select as select2, spinner as spinner5, 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";
5585
6561
  import { context as context3, trace as trace3 } from "@opentelemetry/api";
5586
- import {
5587
- flattenAttributes as flattenAttributes3,
5588
- recordSpanException as recordSpanException5
5589
- } from "@trigger.dev/core/v3";
5590
- 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";
5591
6565
  import { execa as execa3 } from "execa";
5592
- import { applyEdits, modify } from "jsonc-parser";
6566
+ import { applyEdits, modify, findNodeAtLocation, parseTree, getNodeValue } from "jsonc-parser";
5593
6567
  import { writeFile as writeFile3 } from "node:fs/promises";
5594
- import { join as join7, relative as relative4, resolve as resolve3 } from "node:path";
5595
- 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";
5596
6570
  import { z as z6 } from "zod";
5597
6571
 
5598
6572
  // src/utilities/createFileFromTemplate.ts
@@ -5667,7 +6641,7 @@ async function initCommand(dir, options) {
5667
6641
  }
5668
6642
  async function _initCommand(dir, options) {
5669
6643
  const span = trace3.getSpan(context3.active());
5670
- intro4("Initializing project");
6644
+ intro5("Initializing project");
5671
6645
  const authorization = await login({
5672
6646
  embedded: true,
5673
6647
  defaultApiUrl: options.apiUrl,
@@ -5691,7 +6665,7 @@ async function _initCommand(dir, options) {
5691
6665
  if (!options.overrideConfig) {
5692
6666
  try {
5693
6667
  const result = await readConfig(dir);
5694
- outro4(
6668
+ outro6(
5695
6669
  result.status === "file" ? `Project already initialized: Found config file at ${result.path}. Pass --override-config to override` : "Project already initialized"
5696
6670
  );
5697
6671
  return;
@@ -5705,58 +6679,59 @@ async function _initCommand(dir, options) {
5705
6679
  options.projectRef
5706
6680
  );
5707
6681
  span?.setAttributes({
5708
- ...flattenAttributes3(selectedProject, "cli.project")
6682
+ ...flattenAttributes4(selectedProject, "cli.project")
5709
6683
  });
5710
6684
  logger.debug("Selected project", selectedProject);
5711
- log3.step(`Configuring project "${selectedProject.name}" (${selectedProject.externalRef})`);
6685
+ log6.step(`Configuring project "${selectedProject.name}" (${selectedProject.externalRef})`);
5712
6686
  if (!options.skipPackageInstall) {
5713
6687
  await installPackages2(dir, options);
5714
6688
  } else {
5715
- log3.info("Skipping package installation");
6689
+ log6.info("Skipping package installation");
5716
6690
  }
5717
6691
  const triggerDir = await createTriggerDir(dir, options);
5718
6692
  await writeConfigFile(dir, selectedProject, options, triggerDir);
5719
6693
  await addConfigFileToTsConfig(dir, options);
5720
6694
  await gitIgnoreDotTriggerDir(dir, options);
5721
- const projectDashboard = terminalLink3(
6695
+ const projectDashboard = terminalLink4(
5722
6696
  "project dashboard",
5723
6697
  `${authorization.dashboardUrl}/projects/v3/${selectedProject.externalRef}`
5724
6698
  );
5725
- log3.success("Successfully initialized project for Trigger.dev v3 \u{1FAE1}");
5726
- log3.info("Next steps:");
5727
- log3.info(
5728
- ` 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(
5729
6703
  `npx trigger.dev@${options.tag} dev`
5730
6704
  )} in your project directory`
5731
6705
  );
5732
- log3.info(` 2. Visit your ${projectDashboard} to view your newly created tasks.`);
5733
- log3.info(
5734
- ` 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(
5735
6709
  "v3 docs",
5736
6710
  "https://trigger.dev/docs/v3"
5737
6711
  )} to learn more.`
5738
6712
  );
5739
- log3.info(
5740
- ` 4. Need help? Join our ${terminalLink3(
6713
+ log6.info(
6714
+ ` 4. Need help? Join our ${terminalLink4(
5741
6715
  "Discord community",
5742
6716
  "https://trigger.dev/discord"
5743
- )} or email us at ${chalk6.cyan("help@trigger.dev")}`
6717
+ )} or email us at ${chalk5.cyan("help@trigger.dev")}`
5744
6718
  );
5745
- outro4(`Project initialized successfully. Happy coding!`);
6719
+ outro6(`Project initialized successfully. Happy coding!`);
5746
6720
  }
5747
6721
  async function createTriggerDir(dir, options) {
5748
6722
  return await tracer.startActiveSpan("createTriggerDir", async (span) => {
5749
6723
  try {
5750
- const defaultValue = `${dir}/src/trigger`;
6724
+ const defaultValue = join8(dir, "src", "trigger");
5751
6725
  const location = await text({
5752
6726
  message: "Where would you like to create the Trigger.dev directory?",
5753
6727
  defaultValue,
5754
6728
  placeholder: defaultValue
5755
6729
  });
5756
- if (isCancel(location)) {
6730
+ if (isCancel2(location)) {
5757
6731
  throw new OutroCommandError();
5758
6732
  }
5759
- const triggerDir = resolve3(process.cwd(), location);
6733
+ const triggerDir = resolve5(process.cwd(), location);
6734
+ logger.debug({ triggerDir });
5760
6735
  span.setAttributes({
5761
6736
  "cli.triggerDir": triggerDir
5762
6737
  });
@@ -5774,7 +6749,7 @@ async function createTriggerDir(dir, options) {
5774
6749
  }
5775
6750
  ]
5776
6751
  });
5777
- if (isCancel(exampleSelection)) {
6752
+ if (isCancel2(exampleSelection)) {
5778
6753
  throw new OutroCommandError();
5779
6754
  }
5780
6755
  const example = exampleSelection;
@@ -5782,25 +6757,25 @@ async function createTriggerDir(dir, options) {
5782
6757
  "cli.example": example
5783
6758
  });
5784
6759
  if (example === "none") {
5785
- await createFile(join7(triggerDir, ".gitkeep"), "");
5786
- log3.step(`Created directory at ${location}`);
6760
+ await createFile(join8(triggerDir, ".gitkeep"), "");
6761
+ log6.step(`Created directory at ${location}`);
5787
6762
  span.end();
5788
6763
  return { location, isCustomValue: location !== defaultValue };
5789
6764
  }
5790
- const templatePath = join7(cliRootPath(), "templates", "examples", `${example}.ts.template`);
5791
- const outputPath = join7(triggerDir, "example.ts");
6765
+ const templatePath = join8(cliRootPath(), "templates", "examples", `${example}.ts.template`);
6766
+ const outputPath = join8(triggerDir, "example.ts");
5792
6767
  await createFileFromTemplate({
5793
6768
  templatePath,
5794
6769
  outputPath,
5795
6770
  replacements: {}
5796
6771
  });
5797
6772
  const relativeOutputPath = relative4(process.cwd(), outputPath);
5798
- log3.step(`Created example file at ${relativeOutputPath}`);
6773
+ log6.step(`Created example file at ${relativeOutputPath}`);
5799
6774
  span.end();
5800
6775
  return { location, isCustomValue: location !== defaultValue };
5801
6776
  } catch (e) {
5802
6777
  if (!(e instanceof SkipCommandError)) {
5803
- recordSpanException5(span, e);
6778
+ recordSpanException6(span, e);
5804
6779
  }
5805
6780
  span.end();
5806
6781
  throw e;
@@ -5810,15 +6785,15 @@ async function createTriggerDir(dir, options) {
5810
6785
  async function gitIgnoreDotTriggerDir(dir, options) {
5811
6786
  return await tracer.startActiveSpan("gitIgnoreDotTriggerDir", async (span) => {
5812
6787
  try {
5813
- const projectDir = resolve3(process.cwd(), dir);
5814
- const gitIgnorePath = join7(projectDir, ".gitignore");
6788
+ const projectDir = resolve5(process.cwd(), dir);
6789
+ const gitIgnorePath = join8(projectDir, ".gitignore");
5815
6790
  span.setAttributes({
5816
6791
  "cli.projectDir": projectDir,
5817
6792
  "cli.gitIgnorePath": gitIgnorePath
5818
6793
  });
5819
6794
  if (!await pathExists(gitIgnorePath)) {
5820
6795
  await createFile(gitIgnorePath, ".trigger");
5821
- log3.step(`Added .trigger to .gitignore`);
6796
+ log6.step(`Added .trigger to .gitignore`);
5822
6797
  span.end();
5823
6798
  return;
5824
6799
  }
@@ -5830,11 +6805,11 @@ async function gitIgnoreDotTriggerDir(dir, options) {
5830
6805
  const newGitIgnoreContent = `${gitIgnoreContent}
5831
6806
  .trigger`;
5832
6807
  await writeFile3(gitIgnorePath, newGitIgnoreContent, "utf-8");
5833
- log3.step(`Added .trigger to .gitignore`);
6808
+ log6.step(`Added .trigger to .gitignore`);
5834
6809
  span.end();
5835
6810
  } catch (e) {
5836
6811
  if (!(e instanceof SkipCommandError)) {
5837
- recordSpanException5(span, e);
6812
+ recordSpanException6(span, e);
5838
6813
  }
5839
6814
  span.end();
5840
6815
  throw e;
@@ -5844,14 +6819,30 @@ async function gitIgnoreDotTriggerDir(dir, options) {
5844
6819
  async function addConfigFileToTsConfig(dir, options) {
5845
6820
  return await tracer.startActiveSpan("createTriggerDir", async (span) => {
5846
6821
  try {
5847
- const projectDir = resolve3(process.cwd(), dir);
5848
- const tsconfigPath = join7(projectDir, "tsconfig.json");
6822
+ const projectDir = resolve5(process.cwd(), dir);
6823
+ const tsconfigPath = join8(projectDir, "tsconfig.json");
5849
6824
  span.setAttributes({
5850
6825
  "cli.projectDir": projectDir,
5851
6826
  "cli.tsconfigPath": tsconfigPath
5852
6827
  });
5853
6828
  const tsconfigContent = await readFile(tsconfigPath);
5854
- 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, {
5855
6846
  isArrayInsertion: true,
5856
6847
  formattingOptions: {
5857
6848
  tabSize: 2,
@@ -5863,11 +6854,11 @@ async function addConfigFileToTsConfig(dir, options) {
5863
6854
  const newTsconfigContent = applyEdits(tsconfigContent, edits);
5864
6855
  logger.debug("new tsconfig.json content", { newTsconfigContent });
5865
6856
  await writeFile3(tsconfigPath, newTsconfigContent, "utf-8");
5866
- log3.step(`Added trigger.config.ts to tsconfig.json`);
6857
+ log6.step(`Added trigger.config.ts to tsconfig.json`);
5867
6858
  span.end();
5868
6859
  } catch (e) {
5869
6860
  if (!(e instanceof SkipCommandError)) {
5870
- recordSpanException5(span, e);
6861
+ recordSpanException6(span, e);
5871
6862
  }
5872
6863
  span.end();
5873
6864
  throw e;
@@ -5876,9 +6867,9 @@ async function addConfigFileToTsConfig(dir, options) {
5876
6867
  }
5877
6868
  async function installPackages2(dir, options) {
5878
6869
  return await tracer.startActiveSpan("installPackages", async (span) => {
5879
- const installSpinner = spinner5();
6870
+ const installSpinner = spinner();
5880
6871
  try {
5881
- const projectDir = resolve3(process.cwd(), dir);
6872
+ const projectDir = resolve5(process.cwd(), dir);
5882
6873
  const pkgManager = await getUserPackageManager(projectDir);
5883
6874
  span.setAttributes({
5884
6875
  "cli.projectDir": projectDir,
@@ -5918,7 +6909,7 @@ async function installPackages2(dir, options) {
5918
6909
  `Failed to install @trigger.dev/sdk@${options.tag}. Rerun command with --log-level debug for more details.`
5919
6910
  );
5920
6911
  if (!(e instanceof SkipCommandError)) {
5921
- recordSpanException5(span, e);
6912
+ recordSpanException6(span, e);
5922
6913
  }
5923
6914
  span.end();
5924
6915
  throw e;
@@ -5928,11 +6919,11 @@ async function installPackages2(dir, options) {
5928
6919
  async function writeConfigFile(dir, project, options, triggerDir) {
5929
6920
  return await tracer.startActiveSpan("writeConfigFile", async (span) => {
5930
6921
  try {
5931
- const spnnr = spinner5();
6922
+ const spnnr = spinner();
5932
6923
  spnnr.start("Creating config file");
5933
- const projectDir = resolve3(process.cwd(), dir);
5934
- const templatePath = join7(cliRootPath(), "templates", "trigger.config.ts.template");
5935
- 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");
5936
6927
  span.setAttributes({
5937
6928
  "cli.projectDir": projectDir,
5938
6929
  "cli.templatePath": templatePath,
@@ -5959,7 +6950,7 @@ async function writeConfigFile(dir, project, options, triggerDir) {
5959
6950
  return result.success;
5960
6951
  } catch (e) {
5961
6952
  if (!(e instanceof SkipCommandError)) {
5962
- recordSpanException5(span, e);
6953
+ recordSpanException6(span, e);
5963
6954
  }
5964
6955
  span.end();
5965
6956
  throw e;
@@ -5972,13 +6963,13 @@ async function selectProject(apiClient2, dashboardUrl, projectRef) {
5972
6963
  if (projectRef) {
5973
6964
  const projectResponse = await apiClient2.getProject(projectRef);
5974
6965
  if (!projectResponse.success) {
5975
- log3.error(
6966
+ log6.error(
5976
6967
  `--project-ref ${projectRef} is not a valid project ref. Request to fetch data resulted in: ${projectResponse.error}`
5977
6968
  );
5978
6969
  throw new SkipCommandError(projectResponse.error);
5979
6970
  }
5980
6971
  span.setAttributes({
5981
- ...flattenAttributes3(projectResponse.data, "cli.project")
6972
+ ...flattenAttributes4(projectResponse.data, "cli.project")
5982
6973
  });
5983
6974
  span.end();
5984
6975
  return projectResponse.data;
@@ -5988,11 +6979,11 @@ async function selectProject(apiClient2, dashboardUrl, projectRef) {
5988
6979
  throw new Error(`Failed to get projects: ${projectsResponse.error}`);
5989
6980
  }
5990
6981
  if (projectsResponse.data.length === 0) {
5991
- const newProjectLink = terminalLink3(
6982
+ const newProjectLink = terminalLink4(
5992
6983
  "Create new project",
5993
6984
  `${dashboardUrl}/projects/new?version=v3`
5994
6985
  );
5995
- outro4(`You don't have any projects yet. ${newProjectLink}`);
6986
+ outro6(`You don't have any projects yet. ${newProjectLink}`);
5996
6987
  throw new SkipCommandError();
5997
6988
  }
5998
6989
  const selectedProject = await select2({
@@ -6003,7 +6994,7 @@ async function selectProject(apiClient2, dashboardUrl, projectRef) {
6003
6994
  hint: project.organization.title
6004
6995
  }))
6005
6996
  });
6006
- if (isCancel(selectedProject)) {
6997
+ if (isCancel2(selectedProject)) {
6007
6998
  throw new OutroCommandError();
6008
6999
  }
6009
7000
  const projectData = projectsResponse.data.find(
@@ -6013,13 +7004,13 @@ async function selectProject(apiClient2, dashboardUrl, projectRef) {
6013
7004
  throw new Error("Invalid project ref");
6014
7005
  }
6015
7006
  span.setAttributes({
6016
- ...flattenAttributes3(projectData, "cli.project")
7007
+ ...flattenAttributes4(projectData, "cli.project")
6017
7008
  });
6018
7009
  span.end();
6019
7010
  return projectData;
6020
7011
  } catch (e) {
6021
7012
  if (!(e instanceof SkipCommandError)) {
6022
- recordSpanException5(span, e);
7013
+ recordSpanException6(span, e);
6023
7014
  }
6024
7015
  span.end();
6025
7016
  throw e;
@@ -6055,7 +7046,7 @@ async function logout(options) {
6055
7046
  }
6056
7047
 
6057
7048
  // src/commands/list-profiles.ts
6058
- import { log as log4, outro as outro5 } from "@clack/prompts";
7049
+ import { log as log7, outro as outro7 } from "@clack/prompts";
6059
7050
  var ListProfilesOptions = CommonCommandOptions;
6060
7051
  function configureListProfilesCommand(program2) {
6061
7052
  return program2.command("list-profiles").description("List all of your CLI profiles").option(
@@ -6081,12 +7072,12 @@ async function listProfiles(options) {
6081
7072
  return;
6082
7073
  }
6083
7074
  const profiles = Object.keys(authConfig);
6084
- log4.message("Profiles:");
7075
+ log7.message("Profiles:");
6085
7076
  for (const profile of profiles) {
6086
7077
  const profileConfig = authConfig[profile];
6087
- log4.info(`${profile}${profileConfig?.apiUrl ? ` - ${chalkGrey(profileConfig.apiUrl)}` : ""}`);
7078
+ log7.info(`${profile}${profileConfig?.apiUrl ? ` - ${chalkGrey(profileConfig.apiUrl)}` : ""}`);
6088
7079
  }
6089
- outro5("Retrieve account info by running whoami --profile <profile>");
7080
+ outro7("Retrieve account info by running whoami --profile <profile>");
6090
7081
  }
6091
7082
 
6092
7083
  // src/cli/index.ts
@@ -6099,6 +7090,7 @@ configureDeployCommand(program);
6099
7090
  configureWhoamiCommand(program);
6100
7091
  configureLogoutCommand(program);
6101
7092
  configureListProfilesCommand(program);
7093
+ configureUpdateCommand(program);
6102
7094
 
6103
7095
  // src/index.ts
6104
7096
  var main = async () => {