Now that the CLI and the Next.js app are one package, nesting it inside app/ served no purpose - the repo root itself becomes the published npm package. Merges app/.gitignore and app/README.md into the root versions, drops the now-duplicate app/LICENSE, and updates path references (README, docs/ARCHITECTURE.md, docs/CONFIG_REFERENCE.md, package.json's repository.directory) that assumed the app/ nesting. Also fixes a real bug this surfaced: the in-app docs viewer resolved docs/ relative to process.cwd(), which only worked by accident when the CLI happened to be invoked from app/'s parent directory. A first attempt at fixing it with import.meta.dirname broke instead, for the same cross-module-graph reason config-path resolution already documented - Next compiles Route Handlers through a separate module graph that doesn't preserve source-relative import.meta paths. Fixed by exposing the app root via TRIGGERSHELL_APP_ROOT (set once in server.ts, where import.meta *does* resolve correctly), the same pattern already used for TRIGGERSHELL_CONFIG_PATH. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
44 lines
1.4 KiB
TypeScript
44 lines
1.4 KiB
TypeScript
import fs from "node:fs";
|
|
|
|
interface EnvEntry {
|
|
key: string;
|
|
value: string;
|
|
}
|
|
|
|
function parseEnvLines(content: string): EnvEntry[] {
|
|
const entries: EnvEntry[] = [];
|
|
for (const line of content.split("\n")) {
|
|
const trimmed = line.trim();
|
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
const eq = trimmed.indexOf("=");
|
|
if (eq === -1) continue;
|
|
entries.push({ key: trimmed.slice(0, eq), value: trimmed.slice(eq + 1) });
|
|
}
|
|
return entries;
|
|
}
|
|
|
|
/** Loads a `.env` file into `process.env`, without overriding vars already set. */
|
|
export function loadDotenv(envPath: string): void {
|
|
if (!fs.existsSync(envPath)) return;
|
|
for (const { key, value } of parseEnvLines(fs.readFileSync(envPath, "utf-8"))) {
|
|
if (process.env[key] === undefined) process.env[key] = value;
|
|
}
|
|
}
|
|
|
|
/** Sets `key=value` in a `.env` file, replacing an existing line for that key rather than duplicating it. */
|
|
export function upsertEnvVar(envPath: string, key: string, value: string): void {
|
|
const lines = fs.existsSync(envPath)
|
|
? fs.readFileSync(envPath, "utf-8").split("\n")
|
|
: [];
|
|
const prefix = `${key}=`;
|
|
const index = lines.findIndex((line) => line.startsWith(prefix));
|
|
const newLine = `${key}=${value}`;
|
|
if (index >= 0) {
|
|
lines[index] = newLine;
|
|
} else {
|
|
if (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();
|
|
lines.push(newLine);
|
|
}
|
|
fs.writeFileSync(envPath, lines.join("\n") + "\n");
|
|
}
|