neonctl 2.27.1 → 2.29.0

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 (136) hide show
  1. package/README.md +35 -3
  2. package/dist/analytics.js +52 -34
  3. package/dist/api.js +643 -13
  4. package/dist/auth.js +50 -44
  5. package/dist/cli.js +8 -1
  6. package/dist/commands/auth.js +64 -51
  7. package/dist/commands/bootstrap.js +115 -157
  8. package/dist/commands/branches.js +160 -150
  9. package/dist/commands/bucket.js +183 -146
  10. package/dist/commands/checkout.js +51 -51
  11. package/dist/commands/config.js +228 -82
  12. package/dist/commands/connection_string.js +62 -62
  13. package/dist/commands/data_api.js +100 -101
  14. package/dist/commands/databases.js +29 -26
  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 +101 -104
  19. package/dist/commands/index.js +27 -25
  20. package/dist/commands/init.js +23 -22
  21. package/dist/commands/ip_allow.js +29 -29
  22. package/dist/commands/link.js +232 -182
  23. package/dist/commands/neon_auth.js +385 -370
  24. package/dist/commands/operations.js +11 -11
  25. package/dist/commands/orgs.js +8 -8
  26. package/dist/commands/projects.js +103 -101
  27. package/dist/commands/psql.js +31 -31
  28. package/dist/commands/roles.js +27 -24
  29. package/dist/commands/schema_diff.js +25 -26
  30. package/dist/commands/set_context.js +17 -17
  31. package/dist/commands/status.js +40 -0
  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 +37 -14
  37. package/dist/current_branch_fast_path.js +55 -0
  38. package/dist/dev/env.js +33 -33
  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 +68 -5
  45. package/dist/functions_api.js +10 -10
  46. package/dist/help.js +15 -15
  47. package/dist/index.js +110 -107
  48. package/dist/log.js +2 -2
  49. package/dist/parameters.gen.js +14 -14
  50. package/dist/pkg.js +5 -5
  51. package/dist/psql/cli.js +4 -2
  52. package/dist/psql/command/cmd_cond.js +61 -61
  53. package/dist/psql/command/cmd_connect.js +159 -154
  54. package/dist/psql/command/cmd_copy.js +107 -97
  55. package/dist/psql/command/cmd_describe.js +368 -363
  56. package/dist/psql/command/cmd_format.js +276 -263
  57. package/dist/psql/command/cmd_io.js +269 -263
  58. package/dist/psql/command/cmd_lo.js +74 -66
  59. package/dist/psql/command/cmd_meta.js +148 -148
  60. package/dist/psql/command/cmd_misc.js +17 -17
  61. package/dist/psql/command/cmd_pipeline.js +142 -135
  62. package/dist/psql/command/cmd_restrict.js +25 -25
  63. package/dist/psql/command/cmd_show.js +183 -168
  64. package/dist/psql/command/dispatch.js +26 -26
  65. package/dist/psql/command/shared.js +14 -14
  66. package/dist/psql/complete/filenames.js +16 -16
  67. package/dist/psql/complete/index.js +4 -4
  68. package/dist/psql/complete/matcher.js +33 -32
  69. package/dist/psql/complete/psqlVars.js +173 -173
  70. package/dist/psql/complete/queries.js +5 -3
  71. package/dist/psql/complete/rules.js +900 -863
  72. package/dist/psql/core/common.js +136 -133
  73. package/dist/psql/core/help.js +343 -343
  74. package/dist/psql/core/mainloop.js +160 -153
  75. package/dist/psql/core/prompt.js +126 -123
  76. package/dist/psql/core/settings.js +111 -111
  77. package/dist/psql/core/sqlHelp.js +150 -150
  78. package/dist/psql/core/startup.js +211 -205
  79. package/dist/psql/core/syncVars.js +14 -14
  80. package/dist/psql/core/variables.js +24 -24
  81. package/dist/psql/describe/formatters.js +302 -289
  82. package/dist/psql/describe/processNamePattern.js +28 -28
  83. package/dist/psql/describe/queries.js +656 -651
  84. package/dist/psql/index.js +436 -411
  85. package/dist/psql/io/history.js +36 -36
  86. package/dist/psql/io/input.js +15 -15
  87. package/dist/psql/io/lineEditor/buffer.js +27 -25
  88. package/dist/psql/io/lineEditor/complete.js +15 -15
  89. package/dist/psql/io/lineEditor/filename.js +22 -22
  90. package/dist/psql/io/lineEditor/index.js +65 -62
  91. package/dist/psql/io/lineEditor/keymap.js +325 -318
  92. package/dist/psql/io/lineEditor/vt100.js +60 -60
  93. package/dist/psql/io/pgpass.js +18 -18
  94. package/dist/psql/io/pgservice.js +14 -14
  95. package/dist/psql/io/psqlrc.js +46 -46
  96. package/dist/psql/print/aligned.js +175 -166
  97. package/dist/psql/print/asciidoc.js +51 -51
  98. package/dist/psql/print/crosstab.js +34 -31
  99. package/dist/psql/print/csv.js +25 -22
  100. package/dist/psql/print/html.js +54 -54
  101. package/dist/psql/print/json.js +12 -12
  102. package/dist/psql/print/latex.js +118 -118
  103. package/dist/psql/print/pager.js +28 -26
  104. package/dist/psql/print/troff.js +48 -48
  105. package/dist/psql/print/unaligned.js +15 -14
  106. package/dist/psql/print/units.js +17 -17
  107. package/dist/psql/scanner/slash.js +48 -46
  108. package/dist/psql/scanner/sql.js +88 -84
  109. package/dist/psql/scanner/stringutils.js +21 -17
  110. package/dist/psql/types/index.js +7 -7
  111. package/dist/psql/types/scanner.js +8 -8
  112. package/dist/psql/wire/connection.js +341 -327
  113. package/dist/psql/wire/copy.js +7 -7
  114. package/dist/psql/wire/pipeline.js +26 -24
  115. package/dist/psql/wire/protocol.js +102 -102
  116. package/dist/psql/wire/sasl.js +62 -62
  117. package/dist/psql/wire/tls.js +79 -73
  118. package/dist/storage_api.js +22 -23
  119. package/dist/test_utils/fixtures.js +74 -41
  120. package/dist/test_utils/oauth_server.js +5 -5
  121. package/dist/utils/api_enums.js +33 -0
  122. package/dist/utils/branch_notice.js +5 -5
  123. package/dist/utils/branch_picker.js +26 -26
  124. package/dist/utils/compute_units.js +4 -4
  125. package/dist/utils/enrichers.js +28 -16
  126. package/dist/utils/esbuild.js +28 -28
  127. package/dist/utils/formats.js +1 -1
  128. package/dist/utils/middlewares.js +3 -3
  129. package/dist/utils/package_manager.js +68 -0
  130. package/dist/utils/point_in_time.js +12 -12
  131. package/dist/utils/psql.js +30 -30
  132. package/dist/utils/string.js +2 -2
  133. package/dist/utils/ui.js +9 -9
  134. package/dist/utils/zip.js +1 -1
  135. package/dist/writer.js +17 -17
  136. package/package.json +10 -12
