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.
- package/README.md +35 -3
- package/dist/analytics.js +52 -34
- package/dist/api.js +643 -13
- package/dist/auth.js +50 -44
- package/dist/cli.js +8 -1
- package/dist/commands/auth.js +64 -51
- package/dist/commands/bootstrap.js +115 -157
- package/dist/commands/branches.js +160 -150
- package/dist/commands/bucket.js +183 -146
- package/dist/commands/checkout.js +51 -51
- package/dist/commands/config.js +228 -82
- package/dist/commands/connection_string.js +62 -62
- package/dist/commands/data_api.js +100 -101
- package/dist/commands/databases.js +29 -26
- 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 +101 -104
- package/dist/commands/index.js +27 -25
- package/dist/commands/init.js +23 -22
- package/dist/commands/ip_allow.js +29 -29
- package/dist/commands/link.js +232 -182
- package/dist/commands/neon_auth.js +385 -370
- package/dist/commands/operations.js +11 -11
- package/dist/commands/orgs.js +8 -8
- package/dist/commands/projects.js +103 -101
- package/dist/commands/psql.js +31 -31
- package/dist/commands/roles.js +27 -24
- package/dist/commands/schema_diff.js +25 -26
- package/dist/commands/set_context.js +17 -17
- package/dist/commands/status.js +40 -0
- 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 +37 -14
- package/dist/current_branch_fast_path.js +55 -0
- 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 +68 -5
- package/dist/functions_api.js +10 -10
- package/dist/help.js +15 -15
- package/dist/index.js +110 -107
- package/dist/log.js +2 -2
- package/dist/parameters.gen.js +14 -14
- 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 +22 -23
- package/dist/test_utils/fixtures.js +74 -41
- package/dist/test_utils/oauth_server.js +5 -5
- package/dist/utils/api_enums.js +33 -0
- 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 +28 -16
- 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 +10 -12
package/dist/psql/print/latex.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { formatNumericLocale } from
|
|
1
|
+
import { formatNumericLocale } from "./units.js";
|
|
2
2
|
/**
|
|
3
3
|
* LaTeX printers — `latex` (tabular) and `latex-longtable` (longtable).
|
|
4
4
|
*
|
|
@@ -32,10 +32,10 @@ import { formatNumericLocale } from './units.js';
|
|
|
32
32
|
// INT2, INT4, INT8, FLOAT4, FLOAT8, NUMERIC, INTERVAL.
|
|
33
33
|
const NUMERIC_OIDS = new Set([21, 23, 20, 700, 701, 1700, 1186]);
|
|
34
34
|
export const latexPrinter = {
|
|
35
|
-
format:
|
|
35
|
+
format: "latex",
|
|
36
36
|
printQuery(rs, opts, out) {
|
|
37
37
|
const topt = opts.topt;
|
|
38
|
-
if (topt.expanded ===
|
|
38
|
+
if (topt.expanded === "on") {
|
|
39
39
|
return printLatexVertical(rs, opts, out);
|
|
40
40
|
}
|
|
41
41
|
return printLatexFlat(rs, opts, out);
|
|
@@ -47,67 +47,67 @@ const printLatexFlat = (rs, opts, out) => {
|
|
|
47
47
|
const startTable = topt.startTable;
|
|
48
48
|
const stopTable = topt.stopTable;
|
|
49
49
|
const border = clampBorder(topt.border, 3);
|
|
50
|
-
const nullPrint = opts.nullPrint !==
|
|
50
|
+
const nullPrint = opts.nullPrint !== "" ? opts.nullPrint : topt.nullPrint;
|
|
51
51
|
const title = opts.title ?? topt.title;
|
|
52
52
|
const footers = opts.footers ?? topt.footers;
|
|
53
53
|
const headers = rs.fields.map((f) => f.name);
|
|
54
54
|
const ncols = rs.fields.length;
|
|
55
|
-
const aligns = rs.fields.map((f) => NUMERIC_OIDS.has(f.dataTypeID) ?
|
|
55
|
+
const aligns = rs.fields.map((f) => NUMERIC_OIDS.has(f.dataTypeID) ? "r" : "l");
|
|
56
56
|
const cells = rs.rows.map((row) => row.map((cell) => renderCell(cell, nullPrint, topt.numericLocale)));
|
|
57
|
-
let buf =
|
|
57
|
+
let buf = "";
|
|
58
58
|
if (startTable) {
|
|
59
59
|
if (!tuplesOnly && title) {
|
|
60
|
-
buf +=
|
|
60
|
+
buf += "\\begin{center}\n";
|
|
61
61
|
buf += escapeLatex(title);
|
|
62
|
-
buf +=
|
|
62
|
+
buf += "\n\\end{center}\n\n";
|
|
63
63
|
}
|
|
64
|
-
buf +=
|
|
64
|
+
buf += "\\begin{tabular}{";
|
|
65
65
|
if (border >= 2)
|
|
66
|
-
buf +=
|
|
66
|
+
buf += "| ";
|
|
67
67
|
aligns.forEach((a, idx) => {
|
|
68
68
|
buf += a;
|
|
69
69
|
if (border !== 0 && idx < ncols - 1)
|
|
70
|
-
buf +=
|
|
70
|
+
buf += " | ";
|
|
71
71
|
});
|
|
72
72
|
if (border >= 2)
|
|
73
|
-
buf +=
|
|
74
|
-
buf +=
|
|
73
|
+
buf += " |";
|
|
74
|
+
buf += "}\n";
|
|
75
75
|
if (!tuplesOnly && border >= 2)
|
|
76
|
-
buf +=
|
|
76
|
+
buf += "\\hline\n";
|
|
77
77
|
if (!tuplesOnly) {
|
|
78
78
|
headers.forEach((h, idx) => {
|
|
79
79
|
if (idx !== 0)
|
|
80
|
-
buf +=
|
|
81
|
-
buf +=
|
|
80
|
+
buf += " & ";
|
|
81
|
+
buf += "\\textit{" + escapeLatex(h) + "}";
|
|
82
82
|
});
|
|
83
|
-
buf +=
|
|
84
|
-
buf +=
|
|
83
|
+
buf += " \\\\\n";
|
|
84
|
+
buf += "\\hline\n";
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
cells.forEach((row) => {
|
|
88
88
|
row.forEach((value, idx) => {
|
|
89
89
|
buf += escapeLatex(value);
|
|
90
90
|
if (idx === ncols - 1) {
|
|
91
|
-
buf +=
|
|
91
|
+
buf += " \\\\\n";
|
|
92
92
|
if (border === 3)
|
|
93
|
-
buf +=
|
|
93
|
+
buf += "\\hline\n";
|
|
94
94
|
}
|
|
95
95
|
else {
|
|
96
|
-
buf +=
|
|
96
|
+
buf += " & ";
|
|
97
97
|
}
|
|
98
98
|
});
|
|
99
99
|
});
|
|
100
100
|
if (stopTable) {
|
|
101
101
|
if (border === 2)
|
|
102
|
-
buf +=
|
|
103
|
-
buf +=
|
|
102
|
+
buf += "\\hline\n";
|
|
103
|
+
buf += "\\end{tabular}\n\n\\noindent ";
|
|
104
104
|
if (!tuplesOnly) {
|
|
105
105
|
const effective = effectiveFooters(rs, topt, footers);
|
|
106
106
|
for (const f of effective) {
|
|
107
|
-
buf += escapeLatex(f) +
|
|
107
|
+
buf += escapeLatex(f) + " \\\\\n";
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
|
-
buf +=
|
|
110
|
+
buf += "\n";
|
|
111
111
|
}
|
|
112
112
|
out.write(buf);
|
|
113
113
|
return Promise.resolve();
|
|
@@ -118,32 +118,32 @@ const printLatexVertical = (rs, opts, out) => {
|
|
|
118
118
|
const startTable = topt.startTable;
|
|
119
119
|
const stopTable = topt.stopTable;
|
|
120
120
|
const border = clampBorder(topt.border, 2);
|
|
121
|
-
const nullPrint = opts.nullPrint !==
|
|
121
|
+
const nullPrint = opts.nullPrint !== "" ? opts.nullPrint : topt.nullPrint;
|
|
122
122
|
const title = opts.title ?? topt.title;
|
|
123
123
|
const footers = opts.footers ?? topt.footers;
|
|
124
124
|
const headers = rs.fields.map((f) => f.name);
|
|
125
125
|
const cells = rs.rows.map((row) => row.map((cell) => renderCell(cell, nullPrint, topt.numericLocale)));
|
|
126
|
-
let buf =
|
|
126
|
+
let buf = "";
|
|
127
127
|
if (startTable) {
|
|
128
128
|
if (!tuplesOnly && title) {
|
|
129
|
-
buf +=
|
|
129
|
+
buf += "\\begin{center}\n";
|
|
130
130
|
buf += escapeLatex(title);
|
|
131
|
-
buf +=
|
|
131
|
+
buf += "\n\\end{center}\n\n";
|
|
132
132
|
}
|
|
133
|
-
buf +=
|
|
133
|
+
buf += "\\begin{tabular}{";
|
|
134
134
|
if (border === 0)
|
|
135
|
-
buf +=
|
|
135
|
+
buf += "cl";
|
|
136
136
|
else if (border === 1)
|
|
137
|
-
buf +=
|
|
137
|
+
buf += "c|l";
|
|
138
138
|
else
|
|
139
|
-
buf +=
|
|
140
|
-
buf +=
|
|
139
|
+
buf += "|c|l|";
|
|
140
|
+
buf += "}\n";
|
|
141
141
|
}
|
|
142
142
|
let record = topt.prior + 1;
|
|
143
143
|
cells.forEach((row) => {
|
|
144
144
|
if (!tuplesOnly) {
|
|
145
145
|
if (border === 2) {
|
|
146
|
-
buf +=
|
|
146
|
+
buf += "\\hline\n";
|
|
147
147
|
buf += `\\multicolumn{2}{|c|}{\\textit{Record ${String(record)}}} \\\\\n`;
|
|
148
148
|
}
|
|
149
149
|
else {
|
|
@@ -152,36 +152,36 @@ const printLatexVertical = (rs, opts, out) => {
|
|
|
152
152
|
record += 1;
|
|
153
153
|
}
|
|
154
154
|
if (border >= 1)
|
|
155
|
-
buf +=
|
|
155
|
+
buf += "\\hline\n";
|
|
156
156
|
row.forEach((value, idx) => {
|
|
157
157
|
buf += escapeLatex(headers[idx]);
|
|
158
|
-
buf +=
|
|
158
|
+
buf += " & ";
|
|
159
159
|
buf += escapeLatex(value);
|
|
160
|
-
buf +=
|
|
160
|
+
buf += " \\\\\n";
|
|
161
161
|
});
|
|
162
162
|
});
|
|
163
163
|
if (stopTable) {
|
|
164
164
|
if (border === 2)
|
|
165
|
-
buf +=
|
|
166
|
-
buf +=
|
|
165
|
+
buf += "\\hline\n";
|
|
166
|
+
buf += "\\end{tabular}\n\n\\noindent ";
|
|
167
167
|
// Expanded mode does NOT include the default "(N rows)" footer;
|
|
168
168
|
// only user-supplied footers (matches print_latex_vertical).
|
|
169
169
|
if (!tuplesOnly && footers && footers.length > 0) {
|
|
170
170
|
for (const f of footers) {
|
|
171
|
-
buf += escapeLatex(f) +
|
|
171
|
+
buf += escapeLatex(f) + " \\\\\n";
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
|
-
buf +=
|
|
174
|
+
buf += "\n";
|
|
175
175
|
}
|
|
176
176
|
out.write(buf);
|
|
177
177
|
return Promise.resolve();
|
|
178
178
|
};
|
|
179
179
|
export const latexLongtablePrinter = {
|
|
180
|
-
format:
|
|
180
|
+
format: "latex-longtable",
|
|
181
181
|
printQuery(rs, opts, out) {
|
|
182
182
|
// Upstream dispatch sends both `latex` and `latex-longtable` to
|
|
183
183
|
// `print_latex_vertical` when expanded is on (cf. print.c).
|
|
184
|
-
if (opts.topt.expanded ===
|
|
184
|
+
if (opts.topt.expanded === "on") {
|
|
185
185
|
return printLatexVertical(rs, opts, out);
|
|
186
186
|
}
|
|
187
187
|
const topt = opts.topt;
|
|
@@ -189,27 +189,27 @@ export const latexLongtablePrinter = {
|
|
|
189
189
|
const startTable = topt.startTable;
|
|
190
190
|
const stopTable = topt.stopTable;
|
|
191
191
|
const border = clampBorder(topt.border, 3);
|
|
192
|
-
const nullPrint = opts.nullPrint !==
|
|
192
|
+
const nullPrint = opts.nullPrint !== "" ? opts.nullPrint : topt.nullPrint;
|
|
193
193
|
const title = opts.title ?? topt.title;
|
|
194
194
|
const headers = rs.fields.map((f) => f.name);
|
|
195
195
|
const ncols = rs.fields.length;
|
|
196
|
-
const aligns = rs.fields.map((f) => NUMERIC_OIDS.has(f.dataTypeID) ?
|
|
196
|
+
const aligns = rs.fields.map((f) => NUMERIC_OIDS.has(f.dataTypeID) ? "r" : "l");
|
|
197
197
|
const cells = rs.rows.map((row) => row.map((cell) => renderCell(cell, nullPrint, topt.numericLocale)));
|
|
198
198
|
// `topt.tableAttr` for longtable encodes per-column widths in a
|
|
199
199
|
// whitespace-separated list, consumed left-to-right with a fall
|
|
200
200
|
// back to the previous value once exhausted.
|
|
201
|
-
const widths = (topt.tableAttr ??
|
|
201
|
+
const widths = (topt.tableAttr ?? "")
|
|
202
202
|
.split(/[\s]+/)
|
|
203
|
-
.filter((w) => w !==
|
|
203
|
+
.filter((w) => w !== "");
|
|
204
204
|
let widthCursor = 0;
|
|
205
205
|
let lastWidth = null;
|
|
206
|
-
let buf =
|
|
206
|
+
let buf = "";
|
|
207
207
|
if (startTable) {
|
|
208
|
-
buf +=
|
|
208
|
+
buf += "\\begin{longtable}{";
|
|
209
209
|
if (border >= 2)
|
|
210
|
-
buf +=
|
|
210
|
+
buf += "| ";
|
|
211
211
|
aligns.forEach((a, idx) => {
|
|
212
|
-
if (a ===
|
|
212
|
+
if (a === "l" && widths.length > 0) {
|
|
213
213
|
let w = null;
|
|
214
214
|
if (widthCursor < widths.length) {
|
|
215
215
|
w = widths[widthCursor];
|
|
@@ -223,62 +223,62 @@ export const latexLongtablePrinter = {
|
|
|
223
223
|
buf += `p{${w}\\textwidth}`;
|
|
224
224
|
}
|
|
225
225
|
else {
|
|
226
|
-
buf +=
|
|
226
|
+
buf += "l";
|
|
227
227
|
}
|
|
228
228
|
}
|
|
229
229
|
else {
|
|
230
230
|
buf += a;
|
|
231
231
|
}
|
|
232
232
|
if (border !== 0 && idx < ncols - 1)
|
|
233
|
-
buf +=
|
|
233
|
+
buf += " | ";
|
|
234
234
|
});
|
|
235
235
|
if (border >= 2)
|
|
236
|
-
buf +=
|
|
237
|
-
buf +=
|
|
236
|
+
buf += " |";
|
|
237
|
+
buf += "}\n";
|
|
238
238
|
if (!tuplesOnly) {
|
|
239
239
|
// firsthead
|
|
240
240
|
if (border >= 2)
|
|
241
|
-
buf +=
|
|
241
|
+
buf += "\\toprule\n";
|
|
242
242
|
headers.forEach((h, idx) => {
|
|
243
243
|
if (idx !== 0)
|
|
244
|
-
buf +=
|
|
245
|
-
buf +=
|
|
244
|
+
buf += " & ";
|
|
245
|
+
buf += "\\small\\textbf{\\textit{" + escapeLatex(h) + "}}";
|
|
246
246
|
});
|
|
247
|
-
buf +=
|
|
248
|
-
buf +=
|
|
247
|
+
buf += " \\\\\n";
|
|
248
|
+
buf += "\\midrule\n\\endfirsthead\n";
|
|
249
249
|
// continuation heads
|
|
250
250
|
if (border >= 2)
|
|
251
|
-
buf +=
|
|
251
|
+
buf += "\\toprule\n";
|
|
252
252
|
headers.forEach((h, idx) => {
|
|
253
253
|
if (idx !== 0)
|
|
254
|
-
buf +=
|
|
255
|
-
buf +=
|
|
254
|
+
buf += " & ";
|
|
255
|
+
buf += "\\small\\textbf{\\textit{" + escapeLatex(h) + "}}";
|
|
256
256
|
});
|
|
257
|
-
buf +=
|
|
257
|
+
buf += " \\\\\n";
|
|
258
258
|
if (border !== 3)
|
|
259
|
-
buf +=
|
|
260
|
-
buf +=
|
|
259
|
+
buf += "\\midrule\n";
|
|
260
|
+
buf += "\\endhead\n";
|
|
261
261
|
if (title) {
|
|
262
262
|
if (border === 2)
|
|
263
|
-
buf +=
|
|
263
|
+
buf += "\\bottomrule\n";
|
|
264
264
|
buf +=
|
|
265
|
-
|
|
265
|
+
"\\caption[" +
|
|
266
266
|
escapeLatex(title) +
|
|
267
|
-
|
|
267
|
+
" (Continued)]{" +
|
|
268
268
|
escapeLatex(title) +
|
|
269
|
-
|
|
269
|
+
"}\n\\endfoot\n";
|
|
270
270
|
if (border === 2)
|
|
271
|
-
buf +=
|
|
271
|
+
buf += "\\bottomrule\n";
|
|
272
272
|
buf +=
|
|
273
|
-
|
|
273
|
+
"\\caption[" +
|
|
274
274
|
escapeLatex(title) +
|
|
275
|
-
|
|
275
|
+
"]{" +
|
|
276
276
|
escapeLatex(title) +
|
|
277
|
-
|
|
277
|
+
"}\n\\endlastfoot\n";
|
|
278
278
|
}
|
|
279
279
|
else if (border >= 2) {
|
|
280
|
-
buf +=
|
|
281
|
-
buf +=
|
|
280
|
+
buf += "\\bottomrule\n\\endfoot\n";
|
|
281
|
+
buf += "\\bottomrule\n\\endlastfoot\n";
|
|
282
282
|
}
|
|
283
283
|
}
|
|
284
284
|
}
|
|
@@ -289,18 +289,18 @@ export const latexLongtablePrinter = {
|
|
|
289
289
|
cells.forEach((row) => {
|
|
290
290
|
row.forEach((value) => {
|
|
291
291
|
if (cellIdx !== 0 && cellIdx % ncols !== 0)
|
|
292
|
-
buf +=
|
|
293
|
-
buf +=
|
|
292
|
+
buf += "\n&\n";
|
|
293
|
+
buf += "\\raggedright{" + escapeLatex(value) + "}";
|
|
294
294
|
if ((cellIdx + 1) % ncols === 0) {
|
|
295
|
-
buf +=
|
|
295
|
+
buf += " \\tabularnewline\n";
|
|
296
296
|
if (border === 3)
|
|
297
|
-
buf +=
|
|
297
|
+
buf += " \\hline\n";
|
|
298
298
|
}
|
|
299
299
|
cellIdx += 1;
|
|
300
300
|
});
|
|
301
301
|
});
|
|
302
302
|
if (stopTable)
|
|
303
|
-
buf +=
|
|
303
|
+
buf += "\\end{longtable}\n";
|
|
304
304
|
out.write(buf);
|
|
305
305
|
return Promise.resolve();
|
|
306
306
|
},
|
|
@@ -317,55 +317,55 @@ const effectiveFooters = (rs, topt, footers) => {
|
|
|
317
317
|
return footers;
|
|
318
318
|
if (topt.defaultFooter) {
|
|
319
319
|
const n = rs.rows.length;
|
|
320
|
-
return [`(${String(n)} ${n === 1 ?
|
|
320
|
+
return [`(${String(n)} ${n === 1 ? "row" : "rows"})`];
|
|
321
321
|
}
|
|
322
322
|
return [];
|
|
323
323
|
};
|
|
324
324
|
const escapeLatex = (input) => {
|
|
325
|
-
let out =
|
|
325
|
+
let out = "";
|
|
326
326
|
for (const ch of input) {
|
|
327
327
|
switch (ch) {
|
|
328
|
-
case
|
|
329
|
-
out +=
|
|
328
|
+
case "#":
|
|
329
|
+
out += "\\#";
|
|
330
330
|
break;
|
|
331
|
-
case
|
|
332
|
-
out +=
|
|
331
|
+
case "$":
|
|
332
|
+
out += "\\$";
|
|
333
333
|
break;
|
|
334
|
-
case
|
|
335
|
-
out +=
|
|
334
|
+
case "%":
|
|
335
|
+
out += "\\%";
|
|
336
336
|
break;
|
|
337
|
-
case
|
|
338
|
-
out +=
|
|
337
|
+
case "&":
|
|
338
|
+
out += "\\&";
|
|
339
339
|
break;
|
|
340
|
-
case
|
|
341
|
-
out +=
|
|
340
|
+
case "<":
|
|
341
|
+
out += "\\textless{}";
|
|
342
342
|
break;
|
|
343
|
-
case
|
|
344
|
-
out +=
|
|
343
|
+
case ">":
|
|
344
|
+
out += "\\textgreater{}";
|
|
345
345
|
break;
|
|
346
|
-
case
|
|
347
|
-
out +=
|
|
346
|
+
case "\\":
|
|
347
|
+
out += "\\textbackslash{}";
|
|
348
348
|
break;
|
|
349
|
-
case
|
|
350
|
-
out +=
|
|
349
|
+
case "^":
|
|
350
|
+
out += "\\^{}";
|
|
351
351
|
break;
|
|
352
|
-
case
|
|
353
|
-
out +=
|
|
352
|
+
case "_":
|
|
353
|
+
out += "\\_";
|
|
354
354
|
break;
|
|
355
|
-
case
|
|
356
|
-
out +=
|
|
355
|
+
case "{":
|
|
356
|
+
out += "\\{";
|
|
357
357
|
break;
|
|
358
|
-
case
|
|
359
|
-
out +=
|
|
358
|
+
case "|":
|
|
359
|
+
out += "\\textbar{}";
|
|
360
360
|
break;
|
|
361
|
-
case
|
|
362
|
-
out +=
|
|
361
|
+
case "}":
|
|
362
|
+
out += "\\}";
|
|
363
363
|
break;
|
|
364
|
-
case
|
|
365
|
-
out +=
|
|
364
|
+
case "~":
|
|
365
|
+
out += "\\~{}";
|
|
366
366
|
break;
|
|
367
|
-
case
|
|
368
|
-
out +=
|
|
367
|
+
case "\n":
|
|
368
|
+
out += "\\\\";
|
|
369
369
|
break;
|
|
370
370
|
default:
|
|
371
371
|
out += ch;
|
|
@@ -376,20 +376,20 @@ const escapeLatex = (input) => {
|
|
|
376
376
|
const renderCell = (cell, nullPrint, numericLocale) => {
|
|
377
377
|
if (cell === null || cell === undefined)
|
|
378
378
|
return nullPrint;
|
|
379
|
-
if (typeof cell ===
|
|
379
|
+
if (typeof cell === "string") {
|
|
380
380
|
return formatNumericLocale(cell, numericLocale);
|
|
381
381
|
}
|
|
382
|
-
if (typeof cell ===
|
|
382
|
+
if (typeof cell === "number" || typeof cell === "bigint") {
|
|
383
383
|
return formatNumericLocale(cell.toString(), numericLocale);
|
|
384
384
|
}
|
|
385
|
-
if (typeof cell ===
|
|
386
|
-
return cell ?
|
|
385
|
+
if (typeof cell === "boolean")
|
|
386
|
+
return cell ? "t" : "f";
|
|
387
387
|
if (cell instanceof Date)
|
|
388
388
|
return cell.toISOString();
|
|
389
389
|
if (cell instanceof Uint8Array) {
|
|
390
|
-
let hex =
|
|
390
|
+
let hex = "\\x";
|
|
391
391
|
for (const b of cell)
|
|
392
|
-
hex += b.toString(16).padStart(2,
|
|
392
|
+
hex += b.toString(16).padStart(2, "0");
|
|
393
393
|
return hex;
|
|
394
394
|
}
|
|
395
395
|
return JSON.stringify(cell);
|
package/dist/psql/print/pager.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { basename, delimiter, isAbsolute, join } from
|
|
1
|
+
import { accessSync, constants as fsConstants } from "node:fs";
|
|
2
|
+
import { spawn } from "child_process";
|
|
3
|
+
import { basename, delimiter, isAbsolute, join } from "path";
|
|
4
4
|
/**
|
|
5
5
|
* Can `command` be spawned with `shell:false`? A bare name is searched on
|
|
6
6
|
* `$PATH`; a path is checked directly. Used to avoid `spawn(missingBinary,
|
|
@@ -17,8 +17,8 @@ const pagerCommandResolvable = (command) => {
|
|
|
17
17
|
catch {
|
|
18
18
|
// On Windows X_OK is not meaningful and a bare name omits `.exe`; fall
|
|
19
19
|
// back to a plain existence probe with common executable extensions.
|
|
20
|
-
if (process.platform ===
|
|
21
|
-
for (const ext of [
|
|
20
|
+
if (process.platform === "win32") {
|
|
21
|
+
for (const ext of ["", ".exe", ".cmd", ".bat"]) {
|
|
22
22
|
try {
|
|
23
23
|
accessSync(p + ext, fsConstants.F_OK);
|
|
24
24
|
return true;
|
|
@@ -31,10 +31,12 @@ const pagerCommandResolvable = (command) => {
|
|
|
31
31
|
return false;
|
|
32
32
|
}
|
|
33
33
|
};
|
|
34
|
-
if (command.includes(
|
|
34
|
+
if (command.includes("/") ||
|
|
35
|
+
command.includes("\\") ||
|
|
36
|
+
isAbsolute(command)) {
|
|
35
37
|
return ok(command);
|
|
36
38
|
}
|
|
37
|
-
return (process.env.PATH ??
|
|
39
|
+
return (process.env.PATH ?? "")
|
|
38
40
|
.split(delimiter)
|
|
39
41
|
.filter((d) => d.length > 0)
|
|
40
42
|
.some((dir) => ok(join(dir, command)));
|
|
@@ -70,9 +72,9 @@ const resolvePagerCmd = (opts) => {
|
|
|
70
72
|
return c;
|
|
71
73
|
}
|
|
72
74
|
// DEFAULT_PAGER: `less` on POSIX; nothing on Windows.
|
|
73
|
-
if (process.platform ===
|
|
74
|
-
return
|
|
75
|
-
return
|
|
75
|
+
if (process.platform === "win32")
|
|
76
|
+
return "";
|
|
77
|
+
return "less";
|
|
76
78
|
};
|
|
77
79
|
const getIsTty = (opts) => {
|
|
78
80
|
if (opts.isTty !== undefined)
|
|
@@ -88,16 +90,16 @@ const getTerminalHeight = (opts) => {
|
|
|
88
90
|
const stream = opts.stdout ?? process.stdout;
|
|
89
91
|
const rows = stream.rows;
|
|
90
92
|
// If we can't tell, fall back to 24 (classic VT100 default).
|
|
91
|
-
return typeof rows ===
|
|
93
|
+
return typeof rows === "number" && rows > 0 ? rows : 24;
|
|
92
94
|
};
|
|
93
95
|
/** Standalone helper to determine whether a pager is needed at all. */
|
|
94
96
|
export const isPagerNeeded = (opts) => {
|
|
95
|
-
if (opts.pager ===
|
|
97
|
+
if (opts.pager === "off")
|
|
96
98
|
return false;
|
|
97
99
|
const cmd = resolvePagerCmd(opts);
|
|
98
|
-
if (cmd ===
|
|
100
|
+
if (cmd === "")
|
|
99
101
|
return false;
|
|
100
|
-
if (opts.pager ===
|
|
102
|
+
if (opts.pager === "always")
|
|
101
103
|
return true;
|
|
102
104
|
// pager === 'on'
|
|
103
105
|
if (!getIsTty(opts))
|
|
@@ -120,7 +122,7 @@ export const isPagerNeeded = (opts) => {
|
|
|
120
122
|
* the TTY guard so non-interactive runs don't spuriously spawn `less`.
|
|
121
123
|
*/
|
|
122
124
|
export const shouldPage = (opts) => {
|
|
123
|
-
if (opts.pager ===
|
|
125
|
+
if (opts.pager === "off")
|
|
124
126
|
return false;
|
|
125
127
|
if (opts.redirectedOutput)
|
|
126
128
|
return false;
|
|
@@ -136,7 +138,7 @@ export const shouldPage = (opts) => {
|
|
|
136
138
|
// `pager === 'always'` bypasses the TTY guard — see the docstring above.
|
|
137
139
|
// The remaining gates (resolved cmd, redirected output, off) are enforced
|
|
138
140
|
// inside `isPagerNeeded`.
|
|
139
|
-
if (opts.pager !==
|
|
141
|
+
if (opts.pager !== "always" && !isTty)
|
|
140
142
|
return false;
|
|
141
143
|
return isPagerNeeded({
|
|
142
144
|
pager: opts.pager,
|
|
@@ -165,10 +167,10 @@ const buildPagerEnv = (cmd, baseEnv) => {
|
|
|
165
167
|
if (env.LESS === undefined) {
|
|
166
168
|
// Pull out the first whitespace-separated token to detect `less` even
|
|
167
169
|
// when args follow (e.g. "less -S").
|
|
168
|
-
const firstToken = cmd.trim().split(/\s+/, 1)[0] ??
|
|
170
|
+
const firstToken = cmd.trim().split(/\s+/, 1)[0] ?? "";
|
|
169
171
|
const program = basename(firstToken);
|
|
170
|
-
if (program ===
|
|
171
|
-
env.LESS =
|
|
172
|
+
if (program === "less") {
|
|
173
|
+
env.LESS = "FRX";
|
|
172
174
|
}
|
|
173
175
|
}
|
|
174
176
|
return env;
|
|
@@ -190,7 +192,7 @@ export const openPager = (opts) => {
|
|
|
190
192
|
}
|
|
191
193
|
const cmd = resolvePagerCmd(opts);
|
|
192
194
|
// isPagerNeeded already verified cmd is non-empty, but guard for safety.
|
|
193
|
-
if (cmd ===
|
|
195
|
+
if (cmd === "") {
|
|
194
196
|
return noOpHandle(stdout);
|
|
195
197
|
}
|
|
196
198
|
const { command, shell } = parsePagerCmd(cmd);
|
|
@@ -206,7 +208,7 @@ export const openPager = (opts) => {
|
|
|
206
208
|
let child;
|
|
207
209
|
try {
|
|
208
210
|
child = spawn(command, [], {
|
|
209
|
-
stdio: [
|
|
211
|
+
stdio: ["pipe", "inherit", "inherit"],
|
|
210
212
|
shell,
|
|
211
213
|
env: childEnv,
|
|
212
214
|
});
|
|
@@ -224,8 +226,8 @@ export const openPager = (opts) => {
|
|
|
224
226
|
// Swallow EPIPE: the user can quit the pager early, after which any
|
|
225
227
|
// pending writes will fail with EPIPE. Upstream relies on SIGPIPE being
|
|
226
228
|
// ignored to short-circuit the write loop; we just drop the error.
|
|
227
|
-
stdin.on(
|
|
228
|
-
if (err.code !==
|
|
229
|
+
stdin.on("error", (err) => {
|
|
230
|
+
if (err.code !== "EPIPE") {
|
|
229
231
|
// Re-throw anything unexpected.
|
|
230
232
|
throw err;
|
|
231
233
|
}
|
|
@@ -234,10 +236,10 @@ export const openPager = (opts) => {
|
|
|
234
236
|
const settle = (code) => {
|
|
235
237
|
resolve(code ?? 0);
|
|
236
238
|
};
|
|
237
|
-
child.once(
|
|
239
|
+
child.once("exit", (code) => {
|
|
238
240
|
settle(code);
|
|
239
241
|
});
|
|
240
|
-
child.once(
|
|
242
|
+
child.once("error", () => {
|
|
241
243
|
// If the child errored (e.g. ENOENT), surface a non-zero exit code
|
|
242
244
|
// but don't throw — the caller's writes will have hit EPIPE which
|
|
243
245
|
// we already swallow.
|
|
@@ -255,7 +257,7 @@ export const openPager = (opts) => {
|
|
|
255
257
|
}
|
|
256
258
|
catch (err) {
|
|
257
259
|
const e = err;
|
|
258
|
-
if (e.code !==
|
|
260
|
+
if (e.code !== "EPIPE")
|
|
259
261
|
throw err;
|
|
260
262
|
}
|
|
261
263
|
}
|