Skip to content

Commit 6769d6b

Browse files
committed
Squashed commit of the following:
commit c028db2 Author: Matt Aitken <[email protected]> Date: Fri Oct 13 16:04:54 2023 +0100 Some fixes for getting the endpoint id commit e31b7ac Author: Matt Aitken <[email protected]> Date: Fri Oct 13 15:39:18 2023 +0100 Added a link in the instructions if Node isn’t detected commit 1a59cce Author: Matt Aitken <[email protected]> Date: Fri Oct 13 15:39:05 2023 +0100 Fixed some conflict issues commit 77263ed Author: Matt Aitken <[email protected]> Date: Fri Oct 13 15:38:56 2023 +0100 Added a changeset commit 1a7df3f Author: GuyBorderless <[email protected]> Date: Fri Oct 13 17:31:01 2023 +0300 feat: enable deno (#531) * adding deno reference project and JSRuntime file * accessing runtime specific functions through JsRuntime * adding support for both deno.json and deno.jsonc * no automatic setup for deno projects currently --------- Co-authored-by: Guy Kedem <[email protected]> Co-authored-by: Matt Aitken <[email protected]>
1 parent 70410d3 commit 6769d6b

File tree

12 files changed

+923
-52
lines changed

12 files changed

+923
-52
lines changed

.changeset/famous-files-talk.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@trigger.dev/cli": patch
3+
---
4+
5+
Detects JSRuntime (Node/Deno at the moment). Adds basic Deno support

.vscode/extensions.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"recommendations": [
3+
"astro-build.astro-vscode",
4+
"denoland.vscode-deno"
5+
],
6+
"unwantedRecommendations": [
7+
8+
]
9+
}

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"deno.enablePaths": ["references/deno-reference"]
3+
}

packages/cli/src/commands/dev.ts

Lines changed: 14 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,18 @@
11
import boxen from "boxen";
2-
import chalk from "chalk";
32
import childProcess from "child_process";
43
import chokidar from "chokidar";
5-
import fs from "fs/promises";
64
import ngrok from "ngrok";
7-
import { run as ncuRun } from "npm-check-updates";
85
import ora, { Ora } from "ora";
96
import pRetry, { AbortError } from "p-retry";
10-
import pathModule from "path";
117
import util from "util";
128
import { z } from "zod";
13-
import { Framework, getFramework } from "../frameworks";
9+
import { Framework } from "../frameworks";
1410
import { standardWatchFilePaths, standardWatchIgnoreRegex } from "../frameworks/watchConfig";
1511
import { telemetryClient } from "../telemetry/telemetry";
1612
import { getEnvFilename } from "../utils/env";
1713
import fetch from "../utils/fetchUseProxy";
1814
import { getTriggerApiDetails } from "../utils/getTriggerApiDetails";
19-
import { getUserPackageManager } from "../utils/getUserPkgManager";
15+
import { JsRuntime, getJsRuntime } from "../utils/jsRuntime";
2016
import { logger } from "../utils/logger";
2117
import { resolvePath } from "../utils/parseNameAndPath";
2218
import { RequireKeys } from "../utils/requiredKeys";
@@ -45,6 +41,8 @@ const formattedDate = new Intl.DateTimeFormat("en", {
4541
second: "numeric",
4642
});
4743

