bgipfs
Version:
BuidlGuidl IPFS CLI
81 lines (80 loc) • 2.9 kB
JavaScript
import * as dotenv from 'dotenv';
import { promises as fs } from 'node:fs';
import { baseSchema } from './env-schema.js';
export class EnvManager {
filePath;
constructor(filePath = '.env') {
this.filePath = filePath;
}
async appendNewline() {
const content = await fs.readFile(this.filePath, 'utf8');
if (!content.endsWith('\n')) {
await fs.appendFile(this.filePath, '\n');
}
}
async ensureEnvFile() {
try {
await fs.access(this.filePath);
}
catch {
await fs.writeFile(this.filePath, '');
}
}
async exists() {
try {
await fs.access(this.filePath);
return true;
}
catch {
return false;
}
}
// Helper to get typed env values
async getEnvValue(key, options = {}) {
const env = await this.readEnv(options);
return env[key];
}
async readEnv(options = {}) {
await this.ensureEnvFile();
const content = await fs.readFile(this.filePath, 'utf8');
const parsed = dotenv.parse(content);
// Use provided schema or default to base schema
const selectedSchema = options.schema || baseSchema;
// Make schema partial if requested
const schema = options.partial ? selectedSchema.partial() : selectedSchema;
const result = schema.safeParse(parsed);
if (!result.success) {
const formatted = result.error.format();
throw new Error(`Invalid environment configuration: ${JSON.stringify(formatted, null, 2)}`);
}
return result.data;
}
async readRawEnv() {
await this.ensureEnvFile();
const content = await fs.readFile(this.filePath, 'utf8');
return dotenv.parse(content);
}
async updateEnv(updates) {
await this.ensureEnvFile();
// Get current raw env including unknown properties
const content = await fs.readFile(this.filePath, 'utf8');
const currentEnv = dotenv.parse(content);
// Apply updates
const newEnv = {
...currentEnv, // Preserve all existing values including unknown ones
...Object.fromEntries(updates.map(({ key, value }) => [key, value])),
};
// Validate with base schema
const result = baseSchema.safeParse(newEnv);
if (!result.success) {
throw new Error(`Invalid environment update: ${JSON.stringify(result.error.format(), null, 2)}`);
}
// Write back to file preserving all properties
const newContent = Object.entries(newEnv)
.map(([key, value]) => `${key}=${value}`)
.join('\n');
await fs.writeFile(this.filePath, newContent + '\n');
// Reload environment variables
dotenv.config({ override: true, path: this.filePath });
}
}