All files / dotenv / stringify.ts

100.00% Branches 22/22
100.00% Functions 1/1
100.00% Lines 34/34
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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
x6
x488
x488
x488
 
x488
x488
 
x1
x1
 
x1
x488
x488
x488
x488
x488
x488
x488
 
 
 
x436
x436
x436
x436
x436
x436
x487
x47
x47
 
x488
 
x483
x483
x483
x487
x487
x487
x488
x488


























































// Copyright 2018-2026 the Deno authors. MIT license.
// This module is browser compatible.

/**
 * Stringify an object into a valid `.env` file format.
 *
 * @example Usage
 * ```ts
 * import { stringify } from "@std/dotenv/stringify";
 * import { assertEquals } from "@std/assert";
 *
 * const object = { GREETING: "hello world" };
 * assertEquals(stringify(object), "GREETING='hello world'");
 * ```
 *
 * @param object object to be stringified
 * @returns string of object
 */
export function stringify(object: Record<string, string>): string {
  const lines: string[] = [];
  for (const [key, value] of Object.entries(object)) {
    let quote;

    let escapedValue = value ?? "";
    if (key.startsWith("#")) {
      // deno-lint-ignore no-console
      console.warn(
        `key starts with a '#' indicates a comment and is ignored: '${key}'`,
      );
      continue;
    } else if (
      escapedValue.includes("\n") ||
      escapedValue.includes("\r") ||
      escapedValue.includes("\t") ||
      escapedValue.includes("'") ||
      escapedValue.includes("\\")
    ) {
      // Escape backslashes first so we don't double-escape sequences we add
      // below (e.g. so a literal `\n` (backslash-n) is preserved distinctly
      // from a real newline).
      escapedValue = escapedValue
        .replaceAll("\\", "\\\\")
        .replaceAll("\n", "\\n")
        .replaceAll("\r", "\\r")
        .replaceAll("\t", "\\t");
      quote = `"`;
    } else if (escapedValue.match(/\W/)) {
      quote = "'";
    }

    if (quote) {
      // escape inner quotes
      escapedValue = escapedValue.replaceAll(quote, `\\${quote}`);
      escapedValue = `${quote}${escapedValue}${quote}`;
    }
    const line = `${key}=${escapedValue}`;
    lines.push(line);
  }
  return lines.join("\n");
}