neonctl 2.28.0 → 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 (135) hide show
  1. package/README.md +2 -2
  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 +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 +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
@@ -54,21 +54,21 @@
54
54
  * error message if we ever see a copy result come back through
55
55
  * `execSimple`.
56
56
  */
57
- import { alignedPrinter } from '../print/aligned.js';
58
- import { asciidocPrinter } from '../print/asciidoc.js';
59
- import { csvPrinter } from '../print/csv.js';
60
- import { htmlPrinter } from '../print/html.js';
61
- import { jsonPrinter } from '../print/json.js';
62
- import { latexLongtablePrinter, latexPrinter } from '../print/latex.js';
63
- import { troffMsPrinter } from '../print/troff.js';
64
- import { unalignedPrinter } from '../print/unaligned.js';
65
- import { formatDurationMs } from '../print/units.js';
66
- import { openPager, shouldPage } from '../print/pager.js';
67
- import { getQueryFout } from '../command/cmd_io.js';
68
- import { formatErrorReport, psqlErrorPrefix } from '../command/cmd_meta.js';
57
+ import { getQueryFout } from "../command/cmd_io.js";
58
+ import { formatErrorReport, psqlErrorPrefix } from "../command/cmd_meta.js";
59
+ import { alignedPrinter } from "../print/aligned.js";
60
+ import { asciidocPrinter } from "../print/asciidoc.js";
61
+ import { csvPrinter } from "../print/csv.js";
62
+ import { htmlPrinter } from "../print/html.js";
63
+ import { jsonPrinter } from "../print/json.js";
64
+ import { latexLongtablePrinter, latexPrinter } from "../print/latex.js";
65
+ import { openPager, shouldPage } from "../print/pager.js";
66
+ import { troffMsPrinter } from "../print/troff.js";
67
+ import { unalignedPrinter } from "../print/unaligned.js";
68
+ import { formatDurationMs } from "../print/units.js";
69
69
  const readTxStatus = (conn) => {
70
70
  const status = conn.txStatus;
71
- return status ?? 'I';
71
+ return status ?? "I";
72
72
  };
73
73
  // ---------------------------------------------------------------------------
74
74
  // Statement classification.
