neonctl 2.28.0 → 2.29.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/README.md +71 -71
  2. package/dist/analytics.js +35 -33
  3. package/dist/api.js +34 -34
  4. package/dist/auth.js +50 -44
  5. package/dist/cli.js +2 -2
  6. package/dist/commands/auth.js +58 -52
  7. package/dist/commands/bootstrap.js +115 -157
  8. package/dist/commands/branches.js +154 -147
  9. package/dist/commands/bucket.js +124 -118
  10. package/dist/commands/checkout.js +49 -49
  11. package/dist/commands/config.js +212 -88
  12. package/dist/commands/connection_string.js +62 -62
  13. package/dist/commands/data_api.js +96 -96
  14. package/dist/commands/databases.js +23 -23
  15. package/dist/commands/deploy.js +12 -12
  16. package/dist/commands/dev.js +114 -114
  17. package/dist/commands/env.js +43 -43
  18. package/dist/commands/functions.js +97 -98
  19. package/dist/commands/index.js +26 -26
  20. package/dist/commands/init.js +23 -22
  21. package/dist/commands/ip_allow.js +29 -29
  22. package/dist/commands/link.js +223 -166
  23. package/dist/commands/neon_auth.js +381 -363
  24. package/dist/commands/operations.js +11 -11
  25. package/dist/commands/orgs.js +8 -8
  26. package/dist/commands/projects.js +101 -99
  27. package/dist/commands/psql.js +31 -31
  28. package/dist/commands/roles.js +21 -21
  29. package/dist/commands/schema_diff.js +23 -23
  30. package/dist/commands/set_context.js +17 -17
  31. package/dist/commands/status.js +17 -17
  32. package/dist/commands/user.js +5 -5
  33. package/dist/commands/vpc_endpoints.js +50 -50
  34. package/dist/config.js +7 -7
  35. package/dist/config_format.js +5 -5
  36. package/dist/context.js +23 -16
  37. package/dist/current_branch_fast_path.js +6 -6
  38. package/dist/dev/env.js +34 -34
  39. package/dist/dev/functions.js +4 -4
  40. package/dist/dev/inputs.js +6 -6
  41. package/dist/dev/runtime.js +25 -25
  42. package/dist/env.js +14 -14
  43. package/dist/env_file.js +13 -13
  44. package/dist/errors.js +19 -19
  45. package/dist/functions_api.js +10 -10
  46. package/dist/help.js +15 -15
  47. package/dist/index.js +94 -92
  48. package/dist/log.js +2 -2
  49. package/dist/pkg.js +5 -5
  50. package/dist/psql/cli.js +4 -2
  51. package/dist/psql/command/cmd_cond.js +61 -61
  52. package/dist/psql/command/cmd_connect.js +159 -154
  53. package/dist/psql/command/cmd_copy.js +107 -97
  54. package/dist/psql/command/cmd_describe.js +368 -363
  55. package/dist/psql/command/cmd_format.js +276 -263
  56. package/dist/psql/command/cmd_io.js +269 -263
  57. package/dist/psql/command/cmd_lo.js +74 -66
  58. package/dist/psql/command/cmd_meta.js +148 -148
  59. package/dist/psql/command/cmd_misc.js +17 -17
  60. package/dist/psql/command/cmd_pipeline.js +142 -135
  61. package/dist/psql/command/cmd_restrict.js +25 -25
  62. package/dist/psql/command/cmd_show.js +183 -168
  63. package/dist/psql/command/dispatch.js +26 -26
  64. package/dist/psql/command/shared.js +14 -14
  65. package/dist/psql/complete/filenames.js +16 -16
  66. package/dist/psql/complete/index.js +4 -4
  67. package/dist/psql/complete/matcher.js +33 -32
  68. package/dist/psql/complete/psqlVars.js +173 -173
  69. package/dist/psql/complete/queries.js +5 -3
  70. package/dist/psql/complete/rules.js +900 -863
  71. package/dist/psql/core/common.js +136 -133
  72. package/dist/psql/core/help.js +343 -343
  73. package/dist/psql/core/mainloop.js +160 -153
  74. package/dist/psql/core/prompt.js +126 -123
  75. package/dist/psql/core/settings.js +111 -111
  76. package/dist/psql/core/sqlHelp.js +150 -150
  77. package/dist/psql/core/startup.js +211 -205
  78. package/dist/psql/core/syncVars.js +14 -14
  79. package/dist/psql/core/variables.js +24 -24
  80. package/dist/psql/describe/formatters.js +302 -289
  81. package/dist/psql/describe/processNamePattern.js +28 -28
  82. package/dist/psql/describe/queries.js +656 -651
  83. package/dist/psql/index.js +436 -411
  84. package/dist/psql/io/history.js +36 -36
  85. package/dist/psql/io/input.js +15 -15
  86. package/dist/psql/io/lineEditor/buffer.js +27 -25
  87. package/dist/psql/io/lineEditor/complete.js +15 -15
  88. package/dist/psql/io/lineEditor/filename.js +22 -22
  89. package/dist/psql/io/lineEditor/index.js +65 -62
  90. package/dist/psql/io/lineEditor/keymap.js +325 -318
  91. package/dist/psql/io/lineEditor/vt100.js +60 -60
  92. package/dist/psql/io/pgpass.js +18 -18
  93. package/dist/psql/io/pgservice.js +14 -14
  94. package/dist/psql/io/psqlrc.js +46 -46
  95. package/dist/psql/print/aligned.js +175 -166
  96. package/dist/psql/print/asciidoc.js +51 -51
  97. package/dist/psql/print/crosstab.js +34 -31
  98. package/dist/psql/print/csv.js +25 -22
  99. package/dist/psql/print/html.js +54 -54
  100. package/dist/psql/print/json.js +12 -12
  101. package/dist/psql/print/latex.js +118 -118
  102. package/dist/psql/print/pager.js +28 -26
  103. package/dist/psql/print/troff.js +48 -48
  104. package/dist/psql/print/unaligned.js +15 -14
  105. package/dist/psql/print/units.js +17 -17
  106. package/dist/psql/scanner/slash.js +48 -46
  107. package/dist/psql/scanner/sql.js +88 -84
  108. package/dist/psql/scanner/stringutils.js +21 -17
  109. package/dist/psql/types/index.js +7 -7
  110. package/dist/psql/types/scanner.js +8 -8
  111. package/dist/psql/wire/connection.js +341 -327
  112. package/dist/psql/wire/copy.js +7 -7
  113. package/dist/psql/wire/pipeline.js +26 -24
  114. package/dist/psql/wire/protocol.js +102 -102
  115. package/dist/psql/wire/sasl.js +62 -62
  116. package/dist/psql/wire/tls.js +79 -73
  117. package/dist/storage_api.js +15 -15
  118. package/dist/test_utils/fixtures.js +34 -31
  119. package/dist/test_utils/oauth_server.js +5 -5
  120. package/dist/utils/api_enums.js +13 -13
  121. package/dist/utils/branch_notice.js +5 -5
  122. package/dist/utils/branch_picker.js +26 -26
  123. package/dist/utils/compute_units.js +4 -4
  124. package/dist/utils/enrichers.js +20 -15
  125. package/dist/utils/esbuild.js +28 -28
  126. package/dist/utils/formats.js +1 -1
  127. package/dist/utils/middlewares.js +3 -3
  128. package/dist/utils/package_manager.js +68 -0
  129. package/dist/utils/point_in_time.js +12 -12
  130. package/dist/utils/psql.js +30 -30
  131. package/dist/utils/string.js +2 -2
  132. package/dist/utils/ui.js +9 -9
  133. package/dist/utils/zip.js +1 -1
  134. package/dist/writer.js +17 -17
  135. package/package.json +6 -7
