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.
- package/README.md +2 -2
- package/dist/analytics.js +35 -33
- package/dist/api.js +34 -34
- package/dist/auth.js +50 -44
- package/dist/cli.js +2 -2
- package/dist/commands/auth.js +58 -52
- package/dist/commands/bootstrap.js +115 -157
- package/dist/commands/branches.js +154 -147
- package/dist/commands/bucket.js +124 -118
- package/dist/commands/checkout.js +49 -49
- package/dist/commands/config.js +212 -88
- package/dist/commands/connection_string.js +62 -62
- package/dist/commands/data_api.js +96 -96
- package/dist/commands/databases.js +23 -23
- package/dist/commands/deploy.js +12 -12
- package/dist/commands/dev.js +114 -114
- package/dist/commands/env.js +43 -43
- package/dist/commands/functions.js +97 -98
- package/dist/commands/index.js +26 -26
- package/dist/commands/init.js +23 -22
- package/dist/commands/ip_allow.js +29 -29
- package/dist/commands/link.js +223 -166
- package/dist/commands/neon_auth.js +381 -363
- package/dist/commands/operations.js +11 -11
- package/dist/commands/orgs.js +8 -8
- package/dist/commands/projects.js +101 -99
- package/dist/commands/psql.js +31 -31
- package/dist/commands/roles.js +21 -21
- package/dist/commands/schema_diff.js +23 -23
- package/dist/commands/set_context.js +17 -17
- package/dist/commands/status.js +17 -17
- package/dist/commands/user.js +5 -5
- package/dist/commands/vpc_endpoints.js +50 -50
- package/dist/config.js +7 -7
- package/dist/config_format.js +5 -5
- package/dist/context.js +23 -16
- package/dist/current_branch_fast_path.js +6 -6
- package/dist/dev/env.js +33 -33
- package/dist/dev/functions.js +4 -4
- package/dist/dev/inputs.js +6 -6
- package/dist/dev/runtime.js +25 -25
- package/dist/env.js +14 -14
- package/dist/env_file.js +13 -13
- package/dist/errors.js +19 -19
- package/dist/functions_api.js +10 -10
- package/dist/help.js +15 -15
- package/dist/index.js +94 -92
- package/dist/log.js +2 -2
- package/dist/pkg.js +5 -5
- package/dist/psql/cli.js +4 -2
- package/dist/psql/command/cmd_cond.js +61 -61
- package/dist/psql/command/cmd_connect.js +159 -154
- package/dist/psql/command/cmd_copy.js +107 -97
- package/dist/psql/command/cmd_describe.js +368 -363
- package/dist/psql/command/cmd_format.js +276 -263
- package/dist/psql/command/cmd_io.js +269 -263
- package/dist/psql/command/cmd_lo.js +74 -66
- package/dist/psql/command/cmd_meta.js +148 -148
- package/dist/psql/command/cmd_misc.js +17 -17
- package/dist/psql/command/cmd_pipeline.js +142 -135
- package/dist/psql/command/cmd_restrict.js +25 -25
- package/dist/psql/command/cmd_show.js +183 -168
- package/dist/psql/command/dispatch.js +26 -26
- package/dist/psql/command/shared.js +14 -14
- package/dist/psql/complete/filenames.js +16 -16
- package/dist/psql/complete/index.js +4 -4
- package/dist/psql/complete/matcher.js +33 -32
- package/dist/psql/complete/psqlVars.js +173 -173
- package/dist/psql/complete/queries.js +5 -3
- package/dist/psql/complete/rules.js +900 -863
- package/dist/psql/core/common.js +136 -133
- package/dist/psql/core/help.js +343 -343
- package/dist/psql/core/mainloop.js +160 -153
- package/dist/psql/core/prompt.js +126 -123
- package/dist/psql/core/settings.js +111 -111
- package/dist/psql/core/sqlHelp.js +150 -150
- package/dist/psql/core/startup.js +211 -205
- package/dist/psql/core/syncVars.js +14 -14
- package/dist/psql/core/variables.js +24 -24
- package/dist/psql/describe/formatters.js +302 -289
- package/dist/psql/describe/processNamePattern.js +28 -28
- package/dist/psql/describe/queries.js +656 -651
- package/dist/psql/index.js +436 -411
- package/dist/psql/io/history.js +36 -36
- package/dist/psql/io/input.js +15 -15
- package/dist/psql/io/lineEditor/buffer.js +27 -25
- package/dist/psql/io/lineEditor/complete.js +15 -15
- package/dist/psql/io/lineEditor/filename.js +22 -22
- package/dist/psql/io/lineEditor/index.js +65 -62
- package/dist/psql/io/lineEditor/keymap.js +325 -318
- package/dist/psql/io/lineEditor/vt100.js +60 -60
- package/dist/psql/io/pgpass.js +18 -18
- package/dist/psql/io/pgservice.js +14 -14
- package/dist/psql/io/psqlrc.js +46 -46
- package/dist/psql/print/aligned.js +175 -166
- package/dist/psql/print/asciidoc.js +51 -51
- package/dist/psql/print/crosstab.js +34 -31
- package/dist/psql/print/csv.js +25 -22
- package/dist/psql/print/html.js +54 -54
- package/dist/psql/print/json.js +12 -12
- package/dist/psql/print/latex.js +118 -118
- package/dist/psql/print/pager.js +28 -26
- package/dist/psql/print/troff.js +48 -48
- package/dist/psql/print/unaligned.js +15 -14
- package/dist/psql/print/units.js +17 -17
- package/dist/psql/scanner/slash.js +48 -46
- package/dist/psql/scanner/sql.js +88 -84
- package/dist/psql/scanner/stringutils.js +21 -17
- package/dist/psql/types/index.js +7 -7
- package/dist/psql/types/scanner.js +8 -8
- package/dist/psql/wire/connection.js +341 -327
- package/dist/psql/wire/copy.js +7 -7
- package/dist/psql/wire/pipeline.js +26 -24
- package/dist/psql/wire/protocol.js +102 -102
- package/dist/psql/wire/sasl.js +62 -62
- package/dist/psql/wire/tls.js +79 -73
- package/dist/storage_api.js +15 -15
- package/dist/test_utils/fixtures.js +34 -31
- package/dist/test_utils/oauth_server.js +5 -5
- package/dist/utils/api_enums.js +13 -13
- package/dist/utils/branch_notice.js +5 -5
- package/dist/utils/branch_picker.js +26 -26
- package/dist/utils/compute_units.js +4 -4
- package/dist/utils/enrichers.js +20 -15
- package/dist/utils/esbuild.js +28 -28
- package/dist/utils/formats.js +1 -1
- package/dist/utils/middlewares.js +3 -3
- package/dist/utils/package_manager.js +68 -0
- package/dist/utils/point_in_time.js +12 -12
- package/dist/utils/psql.js +30 -30
- package/dist/utils/string.js +2 -2
- package/dist/utils/ui.js +9 -9
- package/dist/utils/zip.js +1 -1
- package/dist/writer.js +17 -17
- package/package.json +6 -7
|
@@ -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 {
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
40
|
-
import {
|
|
41
|
-
import { writeErr, writeOut } from
|
|
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:
|
|
51
|
-
return { status:
|
|
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(
|
|
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 ===
|
|
82
|
+
return "";
|
|
83
|
+
if (typeof v === "string")
|
|
84
84
|
return v;
|
|
85
85
|
if (Buffer.isBuffer(v))
|
|
86
|
-
return v.toString(
|
|
87
|
-
if (typeof v ===
|
|
88
|
-
typeof v ===
|
|
89
|
-
typeof v ===
|
|
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:
|
|
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:
|
|
134
|
+
return { status: "error" };
|
|
135
135
|
}
|
|
136
136
|
};
|
|
137
137
|
/** `\lo_list` — non-verbose listing. */
|
|
138
138
|
export const cmdLoList = {
|
|
139
|
-
name:
|
|
140
|
-
helpKey:
|
|
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:
|
|
146
|
-
helpKey:
|
|
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:
|
|
168
|
-
helpKey:
|
|
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(
|
|
173
|
+
const file = ctx.nextArg("normal");
|
|
174
174
|
if (file === null || file.length === 0) {
|
|
175
|
-
writeErr(
|
|
176
|
-
ctx.settings.lastErrorResult = {
|
|
177
|
-
|
|
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(
|
|
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:
|
|
195
|
+
return { status: "error" };
|
|
194
196
|
}
|
|
195
197
|
let oidStr;
|
|
196
198
|
try {
|
|
197
|
-
const rs = await c.query(
|
|
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(
|
|
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:
|
|
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:
|
|
220
|
+
return { status: "error" };
|
|
219
221
|
}
|
|
220
222
|
}
|
|
221
223
|
// Side effect: set LASTOID (matches upstream `do_lo_import`).
|
|
222
|
-
ctx.settings.vars.set(
|
|
224
|
+
ctx.settings.vars.set("LASTOID", oidStr);
|
|
223
225
|
writeOut(`lo_import ${oidStr}\n`);
|
|
224
|
-
return { status:
|
|
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:
|
|
243
|
-
helpKey:
|
|
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(
|
|
249
|
-
const file = ctx.nextArg(
|
|
250
|
+
const oidArg = ctx.nextArg("normal");
|
|
251
|
+
const file = ctx.nextArg("normal");
|
|
250
252
|
if (oidArg === null || file === null || file.length === 0) {
|
|
251
|
-
writeErr(
|
|
252
|
-
ctx.settings.lastErrorResult = {
|
|
253
|
-
|
|
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:
|
|
259
|
-
return { status:
|
|
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(
|
|
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(
|
|
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:
|
|
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:
|
|
287
|
+
return { status: "error" };
|
|
282
288
|
}
|
|
283
|
-
writeOut(
|
|
284
|
-
return { status:
|
|
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 !==
|
|
304
|
+
if (typeof cell !== "string") {
|
|
299
305
|
throw new Error(`lo_get returned unexpected cell type: ${typeof cell}`);
|
|
300
306
|
}
|
|
301
|
-
if (cell.startsWith(
|
|
302
|
-
return Buffer.from(cell.slice(2),
|
|
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:
|
|
339
|
-
helpKey:
|
|
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(
|
|
350
|
+
const oidArg = ctx.nextArg("normal");
|
|
345
351
|
if (oidArg === null) {
|
|
346
|
-
writeErr(
|
|
347
|
-
ctx.settings.lastErrorResult = {
|
|
348
|
-
|
|
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:
|
|
354
|
-
return { status:
|
|
361
|
+
ctx.settings.lastErrorResult = { message: "invalid OID" };
|
|
362
|
+
return { status: "error" };
|
|
355
363
|
}
|
|
356
364
|
try {
|
|
357
|
-
await c.query(
|
|
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:
|
|
370
|
+
return { status: "error" };
|
|
363
371
|
}
|
|
364
372
|
writeOut(`lo_unlink ${String(oid)}\n`);
|
|
365
|
-
return { status:
|
|
373
|
+
return { status: "ok" };
|
|
366
374
|
},
|
|
367
375
|
};
|
|
368
376
|
// ---------------------------------------------------------------------------
|