@@ -39,7 +39,7 @@
39
39
  * and consumed by a subsequent PROMPT2 render via the optional
40
40
  * `lastPrompt1Width` field on the context.
41
41
  */
42
- import { execSync } from 'node:child_process';
42
+ import { execSync } from "node:child_process";
43
43
  /**
44
44
  * Test seam for the prompt-level backtick executor. The default
45
45
  * implementation calls `execSync(cmd, { shell: '/bin/sh' })`; tests can
@@ -48,9 +48,9 @@ import { execSync } from 'node:child_process';
48
48
  */
49
49
  export const PROMPT_BACKTICK_EXECUTOR = {
50
50
  current: (cmd) => execSync(cmd, {
51
- shell: '/bin/sh',
52
- encoding: 'utf8',
53
- stdio: ['ignore', 'pipe', 'inherit'],
51
+ shell: "/bin/sh",
52
+ encoding: "utf8",
53
+ stdio: ["ignore", "pipe", "inherit"],
54
54
  // Keep prompt rendering responsive — a heavy backtick command should
55
55
  // not be able to fill arbitrary memory or hang the prompt forever.
56
56
  maxBuffer: 1 << 16,
@@ -63,15 +63,15 @@ export const PROMPT_BACKTICK_EXECUTOR = {
63
63
  */
64
64
  const runPromptBacktick = (cmd) => {
65
65
  if (cmd.length === 0)
66
- return '';
66
+ return "";
67
67
  try {
68
68
  const out = PROMPT_BACKTICK_EXECUTOR.current(cmd);
69
- return out.endsWith('\n') ? out.slice(0, -1) : out;
69
+ return out.endsWith("\n") ? out.slice(0, -1) : out;
70
70
  }
71
71
  catch (err) {
72
72
  const msg = err instanceof Error ? err.message : String(err);
73
73
  process.stderr.write(`psql: error: \\!: ${cmd}: ${msg}\n`);
74
- return '';
74
+ return "";
75
75
  }
76
76
  };
77
77
  /**
@@ -79,12 +79,12 @@ const runPromptBacktick = (cmd) => {
79
79
  * `settings.prompt{1,2,3}` and delegates to the escape-walking core.
80
80
  */
81
81
  export const renderPromptByName = (name, ctx) => {
82
- const template = name === 'PROMPT1'
82
+ const template = name === "PROMPT1"
83
83
  ? ctx.settings.prompt1
84
- : name === 'PROMPT2'
84
+ : name === "PROMPT2"
85
85
  ? ctx.settings.prompt2
86
86
  : ctx.settings.prompt3;
87
- const isPrompt1 = name === 'PROMPT1';
87
+ const isPrompt1 = name === "PROMPT1";
88
88
  const out = renderPrompt(template, ctx);
89
89
  if (isPrompt1) {
90
90
  // Stash the visible width on the context so a subsequent PROMPT2 render
@@ -97,11 +97,11 @@ export const renderPromptByName = (name, ctx) => {
97
97
  * Render an arbitrary prompt template. Pure function over `(template, ctx)`.
98
98
  */
99
99
  export const renderPrompt = (template, ctx) => {
100
- let out = '';
100
+ let out = "";
101
101
  let i = 0;
102
102
  while (i < template.length) {
103
103
  const ch = template[i];
104
- if (ch !== '%') {
104
+ if (ch !== "%") {
105
105
  out += ch;
106
106
  i += 1;
107
107
  continue;
@@ -126,150 +126,153 @@ start, ctx) => {
126
126
  const { settings } = ctx;
127
127
  const db = settings.db;
128
128
  switch (escape) {
129
- case '%':
130
- return { text: '%', consumed: 1 };
131
- case '/':
129
+ case "%":
130
+ return { text: "%", consumed: 1 };
131
+ case "/":
132
132
  // Current database.
133
- return { text: db ? currentDatabase(ctx) : '', consumed: 1 };
134
- case '~': {
133
+ return { text: db ? currentDatabase(ctx) : "", consumed: 1 };
134
+ case "~": {
135
135
  // Like %/, but "~" when current_db matches the user's default db.
136
136
  // Upstream compares PQdb(pset.db) against PQuser(pset.db) and
137
137
  // against $PGDATABASE.
138
138
  if (!db)
139
- return { text: '', consumed: 1 };
139
+ return { text: "", consumed: 1 };
140
140
  const cdb = currentDatabase(ctx);
141
141
  const user = currentUser(ctx);
142
142
  const pgdb = process.env.PGDATABASE;
143
143
  if (cdb === user || (pgdb !== undefined && pgdb === cdb)) {
144
- return { text: '~', consumed: 1 };
144
+ return { text: "~", consumed: 1 };
145
145
  }
146
146
  return { text: cdb, consumed: 1 };
147
147
  }
148
- case 'M':
149
- case 'm':
148
+ case "M":
149
+ case "m":
150
150
  return {
151
- text: db ? hostString(ctx, escape === 'm') : '',
151
+ text: db ? hostString(ctx, escape === "m") : "",
152
152
  consumed: 1,
153
153
  };
154
- case '>':
155
- return { text: db ? portString(ctx) : '', consumed: 1 };
156
- case 'n':
157
- return { text: db ? currentUser(ctx) : '', consumed: 1 };
158
- case 'p': {
154
+ case ">":
155
+ return { text: db ? portString(ctx) : "", consumed: 1 };
156
+ case "n":
157
+ return { text: db ? currentUser(ctx) : "", consumed: 1 };
158
+ case "p": {
159
159
  if (!db)
160
- return { text: '', consumed: 1 };
160
+ return { text: "", consumed: 1 };
161
161
  const pid = backendPid(ctx);
162
- return { text: pid !== null ? String(pid) : '', consumed: 1 };
162
+ return { text: pid !== null ? String(pid) : "", consumed: 1 };
163
163
  }
164
- case 'P': {
164
+ case "P": {
165
165
  if (!db)
166
- return { text: '', consumed: 1 };
166
+ return { text: "", consumed: 1 };
167
167
  // Upstream emits "off" / "on" / "abort" (no trailing 'ed').
168
- const state = ctx.pipelineState ?? 'off';
169
- const text = state === 'on' ? 'on' : state === 'aborted' ? 'abort' : 'off';
168
+ const state = ctx.pipelineState ?? "off";
169
+ const text = state === "on" ? "on" : state === "aborted" ? "abort" : "off";
170
170
  return { text, consumed: 1 };
171
171
  }
172
- case 'i': {
172
+ case "i": {
173
173
  // Hot-standby indicator. Upstream reads in_hot_standby GUC.
174
174
  if (!db)
175
- return { text: '', consumed: 1 };
176
- const hs = parameterStatus(ctx, 'in_hot_standby');
175
+ return { text: "", consumed: 1 };
176
+ const hs = parameterStatus(ctx, "in_hot_standby");
177
177
  if (hs === undefined)
178
- return { text: '?', consumed: 1 };
179
- return { text: hs === 'on' ? 'standby' : 'primary', consumed: 1 };
178
+ return { text: "?", consumed: 1 };
179
+ return { text: hs === "on" ? "standby" : "primary", consumed: 1 };
180
180
  }
181
- case 's': {
181
+ case "s": {
182
182
  // service name from psql var SERVICE (upstream prompt.c).
183
- const svc = settings.vars.get('SERVICE');
184
- return { text: svc ?? '', consumed: 1 };
183
+ const svc = settings.vars.get("SERVICE");
184
+ return { text: svc ?? "", consumed: 1 };
185
185
  }
186
- case 'S': {
186
+ case "S": {
187
187
  // search_path; `?` when unavailable (older servers or no conn).
188
188
  if (!db)
189
- return { text: '?', consumed: 1 };
190
- const sp = parameterStatus(ctx, 'search_path');
191
- return { text: sp ?? '?', consumed: 1 };
189
+ return { text: "?", consumed: 1 };
190
+ const sp = parameterStatus(ctx, "search_path");
191
+ return { text: sp ?? "?", consumed: 1 };
192
192
  }
193
- case 'l':
193
+ case "l":
194
194
  return { text: String(ctx.lineNumber), consumed: 1 };
195
- case 'w': {
195
+ case "w": {
196
196
  // Whitespace padding the width of the last PROMPT1 render.
197
197
  const width = Math.max(0, ctx.lastPrompt1Width ?? 0);
198
- return { text: db ? ' '.repeat(width) : '', consumed: 1 };
198
+ return { text: db ? " ".repeat(width) : "", consumed: 1 };
199
199
  }
200
- case 'a':
200
+ case "a":
201
201
  // Bell. Upstream falls into default, which is just literal 'a' (no
202
202
  // bell handling in get_prompt). The WP-07 spec explicitly asks for
203
203
  // ^G though, and emitting BEL is harmless. Honour the spec.
204
- return { text: '\x07', consumed: 1 };
205
- case 'R': {
204
+ return { text: "\x07", consumed: 1 };
205
+ case "R": {
206
206
  const text = expandR(ctx);
207
207
  return { text, consumed: 1 };
208
208
  }
209
- case 'x': {
209
+ case "x": {
210
210
  if (!db)
211
- return { text: '?', consumed: 1 };
212
- const tx = ctx.inTransaction ?? 'idle';
213
- if (tx === 'in-block')
214
- return { text: '*', consumed: 1 };
215
- if (tx === 'failed')
216
- return { text: '!', consumed: 1 };
217
- if (tx === 'unknown')
218
- return { text: '?', consumed: 1 };
219
- return { text: '', consumed: 1 };
211
+ return { text: "?", consumed: 1 };
212
+ const tx = ctx.inTransaction ?? "idle";
213
+ if (tx === "in-block")
214
+ return { text: "*", consumed: 1 };
215
+ if (tx === "failed")
216
+ return { text: "!", consumed: 1 };
217
+ if (tx === "unknown")
218
+ return { text: "?", consumed: 1 };
219
+ return { text: "", consumed: 1 };
220
220
  }
221
- case '#': {
221
+ case "#": {
222
222
  // Superuser indicator. Upstream calls is_superuser() which checks
223
223
  // pset.vars["IS_SUPERUSER"] === "on".
224
- const isSuper = settings.vars.get('IS_SUPERUSER') === 'on';
225
- return { text: isSuper ? '#' : '>', consumed: 1 };
224
+ const isSuper = settings.vars.get("IS_SUPERUSER") === "on";
225
+ return { text: isSuper ? "#" : ">", consumed: 1 };
226
226
  }
227
- case '?':
227
+ case "?":
228
228
  // Reserved by upstream ("not here yet"). Emit nothing.
229
- return { text: '', consumed: 1 };
230
- case '[':
231
- case ']':
229
+ return { text: "", consumed: 1 };
230
+ case "[":
231
+ case "]":
232
232
  // Readline non-printing markers. Strip — no terminal info embedded.
233
- return { text: '', consumed: 1 };
234
- case '`': {
233
+ return { text: "", consumed: 1 };
234
+ case "`": {
235
235
  // Backtick command: read until the matching `` ` `` after the opening
236
236
  // backtick, then run the body through `sh -c` and substitute its
237
237
  // stdout. Upstream `get_prompt` re-runs the command on every render
238
238
  // rather than caching, so we do the same — callers who want caching
239
239
  // should stash the rendered prompt themselves.
240
- const close = template.indexOf('`', start + 1);
240
+ const close = template.indexOf("`", start + 1);
241
241
  if (close === -1) {
242
242
  // Unterminated — consume the rest defensively without spawning.
243
- return { text: '', consumed: template.length - start };
243
+ return { text: "", consumed: template.length - start };
244
244
  }
245
245
  const body = template.slice(start + 1, close);
246
- return { text: runPromptBacktick(body), consumed: close - start + 1 };
246
+ return {
247
+ text: runPromptBacktick(body),
248
+ consumed: close - start + 1,
249
+ };
247
250
  }
248
- case ':': {
251
+ case ":": {
249
252
  // Variable interpolation %:name:
250
- const close = template.indexOf(':', start + 1);
253
+ const close = template.indexOf(":", start + 1);
251
254
  if (close === -1) {
252
- return { text: '', consumed: template.length - start };
255
+ return { text: "", consumed: template.length - start };
253
256
  }
254
257
  const name = template.slice(start + 1, close);
255
258
  const val = settings.vars.get(name);
256
- return { text: val ?? '', consumed: close - start + 1 };
259
+ return { text: val ?? "", consumed: close - start + 1 };
257
260
  }
258
- case '0':
259
- case '1':
260
- case '2':
261
- case '3':
262
- case '4':
263
- case '5':
264
- case '6':
265
- case '7': {
261
+ case "0":
262
+ case "1":
263
+ case "2":
264
+ case "3":
265
+ case "4":
266
+ case "5":
267
+ case "6":
268
+ case "7": {
266
269
  // Octal byte value `%nnn`. Upstream uses strtol(p, &p, 8), which
267
270
  // greedily consumes 1–3 octal digits.
268
271
  let consumed = 1;
269
272
  let body = escape;
270
273
  while (consumed < 3 && start + consumed < template.length) {
271
274
  const next = template[start + consumed];
272
- if (next >= '0' && next <= '7') {
275
+ if (next >= "0" && next <= "7") {
273
276
  body += next;
274
277
  consumed += 1;
275
278
  }
@@ -304,32 +307,32 @@ start, ctx) => {
304
307
  const expandR = (ctx) => {
305
308
  const { promptStatus, cond, settings } = ctx;
306
309
  switch (promptStatus) {
307
- case 'ready': {
310
+ case "ready": {
308
311
  if (!isConditionalActive(cond))
309
- return '@';
312
+ return "@";
310
313
  if (!settings.db)
311
- return '!';
314
+ return "!";
312
315
  if (!settings.singleline)
313
- return '=';
314
- return '^';
316
+ return "=";
317
+ return "^";
315
318
  }
316
- case 'continue':
317
- return '-';
318
- case 'continue-quote':
319
+ case "continue":
320
+ return "-";
321
+ case "continue-quote":
319
322
  return "'";
320
- case 'continue-dquote':
323
+ case "continue-dquote":
321
324
  return '"';
322
- case 'continue-dollar':
323
- return '$';
324
- case 'comment':
325
- return '*';
326
- case 'paren':
327
- return '(';
328
- case 'copy':
325
+ case "continue-dollar":
326
+ return "$";
327
+ case "comment":
328
+ return "*";
329
+ case "paren":
330
+ return "(";
331
+ case "copy":
329
332
  // PROMPT3 / COPY path — upstream emits nothing for %R here.
330
- return '';
333
+ return "";
331
334
  default:
332
- return '';
335
+ return "";
333
336
  }
334
337
  };
335
338
  /**
@@ -342,7 +345,7 @@ const isConditionalActive = (cond) => {
342
345
  const top = cond.top();
343
346
  if (!top)
344
347
  return true;
345
- const inactive = ['false', 'else-false', 'ignored'];
348
+ const inactive = ["false", "else-false", "ignored"];
346
349
  return !inactive.includes(top.state);
347
350
  };
348
351
  /**
@@ -354,8 +357,8 @@ const visibleWidth = (s) => {
354
357
  // Strip CSI escapes (ESC `[` … letter). Conservative — only trims the
355
358
  // common ANSI color form psql emits. Newlines reset the count.
356
359
  // eslint-disable-next-line no-control-regex
357
- const stripped = s.replace(/\x1b\[[0-9;]*[A-Za-z]/g, '');
358
- const lastNl = stripped.lastIndexOf('\n');
360
+ const stripped = s.replace(/\x1b\[[0-9;]*[A-Za-z]/g, "");
361
+ const lastNl = stripped.lastIndexOf("\n");
359
362
  const tail = lastNl === -1 ? stripped : stripped.slice(lastNl + 1);
360
363
  // Code-unit count — good enough for ASCII prompts; CJK / surrogate-pair
361
364
  // width handling is a printer-WP concern.
@@ -364,39 +367,39 @@ const visibleWidth = (s) => {
364
367
  const currentDatabase = (ctx) => {
365
368
  const db = ctx.settings.db;
366
369
  if (!db)
367
- return '';
370
+ return "";
368
371
  // Prefer a libpq-style accessor if the runtime Connection exposes one;
369
372
  // otherwise fall back to the application's GUC view.
370
373
  const meta = db;
371
- if (typeof meta.database === 'string' && meta.database.length > 0) {
374
+ if (typeof meta.database === "string" && meta.database.length > 0) {
372
375
  return meta.database;
373
376
  }
374
- return parameterStatus(ctx, 'database') ?? '';
377
+ return parameterStatus(ctx, "database") ?? "";
375
378
  };
376
379
  const currentUser = (ctx) => {
377
380
  const db = ctx.settings.db;
378
381
  if (!db)
379
- return '';
382
+ return "";
380
383
  const meta = db;
381
- if (typeof meta.user === 'string' && meta.user.length > 0) {
384
+ if (typeof meta.user === "string" && meta.user.length > 0) {
382
385
  return meta.user;
383
386
  }
384
- return parameterStatus(ctx, 'session_authorization') ?? '';
387
+ return parameterStatus(ctx, "session_authorization") ?? "";
385
388
  };
386
389
  const hostString = (ctx, short) => {
387
390
  const db = ctx.settings.db;
388
391
  if (!db)
389
- return '';
392
+ return "";
390
393
  const meta = db;
391
- const host = typeof meta.host === 'string' ? meta.host : '';
392
- if (host.length === 0 || host.startsWith('/')) {
394
+ const host = typeof meta.host === "string" ? meta.host : "";
395
+ if (host.length === 0 || host.startsWith("/")) {
393
396
  // UNIX socket / unknown — upstream emits "[local]" or "[local:path]".
394
397
  if (host.length === 0 || short)
395
- return '[local]';
398
+ return "[local]";
396
399
  return `[local:${host}]`;
397
400
  }
398
401
  if (short) {
399
- const dot = host.indexOf('.');
402
+ const dot = host.indexOf(".");
400
403
  return dot === -1 ? host : host.slice(0, dot);
401
404
  }
402
405
  return host;
@@ -404,22 +407,22 @@ const hostString = (ctx, short) => {
404
407
  const portString = (ctx) => {
405
408
  const db = ctx.settings.db;
406
409
  if (!db)
407
- return '';
410
+ return "";
408
411
  const meta = db;
409
- if (typeof meta.port === 'number' && Number.isFinite(meta.port)) {
412
+ if (typeof meta.port === "number" && Number.isFinite(meta.port)) {
410
413
  return String(meta.port);
411
414
  }
412
- if (typeof meta.port === 'string' && meta.port.length > 0) {
415
+ if (typeof meta.port === "string" && meta.port.length > 0) {
413
416
  return meta.port;
414
417
  }
415
- return '';
418
+ return "";
416
419
  };
417
420
  const backendPid = (ctx) => {
418
421
  const db = ctx.settings.db;
419
422
  if (!db)
420
423
  return null;
421
424
  const meta = db;
422
- if (typeof meta.pid === 'number' && Number.isFinite(meta.pid)) {
425
+ if (typeof meta.pid === "number" && Number.isFinite(meta.pid)) {
423
426
  return meta.pid;
424
427
  }
425
428
  return null;