trigger.dev 3.0.0-beta.3 → 3.0.0-beta.30

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
@@ -57,7 +57,7 @@ var require_XDGAppPaths = __commonJS({
57
57
  return typeof t;
58
58
  }
59
59
  function Adapt(adapter_) {
60
- var meta = adapter_.meta, path6 = adapter_.path, xdg = adapter_.xdg;
60
+ var meta = adapter_.meta, path7 = adapter_.path, xdg = adapter_.xdg;
61
61
  var XDGAppPaths_ = /* @__PURE__ */ function() {
62
62
  function XDGAppPaths_2(options_) {
63
63
  if (options_ === void 0) {
@@ -79,7 +79,7 @@ var require_XDGAppPaths = __commonJS({
79
79
  meta.mainFilename()
80
80
  ];
81
81
  var nameFallback = "$eval";
82
- var name = path6.parse(((_c = namePriorityList.find(function(e) {
82
+ var name = path7.parse(((_c = namePriorityList.find(function(e) {
83
83
  return isString(e);
84
84
  })) !== null && _c !== void 0 ? _c : nameFallback) + suffix).name;
85
85
  XDGAppPaths.$name = function $name() {
@@ -98,28 +98,28 @@ var require_XDGAppPaths = __commonJS({
98
98
  return isIsolated(dirOptions) ? name : "";
99
99
  }
100
100
  XDGAppPaths.cache = function cache(dirOptions) {
101
- return path6.join(xdg.cache(), finalPathSegment(dirOptions));
101
+ return path7.join(xdg.cache(), finalPathSegment(dirOptions));
102
102
  };
103
103
  XDGAppPaths.config = function config(dirOptions) {
104
- return path6.join(xdg.config(), finalPathSegment(dirOptions));
104
+ return path7.join(xdg.config(), finalPathSegment(dirOptions));
105
105
  };
106
106
  XDGAppPaths.data = function data(dirOptions) {
107
- return path6.join(xdg.data(), finalPathSegment(dirOptions));
107
+ return path7.join(xdg.data(), finalPathSegment(dirOptions));
108
108
  };
109
109
  XDGAppPaths.runtime = function runtime(dirOptions) {
110
- return xdg.runtime() ? path6.join(xdg.runtime(), finalPathSegment(dirOptions)) : void 0;
110
+ return xdg.runtime() ? path7.join(xdg.runtime(), finalPathSegment(dirOptions)) : void 0;
111
111
  };
112
112
  XDGAppPaths.state = function state(dirOptions) {
113
- return path6.join(xdg.state(), finalPathSegment(dirOptions));
113
+ return path7.join(xdg.state(), finalPathSegment(dirOptions));
114
114
  };
115
115
  XDGAppPaths.configDirs = function configDirs(dirOptions) {
116
116
  return xdg.configDirs().map(function(s) {
117
- return path6.join(s, finalPathSegment(dirOptions));
117
+ return path7.join(s, finalPathSegment(dirOptions));
118
118
  });
119
119
  };
120
120
  XDGAppPaths.dataDirs = function dataDirs(dirOptions) {
121
121
  return xdg.dataDirs().map(function(s) {
122
- return path6.join(s, finalPathSegment(dirOptions));
122
+ return path7.join(s, finalPathSegment(dirOptions));
123
123
  });
124
124
  };
125
125
  return XDGAppPaths;
@@ -144,14 +144,14 @@ var require_XDG = __commonJS({
144
144
  exports.__esModule = true;
145
145
  exports.Adapt = void 0;
146
146
  function Adapt(adapter_) {
147
- var env = adapter_.env, osPaths = adapter_.osPaths, path6 = adapter_.path;
147
+ var env = adapter_.env, osPaths = adapter_.osPaths, path7 = adapter_.path;
148
148
  var isMacOS = /^darwin$/i.test(adapter_.process.platform);
149
149
  var isWinOS = /^win/i.test(adapter_.process.platform);
150
150
  function baseDir() {
151
151
  return osPaths.home() || osPaths.temp();
152
152
  }
153
153
  function valOrPath(val, pathSegments) {
154
- return val || path6.join.apply(path6, pathSegments);
154
+ return val || path7.join.apply(path7, pathSegments);
155
155
  }
156
156
  var linux = function() {
157
157
  var cache = function() {
@@ -226,11 +226,11 @@ var require_XDG = __commonJS({
226
226
  XDG.state = extension.state;
227
227
  XDG.configDirs = function configDirs() {
228
228
  var pathList = env.get("XDG_CONFIG_DIRS");
229
- return __spreadArray([extension.config()], pathList ? pathList.split(path6.delimiter) : []);
229
+ return __spreadArray([extension.config()], pathList ? pathList.split(path7.delimiter) : []);
230
230
  };
231
231
  XDG.dataDirs = function dataDirs() {
232
232
  var pathList = env.get("XDG_DATA_DIRS");
233
- return __spreadArray([extension.data()], pathList ? pathList.split(path6.delimiter) : []);
233
+ return __spreadArray([extension.data()], pathList ? pathList.split(path7.delimiter) : []);
234
234
  };
235
235
  return XDG;
236
236
  }
@@ -257,13 +257,13 @@ var require_OSPaths = __commonJS({
257
257
  return !s;
258
258
  }
259
259
  function Adapt(adapter_) {
260
- var env = adapter_.env, os2 = adapter_.os, path6 = adapter_.path;
260
+ var env = adapter_.env, os2 = adapter_.os, path7 = adapter_.path;
261
261
  var isWinOS = /^win/i.test(adapter_.process.platform);
262
262
  function normalizePath(path_) {
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() {
@@ -271,19 +271,19 @@ var require_OSPaths = __commonJS({
271
271
  typeof os2.homedir === "function" ? os2.homedir() : void 0,
272
272
  env.get("USERPROFILE"),
273
273
  env.get("HOME"),
274
- env.get("HOMEDRIVE") || env.get("HOMEPATH") ? path6.join(env.get("HOMEDRIVE") || "", env.get("HOMEPATH") || "") : void 0
274
+ env.get("HOMEDRIVE") || env.get("HOMEPATH") ? path7.join(env.get("HOMEDRIVE") || "", env.get("HOMEPATH") || "") : void 0
275
275
  ];
276
276
  return normalizePath(priorityList.find(function(v) {
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
- return base ? path6.join.apply(path6, __spreadArray([base], segments)) : void 0;
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() {
@@ -385,7 +385,7 @@ var require_node = __commonJS({
385
385
  exports.__esModule = true;
386
386
  exports.adapter = void 0;
387
387
  var os2 = __importStar(__require("os"));
388
- var path6 = __importStar(__require("path"));
388
+ var path7 = __importStar(__require("path"));
389
389
  exports.adapter = {
390
390
  atImportPermissions: { env: true },
391
391
  env: {
@@ -394,7 +394,7 @@ var require_node = __commonJS({
394
394
  }
395
395
  },
396
396
  os: os2,
397
- path: path6,
397
+ path: path7,
398
398
  process
399
399
  };
400
400
  }
@@ -447,7 +447,7 @@ var require_node2 = __commonJS({
447
447
  };
448
448
  exports.__esModule = true;
449
449
  exports.adapter = void 0;
450
- var path6 = __importStar(__require("path"));
450
+ var path7 = __importStar(__require("path"));
451
451
  var os_paths_1 = __importDefault(require_mod_cjs());
452
452
  exports.adapter = {
453
453
  atImportPermissions: { env: true },
@@ -457,7 +457,7 @@ var require_node2 = __commonJS({
457
457
  }
458
458
  },
459
459
  osPaths: os_paths_1["default"],
460
- path: path6,
460
+ path: path7,
461
461
  process
462
462
  };
463
463
  }
@@ -510,7 +510,7 @@ var require_node3 = __commonJS({
510
510
  };
511
511
  exports.__esModule = true;
512
512
  exports.adapter = void 0;
513
- var path6 = __importStar(__require("path"));
513
+ var path7 = __importStar(__require("path"));
514
514
  var xdg_portable_1 = __importDefault(require_mod_cjs2());
515
515
  exports.adapter = {
516
516
  atImportPermissions: { env: true, read: true },
@@ -525,7 +525,7 @@ var require_node3 = __commonJS({
525
525
  return process.pkg ? process.execPath : void 0;
526
526
  }
527
527
  },
528
- path: path6,
528
+ path: path7,
529
529
  process,
530
530
  xdg: xdg_portable_1["default"]
531
531
  };
@@ -777,31 +777,31 @@ var require_retry2 = __commonJS({
777
777
  import { Command as Command2 } from "commander";
778
778
 
779
779
  // src/commands/deploy.ts
780
- import { intro as intro3, log as 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
+ TaskMetadataFailedToParseData,
784
785
  detectDependencyVersion,
785
- flattenAttributes as flattenAttributes2,
786
- recordSpanException as recordSpanException4
786
+ flattenAttributes as flattenAttributes3
787
787
  } from "@trigger.dev/core/v3";
788
- import chalk4 from "chalk";
788
+ import { recordSpanException as recordSpanException5 } from "@trigger.dev/core/v3/workers";
789
789
  import { Option as CommandOption } from "commander";
790
790
  import { build as build2 } from "esbuild";
791
791
  import { execa as execa2 } from "execa";
792
- import { resolve as importResolve } from "import-meta-resolve";
793
792
  import { createHash } from "node:crypto";
794
793
  import { readFileSync as readFileSync2 } from "node:fs";
795
794
  import { copyFile, mkdir, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
796
- import { dirname, join as join4, relative as relative2 } from "node:path";
795
+ import { dirname, join as join6, posix, relative as relative3 } from "node:path";
797
796
  import { setTimeout as setTimeout2 } from "node:timers/promises";
798
- import terminalLink from "terminal-link";
797
+ import terminalLink2 from "terminal-link";
799
798
  import invariant from "tiny-invariant";
800
799
  import { z as z4 } from "zod";
801
800
 
802
801
  // package.json
803
- var version = "3.0.0-beta.3";
802
+ var version = "3.0.0-beta.30";
804
803
  var dependencies = {
804
+ "@anatine/esbuild-decorators": "^0.2.19",
805
805
  "@clack/prompts": "^0.7.0",
806
806
  "@depot/cli": "0.0.1-cli.2.55.0",
807
807
  "@opentelemetry/api": "^1.8.0",
@@ -816,7 +816,7 @@ var dependencies = {
816
816
  "@opentelemetry/sdk-trace-base": "^1.22.0",
817
817
  "@opentelemetry/sdk-trace-node": "^1.22.0",
818
818
  "@opentelemetry/semantic-conventions": "^1.22.0",
819
- "@trigger.dev/core": "workspace:^3.0.0-beta.2",
819
+ "@trigger.dev/core": "workspace:3.0.0-beta.30",
820
820
  "@types/degit": "^2.8.3",
821
821
  chalk: "^5.2.0",
822
822
  chokidar: "^3.5.3",
@@ -833,12 +833,10 @@ var dependencies = {
833
833
  "import-meta-resolve": "^4.0.0",
834
834
  ink: "^4.4.1",
835
835
  "jsonc-parser": "^3.2.1",
836
- jsonlines: "^0.1.1",
837
836
  liquidjs: "^10.9.2",
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",
@@ -850,7 +848,6 @@ var dependencies = {
850
848
  "simple-git": "^3.19.0",
851
849
  "socket.io-client": "^4.7.4",
852
850
  "source-map-support": "^0.5.21",
853
- "supports-color": "^9.4.0",
854
851
  "terminal-link": "^3.0.0",
855
852
  "tiny-invariant": "^1.2.0",
856
853
  "tsconfig-paths": "^4.2.0",
@@ -858,7 +855,8 @@ var dependencies = {
858
855
  url: "^0.11.1",
859
856
  ws: "^8.12.0",
860
857
  zod: "3.22.3",
861
- "zod-validation-error": "^1.5.0"
858
+ "zod-validation-error": "^1.5.0",
859
+ typescript: "^5.4.0"
862
860
  };
863
861
  var package_default = {
864
862
  name: "trigger.dev",
@@ -894,13 +892,12 @@ var package_default = {
894
892
  type: "module",
895
893
  exports: "./dist/index.js",
896
894
  bin: {
897
- "trigger.dev": "./dist/index.js"
895
+ triggerdev: "./dist/index.js"
898
896
  },
899
897
  devDependencies: {
900
898
  "@trigger.dev/core-apps": "workspace:*",
901
899
  "@trigger.dev/tsconfig": "workspace:*",
902
900
  "@types/gradient-string": "^1.1.2",
903
- "@types/jsonlines": "^0.1.5",
904
901
  "@types/mock-fs": "^4.13.1",
905
902
  "@types/node": "18",
906
903
  "@types/object-hash": "^3.0.6",
@@ -908,8 +905,8 @@ var package_default = {
908
905
  "@types/semver": "^7.3.13",
909
906
  "@types/ws": "^8.5.3",
910
907
  "cpy-cli": "^5.0.0",
908
+ nodemon: "^3.0.1",
911
909
  "npm-run-all": "^4.1.5",
912
- "npm-watch": "^0.11.0",
913
910
  open: "^10.0.3",
914
911
  "p-retry": "^6.1.0",
915
912
  rimraf: "^3.0.2",
@@ -919,9 +916,6 @@ var package_default = {
919
916
  vitest: "^0.34.4",
920
917
  "xdg-app-paths": "^8.3.0"
921
918
  },
922
- watch: {
923
- "build:prod-containerfile": "src/Containerfile.prod"
924
- },
925
919
  scripts: {
926
920
  typecheck: "tsc -p tsconfig.check.json",
927
921
  build: "npm run clean && run-p build:**",
@@ -931,7 +925,7 @@ var package_default = {
931
925
  dev: "npm run clean && run-p dev:**",
932
926
  "dev:main": "tsup --watch",
933
927
  "dev:workers": "tsup --config tsup.workers.config.ts --watch",
934
- "dev:prod-containerfile": "npm-watch",
928
+ "dev:test": "nodemon -w src/Containerfile.prod -x npm run build:prod-containerfile",
935
929
  clean: "rimraf dist",
936
930
  start: "node dist/index.js",
937
931
  test: "vitest"
@@ -1147,7 +1141,8 @@ async function zodfetch(schema, url, requestInit) {
1147
1141
  }
1148
1142
 
1149
1143
  // src/cli/common.ts
1150
- import { flattenAttributes, recordSpanException } from "@trigger.dev/core/v3";
1144
+ import { flattenAttributes } from "@trigger.dev/core/v3";
1145
+ import { recordSpanException } from "@trigger.dev/core/v3/workers";
1151
1146
  import { z } from "zod";
1152
1147
 
1153
1148
  // src/telemetry/tracing.ts
@@ -1157,6 +1152,10 @@ import { Resource, detectResourcesSync, processDetectorSync } from "@opentelemet
1157
1152
  import { NodeTracerProvider, SimpleSpanProcessor } from "@opentelemetry/sdk-trace-node";
1158
1153
  import { FetchInstrumentation } from "@opentelemetry/instrumentation-fetch";
1159
1154
  import { DiagConsoleLogger, DiagLogLevel, diag, trace } from "@opentelemetry/api";
1155
+ import {
1156
+ SEMRESATTRS_SERVICE_NAME,
1157
+ SEMRESATTRS_SERVICE_VERSION
1158
+ } from "@opentelemetry/semantic-conventions";
1160
1159
  function initializeTracing() {
1161
1160
  if (process.argv.includes("--skip-telemetry") || process.env.TRIGGER_DEV_SKIP_TELEMETRY) {
1162
1161
  return;
@@ -1168,7 +1167,8 @@ function initializeTracing() {
1168
1167
  detectors: [processDetectorSync]
1169
1168
  }).merge(
1170
1169
  new Resource({
1171
- service: "trigger.dev cli v3"
1170
+ [SEMRESATTRS_SERVICE_NAME]: "trigger.dev cli v3",
1171
+ [SEMRESATTRS_SERVICE_VERSION]: version
1172
1172
  })
1173
1173
  );
1174
1174
  const traceProvider = new NodeTracerProvider({
@@ -1185,10 +1185,9 @@ function initializeTracing() {
1185
1185
  });
1186
1186
  const spanExporter = new OTLPTraceExporter({
1187
1187
  url: "https://otel.baselime.io/v1",
1188
- timeoutMillis: 500,
1188
+ timeoutMillis: 5e3,
1189
1189
  headers: {
1190
- "x-api-key": "e9f963244f8b092850d42e34a5339b2d5e68070b".split("").reverse().join("")
1191
- // this is a joke
1190
+ "x-api-key": "b6e0fbbaf8dc2524773d2152ae2e9eb5c7fbaa52"
1192
1191
  }
1193
1192
  });
1194
1193
  const spanProcessor = new SimpleSpanProcessor(spanExporter);
@@ -1201,7 +1200,7 @@ function initializeTracing() {
1201
1200
  }
1202
1201
  var provider = initializeTracing();
1203
1202
  function getTracer() {
1204
- return trace.getTracer("trigger.dev cli", version);
1203
+ return trace.getTracer("trigger.dev cli v3", version);
1205
1204
  }
1206
1205
 
1207
1206
  // src/cli/common.ts
@@ -1307,7 +1306,7 @@ var Logger = class {
1307
1306
  const kind = LOGGER_LEVEL_FORMAT_TYPE_MAP[level];
1308
1307
  if (kind) {
1309
1308
  const [firstLine, ...otherLines] = message.split("\n");
1310
- const notes = otherLines.length > 0 ? otherLines.map((text2) => ({ text: text2 })) : void 0;
1309
+ const notes = otherLines.length > 0 ? otherLines.map((text3) => ({ text: text3 })) : void 0;
1311
1310
  return formatMessagesSync([{ text: firstLine, notes }], {
1312
1311
  color: true,
1313
1312
  kind,
@@ -1322,6 +1321,83 @@ var logger = new Logger();
1322
1321
 
1323
1322
  // src/cli/common.ts
1324
1323
  import { outro } from "@clack/prompts";
1324
+
1325
+ // src/utilities/cliOutput.ts
1326
+ import { log } from "@clack/prompts";
1327
+ import chalk2 from "chalk";
1328
+ var green = "#4FFF54";
1329
+ var purple = "#735BF3";
1330
+ function chalkGreen(text3) {
1331
+ return chalk2.hex(green)(text3);
1332
+ }
1333
+ function chalkPurple(text3) {
1334
+ return chalk2.hex(purple)(text3);
1335
+ }
1336
+ function chalkGrey(text3) {
1337
+ return chalk2.hex("#878C99")(text3);
1338
+ }
1339
+ function chalkError(text3) {
1340
+ return chalk2.hex("#E11D48")(text3);
1341
+ }
1342
+ function chalkWarning(text3) {
1343
+ return chalk2.yellow(text3);
1344
+ }
1345
+ function chalkSuccess(text3) {
1346
+ return chalk2.hex("#28BF5C")(text3);
1347
+ }
1348
+ function chalkLink(text3) {
1349
+ return chalk2.underline.hex("#D7D9DD")(text3);
1350
+ }
1351
+ function chalkWorker(text3) {
1352
+ return chalk2.hex("#FFFF89")(text3);
1353
+ }
1354
+ function chalkTask(text3) {
1355
+ return chalk2.hex("#60A5FA")(text3);
1356
+ }
1357
+ function chalkRun(text3) {
1358
+ return chalk2.hex("#A78BFA")(text3);
1359
+ }
1360
+ function logo() {
1361
+ return `${chalk2.hex(green).bold("Trigger")}${chalk2.hex(purple).bold(".dev")}`;
1362
+ }
1363
+ function prettyPrintDate(date = /* @__PURE__ */ new Date()) {
1364
+ let formattedDate = new Intl.DateTimeFormat("en-US", {
1365
+ month: "short",
1366
+ day: "2-digit",
1367
+ hour: "2-digit",
1368
+ minute: "2-digit",
1369
+ second: "2-digit",
1370
+ hour12: false
1371
+ }).format(date);
1372
+ formattedDate += "." + ("00" + date.getMilliseconds()).slice(-3);
1373
+ return formattedDate;
1374
+ }
1375
+ function prettyError(header, body, footer) {
1376
+ const prefix = "Error: ";
1377
+ const indent = Array(prefix.length).fill(" ").join("");
1378
+ const spacing = "\n\n";
1379
+ const prettyPrefix = chalkError(prefix);
1380
+ const withIndents = (text3) => text3?.split("\n").map((line) => `${indent}${line}`).join("\n");
1381
+ const prettyBody = withIndents(body);
1382
+ const prettyFooter = withIndents(footer);
1383
+ log.error(
1384
+ `${prettyPrefix}${header}${prettyBody ? `${spacing}${prettyBody}` : ""}${prettyFooter ? `${spacing}${prettyFooter}` : ""}`
1385
+ );
1386
+ }
1387
+ function prettyWarning(header, body, footer) {
1388
+ const prefix = "Warning: ";
1389
+ const indent = Array(prefix.length).fill(" ").join("");
1390
+ const spacing = "\n\n";
1391
+ const prettyPrefix = chalkWarning(prefix);
1392
+ const withIndents = (text3) => text3?.split("\n").map((line) => `${indent}${line}`).join("\n");
1393
+ const prettyBody = withIndents(body);
1394
+ const prettyFooter = withIndents(footer);
1395
+ log.warn(
1396
+ `${prettyPrefix}${header}${prettyBody ? `${spacing}${prettyBody}` : ""}${prettyFooter ? `${spacing}${prettyFooter}` : ""}`
1397
+ );
1398
+ }
1399
+
1400
+ // src/cli/common.ts
1325
1401
  var CommonCommandOptions = z.object({
1326
1402
  apiUrl: z.string().optional(),
1327
1403
  logLevel: z.enum(["debug", "info", "log", "warn", "error", "none"]).default("log"),
@@ -1331,7 +1407,7 @@ var CommonCommandOptions = z.object({
1331
1407
  function commonOptions(command) {
1332
1408
  return command.option("--profile <profile>", "The login profile to use", "default").option("-a, --api-url <value>", "Override the API URL", "https://api.trigger.dev").option(
1333
1409
  "-l, --log-level <level>",
1334
- "The log level to use (debug, info, log, warn, error, none)",
1410
+ "The CLI log level to use (debug, info, log, warn, error, none). This does not effect the log level of your trigger.dev tasks.",
1335
1411
  "log"
1336
1412
  ).option("--skip-telemetry", "Opt-out of sending telemetry");
1337
1413
  }
@@ -1377,7 +1453,7 @@ async function wrapCommandAction(name, schema, options, action) {
1377
1453
  } else if (e instanceof SkipCommandError) {
1378
1454
  } else {
1379
1455
  recordSpanException(span, e);
1380
- logger.error(e instanceof Error ? e.message : String(e));
1456
+ logger.log(`${chalkError("X Error:")} ${e instanceof Error ? e.message : String(e)}`);
1381
1457
  }
1382
1458
  span.end();
1383
1459
  throw e;
@@ -1420,31 +1496,34 @@ import fsModule, { writeFile } from "fs/promises";
1420
1496
  import fs from "node:fs";
1421
1497
  import { tmpdir } from "node:os";
1422
1498
  import pathModule from "node:path";
1423
- async function createFile(path6, contents) {
1424
- await fsModule.mkdir(pathModule.dirname(path6), { recursive: true });
1425
- await fsModule.writeFile(path6, contents);
1426
- return path6;
1499
+ async function createFile(path7, contents) {
1500
+ await fsModule.mkdir(pathModule.dirname(path7), { recursive: true });
1501
+ await fsModule.writeFile(path7, contents);
1502
+ return path7;
1427
1503
  }
1428
- async function pathExists(path6) {
1429
- return fsSync.existsSync(path6);
1504
+ async function pathExists(path7) {
1505
+ return fsSync.existsSync(path7);
1430
1506
  }
1431
- async function readFile(path6) {
1432
- return await fsModule.readFile(path6, "utf8");
1507
+ async function removeFile(path7) {
1508
+ await fsModule.unlink(path7);
1433
1509
  }
1434
- async function readJSONFile(path6) {
1435
- const fileContents = await fsModule.readFile(path6, "utf8");
1510
+ async function readFile(path7) {
1511
+ return await fsModule.readFile(path7, "utf8");
1512
+ }
1513
+ async function readJSONFile(path7) {
1514
+ const fileContents = await fsModule.readFile(path7, "utf8");
1436
1515
  return JSON.parse(fileContents);
1437
1516
  }
1438
- async function writeJSONFile(path6, json) {
1439
- await writeFile(path6, JSON.stringify(json), "utf8");
1517
+ async function writeJSONFile(path7, json, pretty = false) {
1518
+ await writeFile(path7, JSON.stringify(json, void 0, pretty ? 2 : void 0), "utf8");
1440
1519
  }
1441
- function readJSONFileSync(path6) {
1442
- const fileContents = fsSync.readFileSync(path6, "utf8");
1520
+ function readJSONFileSync(path7) {
1521
+ const fileContents = fsSync.readFileSync(path7, "utf8");
1443
1522
  return JSON.parse(fileContents);
1444
1523
  }
1445
- function safeDeleteFileSync(path6) {
1524
+ function safeDeleteFileSync(path7) {
1446
1525
  try {
1447
- fs.unlinkSync(path6);
1526
+ fs.unlinkSync(path7);
1448
1527
  } catch (error) {
1449
1528
  }
1450
1529
  }
@@ -1467,16 +1546,26 @@ function createTaskFileImports(taskFiles) {
1467
1546
  async function gatherTaskFiles(config) {
1468
1547
  const taskFiles = [];
1469
1548
  for (const triggerDir of config.triggerDirectories) {
1470
- const files = await fs2.promises.readdir(triggerDir, { withFileTypes: true });
1471
- for (const file of files) {
1472
- if (!file.isFile())
1473
- continue;
1474
- if (!file.name.endsWith(".js") && !file.name.endsWith(".ts"))
1549
+ const files = await gatherTaskFilesFromDir(triggerDir, triggerDir, config);
1550
+ taskFiles.push(...files);
1551
+ }
1552
+ return taskFiles;
1553
+ }
1554
+ async function gatherTaskFilesFromDir(dirPath, triggerDir, config) {
1555
+ const taskFiles = [];
1556
+ const files = await fs2.promises.readdir(dirPath, { withFileTypes: true });
1557
+ for (const file of files) {
1558
+ if (!file.isFile()) {
1559
+ const fullPath = join(dirPath, file.name);
1560
+ taskFiles.push(...await gatherTaskFilesFromDir(fullPath, triggerDir, config));
1561
+ } else {
1562
+ if (!file.name.endsWith(".js") && !file.name.endsWith(".ts") && !file.name.endsWith(".jsx") && !file.name.endsWith(".tsx")) {
1475
1563
  continue;
1476
- const fullPath = join(triggerDir, file.name);
1564
+ }
1565
+ const fullPath = join(dirPath, file.name);
1477
1566
  const filePath = relative(config.projectDir, fullPath);
1478
- const importPath = filePath.replace(/\.(js|ts)$/, "");
1479
- const importName = importPath.replace(/\//g, "_").replace(/\./g, "_").replace(/-/g, "_");
1567
+ const importName = filePath.replace(/\..+$/, "").replace(/[^a-zA-Z0-9_$]/g, "_");
1568
+ const importPath = filePath.replace(/\\/g, "/");
1480
1569
  taskFiles.push({ triggerDir, importPath, importName, filePath });
1481
1570
  }
1482
1571
  }
@@ -1493,9 +1582,12 @@ async function getTriggerDirectories(dirPath) {
1493
1582
  const entries = await fs2.promises.readdir(dirPath, { withFileTypes: true });
1494
1583
  const triggerDirectories = [];
1495
1584
  for (const entry of entries) {
1496
- if (!entry.isDirectory() || IGNORED_DIRS.includes(entry.name))
1585
+ if (!entry.isDirectory() || IGNORED_DIRS.includes(entry.name) || entry.name.startsWith("."))
1497
1586
  continue;
1498
1587
  const fullPath = join(dirPath, entry.name);
1588
+ if (fullPath.endsWith("app/api/trigger")) {
1589
+ continue;
1590
+ }
1499
1591
  if (entry.name === "trigger") {
1500
1592
  triggerDirectories.push(fullPath);
1501
1593
  }
@@ -1506,6 +1598,7 @@ async function getTriggerDirectories(dirPath) {
1506
1598
 
1507
1599
  // src/utilities/configFiles.ts
1508
1600
  import { build } from "esbuild";
1601
+ import { esbuildDecorators } from "@anatine/esbuild-decorators";
1509
1602
  function getGlobalConfigFolderPath() {
1510
1603
  const configDir = mod_esm_default("trigger").config();
1511
1604
  return configDir;
@@ -1535,6 +1628,11 @@ function readAuthConfigProfile(profile = "default") {
1535
1628
  return void 0;
1536
1629
  }
1537
1630
  }
1631
+ function deleteAuthConfigProfile(profile = "default") {
1632
+ const existingConfig = readAuthConfigFile() || {};
1633
+ delete existingConfig[profile];
1634
+ writeAuthConfigFile(existingConfig);
1635
+ }
1538
1636
  function readAuthConfigFile() {
1539
1637
  try {
1540
1638
  const authConfigFilePath = getAuthConfigFilePath();
@@ -1564,16 +1662,25 @@ async function getConfigPath(dir, fileName) {
1564
1662
  });
1565
1663
  return await findUp(fileName ? [fileName] : CONFIG_FILES, { cwd: dir });
1566
1664
  }
1665
+ async function findFilePath(dir, fileName) {
1666
+ const result = await findUp([fileName], { cwd: dir });
1667
+ logger.debug("Searched for the file", {
1668
+ dir,
1669
+ fileName,
1670
+ result
1671
+ });
1672
+ return result;
1673
+ }
1567
1674
  async function readConfig(dir, options) {
1568
1675
  const absoluteDir = path2.resolve(process.cwd(), dir);
1569
1676
  const configPath = await getConfigPath(dir, options?.configFile);
1570
1677
  if (!configPath) {
1571
1678
  if (options?.projectRef) {
1572
- const rawConfig2 = await normalizeConfig({ project: options.projectRef });
1573
- const config2 = Config.parse(rawConfig2);
1679
+ const rawConfig = await normalizeConfig({ project: options.projectRef });
1680
+ const config = Config.parse(rawConfig);
1574
1681
  return {
1575
1682
  status: "in-memory",
1576
- config: await resolveConfig(absoluteDir, config2)
1683
+ config: await resolveConfig(absoluteDir, config)
1577
1684
  };
1578
1685
  } else {
1579
1686
  throw new Error(`Config file not found in ${absoluteDir} or any parent directory.`);
@@ -1597,92 +1704,64 @@ async function readConfig(dir, options) {
1597
1704
  platform: "node",
1598
1705
  target: ["es2018", "node18"],
1599
1706
  outfile: builtConfigFilePath,
1600
- logLevel: "silent"
1707
+ logLevel: "silent",
1708
+ plugins: [
1709
+ esbuildDecorators({
1710
+ cwd: absoluteDir,
1711
+ tsx: false,
1712
+ force: false
1713
+ })
1714
+ ]
1601
1715
  });
1602
- const userConfigModule = await import(builtConfigFileHref);
1603
- const rawConfig = await normalizeConfig(
1604
- userConfigModule ? userConfigModule.config : { project: options?.projectRef }
1605
- );
1606
- const config = Config.parse(rawConfig);
1607
- return {
1608
- status: "file",
1609
- config: await resolveConfig(absoluteDir, config),
1610
- path: configPath
1611
- };
1716
+ try {
1717
+ const userConfigModule = await import(builtConfigFileHref);
1718
+ const rawConfig = await normalizeConfig(
1719
+ userConfigModule?.config,
1720
+ options?.projectRef ? { project: options?.projectRef } : void 0
1721
+ );
1722
+ const config = Config.parse(rawConfig);
1723
+ return {
1724
+ status: "file",
1725
+ config: await resolveConfig(absoluteDir, config),
1726
+ path: configPath
1727
+ };
1728
+ } catch (error) {
1729
+ return {
1730
+ status: "error",
1731
+ error
1732
+ };
1733
+ }
1612
1734
  }
1613
- async function resolveConfig(path6, config) {
1735
+ async function resolveConfig(path7, config) {
1614
1736
  if (!config.triggerDirectories) {
1615
- config.triggerDirectories = await findTriggerDirectories(path6);
1737
+ config.triggerDirectories = await findTriggerDirectories(path7);
1616
1738
  }
1617
1739
  config.triggerDirectories = resolveTriggerDirectories(config.triggerDirectories);
1740
+ logger.debug("Resolved trigger directories", { triggerDirectories: config.triggerDirectories });
1618
1741
  if (!config.triggerUrl) {
1619
1742
  config.triggerUrl = CLOUD_API_URL;
1620
1743
  }
1621
1744
  if (!config.projectDir) {
1622
- config.projectDir = path6;
1745
+ config.projectDir = path7;
1623
1746
  }
1624
1747
  if (!config.tsconfigPath) {
1625
- config.tsconfigPath = await getConfigPath(path6, "tsconfig.json");
1748
+ config.tsconfigPath = await findFilePath(path7, "tsconfig.json");
1626
1749
  }
1627
1750
  return config;
1628
1751
  }
1629
- async function normalizeConfig(config) {
1752
+ async function normalizeConfig(config, overrides) {
1753
+ let normalized = config;
1630
1754
  if (typeof config === "function") {
1631
- config = config();
1755
+ normalized = await config();
1632
1756
  }
1633
- return await config;
1757
+ normalized = { ...normalized, ...overrides };
1758
+ return normalized;
1634
1759
  }
1635
1760
 
1636
1761
  // src/utilities/initialBanner.ts
1637
- import { spinner } from "@clack/prompts";
1638
1762
  import chalk3 from "chalk";
1639
- import supportsColor from "supports-color";
1640
1763
  import checkForUpdate from "update-check";
1641
1764
 
1642
- // src/utilities/cliOutput.ts
1643
- import chalk2 from "chalk";
1644
- var green = "#4FFF54";
1645
- var purple = "#735BF3";
1646
- function chalkGrey(text2) {
1647
- return chalk2.hex("#878C99")(text2);
1648
- }
1649
- function chalkError(text2) {
1650
- return chalk2.hex("#E11D48")(text2);
1651
- }
1652
- function chalkWarning(text2) {
1653
- return chalk2.yellow(text2);
1654
- }
1655
- function chalkSuccess(text2) {
1656
- return chalk2.hex("#28BF5C")(text2);
1657
- }
1658
- function chalkLink(text2) {
1659
- return chalk2.underline.hex("#D7D9DD")(text2);
1660
- }
1661
- function chalkWorker(text2) {
1662
- return chalk2.hex("#FFFF89")(text2);
1663
- }
1664
- function chalkTask(text2) {
1665
- return chalk2.hex("#60A5FA")(text2);
1666
- }
1667
- function chalkRun(text2) {
1668
- return chalk2.hex("#A78BFA")(text2);
1669
- }
1670
- function logo() {
1671
- return `${chalk2.hex(green).bold("Trigger")}${chalk2.hex(purple).bold(".dev")}`;
1672
- }
1673
- function prettyPrintDate(date = /* @__PURE__ */ new Date()) {
1674
- let formattedDate = new Intl.DateTimeFormat("en-US", {
1675
- month: "short",
1676
- day: "2-digit",
1677
- hour: "2-digit",
1678
- minute: "2-digit",
1679
- second: "2-digit",
1680
- hour12: false
1681
- }).format(date);
1682
- formattedDate += "." + ("00" + date.getMilliseconds()).slice(-3);
1683
- return formattedDate;
1684
- }
1685
-
1686
1765
  // src/utilities/getVersion.ts
1687
1766
  import path3 from "path";
1688
1767
  function getVersion() {
@@ -1691,13 +1770,32 @@ function getVersion() {
1691
1770
  return packageJsonContent.version ?? "1.0.0";
1692
1771
  }
1693
1772
 
1773
+ // src/utilities/windows.ts
1774
+ import { log as log2, spinner as clackSpinner } from "@clack/prompts";
1775
+ var isWindows = process.platform === "win32";
1776
+ function escapeImportPath(path7) {
1777
+ return isWindows ? path7.replaceAll("\\", "\\\\") : path7;
1778
+ }
1779
+ var ballmerSpinner = () => ({
1780
+ start: (msg) => {
1781
+ log2.step(msg ?? "");
1782
+ },
1783
+ stop: (msg, code) => {
1784
+ log2.message(msg ?? "");
1785
+ },
1786
+ message: (msg) => {
1787
+ log2.message(msg ?? "");
1788
+ }
1789
+ });
1790
+ var spinner = () => isWindows ? ballmerSpinner() : clackSpinner();
1791
+
1694
1792
  // src/utilities/initialBanner.ts
1695
1793
  async function printInitialBanner(performUpdateCheck = true) {
1696
- const packageVersion = getVersion();
1697
- const text2 = `
1698
- ${logo()} ${chalkGrey(`(${packageVersion})`)}
1794
+ const cliVersion = getVersion();
1795
+ const text3 = `
1796
+ ${logo()} ${chalkGrey(`(${cliVersion})`)}
1699
1797
  `;
1700
- logger.info(text2);
1798
+ logger.info(text3);
1701
1799
  let maybeNewVersion;
1702
1800
  if (performUpdateCheck) {
1703
1801
  const loadingSpinner = spinner();
@@ -1705,7 +1803,7 @@ ${logo()} ${chalkGrey(`(${packageVersion})`)}
1705
1803
  maybeNewVersion = await updateCheck();
1706
1804
  if (maybeNewVersion !== void 0) {
1707
1805
  loadingSpinner.stop(`Update available ${chalk3.green(maybeNewVersion)}`);
1708
- const currentMajor = parseInt(packageVersion.split(".")[0]);
1806
+ const currentMajor = parseInt(cliVersion.split(".")[0]);
1709
1807
  const newMajor = parseInt(maybeNewVersion.split(".")[0]);
1710
1808
  if (newMajor > currentMajor) {
1711
1809
  logger.warn(
@@ -1720,18 +1818,26 @@ After installation, run Trigger.dev with \`npx trigger.dev\`.`
1720
1818
  }
1721
1819
  }
1722
1820
  async function printStandloneInitialBanner(performUpdateCheck = true) {
1723
- const packageVersion = getVersion();
1724
- let text2 = `
1725
- ${logo()} ${chalkGrey("(v3 Developer Preview)")}`;
1821
+ const cliVersion = getVersion();
1726
1822
  if (performUpdateCheck) {
1727
1823
  const maybeNewVersion = await updateCheck();
1728
1824
  if (maybeNewVersion !== void 0) {
1729
- text2 = `${text2} (update available ${chalk3.green(maybeNewVersion)})`;
1825
+ logger.log(`
1826
+ ${logo()} ${chalkGrey(`(${cliVersion} -> ${chalk3.green(maybeNewVersion)})`)}`);
1827
+ } else {
1828
+ logger.log(`
1829
+ ${logo()} ${chalkGrey(`(${cliVersion})`)}`);
1730
1830
  }
1831
+ } else {
1832
+ logger.log(`
1833
+ ${logo()} ${chalkGrey(`(${cliVersion})`)}`);
1731
1834
  }
1732
- logger.log(text2 + "\n" + (supportsColor.stdout ? chalkGrey("-".repeat(54)) : "-".repeat(54)));
1835
+ logger.log(`${chalkGrey("-".repeat(54))}`);
1733
1836
  }
1734
- function printDevBanner() {
1837
+ function printDevBanner(printTopBorder = true) {
1838
+ if (printTopBorder) {
1839
+ logger.log(chalkGrey("-".repeat(54)));
1840
+ }
1735
1841
  logger.log(
1736
1842
  `${chalkGrey("Key:")} ${chalkWorker("Version")} ${chalkGrey("|")} ${chalkTask(
1737
1843
  "Task"
@@ -1743,7 +1849,7 @@ async function doUpdateCheck() {
1743
1849
  let update = null;
1744
1850
  try {
1745
1851
  update = await checkForUpdate(package_default, {
1746
- distTag: package_default.version.startsWith("0.0.0") ? "beta" : "latest"
1852
+ distTag: package_default.version.startsWith("3.0.0-beta") ? "beta" : "latest"
1747
1853
  });
1748
1854
  } catch (err) {
1749
1855
  }
@@ -1761,26 +1867,20 @@ async function installPackages(packages, options) {
1761
1867
  const cwd = options?.cwd ?? process.cwd();
1762
1868
  logger.debug("Installing packages", { packages });
1763
1869
  await setPackageJsonDeps(join3(cwd, "package.json"), packages);
1764
- const childProcess2 = execa(
1870
+ await execa(
1765
1871
  "npm",
1766
1872
  ["install", "--install-strategy", "nested", "--ignore-scripts", "--no-audit", "--no-fund"],
1767
1873
  {
1768
1874
  cwd,
1769
- stderr: "inherit"
1875
+ stderr: "pipe"
1770
1876
  }
1771
1877
  );
1772
- await new Promise((res, rej) => {
1773
- childProcess2.on("error", (e) => rej(e));
1774
- childProcess2.on("close", () => res());
1775
- });
1776
- await childProcess2;
1777
- return;
1778
1878
  }
1779
- function detectPackageNameFromImportPath(path6) {
1780
- if (path6.startsWith("@")) {
1781
- return path6.split("/").slice(0, 2).join("/");
1879
+ function detectPackageNameFromImportPath(path7) {
1880
+ if (path7.startsWith("@")) {
1881
+ return path7.split("/").slice(0, 2).join("/");
1782
1882
  } else {
1783
- return path6.split("/")[0];
1883
+ return path7.split("/")[0];
1784
1884
  }
1785
1885
  }
1786
1886
  function stripWorkspaceFromVersion(version2) {
@@ -1796,16 +1896,16 @@ function parsePackageName(packageSpecifier) {
1796
1896
  }
1797
1897
  return { name: packageSpecifier };
1798
1898
  }
1799
- async function setPackageJsonDeps(path6, deps) {
1899
+ async function setPackageJsonDeps(path7, deps) {
1800
1900
  try {
1801
- const existingPackageJson = await readJSONFile(path6);
1901
+ const existingPackageJson = await readJSONFile(path7);
1802
1902
  const newPackageJson = {
1803
1903
  ...existingPackageJson,
1804
1904
  dependencies: {
1805
1905
  ...deps
1806
1906
  }
1807
1907
  };
1808
- await writeJSONFile(path6, newPackageJson);
1908
+ await writeJSONFile(path7, newPackageJson);
1809
1909
  } catch (error) {
1810
1910
  const defaultPackageJson = {
1811
1911
  name: "temp",
@@ -1813,13 +1913,13 @@ async function setPackageJsonDeps(path6, deps) {
1813
1913
  description: "",
1814
1914
  dependencies: deps
1815
1915
  };
1816
- await writeJSONFile(path6, defaultPackageJson);
1916
+ await writeJSONFile(path7, defaultPackageJson);
1817
1917
  }
1818
1918
  }
1819
1919
 
1820
1920
  // src/commands/login.ts
1821
- import { intro as intro2, log, outro as outro2, select, spinner as spinner3 } from "@clack/prompts";
1822
- import { recordSpanException as recordSpanException3 } from "@trigger.dev/core/v3";
1921
+ import { intro as intro2, log as log3, outro as outro3, select } from "@clack/prompts";
1922
+ import { recordSpanException as recordSpanException3 } from "@trigger.dev/core/v3/workers";
1823
1923
 
1824
1924
  // ../../node_modules/.pnpm/open@10.0.3/node_modules/open/index.js
1825
1925
  import process6 from "node:process";
@@ -2189,14 +2289,14 @@ var baseOpen = async (options) => {
2189
2289
  }
2190
2290
  const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
2191
2291
  if (options.wait) {
2192
- return new Promise((resolve4, reject) => {
2292
+ return new Promise((resolve5, reject) => {
2193
2293
  subprocess.once("error", reject);
2194
2294
  subprocess.once("close", (exitCode) => {
2195
2295
  if (!options.allowNonzeroExitCode && exitCode > 0) {
2196
2296
  reject(new Error(`Exited with code ${exitCode}`));
2197
2297
  return;
2198
2298
  }
2199
- resolve4(subprocess);
2299
+ resolve5(subprocess);
2200
2300
  });
2201
2301
  });
2202
2302
  }
@@ -2313,7 +2413,7 @@ var decorateErrorWithCounts = (error, attemptNumber, options) => {
2313
2413
  return error;
2314
2414
  };
2315
2415
  async function pRetry(input, options) {
2316
- return new Promise((resolve4, reject) => {
2416
+ return new Promise((resolve5, reject) => {
2317
2417
  options = {
2318
2418
  onFailedAttempt() {
2319
2419
  },
@@ -2336,7 +2436,7 @@ async function pRetry(input, options) {
2336
2436
  try {
2337
2437
  const result = await input(attemptNumber);
2338
2438
  cleanUp();
2339
- resolve4(result);
2439
+ resolve5(result);
2340
2440
  } catch (error) {
2341
2441
  try {
2342
2442
  if (!(error instanceof Error)) {
@@ -2366,10 +2466,10 @@ async function pRetry(input, options) {
2366
2466
  import { z as z3 } from "zod";
2367
2467
 
2368
2468
  // src/commands/whoami.ts
2369
- import { intro, note, spinner as spinner2 } from "@clack/prompts";
2469
+ import { intro, note, outro as outro2 } from "@clack/prompts";
2370
2470
 
2371
2471
  // src/utilities/session.ts
2372
- import { recordSpanException as recordSpanException2 } from "@trigger.dev/core/v3";
2472
+ import { recordSpanException as recordSpanException2 } from "@trigger.dev/core/v3/workers";
2373
2473
  var tracer2 = getTracer();
2374
2474
  async function isLoggedIn(profile = "default") {
2375
2475
  return await tracer2.startActiveSpan("isLoggedIn", async (span) => {
@@ -2444,16 +2544,23 @@ async function whoAmI(options, embedded = false) {
2444
2544
  if (!embedded) {
2445
2545
  intro(`Displaying your account details [${options?.profile ?? "default"}]`);
2446
2546
  }
2447
- const loadingSpinner = spinner2();
2547
+ const loadingSpinner = spinner();
2448
2548
  loadingSpinner.start("Checking your account details");
2449
2549
  const authentication = await isLoggedIn(options?.profile);
2450
2550
  if (!authentication.ok) {
2451
2551
  if (authentication.error === "fetch failed") {
2452
2552
  loadingSpinner.stop("Fetch failed. Platform down?");
2453
2553
  } else {
2454
- loadingSpinner.stop(
2455
- `You must login first. Use \`trigger.dev login --profile ${options?.profile ?? "default"}\` to login.`
2456
- );
2554
+ if (embedded) {
2555
+ loadingSpinner.stop(
2556
+ `Failed to check account details. You may want to run \`trigger.dev logout --profile ${options?.profile ?? "default"}\` and try again.`
2557
+ );
2558
+ } else {
2559
+ loadingSpinner.stop(
2560
+ `You must login first. Use \`trigger.dev login --profile ${options?.profile ?? "default"}\` to login.`
2561
+ );
2562
+ outro2("Whoami failed");
2563
+ }
2457
2564
  }
2458
2565
  return {
2459
2566
  success: false,
@@ -2518,6 +2625,29 @@ async function login(options) {
2518
2625
  if (!opts.embedded) {
2519
2626
  intro2("Logging in to Trigger.dev");
2520
2627
  }
2628
+ const accessTokenFromEnv = process.env.TRIGGER_ACCESS_TOKEN;
2629
+ if (accessTokenFromEnv) {
2630
+ const auth = {
2631
+ accessToken: accessTokenFromEnv,
2632
+ apiUrl: process.env.TRIGGER_API_URL ?? "https://api.trigger.dev"
2633
+ };
2634
+ const apiClient3 = new CliApiClient(auth.apiUrl, auth.accessToken);
2635
+ const userData = await apiClient3.whoAmI();
2636
+ if (!userData.success) {
2637
+ throw new Error(userData.error);
2638
+ }
2639
+ return {
2640
+ ok: true,
2641
+ profile: options?.profile ?? "default",
2642
+ userId: userData.data.userId,
2643
+ email: userData.data.email,
2644
+ dashboardUrl: userData.data.dashboardUrl,
2645
+ auth: {
2646
+ accessToken: auth.accessToken,
2647
+ apiUrl: auth.apiUrl
2648
+ }
2649
+ };
2650
+ }
2521
2651
  const authConfig = readAuthConfigProfile(options?.profile);
2522
2652
  if (authConfig && authConfig.accessToken) {
2523
2653
  const whoAmIResult = await whoAmI(
@@ -2526,10 +2656,18 @@ async function login(options) {
2526
2656
  skipTelemetry: !span.isRecording(),
2527
2657
  logLevel: logger.loggerLevel
2528
2658
  },
2529
- opts.embedded
2659
+ true
2530
2660
  );
2531
2661
  if (!whoAmIResult.success) {
2532
- throw new Error(whoAmIResult.error);
2662
+ prettyError("Unable to validate existing personal access token", whoAmIResult.error);
2663
+ if (!opts.embedded) {
2664
+ outro3(
2665
+ `Login failed using stored token. To fix, first logout using \`trigger.dev logout${options?.profile ? ` --profile ${options.profile}` : ""}\` and then try again.`
2666
+ );
2667
+ throw new SkipLoggingError(whoAmIResult.error);
2668
+ } else {
2669
+ throw new Error(whoAmIResult.error);
2670
+ }
2533
2671
  } else {
2534
2672
  if (!opts.embedded) {
2535
2673
  const continueOption = await select({
@@ -2547,7 +2685,7 @@ async function login(options) {
2547
2685
  initialValue: false
2548
2686
  });
2549
2687
  if (continueOption !== true) {
2550
- outro2("Already logged in");
2688
+ outro3("Already logged in");
2551
2689
  span.setAttributes({
2552
2690
  "cli.userId": whoAmIResult.data.userId,
2553
2691
  "cli.email": whoAmIResult.data.email,
@@ -2588,16 +2726,16 @@ async function login(options) {
2588
2726
  }
2589
2727
  }
2590
2728
  if (opts.embedded) {
2591
- log.step("You must login to continue.");
2729
+ log3.step("You must login to continue.");
2592
2730
  }
2593
2731
  const apiClient2 = new CliApiClient(authConfig?.apiUrl ?? opts.defaultApiUrl);
2594
2732
  const authorizationCodeResult = await createAuthorizationCode(apiClient2);
2595
- log.step(
2733
+ log3.step(
2596
2734
  `Please visit the following URL to login:
2597
2735
  ${chalkLink(authorizationCodeResult.url)}`
2598
2736
  );
2599
2737
  await open_default(authorizationCodeResult.url);
2600
- const getPersonalAccessTokenSpinner = spinner3();
2738
+ const getPersonalAccessTokenSpinner = spinner();
2601
2739
  getPersonalAccessTokenSpinner.start("Waiting for you to login");
2602
2740
  try {
2603
2741
  const indexResult = await pRetry(
@@ -2626,9 +2764,9 @@ ${chalkLink(authorizationCodeResult.url)}`
2626
2764
  throw new Error(whoAmIResult.error);
2627
2765
  }
2628
2766
  if (opts.embedded) {
2629
- log.step("Logged in successfully");
2767
+ log3.step("Logged in successfully");
2630
2768
  } else {
2631
- outro2("Logged in successfully");
2769
+ outro3("Logged in successfully");
2632
2770
  }
2633
2771
  span.end();
2634
2772
  return {
@@ -2645,7 +2783,7 @@ ${chalkLink(authorizationCodeResult.url)}`
2645
2783
  } catch (e) {
2646
2784
  getPersonalAccessTokenSpinner.stop(`Failed to get access token`);
2647
2785
  if (e instanceof AbortError) {
2648
- log.error(e.message);
2786
+ log3.error(e.message);
2649
2787
  }
2650
2788
  recordSpanException3(span, e);
2651
2789
  span.end();
@@ -2694,7 +2832,7 @@ async function getPersonalAccessToken(apiClient2, authorizationCode) {
2694
2832
  async function createAuthorizationCode(apiClient2) {
2695
2833
  return await tracer.startActiveSpan("createAuthorizationCode", async (span) => {
2696
2834
  try {
2697
- const createAuthCodeSpinner = spinner3();
2835
+ const createAuthCodeSpinner = spinner();
2698
2836
  createAuthCodeSpinner.start("Creating authorition code");
2699
2837
  const authorizationCodeResult = await apiClient2.createAuthorizationCode();
2700
2838
  if (!authorizationCodeResult.success) {
@@ -2718,10 +2856,69 @@ ${authorizationCodeResult.error}`
2718
2856
  });
2719
2857
  }
2720
2858
 
2859
+ // src/commands/deploy.ts
2860
+ import { esbuildDecorators as esbuildDecorators2 } from "@anatine/esbuild-decorators";
2861
+ import { Glob } from "glob";
2862
+
2721
2863
  // src/utilities/build.ts
2722
2864
  import { readFileSync } from "node:fs";
2723
2865
  import { extname, isAbsolute } from "node:path";
2724
2866
  import tsConfigPaths from "tsconfig-paths";
2867
+ function mockServerOnlyPlugin() {
2868
+ return {
2869
+ name: "trigger-mock-server-only",
2870
+ setup(build3) {
2871
+ build3.onResolve({ filter: /server-only/ }, (args) => {
2872
+ if (args.path !== "server-only") {
2873
+ return void 0;
2874
+ }
2875
+ logger.debug(`[trigger-mock-server-only] Bundling ${args.path}`, {
2876
+ ...args
2877
+ });
2878
+ return {
2879
+ path: args.path,
2880
+ external: false,
2881
+ namespace: "server-only-mock"
2882
+ };
2883
+ });
2884
+ build3.onLoad({ filter: /server-only/, namespace: "server-only-mock" }, (args) => {
2885
+ return {
2886
+ contents: `export default true;`,
2887
+ loader: "js"
2888
+ };
2889
+ });
2890
+ }
2891
+ };
2892
+ }
2893
+ function bundleTriggerDevCore(buildIdentifier, tsconfigPath) {
2894
+ return {
2895
+ name: "trigger-bundle-core",
2896
+ setup(build3) {
2897
+ build3.onResolve({ filter: /.*/ }, (args) => {
2898
+ if (!args.path.startsWith("@trigger.dev/core/v3")) {
2899
+ return void 0;
2900
+ }
2901
+ const triggerSdkPath = __require.resolve("@trigger.dev/sdk/v3", { paths: [process.cwd()] });
2902
+ logger.debug(`[${buildIdentifier}][trigger-bundle-core] Resolved @trigger.dev/sdk/v3`, {
2903
+ ...args,
2904
+ triggerSdkPath
2905
+ });
2906
+ const resolvedPath = __require.resolve(args.path, {
2907
+ paths: [triggerSdkPath]
2908
+ });
2909
+ logger.debug(`[${buildIdentifier}][trigger-bundle-core] Externalizing ${args.path}`, {
2910
+ ...args,
2911
+ triggerSdkPath,
2912
+ resolvedPath
2913
+ });
2914
+ return {
2915
+ path: resolvedPath,
2916
+ external: false
2917
+ };
2918
+ });
2919
+ }
2920
+ };
2921
+ }
2725
2922
  function workerSetupImportConfigPlugin(configPath) {
2726
2923
  return {
2727
2924
  name: "trigger-worker-setup",
@@ -2733,7 +2930,9 @@ function workerSetupImportConfigPlugin(configPath) {
2733
2930
  let workerSetupContents = readFileSync(args.path, "utf-8");
2734
2931
  workerSetupContents = workerSetupContents.replace(
2735
2932
  "__SETUP_IMPORTED_PROJECT_CONFIG__",
2736
- `import * as setupImportedConfigExports from "${configPath}"; const setupImportedConfig = setupImportedConfigExports.config;`
2933
+ `import * as setupImportedConfigExports from "${escapeImportPath(
2934
+ configPath
2935
+ )}"; const setupImportedConfig = setupImportedConfigExports.config;`
2737
2936
  );
2738
2937
  logger.debug("Loading worker setup", {
2739
2938
  args,
@@ -2780,7 +2979,7 @@ function bundleDependenciesPlugin(buildIdentifier, dependenciesToBundle, tsconfi
2780
2979
  return void 0;
2781
2980
  }
2782
2981
  }
2783
- logger.ignore(`[${buildIdentifier}] Externalizing ${args.path}`, {
2982
+ logger.debug(`[${buildIdentifier}] Externalizing ${args.path}`, {
2784
2983
  ...args
2785
2984
  });
2786
2985
  return {
@@ -2868,12 +3067,728 @@ function getLoaderForFile(file) {
2868
3067
  throw new Error(`Cannot get loader for file ${file}`);
2869
3068
  }
2870
3069
 
3070
+ // src/utilities/deployErrors.ts
3071
+ import chalk4 from "chalk";
3072
+ import { relative as relative2 } from "node:path";
3073
+ import { groupTaskMetadataIssuesByTask } from "@trigger.dev/core/v3";
3074
+ import terminalLink from "terminal-link";
3075
+
3076
+ // src/utilities/links.ts
3077
+ var docs = {
3078
+ config: {
3079
+ home: "https://trigger.dev/docs/v3/trigger-config",
3080
+ esm: "https://trigger.dev/docs/v3/trigger-config#esm-only-packages",
3081
+ prisma: "https://trigger.dev/docs/v3/trigger-config#prisma-and-other-generators",
3082
+ additionalPackages: "https://trigger.dev/docs/v3/trigger-config#prisma-and-other-generators"
3083
+ }
3084
+ };
3085
+ var getInTouch = "https://trigger.dev/contact";
3086
+
3087
+ // src/utilities/deployErrors.ts
3088
+ function errorIsErrorLike(error) {
3089
+ return error instanceof Error || typeof error === "object" && error !== null && "message" in error;
3090
+ }
3091
+ function parseBuildErrorStack(error) {
3092
+ if (typeof error === "string") {
3093
+ return error;
3094
+ }
3095
+ if (errorIsErrorLike(error)) {
3096
+ if (typeof error.stack === "string") {
3097
+ const isErrRequireEsm = error.stack.includes("ERR_REQUIRE_ESM");
3098
+ let moduleName = null;
3099
+ if (isErrRequireEsm) {
3100
+ const moduleRegex = /node_modules\/(@[^\/]+\/[^\/]+|[^\/]+)\/[^\/]+\s/;
3101
+ const match = moduleRegex.exec(error.stack);
3102
+ if (match) {
3103
+ moduleName = match[1];
3104
+ return {
3105
+ type: "esm-require-error",
3106
+ moduleName
3107
+ };
3108
+ }
3109
+ }
3110
+ } else {
3111
+ return error.message;
3112
+ }
3113
+ }
3114
+ }
3115
+ function logESMRequireError(parsedError, resolvedConfig) {
3116
+ logger.log(
3117
+ `
3118
+ ${chalkError("X Error:")} The ${chalkPurple(
3119
+ parsedError.moduleName
3120
+ )} module is being required even though it's ESM only, and builds only support CommonJS. There are two ${chalk4.underline(
3121
+ "possible"
3122
+ )} ways to fix this:`
3123
+ );
3124
+ logger.log(
3125
+ `
3126
+ ${chalkGrey("\u25CB")} Dynamically import the module in your code: ${chalkGrey(
3127
+ `const myModule = await import("${parsedError.moduleName}");`
3128
+ )}`
3129
+ );
3130
+ if (resolvedConfig.status === "file") {
3131
+ const relativePath = relative2(resolvedConfig.config.projectDir, resolvedConfig.path).replace(
3132
+ /\\/g,
3133
+ "/"
3134
+ );
3135
+ logger.log(
3136
+ `${chalkGrey("\u25CB")} ${chalk4.underline("Or")} add ${chalkPurple(
3137
+ parsedError.moduleName
3138
+ )} to the ${chalkGreen("dependenciesToBundle")} array in your config file ${chalkGrey(
3139
+ `(${relativePath})`
3140
+ )}. This will bundle the module with your code.
3141
+ `
3142
+ );
3143
+ } else {
3144
+ logger.log(
3145
+ `${chalkGrey("\u25CB")} ${chalk4.underline("Or")} add ${chalkPurple(
3146
+ parsedError.moduleName
3147
+ )} to the ${chalkGreen("dependenciesToBundle")} array in your config file ${chalkGrey(
3148
+ "(you'll need to create one)"
3149
+ )}. This will bundle the module with your code.
3150
+ `
3151
+ );
3152
+ }
3153
+ logger.log(
3154
+ `${chalkGrey("\u25CB")} For more info see the ${terminalLink("relevant docs", docs.config.esm)}.
3155
+ `
3156
+ );
3157
+ }
3158
+ function parseNpmInstallError(error) {
3159
+ if (typeof error === "string") {
3160
+ return error;
3161
+ }
3162
+ if (error instanceof Error) {
3163
+ if (typeof error.stack === "string") {
3164
+ const isPackageNotFoundError = error.stack.includes("ERR! 404 Not Found") && error.stack.includes("is not in this registry");
3165
+ let packageName = null;
3166
+ if (isPackageNotFoundError) {
3167
+ const packageNameRegex = /'([^']+)' is not in this registry/;
3168
+ const match = packageNameRegex.exec(error.stack);
3169
+ if (match) {
3170
+ packageName = match[1];
3171
+ }
3172
+ }
3173
+ if (packageName) {
3174
+ return {
3175
+ type: "package-not-found-error",
3176
+ packageName
3177
+ };
3178
+ }
3179
+ const noMatchingVersionRegex = /No matching version found for ([^\s]+)\s/;
3180
+ const noMatchingVersionMatch = noMatchingVersionRegex.exec(error.stack);
3181
+ if (noMatchingVersionMatch) {
3182
+ return {
3183
+ type: "no-matching-version-error",
3184
+ packageName: noMatchingVersionMatch[1].replace(/.$/, "")
3185
+ };
3186
+ }
3187
+ return error.message;
3188
+ } else {
3189
+ return error.message;
3190
+ }
3191
+ }
3192
+ return "Unknown error";
3193
+ }
3194
+ function logTaskMetadataParseError(zodIssues, tasks) {
3195
+ logger.log(
3196
+ `
3197
+ ${chalkError("X Error:")} Failed to start. The following ${zodIssues.length === 1 ? "task issue was" : "task issues were"} found:`
3198
+ );
3199
+ const groupedIssues = groupTaskMetadataIssuesByTask(tasks, zodIssues);
3200
+ for (const key in groupedIssues) {
3201
+ const taskWithIssues = groupedIssues[key];
3202
+ if (!taskWithIssues) {
3203
+ continue;
3204
+ }
3205
+ logger.log(
3206
+ `
3207
+ ${chalkWarning("\u276F")} ${taskWithIssues.exportName} ${chalkGrey("in")} ${taskWithIssues.filePath}`
3208
+ );
3209
+ for (const issue of taskWithIssues.issues) {
3210
+ if (issue.path) {
3211
+ logger.log(` ${chalkError("x")} ${issue.path} ${chalkGrey(issue.message)}`);
3212
+ } else {
3213
+ logger.log(` ${chalkError("x")} ${chalkGrey(issue.message)}`);
3214
+ }
3215
+ }
3216
+ }
3217
+ }
3218
+
3219
+ // src/utilities/javascriptProject.ts
3220
+ import { $ } from "execa";
3221
+ import { join as join4 } from "node:path";
3222
+
3223
+ // src/utilities/getUserPackageManager.ts
3224
+ import { findUp as findUp2 } from "find-up";
3225
+ import { basename } from "path";
3226
+ async function getUserPackageManager(path7) {
3227
+ const packageManager = await detectPackageManager(path7);
3228
+ logger.debug("Detected package manager", { packageManager });
3229
+ return packageManager;
3230
+ }
3231
+ async function detectPackageManager(path7) {
3232
+ try {
3233
+ return await detectPackageManagerFromArtifacts(path7);
3234
+ } catch (error) {
3235
+ return detectPackageManagerFromCurrentCommand();
3236
+ }
3237
+ }
3238
+ function detectPackageManagerFromCurrentCommand() {
3239
+ const userAgent = process.env.npm_config_user_agent;
3240
+ if (userAgent) {
3241
+ if (userAgent.startsWith("yarn")) {
3242
+ return "yarn";
3243
+ } else if (userAgent.startsWith("pnpm")) {
3244
+ return "pnpm";
3245
+ } else {
3246
+ return "npm";
3247
+ }
3248
+ } else {
3249
+ return "npm";
3250
+ }
3251
+ }
3252
+ async function detectPackageManagerFromArtifacts(path7) {
3253
+ const artifacts = {
3254
+ yarn: "yarn.lock",
3255
+ pnpm: "pnpm-lock.yaml",
3256
+ npm: "package-lock.json",
3257
+ npmShrinkwrap: "npm-shrinkwrap.json"
3258
+ };
3259
+ const foundPath = await findUp2(Object.values(artifacts), { cwd: path7 });
3260
+ if (!foundPath) {
3261
+ throw new Error("Could not detect package manager from artifacts");
3262
+ }
3263
+ logger.debug("Found path from package manager artifacts", { foundPath });
3264
+ switch (basename(foundPath)) {
3265
+ case artifacts.yarn:
3266
+ return "yarn";
3267
+ case artifacts.pnpm:
3268
+ return "pnpm";
3269
+ case artifacts.npm:
3270
+ case artifacts.npmShrinkwrap:
3271
+ return "npm";
3272
+ default:
3273
+ throw new Error(`Unhandled package manager detection path: ${foundPath}`);
3274
+ }
3275
+ }
3276
+
3277
+ // src/utilities/assertExhaustive.ts
3278
+ function assertExhaustive(x) {
3279
+ throw new Error("Unexpected object: " + x);
3280
+ }
3281
+
3282
+ // src/utilities/javascriptProject.ts
3283
+ import { builtinModules } from "node:module";
3284
+ import { recordSpanException as recordSpanException4 } from "@trigger.dev/core/v3/otel";
3285
+ import { flattenAttributes as flattenAttributes2 } from "@trigger.dev/core/v3";
3286
+ var JavascriptProject = class {
3287
+ constructor(projectPath) {
3288
+ this.projectPath = projectPath;
3289
+ }
3290
+ _packageJson;
3291
+ _packageManager;
3292
+ get packageJson() {
3293
+ if (!this._packageJson) {
3294
+ this._packageJson = readJSONFileSync(join4(this.projectPath, "package.json"));
3295
+ }
3296
+ return this._packageJson;
3297
+ }
3298
+ get scripts() {
3299
+ return {
3300
+ postinstall: this.packageJson.scripts?.postinstall ?? ""
3301
+ };
3302
+ }
3303
+ async install() {
3304
+ const command = await this.#getCommand();
3305
+ try {
3306
+ await command.installDependencies({
3307
+ cwd: this.projectPath
3308
+ });
3309
+ } catch (error) {
3310
+ logger.debug(`Failed to install dependencies using ${command.name}`, {
3311
+ error
3312
+ });
3313
+ }
3314
+ }
3315
+ async resolveAll(packageNames, options) {
3316
+ return tracer.startActiveSpan("JavascriptProject.resolveAll", async (span) => {
3317
+ const externalPackages = packageNames.filter((packageName) => !isBuiltInModule(packageName));
3318
+ const opts = { allowDev: false, ...options };
3319
+ const command = await this.#getCommand();
3320
+ span.setAttributes({
3321
+ externalPackages,
3322
+ packageManager: command.name
3323
+ });
3324
+ try {
3325
+ const versions = await command.resolveDependencyVersions(externalPackages, {
3326
+ cwd: this.projectPath
3327
+ });
3328
+ if (versions) {
3329
+ logger.debug(`Resolved [${externalPackages.join(", ")}] version using ${command.name}`, {
3330
+ versions
3331
+ });
3332
+ span.setAttributes({
3333
+ ...flattenAttributes2(versions, "versions")
3334
+ });
3335
+ }
3336
+ const missingPackages = externalPackages.filter((packageName) => !versions[packageName]);
3337
+ const missingPackageVersions = {};
3338
+ for (const packageName of missingPackages) {
3339
+ const packageJsonVersion = this.packageJson.dependencies?.[packageName];
3340
+ if (typeof packageJsonVersion === "string") {
3341
+ logger.debug(`Resolved ${packageName} version using package.json`, {
3342
+ packageJsonVersion
3343
+ });
3344
+ missingPackageVersions[packageName] = packageJsonVersion;
3345
+ }
3346
+ if (opts.allowDev) {
3347
+ const devPackageJsonVersion = this.packageJson.devDependencies?.[packageName];
3348
+ if (typeof devPackageJsonVersion === "string") {
3349
+ logger.debug(`Resolved ${packageName} version using devDependencies`, {
3350
+ devPackageJsonVersion
3351
+ });
3352
+ missingPackageVersions[packageName] = devPackageJsonVersion;
3353
+ }
3354
+ }
3355
+ }
3356
+ span.setAttributes({
3357
+ ...flattenAttributes2(missingPackageVersions, "missingPackageVersions"),
3358
+ missingPackages
3359
+ });
3360
+ span.end();
3361
+ return { ...versions, ...missingPackageVersions };
3362
+ } catch (error) {
3363
+ recordSpanException4(span, error);
3364
+ span.end();
3365
+ logger.debug(`Failed to resolve dependency versions using ${command.name}`, {
3366
+ packageNames,
3367
+ error
3368
+ });
3369
+ return {};
3370
+ }
3371
+ });
3372
+ }
3373
+ async resolve(packageName, options) {
3374
+ if (isBuiltInModule(packageName)) {
3375
+ return void 0;
3376
+ }
3377
+ const opts = { allowDev: false, ...options };
3378
+ const command = await this.#getCommand();
3379
+ try {
3380
+ const version2 = await command.resolveDependencyVersion(packageName, {
3381
+ cwd: this.projectPath
3382
+ });
3383
+ if (version2) {
3384
+ logger.debug(`Resolved ${packageName} version using ${command.name}`, { version: version2 });
3385
+ return version2;
3386
+ }
3387
+ const packageJsonVersion = this.packageJson.dependencies?.[packageName];
3388
+ if (typeof packageJsonVersion === "string") {
3389
+ logger.debug(`Resolved ${packageName} version using package.json`, { packageJsonVersion });
3390
+ return packageJsonVersion;
3391
+ }
3392
+ if (opts.allowDev) {
3393
+ const devPackageJsonVersion = this.packageJson.devDependencies?.[packageName];
3394
+ if (typeof devPackageJsonVersion === "string") {
3395
+ logger.debug(`Resolved ${packageName} version using devDependencies`, {
3396
+ devPackageJsonVersion
3397
+ });
3398
+ return devPackageJsonVersion;
3399
+ }
3400
+ }
3401
+ } catch (error) {
3402
+ logger.debug(`Failed to resolve dependency version using ${command.name}`, {
3403
+ packageName,
3404
+ error
3405
+ });
3406
+ }
3407
+ }
3408
+ async #getCommand() {
3409
+ const packageManager = await this.getPackageManager();
3410
+ switch (packageManager) {
3411
+ case "npm":
3412
+ return new NPMCommands();
3413
+ case "pnpm":
3414
+ return new PNPMCommands();
3415
+ case "yarn":
3416
+ return new YarnCommands();
3417
+ default:
3418
+ assertExhaustive(packageManager);
3419
+ }
3420
+ }
3421
+ async getPackageManager() {
3422
+ if (!this._packageManager) {
3423
+ this._packageManager = await getUserPackageManager(this.projectPath);
3424
+ }
3425
+ return this._packageManager;
3426
+ }
3427
+ };
3428
+ var PNPMCommands = class {
3429
+ get name() {
3430
+ return "pnpm";
3431
+ }
3432
+ get cmd() {
3433
+ return process.platform === "win32" ? "pnpm.cmd" : "pnpm";
3434
+ }
3435
+ async installDependencies(options) {
3436
+ const { stdout, stderr } = await $({ cwd: options.cwd })`${this.cmd} install`;
3437
+ logger.debug(`Installing dependencies using ${this.name}`, { stdout, stderr });
3438
+ }
3439
+ async resolveDependencyVersion(packageName, options) {
3440
+ const { stdout } = await $({ cwd: options.cwd })`${this.cmd} list ${packageName} -r --json`;
3441
+ const result = JSON.parse(stdout);
3442
+ logger.debug(`Resolving ${packageName} version using ${this.name}`);
3443
+ for (const dep of result) {
3444
+ const dependency = dep.dependencies?.[packageName];
3445
+ if (dependency) {
3446
+ return dependency.version;
3447
+ }
3448
+ }
3449
+ }
3450
+ async resolveDependencyVersions(packageNames, options) {
3451
+ const { stdout } = await $({ cwd: options.cwd })`${this.cmd} list ${packageNames} -r --json`;
3452
+ const result = JSON.parse(stdout);
3453
+ logger.debug(`Resolving ${packageNames.join(" ")} version using ${this.name}`);
3454
+ const results = {};
3455
+ for (const dep of result) {
3456
+ for (const packageName of packageNames) {
3457
+ const dependency = dep.dependencies?.[packageName];
3458
+ if (dependency) {
3459
+ results[packageName] = dependency.version;
3460
+ }
3461
+ }
3462
+ }
3463
+ return results;
3464
+ }
3465
+ };
3466
+ var NPMCommands = class {
3467
+ get name() {
3468
+ return "npm";
3469
+ }
3470
+ get cmd() {
3471
+ return process.platform === "win32" ? "npm.cmd" : "npm";
3472
+ }
3473
+ async installDependencies(options) {
3474
+ const { stdout, stderr } = await $({ cwd: options.cwd })`${this.cmd} install`;
3475
+ logger.debug(`Installing dependencies using ${this.name}`, { stdout, stderr });
3476
+ }
3477
+ async resolveDependencyVersion(packageName, options) {
3478
+ const { stdout } = await $({ cwd: options.cwd })`${this.cmd} list ${packageName} --json`;
3479
+ const output = JSON.parse(stdout);
3480
+ logger.debug(`Resolving ${packageName} version using ${this.name}`, { output });
3481
+ return this.#recursivelySearchDependencies(output.dependencies, packageName);
3482
+ }
3483
+ async resolveDependencyVersions(packageNames, options) {
3484
+ const { stdout } = await $({ cwd: options.cwd })`${this.cmd} list ${packageNames} --json`;
3485
+ const output = JSON.parse(stdout);
3486
+ logger.debug(`Resolving ${packageNames.join(" ")} version using ${this.name}`, { output });
3487
+ const results = {};
3488
+ for (const packageName of packageNames) {
3489
+ const version2 = this.#recursivelySearchDependencies(output.dependencies, packageName);
3490
+ if (version2) {
3491
+ results[packageName] = version2;
3492
+ }
3493
+ }
3494
+ return results;
3495
+ }
3496
+ #recursivelySearchDependencies(dependencies2, packageName) {
3497
+ for (const [name, dependency] of Object.entries(dependencies2)) {
3498
+ if (name === packageName) {
3499
+ return dependency.version;
3500
+ }
3501
+ if (dependency.dependencies) {
3502
+ const result = this.#recursivelySearchDependencies(dependency.dependencies, packageName);
3503
+ if (result) {
3504
+ return result;
3505
+ }
3506
+ }
3507
+ }
3508
+ }
3509
+ };
3510
+ var YarnCommands = class {
3511
+ get name() {
3512
+ return "yarn";
3513
+ }
3514
+ get cmd() {
3515
+ return process.platform === "win32" ? "yarn.cmd" : "yarn";
3516
+ }
3517
+ async installDependencies(options) {
3518
+ const { stdout, stderr } = await $({ cwd: options.cwd })`${this.cmd} install`;
3519
+ logger.debug(`Installing dependencies using ${this.name}`, { stdout, stderr });
3520
+ }
3521
+ async resolveDependencyVersion(packageName, options) {
3522
+ const { stdout } = await $({ cwd: options.cwd })`${this.cmd} info ${packageName} --json`;
3523
+ const lines = stdout.split("\n");
3524
+ logger.debug(`Resolving ${packageName} version using ${this.name}`);
3525
+ for (const line of lines) {
3526
+ const json = JSON.parse(line);
3527
+ if (json.value === packageName) {
3528
+ return json.children.Version;
3529
+ }
3530
+ }
3531
+ }
3532
+ async resolveDependencyVersions(packageNames, options) {
3533
+ const { stdout } = await $({ cwd: options.cwd })`${this.cmd} info ${packageNames} --json`;
3534
+ const lines = stdout.split("\n");
3535
+ logger.debug(`Resolving ${packageNames.join(" ")} version using ${this.name}`);
3536
+ const results = {};
3537
+ for (const line of lines) {
3538
+ const json = JSON.parse(line);
3539
+ const packageName = this.#parseYarnValueIntoPackageName(json.value);
3540
+ if (packageNames.includes(packageName)) {
3541
+ results[packageName] = json.children.Version;
3542
+ }
3543
+ }
3544
+ return results;
3545
+ }
3546
+ // The "value" when doing yarn info is formatted like this:
3547
+ // "package-name@npm:version" or "package-name@workspace:version"
3548
+ // This function will parse the value into just the package name.
3549
+ // This correctly handles scoped packages as well e.g. @scope/package-name@npm:version
3550
+ #parseYarnValueIntoPackageName(value) {
3551
+ const parts = value.split("@");
3552
+ if (parts.length === 3) {
3553
+ return parts[1];
3554
+ }
3555
+ return parts[0];
3556
+ }
3557
+ };
3558
+ function isBuiltInModule(module) {
3559
+ if (module.startsWith("node:")) {
3560
+ return true;
3561
+ }
3562
+ return builtinModules.includes(module);
3563
+ }
3564
+
3565
+ // src/utilities/resolveInternalFilePath.ts
3566
+ import path5 from "path";
3567
+ import { fileURLToPath as fileURLToPath3 } from "url";
3568
+ function cliRootPath() {
3569
+ const __filename2 = fileURLToPath3(import.meta.url);
3570
+ const __dirname2 = path5.dirname(__filename2);
3571
+ return __dirname2;
3572
+ }
3573
+
3574
+ // src/utilities/safeJsonParse.ts
3575
+ function safeJsonParse(json) {
3576
+ if (!json) {
3577
+ return void 0;
3578
+ }
3579
+ try {
3580
+ return JSON.parse(json);
3581
+ } catch {
3582
+ return void 0;
3583
+ }
3584
+ }
3585
+
3586
+ // src/commands/update.ts
3587
+ import { confirm, intro as intro3, isCancel, log as log4, outro as outro4 } from "@clack/prompts";
3588
+ import { join as join5, resolve as resolve2 } from "path";
3589
+ var UpdateCommandOptions = CommonCommandOptions.pick({
3590
+ logLevel: true,
3591
+ skipTelemetry: true
3592
+ });
3593
+ function configureUpdateCommand(program2) {
3594
+ 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(
3595
+ "-l, --log-level <level>",
3596
+ "The CLI log level to use (debug, info, log, warn, error, none). This does not effect the log level of your trigger.dev tasks.",
3597
+ "log"
3598
+ ).option("--skip-telemetry", "Opt-out of sending telemetry").action(async (path7, options) => {
3599
+ wrapCommandAction("dev", UpdateCommandOptions, options, async (opts) => {
3600
+ await printStandloneInitialBanner(true);
3601
+ await updateCommand(path7, opts);
3602
+ });
3603
+ });
3604
+ }
3605
+ var triggerPackageFilter = /^@trigger\.dev/;
3606
+ async function updateCommand(dir, options) {
3607
+ await updateTriggerPackages(dir, options);
3608
+ }
3609
+ async function updateTriggerPackages(dir, options, embedded, requireUpdate) {
3610
+ let hasOutput = false;
3611
+ if (!embedded) {
3612
+ intro3("Updating packages");
3613
+ }
3614
+ const projectPath = resolve2(process.cwd(), dir);
3615
+ const { packageJson, readonlyPackageJson, packageJsonPath } = await getPackageJson(projectPath);
3616
+ if (!packageJson) {
3617
+ log4.error("Failed to load package.json. Try to re-run with `-l debug` to see what's going on.");
3618
+ return false;
3619
+ }
3620
+ const cliVersion = getVersion();
3621
+ const newCliVersion = await updateCheck();
3622
+ if (newCliVersion) {
3623
+ prettyWarning(
3624
+ "You're not running the latest CLI version, please consider updating ASAP",
3625
+ `Current: ${cliVersion}
3626
+ Latest: ${newCliVersion}`,
3627
+ "Run latest: npx trigger.dev@beta"
3628
+ );
3629
+ hasOutput = true;
3630
+ }
3631
+ const triggerDependencies = getTriggerDependencies(packageJson);
3632
+ function getVersionMismatches(deps, targetVersion) {
3633
+ const mismatches = [];
3634
+ for (const dep of deps) {
3635
+ if (dep.version === targetVersion) {
3636
+ continue;
3637
+ }
3638
+ mismatches.push(dep);
3639
+ }
3640
+ return mismatches;
3641
+ }
3642
+ const versionMismatches = getVersionMismatches(triggerDependencies, cliVersion);
3643
+ if (versionMismatches.length === 0) {
3644
+ if (!embedded) {
3645
+ outro4(`Nothing to do${newCliVersion ? " ..but you should really update your CLI!" : ""}`);
3646
+ return hasOutput;
3647
+ }
3648
+ return hasOutput;
3649
+ }
3650
+ prettyWarning(
3651
+ "Mismatch between your CLI version and installed packages",
3652
+ "We recommend pinned versions for guaranteed compatibility"
3653
+ );
3654
+ if (!process.stdout.isTTY) {
3655
+ outro4("Deploy failed");
3656
+ console.log(
3657
+ `ERROR: Version mismatch detected while running in CI. This won't end well. Aborting.
3658
+
3659
+ 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.
3660
+
3661
+ 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\`
3662
+
3663
+ CLI version: ${cliVersion}
3664
+
3665
+ Current package versions that don't match the CLI:
3666
+ ${versionMismatches.map((dep) => `- ${dep.name}@${dep.version}`).join("\n")}
3667
+ `
3668
+ );
3669
+ process.exit(1);
3670
+ }
3671
+ log4.message("");
3672
+ const userWantsToUpdate = await updateConfirmation(versionMismatches, cliVersion);
3673
+ if (isCancel(userWantsToUpdate)) {
3674
+ throw new OutroCommandError();
3675
+ }
3676
+ if (!userWantsToUpdate) {
3677
+ if (requireUpdate) {
3678
+ outro4("You shall not pass!");
3679
+ logger.log(
3680
+ `${chalkError(
3681
+ "X Error:"
3682
+ )} Update required: Version mismatches are a common source of bugs and errors. Please update or use \`--skip-update-check\` at your own risk.
3683
+ `
3684
+ );
3685
+ process.exit(1);
3686
+ }
3687
+ if (!embedded) {
3688
+ outro4("You've been warned!");
3689
+ }
3690
+ return hasOutput;
3691
+ }
3692
+ const installSpinner = spinner();
3693
+ installSpinner.start("Writing new package.json file");
3694
+ const packageJsonBackupPath = `${packageJsonPath}.bak`;
3695
+ await writeJSONFile(packageJsonBackupPath, readonlyPackageJson, true);
3696
+ const exitHandler = async (sig) => {
3697
+ log4.warn(
3698
+ `You may have to manually roll back any package.json changes. Backup written to ${packageJsonBackupPath}`
3699
+ );
3700
+ };
3701
+ process.prependOnceListener("exit", exitHandler);
3702
+ mutatePackageJsonWithUpdatedPackages(packageJson, versionMismatches, cliVersion);
3703
+ await writeJSONFile(packageJsonPath, packageJson, true);
3704
+ async function revertPackageJsonChanges() {
3705
+ await writeJSONFile(packageJsonPath, readonlyPackageJson, true);
3706
+ await removeFile(packageJsonBackupPath);
3707
+ }
3708
+ installSpinner.message("Installing new package versions");
3709
+ const jsProject = new JavascriptProject(projectPath);
3710
+ let packageManager;
3711
+ try {
3712
+ packageManager = await jsProject.getPackageManager();
3713
+ installSpinner.message(`Installing new package versions with ${packageManager}`);
3714
+ await jsProject.install();
3715
+ } catch (error) {
3716
+ installSpinner.stop(
3717
+ `Failed to install new package versions${packageManager ? ` with ${packageManager}` : ""}`
3718
+ );
3719
+ process.removeListener("exit", exitHandler);
3720
+ await revertPackageJsonChanges();
3721
+ throw error;
3722
+ }
3723
+ installSpinner.stop("Installed new package versions");
3724
+ process.removeListener("exit", exitHandler);
3725
+ await removeFile(packageJsonBackupPath);
3726
+ if (!embedded) {
3727
+ outro4(
3728
+ `Packages updated${newCliVersion ? " ..but you should really update your CLI too!" : ""}`
3729
+ );
3730
+ }
3731
+ return hasOutput;
3732
+ }
3733
+ function getTriggerDependencies(packageJson) {
3734
+ const deps = [];
3735
+ for (const type of ["dependencies", "devDependencies"]) {
3736
+ for (const [name, version2] of Object.entries(packageJson[type] ?? {})) {
3737
+ if (!version2) {
3738
+ continue;
3739
+ }
3740
+ if (version2.startsWith("workspace")) {
3741
+ continue;
3742
+ }
3743
+ if (!triggerPackageFilter.test(name)) {
3744
+ continue;
3745
+ }
3746
+ const ignoredPackages = ["@trigger.dev/companyicons"];
3747
+ if (ignoredPackages.includes(name)) {
3748
+ continue;
3749
+ }
3750
+ deps.push({ type, name, version: version2 });
3751
+ }
3752
+ }
3753
+ return deps;
3754
+ }
3755
+ function mutatePackageJsonWithUpdatedPackages(packageJson, depsToUpdate, targetVersion) {
3756
+ for (const { type, name, version: version2 } of depsToUpdate) {
3757
+ if (!packageJson[type]) {
3758
+ throw new Error(
3759
+ `No ${type} entry found in package.json. Please try to upgrade manually instead.`
3760
+ );
3761
+ }
3762
+ packageJson[type][name] = targetVersion;
3763
+ }
3764
+ }
3765
+ function printUpdateTable(depsToUpdate, targetVersion) {
3766
+ log4.message("Suggested updates");
3767
+ const tableData = depsToUpdate.map((dep) => ({
3768
+ package: dep.name,
3769
+ old: dep.version,
3770
+ new: targetVersion
3771
+ }));
3772
+ logger.table(tableData);
3773
+ }
3774
+ async function updateConfirmation(depsToUpdate, targetVersion) {
3775
+ printUpdateTable(depsToUpdate, targetVersion);
3776
+ let confirmMessage = "Would you like to apply those updates?";
3777
+ return await confirm({
3778
+ message: confirmMessage
3779
+ });
3780
+ }
3781
+ async function getPackageJson(absoluteProjectPath) {
3782
+ const packageJsonPath = join5(absoluteProjectPath, "package.json");
3783
+ const readonlyPackageJson = Object.freeze(await readJSONFile(packageJsonPath));
3784
+ const packageJson = structuredClone(readonlyPackageJson);
3785
+ return { packageJson, readonlyPackageJson, packageJsonPath };
3786
+ }
3787
+
2871
3788
  // src/commands/deploy.ts
2872
- import { Glob } from "glob";
2873
3789
  var DeployCommandOptions = CommonCommandOptions.extend({
2874
3790
  skipTypecheck: z4.boolean().default(false),
2875
3791
  skipDeploy: z4.boolean().default(false),
2876
- ignoreEnvVarCheck: z4.boolean().default(false),
2877
3792
  env: z4.enum(["prod", "staging"]),
2878
3793
  loadImage: z4.boolean().default(false),
2879
3794
  buildPlatform: z4.enum(["linux/amd64", "linux/arm64"]).default("linux/amd64"),
@@ -2883,7 +3798,10 @@ var DeployCommandOptions = CommonCommandOptions.extend({
2883
3798
  config: z4.string().optional(),
2884
3799
  projectRef: z4.string().optional(),
2885
3800
  outputMetafile: z4.string().optional(),
2886
- apiUrl: z4.string().optional()
3801
+ apiUrl: z4.string().optional(),
3802
+ saveLogs: z4.boolean().default(false),
3803
+ skipUpdateCheck: z4.boolean().default(false),
3804
+ noCache: z4.boolean().default(false)
2887
3805
  });
2888
3806
  function configureDeployCommand(program2) {
2889
3807
  return commonOptions(
@@ -2891,18 +3809,20 @@ function configureDeployCommand(program2) {
2891
3809
  "-e, --env <env>",
2892
3810
  "Deploy to a specific environment (currently only prod and staging are supported)",
2893
3811
  "prod"
2894
- ).option("--skip-typecheck", "Whether to skip the pre-build typecheck").option(
2895
- "--ignore-env-var-check",
2896
- "Detected missing environment variables won't block deployment"
2897
- ).option("-c, --config <config file>", "The name of the config file, found at [path]").option(
3812
+ ).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(
2898
3813
  "-p, --project-ref <project ref>",
2899
- "The project ref. Required if there is no config file."
3814
+ "The project ref. Required if there is no config file. This will override the project specified in the config file."
2900
3815
  )
2901
3816
  ).addOption(
2902
3817
  new CommandOption(
2903
3818
  "--self-hosted",
2904
3819
  "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."
2905
3820
  ).hideHelp()
3821
+ ).addOption(
3822
+ new CommandOption(
3823
+ "--no-cache",
3824
+ "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."
3825
+ ).hideHelp()
2906
3826
  ).addOption(
2907
3827
  new CommandOption(
2908
3828
  "--push",
@@ -2918,6 +3838,11 @@ function configureDeployCommand(program2) {
2918
3838
  "--tag <tag>",
2919
3839
  "(Coming soon) Specify the tag to use when pushing the image to the registry"
2920
3840
  ).hideHelp()
3841
+ ).addOption(
3842
+ new CommandOption(
3843
+ "--ignore-env-var-check",
3844
+ "(deprecated) Detected missing environment variables won't block deployment"
3845
+ ).hideHelp()
2921
3846
  ).addOption(new CommandOption("-D, --skip-deploy", "Skip deploying the image").hideHelp()).addOption(
2922
3847
  new CommandOption("--load-image", "Load the built image into your local docker").hideHelp()
2923
3848
  ).addOption(
@@ -2930,10 +3855,15 @@ function configureDeployCommand(program2) {
2930
3855
  "--output-metafile <path>",
2931
3856
  "If provided, will save the esbuild metafile for the build to the specified path"
2932
3857
  ).hideHelp()
2933
- ).action(async (path6, options) => {
3858
+ ).addOption(
3859
+ new CommandOption(
3860
+ "--save-logs",
3861
+ "If provided, will save logs even for successful builds"
3862
+ ).hideHelp()
3863
+ ).action(async (path7, options) => {
2934
3864
  await handleTelemetry(async () => {
2935
3865
  await printStandloneInitialBanner(true);
2936
- await deployCommand(path6, options);
3866
+ await deployCommand(path7, options);
2937
3867
  });
2938
3868
  });
2939
3869
  }
@@ -2944,7 +3874,10 @@ async function deployCommand(dir, options) {
2944
3874
  }
2945
3875
  async function _deployCommand(dir, options) {
2946
3876
  const span = trace2.getSpan(context.active());
2947
- intro3("Deploying project");
3877
+ intro4("Deploying project");
3878
+ if (!options.skipUpdateCheck) {
3879
+ await updateTriggerPackages(dir, { ...options }, true, true);
3880
+ }
2948
3881
  const authorization = await login({
2949
3882
  embedded: true,
2950
3883
  defaultApiUrl: options.apiUrl,
@@ -2968,6 +3901,11 @@ async function _deployCommand(dir, options) {
2968
3901
  configFile: options.config,
2969
3902
  projectRef: options.projectRef
2970
3903
  });
3904
+ if (resolvedConfig.status === "error") {
3905
+ logger.error("Failed to read config:", resolvedConfig.error);
3906
+ span && recordSpanException5(span, resolvedConfig.error);
3907
+ throw new SkipLoggingError("Failed to read config");
3908
+ }
2971
3909
  logger.debug("Resolved config", { resolvedConfig });
2972
3910
  span?.setAttributes({
2973
3911
  "resolvedConfig.status": resolvedConfig.status,
@@ -2976,7 +3914,7 @@ async function _deployCommand(dir, options) {
2976
3914
  "resolvedConfig.config.projectDir": resolvedConfig.config.projectDir,
2977
3915
  "resolvedConfig.config.triggerUrl": resolvedConfig.config.triggerUrl,
2978
3916
  "resolvedConfig.config.triggerDirectories": resolvedConfig.config.triggerDirectories,
2979
- ...flattenAttributes2(resolvedConfig.config.retries, "resolvedConfig.config.retries")
3917
+ ...flattenAttributes3(resolvedConfig.config.retries, "resolvedConfig.config.retries")
2980
3918
  });
2981
3919
  const apiClient2 = new CliApiClient(authorization.auth.apiUrl, authorization.auth.accessToken);
2982
3920
  const deploymentEnv = await apiClient2.getProjectEnv({
@@ -2987,7 +3925,7 @@ async function _deployCommand(dir, options) {
2987
3925
  throw new Error(deploymentEnv.error);
2988
3926
  }
2989
3927
  const environmentClient = new CliApiClient(authorization.auth.apiUrl, deploymentEnv.data.apiKey);
2990
- log2.step(
3928
+ log5.step(
2991
3929
  `Preparing to deploy "${deploymentEnv.data.name}" (${resolvedConfig.config.project}) to ${options.env}`
2992
3930
  );
2993
3931
  const compilation = await compileProject(
@@ -2996,15 +3934,6 @@ async function _deployCommand(dir, options) {
2996
3934
  resolvedConfig.status === "file" ? resolvedConfig.path : void 0
2997
3935
  );
2998
3936
  logger.debug("Compilation result", { compilation });
2999
- if (compilation.envVars.length > 0) {
3000
- await checkEnvVars(
3001
- compilation.envVars ?? [],
3002
- resolvedConfig.config,
3003
- options,
3004
- environmentClient,
3005
- authorization.dashboardUrl
3006
- );
3007
- }
3008
3937
  const deploymentResponse = await environmentClient.initializeDeployment({
3009
3938
  contentHash: compilation.contentHash,
3010
3939
  userId: authorization.userId
@@ -3018,7 +3947,7 @@ async function _deployCommand(dir, options) {
3018
3947
  );
3019
3948
  }
3020
3949
  const version2 = deploymentResponse.data.version;
3021
- const deploymentSpinner = spinner4();
3950
+ const deploymentSpinner = spinner();
3022
3951
  deploymentSpinner.start(`Deploying version ${version2}`);
3023
3952
  const selfHostedRegistryHost = deploymentResponse.data.registryHost ?? options.registry;
3024
3953
  const registryHost = selfHostedRegistryHost ?? "registry.trigger.dev";
@@ -3035,7 +3964,8 @@ async function _deployCommand(dir, options) {
3035
3964
  projectRef: resolvedConfig.config.project,
3036
3965
  buildPlatform: options.buildPlatform,
3037
3966
  pushImage: options.push,
3038
- selfHostedRegistry: !!options.registry
3967
+ selfHostedRegistry: !!options.registry,
3968
+ noCache: options.noCache
3039
3969
  });
3040
3970
  }
3041
3971
  if (!deploymentResponse.data.externalBuildData) {
@@ -3043,28 +3973,57 @@ async function _deployCommand(dir, options) {
3043
3973
  "Failed to initialize deployment. The deployment does not have any external build data. To deploy this project, you must use the --self-hosted flag to build and push the image yourself."
3044
3974
  );
3045
3975
  }
3046
- return buildAndPushImage({
3047
- registryHost,
3048
- auth: authorization.auth.accessToken,
3049
- imageTag: deploymentResponse.data.imageTag,
3050
- buildId: deploymentResponse.data.externalBuildData.buildId,
3051
- buildToken: deploymentResponse.data.externalBuildData.buildToken,
3052
- buildProjectId: deploymentResponse.data.externalBuildData.projectId,
3053
- cwd: compilation.path,
3054
- projectId: resolvedConfig.config.project,
3055
- deploymentId: deploymentResponse.data.id,
3056
- deploymentVersion: deploymentResponse.data.version,
3057
- contentHash: deploymentResponse.data.contentHash,
3058
- projectRef: resolvedConfig.config.project,
3059
- loadImage: options.loadImage,
3060
- buildPlatform: options.buildPlatform
3061
- });
3976
+ return buildAndPushImage(
3977
+ {
3978
+ registryHost,
3979
+ auth: authorization.auth.accessToken,
3980
+ imageTag: deploymentResponse.data.imageTag,
3981
+ buildId: deploymentResponse.data.externalBuildData.buildId,
3982
+ buildToken: deploymentResponse.data.externalBuildData.buildToken,
3983
+ buildProjectId: deploymentResponse.data.externalBuildData.projectId,
3984
+ cwd: compilation.path,
3985
+ projectId: resolvedConfig.config.project,
3986
+ deploymentId: deploymentResponse.data.id,
3987
+ deploymentVersion: deploymentResponse.data.version,
3988
+ contentHash: deploymentResponse.data.contentHash,
3989
+ projectRef: resolvedConfig.config.project,
3990
+ loadImage: options.loadImage,
3991
+ buildPlatform: options.buildPlatform,
3992
+ noCache: options.noCache
3993
+ },
3994
+ deploymentSpinner
3995
+ );
3062
3996
  };
3063
3997
  const image = await buildImage();
3998
+ const warnings = checkLogsForWarnings(image.logs);
3999
+ if (!warnings.ok) {
4000
+ await failDeploy(
4001
+ deploymentResponse.data.shortCode,
4002
+ warnings.summary,
4003
+ image.logs,
4004
+ deploymentSpinner,
4005
+ warnings.warnings,
4006
+ warnings.errors
4007
+ );
4008
+ throw new SkipLoggingError(`Failed to build project image: ${warnings.summary}`);
4009
+ }
3064
4010
  if (!image.ok) {
3065
- deploymentSpinner.stop(`Failed to build project image: ${image.error}`);
4011
+ await failDeploy(
4012
+ deploymentResponse.data.shortCode,
4013
+ image.error,
4014
+ image.logs,
4015
+ deploymentSpinner,
4016
+ warnings.warnings
4017
+ );
3066
4018
  throw new SkipLoggingError(`Failed to build project image: ${image.error}`);
3067
4019
  }
4020
+ const preExitTasks = async () => {
4021
+ printWarnings(warnings.warnings);
4022
+ if (options.saveLogs) {
4023
+ const logPath = await saveLogs(deploymentResponse.data.shortCode, image.logs);
4024
+ log5.info(`Build logs have been saved to ${logPath}`);
4025
+ }
4026
+ };
3068
4027
  const imageReference = options.selfHosted ? `${selfHostedRegistryHost ? `${selfHostedRegistryHost}/` : ""}${image.image}${image.digest ? `@${image.digest}` : ""}` : `${registryHost}/${image.image}${image.digest ? `@${image.digest}` : ""}`;
3069
4028
  span?.setAttributes({
3070
4029
  "image.reference": imageReference
@@ -3073,6 +4032,7 @@ async function _deployCommand(dir, options) {
3073
4032
  deploymentSpinner.stop(
3074
4033
  `Project image built: ${imageReference}. Skipping deployment as requested`
3075
4034
  );
4035
+ await preExitTasks();
3076
4036
  throw new SkipCommandError("Skipping deployment as requested");
3077
4037
  }
3078
4038
  deploymentSpinner.message(
@@ -3082,11 +4042,13 @@ async function _deployCommand(dir, options) {
3082
4042
  const startIndexingResponse = await environmentClient.startDeploymentIndexing(
3083
4043
  deploymentResponse.data.id,
3084
4044
  {
3085
- imageReference
4045
+ imageReference,
4046
+ selfHosted: options.selfHosted
3086
4047
  }
3087
4048
  );
3088
4049
  if (!startIndexingResponse.success) {
3089
4050
  deploymentSpinner.stop(`Failed to start indexing: ${startIndexingResponse.error}`);
4051
+ await preExitTasks();
3090
4052
  throw new SkipLoggingError(`Failed to start indexing: ${startIndexingResponse.error}`);
3091
4053
  }
3092
4054
  const finishedDeployment = await waitForDeploymentToFinish(
@@ -3095,26 +4057,33 @@ async function _deployCommand(dir, options) {
3095
4057
  );
3096
4058
  if (!finishedDeployment) {
3097
4059
  deploymentSpinner.stop(`Deployment failed to complete`);
4060
+ await preExitTasks();
3098
4061
  throw new SkipLoggingError("Deployment failed to complete: unknown issue");
3099
4062
  }
3100
4063
  if (typeof finishedDeployment === "string") {
3101
4064
  deploymentSpinner.stop(`Deployment failed to complete: ${finishedDeployment}`);
4065
+ await preExitTasks();
3102
4066
  throw new SkipLoggingError(`Deployment failed to complete: ${finishedDeployment}`);
3103
4067
  }
3104
- const deploymentLink = terminalLink(
4068
+ const deploymentLink = terminalLink2(
3105
4069
  "View deployment",
3106
4070
  `${authorization.dashboardUrl}/projects/v3/${resolvedConfig.config.project}/deployments/${finishedDeployment.shortCode}`
3107
4071
  );
3108
4072
  switch (finishedDeployment.status) {
3109
4073
  case "DEPLOYED": {
3110
- deploymentSpinner.stop("Deployment completed");
4074
+ if (warnings.warnings.length > 0) {
4075
+ deploymentSpinner.stop("Deployment completed with warnings");
4076
+ } else {
4077
+ deploymentSpinner.stop("Deployment completed");
4078
+ }
4079
+ await preExitTasks();
3111
4080
  const taskCount = finishedDeployment.worker?.tasks.length ?? 0;
3112
4081
  if (taskCount === 0) {
3113
- outro3(
4082
+ outro5(
3114
4083
  `Version ${version2} deployed with no detected tasks. Please make sure you are exporting tasks in your project. ${deploymentLink}`
3115
4084
  );
3116
4085
  } else {
3117
- outro3(
4086
+ outro5(
3118
4087
  `Version ${version2} deployed with ${taskCount} detected task${taskCount === 1 ? "" : "s"} ${deploymentLink}`
3119
4088
  );
3120
4089
  }
@@ -3122,10 +4091,29 @@ async function _deployCommand(dir, options) {
3122
4091
  }
3123
4092
  case "FAILED": {
3124
4093
  if (finishedDeployment.errorData) {
3125
- deploymentSpinner.stop(
3126
- `Deployment encountered an error: ${finishedDeployment.errorData.name}. ${deploymentLink}`
3127
- );
3128
- logger.error(finishedDeployment.errorData.stack);
4094
+ if (finishedDeployment.errorData.name === "TaskMetadataParseError") {
4095
+ const errorJson = safeJsonParse(finishedDeployment.errorData.stack);
4096
+ if (errorJson) {
4097
+ const parsedError2 = TaskMetadataFailedToParseData.safeParse(errorJson);
4098
+ if (parsedError2.success) {
4099
+ deploymentSpinner.stop(`Deployment encountered an error. ${deploymentLink}`);
4100
+ logTaskMetadataParseError(parsedError2.data.zodIssues, parsedError2.data.tasks);
4101
+ await preExitTasks();
4102
+ throw new SkipLoggingError(
4103
+ `Deployment encountered an error: ${finishedDeployment.errorData.name}`
4104
+ );
4105
+ }
4106
+ }
4107
+ }
4108
+ const parsedError = finishedDeployment.errorData.stack ? parseBuildErrorStack(finishedDeployment.errorData) ?? finishedDeployment.errorData.message : finishedDeployment.errorData.message;
4109
+ if (typeof parsedError === "string") {
4110
+ deploymentSpinner.stop(`Deployment encountered an error. ${deploymentLink}`);
4111
+ logger.log(`${chalkError("X Error:")} ${parsedError}`);
4112
+ } else {
4113
+ deploymentSpinner.stop(`Deployment encountered an error. ${deploymentLink}`);
4114
+ logESMRequireError(parsedError, resolvedConfig);
4115
+ }
4116
+ await preExitTasks();
3129
4117
  throw new SkipLoggingError(
3130
4118
  `Deployment encountered an error: ${finishedDeployment.errorData.name}`
3131
4119
  );
@@ -3133,62 +4121,132 @@ async function _deployCommand(dir, options) {
3133
4121
  deploymentSpinner.stop(
3134
4122
  `Deployment failed with an unknown error. Please contact eric@trigger.dev for help. ${deploymentLink}`
3135
4123
  );
4124
+ await preExitTasks();
3136
4125
  throw new SkipLoggingError("Deployment failed with an unknown error");
3137
4126
  }
3138
4127
  }
3139
4128
  case "CANCELED": {
3140
4129
  deploymentSpinner.stop(`Deployment was canceled. ${deploymentLink}`);
4130
+ await preExitTasks();
3141
4131
  throw new SkipLoggingError("Deployment was canceled");
3142
4132
  }
3143
- case "TIMED_OUT": {
3144
- deploymentSpinner.stop(`Deployment timed out. ${deploymentLink}`);
3145
- throw new SkipLoggingError("Deployment timed out");
4133
+ case "TIMED_OUT": {
4134
+ deploymentSpinner.stop(`Deployment timed out. ${deploymentLink}`);
4135
+ await preExitTasks();
4136
+ throw new SkipLoggingError("Deployment timed out");
4137
+ }
4138
+ }
4139
+ }
4140
+ function printErrors(errors) {
4141
+ for (const error of errors ?? []) {
4142
+ log5.error(`${chalkError("Error:")} ${error}`);
4143
+ }
4144
+ }
4145
+ function printWarnings(warnings) {
4146
+ for (const warning of warnings ?? []) {
4147
+ log5.warn(`${chalkWarning("Warning:")} ${warning}`);
4148
+ }
4149
+ }
4150
+ function checkLogsForWarnings(logs) {
4151
+ const warnings = [
4152
+ {
4153
+ regex: /prisma:warn We could not find your Prisma schema/,
4154
+ message: `Prisma generate failed to find the default schema. Did you include it in config.additionalFiles? ${terminalLink2(
4155
+ "Config docs",
4156
+ docs.config.prisma
4157
+ )}
4158
+ Custom schema paths require a postinstall script like this: \`prisma generate --schema=./custom/path/to/schema.prisma\``,
4159
+ shouldFail: true
4160
+ }
4161
+ ];
4162
+ const errorMessages2 = [];
4163
+ const warningMessages = [];
4164
+ let shouldFail = false;
4165
+ for (const warning of warnings) {
4166
+ const matches = logs.match(warning.regex);
4167
+ if (!matches) {
4168
+ continue;
4169
+ }
4170
+ const message = getMessageFromTemplate(warning.message, matches.groups);
4171
+ if (warning.shouldFail) {
4172
+ shouldFail = true;
4173
+ errorMessages2.push(message);
4174
+ } else {
4175
+ warningMessages.push(message);
4176
+ }
4177
+ }
4178
+ if (shouldFail) {
4179
+ return {
4180
+ ok: false,
4181
+ summary: "Build succeeded with critical warnings. Will not proceed",
4182
+ warnings: warningMessages,
4183
+ errors: errorMessages2
4184
+ };
4185
+ }
4186
+ return {
4187
+ ok: true,
4188
+ warnings: warningMessages
4189
+ };
4190
+ }
4191
+ function checkLogsForErrors(logs) {
4192
+ const errors = [
4193
+ {
4194
+ regex: /Error: Provided --schema at (?<schema>.*) doesn't exist/,
4195
+ message: `Prisma generate failed to find the specified schema at "$schema".
4196
+ Did you include it in config.additionalFiles? ${terminalLink2(
4197
+ "Config docs",
4198
+ docs.config.prisma
4199
+ )}`
4200
+ },
4201
+ {
4202
+ regex: /sh: 1: (?<packageOrBinary>.*): not found/,
4203
+ message: `$packageOrBinary not found
4204
+
4205
+ If it's a package: Include it in ${terminalLink2(
4206
+ "config.additionalPackages",
4207
+ docs.config.prisma
4208
+ )}
4209
+ If it's a binary: Please ${terminalLink2(
4210
+ "get in touch",
4211
+ getInTouch
4212
+ )} and we'll see what we can do!`
4213
+ }
4214
+ ];
4215
+ for (const error of errors) {
4216
+ const matches = logs.match(error.regex);
4217
+ if (!matches) {
4218
+ continue;
3146
4219
  }
4220
+ const message = getMessageFromTemplate(error.message, matches.groups);
4221
+ log5.error(`${chalkError("Error:")} ${message}`);
4222
+ break;
3147
4223
  }
3148
4224
  }
3149
- async function checkEnvVars(envVars, config, options, environmentClient, apiUrl) {
3150
- return await tracer.startActiveSpan("detectEnvVars", async (span) => {
3151
- try {
3152
- span.setAttribute("envVars.check", envVars);
3153
- const environmentVariablesSpinner = spinner4();
3154
- environmentVariablesSpinner.start("Checking environment variables");
3155
- const environmentVariables = await environmentClient.getEnvironmentVariables(config.project);
3156
- if (!environmentVariables.success) {
3157
- environmentVariablesSpinner.stop(`Failed to fetch environment variables, skipping check`);
3158
- } else {
3159
- const missingEnvironmentVariables = envVars.filter(
3160
- (envVar) => environmentVariables.data.variables[envVar] === void 0
3161
- );
3162
- if (missingEnvironmentVariables.length > 0) {
3163
- environmentVariablesSpinner.stop(
3164
- `Found missing env vars in ${options.env}: ${arrayToSentence(
3165
- missingEnvironmentVariables
3166
- )}. ${options.ignoreEnvVarCheck ? "Continuing deployment because of --ignore-env-var-check. " : "Aborting deployment. "}${chalk4.bgBlueBright(
3167
- terminalLink(
3168
- "Manage env vars",
3169
- `${apiUrl}/projects/v3/${config.project}/environment-variables`
3170
- )
3171
- )}`
3172
- );
3173
- span.setAttributes({
3174
- "envVars.missing": missingEnvironmentVariables
3175
- });
3176
- if (!options.ignoreEnvVarCheck) {
3177
- throw new SkipLoggingError("Found missing environment variables");
3178
- } else {
3179
- span.end();
3180
- return;
3181
- }
3182
- }
3183
- environmentVariablesSpinner.stop(`Environment variable check passed`);
3184
- }
3185
- span.end();
3186
- } catch (e) {
3187
- recordSpanException4(span, e);
3188
- span.end();
3189
- throw e;
4225
+ function getMessageFromTemplate(template, replacer) {
4226
+ let message = template;
4227
+ if (replacer) {
4228
+ for (const [key, value] of Object.entries(replacer)) {
4229
+ message = message.replaceAll(`$${key}`, value);
3190
4230
  }
3191
- });
4231
+ }
4232
+ return message;
4233
+ }
4234
+ async function saveLogs(shortCode, logs) {
4235
+ const logPath = join6(await createTempDir(), `build-${shortCode}.log`);
4236
+ await writeFile2(logPath, logs);
4237
+ return logPath;
4238
+ }
4239
+ async function failDeploy(shortCode, errorSummary, logs, deploymentSpinner, warnings, errors) {
4240
+ deploymentSpinner.stop(`Failed to deploy project`);
4241
+ if (logs.trim() !== "") {
4242
+ const logPath = await saveLogs(shortCode, logs);
4243
+ printWarnings(warnings);
4244
+ printErrors(errors);
4245
+ checkLogsForErrors(logs);
4246
+ outro5(`${chalkError("Error:")} ${errorSummary}. Full build logs have been saved to ${logPath}`);
4247
+ } else {
4248
+ outro5(`${chalkError("Error:")} ${errorSummary}.`);
4249
+ }
3192
4250
  }
3193
4251
  async function waitForDeploymentToFinish(deploymentId, client, timeoutInSeconds = 60) {
3194
4252
  return tracer.startActiveSpan("waitForDeploymentToFinish", async (span) => {
@@ -3218,13 +4276,13 @@ async function waitForDeploymentToFinish(deploymentId, client, timeoutInSeconds
3218
4276
  await setTimeout2(1e3);
3219
4277
  }
3220
4278
  } catch (error) {
3221
- recordSpanException4(span, error);
4279
+ recordSpanException5(span, error);
3222
4280
  span.end();
3223
4281
  return error instanceof Error ? error.message : JSON.stringify(error);
3224
4282
  }
3225
4283
  });
3226
4284
  }
3227
- async function buildAndPushImage(options) {
4285
+ async function buildAndPushImage(options, updater) {
3228
4286
  return tracer.startActiveSpan("buildAndPushImage", async (span) => {
3229
4287
  span.setAttributes({
3230
4288
  "options.registryHost": options.registryHost,
@@ -3245,6 +4303,7 @@ async function buildAndPushImage(options) {
3245
4303
  "build",
3246
4304
  "-f",
3247
4305
  "Containerfile",
4306
+ options.noCache ? "--no-cache" : void 0,
3248
4307
  "--platform",
3249
4308
  options.buildPlatform,
3250
4309
  "--provenance",
@@ -3280,15 +4339,24 @@ async function buildAndPushImage(options) {
3280
4339
  });
3281
4340
  const errors = [];
3282
4341
  try {
3283
- await new Promise((res, rej) => {
4342
+ const processCode = await new Promise((res, rej) => {
3284
4343
  childProcess2.stderr?.on("data", (data) => {
3285
- const text2 = data.toString();
3286
- errors.push(text2);
3287
- logger.debug(text2);
4344
+ const text3 = data.toString();
4345
+ const lines = text3.split("\n").filter(Boolean);
4346
+ errors.push(...lines);
4347
+ logger.debug(text3);
3288
4348
  });
3289
4349
  childProcess2.on("error", (e) => rej(e));
3290
- childProcess2.on("close", () => res());
4350
+ childProcess2.on("close", (code) => res(code));
3291
4351
  });
4352
+ const logs = extractLogs(errors);
4353
+ if (processCode !== 0) {
4354
+ return {
4355
+ ok: false,
4356
+ error: `Error building image`,
4357
+ logs
4358
+ };
4359
+ }
3292
4360
  const digest = extractImageDigest(errors);
3293
4361
  span.setAttributes({
3294
4362
  "image.digest": digest
@@ -3297,14 +4365,16 @@ async function buildAndPushImage(options) {
3297
4365
  return {
3298
4366
  ok: true,
3299
4367
  image: options.imageTag,
4368
+ logs,
3300
4369
  digest
3301
4370
  };
3302
4371
  } catch (e) {
3303
- recordSpanException4(span, e);
4372
+ recordSpanException5(span, e);
3304
4373
  span.end();
3305
4374
  return {
3306
4375
  ok: false,
3307
- error: e instanceof Error ? e.message : JSON.stringify(e)
4376
+ error: e instanceof Error ? e.message : JSON.stringify(e),
4377
+ logs: extractLogs(errors)
3308
4378
  };
3309
4379
  }
3310
4380
  });
@@ -3325,6 +4395,7 @@ async function buildAndPushSelfHostedImage(options) {
3325
4395
  "build",
3326
4396
  "-f",
3327
4397
  "Containerfile",
4398
+ options.noCache ? "--no-cache" : void 0,
3328
4399
  "--platform",
3329
4400
  options.buildPlatform,
3330
4401
  "--build-arg",
@@ -3342,7 +4413,9 @@ async function buildAndPushSelfHostedImage(options) {
3342
4413
  "."
3343
4414
  // The build context
3344
4415
  ].filter(Boolean);
3345
- logger.debug(`docker ${buildArgs.join(" ")}`);
4416
+ logger.debug(`docker ${buildArgs.join(" ")}`, {
4417
+ cwd: options.cwd
4418
+ });
3346
4419
  span.setAttribute("docker.command.build", `docker ${buildArgs.join(" ")}`);
3347
4420
  const buildProcess = execa2("docker", buildArgs, {
3348
4421
  cwd: options.cwd
@@ -3350,25 +4423,33 @@ async function buildAndPushSelfHostedImage(options) {
3350
4423
  const errors = [];
3351
4424
  let digest;
3352
4425
  try {
3353
- await new Promise((res, rej) => {
4426
+ const processCode = await new Promise((res, rej) => {
3354
4427
  buildProcess.stderr?.on("data", (data) => {
3355
- const text2 = data.toString();
3356
- errors.push(text2);
3357
- logger.debug(text2);
4428
+ const text3 = data.toString();
4429
+ errors.push(text3);
4430
+ logger.debug(text3);
3358
4431
  });
3359
4432
  buildProcess.on("error", (e) => rej(e));
3360
- buildProcess.on("close", () => res());
4433
+ buildProcess.on("close", (code) => res(code));
3361
4434
  });
4435
+ if (processCode !== 0) {
4436
+ return {
4437
+ ok: false,
4438
+ error: "Error building image",
4439
+ logs: extractLogs(errors)
4440
+ };
4441
+ }
3362
4442
  digest = extractImageDigest(errors);
3363
4443
  span.setAttributes({
3364
4444
  "image.digest": digest
3365
4445
  });
3366
4446
  } catch (e) {
3367
- recordSpanException4(span, e);
4447
+ recordSpanException5(span, e);
3368
4448
  span.end();
3369
4449
  return {
3370
4450
  ok: false,
3371
- error: e instanceof Error ? e.message : JSON.stringify(e)
4451
+ error: e instanceof Error ? e.message : JSON.stringify(e),
4452
+ logs: extractLogs(errors)
3372
4453
  };
3373
4454
  }
3374
4455
  const pushArgs = ["push", imageRef].filter(Boolean);
@@ -3379,25 +4460,33 @@ async function buildAndPushSelfHostedImage(options) {
3379
4460
  cwd: options.cwd
3380
4461
  });
3381
4462
  try {
3382
- await new Promise((res, rej) => {
4463
+ const processCode = await new Promise((res, rej) => {
3383
4464
  pushProcess.stdout?.on("data", (data) => {
3384
- const text2 = data.toString();
3385
- logger.debug(text2);
4465
+ const text3 = data.toString();
4466
+ logger.debug(text3);
3386
4467
  });
3387
4468
  pushProcess.stderr?.on("data", (data) => {
3388
- const text2 = data.toString();
3389
- logger.debug(text2);
4469
+ const text3 = data.toString();
4470
+ logger.debug(text3);
3390
4471
  });
3391
4472
  pushProcess.on("error", (e) => rej(e));
3392
- pushProcess.on("close", () => res());
4473
+ pushProcess.on("close", (code) => res(code));
3393
4474
  });
4475
+ if (processCode !== 0) {
4476
+ return {
4477
+ ok: false,
4478
+ error: "Error pushing image",
4479
+ logs: extractLogs(errors)
4480
+ };
4481
+ }
3394
4482
  span.end();
3395
4483
  } catch (e) {
3396
- recordSpanException4(span, e);
4484
+ recordSpanException5(span, e);
3397
4485
  span.end();
3398
4486
  return {
3399
4487
  ok: false,
3400
- error: e instanceof Error ? e.message : JSON.stringify(e)
4488
+ error: e instanceof Error ? e.message : JSON.stringify(e),
4489
+ logs: extractLogs(errors)
3401
4490
  };
3402
4491
  }
3403
4492
  }
@@ -3405,21 +4494,25 @@ async function buildAndPushSelfHostedImage(options) {
3405
4494
  return {
3406
4495
  ok: true,
3407
4496
  image: options.imageTag,
3408
- digest
4497
+ digest,
4498
+ logs: extractLogs(errors)
3409
4499
  };
3410
4500
  });
3411
4501
  }
3412
4502
  function extractImageDigest(outputs) {
3413
- const imageDigestRegex = /sha256:[a-f0-9]{64}/;
4503
+ const imageDigestRegex = /pushing manifest for .+(?<digest>sha256:[a-f0-9]{64})/;
3414
4504
  for (const line of outputs) {
3415
- if (line.includes("pushing manifest")) {
3416
- const imageDigestMatch = line.match(imageDigestRegex);
3417
- if (imageDigestMatch) {
3418
- return imageDigestMatch[0];
3419
- }
4505
+ const imageDigestMatch = line.match(imageDigestRegex);
4506
+ const digest = imageDigestMatch?.groups?.digest;
4507
+ if (digest) {
4508
+ return digest;
3420
4509
  }
3421
4510
  }
3422
4511
  }
4512
+ function extractLogs(outputs) {
4513
+ const cleanedOutputs = outputs.map((line) => line.trim()).filter((line) => line !== "");
4514
+ return cleanedOutputs.map((line) => line.trim()).join("\n");
4515
+ }
3423
4516
  async function compileProject(config, options, configPath) {
3424
4517
  return await tracer.startActiveSpan("compileProject", async (span) => {
3425
4518
  try {
@@ -3429,25 +4522,25 @@ async function compileProject(config, options, configPath) {
3429
4522
  throw new Error("Typecheck failed, aborting deployment");
3430
4523
  }
3431
4524
  }
3432
- const compileSpinner = spinner4();
4525
+ const compileSpinner = spinner();
3433
4526
  compileSpinner.start(`Building project in ${config.projectDir}`);
3434
4527
  const taskFiles = await gatherTaskFiles(config);
3435
4528
  const workerFacade = readFileSync2(
3436
- new URL(importResolve("./workers/prod/worker-facade.js", import.meta.url)).href.replace(
3437
- "file://",
3438
- ""
3439
- ),
4529
+ join6(cliRootPath(), "workers", "prod", "worker-facade.js"),
3440
4530
  "utf-8"
3441
4531
  );
3442
- const workerSetupPath = new URL(
3443
- importResolve("./workers/prod/worker-setup.js", import.meta.url)
3444
- ).href.replace("file://", "");
3445
- let workerContents = workerFacade.replace("__TASKS__", createTaskFileImports(taskFiles)).replace("__WORKER_SETUP__", `import { tracingSDK } from "${workerSetupPath}";`);
4532
+ const workerSetupPath = join6(cliRootPath(), "workers", "prod", "worker-setup.js");
4533
+ let workerContents = workerFacade.replace("__TASKS__", createTaskFileImports(taskFiles)).replace(
4534
+ "__WORKER_SETUP__",
4535
+ `import { tracingSDK } from "${escapeImportPath(workerSetupPath)}";`
4536
+ );
3446
4537
  if (configPath) {
3447
4538
  logger.debug("Importing project config from", { configPath });
3448
4539
  workerContents = workerContents.replace(
3449
4540
  "__IMPORTED_PROJECT_CONFIG__",
3450
- `import * as importedConfigExports from "${configPath}"; const importedConfig = importedConfigExports.config; const handleError = importedConfigExports.handleError;`
4541
+ `import * as importedConfigExports from "${escapeImportPath(
4542
+ configPath
4543
+ )}"; const importedConfig = importedConfigExports.config; const handleError = importedConfigExports.handleError;`
3451
4544
  );
3452
4545
  } else {
3453
4546
  workerContents = workerContents.replace(
@@ -3473,17 +4566,26 @@ async function compileProject(config, options, configPath) {
3473
4566
  // This is needed to support opentelemetry instrumentation that uses module patching
3474
4567
  target: ["node18", "es2020"],
3475
4568
  outdir: "out",
4569
+ banner: {
4570
+ 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" } }); } });`
4571
+ },
3476
4572
  define: {
3477
4573
  TRIGGER_API_URL: `"${config.triggerUrl}"`,
3478
4574
  __PROJECT_CONFIG__: JSON.stringify(config)
3479
4575
  },
3480
4576
  plugins: [
4577
+ mockServerOnlyPlugin(),
3481
4578
  bundleDependenciesPlugin(
3482
4579
  "workerFacade",
3483
4580
  config.dependenciesToBundle,
3484
4581
  config.tsconfigPath
3485
4582
  ),
3486
- workerSetupImportConfigPlugin(configPath)
4583
+ workerSetupImportConfigPlugin(configPath),
4584
+ esbuildDecorators2({
4585
+ tsconfig: config.tsconfigPath,
4586
+ tsx: true,
4587
+ force: false
4588
+ })
3487
4589
  ]
3488
4590
  });
3489
4591
  if (result.errors.length > 0) {
@@ -3496,13 +4598,10 @@ async function compileProject(config, options, configPath) {
3496
4598
  throw new Error("Build failed, aborting deployment");
3497
4599
  }
3498
4600
  if (options.outputMetafile) {
3499
- await writeJSONFile(join4(options.outputMetafile, "worker.json"), result.metafile);
4601
+ await writeJSONFile(join6(options.outputMetafile, "worker.json"), result.metafile);
3500
4602
  }
3501
4603
  const entryPointContents = readFileSync2(
3502
- new URL(importResolve("./workers/prod/entry-point.js", import.meta.url)).href.replace(
3503
- "file://",
3504
- ""
3505
- ),
4604
+ join6(cliRootPath(), "workers", "prod", "entry-point.js"),
3506
4605
  "utf-8"
3507
4606
  );
3508
4607
  const entryPointResult = await build2({
@@ -3545,58 +4644,72 @@ async function compileProject(config, options, configPath) {
3545
4644
  }
3546
4645
  if (options.outputMetafile) {
3547
4646
  await writeJSONFile(
3548
- join4(options.outputMetafile, "entry-point.json"),
4647
+ join6(options.outputMetafile, "entry-point.json"),
3549
4648
  entryPointResult.metafile
3550
4649
  );
3551
4650
  }
3552
4651
  const tempDir = await createTempDir();
3553
4652
  logger.debug(`Writing compiled files to ${tempDir}`);
3554
- const metaOutput = result.metafile.outputs[join4("out", "stdin.js")];
4653
+ const metaOutput = result.metafile.outputs[posix.join("out", "stdin.js")];
3555
4654
  invariant(metaOutput, "Meta output for the result build is missing");
3556
- const entryPointMetaOutput = entryPointResult.metafile.outputs[join4("out", "stdin.js")];
4655
+ const entryPointMetaOutput = entryPointResult.metafile.outputs[posix.join("out", "stdin.js")];
3557
4656
  invariant(entryPointMetaOutput, "Meta output for the entryPoint build is missing");
3558
4657
  const workerOutputFile = result.outputFiles.find(
3559
- (file) => file.path === join4(config.projectDir, "out", "stdin.js")
4658
+ (file) => file.path === join6(config.projectDir, "out", "stdin.js")
3560
4659
  );
3561
4660
  invariant(workerOutputFile, "Output file for the result build is missing");
3562
4661
  const workerSourcemapFile = result.outputFiles.find(
3563
- (file) => file.path === join4(config.projectDir, "out", "stdin.js.map")
4662
+ (file) => file.path === join6(config.projectDir, "out", "stdin.js.map")
3564
4663
  );
3565
4664
  invariant(workerSourcemapFile, "Sourcemap file for the result build is missing");
3566
4665
  const entryPointOutputFile = entryPointResult.outputFiles.find(
3567
- (file) => file.path === join4(config.projectDir, "out", "stdin.js")
4666
+ (file) => file.path === join6(config.projectDir, "out", "stdin.js")
3568
4667
  );
3569
4668
  invariant(entryPointOutputFile, "Output file for the entryPoint build is missing");
3570
4669
  await writeFile2(
3571
- join4(tempDir, "worker.js"),
4670
+ join6(tempDir, "worker.js"),
3572
4671
  `${workerOutputFile.text}
3573
4672
  //# sourceMappingURL=worker.js.map`
3574
4673
  );
3575
- await writeFile2(join4(tempDir, "worker.js.map"), workerSourcemapFile.text);
3576
- await writeFile2(join4(tempDir, "index.js"), entryPointOutputFile.text);
4674
+ await writeFile2(join6(tempDir, "worker.js.map"), workerSourcemapFile.text);
4675
+ await writeFile2(join6(tempDir, "index.js"), entryPointOutputFile.text);
3577
4676
  logger.debug("Getting the imports for the worker and entryPoint builds", {
3578
4677
  workerImports: metaOutput.imports,
3579
4678
  entryPointImports: entryPointMetaOutput.imports
3580
4679
  });
3581
4680
  const allImports = [...metaOutput.imports, ...entryPointMetaOutput.imports];
3582
- const externalPackageJson = await readJSONFile(join4(config.projectDir, "package.json"));
3583
- const dependencies2 = await gatherRequiredDependencies(
3584
- allImports,
3585
- config,
3586
- externalPackageJson
3587
- );
4681
+ const javascriptProject = new JavascriptProject(config.projectDir);
4682
+ const dependencies2 = await resolveRequiredDependencies(allImports, config, javascriptProject);
4683
+ logger.debug("gatherRequiredDependencies()", { dependencies: dependencies2 });
3588
4684
  const packageJsonContents = {
3589
4685
  name: "trigger-worker",
3590
4686
  version: "0.0.0",
3591
4687
  description: "",
3592
4688
  dependencies: dependencies2,
3593
4689
  scripts: {
3594
- postinstall: externalPackageJson?.scripts?.postinstall
4690
+ ...javascriptProject.scripts
3595
4691
  }
3596
4692
  };
3597
- await writeJSONFile(join4(tempDir, "package.json"), packageJsonContents);
3598
- await copyAdditionalFiles(config, tempDir);
3599
- compileSpinner.stop("Project built successfully");
4693
+ span.setAttributes({
4694
+ ...flattenAttributes3(packageJsonContents, "packageJson.contents")
4695
+ });
4696
+ await writeJSONFile(join6(tempDir, "package.json"), packageJsonContents);
4697
+ const copyResult = await copyAdditionalFiles(config, tempDir);
4698
+ if (!copyResult.ok) {
4699
+ compileSpinner.stop("Project built with warnings");
4700
+ log5.warn(
4701
+ `No additionalFiles matches for:
4702
+
4703
+ ${copyResult.noMatches.map((glob) => `- "${glob}"`).join("\n")}
4704
+
4705
+ If this is unexpected you should check your ${terminalLink2(
4706
+ "glob patterns",
4707
+ "https://github.com/isaacs/node-glob?tab=readme-ov-file#glob-primer"
4708
+ )} are valid.`
4709
+ );
4710
+ } else {
4711
+ compileSpinner.stop("Project built successfully");
4712
+ }
3600
4713
  const resolvingDependenciesResult = await resolveDependencies(
3601
4714
  tempDir,
3602
4715
  packageJsonContents,
@@ -3604,31 +4717,31 @@ async function compileProject(config, options, configPath) {
3604
4717
  options
3605
4718
  );
3606
4719
  if (!resolvingDependenciesResult) {
3607
- throw new Error("Failed to resolve dependencies");
4720
+ throw new SkipLoggingError("Failed to resolve dependencies");
4721
+ }
4722
+ const containerFilePath = join6(cliRootPath(), "Containerfile.prod");
4723
+ let containerFileContents = readFileSync2(containerFilePath, "utf-8");
4724
+ if (config.postInstall) {
4725
+ containerFileContents = containerFileContents.replace(
4726
+ "__POST_INSTALL__",
4727
+ `RUN ${config.postInstall}`
4728
+ );
4729
+ } else {
4730
+ containerFileContents = containerFileContents.replace("__POST_INSTALL__", "");
3608
4731
  }
3609
- const containerFilePath = new URL(
3610
- importResolve("./Containerfile.prod", import.meta.url)
3611
- ).href.replace("file://", "");
3612
- await copyFile(containerFilePath, join4(tempDir, "Containerfile"));
4732
+ await writeFile2(join6(tempDir, "Containerfile"), containerFileContents);
3613
4733
  const contentHasher = createHash("sha256");
3614
4734
  contentHasher.update(Buffer.from(entryPointOutputFile.text));
3615
4735
  contentHasher.update(Buffer.from(workerOutputFile.text));
3616
4736
  contentHasher.update(Buffer.from(JSON.stringify(dependencies2)));
3617
4737
  const contentHash = contentHasher.digest("hex");
3618
- const workerSetupEnvVars = await findAllEnvironmentVariableReferencesInFile(workerSetupPath);
3619
- const workerFacadeEnvVars = findAllEnvironmentVariableReferences(workerContents);
3620
- const envVars = findAllEnvironmentVariableReferences(workerOutputFile.text);
3621
- const finalEnvVars = envVars.filter(
3622
- (envVar) => !workerFacadeEnvVars.includes(envVar) && !workerSetupEnvVars.includes(envVar)
3623
- );
3624
4738
  span.setAttributes({
3625
- contentHash,
3626
- envVars: finalEnvVars
4739
+ contentHash
3627
4740
  });
3628
4741
  span.end();
3629
- return { path: tempDir, contentHash, envVars: finalEnvVars };
4742
+ return { path: tempDir, contentHash };
3630
4743
  } catch (e) {
3631
- recordSpanException4(span, e);
4744
+ recordSpanException5(span, e);
3632
4745
  span.end();
3633
4746
  throw e;
3634
4747
  }
@@ -3636,22 +4749,22 @@ async function compileProject(config, options, configPath) {
3636
4749
  }
3637
4750
  async function resolveDependencies(projectDir, packageJsonContents, config, options) {
3638
4751
  return await tracer.startActiveSpan("resolveDependencies", async (span) => {
3639
- const resolvingDepsSpinner = spinner4();
4752
+ const resolvingDepsSpinner = spinner();
3640
4753
  resolvingDepsSpinner.start("Resolving dependencies");
3641
4754
  const hasher = createHash("sha256");
3642
4755
  hasher.update(JSON.stringify(packageJsonContents));
3643
4756
  const digest = hasher.digest("hex").slice(0, 16);
3644
- const cacheDir = join4(config.projectDir, ".trigger", "cache");
3645
- const cachePath = join4(cacheDir, `${digest}.json`);
4757
+ const cacheDir = join6(config.projectDir, ".trigger", "cache");
4758
+ const cachePath = join6(cacheDir, `${digest}.json`);
3646
4759
  span.setAttributes({
3647
4760
  "packageJson.digest": digest,
3648
4761
  "cache.path": cachePath,
3649
- ...flattenAttributes2(packageJsonContents, "packageJson.contents")
4762
+ ...flattenAttributes3(packageJsonContents, "packageJson.contents")
3650
4763
  });
3651
4764
  try {
3652
4765
  const cachedPackageLock = await readFile2(cachePath, "utf-8");
3653
4766
  logger.debug(`Using cached package-lock.json for ${digest}`);
3654
- await writeFile2(join4(projectDir, "package-lock.json"), cachedPackageLock);
4767
+ await writeFile2(join6(projectDir, "package-lock.json"), cachedPackageLock);
3655
4768
  span.setAttributes({
3656
4769
  "cache.hit": true
3657
4770
  });
@@ -3674,21 +4787,44 @@ async function resolveDependencies(projectDir, packageJsonContents, config, opti
3674
4787
  cwd: projectDir,
3675
4788
  stdio: logger.loggerLevel === "debug" ? "inherit" : "pipe"
3676
4789
  });
3677
- const packageLockContents = await readFile2(join4(projectDir, "package-lock.json"), "utf-8");
4790
+ const packageLockContents = await readFile2(join6(projectDir, "package-lock.json"), "utf-8");
3678
4791
  logger.debug(`Writing package-lock.json to cache for ${digest}`);
3679
4792
  await mkdir(cacheDir, { recursive: true });
3680
4793
  await writeFile2(cachePath, packageLockContents);
3681
- await writeFile2(join4(projectDir, "package-lock.json"), packageLockContents);
4794
+ await writeFile2(join6(projectDir, "package-lock.json"), packageLockContents);
3682
4795
  span.end();
3683
4796
  resolvingDepsSpinner.stop("Dependencies resolved");
3684
4797
  return true;
3685
4798
  } catch (installError) {
3686
- logger.debug(`Failed to resolve dependencies: ${JSON.stringify(installError)}`);
3687
- recordSpanException4(span, installError);
4799
+ recordSpanException5(span, installError);
3688
4800
  span.end();
3689
- resolvingDepsSpinner.stop(
3690
- "Failed to resolve dependencies. Rerun with --log-level=debug for more information"
3691
- );
4801
+ const parsedError = parseNpmInstallError(installError);
4802
+ if (typeof parsedError === "string") {
4803
+ resolvingDepsSpinner.stop(`Failed to resolve dependencies: ${parsedError}`);
4804
+ } else {
4805
+ switch (parsedError.type) {
4806
+ case "package-not-found-error": {
4807
+ resolvingDepsSpinner.stop(`Failed to resolve dependencies`);
4808
+ logger.log(
4809
+ `
4810
+ ${chalkError("X Error:")} The package ${chalkPurple(
4811
+ parsedError.packageName
4812
+ )} could not be found in the npm registry.`
4813
+ );
4814
+ break;
4815
+ }
4816
+ case "no-matching-version-error": {
4817
+ resolvingDepsSpinner.stop(`Failed to resolve dependencies`);
4818
+ logger.log(
4819
+ `
4820
+ ${chalkError("X Error:")} The package ${chalkPurple(
4821
+ parsedError.packageName
4822
+ )} could not resolve because the version doesn't exist`
4823
+ );
4824
+ break;
4825
+ }
4826
+ }
4827
+ }
3692
4828
  return false;
3693
4829
  }
3694
4830
  }
@@ -3697,7 +4833,7 @@ async function resolveDependencies(projectDir, packageJsonContents, config, opti
3697
4833
  async function typecheckProject(config, options) {
3698
4834
  return await tracer.startActiveSpan("typecheckProject", async (span) => {
3699
4835
  try {
3700
- const typecheckSpinner = spinner4();
4836
+ const typecheckSpinner = spinner();
3701
4837
  typecheckSpinner.start("Typechecking project");
3702
4838
  const tscTypecheck = execa2("npm", ["exec", "tsc", "--", "--noEmit"], {
3703
4839
  cwd: config.projectDir
@@ -3707,8 +4843,8 @@ async function typecheckProject(config, options) {
3707
4843
  tscTypecheck.stdout?.on("data", (chunk) => stdouts.push(chunk.toString()));
3708
4844
  tscTypecheck.stderr?.on("data", (chunk) => stderrs.push(chunk.toString()));
3709
4845
  try {
3710
- await new Promise((resolve4, reject) => {
3711
- tscTypecheck.addListener("exit", (code) => code === 0 ? resolve4(code) : reject(code));
4846
+ await new Promise((resolve5, reject) => {
4847
+ tscTypecheck.addListener("exit", (code) => code === 0 ? resolve5(code) : reject(code));
3712
4848
  });
3713
4849
  } catch (error) {
3714
4850
  typecheckSpinner.stop(
@@ -3726,63 +4862,100 @@ async function typecheckProject(config, options) {
3726
4862
  span.end();
3727
4863
  return true;
3728
4864
  } catch (e) {
3729
- recordSpanException4(span, e);
4865
+ recordSpanException5(span, e);
3730
4866
  span.end();
3731
4867
  return false;
3732
4868
  }
3733
4869
  });
3734
4870
  }
3735
- async function gatherRequiredDependencies(imports, config, projectPackageJson) {
3736
- const dependencies2 = {};
3737
- for (const file of imports) {
3738
- if (file.kind !== "require-call" && file.kind !== "dynamic-import" || !file.external) {
3739
- continue;
3740
- }
3741
- const packageName = detectPackageNameFromImportPath(file.path);
3742
- if (dependencies2[packageName]) {
3743
- continue;
3744
- }
3745
- const externalDependencyVersion = (projectPackageJson?.dependencies ?? {})[packageName];
3746
- if (externalDependencyVersion) {
3747
- dependencies2[packageName] = stripWorkspaceFromVersion(externalDependencyVersion);
3748
- continue;
3749
- }
3750
- const internalDependencyVersion = dependencies[packageName] ?? detectDependencyVersion(packageName);
3751
- if (internalDependencyVersion) {
3752
- dependencies2[packageName] = stripWorkspaceFromVersion(internalDependencyVersion);
3753
- }
3754
- }
3755
- if (config.additionalPackages) {
3756
- for (const packageName of config.additionalPackages) {
3757
- if (dependencies2[packageName]) {
4871
+ async function resolveRequiredDependencies(imports, config, project) {
4872
+ return await tracer.startActiveSpan("resolveRequiredDependencies", async (span) => {
4873
+ const resolvablePackageNames = /* @__PURE__ */ new Set();
4874
+ for (const file of imports) {
4875
+ if (file.kind !== "require-call" && file.kind !== "dynamic-import" || !file.external) {
3758
4876
  continue;
3759
4877
  }
3760
- const packageParts = parsePackageName(packageName);
3761
- if (packageParts.version) {
3762
- dependencies2[packageParts.name] = packageParts.version;
4878
+ const packageName = detectPackageNameFromImportPath(file.path);
4879
+ if (!packageName) {
3763
4880
  continue;
3764
- } else {
3765
- const externalDependencyVersion = {
3766
- ...projectPackageJson?.devDependencies,
3767
- ...projectPackageJson?.dependencies
3768
- }[packageName];
3769
- if (externalDependencyVersion) {
3770
- dependencies2[packageParts.name] = externalDependencyVersion;
4881
+ }
4882
+ resolvablePackageNames.add(packageName);
4883
+ }
4884
+ span.setAttribute("resolvablePackageNames", Array.from(resolvablePackageNames));
4885
+ const resolvedPackageVersions = await project.resolveAll(Array.from(resolvablePackageNames));
4886
+ const missingPackages = Array.from(resolvablePackageNames).filter(
4887
+ (packageName) => !resolvedPackageVersions[packageName]
4888
+ );
4889
+ span.setAttributes({
4890
+ ...flattenAttributes3(resolvedPackageVersions, "resolvedPackageVersions")
4891
+ });
4892
+ span.setAttribute("missingPackages", missingPackages);
4893
+ const dependencies2 = {};
4894
+ for (const missingPackage of missingPackages) {
4895
+ const internalDependencyVersion = dependencies[missingPackage] ?? detectDependencyVersion(missingPackage);
4896
+ if (internalDependencyVersion) {
4897
+ dependencies2[missingPackage] = stripWorkspaceFromVersion(internalDependencyVersion);
4898
+ }
4899
+ }
4900
+ for (const [packageName, version2] of Object.entries(resolvedPackageVersions)) {
4901
+ dependencies2[packageName] = version2;
4902
+ }
4903
+ if (config.additionalPackages) {
4904
+ span.setAttribute("additionalPackages", config.additionalPackages);
4905
+ for (const packageName of config.additionalPackages) {
4906
+ if (dependencies2[packageName]) {
4907
+ continue;
4908
+ }
4909
+ const packageParts = parsePackageName(packageName);
4910
+ if (packageParts.version) {
4911
+ dependencies2[packageParts.name] = packageParts.version;
3771
4912
  continue;
3772
4913
  } else {
3773
- logger.warn(
3774
- `Could not find version for package ${packageName}, add a version specifier to the package name (e.g. ${packageParts.name}@latest) or add it to your project's package.json`
3775
- );
4914
+ const externalDependencyVersion = await project.resolve(packageParts.name, {
4915
+ allowDev: true
4916
+ });
4917
+ if (externalDependencyVersion) {
4918
+ dependencies2[packageParts.name] = externalDependencyVersion;
4919
+ continue;
4920
+ } else {
4921
+ logger.log(
4922
+ `${chalkWarning("X Warning:")} Could not find version for package ${chalkPurple(
4923
+ packageName
4924
+ )}, add a version specifier to the package name (e.g. ${packageParts.name}@latest) or add it to your project's package.json`
4925
+ );
4926
+ }
3776
4927
  }
3777
4928
  }
3778
4929
  }
3779
- }
3780
- return Object.fromEntries(Object.entries(dependencies2).sort(([a], [b]) => a.localeCompare(b)));
4930
+ if (!dependencies2["@trigger.dev/sdk"]) {
4931
+ logger.debug("Adding missing @trigger.dev/sdk dependency", {
4932
+ version
4933
+ });
4934
+ span.setAttribute("addingMissingSDK", version);
4935
+ dependencies2["@trigger.dev/sdk"] = version;
4936
+ }
4937
+ if (!dependencies2["@trigger.dev/core"]) {
4938
+ logger.debug("Adding missing @trigger.dev/core dependency", {
4939
+ version
4940
+ });
4941
+ span.setAttribute("addingMissingCore", version);
4942
+ dependencies2["@trigger.dev/core"] = version;
4943
+ }
4944
+ const result = Object.fromEntries(
4945
+ Object.entries(dependencies2).sort(([a], [b]) => a.localeCompare(b))
4946
+ );
4947
+ span.setAttributes({
4948
+ ...flattenAttributes3(result, "dependencies")
4949
+ });
4950
+ span.end();
4951
+ return result;
4952
+ });
3781
4953
  }
3782
4954
  async function copyAdditionalFiles(config, tempDir) {
3783
4955
  const additionalFiles = config.additionalFiles ?? [];
4956
+ const noMatches = [];
3784
4957
  if (additionalFiles.length === 0) {
3785
- return;
4958
+ return { ok: true };
3786
4959
  }
3787
4960
  return await tracer.startActiveSpan(
3788
4961
  "copyAdditionalFiles",
@@ -3796,24 +4969,57 @@ async function copyAdditionalFiles(config, tempDir) {
3796
4969
  logger.debug(`Copying files to ${tempDir}`, {
3797
4970
  additionalFiles
3798
4971
  });
3799
- const glob = new Glob(additionalFiles, {
4972
+ const globOptions = {
3800
4973
  withFileTypes: true,
3801
4974
  ignore: ["node_modules"],
3802
4975
  cwd: config.projectDir,
3803
4976
  nodir: true
3804
- });
3805
- for await (const file of glob) {
3806
- const relativeDestinationPath = join4(
3807
- tempDir,
3808
- relative2(config.projectDir, file.fullpath())
3809
- );
3810
- logger.debug(`Copying file ${file.fullpath()} to ${relativeDestinationPath}`);
3811
- await mkdir(dirname(relativeDestinationPath), { recursive: true });
3812
- await copyFile(file.fullpath(), relativeDestinationPath);
4977
+ };
4978
+ const globs = [];
4979
+ let i = 0;
4980
+ for (const additionalFile of additionalFiles) {
4981
+ let glob;
4982
+ if (i === 0) {
4983
+ glob = new Glob(additionalFile, globOptions);
4984
+ } else {
4985
+ const previousGlob = globs[i - 1];
4986
+ if (!previousGlob) {
4987
+ logger.error("No previous glob, this shouldn't happen", { i, additionalFiles });
4988
+ continue;
4989
+ }
4990
+ glob = new Glob(additionalFile, previousGlob);
4991
+ }
4992
+ if (!(Symbol.asyncIterator in glob)) {
4993
+ logger.error("Glob should be an async iterator", { glob });
4994
+ throw new Error("Unrecoverable error while copying additional files");
4995
+ }
4996
+ let matches = 0;
4997
+ for await (const file of glob) {
4998
+ matches++;
4999
+ const pathInsideTempDir = relative3(config.projectDir, file.fullpath()).split(posix.sep).filter((p) => p !== "..").join(posix.sep);
5000
+ const relativeDestinationPath = join6(tempDir, pathInsideTempDir);
5001
+ logger.debug(`Copying file ${file.fullpath()} to ${relativeDestinationPath}`);
5002
+ await mkdir(dirname(relativeDestinationPath), { recursive: true });
5003
+ await copyFile(file.fullpath(), relativeDestinationPath);
5004
+ }
5005
+ if (matches === 0) {
5006
+ noMatches.push(additionalFile);
5007
+ }
5008
+ globs[i] = glob;
5009
+ i++;
3813
5010
  }
3814
5011
  span.end();
5012
+ if (noMatches.length > 0) {
5013
+ return {
5014
+ ok: false,
5015
+ noMatches
5016
+ };
5017
+ }
5018
+ return {
5019
+ ok: true
5020
+ };
3815
5021
  } catch (error) {
3816
- recordSpanException4(span, error);
5022
+ recordSpanException5(span, error);
3817
5023
  span.end();
3818
5024
  throw error;
3819
5025
  }
@@ -3822,7 +5028,7 @@ async function copyAdditionalFiles(config, tempDir) {
3822
5028
  }
3823
5029
  async function ensureLoggedIntoDockerRegistry(registryHost, auth) {
3824
5030
  const tmpDir = await createTempDir();
3825
- const dockerConfigPath = join4(tmpDir, "config.json");
5031
+ const dockerConfigPath = join6(tmpDir, "config.json");
3826
5032
  await writeJSONFile(dockerConfigPath, {
3827
5033
  auths: {
3828
5034
  [registryHost]: {
@@ -3833,43 +5039,20 @@ async function ensureLoggedIntoDockerRegistry(registryHost, auth) {
3833
5039
  logger.debug(`Writing docker config to ${dockerConfigPath}`);
3834
5040
  return tmpDir;
3835
5041
  }
3836
- async function findAllEnvironmentVariableReferencesInFile(filePath) {
3837
- const fileContents = await readFile2(filePath, "utf-8");
3838
- return findAllEnvironmentVariableReferences(fileContents);
3839
- }
3840
- var IGNORED_ENV_VARS = ["NODE_ENV", "SHELL", "HOME", "PWD", "LOGNAME", "USER", "PATH", "DEBUG"];
3841
- function findAllEnvironmentVariableReferences(code) {
3842
- const regex = /\bprocess\.env\.([a-zA-Z_][a-zA-Z0-9_]*)\b/g;
3843
- const matches = code.matchAll(regex);
3844
- const matchesArray = Array.from(matches, (match) => match[1]).filter(Boolean);
3845
- const filteredMatches = matchesArray.filter((match) => !IGNORED_ENV_VARS.includes(match));
3846
- return Array.from(new Set(filteredMatches));
3847
- }
3848
- function arrayToSentence(items) {
3849
- if (items.length === 1 && typeof items[0] === "string") {
3850
- return items[0];
3851
- }
3852
- if (items.length === 2) {
3853
- return `${items[0]} and ${items[1]}`;
3854
- }
3855
- return `${items.slice(0, -1).join(", ")}, and ${items[items.length - 1]}`;
3856
- }
3857
5042
 
3858
5043
  // src/commands/dev.tsx
3859
5044
  import {
3860
- ZodMessageHandler as ZodMessageHandler2,
3861
- ZodMessageSender as ZodMessageSender2,
3862
5045
  clientWebsocketMessages,
3863
5046
  detectDependencyVersion as detectDependencyVersion2,
3864
5047
  serverWebsocketMessages
3865
5048
  } from "@trigger.dev/core/v3";
5049
+ import { ZodMessageHandler as ZodMessageHandler2, ZodMessageSender as ZodMessageSender2 } from "@trigger.dev/core/v3/zodMessageHandler";
3866
5050
  import { watch } from "chokidar";
3867
5051
  import { context as context2 } from "esbuild";
3868
- import { resolve as importResolve2 } from "import-meta-resolve";
3869
5052
  import { render, useInput } from "ink";
3870
5053
  import { createHash as createHash2 } from "node:crypto";
3871
5054
  import fs7, { readFileSync as readFileSync3 } from "node:fs";
3872
- import { basename, dirname as dirname3, join as join5 } from "node:path";
5055
+ import { basename as basename2, dirname as dirname3, join as join7, normalize } from "node:path";
3873
5056
  import pDebounce from "p-debounce";
3874
5057
  import { WebSocket } from "partysocket";
3875
5058
  import React, { Suspense, useEffect } from "react";
@@ -3885,23 +5068,30 @@ var UncaughtExceptionError = class extends Error {
3885
5068
  this.name = "UncaughtExceptionError";
3886
5069
  }
3887
5070
  };
5071
+ var TaskMetadataParseError = class extends Error {
5072
+ constructor(zodIssues, tasks) {
5073
+ super(`Failed to parse task metadata`);
5074
+ this.zodIssues = zodIssues;
5075
+ this.tasks = tasks;
5076
+ this.name = "TaskMetadataParseError";
5077
+ }
5078
+ };
3888
5079
 
3889
5080
  // src/workers/dev/backgroundWorker.ts
3890
5081
  import {
3891
5082
  SemanticInternalAttributes,
3892
5083
  TaskRunErrorCodes,
3893
- ZodMessageHandler,
3894
- ZodMessageSender,
3895
5084
  childToWorkerMessages,
3896
5085
  correctErrorStackTrace,
3897
5086
  formatDurationMilliseconds,
3898
5087
  workerToChildMessages
3899
5088
  } from "@trigger.dev/core/v3";
5089
+ import { ZodMessageHandler, ZodMessageSender } from "@trigger.dev/core/v3/zodMessageHandler";
3900
5090
  import dotenv from "dotenv";
3901
5091
  import { Evt } from "evt";
3902
5092
  import { fork } from "node:child_process";
3903
- import { dirname as dirname2, resolve as resolve2 } from "node:path";
3904
- import terminalLink2 from "terminal-link";
5093
+ import { dirname as dirname2, resolve as resolve3 } from "node:path";
5094
+ import terminalLink3 from "terminal-link";
3905
5095
  var BackgroundWorkerCoordinator = class {
3906
5096
  constructor(baseURL) {
3907
5097
  this.baseURL = baseURL;
@@ -3986,7 +5176,7 @@ var BackgroundWorkerCoordinator = class {
3986
5176
  const logsUrl = `${this.baseURL}/runs/${execution.run.id}`;
3987
5177
  const pipe = chalkGrey("|");
3988
5178
  const bullet = chalkGrey("\u25CB");
3989
- const link = chalkLink(terminalLink2("View logs", logsUrl));
5179
+ const link = chalkLink(terminalLink3("View logs", logsUrl));
3990
5180
  let timestampPrefix = chalkGrey(prettyPrintDate(payload.execution.attempt.startedAt));
3991
5181
  const workerPrefix = chalkWorker(record.version);
3992
5182
  const taskPrefix = chalkTask(execution.task.id);
@@ -4059,8 +5249,8 @@ var CancelledProcessError = class extends Error {
4059
5249
  }
4060
5250
  };
4061
5251
  var BackgroundWorker = class {
4062
- constructor(path6, params) {
4063
- this.path = path6;
5252
+ constructor(path7, params) {
5253
+ this.path = path7;
4064
5254
  this.params = params;
4065
5255
  }
4066
5256
  _initialized = false;
@@ -4094,7 +5284,13 @@ var BackgroundWorker = class {
4094
5284
  await installPackages(this.params.dependencies, { cwd: dirname2(this.path) });
4095
5285
  }
4096
5286
  let resolved = false;
4097
- this.tasks = await new Promise((resolve4, reject) => {
5287
+ const cwd = dirname2(this.path);
5288
+ const fullEnv = {
5289
+ ...this.params.env,
5290
+ ...this.#readEnvVars()
5291
+ };
5292
+ logger.debug("Initializing worker", { path: this.path, cwd, fullEnv });
5293
+ this.tasks = await new Promise((resolve5, reject) => {
4098
5294
  const child = fork(this.path, {
4099
5295
  stdio: [
4100
5296
  /*stdin*/
@@ -4105,10 +5301,8 @@ var BackgroundWorker = class {
4105
5301
  "pipe",
4106
5302
  "ipc"
4107
5303
  ],
4108
- env: {
4109
- ...this.params.env,
4110
- ...this.#readEnvVars()
4111
- }
5304
+ cwd,
5305
+ env: fullEnv
4112
5306
  });
4113
5307
  const timeout = setTimeout(() => {
4114
5308
  if (resolved) {
@@ -4123,13 +5317,18 @@ var BackgroundWorker = class {
4123
5317
  if (message.type === "TASKS_READY" && !resolved) {
4124
5318
  clearTimeout(timeout);
4125
5319
  resolved = true;
4126
- resolve4(message.payload.tasks);
5320
+ resolve5(message.payload.tasks);
4127
5321
  child.kill();
4128
5322
  } else if (message.type === "UNCAUGHT_EXCEPTION") {
4129
5323
  clearTimeout(timeout);
4130
5324
  resolved = true;
4131
5325
  reject(new UncaughtExceptionError(message.payload.error, message.payload.origin));
4132
5326
  child.kill();
5327
+ } else if (message.type === "TASKS_FAILED_TO_PARSE") {
5328
+ clearTimeout(timeout);
5329
+ resolved = true;
5330
+ reject(new TaskMetadataParseError(message.payload.zodIssues, message.payload.tasks));
5331
+ child.kill();
4133
5332
  }
4134
5333
  });
4135
5334
  child.on("exit", (code) => {
@@ -4139,6 +5338,9 @@ var BackgroundWorker = class {
4139
5338
  reject(new Error(`Worker exited with code ${code}`));
4140
5339
  }
4141
5340
  });
5341
+ child.stdout?.on("data", (data) => {
5342
+ logger.log(data.toString());
5343
+ });
4142
5344
  });
4143
5345
  this._initialized = true;
4144
5346
  }
@@ -4155,7 +5357,7 @@ var BackgroundWorker = class {
4155
5357
  }
4156
5358
  if (!this._taskRunProcesses.has(payload.execution.run.id)) {
4157
5359
  const taskRunProcess = new TaskRunProcess(
4158
- payload.execution.run.id,
5360
+ payload.execution,
4159
5361
  this.path,
4160
5362
  {
4161
5363
  ...this.params.env,
@@ -4250,7 +5452,7 @@ var BackgroundWorker = class {
4250
5452
  const result = {};
4251
5453
  dotenv.config({
4252
5454
  processEnv: result,
4253
- path: [".env", ".env.local", ".env.development.local"].map((p) => resolve2(process.cwd(), p))
5455
+ path: [".env", ".env.local", ".env.development.local"].map((p) => resolve3(process.cwd(), p))
4254
5456
  });
4255
5457
  process.env.TRIGGER_API_URL && (result.TRIGGER_API_URL = process.env.TRIGGER_API_URL);
4256
5458
  delete result.TRIGGER_API_URL;
@@ -4265,9 +5467,9 @@ var BackgroundWorker = class {
4265
5467
  }
4266
5468
  };
4267
5469
  var TaskRunProcess = class {
4268
- constructor(runId, path6, env, metadata, worker) {
4269
- this.runId = runId;
4270
- this.path = path6;
5470
+ constructor(execution, path7, env, metadata, worker) {
5471
+ this.execution = execution;
5472
+ this.path = path7;
4271
5473
  this.env = env;
4272
5474
  this.metadata = metadata;
4273
5475
  this.worker = worker;
@@ -4297,9 +5499,20 @@ var TaskRunProcess = class {
4297
5499
  await this.cleanup(true);
4298
5500
  }
4299
5501
  async initialize() {
4300
- logger.debug(`[${this.runId}] initializing task run process`, {
4301
- env: this.env,
4302
- path: this.path
5502
+ const fullEnv = {
5503
+ ...this.execution.run.isTest ? { TRIGGER_LOG_LEVEL: "debug" } : {},
5504
+ ...this.env,
5505
+ OTEL_RESOURCE_ATTRIBUTES: JSON.stringify({
5506
+ [SemanticInternalAttributes.PROJECT_DIR]: this.worker.projectConfig.projectDir
5507
+ }),
5508
+ OTEL_EXPORTER_OTLP_COMPRESSION: "none",
5509
+ ...this.worker.debugOtel ? { OTEL_LOG_LEVEL: "debug" } : {}
5510
+ };
5511
+ const cwd = dirname2(this.path);
5512
+ logger.debug(`[${this.execution.run.id}] initializing task run process`, {
5513
+ env: fullEnv,
5514
+ path: this.path,
5515
+ cwd
4303
5516
  });
4304
5517
  this._child = fork(this.path, {
4305
5518
  stdio: [
@@ -4311,15 +5524,8 @@ var TaskRunProcess = class {
4311
5524
  "pipe",
4312
5525
  "ipc"
4313
5526
  ],
4314
- cwd: dirname2(this.path),
4315
- env: {
4316
- ...this.env,
4317
- OTEL_RESOURCE_ATTRIBUTES: JSON.stringify({
4318
- [SemanticInternalAttributes.PROJECT_DIR]: this.worker.projectConfig.projectDir
4319
- }),
4320
- OTEL_EXPORTER_OTLP_COMPRESSION: "none",
4321
- ...this.worker.debugOtel ? { OTEL_LOG_LEVEL: "debug" } : {}
4322
- },
5527
+ cwd,
5528
+ env: fullEnv,
4323
5529
  execArgv: this.worker.debuggerOn ? ["--inspect-brk", "--trace-uncaught", "--no-warnings=ExperimentalWarning"] : ["--trace-uncaught", "--no-warnings=ExperimentalWarning"]
4324
5530
  });
4325
5531
  this._child.on("message", this.#handleMessage.bind(this));
@@ -4331,18 +5537,24 @@ var TaskRunProcess = class {
4331
5537
  if (kill && this._isBeingKilled) {
4332
5538
  return;
4333
5539
  }
4334
- logger.debug(`[${this.runId}] cleaning up task run process`, { kill });
5540
+ logger.debug(`[${this.execution.run.id}] cleaning up task run process`, { kill });
4335
5541
  await this._sender.send("CLEANUP", {
4336
5542
  flush: true,
4337
5543
  kill
4338
5544
  });
4339
5545
  this._isBeingKilled = kill;
5546
+ setTimeout(() => {
5547
+ if (this._child && !this._child.killed) {
5548
+ logger.debug(`[${this.execution.run.id}] killing task run process after timeout`);
5549
+ this._child.kill();
5550
+ }
5551
+ }, 5e3);
4340
5552
  }
4341
5553
  async executeTaskRun(payload) {
4342
5554
  let resolver;
4343
5555
  let rejecter;
4344
- const promise = new Promise((resolve4, reject) => {
4345
- resolver = resolve4;
5556
+ const promise = new Promise((resolve5, reject) => {
5557
+ resolver = resolve5;
4346
5558
  rejecter = reject;
4347
5559
  });
4348
5560
  this._attemptStatuses.set(payload.execution.attempt.id, "PENDING");
@@ -4362,10 +5574,13 @@ var TaskRunProcess = class {
4362
5574
  if (!completion.ok && typeof completion.retry !== "undefined") {
4363
5575
  return;
4364
5576
  }
4365
- if (execution.run.id === this.runId) {
5577
+ if (execution.run.id === this.execution.run.id) {
4366
5578
  return;
4367
5579
  }
4368
- logger.debug(`[${this.runId}] task run completed notification`, { completion, execution });
5580
+ logger.debug(`[${this.execution.run.id}] task run completed notification`, {
5581
+ completion,
5582
+ execution
5583
+ });
4369
5584
  this._sender.send("TASK_RUN_COMPLETED_NOTIFICATION", {
4370
5585
  completion,
4371
5586
  execution
@@ -4390,6 +5605,7 @@ var TaskRunProcess = class {
4390
5605
  break;
4391
5606
  }
4392
5607
  case "READY_TO_DISPOSE": {
5608
+ logger.debug(`[${this.execution.run.id}] task run process is ready to dispose`);
4393
5609
  this.#kill();
4394
5610
  break;
4395
5611
  }
@@ -4403,7 +5619,7 @@ var TaskRunProcess = class {
4403
5619
  }
4404
5620
  }
4405
5621
  async #handleExit(code) {
4406
- logger.debug(`[${this.runId}] task run process exiting`, { code });
5622
+ logger.debug(`[${this.execution.run.id}] task run process exiting`, { code });
4407
5623
  for (const [id, status] of this._attemptStatuses.entries()) {
4408
5624
  if (status === "PENDING") {
4409
5625
  this._attemptStatuses.set(id, "REJECTED");
@@ -4425,10 +5641,14 @@ var TaskRunProcess = class {
4425
5641
  }
4426
5642
  #handleLog(data) {
4427
5643
  if (!this._currentExecution) {
5644
+ logger.log(`${chalkGrey("\u25CB")} ${chalkGrey(prettyPrintDate(/* @__PURE__ */ new Date()))} ${data.toString()}`);
4428
5645
  return;
4429
5646
  }
5647
+ const runId = chalkRun(
5648
+ `${this._currentExecution.run.id}.${this._currentExecution.attempt.number}`
5649
+ );
4430
5650
  logger.log(
4431
- `[${this.metadata.version}][${this._currentExecution.run.id}.${this._currentExecution.attempt.number}] ${data.toString()}`
5651
+ `${chalkGrey("\u25CB")} ${chalkGrey(prettyPrintDate(/* @__PURE__ */ new Date()))} ${runId} ${data.toString()}`
4432
5652
  );
4433
5653
  }
4434
5654
  #handleStdErr(data) {
@@ -4436,41 +5656,76 @@ var TaskRunProcess = class {
4436
5656
  return;
4437
5657
  }
4438
5658
  if (!this._currentExecution) {
4439
- logger.error(`[${this.metadata.version}] ${data.toString()}`);
5659
+ logger.log(`${chalkError("\u25CB")} ${chalkGrey(prettyPrintDate(/* @__PURE__ */ new Date()))} ${data.toString()}`);
4440
5660
  return;
4441
5661
  }
4442
- logger.error(
4443
- `[${this.metadata.version}][${this._currentExecution.run.id}.${this._currentExecution.attempt.number}] ${data.toString()}`
5662
+ const runId = chalkRun(
5663
+ `${this._currentExecution.run.id}.${this._currentExecution.attempt.number}`
5664
+ );
5665
+ logger.log(
5666
+ `${chalkError("\u25CB")} ${chalkGrey(prettyPrintDate(/* @__PURE__ */ new Date()))} ${runId} ${data.toString()}`
4444
5667
  );
4445
5668
  }
4446
5669
  #kill() {
4447
5670
  if (this._child && !this._child.killed) {
5671
+ logger.debug(`[${this.execution.run.id}] killing task run process`);
4448
5672
  this._child?.kill();
4449
5673
  }
4450
5674
  }
4451
5675
  };
4452
5676
 
5677
+ // src/utilities/runtimeCheck.ts
5678
+ function runtimeCheck(minimumMajor, minimumMinor) {
5679
+ if (typeof process === "undefined") {
5680
+ throw "The dev CLI can only be run in a Node.js compatible environment";
5681
+ }
5682
+ const [major = 0, minor = 0] = process.versions.node.split(".").map(Number);
5683
+ const isBun = typeof process.versions.bun === "string";
5684
+ if (major < minimumMajor || major === minimumMajor && minor < minimumMinor) {
5685
+ if (isBun) {
5686
+ throw `The dev CLI requires at least Node.js ${minimumMajor}.${minimumMinor}. You are running Bun ${process.versions.bun}, which is compatible with Node.js ${process.versions.node}`;
5687
+ } else {
5688
+ throw `The dev CLI requires at least Node.js ${minimumMajor}.${minimumMinor}. You are running Node.js ${process.versions.node}`;
5689
+ }
5690
+ }
5691
+ logger.debug(
5692
+ `Node.js version: ${process.versions.node}${isBun ? ` (Bun ${process.versions.bun})` : ""}`
5693
+ );
5694
+ }
5695
+
4453
5696
  // src/commands/dev.tsx
5697
+ import { findUp as findUp3, pathExists as pathExists2 } from "find-up";
5698
+ import { esbuildDecorators as esbuildDecorators3 } from "@anatine/esbuild-decorators";
4454
5699
  var apiClient;
4455
5700
  var DevCommandOptions = CommonCommandOptions.extend({
4456
5701
  debugger: z5.boolean().default(false),
4457
5702
  debugOtel: z5.boolean().default(false),
4458
5703
  config: z5.string().optional(),
4459
- projectRef: z5.string().optional()
5704
+ projectRef: z5.string().optional(),
5705
+ skipUpdateCheck: z5.boolean().default(false)
4460
5706
  });
4461
5707
  function configureDevCommand(program2) {
4462
5708
  return commonOptions(
4463
- program2.command("dev").description("Run your Trigger.dev tasks locally").argument("[path]", "The path to the project", ".").option("-c, --config <config file>", "The name of the config file, found at [path]").option(
5709
+ program2.command("dev").description("Run your Trigger.dev tasks locally").argument("[path]", "The path to the project", ".").option("-c, --config <config file>", "The name of the config file, found at [path].").option(
4464
5710
  "-p, --project-ref <project ref>",
4465
5711
  "The project ref. Required if there is no config file."
4466
- ).option("--debugger", "Enable the debugger").option("--debug-otel", "Enable OpenTelemetry debugging")
4467
- ).action(async (path6, options) => {
5712
+ ).option("--debugger", "Enable the debugger").option("--debug-otel", "Enable OpenTelemetry debugging").option("--skip-update-check", "Skip checking for @trigger.dev package updates")
5713
+ ).action(async (path7, options) => {
4468
5714
  wrapCommandAction("dev", DevCommandOptions, options, async (opts) => {
4469
- await devCommand(path6, opts);
5715
+ await devCommand(path7, opts);
4470
5716
  });
4471
5717
  });
4472
5718
  }
5719
+ var MINIMUM_NODE_MAJOR = 18;
5720
+ var MINIMUM_NODE_MINOR = 16;
4473
5721
  async function devCommand(dir, options) {
5722
+ try {
5723
+ runtimeCheck(MINIMUM_NODE_MAJOR, MINIMUM_NODE_MINOR);
5724
+ } catch (e) {
5725
+ logger.log(`${chalkError("X Error:")} ${e}`);
5726
+ process.exitCode = 1;
5727
+ return;
5728
+ }
4474
5729
  const authorization = await isLoggedIn(options.profile);
4475
5730
  if (!authorization.ok) {
4476
5731
  if (authorization.error === "fetch failed") {
@@ -4485,40 +5740,48 @@ async function devCommand(dir, options) {
4485
5740
  process.exitCode = 1;
4486
5741
  return;
4487
5742
  }
4488
- const devInstance = await startDev(dir, options, authorization.auth);
5743
+ const devInstance = await startDev(dir, options, authorization.auth, authorization.dashboardUrl);
4489
5744
  const { waitUntilExit } = devInstance.devReactElement;
4490
5745
  await waitUntilExit();
4491
5746
  }
4492
- async function startDev(dir, options, authorization) {
5747
+ async function startDev(dir, options, authorization, dashboardUrl) {
4493
5748
  let rerender;
4494
5749
  try {
4495
5750
  if (options.logLevel) {
4496
5751
  logger.loggerLevel = options.logLevel;
4497
5752
  }
4498
5753
  await printStandloneInitialBanner(true);
4499
- printDevBanner();
5754
+ let displayedUpdateMessage = false;
5755
+ if (!options.skipUpdateCheck) {
5756
+ displayedUpdateMessage = await updateTriggerPackages(dir, { ...options }, true, true);
5757
+ }
5758
+ printDevBanner(displayedUpdateMessage);
4500
5759
  logger.debug("Starting dev session", { dir, options, authorization });
4501
5760
  let config = await readConfig(dir, {
4502
5761
  projectRef: options.projectRef,
4503
5762
  configFile: options.config
4504
5763
  });
4505
5764
  logger.debug("Initial config", { config });
5765
+ if (config.status === "error") {
5766
+ logger.error("Failed to read config", config.error);
5767
+ process.exit(1);
5768
+ }
4506
5769
  async function getDevReactElement(configParam, authorization2, configPath) {
4507
5770
  const accessToken = authorization2.accessToken;
4508
5771
  const apiUrl = authorization2.apiUrl;
4509
5772
  apiClient = new CliApiClient(apiUrl, accessToken);
4510
5773
  const devEnv = await apiClient.getProjectEnv({
4511
- projectRef: config.config.project,
5774
+ projectRef: configParam.project,
4512
5775
  env: "dev"
4513
5776
  });
4514
5777
  if (!devEnv.success) {
4515
5778
  if (devEnv.error === "Project not found") {
4516
5779
  logger.error(
4517
- `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}`
5780
+ `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}`
4518
5781
  );
4519
5782
  } else {
4520
5783
  logger.error(
4521
- `Failed to initialize dev environment: ${devEnv.error}. Using project ref ${config.config.project}`
5784
+ `Failed to initialize dev environment: ${devEnv.error}. Using project ref ${configParam.project}`
4522
5785
  );
4523
5786
  }
4524
5787
  process.exit(1);
@@ -4527,6 +5790,7 @@ async function startDev(dir, options, authorization) {
4527
5790
  return /* @__PURE__ */ React.createElement(
4528
5791
  DevUI,
4529
5792
  {
5793
+ dashboardUrl,
4530
5794
  config: configParam,
4531
5795
  apiUrl,
4532
5796
  apiKey: devEnv.data.apiKey,
@@ -4558,6 +5822,7 @@ async function startDev(dir, options, authorization) {
4558
5822
  }
4559
5823
  function useDev({
4560
5824
  config,
5825
+ dashboardUrl,
4561
5826
  apiUrl,
4562
5827
  apiKey,
4563
5828
  environmentClient,
@@ -4587,7 +5852,7 @@ function useDev({
4587
5852
  }
4588
5853
  });
4589
5854
  const backgroundWorkerCoordinator = new BackgroundWorkerCoordinator(
4590
- `${apiUrl}/projects/v3/${config.project}`
5855
+ `${dashboardUrl}/projects/v3/${config.project}`
4591
5856
  );
4592
5857
  websocket.addEventListener("open", async (event) => {
4593
5858
  });
@@ -4659,22 +5924,21 @@ function useDev({
4659
5924
  }
4660
5925
  let latestWorkerContentHash;
4661
5926
  const taskFiles = await gatherTaskFiles(config);
4662
- const workerFacade = readFileSync3(
4663
- new URL(importResolve2("./workers/dev/worker-facade.js", import.meta.url)).href.replace(
4664
- "file://",
4665
- ""
4666
- ),
4667
- "utf-8"
5927
+ const workerFacadePath = join7(cliRootPath(), "workers", "dev", "worker-facade.js");
5928
+ const workerFacade = readFileSync3(workerFacadePath, "utf-8");
5929
+ const workerSetupPath = join7(cliRootPath(), "workers", "dev", "worker-setup.js");
5930
+ let entryPointContents = workerFacade.replace("__TASKS__", createTaskFileImports(taskFiles)).replace(
5931
+ "__WORKER_SETUP__",
5932
+ `import { tracingSDK, sender } from "${escapeImportPath(workerSetupPath)}";`
4668
5933
  );
4669
- const workerSetupPath = new URL(
4670
- importResolve2("./workers/dev/worker-setup.js", import.meta.url)
4671
- ).href.replace("file://", "");
4672
- let entryPointContents = workerFacade.replace("__TASKS__", createTaskFileImports(taskFiles)).replace("__WORKER_SETUP__", `import { tracingSDK, sender } from "${workerSetupPath}";`);
4673
5934
  if (configPath) {
5935
+ configPath = normalize(configPath);
4674
5936
  logger.debug("Importing project config from", { configPath });
4675
5937
  entryPointContents = entryPointContents.replace(
4676
5938
  "__IMPORTED_PROJECT_CONFIG__",
4677
- `import * as importedConfigExports from "${configPath}"; const importedConfig = importedConfigExports.config; const handleError = importedConfigExports.handleError;`
5939
+ `import * as importedConfigExports from "${escapeImportPath(
5940
+ configPath
5941
+ )}"; const importedConfig = importedConfigExports.config; const handleError = importedConfigExports.handleError;`
4678
5942
  );
4679
5943
  } else {
4680
5944
  entryPointContents = entryPointContents.replace(
@@ -4690,6 +5954,9 @@ function useDev({
4690
5954
  resolveDir: process.cwd(),
4691
5955
  sourcefile: "__entryPoint.ts"
4692
5956
  },
5957
+ banner: {
5958
+ 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" }); } });`
5959
+ },
4693
5960
  bundle: true,
4694
5961
  metafile: true,
4695
5962
  write: false,
@@ -4707,12 +5974,19 @@ function useDev({
4707
5974
  __PROJECT_CONFIG__: JSON.stringify(config)
4708
5975
  },
4709
5976
  plugins: [
5977
+ mockServerOnlyPlugin(),
5978
+ bundleTriggerDevCore("workerFacade", config.tsconfigPath),
4710
5979
  bundleDependenciesPlugin(
4711
5980
  "workerFacade",
4712
5981
  (config.dependenciesToBundle ?? []).concat([/^@trigger.dev/]),
4713
5982
  config.tsconfigPath
4714
5983
  ),
4715
5984
  workerSetupImportConfigPlugin(configPath),
5985
+ esbuildDecorators3({
5986
+ tsconfig: config.tsconfigPath,
5987
+ tsx: true,
5988
+ force: false
5989
+ }),
4716
5990
  {
4717
5991
  name: "trigger.dev v3",
4718
5992
  setup(build3) {
@@ -4726,19 +6000,19 @@ function useDev({
4726
6000
  if (!firstBuild) {
4727
6001
  logger.log(chalkGrey("\u25CB Building background worker\u2026"));
4728
6002
  }
4729
- const metaOutputKey = join5("out", `stdin.js`);
6003
+ const metaOutputKey = join7("out", `stdin.js`).replace(/\\/g, "/");
4730
6004
  const metaOutput = result.metafile.outputs[metaOutputKey];
4731
6005
  if (!metaOutput) {
4732
6006
  throw new Error(`Could not find metafile`);
4733
6007
  }
4734
- const outputFileKey = join5(config.projectDir, metaOutputKey);
6008
+ const outputFileKey = join7(config.projectDir, metaOutputKey);
4735
6009
  const outputFile = result.outputFiles.find((file) => file.path === outputFileKey);
4736
6010
  if (!outputFile) {
4737
6011
  throw new Error(
4738
6012
  `Could not find output file for entry point ${metaOutput.entryPoint}`
4739
6013
  );
4740
6014
  }
4741
- const sourceMapFileKey = join5(config.projectDir, `${metaOutputKey}.map`);
6015
+ const sourceMapFileKey = join7(config.projectDir, `${metaOutputKey}.map`);
4742
6016
  const sourceMapFile = result.outputFiles.find(
4743
6017
  (file) => file.path === sourceMapFileKey
4744
6018
  );
@@ -4749,20 +6023,20 @@ function useDev({
4749
6023
  logger.log(chalkGrey("\u25CB No changes detected, skipping build\u2026"));
4750
6024
  return;
4751
6025
  }
4752
- const fullPath = join5(config.projectDir, ".trigger", `${contentHash}.js`);
6026
+ const fullPath = join7(config.projectDir, ".trigger", `${contentHash}.js`);
4753
6027
  const sourceMapPath = `${fullPath}.map`;
4754
6028
  const outputFileWithSourceMap = `${outputFile.text}
4755
- //# sourceMappingURL=${basename(sourceMapPath)}`;
6029
+ //# sourceMappingURL=${basename2(sourceMapPath)}`;
4756
6030
  await fs7.promises.mkdir(dirname3(fullPath), { recursive: true });
4757
6031
  await fs7.promises.writeFile(fullPath, outputFileWithSourceMap);
4758
6032
  logger.debug(`Wrote background worker to ${fullPath}`);
4759
- const dependencies2 = await gatherRequiredDependencies2(metaOutput, config);
6033
+ const dependencies2 = await gatherRequiredDependencies(metaOutput, config);
4760
6034
  if (sourceMapFile) {
4761
6035
  const sourceMapPath2 = `${fullPath}.map`;
4762
6036
  await fs7.promises.writeFile(sourceMapPath2, sourceMapFile.text);
4763
6037
  }
4764
6038
  const environmentVariablesResponse = await environmentClient.getEnvironmentVariables(config.project);
4765
- const processEnv = gatherProcessEnv();
6039
+ const processEnv = await gatherProcessEnv();
4766
6040
  const backgroundWorker = new BackgroundWorker(fullPath, {
4767
6041
  projectConfig: config,
4768
6042
  dependencies: dependencies2,
@@ -4780,8 +6054,15 @@ function useDev({
4780
6054
  latestWorkerContentHash = contentHash;
4781
6055
  let packageVersion;
4782
6056
  const taskResources = [];
4783
- if (!backgroundWorker.tasks) {
4784
- throw new Error(`Background Worker started without tasks`);
6057
+ if (!backgroundWorker.tasks || backgroundWorker.tasks.length === 0) {
6058
+ logger.log(
6059
+ `${chalkError(
6060
+ "X Error:"
6061
+ )} Worker failed to build: no tasks found. Searched in ${config.triggerDirectories.join(
6062
+ ", "
6063
+ )}`
6064
+ );
6065
+ return;
4785
6066
  }
4786
6067
  for (const task of backgroundWorker.tasks) {
4787
6068
  taskResources.push(task);
@@ -4800,6 +6081,9 @@ function useDev({
4800
6081
  );
4801
6082
  return;
4802
6083
  }
6084
+ logger.debug("Creating background worker with tasks", {
6085
+ tasks: taskResources
6086
+ });
4803
6087
  const backgroundWorkerBody = {
4804
6088
  localOnly: true,
4805
6089
  metadata: {
@@ -4830,17 +6114,52 @@ function useDev({
4830
6114
  backgroundWorker
4831
6115
  );
4832
6116
  } catch (e) {
4833
- if (e instanceof UncaughtExceptionError) {
4834
- if (e.originalError.stack) {
4835
- logger.error("Background worker failed to start", e.originalError.stack);
6117
+ if (e instanceof TaskMetadataParseError) {
6118
+ logTaskMetadataParseError(e.zodIssues, e.tasks);
6119
+ return;
6120
+ } else if (e instanceof UncaughtExceptionError) {
6121
+ const parsedBuildError = parseBuildErrorStack(e.originalError);
6122
+ if (parsedBuildError && typeof parsedBuildError !== "string") {
6123
+ logESMRequireError(
6124
+ parsedBuildError,
6125
+ configPath ? { status: "file", path: configPath, config } : { status: "in-memory", config }
6126
+ );
6127
+ return;
6128
+ } else {
6129
+ }
6130
+ if (e.originalError.message || e.originalError.stack) {
6131
+ logger.log(
6132
+ `${chalkError("X Error:")} Worker failed to start`,
6133
+ e.originalError.stack ?? e.originalError.message
6134
+ );
4836
6135
  }
4837
6136
  return;
4838
6137
  }
4839
- if (e instanceof Error) {
4840
- logger.error(`Background worker failed to start`, e.stack);
4841
- return;
6138
+ const parsedError = parseNpmInstallError(e);
6139
+ if (typeof parsedError === "string") {
6140
+ logger.log(`${chalkError("X Error:")} ${parsedError}`);
6141
+ } else {
6142
+ switch (parsedError.type) {
6143
+ case "package-not-found-error": {
6144
+ logger.log(
6145
+ `
6146
+ ${chalkError("X Error:")} The package ${chalkPurple(
6147
+ parsedError.packageName
6148
+ )} could not be found in the npm registry.`
6149
+ );
6150
+ break;
6151
+ }
6152
+ case "no-matching-version-error": {
6153
+ logger.log(
6154
+ `
6155
+ ${chalkError("X Error:")} The package ${chalkPurple(
6156
+ parsedError.packageName
6157
+ )} could not resolve because the version doesn't exist`
6158
+ );
6159
+ break;
6160
+ }
6161
+ }
4842
6162
  }
4843
- logger.error(`Background worker failed to start: ${e}`);
4844
6163
  }
4845
6164
  });
4846
6165
  }
@@ -4851,17 +6170,17 @@ function useDev({
4851
6170
  }
4852
6171
  const throttledRebuild = pDebounce(runBuild, 250, { before: true });
4853
6172
  const taskFileWatcher = watch(
4854
- config.triggerDirectories.map((triggerDir) => `${triggerDir}/*.ts`),
6173
+ config.triggerDirectories.map((triggerDir) => `${triggerDir}/**/*.ts`),
4855
6174
  {
4856
6175
  ignoreInitial: true
4857
6176
  }
4858
6177
  );
4859
- taskFileWatcher.on("add", async (path6) => {
6178
+ taskFileWatcher.on("add", async (path7) => {
4860
6179
  throttledRebuild().catch((error) => {
4861
6180
  logger.error(error);
4862
6181
  });
4863
6182
  });
4864
- taskFileWatcher.on("unlink", async (path6) => {
6183
+ taskFileWatcher.on("unlink", async (path7) => {
4865
6184
  throttledRebuild().catch((error) => {
4866
6185
  logger.error(error);
4867
6186
  });
@@ -4902,7 +6221,7 @@ function WebsocketFactory(apiKey) {
4902
6221
  }
4903
6222
  };
4904
6223
  }
4905
- async function gatherRequiredDependencies2(outputMeta, config) {
6224
+ async function gatherRequiredDependencies(outputMeta, config) {
4906
6225
  const dependencies2 = {};
4907
6226
  logger.debug("Gathering required dependencies from imports", {
4908
6227
  imports: outputMeta.imports
@@ -4921,7 +6240,7 @@ async function gatherRequiredDependencies2(outputMeta, config) {
4921
6240
  }
4922
6241
  }
4923
6242
  if (config.additionalPackages) {
4924
- const projectPackageJson = await readJSONFile(join5(config.projectDir, "package.json"));
6243
+ const projectPackageJson = await readJSONFile(join7(config.projectDir, "package.json"));
4925
6244
  for (const packageName of config.additionalPackages) {
4926
6245
  if (dependencies2[packageName]) {
4927
6246
  continue;
@@ -4958,7 +6277,7 @@ ${task.filePath} -> ${task.exportName}`).join("")}`;
4958
6277
  }).join("");
4959
6278
  return `Duplicate ${chalkTask("task id")} detected:${duplicateTable}`;
4960
6279
  }
4961
- function gatherProcessEnv() {
6280
+ async function gatherProcessEnv() {
4962
6281
  const env = {
4963
6282
  NODE_ENV: process.env.NODE_ENV ?? "development",
4964
6283
  PATH: process.env.PATH,
@@ -4969,31 +6288,54 @@ function gatherProcessEnv() {
4969
6288
  NVM_BIN: process.env.NVM_BIN,
4970
6289
  LANG: process.env.LANG,
4971
6290
  TERM: process.env.TERM,
4972
- NODE_PATH: process.env.NODE_PATH,
6291
+ NODE_PATH: await amendNodePathWithPnpmNodeModules(process.env.NODE_PATH),
4973
6292
  HOME: process.env.HOME,
4974
6293
  BUN_INSTALL: process.env.BUN_INSTALL
4975
6294
  };
4976
6295
  return Object.fromEntries(Object.entries(env).filter(([key, value]) => value !== void 0));
4977
6296
  }
6297
+ async function amendNodePathWithPnpmNodeModules(nodePath) {
6298
+ const pnpmModulesPath = await findPnpmNodeModulesPath();
6299
+ if (!pnpmModulesPath) {
6300
+ return nodePath;
6301
+ }
6302
+ if (nodePath) {
6303
+ if (nodePath.includes(pnpmModulesPath)) {
6304
+ return nodePath;
6305
+ }
6306
+ return `${nodePath}:${pnpmModulesPath}`;
6307
+ }
6308
+ return pnpmModulesPath;
6309
+ }
6310
+ async function findPnpmNodeModulesPath() {
6311
+ return await findUp3(
6312
+ async (directory) => {
6313
+ const pnpmModules = join7(directory, "node_modules", ".pnpm", "node_modules");
6314
+ const hasPnpmNodeModules = await pathExists2(pnpmModules);
6315
+ if (hasPnpmNodeModules) {
6316
+ return pnpmModules;
6317
+ }
6318
+ },
6319
+ { type: "directory" }
6320
+ );
6321
+ }
4978
6322
 
4979
6323
  // src/commands/init.ts
4980
- import { intro as intro4, isCancel, log as log3, outro as outro4, select as select2, spinner as spinner5, text } from "@clack/prompts";
6324
+ import { intro as intro5, isCancel as isCancel2, log as log6, outro as outro6, select as select2, text } from "@clack/prompts";
4981
6325
  import { context as context3, trace as trace3 } from "@opentelemetry/api";
4982
- import {
4983
- flattenAttributes as flattenAttributes3,
4984
- recordSpanException as recordSpanException5
4985
- } from "@trigger.dev/core/v3";
6326
+ import { flattenAttributes as flattenAttributes4 } from "@trigger.dev/core/v3";
6327
+ import { recordSpanException as recordSpanException6 } from "@trigger.dev/core/v3/workers";
4986
6328
  import chalk5 from "chalk";
4987
6329
  import { execa as execa3 } from "execa";
4988
6330
  import { applyEdits, modify } from "jsonc-parser";
4989
6331
  import { writeFile as writeFile3 } from "node:fs/promises";
4990
- import { join as join6, relative as relative3, resolve as resolve3 } from "node:path";
4991
- import terminalLink3 from "terminal-link";
6332
+ import { join as join8, relative as relative4, resolve as resolve4 } from "node:path";
6333
+ import terminalLink4 from "terminal-link";
4992
6334
  import { z as z6 } from "zod";
4993
6335
 
4994
6336
  // src/utilities/createFileFromTemplate.ts
4995
6337
  import fs8 from "fs/promises";
4996
- import path5 from "path";
6338
+ import path6 from "path";
4997
6339
  async function createFileFromTemplate(params) {
4998
6340
  let template = await readFile(params.templatePath);
4999
6341
  if (await pathExists(params.outputPath) && !params.override) {
@@ -5004,7 +6346,7 @@ async function createFileFromTemplate(params) {
5004
6346
  }
5005
6347
  try {
5006
6348
  const output = replaceAll(template, params.replacements);
5007
- const directoryName = path5.dirname(params.outputPath);
6349
+ const directoryName = path6.dirname(params.outputPath);
5008
6350
  await fs8.mkdir(directoryName, { recursive: true });
5009
6351
  await fs8.writeFile(params.outputPath, output);
5010
6352
  return {
@@ -5032,51 +6374,6 @@ function replaceAll(input, replacements) {
5032
6374
  return output;
5033
6375
  }
5034
6376
 
5035
- // src/utilities/getUserPackageManager.ts
5036
- import pathModule2 from "path";
5037
- async function getUserPackageManager(path6) {
5038
- try {
5039
- return await detectPackageManagerFromArtifacts(path6);
5040
- } catch (error) {
5041
- return detectPackageManagerFromCurrentCommand();
5042
- }
5043
- }
5044
- function detectPackageManagerFromCurrentCommand() {
5045
- const userAgent = process.env.npm_config_user_agent;
5046
- if (userAgent) {
5047
- if (userAgent.startsWith("yarn")) {
5048
- return "yarn";
5049
- } else if (userAgent.startsWith("pnpm")) {
5050
- return "pnpm";
5051
- } else {
5052
- return "npm";
5053
- }
5054
- } else {
5055
- return "npm";
5056
- }
5057
- }
5058
- async function detectPackageManagerFromArtifacts(path6) {
5059
- const packageFiles = [
5060
- { name: "yarn.lock", pm: "yarn" },
5061
- { name: "pnpm-lock.yaml", pm: "pnpm" },
5062
- { name: "package-lock.json", pm: "npm" },
5063
- { name: "npm-shrinkwrap.json", pm: "npm" }
5064
- ];
5065
- for (const { name, pm } of packageFiles) {
5066
- const exists = await pathExists(pathModule2.join(path6, name));
5067
- if (exists) {
5068
- return pm;
5069
- }
5070
- }
5071
- throw new Error("Could not detect package manager from artifacts");
5072
- }
5073
-
5074
- // src/utilities/resolveInternalFilePath.ts
5075
- import { resolve as importResolve3 } from "import-meta-resolve";
5076
- function resolveInternalFilePath(filePath) {
5077
- return new URL(importResolve3(filePath, import.meta.url)).href.replace("file://", "");
5078
- }
5079
-
5080
6377
  // src/commands/init.ts
5081
6378
  var InitCommandOptions = CommonCommandOptions.extend({
5082
6379
  projectRef: z6.string().optional(),
@@ -5094,10 +6391,10 @@ function configureInitCommand(program2) {
5094
6391
  "The version of the @trigger.dev/sdk package to install",
5095
6392
  "beta"
5096
6393
  ).option("--skip-package-install", "Skip installing the @trigger.dev/sdk package").option("--override-config", "Override the existing config file if it exists")
5097
- ).action(async (path6, options) => {
6394
+ ).action(async (path7, options) => {
5098
6395
  await handleTelemetry(async () => {
5099
6396
  await printStandloneInitialBanner(true);
5100
- await initCommand(path6, options);
6397
+ await initCommand(path7, options);
5101
6398
  });
5102
6399
  });
5103
6400
  }
@@ -5108,7 +6405,7 @@ async function initCommand(dir, options) {
5108
6405
  }
5109
6406
  async function _initCommand(dir, options) {
5110
6407
  const span = trace3.getSpan(context3.active());
5111
- intro4("Initializing project");
6408
+ intro5("Initializing project");
5112
6409
  const authorization = await login({
5113
6410
  embedded: true,
5114
6411
  defaultApiUrl: options.apiUrl,
@@ -5132,7 +6429,7 @@ async function _initCommand(dir, options) {
5132
6429
  if (!options.overrideConfig) {
5133
6430
  try {
5134
6431
  const result = await readConfig(dir);
5135
- outro4(
6432
+ outro6(
5136
6433
  result.status === "file" ? `Project already initialized: Found config file at ${result.path}. Pass --override-config to override` : "Project already initialized"
5137
6434
  );
5138
6435
  return;
@@ -5146,58 +6443,59 @@ async function _initCommand(dir, options) {
5146
6443
  options.projectRef
5147
6444
  );
5148
6445
  span?.setAttributes({
5149
- ...flattenAttributes3(selectedProject, "cli.project")
6446
+ ...flattenAttributes4(selectedProject, "cli.project")
5150
6447
  });
5151
6448
  logger.debug("Selected project", selectedProject);
5152
- log3.step(`Configuring project "${selectedProject.name}" (${selectedProject.externalRef})`);
6449
+ log6.step(`Configuring project "${selectedProject.name}" (${selectedProject.externalRef})`);
5153
6450
  if (!options.skipPackageInstall) {
5154
6451
  await installPackages2(dir, options);
5155
6452
  } else {
5156
- log3.info("Skipping package installation");
6453
+ log6.info("Skipping package installation");
5157
6454
  }
5158
6455
  const triggerDir = await createTriggerDir(dir, options);
5159
6456
  await writeConfigFile(dir, selectedProject, options, triggerDir);
5160
6457
  await addConfigFileToTsConfig(dir, options);
5161
6458
  await gitIgnoreDotTriggerDir(dir, options);
5162
- const projectDashboard = terminalLink3(
6459
+ const projectDashboard = terminalLink4(
5163
6460
  "project dashboard",
5164
6461
  `${authorization.dashboardUrl}/projects/v3/${selectedProject.externalRef}`
5165
6462
  );
5166
- log3.success("Successfully initialized project for Trigger.dev v3 \u{1FAE1}");
5167
- log3.info("Next steps:");
5168
- log3.info(
6463
+ log6.success("Successfully initialized project for Trigger.dev v3 \u{1FAE1}");
6464
+ log6.info("Next steps:");
6465
+ log6.info(
5169
6466
  ` 1. To start developing, run ${chalk5.green(
5170
6467
  `npx trigger.dev@${options.tag} dev`
5171
6468
  )} in your project directory`
5172
6469
  );
5173
- log3.info(` 2. Visit your ${projectDashboard} to view your newly created tasks.`);
5174
- log3.info(
5175
- ` 3. Head over to our ${terminalLink3(
6470
+ log6.info(` 2. Visit your ${projectDashboard} to view your newly created tasks.`);
6471
+ log6.info(
6472
+ ` 3. Head over to our ${terminalLink4(
5176
6473
  "v3 docs",
5177
6474
  "https://trigger.dev/docs/v3"
5178
6475
  )} to learn more.`
5179
6476
  );
5180
- log3.info(
5181
- ` 4. Need help? Join our ${terminalLink3(
6477
+ log6.info(
6478
+ ` 4. Need help? Join our ${terminalLink4(
5182
6479
  "Discord community",
5183
6480
  "https://trigger.dev/discord"
5184
6481
  )} or email us at ${chalk5.cyan("help@trigger.dev")}`
5185
6482
  );
5186
- outro4(`Project initialized successfully. Happy coding!`);
6483
+ outro6(`Project initialized successfully. Happy coding!`);
5187
6484
  }
5188
6485
  async function createTriggerDir(dir, options) {
5189
6486
  return await tracer.startActiveSpan("createTriggerDir", async (span) => {
5190
6487
  try {
5191
- const defaultValue = `${dir}/src/trigger`;
6488
+ const defaultValue = join8(dir, "src", "trigger");
5192
6489
  const location = await text({
5193
6490
  message: "Where would you like to create the Trigger.dev directory?",
5194
6491
  defaultValue,
5195
6492
  placeholder: defaultValue
5196
6493
  });
5197
- if (isCancel(location)) {
6494
+ if (isCancel2(location)) {
5198
6495
  throw new OutroCommandError();
5199
6496
  }
5200
- const triggerDir = resolve3(process.cwd(), location);
6497
+ const triggerDir = resolve4(process.cwd(), location);
6498
+ logger.debug({ triggerDir });
5201
6499
  span.setAttributes({
5202
6500
  "cli.triggerDir": triggerDir
5203
6501
  });
@@ -5215,7 +6513,7 @@ async function createTriggerDir(dir, options) {
5215
6513
  }
5216
6514
  ]
5217
6515
  });
5218
- if (isCancel(exampleSelection)) {
6516
+ if (isCancel2(exampleSelection)) {
5219
6517
  throw new OutroCommandError();
5220
6518
  }
5221
6519
  const example = exampleSelection;
@@ -5223,25 +6521,25 @@ async function createTriggerDir(dir, options) {
5223
6521
  "cli.example": example
5224
6522
  });
5225
6523
  if (example === "none") {
5226
- await createFile(join6(triggerDir, ".gitkeep"), "");
5227
- log3.step(`Created directory at ${location}`);
6524
+ await createFile(join8(triggerDir, ".gitkeep"), "");
6525
+ log6.step(`Created directory at ${location}`);
5228
6526
  span.end();
5229
6527
  return { location, isCustomValue: location !== defaultValue };
5230
6528
  }
5231
- const exampleFile = resolveInternalFilePath(`./templates/examples/${example}.ts.template`);
5232
- const outputPath = join6(triggerDir, "example.ts");
6529
+ const templatePath = join8(cliRootPath(), "templates", "examples", `${example}.ts.template`);
6530
+ const outputPath = join8(triggerDir, "example.ts");
5233
6531
  await createFileFromTemplate({
5234
- templatePath: exampleFile,
6532
+ templatePath,
5235
6533
  outputPath,
5236
6534
  replacements: {}
5237
6535
  });
5238
- const relativeOutputPath = relative3(process.cwd(), outputPath);
5239
- log3.step(`Created example file at ${relativeOutputPath}`);
6536
+ const relativeOutputPath = relative4(process.cwd(), outputPath);
6537
+ log6.step(`Created example file at ${relativeOutputPath}`);
5240
6538
  span.end();
5241
6539
  return { location, isCustomValue: location !== defaultValue };
5242
6540
  } catch (e) {
5243
6541
  if (!(e instanceof SkipCommandError)) {
5244
- recordSpanException5(span, e);
6542
+ recordSpanException6(span, e);
5245
6543
  }
5246
6544
  span.end();
5247
6545
  throw e;
@@ -5251,15 +6549,15 @@ async function createTriggerDir(dir, options) {
5251
6549
  async function gitIgnoreDotTriggerDir(dir, options) {
5252
6550
  return await tracer.startActiveSpan("gitIgnoreDotTriggerDir", async (span) => {
5253
6551
  try {
5254
- const projectDir = resolve3(process.cwd(), dir);
5255
- const gitIgnorePath = join6(projectDir, ".gitignore");
6552
+ const projectDir = resolve4(process.cwd(), dir);
6553
+ const gitIgnorePath = join8(projectDir, ".gitignore");
5256
6554
  span.setAttributes({
5257
6555
  "cli.projectDir": projectDir,
5258
6556
  "cli.gitIgnorePath": gitIgnorePath
5259
6557
  });
5260
6558
  if (!await pathExists(gitIgnorePath)) {
5261
6559
  await createFile(gitIgnorePath, ".trigger");
5262
- log3.step(`Added .trigger to .gitignore`);
6560
+ log6.step(`Added .trigger to .gitignore`);
5263
6561
  span.end();
5264
6562
  return;
5265
6563
  }
@@ -5271,11 +6569,11 @@ async function gitIgnoreDotTriggerDir(dir, options) {
5271
6569
  const newGitIgnoreContent = `${gitIgnoreContent}
5272
6570
  .trigger`;
5273
6571
  await writeFile3(gitIgnorePath, newGitIgnoreContent, "utf-8");
5274
- log3.step(`Added .trigger to .gitignore`);
6572
+ log6.step(`Added .trigger to .gitignore`);
5275
6573
  span.end();
5276
6574
  } catch (e) {
5277
6575
  if (!(e instanceof SkipCommandError)) {
5278
- recordSpanException5(span, e);
6576
+ recordSpanException6(span, e);
5279
6577
  }
5280
6578
  span.end();
5281
6579
  throw e;
@@ -5285,8 +6583,8 @@ async function gitIgnoreDotTriggerDir(dir, options) {
5285
6583
  async function addConfigFileToTsConfig(dir, options) {
5286
6584
  return await tracer.startActiveSpan("createTriggerDir", async (span) => {
5287
6585
  try {
5288
- const projectDir = resolve3(process.cwd(), dir);
5289
- const tsconfigPath = join6(projectDir, "tsconfig.json");
6586
+ const projectDir = resolve4(process.cwd(), dir);
6587
+ const tsconfigPath = join8(projectDir, "tsconfig.json");
5290
6588
  span.setAttributes({
5291
6589
  "cli.projectDir": projectDir,
5292
6590
  "cli.tsconfigPath": tsconfigPath
@@ -5304,11 +6602,11 @@ async function addConfigFileToTsConfig(dir, options) {
5304
6602
  const newTsconfigContent = applyEdits(tsconfigContent, edits);
5305
6603
  logger.debug("new tsconfig.json content", { newTsconfigContent });
5306
6604
  await writeFile3(tsconfigPath, newTsconfigContent, "utf-8");
5307
- log3.step(`Added trigger.config.ts to tsconfig.json`);
6605
+ log6.step(`Added trigger.config.ts to tsconfig.json`);
5308
6606
  span.end();
5309
6607
  } catch (e) {
5310
6608
  if (!(e instanceof SkipCommandError)) {
5311
- recordSpanException5(span, e);
6609
+ recordSpanException6(span, e);
5312
6610
  }
5313
6611
  span.end();
5314
6612
  throw e;
@@ -5317,9 +6615,9 @@ async function addConfigFileToTsConfig(dir, options) {
5317
6615
  }
5318
6616
  async function installPackages2(dir, options) {
5319
6617
  return await tracer.startActiveSpan("installPackages", async (span) => {
5320
- const installSpinner = spinner5();
6618
+ const installSpinner = spinner();
5321
6619
  try {
5322
- const projectDir = resolve3(process.cwd(), dir);
6620
+ const projectDir = resolve4(process.cwd(), dir);
5323
6621
  const pkgManager = await getUserPackageManager(projectDir);
5324
6622
  span.setAttributes({
5325
6623
  "cli.projectDir": projectDir,
@@ -5359,7 +6657,7 @@ async function installPackages2(dir, options) {
5359
6657
  `Failed to install @trigger.dev/sdk@${options.tag}. Rerun command with --log-level debug for more details.`
5360
6658
  );
5361
6659
  if (!(e instanceof SkipCommandError)) {
5362
- recordSpanException5(span, e);
6660
+ recordSpanException6(span, e);
5363
6661
  }
5364
6662
  span.end();
5365
6663
  throw e;
@@ -5369,11 +6667,11 @@ async function installPackages2(dir, options) {
5369
6667
  async function writeConfigFile(dir, project, options, triggerDir) {
5370
6668
  return await tracer.startActiveSpan("writeConfigFile", async (span) => {
5371
6669
  try {
5372
- const spnnr = spinner5();
6670
+ const spnnr = spinner();
5373
6671
  spnnr.start("Creating config file");
5374
- const projectDir = resolve3(process.cwd(), dir);
5375
- const templatePath = resolveInternalFilePath("./templates/trigger.config.ts.template");
5376
- const outputPath = join6(projectDir, "trigger.config.ts");
6672
+ const projectDir = resolve4(process.cwd(), dir);
6673
+ const templatePath = join8(cliRootPath(), "templates", "trigger.config.ts.template");
6674
+ const outputPath = join8(projectDir, "trigger.config.ts");
5377
6675
  span.setAttributes({
5378
6676
  "cli.projectDir": projectDir,
5379
6677
  "cli.templatePath": templatePath,
@@ -5389,7 +6687,7 @@ async function writeConfigFile(dir, project, options, triggerDir) {
5389
6687
  outputPath,
5390
6688
  override: options.overrideConfig
5391
6689
  });
5392
- const relativePathToOutput = relative3(process.cwd(), outputPath);
6690
+ const relativePathToOutput = relative4(process.cwd(), outputPath);
5393
6691
  spnnr.stop(
5394
6692
  result.success ? `Config file created at ${relativePathToOutput}` : `Failed to create config file: ${result.error}`
5395
6693
  );
@@ -5400,7 +6698,7 @@ async function writeConfigFile(dir, project, options, triggerDir) {
5400
6698
  return result.success;
5401
6699
  } catch (e) {
5402
6700
  if (!(e instanceof SkipCommandError)) {
5403
- recordSpanException5(span, e);
6701
+ recordSpanException6(span, e);
5404
6702
  }
5405
6703
  span.end();
5406
6704
  throw e;
@@ -5413,13 +6711,13 @@ async function selectProject(apiClient2, dashboardUrl, projectRef) {
5413
6711
  if (projectRef) {
5414
6712
  const projectResponse = await apiClient2.getProject(projectRef);
5415
6713
  if (!projectResponse.success) {
5416
- log3.error(
6714
+ log6.error(
5417
6715
  `--project-ref ${projectRef} is not a valid project ref. Request to fetch data resulted in: ${projectResponse.error}`
5418
6716
  );
5419
6717
  throw new SkipCommandError(projectResponse.error);
5420
6718
  }
5421
6719
  span.setAttributes({
5422
- ...flattenAttributes3(projectResponse.data, "cli.project")
6720
+ ...flattenAttributes4(projectResponse.data, "cli.project")
5423
6721
  });
5424
6722
  span.end();
5425
6723
  return projectResponse.data;
@@ -5429,11 +6727,11 @@ async function selectProject(apiClient2, dashboardUrl, projectRef) {
5429
6727
  throw new Error(`Failed to get projects: ${projectsResponse.error}`);
5430
6728
  }
5431
6729
  if (projectsResponse.data.length === 0) {
5432
- const newProjectLink = terminalLink3(
6730
+ const newProjectLink = terminalLink4(
5433
6731
  "Create new project",
5434
6732
  `${dashboardUrl}/projects/new?version=v3`
5435
6733
  );
5436
- outro4(`You don't have any projects yet. ${newProjectLink}`);
6734
+ outro6(`You don't have any projects yet. ${newProjectLink}`);
5437
6735
  throw new SkipCommandError();
5438
6736
  }
5439
6737
  const selectedProject = await select2({
@@ -5444,7 +6742,7 @@ async function selectProject(apiClient2, dashboardUrl, projectRef) {
5444
6742
  hint: project.organization.title
5445
6743
  }))
5446
6744
  });
5447
- if (isCancel(selectedProject)) {
6745
+ if (isCancel2(selectedProject)) {
5448
6746
  throw new OutroCommandError();
5449
6747
  }
5450
6748
  const projectData = projectsResponse.data.find(
@@ -5454,13 +6752,13 @@ async function selectProject(apiClient2, dashboardUrl, projectRef) {
5454
6752
  throw new Error("Invalid project ref");
5455
6753
  }
5456
6754
  span.setAttributes({
5457
- ...flattenAttributes3(projectData, "cli.project")
6755
+ ...flattenAttributes4(projectData, "cli.project")
5458
6756
  });
5459
6757
  span.end();
5460
6758
  return projectData;
5461
6759
  } catch (e) {
5462
6760
  if (!(e instanceof SkipCommandError)) {
5463
- recordSpanException5(span, e);
6761
+ recordSpanException6(span, e);
5464
6762
  }
5465
6763
  span.end();
5466
6764
  throw e;
@@ -5471,12 +6769,14 @@ async function selectProject(apiClient2, dashboardUrl, projectRef) {
5471
6769
  // src/commands/logout.ts
5472
6770
  var LogoutCommandOptions = CommonCommandOptions;
5473
6771
  function configureLogoutCommand(program2) {
5474
- return commonOptions(program2.command("logout").description("Logout of Trigger.dev")).action(async (options) => {
5475
- await handleTelemetry(async () => {
5476
- await printInitialBanner(false);
5477
- await logoutCommand(options);
5478
- });
5479
- });
6772
+ return commonOptions(program2.command("logout").description("Logout of Trigger.dev")).action(
6773
+ async (options) => {
6774
+ await handleTelemetry(async () => {
6775
+ await printInitialBanner(false);
6776
+ await logoutCommand(options);
6777
+ });
6778
+ }
6779
+ );
5480
6780
  }
5481
6781
  async function logoutCommand(options) {
5482
6782
  return await wrapCommandAction("logoutCommand", LogoutCommandOptions, options, async (opts) => {
@@ -5486,11 +6786,46 @@ async function logoutCommand(options) {
5486
6786
  async function logout(options) {
5487
6787
  const config = readAuthConfigProfile(options.profile);
5488
6788
  if (!config?.accessToken) {
5489
- logger.info(`You are already logged out [${options.profile ?? "default"}]`);
6789
+ logger.info(`You are already logged out [${options.profile}]`);
6790
+ return;
6791
+ }
6792
+ deleteAuthConfigProfile(options.profile);
6793
+ logger.info(`Logged out of Trigger.dev [${options.profile}]`);
6794
+ }
6795
+
6796
+ // src/commands/list-profiles.ts
6797
+ import { log as log7, outro as outro7 } from "@clack/prompts";
6798
+ var ListProfilesOptions = CommonCommandOptions;
6799
+ function configureListProfilesCommand(program2) {
6800
+ return program2.command("list-profiles").description("List all of your CLI profiles").option(
6801
+ "-l, --log-level <level>",
6802
+ "The CLI log level to use (debug, info, log, warn, error, none). This does not effect the log level of your trigger.dev tasks.",
6803
+ "log"
6804
+ ).option("--skip-telemetry", "Opt-out of sending telemetry").action(async (options) => {
6805
+ await handleTelemetry(async () => {
6806
+ await printInitialBanner(true);
6807
+ await listProfilesCommand(options);
6808
+ });
6809
+ });
6810
+ }
6811
+ async function listProfilesCommand(options) {
6812
+ return await wrapCommandAction("listProfiles", ListProfilesOptions, options, async (opts) => {
6813
+ return await listProfiles(opts);
6814
+ });
6815
+ }
6816
+ async function listProfiles(options) {
6817
+ const authConfig = readAuthConfigFile();
6818
+ if (!authConfig) {
6819
+ logger.info("No profiles found");
5490
6820
  return;
5491
6821
  }
5492
- writeAuthConfigProfile({ ...config, accessToken: void 0, apiUrl: void 0 }, options.profile);
5493
- logger.info(`Logged out of Trigger.dev [${options.profile ?? "default"}]`);
6822
+ const profiles = Object.keys(authConfig);
6823
+ log7.message("Profiles:");
6824
+ for (const profile of profiles) {
6825
+ const profileConfig = authConfig[profile];
6826
+ log7.info(`${profile}${profileConfig?.apiUrl ? ` - ${chalkGrey(profileConfig.apiUrl)}` : ""}`);
6827
+ }
6828
+ outro7("Retrieve account info by running whoami --profile <profile>");
5494
6829
  }
5495
6830
 
5496
6831
  // src/cli/index.ts
@@ -5502,6 +6837,8 @@ configureDevCommand(program);
5502
6837
  configureDeployCommand(program);
5503
6838
  configureWhoamiCommand(program);
5504
6839
  configureLogoutCommand(program);
6840
+ configureListProfilesCommand(program);
6841
+ configureUpdateCommand(program);
5505
6842
 
5506
6843
  // src/index.ts
5507
6844
  var main = async () => {