44+
let runtime: JsRuntime;
45+
4846
export async function devCommand(path: string, anyOptions: any) {
4947
telemetryClient.dev.started(path, anyOptions);
5048

@@ -57,12 +55,12 @@ export async function devCommand(path: string, anyOptions: any) {
5755
const options = result.data;
5856

5957
const resolvedPath = resolvePath(path);
60-
58+
runtime = await getJsRuntime(resolvedPath, logger);
6159
//check for outdated packages, don't await this
62-
checkForOutdatedPackages(resolvedPath);
60+
runtime.checkForOutdatedPackages();
6361

6462
// Read from package.json to get the endpointId
65-
const endpointId = await getEndpointIdFromPackageJson(resolvedPath, options);
63+
const endpointId = await getEndpointId(runtime, options.clientId);
6664
if (!endpointId) {
6765
logger.error(
6866
"You must run the `init` command first to setup the project – you are missing \n'trigger.dev': { 'endpointId': 'your-client-id' } from your package.json file, or pass in the --client-id option to this command"
@@ -73,8 +71,8 @@ export async function devCommand(path: string, anyOptions: any) {
7371
logger.success(`✔️ [trigger.dev] Detected TriggerClient id: ${endpointId}`);
7472

7573
//resolve the options using the detected framework (use default if there isn't a matching framework)
76-
const packageManager = await getUserPackageManager(resolvedPath);
77-
const framework = await getFramework(resolvedPath, packageManager);
74+
const packageManager = await runtime.getUserPackageManager();
75+
const framework = await runtime.getFramework();
7876
const resolvedOptions = await resolveOptions(framework, resolvedPath, options);
7977

8078
// Read from .env.local or .env to get the TRIGGER_API_KEY and TRIGGER_API_URL
@@ -250,8 +248,7 @@ async function startIndexing({
250248
apiClient,
251249
}: RefreshOptions & { apiClient: TriggerApi }) {
252250
spinner.start();
253-
254-
const refreshedEndpointId = await getEndpointIdFromPackageJson(path, resolvedOptions);
251+
const refreshedEndpointId = await getEndpointId(runtime, resolvedOptions.clientId);
255252

256253
const authorizedKey = await apiClient.whoami();
257254
if (!authorizedKey) {
@@ -396,43 +393,10 @@ async function verifyEndpoint(
396393
return;
397394
}
398395

399-
export async function checkForOutdatedPackages(path: string) {
400-
const updates = (await ncuRun({
401-
packageFile: `${path}/package.json`,
402-
filter: "/trigger.dev/.+$/",
403-
upgrade: false,
404-
})) as {
405-
[key: string]: string;
406-
};
407-
408-
if (typeof updates === "undefined" || Object.keys(updates).length === 0) {
409-
return;
410-
}
411-
412-
const packageFile = await fs.readFile(`${path}/package.json`);
413-
const data = JSON.parse(Buffer.from(packageFile).toString("utf8"));
414-
const dependencies = data.dependencies;
415-
console.log(chalk.bgYellow("Updates available for trigger.dev packages"));
416-
console.log(chalk.bgBlue("Run npx @trigger.dev/cli@latest update"));
417-
418-
for (let dep in updates) {
419-
console.log(`${dep} ${dependencies[dep]}${updates[dep]}`);
420-
}
421-
}
422-
423-
export async function getEndpointIdFromPackageJson(path: string, options: DevCommandOptions) {
424-
if (options.clientId) {
425-
return options.clientId;
426-
}
427-
428-
const pkgJsonPath = pathModule.join(path, "package.json");
429-
const pkgBuffer = await fs.readFile(pkgJsonPath);
430-
const pkgJson = JSON.parse(pkgBuffer.toString());
431-
432-
const value = pkgJson["trigger.dev"]?.endpointId;
433-
if (!value || typeof value !== "string") return;
434-
435-
return value as string;
396+
export function getEndpointId(runtime: JsRuntime, clientId?: string) {
397+
if (clientId) {
398+
return clientId;
399+
} else return runtime.getEndpointId();
436400
}
437401

438402
async function resolveEndpointUrl(apiUrl: string, port: number, hostname: string) {

packages/cli/src/commands/init.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { resolvePath } from "../utils/parseNameAndPath";
2222
import { readPackageJson } from "../utils/readPackageJson";
2323
import { renderTitle } from "../utils/renderTitle";
2424
import { TriggerApi, WhoamiResponse } from "../utils/triggerApi";
25+
import { getJsRuntime } from "../utils/jsRuntime";
2526

2627
export type InitCommandOptions = {
2728
projectPath: string;
@@ -38,6 +39,19 @@ export const initCommand = async (options: InitCommandOptions) => {
3839

3940
const resolvedPath = resolvePath(options.projectPath);
4041

42+
// assuming nodejs by default
43+
let runtimeId: string = "nodejs";
44+
try {
45+
runtimeId = (await getJsRuntime(resolvedPath, logger)).id;
46+
} catch {}
47+
if (runtimeId !== "nodejs") {
48+
logger.error(
49+
`We currently only support automatic setup for NodeJS projects. This is a ${runtimeId} project. View our manual installation guides here: https://trigger.dev/docs/documentation/quickstarts/introduction`
50+
);
51+
telemetryClient.init.failed("not_supported_runtime", options);
52+
return;
53+
}
54+
4155
await renderTitle(resolvedPath);
4256

4357
if (options.triggerUrl === CLOUD_TRIGGER_URL) {

packages/cli/src/commands/whoami.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ import { z } from "zod";
22
import { logger } from "../utils/logger";
33
import { resolvePath } from "../utils/parseNameAndPath";
44
import { TriggerApi } from "../utils/triggerApi";
5-
import { DevCommandOptions, getEndpointIdFromPackageJson } from "./dev";
5+
import { DevCommandOptions, getEndpointId } from "./dev";
66
import ora from "ora";
77
import { getTriggerApiDetails } from "../utils/getTriggerApiDetails";
8+
import { getJsRuntime } from "../utils/jsRuntime";
89

910
export const WhoAmICommandOptionsSchema = z.object({
1011
envFile: z.string(),
@@ -26,7 +27,8 @@ export async function whoamiCommand(path: string, anyOptions: any) {
2627
const resolvedPath = resolvePath(path);
2728

2829
// Read from package.json to get the endpointId
29-
const endpointId = await getEndpointIdFromPackageJson(resolvedPath, options as DevCommandOptions);
30+
const runtime = await getJsRuntime(resolvedPath, logger);
31+
const endpointId = await getEndpointId(runtime);
3032
if (!endpointId) {
3133
logger.error(
3234
"You must run the `init` command first to setup the project – you are missing \n'trigger.dev': { 'endpointId': 'your-client-id' } from your package.json file, or pass in the --client-id option to this command"

packages/cli/src/utils/jsRuntime.ts

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import { Framework, getFramework } from "../frameworks";
2+
import { PackageManager, getUserPackageManager } from "./getUserPkgManager";
3+
import { Logger } from "./logger";
4+
import { run as ncuRun } from "npm-check-updates";
5+
import chalk from "chalk";
6+
import fs from "fs/promises";
7+
import pathModule from "path";
8+
9+
export abstract class JsRuntime {
10+
logger: Logger;
11+
projectRootPath: string;
12+
constructor(projectRootPath: string, logger: Logger) {
13+
this.logger = logger;
14+
this.projectRootPath = projectRootPath;
15+
}
16+
abstract get id(): string;
17+
abstract checkForOutdatedPackages(): Promise<void>;
18+
abstract getUserPackageManager(): Promise<PackageManager | undefined>;
19+
abstract getFramework(): Promise<Framework | undefined>;
20+
abstract getEndpointId(): Promise<string | undefined>;
21+
}
22+
23+
export async function getJsRuntime(projectRootPath: string, logger: Logger): Promise<JsRuntime> {
24+
if (await NodeJsRuntime.isNodeJsRuntime(projectRootPath)) {
25+
return new NodeJsRuntime(projectRootPath, logger);
26+
} else if (await DenoRuntime.isDenoJsRuntime(projectRootPath)) {
27+
return new DenoRuntime(projectRootPath, logger);
28+
}
29+
throw new Error("Unsupported runtime");
30+
}
31+
32+
class NodeJsRuntime extends JsRuntime {
33+
static async isNodeJsRuntime(projectRootPath: string): Promise<boolean> {
34+
try {
35+
await fs.stat(pathModule.join(projectRootPath, "package.json"));
36+
return true;
37+
} catch {
38+
return false;
39+
}
40+
}
41+
42+
get id() {
43+
return "nodejs";
44+
}
45+
get packageJsonPath(): string {
46+
return pathModule.join(this.projectRootPath, "package.json");
47+
}
48+
49+
async checkForOutdatedPackages(): Promise<void> {
50+
const updates = (await ncuRun({
51+
packageFile: `${this.packageJsonPath}`,
52+
filter: "/trigger.dev/.+$/",
53+
upgrade: false,
54+
})) as {
55+
[key: string]: string;
56+
};
57+
58+
if (typeof updates === "undefined" || Object.keys(updates).length === 0) {
59+
return;
60+
}
61+
62+
const packageFile = await fs.readFile(this.packageJsonPath);
63+
const data = JSON.parse(Buffer.from(packageFile).toString("utf8"));
64+
const dependencies = data.dependencies;
65+
console.log(chalk.bgYellow("Updates available for trigger.dev packages"));
66+
console.log(chalk.bgBlue("Run npx @trigger.dev/cli@latest update"));
67+
68+
for (let dep in updates) {
69+
console.log(`${dep} ${dependencies[dep]}${updates[dep]}`);
70+
}
71+
}
72+
73+
async getUserPackageManager() {
74+
return getUserPackageManager(this.projectRootPath);
75+
}
76+
77+
async getFramework() {
78+
const userPackageManager = await this.getUserPackageManager();
79+
return getFramework(this.projectRootPath, userPackageManager);
80+
}
81+
async getEndpointId() {
82+
const pkgJsonPath = pathModule.join(this.projectRootPath, "package.json");
83+
const pkgBuffer = await fs.readFile(pkgJsonPath);
84+
const pkgJson = JSON.parse(pkgBuffer.toString());
85+
const value = pkgJson["trigger.dev"]?.endpointId;
86+
if (!value || typeof value !== "string") return undefined;
87+
return value;
88+
}
89+
}
90+
91+
class DenoRuntime extends JsRuntime {
92+
getDenoJsonPath(): Promise<string> {
93+
try {
94+
return fs
95+
.stat(pathModule.join(this.projectRootPath, "deno.json"))
96+
.then(() => pathModule.join(this.projectRootPath, "deno.json"));
97+
} catch {
98+
return fs
99+
.stat(pathModule.join(this.projectRootPath, "deno.jsonc"))
100+
.then(() => pathModule.join(this.projectRootPath, "deno.jsonc"));
101+
}
102+
}
103+
104+
get id() {
105+
return "deno";
106+
}
107+
108+
static async isDenoJsRuntime(projectRootPath: string): Promise<boolean> {
109+
try {
110+
try {
111+
await fs.stat(pathModule.join(projectRootPath, "deno.json"));
112+
} catch (e) {
113+
await fs.stat(pathModule.join(projectRootPath, "deno.jsonc"));
114+
}
115+
return true;
116+
} catch {
117+
return false;
118+
}
119+
}
120+
121+
async checkForOutdatedPackages() {
122+
// not implemented currently
123+
}
124+
async getUserPackageManager() {
125+
return undefined;
126+
}
127+
async getFramework() {
128+
// not implemented currently
129+
return undefined;
130+
}
131+
async getEndpointId() {
132+
const pkgJsonPath = await this.getDenoJsonPath();
133+
const pkgBuffer = await fs.readFile(pkgJsonPath);
134+
const pkgJson = JSON.parse(pkgBuffer.toString());
135+
return pkgJson["trigger.dev"]?.endpointId;
136+
}
137+
}

packages/cli/src/utils/logger.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import chalk from "chalk";
22

3+
export type Logger = typeof logger;
34
export const logger = {
45
error(...args: unknown[]) {
56
console.log(chalk.red(...args));
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"deno.enable": true
3+
}

references/deno-reference/deno.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"trigger.dev": {
3+
"endpointId": "borderless"
4+
},
5+
"tasks": {
6+
"dev": "deno run --watch main.ts"
7+
}
8+
}

0 commit comments

Comments
 (0)