-
Notifications
You must be signed in to change notification settings - Fork 154
/
Copy pathdot-env.ts
96 lines (84 loc) · 2.58 KB
/
dot-env.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import {AbortError} from './error.js'
import {fileExists, readFile, writeFile} from './fs.js'
import {outputDebug, outputContent, outputToken} from '../../public/node/output.js'
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import {parse, stringify} from 'envfile'
/**
* Error that's thrown when the .env is not found.
* @param path - Path to the .env file.
* @returns An abort error.
*/
export const DotEnvNotFoundError = (path: string): AbortError => {
return new AbortError(`The environment file at ${path} does not exist.`)
}
/**
* This interface represents a .env file.
*/
export interface DotEnvFile {
/**
* Path to the .env file.
*/
path: string
/**
* Variables of the .env file.
*/
variables: {[name: string]: string}
}
/**
* Reads and parses a .env file.
* @param path - Path to the .env file
* @returns An in-memory representation of the .env file.
*/
export async function readAndParseDotEnv(path: string): Promise<DotEnvFile> {
outputDebug(outputContent`Reading the .env file at ${outputToken.path(path)}`)
if (!(await fileExists(path))) {
throw DotEnvNotFoundError(path)
}
const content = await readFile(path)
return {
path,
variables: parse(content),
}
}
/**
* Writes a .env file to disk.
* @param file - .env file to be written.
*/
export async function writeDotEnv(file: DotEnvFile): Promise<void> {
await writeFile(file.path, stringify(file.variables))
}
/**
* Given an .env file content, generates a new one with new values
* without removing already existing lines.
* @param envFileContent - .env file contents.
* @param updatedValues - object containing new env variables values.
*/
export function patchEnvFile(
envFileContent: string | null,
updatedValues: {[key: string]: string | undefined},
): string {
const outputLines: string[] = []
const lines = envFileContent === null ? [] : envFileContent.split('\n')
const alreadyPresentKeys: string[] = []
const toLine = (key: string, value?: string) => `${key}=${value}`
for (const line of lines) {
const match = line.match(/^([^=:#]+?)[=:](.*)/)
let lineToWrite = line
if (match) {
const key = match[1]!.trim()
const newValue = updatedValues[key]
if (newValue) {
alreadyPresentKeys.push(key)
lineToWrite = toLine(key, newValue)
}
}
outputLines.push(lineToWrite)
}
for (const [patchKey, updatedValue] of Object.entries(updatedValues)) {
if (!alreadyPresentKeys.includes(patchKey)) {
outputLines.push(toLine(patchKey, updatedValue))
}
}
return outputLines.join('\n')
}