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
@@ -34,11 +34,11 @@
34
34
  * Variable side-effects: `\lo_import` sets `LASTOID` to the new OID
35
35
  * (mirrors `do_lo_import`'s `SetVariable(pset.vars, "LASTOID", oidbuf)`).
36
36
  */
37
- import { promises as fsPromises } from 'node:fs';
38
- import { Buffer } from 'node:buffer';
39
- import { alignedPrinter } from '../print/aligned.js';
40
- import { listLargeObjects } from '../describe/queries.js';
41
- import { writeErr, writeOut } from './shared.js';
37
+ import { Buffer } from "node:buffer";
38
+ import { promises as fsPromises } from "node:fs";
39
+ import { listLargeObjects } from "../describe/queries.js";
40
+ import { alignedPrinter } from "../print/aligned.js";
41
+ import { writeErr, writeOut } from "./shared.js";
42
42
  // ---------------------------------------------------------------------------
43
43
  // Helpers shared by all four commands
44
44
  // ---------------------------------------------------------------------------
@@ -47,8 +47,8 @@ const conn = (ctx) => ctx.settings.db;
47
47
  /** Emit "no current connection" error in the psql style. */
48
48
  const noConn = (ctx) => {
49
49
  writeErr(`\\${ctx.cmdName}: no connection to the server\n`);
50
- ctx.settings.lastErrorResult = { message: 'no connection to the server' };
51
- return { status: 'error' };
50
+ ctx.settings.lastErrorResult = { message: "no connection to the server" };
51
+ return { status: "error" };
52
52
  };
53
53
  /** Pull the diagnostic-style error message off a thrown value. */
54
54
  const errMsg = (err) => err instanceof Error ? err.message : String(err);
@@ -57,7 +57,7 @@ const errMsg = (err) => err instanceof Error ? err.message : String(err);
57
57
  * Hex form is unambiguous and works regardless of `bytea_output` or
58
58
  * `standard_conforming_strings`.
59
59
  */
60
- const byteaText = (buf) => `\\x${buf.toString('hex')}`;
60
+ const byteaText = (buf) => `\\x${buf.toString("hex")}`;
61
61
  /**
62
62
  * Parse a string argument as an unsigned 32-bit OID. Returns `null` on
63
63
  * malformed input (negative, non-integer, or out of range). Matches the
@@ -79,21 +79,21 @@ const parseOid = (raw) => {
79
79
  */
80
80
  const cellToString = (v) => {
81
81
  if (v === null || v === undefined)
82
- return '';
83
- if (typeof v === 'string')
82
+ return "";
83
+ if (typeof v === "string")
84
84
  return v;
85
85
  if (Buffer.isBuffer(v))
86
- return v.toString('utf-8');
87
- if (typeof v === 'number' ||
88
- typeof v === 'boolean' ||
89
- typeof v === 'bigint') {
86
+ return v.toString("utf-8");
87
+ if (typeof v === "number" ||
88
+ typeof v === "boolean" ||
89
+ typeof v === "bigint") {
90
90
  return String(v);
91
91
  }
92
92
  try {
93
93
  return JSON.stringify(v);
94
94
  }
95
95
  catch {
96
- return '';
96
+ return "";
97
97
  }
98
98
  };
99
99
  // ---------------------------------------------------------------------------
@@ -126,24 +126,24 @@ const runLoList = async (ctx, verbose) => {
126
126
  },
127
127
  };
128
128
  await alignedPrinter.printQuery(coerced, opts, process.stdout);
129
- return { status: 'ok' };
129
+ return { status: "ok" };
130
130
  }
131
131
  catch (err) {
132
132
  writeErr(`\\${ctx.cmdName}: ${errMsg(err)}\n`);
133
133
  ctx.settings.lastErrorResult = { message: errMsg(err) };
134
- return { status: 'error' };
134
+ return { status: "error" };
135
135
  }
136
136
  };
137
137
  /** `\lo_list` — non-verbose listing. */
138
138
  export const cmdLoList = {
139
- name: 'lo_list',
140
- helpKey: 'lo_list',
139
+ name: "lo_list",
140
+ helpKey: "lo_list",
141
141
  run: (ctx) => runLoList(ctx, false),
142
142
  };
143
143
  /** `\lo_list+` — verbose listing (adds Access privileges column). */
144
144
  export const cmdLoListPlus = {
145
- name: 'lo_list+',
146
- helpKey: 'lo_list',
145
+ name: "lo_list+",
146
+ helpKey: "lo_list",
147
147
  run: (ctx) => runLoList(ctx, true),
148
148
  };
149
149
  // ---------------------------------------------------------------------------