@@ -23,7 +23,7 @@
23
23
  const controlEvent = (b) => {
24
24
  // ^A == 0x01 maps back to 'a'. Lowercase keeps things consistent.
25
25
  const letter = String.fromCharCode(b + 0x60);
26
- return { key: 'char', char: letter, ctrl: true };
26
+ return { key: "char", char: letter, ctrl: true };
27
27
  };
28
28
  /** Streaming decoder. Owns a small pending-byte buffer. */
29
29
  export class Vt100Decoder {
@@ -102,7 +102,7 @@ export class Vt100Decoder {
102
102
  this.utf8Bytes.length = 0;
103
103
  this.utf8Expect = 0;
104
104
  this.pending.shift();
105
- return { key: 'unknown', raw: new Uint8Array([b]) };
105
+ return { key: "unknown", raw: new Uint8Array([b]) };
106
106
  }
107
107
  this.utf8Bytes.push(b);
108
108
  this.pending.shift();
@@ -111,27 +111,27 @@ export class Vt100Decoder {
111
111
  const bytes = Uint8Array.from(this.utf8Bytes);
112
112
  this.utf8Bytes.length = 0;
113
113
  const decoded = utf8Decode(bytes);
114
- return { key: 'char', char: decoded };
114
+ return { key: "char", char: decoded };
115
115
  }
116
116
  return null;
117
117
  }
