neonctl 2.28.0 → 2.29.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -71
- 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 +34 -34
- 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
|
@@ -41,121 +41,121 @@
|
|
|
41
41
|
* surface the real PG version from a const, but for now we expose the
|
|
42
42
|
* embedded build's version label.
|
|
43
43
|
*/
|
|
44
|
-
import { envConnectionDefaults, libpqConnectionDefaults, looksLikeConnectionString, mergeConnectOptions,
|
|
45
|
-
import { lookupPgPass } from
|
|
46
|
-
import {
|
|
47
|
-
import {
|
|
44
|
+
import { envConnectionDefaults, libpqConnectionDefaults, looksLikeConnectionString, mergeConnectOptions, parseConnectionUriPartial, parseConninfo, serviceEntryToConnectOptions, } from "../index.js";
|
|
45
|
+
import { lookupPgPass } from "../io/pgpass.js";
|
|
46
|
+
import { helpVariables, slashUsage, usage } from "./help.js";
|
|
47
|
+
import { setStartupVars } from "./syncVars.js";
|
|
48
48
|
// ---------------------------------------------------------------------------
|
|
49
49
|
// Internal helpers.
|
|
50
50
|
// ---------------------------------------------------------------------------
|
|
51
51
|
/** Short options that consume the next argv slot (or attached value). */
|
|
52
52
|
const SHORT_WITH_ARG = new Set([
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
53
|
+
"c",
|
|
54
|
+
"d",
|
|
55
|
+
"f",
|
|
56
|
+
"F",
|
|
57
|
+
"h",
|
|
58
|
+
"L",
|
|
59
|
+
"o",
|
|
60
|
+
"p",
|
|
61
|
+
"P",
|
|
62
|
+
"R",
|
|
63
|
+
"T",
|
|
64
|
+
"U",
|
|
65
|
+
"v",
|
|
66
66
|
]);
|
|
67
67
|
/** Short flags (no argument). */
|
|
68
68
|
const SHORT_NO_ARG = new Set([
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
69
|
+
"a",
|
|
70
|
+
"A",
|
|
71
|
+
"b",
|
|
72
|
+
"C",
|
|
73
|
+
"e",
|
|
74
|
+
"E",
|
|
75
|
+
"H",
|
|
76
|
+
"l",
|
|
77
|
+
"n",
|
|
78
|
+
"q",
|
|
79
|
+
"s",
|
|
80
|
+
"S",
|
|
81
|
+
"t",
|
|
82
|
+
"V",
|
|
83
|
+
"w",
|
|
84
|
+
"W",
|
|
85
|
+
"x",
|
|
86
|
+
"X",
|
|
87
|
+
"z",
|
|
88
|
+
"0",
|
|
89
|
+
"1",
|
|
90
|
+
"?",
|
|
91
91
|
]);
|
|
92
92
|
/** Long option → canonical short equivalent (or sentinel string). */
|
|
93
93
|
const LONG_MAP = {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
command:
|
|
97
|
-
dbname:
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
file:
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
host:
|
|
105
|
-
html:
|
|
106
|
-
list:
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
output:
|
|
111
|
-
port:
|
|
112
|
-
pset:
|
|
113
|
-
quiet:
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
username:
|
|
121
|
-
set:
|
|
122
|
-
variable:
|
|
123
|
-
version:
|
|
124
|
-
|
|
125
|
-
password:
|
|
126
|
-
expanded:
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
help:
|
|
131
|
-
csv:
|
|
94
|
+
"echo-all": "a",
|
|
95
|
+
"no-align": "A",
|
|
96
|
+
command: "c",
|
|
97
|
+
dbname: "d",
|
|
98
|
+
"echo-queries": "e",
|
|
99
|
+
"echo-errors": "b",
|
|
100
|
+
"echo-hidden": "E",
|
|
101
|
+
file: "f",
|
|
102
|
+
"field-separator": "F",
|
|
103
|
+
"field-separator-zero": "z",
|
|
104
|
+
host: "h",
|
|
105
|
+
html: "H",
|
|
106
|
+
list: "l",
|
|
107
|
+
"log-file": "L",
|
|
108
|
+
"no-readline": "n",
|
|
109
|
+
"single-transaction": "1",
|
|
110
|
+
output: "o",
|
|
111
|
+
port: "p",
|
|
112
|
+
pset: "P",
|
|
113
|
+
quiet: "q",
|
|
114
|
+
"record-separator": "R",
|
|
115
|
+
"record-separator-zero": "0",
|
|
116
|
+
"single-step": "s",
|
|
117
|
+
"single-line": "S",
|
|
118
|
+
"tuples-only": "t",
|
|
119
|
+
"table-attr": "T",
|
|
120
|
+
username: "U",
|
|
121
|
+
set: "v",
|
|
122
|
+
variable: "v",
|
|
123
|
+
version: "V",
|
|
124
|
+
"no-password": "w",
|
|
125
|
+
password: "W",
|
|
126
|
+
expanded: "x",
|
|
127
|
+
"no-psqlrc": "X",
|
|
128
|
+
"no-pager": "__no_pager__",
|
|
129
|
+
"on-error-stop": "__on_error_stop__",
|
|
130
|
+
help: "__help__",
|
|
131
|
+
csv: "__csv__",
|
|
132
132
|
};
|
|
133
133
|
/** Long options that REQUIRE an attached value (or one in the next argv). */
|
|
134
134
|
const LONG_WITH_ARG = new Set([
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
135
|
+
"command",
|
|
136
|
+
"dbname",
|
|
137
|
+
"file",
|
|
138
|
+
"field-separator",
|
|
139
|
+
"host",
|
|
140
|
+
"log-file",
|
|
141
|
+
"output",
|
|
142
|
+
"port",
|
|
143
|
+
"pset",
|
|
144
|
+
"record-separator",
|
|
145
|
+
"table-attr",
|
|
146
|
+
"username",
|
|
147
|
+
"set",
|
|
148
|
+
"variable",
|
|
149
149
|
]);
|
|
150
150
|
/** Long options whose value is optional (only attached with `=`). */
|
|
151
|
-
const LONG_OPTIONAL_ARG = new Set([
|
|
151
|
+
const LONG_OPTIONAL_ARG = new Set(["help", "echo-hidden"]);
|
|
152
152
|
const blankArgs = () => ({
|
|
153
153
|
actions: [],
|
|
154
154
|
variables: [],
|
|
155
155
|
noPsqlrc: false,
|
|
156
156
|
noReadline: false,
|
|
157
157
|
echoAll: false,
|
|
158
|
-
echoHidden:
|
|
158
|
+
echoHidden: "off",
|
|
159
159
|
echoErrors: false,
|
|
160
160
|
echoQueries: false,
|
|
161
161
|
quiet: false,
|
|
@@ -181,30 +181,32 @@ const renderToString = (fn) => {
|
|
|
181
181
|
const chunks = [];
|
|
182
182
|
const sink = {
|
|
183
183
|
write(chunk) {
|
|
184
|
-
chunks.push(typeof chunk ===
|
|
184
|
+
chunks.push(typeof chunk === "string"
|
|
185
|
+
? chunk
|
|
186
|
+
: Buffer.from(chunk).toString("utf8"));
|
|
185
187
|
return true;
|
|
186
188
|
},
|
|
187
189
|
};
|
|
188
190
|
fn(sink);
|
|
189
|
-
return chunks.join(
|
|
191
|
+
return chunks.join("");
|
|
190
192
|
};
|
|
191
193
|
const renderHelp = (topic) => {
|
|
192
|
-
if (topic === undefined || topic ===
|
|
194
|
+
if (topic === undefined || topic === "options") {
|
|
193
195
|
return renderToString((out) => {
|
|
194
196
|
usage(out);
|
|
195
197
|
});
|
|
196
198
|
}
|
|
197
|
-
if (topic ===
|
|
199
|
+
if (topic === "commands") {
|
|
198
200
|
return renderToString((out) => {
|
|
199
201
|
slashUsage(out, false);
|
|
200
202
|
});
|
|
201
203
|
}
|
|
202
|
-
if (topic ===
|
|
204
|
+
if (topic === "variables") {
|
|
203
205
|
return renderToString((out) => {
|
|
204
206
|
helpVariables(out);
|
|
205
207
|
});
|
|
206
208
|
}
|
|
207
|
-
return
|
|
209
|
+
return "";
|
|
208
210
|
};
|
|
209
211
|
/**
|
|
210
212
|
* Version label for the embedded TypeScript psql. This is the "client"
|
|
@@ -215,7 +217,7 @@ const renderHelp = (topic) => {
|
|
|
215
217
|
* `MAJOR.MINOR.PATCH` string so the numeric mapping stays meaningful. Bump
|
|
216
218
|
* alongside meaningful behaviour changes to the embedded psql.
|
|
217
219
|
*/
|
|
218
|
-
export const CLIENT_VERSION =
|
|
220
|
+
export const CLIENT_VERSION = "1.0.0";
|
|
219
221
|
// `psql --version` / `-V` output. Mirrors upstream's `psql (PostgreSQL)
|
|
220
222
|
// <PG_VERSION>` SHAPE (tools parse the leading `psql (PostgreSQL)`), with an
|
|
221
223
|
// `embedded-ts` label in place of a real PG build number since this is a
|
|
@@ -226,12 +228,12 @@ const pushAction = (acts, a) => {
|
|
|
226
228
|
acts.push(a);
|
|
227
229
|
};
|
|
228
230
|
const pushVariable = (vars, raw) => {
|
|
229
|
-
const eq = raw.indexOf(
|
|
231
|
+
const eq = raw.indexOf("=");
|
|
230
232
|
if (eq < 0) {
|
|
231
233
|
// psql treats `-v NAME` (no value) as "delete this variable". We surface
|
|
232
234
|
// an empty value; the caller decides whether to set or unset. Tests
|
|
233
235
|
// verify both shapes.
|
|
234
|
-
vars.push({ name: raw, value:
|
|
236
|
+
vars.push({ name: raw, value: "" });
|
|
235
237
|
return;
|
|
236
238
|
}
|
|
237
239
|
vars.push({ name: raw.slice(0, eq), value: raw.slice(eq + 1) });
|
|
@@ -262,7 +264,7 @@ const applyDashD = (args, value) => {
|
|
|
262
264
|
// user`) eagerly, and those non-undefined defaults would then land in the
|
|
263
265
|
// top-priority argv layer and override `PGUSER` / `PGDATABASE` (review #7).
|
|
264
266
|
// The partial parser returns only the keys the URI actually specified.
|
|
265
|
-
const parsed = value.startsWith(
|
|
267
|
+
const parsed = value.startsWith("postgresql://") || value.startsWith("postgres://")
|
|
266
268
|
? parseConnectionUriPartial(value)
|
|
267
269
|
: parseConninfo(value);
|
|
268
270
|
// Keep the whole partial (incl. ssl*/channelBinding/hostaddr/requireAuth)
|
|
@@ -303,7 +305,7 @@ export const parseStartupArgs = (argv) => {
|
|
|
303
305
|
const needValue = (flagDisplay) => {
|
|
304
306
|
if (i + 1 >= n) {
|
|
305
307
|
return {
|
|
306
|
-
kind:
|
|
308
|
+
kind: "missing-arg",
|
|
307
309
|
message: `option requires an argument -- ${flagDisplay}`,
|
|
308
310
|
};
|
|
309
311
|
}
|
|
@@ -322,7 +324,7 @@ export const parseStartupArgs = (argv) => {
|
|
|
322
324
|
}
|
|
323
325
|
else {
|
|
324
326
|
const v = needValue(flagDisplay);
|
|
325
|
-
if (typeof v !==
|
|
327
|
+
if (typeof v !== "string")
|
|
326
328
|
return v;
|
|
327
329
|
value = v;
|
|
328
330
|
}
|
|
@@ -333,135 +335,135 @@ export const parseStartupArgs = (argv) => {
|
|
|
333
335
|
// for clusters like `-Xy` where `X` doesn't take an argument — flex
|
|
334
336
|
// continues to `y`; we keep it strict for clarity).
|
|
335
337
|
return {
|
|
336
|
-
kind:
|
|
338
|
+
kind: "invalid-option",
|
|
337
339
|
message: `option does not take an argument -- ${letter}`,
|
|
338
340
|
};
|
|
339
341
|
}
|
|
340
342
|
switch (letter) {
|
|
341
|
-
case
|
|
343
|
+
case "a":
|
|
342
344
|
args.echoAll = true;
|
|
343
345
|
return null;
|
|
344
|
-
case
|
|
346
|
+
case "A":
|
|
345
347
|
args.noAlign = true;
|
|
346
348
|
return null;
|
|
347
|
-
case
|
|
349
|
+
case "b":
|
|
348
350
|
args.echoErrors = true;
|
|
349
351
|
return null;
|
|
350
|
-
case
|
|
352
|
+
case "C":
|
|
351
353
|
// Since-PG17 "skip connection check" — no-op for our use.
|
|
352
354
|
return null;
|
|
353
|
-
case
|
|
354
|
-
pushAction(actions, { kind:
|
|
355
|
+
case "c":
|
|
356
|
+
pushAction(actions, { kind: "command", sql: value });
|
|
355
357
|
return null;
|
|
356
|
-
case
|
|
358
|
+
case "d":
|
|
357
359
|
applyDashD(args, value);
|
|
358
360
|
return null;
|
|
359
|
-
case
|
|
361
|
+
case "e":
|
|
360
362
|
args.echoQueries = true;
|
|
361
363
|
return null;
|
|
362
|
-
case
|
|
363
|
-
args.echoHidden =
|
|
364
|
+
case "E":
|
|
365
|
+
args.echoHidden = "on";
|
|
364
366
|
return null;
|
|
365
|
-
case
|
|
366
|
-
pushAction(actions, { kind:
|
|
367
|
+
case "f":
|
|
368
|
+
pushAction(actions, { kind: "file", path: value });
|
|
367
369
|
return null;
|
|
368
|
-
case
|
|
370
|
+
case "F":
|
|
369
371
|
args.fieldSep = value;
|
|
370
372
|
args.fieldSepZero = false;
|
|
371
373
|
return null;
|
|
372
|
-
case
|
|
374
|
+
case "h":
|
|
373
375
|
args.host = value;
|
|
374
376
|
return null;
|
|
375
|
-
case
|
|
377
|
+
case "H":
|
|
376
378
|
args.htmlMode = true;
|
|
377
379
|
return null;
|
|
378
|
-
case
|
|
380
|
+
case "l":
|
|
379
381
|
args.list = true;
|
|
380
382
|
return null;
|
|
381
|
-
case
|
|
383
|
+
case "L":
|
|
382
384
|
args.log = value;
|
|
383
385
|
return null;
|
|
384
|
-
case
|
|
386
|
+
case "n":
|
|
385
387
|
args.noReadline = true;
|
|
386
388
|
return null;
|
|
387
|
-
case
|
|
389
|
+
case "o":
|
|
388
390
|
args.output = value;
|
|
389
391
|
return null;
|
|
390
|
-
case
|
|
392
|
+
case "p": {
|
|
391
393
|
const p = Number.parseInt(value, 10);
|
|
392
394
|
if (!Number.isFinite(p) || p <= 0 || p > 65535) {
|
|
393
395
|
return {
|
|
394
|
-
kind:
|
|
396
|
+
kind: "invalid-value",
|
|
395
397
|
message: `invalid port number: "${value}"`,
|
|
396
398
|
};
|
|
397
399
|
}
|
|
398
400
|
args.port = p;
|
|
399
401
|
return null;
|
|
400
402
|
}
|
|
401
|
-
case
|
|
403
|
+
case "P":
|
|
402
404
|
pset.push(value);
|
|
403
405
|
return null;
|
|
404
|
-
case
|
|
406
|
+
case "q":
|
|
405
407
|
args.quiet = true;
|
|
406
408
|
return null;
|
|
407
|
-
case
|
|
409
|
+
case "R":
|
|
408
410
|
args.recordSep = value;
|
|
409
411
|
args.recordSepZero = false;
|
|
410
412
|
return null;
|
|
411
|
-
case
|
|
413
|
+
case "s":
|
|
412
414
|
args.singlestep = true;
|
|
413
415
|
return null;
|
|
414
|
-
case
|
|
416
|
+
case "S":
|
|
415
417
|
args.singleline = true;
|
|
416
418
|
return null;
|
|
417
|
-
case
|
|
419
|
+
case "t":
|
|
418
420
|
args.tuplesOnly = true;
|
|
419
421
|
return null;
|
|
420
|
-
case
|
|
422
|
+
case "T":
|
|
421
423
|
// -T TEXT → push a synthetic pset directive so it routes through
|
|
422
424
|
// the same `\pset tableattr` plumbing.
|
|
423
425
|
pset.push(`tableattr=${value}`);
|
|
424
426
|
return null;
|
|
425
|
-
case
|
|
427
|
+
case "U":
|
|
426
428
|
args.user = value;
|
|
427
429
|
return null;
|
|
428
|
-
case
|
|
430
|
+
case "v":
|
|
429
431
|
pushVariable(variables, value);
|
|
430
432
|
return null;
|
|
431
|
-
case
|
|
433
|
+
case "V":
|
|
432
434
|
return {
|
|
433
|
-
kind:
|
|
435
|
+
kind: "version",
|
|
434
436
|
message: VERSION_STRING,
|
|
435
437
|
};
|
|
436
|
-
case
|
|
438
|
+
case "w":
|
|
437
439
|
args.promptPassword = false;
|
|
438
440
|
return null;
|
|
439
|
-
case
|
|
441
|
+
case "W":
|
|
440
442
|
args.promptPassword = true;
|
|
441
443
|
return null;
|
|
442
|
-
case
|
|
444
|
+
case "x":
|
|
443
445
|
args.expanded = true;
|
|
444
446
|
return null;
|
|
445
|
-
case
|
|
447
|
+
case "X":
|
|
446
448
|
args.noPsqlrc = true;
|
|
447
449
|
return null;
|
|
448
|
-
case
|
|
450
|
+
case "z":
|
|
449
451
|
args.fieldSepZero = true;
|
|
450
452
|
return null;
|
|
451
|
-
case
|
|
453
|
+
case "0":
|
|
452
454
|
args.recordSepZero = true;
|
|
453
455
|
return null;
|
|
454
|
-
case
|
|
456
|
+
case "1":
|
|
455
457
|
args.singleTransaction = true;
|
|
456
458
|
return null;
|
|
457
|
-
case
|
|
459
|
+
case "?":
|
|
458
460
|
return {
|
|
459
|
-
kind:
|
|
461
|
+
kind: "help",
|
|
460
462
|
message: renderHelp(undefined),
|
|
461
463
|
};
|
|
462
464
|
default:
|
|
463
465
|
return {
|
|
464
|
-
kind:
|
|
466
|
+
kind: "invalid-option",
|
|
465
467
|
message: `invalid option -- ${letter}`,
|
|
466
468
|
};
|
|
467
469
|
}
|
|
@@ -469,7 +471,7 @@ export const parseStartupArgs = (argv) => {
|
|
|
469
471
|
// ---- Main loop. -------------------------------------------------------
|
|
470
472
|
while (i < n) {
|
|
471
473
|
const tok = argv[i];
|
|
472
|
-
if (tok ===
|
|
474
|
+
if (tok === "--") {
|
|
473
475
|
// End of options. Everything after is positional.
|
|
474
476
|
i += 1;
|
|
475
477
|
while (i < n) {
|
|
@@ -478,16 +480,16 @@ export const parseStartupArgs = (argv) => {
|
|
|
478
480
|
}
|
|
479
481
|
break;
|
|
480
482
|
}
|
|
481
|
-
if (tok.startsWith(
|
|
483
|
+
if (tok.startsWith("--")) {
|
|
482
484
|
// Long option: `--name` or `--name=value`.
|
|
483
|
-
const eq = tok.indexOf(
|
|
485
|
+
const eq = tok.indexOf("=");
|
|
484
486
|
const name = eq < 0 ? tok.slice(2) : tok.slice(2, eq);
|
|
485
487
|
const attached = eq < 0 ? undefined : tok.slice(eq + 1);
|
|
486
488
|
// Special-case the long-only synthetic options first.
|
|
487
|
-
if (name ===
|
|
489
|
+
if (name === "csv") {
|
|
488
490
|
if (attached !== undefined) {
|
|
489
491
|
return {
|
|
490
|
-
kind:
|
|
492
|
+
kind: "invalid-option",
|
|
491
493
|
message: `option does not take an argument: --${name}`,
|
|
492
494
|
};
|
|
493
495
|
}
|
|
@@ -495,10 +497,10 @@ export const parseStartupArgs = (argv) => {
|
|
|
495
497
|
i += 1;
|
|
496
498
|
continue;
|
|
497
499
|
}
|
|
498
|
-
if (name ===
|
|
500
|
+
if (name === "no-pager") {
|
|
499
501
|
if (attached !== undefined) {
|
|
500
502
|
return {
|
|
501
|
-
kind:
|
|
503
|
+
kind: "invalid-option",
|
|
502
504
|
message: `option does not take an argument: --${name}`,
|
|
503
505
|
};
|
|
504
506
|
}
|
|
@@ -506,44 +508,44 @@ export const parseStartupArgs = (argv) => {
|
|
|
506
508
|
i += 1;
|
|
507
509
|
continue;
|
|
508
510
|
}
|
|
509
|
-
if (name ===
|
|
511
|
+
if (name === "on-error-stop") {
|
|
510
512
|
if (attached !== undefined) {
|
|
511
513
|
return {
|
|
512
|
-
kind:
|
|
514
|
+
kind: "invalid-option",
|
|
513
515
|
message: `option does not take an argument: --${name}`,
|
|
514
516
|
};
|
|
515
517
|
}
|
|
516
518
|
args.onErrorStop = true;
|
|
517
|
-
variables.push({ name:
|
|
519
|
+
variables.push({ name: "ON_ERROR_STOP", value: "on" });
|
|
518
520
|
i += 1;
|
|
519
521
|
continue;
|
|
520
522
|
}
|
|
521
|
-
if (name ===
|
|
523
|
+
if (name === "help") {
|
|
522
524
|
const topic = attached;
|
|
523
525
|
if (topic !== undefined &&
|
|
524
|
-
topic !==
|
|
525
|
-
topic !==
|
|
526
|
-
topic !==
|
|
526
|
+
topic !== "options" &&
|
|
527
|
+
topic !== "commands" &&
|
|
528
|
+
topic !== "variables") {
|
|
527
529
|
return {
|
|
528
|
-
kind:
|
|
530
|
+
kind: "invalid-option",
|
|
529
531
|
message: `unrecognized help topic: ${topic}`,
|
|
530
532
|
};
|
|
531
533
|
}
|
|
532
|
-
return { kind:
|
|
534
|
+
return { kind: "help", message: renderHelp(topic) };
|
|
533
535
|
}
|
|
534
|
-
if (name ===
|
|
536
|
+
if (name === "echo-hidden") {
|
|
535
537
|
if (attached === undefined) {
|
|
536
|
-
args.echoHidden =
|
|
538
|
+
args.echoHidden = "on";
|
|
537
539
|
}
|
|
538
|
-
else if (attached ===
|
|
539
|
-
args.echoHidden =
|
|
540
|
+
else if (attached === "noexec") {
|
|
541
|
+
args.echoHidden = "noexec";
|
|
540
542
|
}
|
|
541
|
-
else if (attached ===
|
|
542
|
-
args.echoHidden =
|
|
543
|
+
else if (attached === "" || attached === "on") {
|
|
544
|
+
args.echoHidden = "on";
|
|
543
545
|
}
|
|
544
546
|
else {
|
|
545
547
|
return {
|
|
546
|
-
kind:
|
|
548
|
+
kind: "invalid-value",
|
|
547
549
|
message: `invalid value for --echo-hidden: "${attached}"`,
|
|
548
550
|
};
|
|
549
551
|
}
|
|
@@ -553,7 +555,7 @@ export const parseStartupArgs = (argv) => {
|
|
|
553
555
|
const short = LONG_MAP[name];
|
|
554
556
|
if (short === undefined) {
|
|
555
557
|
return {
|
|
556
|
-
kind:
|
|
558
|
+
kind: "invalid-option",
|
|
557
559
|
message: `unrecognized option: --${name}`,
|
|
558
560
|
};
|
|
559
561
|
}
|
|
@@ -563,7 +565,7 @@ export const parseStartupArgs = (argv) => {
|
|
|
563
565
|
if (requiresArg && value === undefined) {
|
|
564
566
|
if (i + 1 >= n) {
|
|
565
567
|
return {
|
|
566
|
-
kind:
|
|
568
|
+
kind: "missing-arg",
|
|
567
569
|
message: `option requires an argument: --${name}`,
|
|
568
570
|
};
|
|
569
571
|
}
|
|
@@ -572,7 +574,7 @@ export const parseStartupArgs = (argv) => {
|
|
|
572
574
|
}
|
|
573
575
|
else if (!requiresArg && !optionalArg && value !== undefined) {
|
|
574
576
|
return {
|
|
575
|
-
kind:
|
|
577
|
+
kind: "invalid-option",
|
|
576
578
|
message: `option does not take an argument: --${name}`,
|
|
577
579
|
};
|
|
578
580
|
}
|
|
@@ -582,7 +584,7 @@ export const parseStartupArgs = (argv) => {
|
|
|
582
584
|
i += 1;
|
|
583
585
|
continue;
|
|
584
586
|
}
|
|
585
|
-
if (tok.startsWith(
|
|
587
|
+
if (tok.startsWith("-") && tok.length > 1) {
|
|
586
588
|
// Short option cluster. Each char might consume the rest of the token
|
|
587
589
|
// (or the next argv) as its value.
|
|
588
590
|
let k = 1;
|
|
@@ -590,7 +592,7 @@ export const parseStartupArgs = (argv) => {
|
|
|
590
592
|
const letter = tok[k];
|
|
591
593
|
if (!SHORT_WITH_ARG.has(letter) && !SHORT_NO_ARG.has(letter)) {
|
|
592
594
|
return {
|
|
593
|
-
kind:
|
|
595
|
+
kind: "invalid-option",
|
|
594
596
|
message: `invalid option -- ${letter}`,
|
|
595
597
|
};
|
|
596
598
|
}
|
|
@@ -635,7 +637,7 @@ export const applyStartupArgs = (args, settings, baseConnectOpts, resolution) =>
|
|
|
635
637
|
setStartupVars(settings.vars, CLIENT_VERSION);
|
|
636
638
|
// -------- 1) Variable assignments. -------------------------------------
|
|
637
639
|
for (const v of args.variables) {
|
|
638
|
-
if (v.value ===
|
|
640
|
+
if (v.value === "") {
|
|
639
641
|
// Mirror upstream `-v NAME` (no `=`): DeleteVariable.
|
|
640
642
|
settings.vars.unset(v.name);
|
|
641
643
|
}
|
|
@@ -645,61 +647,61 @@ export const applyStartupArgs = (args, settings, baseConnectOpts, resolution) =>
|
|
|
645
647
|
}
|
|
646
648
|
// -------- 2) Settings flags. -------------------------------------------
|
|
647
649
|
if (args.echoAll)
|
|
648
|
-
settings.vars.set(
|
|
650
|
+
settings.vars.set("ECHO", "all");
|
|
649
651
|
if (args.echoErrors)
|
|
650
|
-
settings.vars.set(
|
|
652
|
+
settings.vars.set("ECHO", "errors");
|
|
651
653
|
if (args.echoQueries)
|
|
652
|
-
settings.vars.set(
|
|
653
|
-
if (args.echoHidden !==
|
|
654
|
+
settings.vars.set("ECHO", "queries");
|
|
655
|
+
if (args.echoHidden !== "off") {
|
|
654
656
|
settings.echoHidden = args.echoHidden;
|
|
655
|
-
settings.vars.set(
|
|
657
|
+
settings.vars.set("ECHO_HIDDEN", args.echoHidden === "noexec" ? "noexec" : "on");
|
|
656
658
|
}
|
|
657
659
|
if (args.quiet) {
|
|
658
660
|
settings.quiet = true;
|
|
659
|
-
settings.vars.set(
|
|
661
|
+
settings.vars.set("QUIET", "on");
|
|
660
662
|
}
|
|
661
663
|
if (args.singleline) {
|
|
662
664
|
settings.singleline = true;
|
|
663
|
-
settings.vars.set(
|
|
665
|
+
settings.vars.set("SINGLELINE", "on");
|
|
664
666
|
}
|
|
665
667
|
if (args.singlestep) {
|
|
666
668
|
settings.singlestep = true;
|
|
667
|
-
settings.vars.set(
|
|
669
|
+
settings.vars.set("SINGLESTEP", "on");
|
|
668
670
|
}
|
|
669
671
|
if (args.onErrorStop) {
|
|
670
672
|
settings.onErrorStop = true;
|
|
671
|
-
settings.vars.set(
|
|
673
|
+
settings.vars.set("ON_ERROR_STOP", "on");
|
|
672
674
|
}
|
|
673
675
|
// -------- 3) Output formatting. ----------------------------------------
|
|
674
676
|
if (args.noAlign) {
|
|
675
|
-
settings.popt.topt.format =
|
|
677
|
+
settings.popt.topt.format = "unaligned";
|
|
676
678
|
}
|
|
677
679
|
if (args.htmlMode) {
|
|
678
|
-
settings.popt.topt.format =
|
|
680
|
+
settings.popt.topt.format = "html";
|
|
679
681
|
}
|
|
680
682
|
if (args.csvOutput) {
|
|
681
|
-
settings.popt.topt.format =
|
|
683
|
+
settings.popt.topt.format = "csv";
|
|
682
684
|
}
|
|
683
685
|
if (args.tuplesOnly) {
|
|
684
686
|
settings.popt.topt.tuplesOnly = true;
|
|
685
687
|
}
|
|
686
688
|
if (args.expanded) {
|
|
687
|
-
settings.popt.topt.expanded =
|
|
689
|
+
settings.popt.topt.expanded = "on";
|
|
688
690
|
}
|
|
689
691
|
if (args.fieldSepZero) {
|
|
690
|
-
settings.popt.topt.fieldSep =
|
|
692
|
+
settings.popt.topt.fieldSep = "\0";
|
|
691
693
|
}
|
|
692
694
|
else if (args.fieldSep !== undefined) {
|
|
693
695
|
settings.popt.topt.fieldSep = args.fieldSep;
|
|
694
696
|
}
|
|
695
697
|
if (args.recordSepZero) {
|
|
696
|
-
settings.popt.topt.recordSep =
|
|
698
|
+
settings.popt.topt.recordSep = "\0";
|
|
697
699
|
}
|
|
698
700
|
else if (args.recordSep !== undefined) {
|
|
699
701
|
settings.popt.topt.recordSep = args.recordSep;
|
|
700
702
|
}
|
|
701
703
|
if (args.noPager) {
|
|
702
|
-
settings.popt.topt.pager =
|
|
704
|
+
settings.popt.topt.pager = "off";
|
|
703
705
|
}
|
|
704
706
|
// -------- 4) pset directives. ------------------------------------------
|
|
705
707
|
// We don't have a parsed `do_pset` here yet (lives in command/cmd_format),
|
|
@@ -707,15 +709,15 @@ export const applyStartupArgs = (args, settings, baseConnectOpts, resolution) =>
|
|
|
707
709
|
// them through once parsed. For tableattr (the most common -T use), apply
|
|
708
710
|
// directly.
|
|
709
711
|
for (const directive of args.pset) {
|
|
710
|
-
const eq = directive.indexOf(
|
|
712
|
+
const eq = directive.indexOf("=");
|
|
711
713
|
if (eq >= 0) {
|
|
712
714
|
const key = directive.slice(0, eq);
|
|
713
715
|
const val = directive.slice(eq + 1);
|
|
714
|
-
if (key ===
|
|
716
|
+
if (key === "tableattr" || key === "T") {
|
|
715
717
|
settings.popt.topt.tableAttr = val.length > 0 ? val : null;
|
|
716
718
|
}
|
|
717
|
-
else if (key ===
|
|
718
|
-
if (val ===
|
|
719
|
+
else if (key === "pager") {
|
|
720
|
+
if (val === "on" || val === "off" || val === "always") {
|
|
719
721
|
settings.popt.topt.pager = val;
|
|
720
722
|
}
|
|
721
723
|
}
|
|
@@ -757,11 +759,11 @@ export const applyStartupArgs = (args, settings, baseConnectOpts, resolution) =>
|
|
|
757
759
|
let connect;
|
|
758
760
|
if (resolution === undefined) {
|
|
759
761
|
const base = baseConnectOpts ?? {
|
|
760
|
-
host:
|
|
762
|
+
host: "localhost",
|
|
761
763
|
port: 5432,
|
|
762
|
-
user:
|
|
763
|
-
database:
|
|
764
|
-
ssl:
|
|
764
|
+
user: "",
|
|
765
|
+
database: "",
|
|
766
|
+
ssl: "prefer",
|
|
765
767
|
};
|
|
766
768
|
connect = { ...base, ...argvLayer };
|
|
767
769
|
}
|
|
@@ -783,14 +785,16 @@ export const applyStartupArgs = (args, settings, baseConnectOpts, resolution) =>
|
|
|
783
785
|
const resolveLayeredConnect = (argvLayer, resolution, legacyBase) => {
|
|
784
786
|
const env = resolution.env ?? {};
|
|
785
787
|
const uriPartial = resolution.uriPartial ??
|
|
786
|
-
(legacyBase !== undefined
|
|
788
|
+
(legacyBase !== undefined
|
|
789
|
+
? legacyBase
|
|
790
|
+
: {});
|
|
787
791
|
// Pick the service entry: explicit `serviceName` argument first, else fall
|
|
788
792
|
// back to `$PGSERVICE`. The URI parser threads `?service=` through to its
|
|
789
793
|
// caller via this same field, so callers should populate `serviceName`
|
|
790
794
|
// from there before invoking us.
|
|
791
795
|
const serviceName = resolution.serviceName ?? env.PGSERVICE;
|
|
792
796
|
let serviceEntry;
|
|
793
|
-
if (serviceName !== undefined && serviceName !==
|
|
797
|
+
if (serviceName !== undefined && serviceName !== "") {
|
|
794
798
|
serviceEntry = resolution.services?.get(serviceName);
|
|
795
799
|
if (serviceEntry === undefined) {
|
|
796
800
|
// Mirror libpq: if the user explicitly named a service (via
|
|
@@ -822,13 +826,15 @@ const resolveLayeredConnect = (argvLayer, resolution, legacyBase) => {
|
|
|
822
826
|
const pgpassPwd = lookupPgPass(resolution.pgpassEntries ?? [], {
|
|
823
827
|
host: merged.host,
|
|
824
828
|
port: merged.port,
|
|
825
|
-
database: merged.database !==
|
|
829
|
+
database: merged.database !== "" ? merged.database : merged.user,
|
|
826
830
|
user: merged.user,
|
|
827
831
|
});
|
|
828
832
|
if (pgpassPwd !== undefined) {
|
|
829
833
|
// Re-merge with pgpass slotted in just above libpq defaults so any
|
|
830
834
|
// explicit `password=` in env / service still wins.
|
|
831
|
-
const pgpassLayer = {
|
|
835
|
+
const pgpassLayer = {
|
|
836
|
+
password: pgpassPwd,
|
|
837
|
+
};
|
|
832
838
|
merged = mergeConnectOptions([...layers, pgpassLayer], defaults);
|
|
833
839
|
}
|
|
834
840
|
}
|