@@ -164,24 +164,26 @@ export const cmdLoListPlus = {
164
164
  * Errors fall through to the standard `\lo_import: <msg>` diagnostic.
165
165
  */
166
166
  export const cmdLoImport = {
167
- name: 'lo_import',
168
- helpKey: 'lo_import',
167
+ name: "lo_import",
168
+ helpKey: "lo_import",
169
169
  run: async (ctx) => {
170
170
  const c = conn(ctx);
171
171
  if (!c)
172
172
  return noConn(ctx);
173
- const file = ctx.nextArg('normal');
173
+ const file = ctx.nextArg("normal");
174
174
  if (file === null || file.length === 0) {
175
- writeErr('\\lo_import: missing required argument\n');
176
- ctx.settings.lastErrorResult = { message: 'missing required argument' };
177
- return { status: 'error' };
175
+ writeErr("\\lo_import: missing required argument\n");
176
+ ctx.settings.lastErrorResult = {
177
+ message: "missing required argument",
178
+ };
179
+ return { status: "error" };
178
180
  }
179
181
  // Comment is the next lexed slash-arg token, mirroring upstream
180
182
  // `do_lo_import`'s second `psql_scan_slash_option(OT_NORMAL)`. Using the
181
183
  // lexer (not the raw line) means it picks up the token AFTER the file —
182
184
  // `restOfLine()` ignored the read cursor and re-included the filename
183
185
  // itself in the comment.
184
- const commentRaw = ctx.nextArg('normal');
186
+ const commentRaw = ctx.nextArg("normal");
185
187
  const comment = commentRaw !== null && commentRaw.length > 0 ? commentRaw : null;
186
188
  let bytes;
187
189
  try {
@@ -190,13 +192,13 @@ export const cmdLoImport = {
190
192
  catch (err) {
191
193
  writeErr(`\\lo_import: ${errMsg(err)}\n`);
192
194
  ctx.settings.lastErrorResult = { message: errMsg(err) };
193
- return { status: 'error' };
195
+ return { status: "error" };
194
196
  }
195
197
  let oidStr;
196
198
  try {
197
- const rs = await c.query('SELECT pg_catalog.lo_from_bytea(0, $1::bytea)', [byteaText(bytes)]);
199
+ const rs = await c.query("SELECT pg_catalog.lo_from_bytea(0, $1::bytea)", [byteaText(bytes)]);
198
200
  if (rs.rows.length === 0) {
199
- throw new Error('lo_from_bytea returned no rows');
201
+ throw new Error("lo_from_bytea returned no rows");
200
202
  }
201
203
  oidStr = cellToString(rs.rows[0][0]);
202
204
  if (!/^\d+$/.test(oidStr)) {
@@ -206,7 +208,7 @@ export const cmdLoImport = {
206
208
  catch (err) {
207
209
  writeErr(`\\lo_import: ${errMsg(err)}\n`);
208
210
  ctx.settings.lastErrorResult = { message: errMsg(err) };
209
- return { status: 'error' };
211
+ return { status: "error" };
210
212
  }
211
213
  if (comment !== null) {
212
214
  try {
@@ -215,13 +217,13 @@ export const cmdLoImport = {
215
217
  catch (err) {
216
218
  writeErr(`\\lo_import: ${errMsg(err)}\n`);
217
219
  ctx.settings.lastErrorResult = { message: errMsg(err) };
218
- return { status: 'error' };
220
+ return { status: "error" };
219
221
  }
220
222
  }
221
223
  // Side effect: set LASTOID (matches upstream `do_lo_import`).
222
- ctx.settings.vars.set('LASTOID', oidStr);
224
+ ctx.settings.vars.set("LASTOID", oidStr);
223
225
  writeOut(`lo_import ${oidStr}\n`);
224
- return { status: 'ok' };
226
+ return { status: "ok" };
225
227
  },
226
228
  };
227
229
  // ---------------------------------------------------------------------------
@@ -239,30 +241,34 @@ export const cmdLoImport = {
239
241
  * Print `lo_export\n` on success — matches upstream `do_lo_export`.
240
242
  */
241
243
  export const cmdLoExport = {
242
- name: 'lo_export',
243
- helpKey: 'lo_export',
244
+ name: "lo_export",
245
+ helpKey: "lo_export",
244
246
  run: async (ctx) => {
245
247
  const c = conn(ctx);
246
248
  if (!c)
247
249
  return noConn(ctx);
248
- const oidArg = ctx.nextArg('normal');
249
- const file = ctx.nextArg('normal');
250
+ const oidArg = ctx.nextArg("normal");
251
+ const file = ctx.nextArg("normal");
250
252
  if (oidArg === null || file === null || file.length === 0) {
251
- writeErr('\\lo_export: missing required argument\n');
252
- ctx.settings.lastErrorResult = { message: 'missing required argument' };
253
- return { status: 'error' };
253
+ writeErr("\\lo_export: missing required argument\n");
254
+ ctx.settings.lastErrorResult = {
255
+ message: "missing required argument",
256
+ };
257
+ return { status: "error" };
254
258
  }
255
259
  const oid = parseOid(oidArg);
256
260
  if (oid === null) {
257
261
  writeErr(`\\lo_export: "${oidArg}" is not a valid large object OID\n`);
258
- ctx.settings.lastErrorResult = { message: 'invalid OID' };
259
- return { status: 'error' };
262
+ ctx.settings.lastErrorResult = { message: "invalid OID" };
263
+ return { status: "error" };
260
264
  }
261
265
  let bytes;
262
266
  try {
263
- const rs = await c.query('SELECT pg_catalog.lo_get($1::oid)', [oid]);
267
+ const rs = await c.query("SELECT pg_catalog.lo_get($1::oid)", [
268
+ oid,
269
+ ]);
264
270
  if (rs.rows.length === 0) {
265
- throw new Error('lo_get returned no rows');
271
+ throw new Error("lo_get returned no rows");
266
272
  }
267
273
  const cell = rs.rows[0][0];
268
274
  bytes = coerceBytea(cell);
@@ -270,7 +276,7 @@ export const cmdLoExport = {
270
276
  catch (err) {
271
277
  writeErr(`\\lo_export: ${errMsg(err)}\n`);
272
278
  ctx.settings.lastErrorResult = { message: errMsg(err) };
273
- return { status: 'error' };
279
+ return { status: "error" };
274
280
  }
275
281
  try {
276
282
  await fsPromises.writeFile(file, bytes);
@@ -278,10 +284,10 @@ export const cmdLoExport = {
278
284
  catch (err) {
279
285
  writeErr(`\\lo_export: ${errMsg(err)}\n`);
280
286
  ctx.settings.lastErrorResult = { message: errMsg(err) };
281
- return { status: 'error' };
287
+ return { status: "error" };
282
288
  }
283
- writeOut('lo_export\n');
284
- return { status: 'ok' };
289
+ writeOut("lo_export\n");
290
+ return { status: "ok" };
285
291
  },
286
292
  };
287
293
  /**
@@ -295,19 +301,19 @@ export const cmdLoExport = {
295
301
  const coerceBytea = (cell) => {
296
302
  if (Buffer.isBuffer(cell))
297
303
  return cell;
298
- if (typeof cell !== 'string') {
304
+ if (typeof cell !== "string") {
299
305
  throw new Error(`lo_get returned unexpected cell type: ${typeof cell}`);
300
306
  }
301
- if (cell.startsWith('\\x')) {
302
- return Buffer.from(cell.slice(2), 'hex');
307
+ if (cell.startsWith("\\x")) {
308
+ return Buffer.from(cell.slice(2), "hex");
303
309
  }
304
310
  // Legacy octal-escape decode (`\\\\NNN` → byte, `\\\\` → `\\`, others
305
311
  // pass through). Upstream `PQunescapeBytea` does the same.
306
312
  const out = [];
307
313
  let i = 0;
308
314
  while (i < cell.length) {
309
- if (cell[i] === '\\') {
310
- if (cell[i + 1] === '\\') {
315
+ if (cell[i] === "\\") {
316
+ if (cell[i + 1] === "\\") {
311
317
  out.push(0x5c);
312
318
  i += 2;
313
319
  continue;
@@ -335,34 +341,36 @@ const coerceBytea = (cell) => {
335
341
  * Print `lo_unlink <oid>\n` on success.
336
342
  */
337
343
  export const cmdLoUnlink = {
338
- name: 'lo_unlink',
339
- helpKey: 'lo_unlink',
344
+ name: "lo_unlink",
345
+ helpKey: "lo_unlink",
340
346
  run: async (ctx) => {
341
347
  const c = conn(ctx);
342
348
  if (!c)
343
349
  return noConn(ctx);
344
- const oidArg = ctx.nextArg('normal');
350
+ const oidArg = ctx.nextArg("normal");
345
351
  if (oidArg === null) {
346
- writeErr('\\lo_unlink: missing required argument\n');
347
- ctx.settings.lastErrorResult = { message: 'missing required argument' };
348
- return { status: 'error' };
352
+ writeErr("\\lo_unlink: missing required argument\n");
353
+ ctx.settings.lastErrorResult = {
354
+ message: "missing required argument",
355
+ };
356
+ return { status: "error" };
349
357
  }
350
358
  const oid = parseOid(oidArg);
351
359
  if (oid === null) {
352
360
  writeErr(`\\lo_unlink: "${oidArg}" is not a valid large object OID\n`);
353
- ctx.settings.lastErrorResult = { message: 'invalid OID' };
354
- return { status: 'error' };
361
+ ctx.settings.lastErrorResult = { message: "invalid OID" };
362
+ return { status: "error" };
355
363
  }
356
364
  try {
357
- await c.query('SELECT pg_catalog.lo_unlink($1::oid)', [oid]);
365
+ await c.query("SELECT pg_catalog.lo_unlink($1::oid)", [oid]);
358
366
  }
359
367
  catch (err) {
360
368
  writeErr(`\\lo_unlink: ${errMsg(err)}\n`);
361
369
  ctx.settings.lastErrorResult = { message: errMsg(err) };
362
- return { status: 'error' };
370
+ return { status: "error" };
363
371
  }
364
372
  writeOut(`lo_unlink ${String(oid)}\n`);
365
- return { status: 'ok' };
373
+ return { status: "ok" };
366
374
  },
367
375
  };
368
376
  // ---------------------------------------------------------------------------