118
118
  // ASCII printable.
119
119
  if (b >= 0x20 && b <= 0x7e) {
120
120
  this.pending.shift();
121
- return { key: 'char', char: String.fromCharCode(b) };
121
+ return { key: "char", char: String.fromCharCode(b) };
122
122
  }
123
123
  // Common controls.
124
124
  if (b === 0x09) {
125
125
  this.pending.shift();
126
- return { key: 'tab' };
126
+ return { key: "tab" };
127
127
  }
128
128
  if (b === 0x0a || b === 0x0d) {
129
129
  this.pending.shift();
130
- return { key: 'enter' };
130
+ return { key: "enter" };
131
131
  }
132
132
  if (b === 0x7f || b === 0x08) {
133
133
  this.pending.shift();
134
- return { key: 'backspace' };
134
+ return { key: "backspace" };
135
135
  }
136
136
  if (b === 0x1b) {
137
137
  // Escape: maybe alone, maybe the lead of a CSI/SS3/Meta sequence.
@@ -162,7 +162,7 @@ export class Vt100Decoder {
162
162
  }
163
163
  // Stray high byte. Emit unknown.
164
164
  this.pending.shift();
165
- return { key: 'unknown', raw: new Uint8Array([b]) };
165
+ return { key: "unknown", raw: new Uint8Array([b]) };
166
166
  }
