diff --git a/.changeset/strong-cars-visit.md b/.changeset/strong-cars-visit.md new file mode 100644 index 000000000..c3a4a7a52 --- /dev/null +++ b/.changeset/strong-cars-visit.md @@ -0,0 +1,5 @@ +--- +"@trigger.dev/init": patch +--- + +Fixed an issue that cause environment variables to be incorrectly added to .env.local diff --git a/packages/init-trigger/src/cli/index.ts b/packages/init-trigger/src/cli/index.ts index f398443ef..499ab35ef 100644 --- a/packages/init-trigger/src/cli/index.ts +++ b/packages/init-trigger/src/cli/index.ts @@ -202,8 +202,8 @@ const promptEndpointUrl = async (instanceUrl: string): Promise => { }>({ type: "input", name: "endpointUrl", - message: - "What's the URL of your Next.js project? (e.g. http://localhost:3000)", + default: "http://localhost:3000", + message: "What's the URL of your Next.js project?", validate: (input) => { if (!input) { return "Please enter the URL of your Next.js project"; @@ -214,7 +214,7 @@ const promptEndpointUrl = async (instanceUrl: string): Promise => { const triggerUrl = new URL(instanceUrl); if (triggerUrl.hostname !== "localhost" && url.hostname === "localhost") { - return `Your Trigger.dev instance is hosted at ${triggerUrl.hostname}, so your Next.js project must also be publicly accessible. See our docs for more info: https://trigger.dev/docs/guides/tunneling`; + return `Your Trigger.dev instance is hosted at ${triggerUrl.hostname}, so your Next.js project must also be publicly accessible. See our docs for more info: https://trigger.dev/docs/documentation/guides/tunneling-localhost`; } // Make sure triggerUrl and url don't use the same port if they are both localhost diff --git a/packages/init-trigger/src/index.ts b/packages/init-trigger/src/index.ts index c664b719f..af4b0aec1 100644 --- a/packages/init-trigger/src/index.ts +++ b/packages/init-trigger/src/index.ts @@ -11,6 +11,7 @@ import { simpleGit } from "simple-git"; import { TriggerApi } from "./utils/triggerApi.js"; import { DEFAULT_TRIGGER_URL } from "./consts.js"; import ora from "ora"; +import { renderApiKey } from "./utils/renderApiKey.js"; const main = async () => { renderTitle(); @@ -315,69 +316,78 @@ export const { POST, dynamic } = createAppRoute(client, { } async function setupEnvironmentVariables(path: string, cliResults: CliResults) { - const envFilePath = pathModule.join(path, ".env.local"); - const envFileExists = await pathExists(envFilePath); + if (cliResults.flags.apiKey) { + await setupEnvironmentVariable( + path, + ".env.local", + "TRIGGER_API_KEY", + cliResults.flags.apiKey, + true, + renderApiKey + ); + } - if (envFileExists) { - const envFileContent = await fs.readFile(envFilePath, "utf-8"); + if (cliResults.flags.triggerUrl) { + await setupEnvironmentVariable( + path, + ".env.local", + "TRIGGER_API_URL", + cliResults.flags.triggerUrl, + true + ); + } - if (envFileContent.includes("TRIGGER_API_KEY")) { - // Update the existing value - const updatedEnvFileContent = envFileContent.replace( - /TRIGGER_API_KEY=.*/g, - `TRIGGER_API_KEY=${cliResults.flags.apiKey}` + if (cliResults.flags.endpointUrl) { + await setupEnvironmentVariable( + path, + ".env.local", + "VERCEL_URL", + cliResults.flags.endpointUrl, + false + ); + } +} + +async function setupEnvironmentVariable( + dir: string, + fileName: string, + variableName: string, + value: string, + replaceValue: boolean = true, + renderer: (value: string) => string = (value) => value +) { + const path = pathModule.join(dir, fileName); + const envFileExists = await pathExists(path); + + if (!envFileExists) { + await fs.writeFile(path, ""); + } + + const envFileContent = await fs.readFile(path, "utf-8"); + + if (envFileContent.includes(variableName)) { + if (!replaceValue) { + logger.info( + `☑ Skipping setting ${variableName}=${renderer( + value + )} because it already exists` ); - - await fs.writeFile(envFilePath, updatedEnvFileContent); - - logger.success("✅ Updated TRIGGER_API_KEY in .env.local"); - } else { - await fs.appendFile( - envFilePath, - `TRIGGER_API_KEY=${cliResults.flags.apiKey}\n` - ); - - logger.success("✅ Added TRIGGER_API_KEY to .env.local"); + return; } + // Update the existing value + const updatedEnvFileContent = envFileContent.replace( + new RegExp(`${variableName}=.*\\n`, "g"), + `${variableName}=${value}\n` + ); - if (envFileContent.includes("TRIGGER_API_URL")) { - // Update existing value - const updatedEnvFileContent = envFileContent.replace( - /TRIGGER_API_URL=.*/g, - `TRIGGER_API_URL=${cliResults.flags.triggerUrl}` - ); + await fs.writeFile(path, updatedEnvFileContent); - await fs.writeFile(envFilePath, updatedEnvFileContent); - - logger.success("✅ Updated TRIGGER_API_URL in .env.local"); - } else { - await fs.appendFile( - envFilePath, - `TRIGGER_API_URL=${cliResults.flags.triggerUrl}\n` - ); - - logger.success("✅ Added TRIGGER_API_URL to .env.local"); - } - - if (!envFileContent.includes("VERCEL_URL")) { - await fs.appendFile( - envFilePath, - `VERCEL_URL=${cliResults.flags.endpointUrl}\n` - ); - - logger.success("✅ Added VERCEL_URL to .env.local"); - } + logger.success(`✅ Set ${variableName}=${renderer(value)} in ${fileName}`); } else { - const envFileContent = ` -TRIGGER_API_KEY=${cliResults.flags.apiKey} -TRIGGER_API_URL=${cliResults.flags.triggerUrl} -VERCEL_URL=${cliResults.flags.endpointUrl} - `; - - await fs.writeFile(envFilePath, envFileContent); + await fs.appendFile(path, `\n${variableName}=${value}`); logger.success( - "✅ Created .env.local and added required environment variables" + `✅ Added ${variableName}=${renderer(value)} to ${fileName}` ); } } diff --git a/packages/init-trigger/src/utils/renderApiKey.ts b/packages/init-trigger/src/utils/renderApiKey.ts new file mode 100644 index 000000000..adf213a3a --- /dev/null +++ b/packages/init-trigger/src/utils/renderApiKey.ts @@ -0,0 +1,4 @@ +// Obfuscate the API key (will be in the format tr_dev_XXXX) +export function renderApiKey(apiKey: string): string { + return apiKey.replace(/tr_dev_[a-zA-Z0-9]{6}/g, "tr_dev_********"); +}