import { load as config } from "dotenv";
import { stringify } from "dotenv/stringify";
import { join } from "../deno_ral/path.ts";
import { safeExistsSync } from "../core/path.ts";
import { isEqual } from "../core/lodash.ts";
import { globalTempContext } from "../core/temp.ts";
import { existsSync } from "../deno_ral/fs.ts";
import { activeProfiles, kQuartoProfile } from "./profile.ts";
const kQuartoEnv = "_environment";
const kQuartoEnvLocal = `${kQuartoEnv}.local`;
const kQuartoEnvRequired = `${kQuartoEnv}.required`;
export async function dotenvQuartoProfile(projectDir: string) {
const conf1 = await config({
envPath: join(projectDir, kQuartoEnv),
});
const conf2 = await config({
envPath: join(projectDir, kQuartoEnvLocal),
});
return conf2[kQuartoProfile] || conf1[kQuartoProfile] || "";
}
const dotenvVariablesSet: string[] = [];
let prevDotenvVariablesDefined: Record<string, string> | undefined;
export async function dotenvSetVariables(projectDir: string) {
dotenvVariablesSet.forEach(Deno.env.delete);
dotenvVariablesSet.splice(0, dotenvVariablesSet.length);
const dotenvFiles = [
join(projectDir, kQuartoEnv),
...activeProfiles().reverse().map((profile) =>
join(projectDir, `_environment-${profile}`)
),
join(projectDir, kQuartoEnvLocal),
].filter(safeExistsSync).reverse();
const dotenvVariablesDefined: Record<string, string> = {};
for (const dotenvFile of dotenvFiles) {
const conf = await config({ envPath: dotenvFile });
for (const key in conf) {
if (Deno.env.get(key) === undefined) {
Deno.env.set(key, conf[key]);
dotenvVariablesSet.push(key);
}
if (dotenvVariablesDefined[key] === undefined) {
dotenvVariablesDefined[key] = conf[key];
}
}
}
const dotenvRequired = join(projectDir, kQuartoEnvRequired);
if (existsSync(dotenvRequired)) {
const definedEnvTempPath = globalTempContext().createFile({
suffix: ".yml",
});
Deno.writeTextFileSync(
definedEnvTempPath,
stringify(dotenvVariablesDefined),
);
await config({
envPath: definedEnvTempPath,
});
}
if (
prevDotenvVariablesDefined &&
!isEqual(dotenvVariablesDefined, prevDotenvVariablesDefined)
) {
fireDotenvChanged();
}
prevDotenvVariablesDefined = dotenvVariablesDefined;
return dotenvFiles;
}
const listeners = new Array<() => void>();
function fireDotenvChanged() {
listeners.forEach((listener) => listener());
}
export function onDotenvChanged(
listener: () => void,
) {
listeners.push(listener);
}