167
167
  /**
168
168
  * Called when the head byte is 0x1b. Tries to consume an escape
@@ -181,7 +181,7 @@ export class Vt100Decoder {
181
181
  if (this.pending.length === 1) {
182
182
  if (this.escTimeoutMs === 0) {
183
183
  this.pending.shift();
184
- return { key: 'escape' };
184
+ return { key: "escape" };
185
185
  }
186
186
  // Already waiting? Don't re-arm the timer.
187
187
  if (this.escPending)
@@ -193,7 +193,7 @@ export class Vt100Decoder {
193
193
  if (this.escPending && this.pending[0] === 0x1b) {
194
194
  this.pending.shift();
195
195
  this.escPending = false;
196
- this.onTimeoutEvent?.({ key: 'escape' });
196
+ this.onTimeoutEvent?.({ key: "escape" });
197
197
  }
198
198
  else {
199
199
  this.escPending = false;
@@ -224,16 +224,16 @@ export class Vt100Decoder {
224
224
  }
225
225
  if (b1 === 0x7f) {
226
226
  this.pending.splice(0, 2);
227
- return { key: 'backspace', meta: true };
227
+ return { key: "backspace", meta: true };
228
228
  }
229
229
  if (b1 >= 0x20 && b1 <= 0x7e) {
230
230
  this.pending.splice(0, 2);
231
- return { key: 'char', char: String.fromCharCode(b1), meta: true };
231
+ return { key: "char", char: String.fromCharCode(b1), meta: true };
232
232
  }
233
233
  // Unknown Esc-X sequence; consume both and emit unknown.
234
234
  const raw = Uint8Array.from(this.pending.slice(0, 2));
235
235
  this.pending.splice(0, 2);
236
- return { key: 'unknown', raw };
236
+ return { key: "unknown", raw };
237
237
  }
238
238
  consumeCsi() {
239
239
  // Format: ESC [ (parameter bytes 0x30..0x3f)* (intermediate bytes 0x20..0x2f)* (final byte 0x40..0x7e)
@@ -259,52 +259,52 @@ export class Vt100Decoder {
259
259
  const paramStr = String.fromCharCode(...params);
260
260
  consume();
261
261
  switch (paramStr) {
262
- case '1':
263
- case '7':
264
- return { key: 'home' };
265
- case '2':
266
- return { key: 'unknown' }; // Insert; we don't handle it.
267
- case '3':
268
- return { key: 'delete' };
269
- case '4':
270
- case '8':
271
- return { key: 'end' };
272
- case '5':
273
- return { key: 'pageup' };
274
- case '6':
275
- return { key: 'pagedown' };
276
- case '200':
277
- return { key: 'paste-start' };
278
- case '201':
279
- return { key: 'paste-end' };
262
+ case "1":
263
+ case "7":
264
+ return { key: "home" };
265
+ case "2":
266
+ return { key: "unknown" }; // Insert; we don't handle it.
267
+ case "3":
268
+ return { key: "delete" };
269
+ case "4":
270
+ case "8":
271
+ return { key: "end" };
272
+ case "5":
273
+ return { key: "pageup" };
274
+ case "6":
275
+ return { key: "pagedown" };
276
+ case "200":
277
+ return { key: "paste-start" };
278
+ case "201":
279
+ return { key: "paste-end" };
280
280
  default:
281
- return { key: 'unknown' };
281
+ return { key: "unknown" };
282
282
  }
283
283
  }
284
284
  // Letter finals (A/B/C/D/H/F).
285
285
  // Param string may carry modifiers: e.g. "1;3" → Alt-arrow.
286
286
  const paramStr = String.fromCharCode(...params);
287
287
  consume();
288
- const meta = paramStr.endsWith(';3') || paramStr.endsWith(';7');
288
+ const meta = paramStr.endsWith(";3") || paramStr.endsWith(";7");
289
289
  switch (final) {
290
290
  case 0x41 /* 'A' */:
291
- return meta ? { key: 'up', meta: true } : { key: 'up' };
291
+ return meta ? { key: "up", meta: true } : { key: "up" };
292
292
  case 0x42 /* 'B' */:
293
- return meta ? { key: 'down', meta: true } : { key: 'down' };
293
+ return meta ? { key: "down", meta: true } : { key: "down" };
294
294
  case 0x43 /* 'C' */:
295
- return meta ? { key: 'right', meta: true } : { key: 'right' };
295
+ return meta ? { key: "right", meta: true } : { key: "right" };
296
296
  case 0x44 /* 'D' */:
297
- return meta ? { key: 'left', meta: true } : { key: 'left' };
297
+ return meta ? { key: "left", meta: true } : { key: "left" };
298
298
  case 0x48 /* 'H' */:
299
- return { key: 'home' };
299
+ return { key: "home" };
300
300
  case 0x46 /* 'F' */:
301
- return { key: 'end' };
301
+ return { key: "end" };
302
302
  case 0x5a /* 'Z' */:
303
303
  // Shift-Tab; treat as plain Tab for now (no reverse cycling yet).
304
- return { key: 'tab', meta: true };
304
+ return { key: "tab", meta: true };
305
305
  default:
306
306
  return {
307
- key: 'unknown',
307
+ key: "unknown",
308
308
  raw: Uint8Array.from(this.pending.slice(0, seqLen)),
309
309
  };
310
310
  }