@@ -79,8 +79,8 @@ const readTxStatus = (conn) => {
79
79
  // mirror both with a lightweight prefix matcher — the SQL was already
80
80
  // normalised by the scanner before reaching us.
81
81
  // ---------------------------------------------------------------------------
82
- const SAVEPOINT_NAME = 'pg_psql_temporary_savepoint';
83
- const CURSOR_NAME = '_psql_cursor';
82
+ const SAVEPOINT_NAME = "pg_psql_temporary_savepoint";
83
+ const CURSOR_NAME = "_psql_cursor";
84
84
  /**
85
85
  * Strip leading whitespace and `--` line / slash-star block comments from
86
86
  * `sql`. Mirrors what upstream psql's scanner advances past before handing a
@@ -124,7 +124,8 @@ export const stripLeadingCommentsAndWS = (sql) => {
124
124
  i += 2;
125
125
  let depth = 1;
126
126
  while (i < n && depth > 0) {
127
- if (sql.charCodeAt(i) === 0x2f && sql.charCodeAt(i + 1) === 0x2a) {
127
+ if (sql.charCodeAt(i) === 0x2f &&
128
+ sql.charCodeAt(i + 1) === 0x2a) {
128
129
  depth++;
129
130
  i += 2;
130
131
  }
@@ -150,19 +151,19 @@ const peekKeywords = (sql, count = 3) => {
150
151
  let i = 0;
151
152
  while (i < sql.length) {
152
153
  const ch = sql[i];
153
- if (ch === ' ' || ch === '\t' || ch === '\n' || ch === '\r') {
154
+ if (ch === " " || ch === "\t" || ch === "\n" || ch === "\r") {
154
155
  i++;
155
156
  continue;
156
157
  }
157
- if (ch === '-' && sql[i + 1] === '-') {
158
- const nl = sql.indexOf('\n', i + 2);
158
+ if (ch === "-" && sql[i + 1] === "-") {
159
+ const nl = sql.indexOf("\n", i + 2);
159
160
  if (nl === -1)
160
161
  return [];
161
162
  i = nl + 1;
162
163
  continue;
163
164
  }
164
- if (ch === '/' && sql[i + 1] === '*') {
165
- const end = sql.indexOf('*/', i + 2);
165
+ if (ch === "/" && sql[i + 1] === "*") {
166
+ const end = sql.indexOf("*/", i + 2);
166
167
  if (end === -1)
167
168
  return [];
168
169
  i = end + 2;
@@ -182,56 +183,56 @@ const commandNoBegin = (sql) => {
182
183
  if (!w0)
183
184
  return false;
184
185
  switch (w0) {
185
- case 'ABORT':
186
- case 'BEGIN':
187
- case 'COMMIT':
188
- case 'END':
189
- case 'ROLLBACK':
190
- case 'START':
191
- case 'SAVEPOINT':
192
- case 'RELEASE':
186
+ case "ABORT":
187
+ case "BEGIN":
188
+ case "COMMIT":
189
+ case "END":
190
+ case "ROLLBACK":
191
+ case "START":
192
+ case "SAVEPOINT":
193
+ case "RELEASE":
193
194
  return true;
194
- case 'PREPARE':
195
- return w1 === 'TRANSACTION';
196
- case 'VACUUM':
195
+ case "PREPARE":
196
+ return w1 === "TRANSACTION";
197
+ case "VACUUM":
197
198
  return true;
198
- case 'CLUSTER':
199
+ case "CLUSTER":
199
200
  // CLUSTER without an explicit argument runs over the whole DB and
200
201
  // cannot be transactional.
201
- return w1 === undefined || w1 === '';
202
- case 'CREATE':
203
- if (w1 === 'DATABASE' || w1 === 'TABLESPACE')
202
+ return w1 === undefined || w1 === "";
203
+ case "CREATE":
204
+ if (w1 === "DATABASE" || w1 === "TABLESPACE")
204
205
  return true;
205
206
  // CREATE INDEX CONCURRENTLY / CREATE UNIQUE INDEX CONCURRENTLY cannot
206
207
  // run inside a transaction block — psql must send them bare even with
207
208
  // AUTOCOMMIT=off (review item #24).
208
- if (w1 === 'INDEX' && w2 === 'CONCURRENTLY')
209
+ if (w1 === "INDEX" && w2 === "CONCURRENTLY")
209
210
  return true;
210
- if (w1 === 'UNIQUE' && w2 === 'INDEX' && w3 === 'CONCURRENTLY') {
211
+ if (w1 === "UNIQUE" && w2 === "INDEX" && w3 === "CONCURRENTLY") {
211
212
  return true;
212
213
  }
213
214
  return false;
214
- case 'DROP':
215
+ case "DROP":
215
216
  // DROP DATABASE / TABLESPACE / INDEX CONCURRENTLY. (There is no
216
217
  // `DROP TABLE … CONCURRENTLY` in PostgreSQL — removed that bogus case.)
217
- if (w1 === 'DATABASE' || w1 === 'TABLESPACE')
218
+ if (w1 === "DATABASE" || w1 === "TABLESPACE")
218
219
  return true;
219
- if (w1 === 'INDEX' && w2 === 'CONCURRENTLY')
220
+ if (w1 === "INDEX" && w2 === "CONCURRENTLY")
220
221
  return true;
221
222
  return false;
222
- case 'REINDEX':
223
+ case "REINDEX":
223
224
  // REINDEX DATABASE / SYSTEM / INDEX CONCURRENTLY / TABLE CONCURRENTLY.
224
- if (w1 === 'DATABASE' || w1 === 'SYSTEM')
225
+ if (w1 === "DATABASE" || w1 === "SYSTEM")
225
226
  return true;
226
- if (w1 === 'INDEX' && w2 === 'CONCURRENTLY')
227
+ if (w1 === "INDEX" && w2 === "CONCURRENTLY")
227
228
  return true;
228
- if (w1 === 'TABLE' && w2 === 'CONCURRENTLY')
229
+ if (w1 === "TABLE" && w2 === "CONCURRENTLY")
229
230
  return true;
230
231
  return false;
231
- case 'ALTER':
232
- return w1 === 'SYSTEM';
233
- case 'DISCARD':
234
- return w1 === 'ALL';
232
+ case "ALTER":
233
+ return w1 === "SYSTEM";
234
+ case "DISCARD":
235
+ return w1 === "ALL";
235
236
  default:
236
237
  return false;
237
238
  }
@@ -239,7 +240,7 @@ const commandNoBegin = (sql) => {
239
240
  /** True when the statement opens with SELECT / VALUES / TABLE / WITH. */
240
241
  const isSelectCommand = (sql) => {
241
242
  const [w0] = peekKeywords(sql, 1);
242
- return w0 === 'SELECT' || w0 === 'VALUES' || w0 === 'TABLE' || w0 === 'WITH';
243
+ return (w0 === "SELECT" || w0 === "VALUES" || w0 === "TABLE" || w0 === "WITH");
243
244
  };
244
245
  /**
245
246
  * Does this statement effectively destroy / replace the temporary savepoint?
@@ -249,10 +250,10 @@ const isSelectCommand = (sql) => {
249
250
  */
250
251
  const destroysSavepoint = (sql) => {
251
252
  const [w0] = peekKeywords(sql, 1);
252
- return (w0 === 'COMMIT' ||
253
- w0 === 'ROLLBACK' ||
254
- w0 === 'SAVEPOINT' ||
255
- w0 === 'RELEASE');
253
+ return (w0 === "COMMIT" ||
254
+ w0 === "ROLLBACK" ||
255
+ w0 === "SAVEPOINT" ||
256
+ w0 === "RELEASE");
256
257
  };
257
258
  // ---------------------------------------------------------------------------
258
259
  // Printer selection. Routes to the printer for the active output format —
@@ -262,24 +263,24 @@ const destroysSavepoint = (sql) => {
262
263
  // ---------------------------------------------------------------------------
263
264
  const pickPrinter = (settings) => {
264
265
  switch (settings.popt.topt.format) {
265
- case 'aligned':
266
- case 'wrapped':
266
+ case "aligned":
267
+ case "wrapped":
267
268
  return alignedPrinter;
268
- case 'unaligned':
269
+ case "unaligned":
269
270
  return unalignedPrinter;
270
- case 'csv':
271
+ case "csv":
271
272
  return csvPrinter;
272
- case 'json':
273
+ case "json":
273
274
  return jsonPrinter;
274
- case 'html':
275
+ case "html":
275
276
  return htmlPrinter;
276
- case 'asciidoc':
277
+ case "asciidoc":
277
278
  return asciidocPrinter;
278
- case 'latex':
279
+ case "latex":
279
280
  return latexPrinter;
280
- case 'latex-longtable':
281
+ case "latex-longtable":
281
282
  return latexLongtablePrinter;
282
- case 'troff-ms':
283
+ case "troff-ms":
283
284
  return troffMsPrinter;
284
285
  default:
285
286
  return alignedPrinter;
@@ -303,32 +304,32 @@ export const pickOut = (ctx, oneShot) => {
303
304
  // Upstream reads them once at the start of SendQuery; we do the same so a
304
305
  // hook that mutates them mid-query doesn't reshape our logic underneath us.
305
306
  // ---------------------------------------------------------------------------
306
- const readAutocommit = (settings) => settings.vars.asBool('AUTOCOMMIT', true);
307
+ const readAutocommit = (settings) => settings.vars.asBool("AUTOCOMMIT", true);
307
308
  const readOnErrorRollback = (settings) => {
308
- const raw = settings.vars.get('ON_ERROR_ROLLBACK');
309
+ const raw = settings.vars.get("ON_ERROR_ROLLBACK");
309
310
  if (raw === undefined)
310
311
  return settings.onErrorRollback;
311
312
  const v = raw.toLowerCase();
312
- if (v === 'interactive')
313
- return 'interactive';
314
- if (v === 'on' || v === 'true' || v === 'yes' || v === '1')
315
- return 'on';
316
- return 'off';
313
+ if (v === "interactive")
314
+ return "interactive";
315
+ if (v === "on" || v === "true" || v === "yes" || v === "1")
316
+ return "on";
317
+ return "off";
317
318
  };
318
319
  const readFetchCount = (settings) => {
319
- const v = settings.vars.asInt('FETCH_COUNT', settings.fetchCount);
320
- if (typeof v !== 'number')
320
+ const v = settings.vars.asInt("FETCH_COUNT", settings.fetchCount);
321
+ if (typeof v !== "number")
321
322
  return 0;
322
323
  return Math.max(0, v | 0);
323
324
  };
324
- const readSinglestep = (settings) => settings.singlestep || settings.vars.asBool('SINGLESTEP', false);
325
+ const readSinglestep = (settings) => settings.singlestep || settings.vars.asBool("SINGLESTEP", false);
325
326
  /**
326
327
  * SHOW_ALL_RESULTS controls multi-statement `\;` printing. Default 'on' —
327
328
  * every result set is rendered. When 'off' / '0', only the LAST result set
328
329
  * is printed (upstream's `pset.show_all_results` flag, consulted by
329
330
  * `PrintQueryResults` in common.c).
330
331
  */
331
- const readShowAllResults = (settings) => settings.vars.asBool('SHOW_ALL_RESULTS', true);
332
+ const readShowAllResults = (settings) => settings.vars.asBool("SHOW_ALL_RESULTS", true);
332
333
  // ---------------------------------------------------------------------------
333
334
  // Error printing — mirrors mainloop's `writeError` format. We keep it local
334
335
  // so callers other than the mainloop can still emit consistent errors.
@@ -371,7 +372,7 @@ export const writeQueryError = (ctx, fallbackMessage) => {
371
372
  const lines = formatErrorReport(e, ctx.settings.verbosity, ctx.settings.showContext);
372
373
  const prefix = psqlErrorPrefix(ctx.settings);
373
374
  const prefixed = [prefix + lines[0], ...lines.slice(1)];
374
- ctx.stderr.write(prefixed.join('\n') + '\n');
375
+ ctx.stderr.write(prefixed.join("\n") + "\n");
375
376
  };
376
377
  /**
377
378
  * Strip leading whitespace from a query and rebase a 1-based server position
@@ -404,7 +405,7 @@ const normaliseSqlAndPosition = (sqlText, position) => {
404
405
  if (leading === 0)
405
406
  return { sqlText, position };
406
407
  const trimmed = sqlText.slice(leading);
407
- if (typeof position !== 'string')
408
+ if (typeof position !== "string")
408
409
  return { sqlText: trimmed, position };
409
410
  const original = parseInt(position, 10);
410
411
  if (!Number.isFinite(original) || original <= 0) {
@@ -461,7 +462,7 @@ export const captureLastError = (settings, err, sqlText) => {
461
462
  };
462
463
  return settings.lastErrorResult.message ?? fallbackMessage;
463
464
  };
464
- const recordError = (ctx, err, sqlText = '') => captureLastError(ctx.settings, err, sqlText);
465
+ const recordError = (ctx, err, sqlText = "") => captureLastError(ctx.settings, err, sqlText);
465
466
  /**
466
467
  * Update the per-statement diagnostic psql variables that upstream's
467
468
  * `SetResultVariables` / `SetErrorVariables` in `src/bin/psql/common.c`
@@ -487,21 +488,21 @@ const recordError = (ctx, err, sqlText = '') => captureLastError(ctx.settings, e
487
488
  */
488
489
  export const refreshErrorVars = (settings, outcome) => {
489
490
  const { vars } = settings;
490
- if (outcome.kind === 'error') {
491
+ if (outcome.kind === "error") {
491
492
  const last = settings.lastErrorResult;
492
- const code = last?.code ?? last?.sqlstate ?? 'XX000';
493
- const message = last?.message ?? '';
494
- vars.set('LAST_ERROR_MESSAGE', message);
495
- vars.set('LAST_ERROR_SQLSTATE', code);
496
- vars.set('SQLSTATE', code);
497
- vars.set('ERROR', 'true');
498
- vars.set('ROW_COUNT', '0');
493
+ const code = last?.code ?? last?.sqlstate ?? "XX000";
494
+ const message = last?.message ?? "";
495
+ vars.set("LAST_ERROR_MESSAGE", message);
496
+ vars.set("LAST_ERROR_SQLSTATE", code);
497
+ vars.set("SQLSTATE", code);
498
+ vars.set("ERROR", "true");
499
+ vars.set("ROW_COUNT", "0");
499
500
  return;
500
501
  }
501
- vars.set('SQLSTATE', '00000');
502
- vars.set('ERROR', 'false');
502
+ vars.set("SQLSTATE", "00000");
503
+ vars.set("ERROR", "false");
503
504
  const rc = outcome.rowCount ?? 0;
504
- vars.set('ROW_COUNT', String(rc));
505
+ vars.set("ROW_COUNT", String(rc));
505
506
  };
506
507
  // ---------------------------------------------------------------------------
507
508
  // SINGLESTEP confirmation.
@@ -511,11 +512,11 @@ export const refreshErrorVars = (settings, outcome) => {
511
512
  // output) and read one line from ctx.stdin. Returns true to proceed.
512
513
  // ---------------------------------------------------------------------------
513
514
  const readOneLine = (stdin) => new Promise((resolve) => {
514
- let buf = '';
515
+ let buf = "";
515
516
  let resolved = false;
516
517
  const onData = (chunk) => {
517
518
  buf += chunk.toString();
518
- const nl = buf.indexOf('\n');
519
+ const nl = buf.indexOf("\n");
519
520
  if (nl !== -1) {
520
521
  const line = buf.slice(0, nl);
521
522
  cleanup();
@@ -533,20 +534,20 @@ const readOneLine = (stdin) => new Promise((resolve) => {
533
534
  }
534
535
  };
535
536
  const cleanup = () => {
536
- stdin.off('data', onData);
537
- stdin.off('end', onEnd);
538
- stdin.off('close', onEnd);
537
+ stdin.off("data", onData);
538
+ stdin.off("end", onEnd);
539
+ stdin.off("close", onEnd);
539
540
  };
540
- stdin.on('data', onData);
541
- stdin.once('end', onEnd);
542
- stdin.once('close', onEnd);
541
+ stdin.on("data", onData);
542
+ stdin.once("end", onEnd);
543
+ stdin.once("close", onEnd);
543
544
  });
544
545
  const confirmSinglestep = async (ctx, sql) => {
545
546
  ctx.stderr.write(`***(Single step mode: verify command)*******************************************\n` +
546
547
  `${sql}\n` +
547
548
  `***(press return to proceed or enter x and return to cancel)********************\n`);
548
549
  const line = await readOneLine(ctx.stdin);
549
- return !line.trim().toLowerCase().startsWith('x');
550
+ return !line.trim().toLowerCase().startsWith("x");
550
551
  };
551
552
  // ---------------------------------------------------------------------------
552
553
  // Result rendering. We tally rows printed / rows affected for the QueryStats
@@ -563,10 +564,10 @@ const confirmSinglestep = async (ctx, sql) => {
563
564
  * the server sent — we round-trip it through our parser).
564
565
  */
565
566
  const formatCommandTag = (rs) => {
566
- const command = (rs.command || '').trim();
567
+ const command = (rs.command || "").trim();
567
568
  if (command.length === 0)
568
- return '';
569
- if (command === 'INSERT') {
569
+ return "";
570
+ if (command === "INSERT") {
570
571
  // INSERT is the only tag with the legacy oid in front of rowCount.
571
572
  return `INSERT ${rs.oid ?? 0} ${rs.rowCount ?? 0}`;
572
573
  }
@@ -585,7 +586,7 @@ const formatCommandTag = (rs) => {
585
586
  const pickPagerDecision = (ctx, results, out) => {
586
587
  const popt = ctx.settings.popt.topt;
587
588
  // Pager off → never page (cheap exit, no looping needed).
588
- if (popt.pager === 'off')
589
+ if (popt.pager === "off")
589
590
  return false;
590
591
  // `\o FILE` (or `\g FILE`) wins over pager. If the queryFout is set, the
591
592
  // pager must not activate even when popt.pager === 'always'.
@@ -755,10 +756,10 @@ export const renderResultSet = (ctx, rs, out) => {
755
756
  * strip it rather than render a caret pointing past end-of-line.
756
757
  */
757
758
  const rebasePositionForCursor = (err, wrapper, userSql) => {
758
- if (!err || typeof err !== 'object')
759
+ if (!err || typeof err !== "object")
759
760
  return;
760
761
  const e = err;
761
- if (typeof e.position !== 'string')
762
+ if (typeof e.position !== "string")
762
763
  return;
763
764
  const original = parseInt(e.position, 10);
764
765
  if (!Number.isFinite(original) || original <= 0)
@@ -767,7 +768,7 @@ const rebasePositionForCursor = (err, wrapper, userSql) => {
767
768
  // user's SQL verbatim (the DECLARE case), the prefix length tells us how
768
769
  // far to shift. The trailing `;` is stripped before wrapping, so we
769
770
  // search for the stripped form.
770
- const stripped = userSql.replace(/;\s*$/u, '');
771
+ const stripped = userSql.replace(/;\s*$/u, "");
771
772
  const offset = wrapper.indexOf(stripped);
772
773
  if (offset === -1) {
773
774
  // FETCH-leg failures: the wrapper is `FETCH FORWARD …` and the server
@@ -789,16 +790,16 @@ const rebasePositionForCursor = (err, wrapper, userSql) => {
789
790
  };
790
791
  const runCursorLoop = async (ctx, sql, fetchCount, out) => {
791
792
  if (!ctx.settings.db)
792
- throw new Error('no connection to the server');
793
+ throw new Error("no connection to the server");
793
794
  const db = ctx.settings.db;
794
795
  // Make sure we're in a transaction so the cursor survives between FETCH
795
796
  // calls. If we're idle, open one here and remember to close it.
796
- const initiallyIdle = readTxStatus(db) === 'I';
797
+ const initiallyIdle = readTxStatus(db) === "I";
797
798
  if (initiallyIdle) {
798
- await db.execSimple('BEGIN');
799
+ await db.execSimple("BEGIN");
799
800
  }
800
801
  // Strip trailing ';' from the user SQL so DECLARE CURSOR FOR <stmt> parses.
801
- const stripped = sql.replace(/;\s*$/u, '');
802
+ const stripped = sql.replace(/;\s*$/u, "");
802
803
  const declared = `DECLARE ${CURSOR_NAME} NO SCROLL CURSOR FOR ${stripped}`;
803
804
  const fetchSql = `FETCH FORWARD ${String(fetchCount)} FROM ${CURSOR_NAME}`;
804
805
  const rowsAffected = 0;
@@ -859,7 +860,7 @@ const runCursorLoop = async (ctx, sql, fetchCount, out) => {
859
860
  await db.execSimple(`CLOSE ${CURSOR_NAME}`);
860
861
  cursorOpen = false;
861
862
  if (initiallyIdle) {
862
- await db.execSimple('COMMIT');
863
+ await db.execSimple("COMMIT");
863
864
  }
864
865
  return { rowsAffected, rowsPrinted, lastRowCount: rowsPrinted };
865
866
  }
@@ -913,7 +914,7 @@ const runCursorLoop = async (ctx, sql, fetchCount, out) => {
913
914
  }
914
915
  if (initiallyIdle) {
915
916
  try {
916
- await db.execSimple('ROLLBACK');
917
+ await db.execSimple("ROLLBACK");
917
918
  }
918
919
  catch {
919
920
  // ignore
@@ -942,7 +943,7 @@ export const executeAndPrint = async (ctx, sqlRaw, opts = {}) => {
942
943
  durationMs: 0,
943
944
  };
944
945
  if (!ctx.settings.db) {
945
- writeError(ctx, 'no connection to the server');
946
+ writeError(ctx, "no connection to the server");
946
947
  stats.hadError = true;
947
948
  return stats;
948
949
  }
@@ -990,7 +991,7 @@ export const executeAndPrint = async (ctx, sqlRaw, opts = {}) => {
990
991
  finally {
991
992
  if (ctx.settings.timing) {
992
993
  stats.durationMs = performance.now() - started;
993
- ctx.stdout.write('\n' + formatDurationMs(stats.durationMs) + '\n');
994
+ ctx.stdout.write("\n" + formatDurationMs(stats.durationMs) + "\n");
994
995
  }
995
996
  }
996
997
  // Mirror upstream's `SetResultVariables` / `SetErrorVariables` call at the
@@ -998,8 +999,8 @@ export const executeAndPrint = async (ctx, sqlRaw, opts = {}) => {
998
999
  // `\echo :SQLSTATE` and friends see the most recent outcome. ROW_COUNT
999
1000
  // tracks libpq's `PQcmdTuples` on the LAST result of a `\;` batch.
1000
1001
  refreshErrorVars(ctx.settings, stats.hadError
1001
- ? { kind: 'error' }
1002
- : { kind: 'success', rowCount: lastRowCount });
1002
+ ? { kind: "error" }
1003
+ : { kind: "success", rowCount: lastRowCount });
1003
1004
  return stats;
1004
1005
  };
1005
1006
  // ---------------------------------------------------------------------------
@@ -1029,7 +1030,7 @@ export const sendQuery = async (ctx, sqlRaw, opts = {}) => {
1029
1030
  // `PSQLexec` and leaves it set on error.
1030
1031
  ctx.settings.lastQuery = sql;
1031
1032
  if (!ctx.settings.db) {
1032
- writeError(ctx, 'no connection to the server');
1033
+ writeError(ctx, "no connection to the server");
1033
1034
  stats.hadError = true;
1034
1035
  return stats;
1035
1036
  }
@@ -1040,7 +1041,9 @@ export const sendQuery = async (ctx, sqlRaw, opts = {}) => {
1040
1041
  // Upstream marks the statement as failed when the user cancels. We
1041
1042
  // mirror that so ON_ERROR_STOP halts a script.
1042
1043
  stats.hadError = true;
1043
- ctx.settings.lastErrorResult = { message: 'command cancelled by user' };
1044
+ ctx.settings.lastErrorResult = {
1045
+ message: "command cancelled by user",
1046
+ };
1044
1047
  return stats;
1045
1048
  }
1046
1049
  }
@@ -1056,9 +1059,9 @@ export const sendQuery = async (ctx, sqlRaw, opts = {}) => {
1056
1059
  const started = ctx.settings.timing ? performance.now() : 0;
1057
1060
  // ----- AUTOCOMMIT: implicit BEGIN ----------------------------------------
1058
1061
  let implicitBeginIssued = false;
1059
- if (!autocommit && readTxStatus(db) === 'I' && !commandNoBegin(sql)) {
1062
+ if (!autocommit && readTxStatus(db) === "I" && !commandNoBegin(sql)) {
1060
1063
  try {
1061
- await db.execSimple('BEGIN');
1064
+ await db.execSimple("BEGIN");
1062
1065
  implicitBeginIssued = true;
1063
1066
  }
1064
1067
  catch (err) {
@@ -1067,16 +1070,16 @@ export const sendQuery = async (ctx, sqlRaw, opts = {}) => {
1067
1070
  stats.hadError = true;
1068
1071
  if (ctx.settings.timing) {
1069
1072
  stats.durationMs = performance.now() - started;
1070
- ctx.stdout.write('\n' + formatDurationMs(stats.durationMs) + '\n');
1073
+ ctx.stdout.write("\n" + formatDurationMs(stats.durationMs) + "\n");
1071
1074
  }
1072
1075
  return stats;
1073
1076
  }
1074
1077
  }
1075
1078
  // ----- ON_ERROR_ROLLBACK: SAVEPOINT --------------------------------------
1076
- const savepointActive = onErrorRollback !== 'off' &&
1077
- (onErrorRollback === 'on' ||
1078
- (onErrorRollback === 'interactive' && interactive)) &&
1079
- readTxStatus(db) === 'T';
1079
+ const savepointActive = onErrorRollback !== "off" &&
1080
+ (onErrorRollback === "on" ||
1081
+ (onErrorRollback === "interactive" && interactive)) &&
1082
+ readTxStatus(db) === "T";
1080
1083
  let savepointIssued = false;
1081
1084
  if (savepointActive) {
1082
1085
  try {
@@ -1090,7 +1093,7 @@ export const sendQuery = async (ctx, sqlRaw, opts = {}) => {
1090
1093
  stats.hadError = true;
1091
1094
  if (ctx.settings.timing) {
1092
1095
  stats.durationMs = performance.now() - started;
1093
- ctx.stdout.write('\n' + formatDurationMs(stats.durationMs) + '\n');
1096
+ ctx.stdout.write("\n" + formatDurationMs(stats.durationMs) + "\n");
1094
1097
  }
1095
1098
  return stats;
1096
1099
  }
@@ -1145,7 +1148,7 @@ export const sendQuery = async (ctx, sqlRaw, opts = {}) => {
1145
1148
  // Release the now-empty savepoint too, matching upstream.
1146
1149
  await db.execSimple(`RELEASE SAVEPOINT ${SAVEPOINT_NAME}`);
1147
1150
  }
1148
- else if (!destroysSavepoint(sql) && readTxStatus(db) === 'T') {
1151
+ else if (!destroysSavepoint(sql) && readTxStatus(db) === "T") {
1149
1152
  await db.execSimple(`RELEASE SAVEPOINT ${SAVEPOINT_NAME}`);
1150
1153
  }
1151
1154
  }
@@ -1175,7 +1178,7 @@ export const sendQuery = async (ctx, sqlRaw, opts = {}) => {
1175
1178
  // `pg_log_info` writes to stderr in upstream and strips one trailing
1176
1179
  // newline before tacking its own `\n` on the message — we mirror by
1177
1180
  // going through ctx.stderr and the explicit trim.
1178
- if (stats.hadError && ctx.settings.echo === 'errors') {
1181
+ if (stats.hadError && ctx.settings.echo === "errors") {
1179
1182
  // Strip leading whitespace + `--`-style comments from queryBuf so the
1180
1183
  // STATEMENT echo matches upstream's shape. Upstream `psqlscan.l`'s
1181
1184
  // `{whitespace}` rule (which includes line comments) SUPPRESSES
@@ -1191,15 +1194,15 @@ export const sendQuery = async (ctx, sqlRaw, opts = {}) => {
1191
1194
  const before = stmt.length;
1192
1195
  // Leading whitespace including form-feed (matches psqlscan's
1193
1196
  // {space} = [ \t\n\r\f]).
1194
- stmt = stmt.replace(/^[ \t\n\r\f]+/, '');
1197
+ stmt = stmt.replace(/^[ \t\n\r\f]+/, "");
1195
1198
  // Leading `--`-style line comment, up to (but not including) the
1196
1199
  // next newline. The trailing newline is then eaten by the next
1197
1200
  // whitespace pass.
1198
- stmt = stmt.replace(/^--[^\n\r]*/, '');
1201
+ stmt = stmt.replace(/^--[^\n\r]*/, "");
1199
1202
  if (stmt.length === before)
1200
1203
  break;
1201
1204
  }
1202
- if (stmt.endsWith('\n'))
1205
+ if (stmt.endsWith("\n"))
1203
1206
  stmt = stmt.slice(0, -1);
1204
1207
  ctx.stderr.write(`STATEMENT: ${stmt}\n`);
1205
1208
  }
@@ -1208,11 +1211,11 @@ export const sendQuery = async (ctx, sqlRaw, opts = {}) => {
1208
1211
  // result of a `\;` batch; SQLSTATE / ERROR reset every statement; the
1209
1212
  // LAST_ERROR_* pair only changes on failure (sticky on success).
1210
1213
  refreshErrorVars(ctx.settings, stats.hadError
1211
- ? { kind: 'error' }
1212
- : { kind: 'success', rowCount: lastRowCount });
1214
+ ? { kind: "error" }
1215
+ : { kind: "success", rowCount: lastRowCount });
1213
1216
  if (ctx.settings.timing) {
1214
1217
  stats.durationMs = performance.now() - started;
1215
- ctx.stdout.write('\n' + formatDurationMs(stats.durationMs) + '\n');
1218
+ ctx.stdout.write("\n" + formatDurationMs(stats.durationMs) + "\n");
1216
1219
  }
1217
1220
  return stats;
1218
1221
  };