v3: config file is now ts by default and uses named exports (#962)
* A bunch of changes to the config file: - No more default export, the config is exported via the `config` named export - `handleError` is moved to a separate named export - Added the ability to include additional packages (e.g. wrangler) that aren’t included by default (think CLI usage) - More reliably install packages in dev - The config is now built first instead of directly imported, meaning we can now support typescript config files (`trigger.config.ts`) * Update to trigger.config.ts in `trigger.dev init`
This commit is contained in:
Vendored
+1
-1
@@ -33,7 +33,7 @@
|
||||
"type": "node-terminal",
|
||||
"request": "launch",
|
||||
"name": "Debug V3 Dev CLI",
|
||||
"command": "pnpm exec trigger.dev dev",
|
||||
"command": "pnpm exec trigger.dev dev --log-level debug",
|
||||
"cwd": "${workspaceFolder}/references/v3-catalog",
|
||||
"sourceMaps": true
|
||||
},
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
"gradient-string": "^2.0.2",
|
||||
"import-meta-resolve": "^4.0.0",
|
||||
"ink": "^4.4.1",
|
||||
"jsonc-parser": "^3.2.1",
|
||||
"jsonlines": "^0.1.1",
|
||||
"liquidjs": "^10.9.2",
|
||||
"mock-fs": "^5.2.0",
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import { intro, log, outro, spinner } from "@clack/prompts";
|
||||
import { depot } from "@depot/cli";
|
||||
import { context, trace } from "@opentelemetry/api";
|
||||
import { ResolvedConfig, detectDependencyVersion, flattenAttributes, recordSpanException } from "@trigger.dev/core/v3";
|
||||
import {
|
||||
ResolvedConfig,
|
||||
detectDependencyVersion,
|
||||
flattenAttributes,
|
||||
recordSpanException,
|
||||
} from "@trigger.dev/core/v3";
|
||||
import chalk from "chalk";
|
||||
import { Command, Option as CommandOption } from "commander";
|
||||
import { Metafile, build } from "esbuild";
|
||||
@@ -29,7 +34,7 @@ import {
|
||||
import { readConfig } from "../utilities/configFiles.js";
|
||||
import { createTempDir, readJSONFile, writeJSONFile } from "../utilities/fileSystem";
|
||||
import { printStandloneInitialBanner } from "../utilities/initialBanner.js";
|
||||
import { detectPackageNameFromImportPath } from "../utilities/installPackages";
|
||||
import { detectPackageNameFromImportPath, parsePackageName } from "../utilities/installPackages";
|
||||
import { logger } from "../utilities/logger.js";
|
||||
import { createTaskFileImports, gatherTaskFiles } from "../utilities/taskFiles";
|
||||
import { login } from "./login";
|
||||
@@ -63,11 +68,7 @@ export function configureDeployCommand(program: Command) {
|
||||
"prod"
|
||||
)
|
||||
.option("-T, --skip-typecheck", "Whether to skip the pre-build typecheck")
|
||||
.option(
|
||||
"-c, --config <config file>",
|
||||
"The name of the config file, found at [path]",
|
||||
"trigger.config.mjs"
|
||||
)
|
||||
.option("-c, --config <config file>", "The name of the config file, found at [path]")
|
||||
.option(
|
||||
"-p, --project-ref <project ref>",
|
||||
"The project ref. Required if there is no config file."
|
||||
@@ -134,7 +135,11 @@ async function _deployCommand(dir: string, options: DeployCommandOptions) {
|
||||
|
||||
intro("Deploying project");
|
||||
|
||||
const authorization = await login({ embedded: true, defaultApiUrl: options.apiUrl, profile: options.profile });
|
||||
const authorization = await login({
|
||||
embedded: true,
|
||||
defaultApiUrl: options.apiUrl,
|
||||
profile: options.profile,
|
||||
});
|
||||
|
||||
if (!authorization.ok) {
|
||||
if (authorization.error === "fetch failed") {
|
||||
@@ -228,7 +233,8 @@ async function _deployCommand(dir: string, options: DeployCommandOptions) {
|
||||
const deploymentSpinner = spinner();
|
||||
|
||||
deploymentSpinner.start(`Deploying version ${version}`);
|
||||
const registryHost = deploymentResponse.data.registryHost ?? options.registry ?? "registry.trigger.dev";
|
||||
const registryHost =
|
||||
deploymentResponse.data.registryHost ?? options.registry ?? "registry.trigger.dev";
|
||||
|
||||
const buildImage = async () => {
|
||||
if (options.selfHosted) {
|
||||
@@ -345,7 +351,8 @@ async function _deployCommand(dir: string, options: DeployCommandOptions) {
|
||||
);
|
||||
} else {
|
||||
outro(
|
||||
`Version ${version} deployed with ${taskCount} detected task${taskCount === 1 ? "" : "s"
|
||||
`Version ${version} deployed with ${taskCount} detected task${
|
||||
taskCount === 1 ? "" : "s"
|
||||
} ${deploymentLink}`
|
||||
);
|
||||
}
|
||||
@@ -515,14 +522,14 @@ type BuildAndPushImageOptions = {
|
||||
|
||||
type BuildAndPushImageResults =
|
||||
| {
|
||||
ok: true;
|
||||
image: string;
|
||||
digest?: string;
|
||||
}
|
||||
ok: true;
|
||||
image: string;
|
||||
digest?: string;
|
||||
}
|
||||
| {
|
||||
ok: false;
|
||||
error: string;
|
||||
};
|
||||
ok: false;
|
||||
error: string;
|
||||
};
|
||||
|
||||
async function buildAndPushImage(
|
||||
options: BuildAndPushImageOptions
|
||||
@@ -774,12 +781,12 @@ async function compileProject(
|
||||
|
||||
workerContents = workerContents.replace(
|
||||
"__IMPORTED_PROJECT_CONFIG__",
|
||||
`import importedConfig from "${configPath}";`
|
||||
`import * as importedConfigExports from "${configPath}"; const importedConfig = importedConfigExports.config; const handleError = importedConfigExports.handleError;`
|
||||
);
|
||||
} else {
|
||||
workerContents = workerContents.replace(
|
||||
"__IMPORTED_PROJECT_CONFIG__",
|
||||
`const importedConfig = undefined;`
|
||||
`const importedConfig = undefined; const handleError = undefined;`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -919,8 +926,7 @@ async function compileProject(
|
||||
|
||||
// Get all the required dependencies from the metaOutputs and save them to /tmp/dir/package.json
|
||||
const allImports = [...metaOutput.imports, ...entryPointMetaOutput.imports];
|
||||
const projectPackageJson = await readJSONFile(join(config.projectDir, "package.json"));
|
||||
const dependencies = gatherRequiredDependencies(allImports, projectPackageJson);
|
||||
const dependencies = await gatherRequiredDependencies(allImports, config);
|
||||
|
||||
const packageJsonContents = {
|
||||
name: "trigger-worker",
|
||||
@@ -1141,10 +1147,12 @@ async function typecheckProject(config: ResolvedConfig, options: DeployCommandOp
|
||||
|
||||
// Returns the dependencies that are required by the output that are found in output and the CLI package dependencies
|
||||
// Returns the dependency names and the version to use (taken from the CLI deps package.json)
|
||||
function gatherRequiredDependencies(
|
||||
async function gatherRequiredDependencies(
|
||||
imports: Metafile["outputs"][string]["imports"],
|
||||
externalPackageJson?: { dependencies: Record<string, string> }
|
||||
config: ResolvedConfig
|
||||
) {
|
||||
const externalPackageJson = await readJSONFile(join(config.projectDir, "package.json"));
|
||||
|
||||
const dependencies: Record<string, string> = {};
|
||||
|
||||
for (const file of imports) {
|
||||
@@ -1165,15 +1173,44 @@ function gatherRequiredDependencies(
|
||||
continue;
|
||||
}
|
||||
|
||||
const internalDependencyVersion = (packageJson.dependencies as Record<string, string>)[
|
||||
packageName
|
||||
] ?? detectDependencyVersion(packageName);
|
||||
const internalDependencyVersion =
|
||||
(packageJson.dependencies as Record<string, string>)[packageName] ??
|
||||
detectDependencyVersion(packageName);
|
||||
|
||||
if (internalDependencyVersion) {
|
||||
dependencies[packageName] = internalDependencyVersion;
|
||||
}
|
||||
}
|
||||
|
||||
if (config.additionalPackages) {
|
||||
for (const packageName of config.additionalPackages) {
|
||||
if (dependencies[packageName]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const packageParts = parsePackageName(packageName);
|
||||
|
||||
if (packageParts.version) {
|
||||
dependencies[packageParts.name] = packageParts.version;
|
||||
continue;
|
||||
} else {
|
||||
const externalDependencyVersion = {
|
||||
...externalPackageJson?.devDependencies,
|
||||
...externalPackageJson?.dependencies,
|
||||
}[packageName];
|
||||
|
||||
if (externalDependencyVersion) {
|
||||
dependencies[packageParts.name] = externalDependencyVersion;
|
||||
continue;
|
||||
} else {
|
||||
logger.warn(
|
||||
`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`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we sort the dependencies by key to ensure consistent hashing
|
||||
return Object.fromEntries(Object.entries(dependencies).sort(([a], [b]) => a.localeCompare(b)));
|
||||
}
|
||||
|
||||
@@ -27,8 +27,9 @@ import * as packageJson from "../../package.json";
|
||||
import { CliApiClient } from "../apiClient";
|
||||
import { CommonCommandOptions, commonOptions, wrapCommandAction } from "../cli/common.js";
|
||||
import { readConfig } from "../utilities/configFiles";
|
||||
import { readJSONFile } from "../utilities/fileSystem";
|
||||
import { printStandloneInitialBanner } from "../utilities/initialBanner.js";
|
||||
import { detectPackageNameFromImportPath } from "../utilities/installPackages";
|
||||
import { detectPackageNameFromImportPath, parsePackageName } from "../utilities/installPackages";
|
||||
import { logger } from "../utilities/logger.js";
|
||||
import { isLoggedIn } from "../utilities/session.js";
|
||||
import { createTaskFileImports, gatherTaskFiles } from "../utilities/taskFiles";
|
||||
@@ -52,11 +53,7 @@ export function configureDevCommand(program: Command) {
|
||||
.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]",
|
||||
"trigger.config.mjs"
|
||||
)
|
||||
.option("-c, --config <config file>", "The name of the config file, found at [path]")
|
||||
.option(
|
||||
"-p, --project-ref <project ref>",
|
||||
"The project ref. Required if there is no config file."
|
||||
@@ -83,16 +80,9 @@ export async function devCommand(dir: string, options: DevCommandOptions) {
|
||||
return;
|
||||
}
|
||||
|
||||
let watcher;
|
||||
|
||||
try {
|
||||
const devInstance = await startDev(dir, options, authorization.auth);
|
||||
watcher = devInstance.watcher;
|
||||
const { waitUntilExit } = devInstance.devReactElement;
|
||||
await waitUntilExit();
|
||||
} finally {
|
||||
await watcher?.close();
|
||||
}
|
||||
const devInstance = await startDev(dir, options, authorization.auth);
|
||||
const { waitUntilExit } = devInstance.devReactElement;
|
||||
await waitUntilExit();
|
||||
}
|
||||
|
||||
async function startDev(
|
||||
@@ -100,7 +90,6 @@ async function startDev(
|
||||
options: DevCommandOptions,
|
||||
authorization: { apiUrl: string; accessToken: string }
|
||||
) {
|
||||
let watcher: ReturnType<typeof watch> | undefined;
|
||||
let rerender: (node: React.ReactNode) => void | undefined;
|
||||
|
||||
try {
|
||||
@@ -110,6 +99,8 @@ async function startDev(
|
||||
|
||||
await printStandloneInitialBanner(true);
|
||||
|
||||
logger.debug("Starting dev session", { dir, options, authorization });
|
||||
|
||||
let config = await readConfig(dir, {
|
||||
projectRef: options.projectRef,
|
||||
configFile: options.config,
|
||||
@@ -117,23 +108,6 @@ async function startDev(
|
||||
|
||||
logger.debug("Initial config", { config });
|
||||
|
||||
if (config.status === "file") {
|
||||
watcher = watch(config.path, {
|
||||
persistent: true,
|
||||
}).on("change", async (_event) => {
|
||||
config = await readConfig(dir, { configFile: options.config });
|
||||
|
||||
if (config.status === "file") {
|
||||
logger.log(`${basename(config.path)} changed...`);
|
||||
logger.debug("New config", { config: config.config });
|
||||
rerender(await getDevReactElement(config.config, authorization, config.path));
|
||||
} else {
|
||||
logger.debug("New config", { config: config.config });
|
||||
rerender(await getDevReactElement(config.config, authorization));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function getDevReactElement(
|
||||
configParam: ResolvedConfig,
|
||||
authorization: { apiUrl: string; accessToken: string },
|
||||
@@ -181,14 +155,11 @@ async function startDev(
|
||||
|
||||
return {
|
||||
devReactElement,
|
||||
watcher,
|
||||
stop: async () => {
|
||||
devReactElement.unmount();
|
||||
await watcher?.close();
|
||||
},
|
||||
};
|
||||
} catch (e) {
|
||||
await watcher?.close();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@@ -341,12 +312,12 @@ function useDev({
|
||||
|
||||
entryPointContents = entryPointContents.replace(
|
||||
"__IMPORTED_PROJECT_CONFIG__",
|
||||
`import importedConfig from "${configPath}";`
|
||||
`import * as importedConfigExports from "${configPath}"; const importedConfig = importedConfigExports.config; const handleError = importedConfigExports.handleError;`
|
||||
);
|
||||
} else {
|
||||
entryPointContents = entryPointContents.replace(
|
||||
"__IMPORTED_PROJECT_CONFIG__",
|
||||
`const importedConfig = undefined;`
|
||||
`const importedConfig = undefined; const handleError = undefined;`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -366,7 +337,7 @@ function useDev({
|
||||
minify: false,
|
||||
sourcemap: "external", // does not set the //# sourceMappingURL= comment in the file, we handle it ourselves
|
||||
packages: "external", // https://esbuild.github.io/api/#packages
|
||||
logLevel: "warning",
|
||||
logLevel: "error",
|
||||
platform: "node",
|
||||
format: "cjs", // This is needed to support opentelemetry instrumentation that uses module patching
|
||||
target: ["node18", "es2020"],
|
||||
@@ -437,7 +408,7 @@ function useDev({
|
||||
|
||||
logger.debug(`Wrote background worker to ${fullPath}`);
|
||||
|
||||
const dependencies = gatherRequiredDependencies(metaOutput);
|
||||
const dependencies = await gatherRequiredDependencies(metaOutput, config);
|
||||
|
||||
if (sourceMapFile) {
|
||||
const sourceMapPath = `${fullPath}.map`;
|
||||
@@ -447,10 +418,13 @@ function useDev({
|
||||
const environmentVariablesResponse =
|
||||
await environmentClient.getEnvironmentVariables(config.project);
|
||||
|
||||
const processEnv = gatherProcessEnv();
|
||||
|
||||
const backgroundWorker = new BackgroundWorker(fullPath, {
|
||||
projectConfig: config,
|
||||
dependencies,
|
||||
env: {
|
||||
...processEnv,
|
||||
TRIGGER_API_URL: apiUrl,
|
||||
TRIGGER_SECRET_KEY: apiKey,
|
||||
...(environmentVariablesResponse.success
|
||||
@@ -678,7 +652,10 @@ function WebsocketFactory(apiKey: string) {
|
||||
|
||||
// Returns the dependencies that are required by the output that are found in output and the CLI package dependencies
|
||||
// Returns the dependency names and the version to use (taken from the CLI deps package.json)
|
||||
function gatherRequiredDependencies(outputMeta: Metafile["outputs"][string]) {
|
||||
async function gatherRequiredDependencies(
|
||||
outputMeta: Metafile["outputs"][string],
|
||||
config: ResolvedConfig
|
||||
) {
|
||||
const dependencies: Record<string, string> = {};
|
||||
|
||||
for (const file of outputMeta.imports) {
|
||||
@@ -701,5 +678,56 @@ function gatherRequiredDependencies(outputMeta: Metafile["outputs"][string]) {
|
||||
}
|
||||
}
|
||||
|
||||
if (config.additionalPackages) {
|
||||
const projectPackageJson = await readJSONFile(join(config.projectDir, "package.json"));
|
||||
|
||||
for (const packageName of config.additionalPackages) {
|
||||
if (dependencies[packageName]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const packageParts = parsePackageName(packageName);
|
||||
|
||||
if (packageParts.version) {
|
||||
dependencies[packageParts.name] = packageParts.version;
|
||||
continue;
|
||||
} else {
|
||||
const externalDependencyVersion = {
|
||||
...projectPackageJson?.devDependencies,
|
||||
...projectPackageJson?.dependencies,
|
||||
}[packageName];
|
||||
|
||||
if (externalDependencyVersion) {
|
||||
dependencies[packageParts.name] = externalDependencyVersion;
|
||||
continue;
|
||||
} else {
|
||||
logger.warn(
|
||||
`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`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
function gatherProcessEnv() {
|
||||
const env = {
|
||||
NODE_ENV: process.env.NODE_ENV ?? "development",
|
||||
PATH: process.env.PATH,
|
||||
USER: process.env.USER,
|
||||
SHELL: process.env.SHELL,
|
||||
NVM_INC: process.env.NVM_INC,
|
||||
NVM_DIR: process.env.NVM_DIR,
|
||||
NVM_BIN: process.env.NVM_BIN,
|
||||
LANG: process.env.LANG,
|
||||
TERM: process.env.TERM,
|
||||
NODE_PATH: process.env.NODE_PATH,
|
||||
HOME: process.env.HOME,
|
||||
BUN_INSTALL: process.env.BUN_INSTALL,
|
||||
};
|
||||
|
||||
// Filter out undefined values
|
||||
return Object.fromEntries(Object.entries(env).filter(([key, value]) => value !== undefined));
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import {
|
||||
import chalk from "chalk";
|
||||
import { Command } from "commander";
|
||||
import { execa } from "execa";
|
||||
import { applyEdits, modify } from "jsonc-parser";
|
||||
import { writeFile } from "node:fs/promises";
|
||||
import { join, relative, resolve } from "node:path";
|
||||
import terminalLink from "terminal-link";
|
||||
import { z } from "zod";
|
||||
@@ -24,7 +26,7 @@ import {
|
||||
} from "../cli/common.js";
|
||||
import { readConfig } from "../utilities/configFiles.js";
|
||||
import { createFileFromTemplate } from "../utilities/createFileFromTemplate";
|
||||
import { createFile, pathExists } from "../utilities/fileSystem";
|
||||
import { createFile, pathExists, readFile } from "../utilities/fileSystem";
|
||||
import { getUserPackageManager } from "../utilities/getUserPackageManager";
|
||||
import { printStandloneInitialBanner } from "../utilities/initialBanner.js";
|
||||
import { logger } from "../utilities/logger";
|
||||
@@ -80,7 +82,11 @@ async function _initCommand(dir: string, options: InitCommandOptions) {
|
||||
|
||||
intro("Initializing project");
|
||||
|
||||
const authorization = await login({ embedded: true, defaultApiUrl: options.apiUrl, profile: options.profile });
|
||||
const authorization = await login({
|
||||
embedded: true,
|
||||
defaultApiUrl: options.apiUrl,
|
||||
profile: options.profile,
|
||||
});
|
||||
|
||||
if (!authorization.ok) {
|
||||
if (authorization.error === "fetch failed") {
|
||||
@@ -145,6 +151,12 @@ async function _initCommand(dir: string, options: InitCommandOptions) {
|
||||
// Create the trigger dir
|
||||
await createTriggerDir(dir, options);
|
||||
|
||||
// Add trigger.config.ts to tsconfig.json
|
||||
await addConfigFileToTsConfig(dir, options);
|
||||
|
||||
// Ignore .trigger dir
|
||||
await gitIgnoreDotTriggerDir(dir, options);
|
||||
|
||||
const projectDashboard = terminalLink(
|
||||
"project dashboard",
|
||||
`${authorization.dashboardUrl}/projects/v3/${selectedProject.externalRef}`
|
||||
@@ -255,6 +267,101 @@ async function createTriggerDir(dir: string, options: InitCommandOptions) {
|
||||
});
|
||||
}
|
||||
|
||||
async function gitIgnoreDotTriggerDir(dir: string, options: InitCommandOptions) {
|
||||
return await tracer.startActiveSpan("gitIgnoreDotTriggerDir", async (span) => {
|
||||
try {
|
||||
const projectDir = resolve(process.cwd(), dir);
|
||||
const gitIgnorePath = join(projectDir, ".gitignore");
|
||||
|
||||
span.setAttributes({
|
||||
"cli.projectDir": projectDir,
|
||||
"cli.gitIgnorePath": gitIgnorePath,
|
||||
});
|
||||
|
||||
if (!(await pathExists(gitIgnorePath))) {
|
||||
// Create .gitignore file
|
||||
await createFile(gitIgnorePath, ".trigger");
|
||||
|
||||
log.step(`Added .trigger to .gitignore`);
|
||||
|
||||
span.end();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if .gitignore already contains .trigger
|
||||
const gitIgnoreContent = await readFile(gitIgnorePath);
|
||||
|
||||
if (gitIgnoreContent.includes(".trigger")) {
|
||||
span.end();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const newGitIgnoreContent = `${gitIgnoreContent}\n.trigger`;
|
||||
|
||||
await writeFile(gitIgnorePath, newGitIgnoreContent, "utf-8");
|
||||
|
||||
log.step(`Added .trigger to .gitignore`);
|
||||
|
||||
span.end();
|
||||
} catch (e) {
|
||||
if (!(e instanceof SkipCommandError)) {
|
||||
recordSpanException(span, e);
|
||||
}
|
||||
|
||||
span.end();
|
||||
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function addConfigFileToTsConfig(dir: string, options: InitCommandOptions) {
|
||||
return await tracer.startActiveSpan("createTriggerDir", async (span) => {
|
||||
try {
|
||||
const projectDir = resolve(process.cwd(), dir);
|
||||
const tsconfigPath = join(projectDir, "tsconfig.json");
|
||||
|
||||
span.setAttributes({
|
||||
"cli.projectDir": projectDir,
|
||||
"cli.tsconfigPath": tsconfigPath,
|
||||
});
|
||||
|
||||
const tsconfigContent = await readFile(tsconfigPath);
|
||||
|
||||
const edits = modify(tsconfigContent, ["include", -1], "trigger.config.ts", {
|
||||
isArrayInsertion: true,
|
||||
formattingOptions: {
|
||||
tabSize: 2,
|
||||
insertSpaces: true,
|
||||
eol: "\n",
|
||||
},
|
||||
});
|
||||
|
||||
logger.debug("tsconfig.json edits", { edits });
|
||||
|
||||
const newTsconfigContent = applyEdits(tsconfigContent, edits);
|
||||
|
||||
logger.debug("new tsconfig.json content", { newTsconfigContent });
|
||||
|
||||
await writeFile(tsconfigPath, newTsconfigContent, "utf-8");
|
||||
|
||||
log.step(`Added trigger.config.ts to tsconfig.json`);
|
||||
|
||||
span.end();
|
||||
} catch (e) {
|
||||
if (!(e instanceof SkipCommandError)) {
|
||||
recordSpanException(span, e);
|
||||
}
|
||||
|
||||
span.end();
|
||||
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function installPackages(dir: string, options: InitCommandOptions) {
|
||||
return await tracer.startActiveSpan("installPackages", async (span) => {
|
||||
const installSpinner = spinner();
|
||||
@@ -332,8 +439,8 @@ async function writeConfigFile(
|
||||
spnnr.start("Creating config file");
|
||||
|
||||
const projectDir = resolve(process.cwd(), dir);
|
||||
const templatePath = resolveInternalFilePath("./templates/trigger.config.mjs");
|
||||
const outputPath = join(projectDir, "trigger.config.mjs");
|
||||
const templatePath = resolveInternalFilePath("./templates/trigger.config.ts");
|
||||
const outputPath = join(projectDir, "trigger.config.ts");
|
||||
|
||||
span.setAttributes({
|
||||
"cli.projectDir": projectDir,
|
||||
|
||||
@@ -10,4 +10,4 @@ export const PKG_ROOT = path.join(distPath, "../");
|
||||
export const COMMAND_NAME = "trigger.dev";
|
||||
export const CLOUD_WEB_URL = "https://cloud.trigger.dev";
|
||||
export const CLOUD_API_URL = "https://api.trigger.dev";
|
||||
export const CONFIG_FILES = ["trigger.config.js", "trigger.config.mjs"];
|
||||
export const CONFIG_FILES = ["trigger.config.ts", "trigger.config.js", "trigger.config.mjs"];
|
||||
|
||||
+2
-3
@@ -1,7 +1,6 @@
|
||||
// @ts-check
|
||||
/** @type {import('@trigger.dev/sdk/v3').Config} */
|
||||
import type { ProjectConfig } from "@trigger.dev/core/v3";
|
||||
|
||||
export default {
|
||||
export const config: ProjectConfig = {
|
||||
project: "${projectRef}",
|
||||
retries: {
|
||||
enabledInDev: false,
|
||||
@@ -1,14 +1,15 @@
|
||||
import { Config, ResolvedConfig } from "@trigger.dev/core/v3";
|
||||
import { findUp } from "find-up";
|
||||
import { mkdirSync, writeFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import path, { join } from "node:path";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import xdgAppPaths from "xdg-app-paths";
|
||||
import { z } from "zod";
|
||||
import { CLOUD_API_URL, CONFIG_FILES } from "../consts.js";
|
||||
import { readJSONFileSync } from "./fileSystem.js";
|
||||
import { createTempDir, readJSONFileSync } from "./fileSystem.js";
|
||||
import { logger } from "./logger.js";
|
||||
import { findTriggerDirectories, resolveTriggerDirectories } from "./taskFiles.js";
|
||||
import { build } from "esbuild";
|
||||
|
||||
function getGlobalConfigFolderPath() {
|
||||
const configDir = xdgAppPaths("trigger").config();
|
||||
@@ -81,6 +82,12 @@ function writeAuthConfigFile(config: UserAuthConfigFile) {
|
||||
}
|
||||
|
||||
async function getConfigPath(dir: string, fileName?: string): Promise<string | undefined> {
|
||||
logger.debug("Searching for the config file", {
|
||||
dir,
|
||||
fileName,
|
||||
configFiles: CONFIG_FILES,
|
||||
});
|
||||
|
||||
return await findUp(fileName ? [fileName] : CONFIG_FILES, { cwd: dir });
|
||||
}
|
||||
|
||||
@@ -91,14 +98,14 @@ export type ReadConfigOptions = {
|
||||
|
||||
export type ReadConfigResult =
|
||||
| {
|
||||
status: "file";
|
||||
config: ResolvedConfig;
|
||||
path: string;
|
||||
}
|
||||
status: "file";
|
||||
config: ResolvedConfig;
|
||||
path: string;
|
||||
}
|
||||
| {
|
||||
status: "in-memory";
|
||||
config: ResolvedConfig;
|
||||
};
|
||||
status: "in-memory";
|
||||
config: ResolvedConfig;
|
||||
};
|
||||
|
||||
export async function readConfig(
|
||||
dir: string,
|
||||
@@ -106,12 +113,6 @@ export async function readConfig(
|
||||
): Promise<ReadConfigResult> {
|
||||
const absoluteDir = path.resolve(process.cwd(), dir);
|
||||
|
||||
logger.debug("Searching for the config file", {
|
||||
dir,
|
||||
options,
|
||||
absoluteDir,
|
||||
});
|
||||
|
||||
const configPath = await getConfigPath(dir, options?.configFile);
|
||||
|
||||
if (!configPath) {
|
||||
@@ -128,9 +129,36 @@ export async function readConfig(
|
||||
}
|
||||
}
|
||||
|
||||
const tempDir = await createTempDir();
|
||||
|
||||
const builtConfigFilePath = join(tempDir, "config.mjs");
|
||||
const builtConfigFileHref = pathToFileURL(builtConfigFilePath).href;
|
||||
|
||||
logger.debug("Building config file", {
|
||||
configPath,
|
||||
builtConfigFileHref,
|
||||
builtConfigFilePath,
|
||||
});
|
||||
|
||||
// We need to build the path to the config file, and then import it?
|
||||
await build({
|
||||
entryPoints: [configPath],
|
||||
bundle: true,
|
||||
metafile: true,
|
||||
minify: false,
|
||||
write: true,
|
||||
format: "esm",
|
||||
platform: "node",
|
||||
target: ["es2018", "node18"],
|
||||
outfile: builtConfigFilePath,
|
||||
logLevel: "silent",
|
||||
});
|
||||
|
||||
// import the config file
|
||||
const userConfigModule = await import(`${pathToFileURL(configPath).href}?_ts=${Date.now()}`);
|
||||
const rawConfig = await normalizeConfig(userConfigModule ? userConfigModule.default : {});
|
||||
const userConfigModule = await import(builtConfigFileHref);
|
||||
const rawConfig = await normalizeConfig(
|
||||
userConfigModule ? userConfigModule.config : { project: options?.projectRef }
|
||||
);
|
||||
const config = Config.parse(rawConfig);
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import semver from "semver";
|
||||
import { execa } from "execa";
|
||||
import { logger } from "./logger";
|
||||
import { join } from "node:path";
|
||||
import { readJSONFile, writeJSONFile } from "./fileSystem";
|
||||
import { logger } from "./logger";
|
||||
|
||||
export type InstallPackagesOptions = { cwd?: string };
|
||||
|
||||
@@ -12,64 +11,13 @@ export async function installPackages(
|
||||
) {
|
||||
const cwd = options?.cwd ?? process.cwd();
|
||||
|
||||
logger.debug(`Installing packages at ${cwd}:`, { packages });
|
||||
logger.debug("Installing packages", { packages });
|
||||
|
||||
// Make sure the cwd has a package.json file (if not create a barebones one)
|
||||
try {
|
||||
await readJSONFile(join(cwd, "package.json"));
|
||||
} catch (error) {
|
||||
await writeJSONFile(join(cwd, "package.json"), {
|
||||
name: "temp",
|
||||
version: "1.0.0",
|
||||
description: "",
|
||||
});
|
||||
}
|
||||
|
||||
// Detect with packages have already been installed at the specified version (use semver to compare)
|
||||
// and only install the ones that are missing or have a different version
|
||||
const installablePackages = await Promise.all(
|
||||
Object.entries(packages).map(async ([name, version]) => {
|
||||
try {
|
||||
const latestVersion = await getPackageVersion(join(cwd, "node_modules", name));
|
||||
|
||||
if (!latestVersion) {
|
||||
return { name, version };
|
||||
}
|
||||
|
||||
return semver.satisfies(latestVersion, version) ? undefined : { name, version };
|
||||
} catch (error) {
|
||||
return { name, version };
|
||||
}
|
||||
})
|
||||
)
|
||||
.then((packages) => packages.filter(Boolean))
|
||||
.then((packages) =>
|
||||
packages.reduce((acc: Record<string, string>, p) => ({ ...acc, [p!.name]: p!.version }), {})
|
||||
);
|
||||
|
||||
if (Object.keys(installablePackages).length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug(`Found installable packages`);
|
||||
logger.table(
|
||||
Object.entries(installablePackages).map(([name, version]) => ({ name, version })),
|
||||
"debug"
|
||||
);
|
||||
await setPackageJsonDeps(join(cwd, "package.json"), packages);
|
||||
|
||||
const childProcess = execa(
|
||||
"npm",
|
||||
[
|
||||
"install",
|
||||
...Object.entries(installablePackages).map(([name, version]) => `${name}@${version}`),
|
||||
"--install-strategy",
|
||||
"nested",
|
||||
"--ignore-scripts",
|
||||
"--no-package-lock",
|
||||
"--no-audit",
|
||||
"--no-fund",
|
||||
"--no-save",
|
||||
],
|
||||
["install", "--install-strategy", "nested", "--ignore-scripts", "--no-audit", "--no-fund"],
|
||||
{
|
||||
cwd,
|
||||
stderr: "inherit",
|
||||
@@ -113,3 +61,41 @@ export function detectPackageNameFromImportPath(path: string): string {
|
||||
return path.split("/")[0] as string;
|
||||
}
|
||||
}
|
||||
|
||||
export function parsePackageName(packageSpecifier: string): { name: string; version?: string } {
|
||||
const parts = packageSpecifier.split("@");
|
||||
|
||||
if (parts.length === 1 && typeof parts[0] === "string") {
|
||||
return { name: parts[0] };
|
||||
}
|
||||
|
||||
if (parts.length === 2 && typeof parts[0] === "string" && typeof parts[1] === "string") {
|
||||
return { name: parts[0], version: parts[1] };
|
||||
}
|
||||
|
||||
return { name: packageSpecifier };
|
||||
}
|
||||
|
||||
async function setPackageJsonDeps(path: string, deps: Record<string, string>) {
|
||||
try {
|
||||
const existingPackageJson = await readJSONFile(path);
|
||||
|
||||
const newPackageJson = {
|
||||
...existingPackageJson,
|
||||
dependencies: {
|
||||
...deps,
|
||||
},
|
||||
};
|
||||
|
||||
await writeJSONFile(path, newPackageJson);
|
||||
} catch (error) {
|
||||
const defaultPackageJson = {
|
||||
name: "temp",
|
||||
version: "1.0.0",
|
||||
description: "",
|
||||
dependencies: deps,
|
||||
};
|
||||
|
||||
await writeJSONFile(path, defaultPackageJson);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,8 +167,8 @@ export class BackgroundWorkerCoordinator {
|
||||
!completion.ok && completion.skippedRetrying
|
||||
? " (retrying skipped)"
|
||||
: !completion.ok && completion.retry !== undefined
|
||||
? ` (retrying in ${completion.retry.delay}ms)`
|
||||
: "";
|
||||
? ` (retrying in ${completion.retry.delay}ms)`
|
||||
: "";
|
||||
|
||||
const resultText = !completion.ok
|
||||
? completion.error.type === "INTERNAL_ERROR" &&
|
||||
@@ -181,8 +181,8 @@ export class BackgroundWorkerCoordinator {
|
||||
const errorText = !completion.ok
|
||||
? this.#formatErrorLog(completion.error)
|
||||
: "retry" in completion
|
||||
? `retry in ${completion.retry}ms`
|
||||
: "";
|
||||
? `retry in ${completion.retry}ms`
|
||||
: "";
|
||||
|
||||
const elapsedText = chalk.dim(`(${elapsed.toFixed(2)}ms)`);
|
||||
|
||||
@@ -263,7 +263,7 @@ export class BackgroundWorker {
|
||||
constructor(
|
||||
public path: string,
|
||||
private params: BackgroundWorkerParams
|
||||
) { }
|
||||
) {}
|
||||
|
||||
close() {
|
||||
if (this._closed) {
|
||||
@@ -316,7 +316,7 @@ export class BackgroundWorker {
|
||||
resolved = true;
|
||||
child.kill();
|
||||
reject(new Error("Worker timed out"));
|
||||
}, 1000);
|
||||
}, 5000);
|
||||
|
||||
child.on("message", async (msg: any) => {
|
||||
const message = this._handler.parseMessage(msg);
|
||||
@@ -545,7 +545,8 @@ class TaskRunProcess {
|
||||
logger.debug("initializing task run process", {
|
||||
env: this.env,
|
||||
path: this.path,
|
||||
})
|
||||
processEnv: process.env,
|
||||
});
|
||||
|
||||
this._child = fork(this.path, {
|
||||
stdio: [/*stdin*/ "ignore", /*stdout*/ "pipe", /*stderr*/ "pipe", "ipc"],
|
||||
@@ -700,7 +701,8 @@ class TaskRunProcess {
|
||||
}
|
||||
|
||||
logger.log(
|
||||
`[${this.metadata.version}][${this._currentExecution.run.id}.${this._currentExecution.attempt.number
|
||||
`[${this.metadata.version}][${this._currentExecution.run.id}.${
|
||||
this._currentExecution.attempt.number
|
||||
}] ${data.toString()}`
|
||||
);
|
||||
}
|
||||
@@ -717,7 +719,8 @@ class TaskRunProcess {
|
||||
}
|
||||
|
||||
logger.error(
|
||||
`[${this.metadata.version}][${this._currentExecution.run.id}.${this._currentExecution.attempt.number
|
||||
`[${this.metadata.version}][${this._currentExecution.run.id}.${
|
||||
this._currentExecution.attempt.number
|
||||
}] ${data.toString()}`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
import { Config, ProjectConfig, TaskExecutor, preciseDateOriginNow, type TracingSDK } from "@trigger.dev/core/v3";
|
||||
import {
|
||||
Config,
|
||||
ProjectConfig,
|
||||
TaskExecutor,
|
||||
preciseDateOriginNow,
|
||||
type TracingSDK,
|
||||
type HandleErrorFunction,
|
||||
} from "@trigger.dev/core/v3";
|
||||
import "source-map-support/register.js";
|
||||
|
||||
__WORKER_SETUP__;
|
||||
@@ -7,6 +14,7 @@ declare const __WORKER_SETUP__: unknown;
|
||||
__IMPORTED_PROJECT_CONFIG__;
|
||||
declare const __IMPORTED_PROJECT_CONFIG__: unknown;
|
||||
declare const importedConfig: ProjectConfig | undefined;
|
||||
declare const handleError: HandleErrorFunction | undefined;
|
||||
|
||||
declare const __PROJECT_CONFIG__: Config;
|
||||
declare const tracingSDK: TracingSDK;
|
||||
@@ -48,7 +56,7 @@ const otelTaskLogger = new OtelTaskLogger({
|
||||
logger: otelLogger,
|
||||
tracer: tracer,
|
||||
level: "info",
|
||||
preciseDateOrigin
|
||||
preciseDateOrigin,
|
||||
});
|
||||
|
||||
logger.setGlobalTaskLogger(otelTaskLogger);
|
||||
@@ -111,6 +119,7 @@ for (const task of tasks) {
|
||||
consoleInterceptor,
|
||||
projectConfig: __PROJECT_CONFIG__,
|
||||
importedConfig,
|
||||
handleErrorFn: handleError,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ class ProdWorker {
|
||||
this.#backgroundWorker = new ProdBackgroundWorker("worker.js", {
|
||||
projectConfig: __PROJECT_CONFIG__,
|
||||
env: {
|
||||
...gatherProcessEnv(),
|
||||
TRIGGER_API_URL: this.apiUrl,
|
||||
TRIGGER_SECRET_KEY: this.apiKey,
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT:
|
||||
@@ -513,3 +514,19 @@ class ProdWorker {
|
||||
|
||||
const prodWorker = new ProdWorker(HTTP_SERVER_PORT);
|
||||
prodWorker.start();
|
||||
|
||||
function gatherProcessEnv() {
|
||||
const env = {
|
||||
NODE_ENV: process.env.NODE_ENV ?? "production",
|
||||
PATH: process.env.PATH,
|
||||
USER: process.env.USER,
|
||||
SHELL: process.env.SHELL,
|
||||
LANG: process.env.LANG,
|
||||
TERM: process.env.TERM,
|
||||
NODE_PATH: process.env.NODE_PATH,
|
||||
HOME: process.env.HOME,
|
||||
};
|
||||
|
||||
// Filter out undefined values
|
||||
return Object.fromEntries(Object.entries(env).filter(([key, value]) => value !== undefined));
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
ZodIpcConnection,
|
||||
type TracingSDK,
|
||||
preciseDateOriginNow,
|
||||
HandleErrorFunction,
|
||||
} from "@trigger.dev/core/v3";
|
||||
import "source-map-support/register.js";
|
||||
|
||||
@@ -16,6 +17,7 @@ declare const __WORKER_SETUP__: unknown;
|
||||
__IMPORTED_PROJECT_CONFIG__;
|
||||
declare const __IMPORTED_PROJECT_CONFIG__: unknown;
|
||||
declare const importedConfig: ProjectConfig | undefined;
|
||||
declare const handleError: HandleErrorFunction | undefined;
|
||||
|
||||
declare const __PROJECT_CONFIG__: Config;
|
||||
declare const tracingSDK: TracingSDK;
|
||||
@@ -47,7 +49,7 @@ const otelTaskLogger = new OtelTaskLogger({
|
||||
logger: otelLogger,
|
||||
tracer: tracer,
|
||||
level: "info",
|
||||
preciseDateOrigin
|
||||
preciseDateOrigin,
|
||||
});
|
||||
|
||||
logger.setGlobalTaskLogger(otelTaskLogger);
|
||||
@@ -110,6 +112,7 @@ for (const task of tasks) {
|
||||
consoleInterceptor,
|
||||
projectConfig: __PROJECT_CONFIG__,
|
||||
importedConfig,
|
||||
handleErrorFn: handleError,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -104,6 +104,14 @@ export class TracingSDK {
|
||||
const traceProvider = new NodeTracerProvider({
|
||||
forceFlushTimeoutMillis: config.forceFlushTimeoutMillis ?? 500,
|
||||
resource: commonResources,
|
||||
spanLimits: {
|
||||
attributeCountLimit: 1000,
|
||||
attributeValueLengthLimit: 1000,
|
||||
eventCountLimit: 100,
|
||||
attributePerEventCountLimit: 100,
|
||||
linkCountLimit: 10,
|
||||
attributePerLinkCountLimit: 100,
|
||||
},
|
||||
});
|
||||
|
||||
const spanExporter = new OTLPTraceExporter({
|
||||
@@ -128,6 +136,10 @@ export class TracingSDK {
|
||||
// To start a logger, you first need to initialize the Logger provider.
|
||||
const loggerProvider = new LoggerProvider({
|
||||
resource: commonResources,
|
||||
logRecordLimits: {
|
||||
attributeCountLimit: 1000,
|
||||
attributeValueLengthLimit: 1000,
|
||||
},
|
||||
});
|
||||
|
||||
loggerProvider.addLogRecordProcessor(
|
||||
|
||||
@@ -21,6 +21,7 @@ export const Config = z.object({
|
||||
default: RetryOptions.optional(),
|
||||
})
|
||||
.optional(),
|
||||
additionalPackages: z.string().array().optional(),
|
||||
});
|
||||
|
||||
export type Config = z.infer<typeof Config>;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { HandleErrorFnParams, HandleErrorResult } from ".";
|
||||
import { RetryOptions } from "../schemas";
|
||||
|
||||
export interface ProjectConfig {
|
||||
@@ -9,9 +8,5 @@ export interface ProjectConfig {
|
||||
enabledInDev?: boolean;
|
||||
default?: RetryOptions;
|
||||
};
|
||||
handleError?: (
|
||||
payload: any,
|
||||
error: unknown,
|
||||
params: HandleErrorFnParams<any>
|
||||
) => HandleErrorResult;
|
||||
additionalPackages?: string[];
|
||||
}
|
||||
|
||||
@@ -48,6 +48,19 @@ export type HandleErrorResult =
|
||||
| HandleErrorModificationOptions
|
||||
| Promise<undefined | void | HandleErrorModificationOptions>;
|
||||
|
||||
export type HandleErrorArgs = {
|
||||
ctx: Context;
|
||||
retry?: RetryOptions;
|
||||
retryAt?: Date;
|
||||
retryDelayInMs?: number;
|
||||
};
|
||||
|
||||
export type HandleErrorFunction = (
|
||||
payload: any,
|
||||
error: unknown,
|
||||
params: HandleErrorArgs
|
||||
) => HandleErrorResult;
|
||||
|
||||
export type TaskMetadataWithFunctions = TaskMetadataWithFilePath & {
|
||||
fns: {
|
||||
run: (payload: any, params: RunFnParams<any>) => Promise<any>;
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
TaskRunExecutionRetry,
|
||||
} from "../schemas";
|
||||
import { SemanticInternalAttributes } from "../semanticInternalAttributes";
|
||||
import { ProjectConfig, TaskMetadataWithFunctions } from "../types";
|
||||
import { HandleErrorFunction, ProjectConfig, TaskMetadataWithFunctions } from "../types";
|
||||
import { flattenAttributes } from "../utils/flattenAttributes";
|
||||
import { accessoryAttributes } from "../utils/styleAttributes";
|
||||
import { calculateNextRetryDelay } from "../utils/retries";
|
||||
@@ -25,6 +25,7 @@ export type TaskExecutorOptions = {
|
||||
consoleInterceptor: ConsoleInterceptor;
|
||||
projectConfig: Config;
|
||||
importedConfig: ProjectConfig | undefined;
|
||||
handleErrorFn: HandleErrorFunction | undefined;
|
||||
};
|
||||
|
||||
export class TaskExecutor {
|
||||
@@ -33,6 +34,7 @@ export class TaskExecutor {
|
||||
private _consoleInterceptor: ConsoleInterceptor;
|
||||
private _config: Config;
|
||||
private _importedConfig: ProjectConfig | undefined;
|
||||
private _handleErrorFn: HandleErrorFunction | undefined;
|
||||
|
||||
constructor(
|
||||
public task: TaskMetadataWithFunctions,
|
||||
@@ -43,6 +45,7 @@ export class TaskExecutor {
|
||||
this._consoleInterceptor = options.consoleInterceptor;
|
||||
this._config = options.projectConfig;
|
||||
this._importedConfig = options.importedConfig;
|
||||
this._handleErrorFn = options.handleErrorFn;
|
||||
}
|
||||
|
||||
async execute(
|
||||
@@ -224,7 +227,9 @@ export class TaskExecutor {
|
||||
| { status: "skipped"; error?: unknown } // skipped is different than noop, it means that the task was skipped from retrying, instead of just not retrying
|
||||
| { status: "noop"; error?: unknown }
|
||||
> {
|
||||
const retry = this.task.retry ?? this._config.retries?.default;
|
||||
const retriesConfig = this._importedConfig?.retries ?? this._config.retries;
|
||||
|
||||
const retry = this.task.retry ?? retriesConfig?.default;
|
||||
|
||||
if (!retry) {
|
||||
return { status: "noop" };
|
||||
@@ -234,8 +239,8 @@ export class TaskExecutor {
|
||||
|
||||
if (
|
||||
execution.environment.type === "DEVELOPMENT" &&
|
||||
typeof this._config.retries?.enabledInDev === "boolean" &&
|
||||
!this._config.retries.enabledInDev
|
||||
typeof retriesConfig?.enabledInDev === "boolean" &&
|
||||
!retriesConfig.enabledInDev
|
||||
) {
|
||||
return { status: "skipped" };
|
||||
}
|
||||
@@ -251,7 +256,7 @@ export class TaskExecutor {
|
||||
retryAt: delay ? new Date(Date.now() + delay) : undefined,
|
||||
})
|
||||
: this._importedConfig
|
||||
? await this._importedConfig.handleError?.(payload, error, {
|
||||
? await this._handleErrorFn?.(payload, error, {
|
||||
ctx,
|
||||
retry,
|
||||
retryDelayInMs: delay,
|
||||
|
||||
Generated
+9
-4
@@ -1078,6 +1078,7 @@ importers:
|
||||
gradient-string: ^2.0.2
|
||||
import-meta-resolve: ^4.0.0
|
||||
ink: ^4.4.1
|
||||
jsonc-parser: ^3.2.1
|
||||
jsonlines: ^0.1.1
|
||||
liquidjs: ^10.9.2
|
||||
mock-fs: ^5.2.0
|
||||
@@ -1148,6 +1149,7 @@ importers:
|
||||
gradient-string: 2.0.2
|
||||
import-meta-resolve: 4.0.0
|
||||
ink: 4.4.1_7kh72gklg5qjlh5zc6s6v3p6v4
|
||||
jsonc-parser: 3.2.1
|
||||
jsonlines: 0.1.1
|
||||
liquidjs: 10.9.3
|
||||
mock-fs: 5.2.0
|
||||
@@ -3487,7 +3489,7 @@ packages:
|
||||
resolution: {integrity: sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/helper-validator-identifier': 7.22.15
|
||||
'@babel/helper-validator-identifier': 7.22.20
|
||||
chalk: 2.4.2
|
||||
js-tokens: 4.0.0
|
||||
|
||||
@@ -28900,6 +28902,9 @@ packages:
|
||||
/jsonc-parser/3.2.0:
|
||||
resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==}
|
||||
|
||||
/jsonc-parser/3.2.1:
|
||||
resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==}
|
||||
|
||||
/jsonfile/4.0.0:
|
||||
resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==}
|
||||
optionalDependencies:
|
||||
@@ -31830,7 +31835,7 @@ packages:
|
||||
bl: 5.1.0
|
||||
chalk: 5.3.0
|
||||
cli-cursor: 4.0.0
|
||||
cli-spinners: 2.9.1
|
||||
cli-spinners: 2.9.2
|
||||
is-interactive: 2.0.0
|
||||
is-unicode-supported: 1.3.0
|
||||
log-symbols: 5.1.0
|
||||
@@ -32541,7 +32546,7 @@ packages:
|
||||
/pkg-types/1.0.3:
|
||||
resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==}
|
||||
dependencies:
|
||||
jsonc-parser: 3.2.0
|
||||
jsonc-parser: 3.2.1
|
||||
mlly: 1.4.2
|
||||
pathe: 1.1.1
|
||||
|
||||
@@ -37084,7 +37089,7 @@ packages:
|
||||
dependencies:
|
||||
bs-logger: 0.2.6
|
||||
fast-json-stable-stringify: 2.1.0
|
||||
jest: 29.6.2_@types+node@18.17.1
|
||||
jest: 29.6.2_@types+node@18.15.13
|
||||
jest-util: 29.6.2
|
||||
json5: 2.2.3
|
||||
lodash.memoize: 4.1.2
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
.trigger
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { HandleErrorFunction } from "@trigger.dev/core/v3";
|
||||
|
||||
export const handleError: HandleErrorFunction = async (payload, error, { ctx, retry }) => {
|
||||
console.log("GOT TO handleError FUNCTION");
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
import { logger, task } from "@trigger.dev/sdk/v3";
|
||||
import { exec } from "node:child_process";
|
||||
import { join } from "node:path";
|
||||
|
||||
const wranglerPath = join(__dirname, "node_modules", ".bin", "wrangler");
|
||||
|
||||
export const wranglerTask = task({
|
||||
id: "wrangler-task",
|
||||
run: async () => {
|
||||
logger.log(`Running wrangler from ${wranglerPath}`, {
|
||||
processEnv: process.env,
|
||||
cwd: process.cwd(),
|
||||
});
|
||||
|
||||
const version = await new Promise<string>((resolve, reject) => {
|
||||
exec(`${wranglerPath} --version`, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(stdout.trim());
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
version,
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -1,16 +0,0 @@
|
||||
// @ts-check
|
||||
/** @type {import('@trigger.dev/sdk/v3').Config} */
|
||||
|
||||
export default {
|
||||
project: "yubjwjsfkxnylobaqvqz",
|
||||
retries: {
|
||||
enabledInDev: false,
|
||||
default: {
|
||||
maxAttempts: 3,
|
||||
minTimeoutInMs: 1000,
|
||||
maxTimeoutInMs: 10000,
|
||||
factor: 2,
|
||||
randomize: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { ProjectConfig } from "@trigger.dev/core/v3";
|
||||
|
||||
export { handleError } from "./src/handleError";
|
||||
|
||||
export const config: ProjectConfig = {
|
||||
project: "yubjwjsfkxnylobaqvqz",
|
||||
retries: {
|
||||
enabledInDev: true,
|
||||
default: {
|
||||
maxAttempts: 3,
|
||||
minTimeoutInMs: 1000,
|
||||
maxTimeoutInMs: 10000,
|
||||
factor: 2,
|
||||
randomize: true,
|
||||
},
|
||||
},
|
||||
additionalPackages: ["wrangler@3.35.0"],
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"extends": "@trigger.dev/tsconfig/node18.json",
|
||||
"include": ["./src/**/*.ts", "trigger.config.mjs"],
|
||||
"include": ["./src/**/*.ts", "trigger.config.ts"],
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"lib": ["DOM", "DOM.Iterable"],
|
||||
|
||||
Reference in New Issue
Block a user