@@ -313,51 +313,51 @@ export class Vt100Decoder {
313
313
  /** Decode a small UTF-8 byte sequence (1..4 bytes) into a string. */
314
314
  const utf8Decode = (bytes) => {
315
315
  // Node provides TextDecoder; available on all supported runtimes (Node 18+).
316
- return new TextDecoder('utf-8', { fatal: false }).decode(bytes);
316
+ return new TextDecoder("utf-8", { fatal: false }).decode(bytes);
317
317
  };
318
318
  /** Translate an SS3 final byte (after `ESC O`) into a key event. */
319
319
  const ss3ToEvent = (b) => {
320
320
  switch (b) {
321
321
  case 0x41:
322
- return { key: 'up' };
322
+ return { key: "up" };
323
323
  case 0x42:
324
- return { key: 'down' };
324
+ return { key: "down" };
325
325
  case 0x43:
326
- return { key: 'right' };
326
+ return { key: "right" };
327
327
  case 0x44:
328
- return { key: 'left' };
328
+ return { key: "left" };
329
329
  case 0x48:
330
- return { key: 'home' };
330
+ return { key: "home" };
331
331
  case 0x46:
332
- return { key: 'end' };
332
+ return { key: "end" };
333
333
  default:
334
- return { key: 'unknown', raw: new Uint8Array([0x1b, 0x4f, b]) };
334
+ return { key: "unknown", raw: new Uint8Array([0x1b, 0x4f, b]) };
335
335
  }
336
336
  };
337
337
  // ---------------------------------------------------------------------------
338
338
  // CSI output helpers
339
339
  // ---------------------------------------------------------------------------
340
340
  /** Move cursor up N rows. */
341
- export const csiUp = (n) => (n > 0 ? `\x1b[${n}A` : '');
341
+ export const csiUp = (n) => (n > 0 ? `\x1b[${n}A` : "");
342
342
  /** Move cursor down N rows. */
343
- export const csiDown = (n) => (n > 0 ? `\x1b[${n}B` : '');
343
+ export const csiDown = (n) => (n > 0 ? `\x1b[${n}B` : "");
344
344
  /** Move cursor right N columns. */
345
- export const csiRight = (n) => (n > 0 ? `\x1b[${n}C` : '');
345
+ export const csiRight = (n) => (n > 0 ? `\x1b[${n}C` : "");
346
346
  /** Move cursor left N columns. */
347
- export const csiLeft = (n) => (n > 0 ? `\x1b[${n}D` : '');
347
+ export const csiLeft = (n) => (n > 0 ? `\x1b[${n}D` : "");
348
348
  /** Move cursor to column N (1-based). */
349
349
  export const csiToColumn = (col) => `\x1b[${col}G`;
350
350
  /** Erase from cursor to end-of-line. */
351
- export const csiEraseToEol = () => '\x1b[K';
351
+ export const csiEraseToEol = () => "\x1b[K";
352
352
  /** Erase entire screen and move cursor to home. */
353
- export const csiClearScreen = () => '\x1b[2J\x1b[H';
353
+ export const csiClearScreen = () => "\x1b[2J\x1b[H";
354
354
  /** Carriage return: move to column 1 without writing a newline. */
355
- export const CR = '\r';
355
+ export const CR = "\r";
356
356
  /** Newline (LF). */
357
- export const LF = '\n';
357
+ export const LF = "\n";
358
358
  /** Enable bracketed paste mode (DEC private mode 2004). */
359
- export const enableBracketedPaste = () => '\x1b[?2004h';
359
+ export const enableBracketedPaste = () => "\x1b[?2004h";
360
360
  /** Disable bracketed paste mode. */
361
- export const disableBracketedPaste = () => '\x1b[?2004l';
361
+ export const disableBracketedPaste = () => "\x1b[?2004l";
362
362
  /** Audible bell. */
363
- export const BEL = '\x07';
363
+ export const BEL = "\x07";
@@ -25,10 +25,10 @@
25
25
  * skip the file and emit a single warning to stderr. Windows skips the check
26
26
  * entirely (libpq does the same — `geteuid` / `S_IRWXG` aren't portable).
27
27
  */
28
- import { promises as fs } from 'node:fs';
29
- import * as os from 'node:os';
30
- import * as path from 'node:path';
31
- const isWindows = process.platform === 'win32';
28
+ import { promises as fs } from "node:fs";
29
+ import * as os from "node:os";
30
+ import * as path from "node:path";
31
+ const isWindows = process.platform === "win32";
32
32
  /**
33
33
  * Return the default `.pgpass` path:
34
34
  *
@@ -46,13 +46,13 @@ export const defaultPgPassPath = (env = process.env) => {
46
46
  if (isWindows) {
47
47
  const appdata = env.APPDATA;
48
48
  if (appdata !== undefined && appdata.length > 0) {
49
- return path.join(appdata, 'postgresql', 'pgpass.conf');
49
+ return path.join(appdata, "postgresql", "pgpass.conf");
50
50
  }
51
51
  // Fall through to homedir() if APPDATA isn't set — degrade gracefully on
52
52
  // a minimally configured Windows session.
53
53
  }
54
54
  const home = env.HOME ?? os.homedir();
55
- return path.join(home, '.pgpass');
55
+ return path.join(home, ".pgpass");
56
56
  };
57
57
  /**
58
58
  * Split a `.pgpass` line into its five fields, respecting `\:` and `\\`
@@ -67,9 +67,9 @@ export const defaultPgPassPath = (env = process.env) => {
67
67
  */
68
68
  /** Un-escape `\X` → `X` (a trailing lone backslash is kept). */
69
69
  const decodeBackslashes = (s) => {
70
- let out = '';
70
+ let out = "";
71
71
  for (let i = 0; i < s.length; i++) {
72
- if (s[i] === '\\' && i + 1 < s.length) {
72
+ if (s[i] === "\\" && i + 1 < s.length) {
73
73
  out += s[i + 1];
74
74
  i += 1;
75
75
  continue;
@@ -87,17 +87,17 @@ const splitLine = (line) => {
87
87
  // char-by-char comparison. The password is the returned secret, so it is
88
88
  // fully decoded here.
89
89
  const fields = [];
90
- let current = '';
90
+ let current = "";
91
91
  for (let i = 0; i < line.length; i++) {
92
92
  const ch = line[i];
93
- if (ch === '\\' && i + 1 < line.length) {
94
- current += '\\' + line[i + 1];
93
+ if (ch === "\\" && i + 1 < line.length) {
94
+ current += "\\" + line[i + 1];
95
95
  i += 1;
96
96
  continue;
97
97
  }
98
- if (ch === ':') {
98
+ if (ch === ":") {
99
99
  fields.push(current);
100
- current = '';
100
+ current = "";
101
101
  continue;
102
102
  }
103
103
  current += ch;
@@ -136,7 +136,7 @@ export const loadPgPass = async (filePath, opts) => {
136
136
  }
137
137
  catch (err) {
138
138
  const code = err.code;
139
- if (code === 'ENOENT' || code === 'ENOTDIR')
139
+ if (code === "ENOENT" || code === "ENOTDIR")
140
140
  return [];
141
141
  return [];
142
142
  }
@@ -148,17 +148,17 @@ export const loadPgPass = async (filePath, opts) => {
148
148
  }
149
149
  let raw;
150
150
  try {
151
- raw = await fs.readFile(resolved, 'utf8');
151
+ raw = await fs.readFile(resolved, "utf8");
152
152
  }
153
153
  catch {
154
154
  return [];
155
155
  }
156
156
  const entries = [];
157
157
  for (const line of raw.split(/\r?\n/)) {
158
- const trimmed = line.replace(/^\s+/, '');
158
+ const trimmed = line.replace(/^\s+/, "");
159
159
  if (trimmed.length === 0)
160
160
  continue;
161
- if (trimmed.startsWith('#'))
161
+ if (trimmed.startsWith("#"))
162
162
  continue;
163
163
  const entry = splitLine(trimmed);
164
164
  if (entry !== null)
@@ -171,7 +171,7 @@ export const loadPgPass = async (filePath, opts) => {
171
171
  */
172
172
  const fieldMatches = (pattern, value) =>
173
173
  // A bare `*` is the wildcard; `\*` decodes to a LITERAL `*` (review #21).
174
- pattern === '*' || decodeBackslashes(pattern) === value;
174
+ pattern === "*" || decodeBackslashes(pattern) === value;
175
175
  /**
176
176
  * Look up a password entry for the given `target`. Returns the first matching
177
177
  * entry's password, or `undefined` if nothing matches.
@@ -36,10 +36,10 @@
36
36
  * silently — libpq would also accept them and feed them to `PQconninfoParse`,
37
37
  * which is responsible for the recognised-key gate.
38
38
  */
39
- import { promises as fs } from 'node:fs';
40
- import * as os from 'node:os';
41
- import * as path from 'node:path';
42
- const isWindows = process.platform === 'win32';
39
+ import { promises as fs } from "node:fs";
40
+ import * as os from "node:os";
41
+ import * as path from "node:path";
42
+ const isWindows = process.platform === "win32";
43
43
  /**
44
44
  * Return the ordered list of candidate `pg_service.conf` paths to try. The
45
45
  * caller stops at the first one that exists. Pure function — `env` defaults
@@ -56,25 +56,25 @@ export const defaultPgServiceFilePath = (env = process.env) => {
56
56
  if (isWindows) {
57
57
  const appdata = env.APPDATA;
58
58
  if (appdata !== undefined && appdata.length > 0) {
59
- out.push(path.join(appdata, 'postgresql', '.pg_service.conf'));
59
+ out.push(path.join(appdata, "postgresql", ".pg_service.conf"));
60
60
  }
61
61
  }
62
62
  else {
63
63
  const home = env.HOME ?? os.homedir();
64
64
  if (home.length > 0) {
65
- out.push(path.join(home, '.pg_service.conf'));
65
+ out.push(path.join(home, ".pg_service.conf"));
66
66
  }
67
67
  }
68
68
  // System-level: `$PGSYSCONFDIR/pg_service.conf`.
69
69
  const sysDir = env.PGSYSCONFDIR;
70
70
  if (sysDir !== undefined && sysDir.length > 0) {
71
- out.push(path.join(sysDir, 'pg_service.conf'));
71
+ out.push(path.join(sysDir, "pg_service.conf"));
72
72
  }
73
73
  // Platform-default system path. libpq's autoconf picks SYSCONFDIR at build
74
74
  // time; for a portable TS implementation we use `/etc/pg_service.conf` on
75
75
  // POSIX. Windows has no canonical equivalent.
76
76
  if (!isWindows) {
77
- out.push('/etc/pg_service.conf');
77
+ out.push("/etc/pg_service.conf");
78
78
  }
79
79
  return out;
80
80
  };
@@ -101,10 +101,10 @@ export const parsePgServiceContent = (content) => {
101
101
  const line = rawLine.trim();
102
102
  if (line.length === 0)
103
103
  continue;
104
- if (line.startsWith('#'))
104
+ if (line.startsWith("#"))
105
105
  continue;
106
- if (line.startsWith('[')) {
107
- const close = line.indexOf(']');
106
+ if (line.startsWith("[")) {
107
+ const close = line.indexOf("]");
108
108
  if (close < 0) {
109
109
  // Malformed header — libpq aborts the file; we mirror by ending the
110
110
  // current section so the bogus line doesn't bleed into it.
@@ -126,7 +126,7 @@ export const parsePgServiceContent = (content) => {
126
126
  // resolve services that appear after the noise.
127
127
  continue;
128
128
  }
129
- const eq = line.indexOf('=');
129
+ const eq = line.indexOf("=");
130
130
  if (eq < 0)
131
131
  continue;
132
132
  const key = line.slice(0, eq).trim();
@@ -139,11 +139,11 @@ export const parsePgServiceContent = (content) => {
139
139
  };
140
140
  const readIfExists = async (filePath) => {
141
141
  try {
142
- return await fs.readFile(filePath, 'utf8');
142
+ return await fs.readFile(filePath, "utf8");
143
143
  }
144
144
  catch (err) {
145
145
  const code = err.code;
146
- if (code === 'ENOENT' || code === 'ENOTDIR')
146
+ if (code === "ENOENT" || code === "ENOTDIR")
147
147
  return null;
148
148
  // Permission / I/O errors silently degrade — libpq treats an unreadable
149
149
  // service file the same as a missing one (the connection falls back to