Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/swift-eagles-float.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
---
"@trigger.dev/cli": patch
---

fix: Add an update sub-command the @trigger.dev/cli that updates all @trigger.dev/* packages
3 changes: 2 additions & 1 deletion packages/cli/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,8 +35,8 @@
"trigger-cli": "./dist/index.js"
},
"devDependencies": {
"@trigger.dev/tsconfig": "workspace:*",
"@gmrchk/cli-testing-library": "^0.1.2",
"@trigger.dev/tsconfig": "workspace:*",
"@types/gradient-string": "^1.1.2",
"@types/inquirer": "^9.0.3",
"@types/jest": "^29.5.3",
Expand DownExpand Up@@ -71,6 +71,7 @@
"nanoid": "^4.0.2",
"ngrok": "5.0.0-beta.2",
"node-fetch": "^3.3.0",
"npm-check-updates": "^16.12.2",
"openai": "^3.3.0",
"ora": "^6.1.2",
"path-to-regexp": "^6.2.1",
Expand Down
9 changes: 9 additions & 0 deletions packages/cli/src/cli/index.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,6 +8,7 @@ import { initCommand } from "../commands/init";
import { CLOUD_TRIGGER_URL, COMMAND_NAME } from "../consts";
import { telemetryClient } from "../telemetry/telemetry";
import { getVersion } from "../utils/getVersion";
import { updateCommand } from "../commands/update";

export const program = new Command();

Expand DownExpand Up@@ -80,6 +81,14 @@ program
await createIntegrationCommand(path, options);
});

program
.command("update")
.description("Updates all @trigger.dev/* packages to their latest compatible versions")
.argument("[path]", "The path to the directory that contains the package.json file", ".")
.action(async (path) => {
await updateCommand(path);
});

program
.command("whoami")
.description("display the current logged in user and project details")
Expand Down
101 changes: 101 additions & 0 deletions packages/cli/src/commands/update.ts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
import path from "path";
import inquirer from "inquirer";
import { run, RunOptions } from "npm-check-updates";
import { installDependencies } from "../utils/installDependencies.js";
import { readJSONFileSync, writeJSONFile } from "../utils/fileSystem.js";

export async function updateCommand(projectPath: string) {
const triggerDevPackage = "@trigger.dev";
const packageJSONPath = path.join(projectPath, "package.json")
const packageData = readJSONFileSync(packageJSONPath);

if (!packageData) {
return;
}

const packageMaps: { [k: string]: { type: string; version: string } } = {};
const packageDependencies = packageData.dependencies || {};
const packageDevDependencies = packageData.devDependencies || {};
Object.keys(packageDependencies).forEach((i) => {
packageMaps[i] = { type: "dependencies", version: packageDependencies[i] };
});
Object.keys(packageDevDependencies).forEach((i) => {
packageMaps[i] = {
type: "devDependencies",
version: packageDevDependencies[i],
};
});

// Use npm-check-updates to get updated dependency versions
const ncuOptions: RunOptions = {
packageData,
upgrade: true,
jsonUpgraded: true,
};

// Can either give a json like package.json or just with deps and their new versions
const updatedDependencies: { [k: string]: any } | void = await run(ncuOptions);

if (!updatedDependencies) return;

const ifUpdatedDependenciesIsPackageJSON =
updatedDependencies.hasOwnProperty("dependencies") ||
updatedDependencies.hasOwnProperty("devDependencies");

const dependencies = updatedDependencies.dependencies || {};
const devDependencies = updatedDependencies.devDependencies || {};

const allDependencies = ifUpdatedDependenciesIsPackageJSON
? Object.keys({ ...dependencies, ...devDependencies })
: Object.keys(updatedDependencies);

const triggerPackages = allDependencies.filter((pkg) => pkg.startsWith(triggerDevPackage));

// If there are no @trigger.dev packages
if (triggerPackages.length === 0) {
console.log("No @trigger.dev/* packages found in package.json.");
return;
}

// Filter the packages with null and what don't match what
// they are installed with so that they can be updated
const packagesToUpdate = triggerPackages.filter((pkg: string) => updatedDependencies[pkg]);

// If no packages require any updation
if (packagesToUpdate.length === 0) {
console.log("All @trigger.dev/* packages are up to date.");
return;
}

// Inform the user of the dependencies that can be updated
console.log("\nNewer versions found for the following packages:");
console.table(
packagesToUpdate.map((i) => ({
name: i,
old: packageMaps[i]?.version,
new: updatedDependencies[i],
}))
);

// Ask the user if they want to update the dependencies
const { confirm } = await inquirer.prompt({
type: "confirm",
name: "confirm",
message: "Do you want to update these packages in package.json and re-install dependencies?",
});

if (confirm) {
const newPackageJSON = packageData;
packagesToUpdate.forEach((packageName) => {
const tmp = packageMaps[packageName];
if (tmp) {
newPackageJSON[tmp.type][packageName] = updatedDependencies[packageName];
}
});
await writeJSONFile(packageJSONPath, newPackageJSON);
console.log("package.json updated. Reinstalling dependencies...");
await installDependencies(projectPath);
} else {
console.log("Operation canceled. No changes were made.");
}
}
Loading