neonctl 2.22.2 → 2.23.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 +84 -0
- package/analytics.js +5 -2
- package/commands/branches.js +9 -1
- package/commands/connection_string.js +9 -1
- package/commands/functions.js +268 -0
- package/commands/index.js +4 -0
- package/commands/neon_auth.js +1013 -0
- package/commands/projects.js +9 -1
- package/commands/psql.js +6 -1
- package/functions_api.js +43 -0
- package/package.json +15 -5
- package/psql/cli.js +51 -0
- package/psql/command/cmd_cond.js +437 -0
- package/psql/command/cmd_connect.js +815 -0
- package/psql/command/cmd_copy.js +1025 -0
- package/psql/command/cmd_describe.js +1810 -0
- package/psql/command/cmd_format.js +909 -0
- package/psql/command/cmd_io.js +2187 -0
- package/psql/command/cmd_lo.js +385 -0
- package/psql/command/cmd_meta.js +970 -0
- package/psql/command/cmd_misc.js +187 -0
- package/psql/command/cmd_pipeline.js +1141 -0
- package/psql/command/cmd_restrict.js +171 -0
- package/psql/command/cmd_show.js +751 -0
- package/psql/command/dispatch.js +343 -0
- package/psql/command/inputQueue.js +42 -0
- package/psql/command/shared.js +71 -0
- package/psql/complete/filenames.js +139 -0
- package/psql/complete/index.js +104 -0
- package/psql/complete/matcher.js +314 -0
- package/psql/complete/psqlVars.js +247 -0
- package/psql/complete/queries.js +491 -0
- package/psql/complete/rules.js +2387 -0
- package/psql/core/common.js +1250 -0
- package/psql/core/help.js +576 -0
- package/psql/core/mainloop.js +1353 -0
- package/psql/core/prompt.js +437 -0
- package/psql/core/settings.js +684 -0
- package/psql/core/sqlHelp.js +1066 -0
- package/psql/core/startup.js +840 -0
- package/psql/core/syncVars.js +116 -0
- package/psql/core/variables.js +287 -0
- package/psql/describe/formatters.js +1277 -0
- package/psql/describe/processNamePattern.js +270 -0
- package/psql/describe/queries.js +2373 -0
- package/psql/describe/versionGate.js +43 -0
- package/psql/index.js +2005 -0
- package/psql/io/history.js +299 -0
- package/psql/io/input.js +120 -0
- package/psql/io/lineEditor/buffer.js +323 -0
- package/psql/io/lineEditor/complete.js +227 -0
- package/psql/io/lineEditor/filename.js +159 -0
- package/psql/io/lineEditor/index.js +891 -0
- package/psql/io/lineEditor/keymap.js +738 -0
- package/psql/io/lineEditor/vt100.js +363 -0
- package/psql/io/pgpass.js +202 -0
- package/psql/io/pgservice.js +194 -0
- package/psql/io/psqlrc.js +422 -0
- package/psql/print/aligned.js +1756 -0
- package/psql/print/asciidoc.js +248 -0
- package/psql/print/crosstab.js +460 -0
- package/psql/print/csv.js +92 -0
- package/psql/print/html.js +258 -0
- package/psql/print/json.js +96 -0
- package/psql/print/latex.js +396 -0
- package/psql/print/pager.js +265 -0
- package/psql/print/troff.js +258 -0
- package/psql/print/unaligned.js +118 -0
- package/psql/print/units.js +135 -0
- package/psql/scanner/slash.js +513 -0
- package/psql/scanner/sql.js +910 -0
- package/psql/scanner/stringutils.js +390 -0
- package/psql/types/backslash.js +1 -0
- package/psql/types/connection.js +1 -0
- package/psql/types/index.js +7 -0
- package/psql/types/printer.js +1 -0
- package/psql/types/repl.js +1 -0
- package/psql/types/scanner.js +24 -0
- package/psql/types/settings.js +1 -0
- package/psql/types/variables.js +1 -0
- package/psql/wire/connection.js +2844 -0
- package/psql/wire/copy.js +108 -0
- package/psql/wire/notify.js +59 -0
- package/psql/wire/pipeline.js +519 -0
- package/psql/wire/protocol.js +466 -0
- package/psql/wire/sasl.js +296 -0
- package/psql/wire/tls.js +596 -0
- package/test_utils/fixtures.js +1 -0
- package/utils/esbuild.js +147 -0
- package/utils/psql.js +107 -11
- package/utils/zip.js +4 -0
- package/writer.js +1 -1
- package/commands/auth.test.js +0 -211
- package/commands/branches.test.js +0 -460
- package/commands/checkout.test.js +0 -170
- package/commands/connection_string.test.js +0 -196
- package/commands/data_api.test.js +0 -169
- package/commands/databases.test.js +0 -39
- package/commands/help.test.js +0 -9
- package/commands/init.test.js +0 -56
- package/commands/ip_allow.test.js +0 -59
- package/commands/link.test.js +0 -381
- package/commands/operations.test.js +0 -7
- package/commands/orgs.test.js +0 -7
- package/commands/projects.test.js +0 -144
- package/commands/psql.test.js +0 -49
- package/commands/roles.test.js +0 -37
- package/commands/set_context.test.js +0 -159
- package/commands/vpc_endpoints.test.js +0 -69
- package/context.test.js +0 -119
- package/env.test.js +0 -55
- package/utils/formats.test.js +0 -32
- package/writer.test.js +0 -104
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { formatNumericLocale } from './units.js';
|
|
2
|
+
/**
|
|
3
|
+
* AsciiDoc printer.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors print.c `print_asciidoc_text` and `print_asciidoc_vertical`.
|
|
6
|
+
*
|
|
7
|
+
* Output shape (flat):
|
|
8
|
+
* .title
|
|
9
|
+
* [options="header",cols="<l,<l,>l",frame="all",grid="all"]
|
|
10
|
+
* |====
|
|
11
|
+
* ^l|col1 ^l|col2 ^l|col3
|
|
12
|
+
* |val1 |val2 |val3
|
|
13
|
+
* |====
|
|
14
|
+
*
|
|
15
|
+
* ....
|
|
16
|
+
* (N rows)
|
|
17
|
+
* ....
|
|
18
|
+
*
|
|
19
|
+
* Output shape (expanded, `\pset expanded on`):
|
|
20
|
+
* .title
|
|
21
|
+
* [cols="h,l",frame="all",grid="all"]
|
|
22
|
+
* |====
|
|
23
|
+
* 2+^|Record 1
|
|
24
|
+
* <l|col1 <l|val1
|
|
25
|
+
* <l|col2 >l|val2
|
|
26
|
+
* ...
|
|
27
|
+
* |====
|
|
28
|
+
* (no row count footer)
|
|
29
|
+
*
|
|
30
|
+
* - `topt.border`:
|
|
31
|
+
* 0 → `,frame="none",grid="none"`
|
|
32
|
+
* 1 → `,frame="none"`
|
|
33
|
+
* 2 → `,frame="all",grid="all"`
|
|
34
|
+
* Borders outside 0..2 fall back to "no extra clause" (matches the
|
|
35
|
+
* switch with no default in print.c).
|
|
36
|
+
* - Numeric columns (per the OID heuristic) get `>l`, others `<l`.
|
|
37
|
+
* Headers in flat mode are centered with `^l|`. In expanded mode
|
|
38
|
+
* header cells render with `<l|` and value cells use the alignment
|
|
39
|
+
* letter from the data column.
|
|
40
|
+
* - AsciiDoc's only structurally hostile character is `|` (it ends a
|
|
41
|
+
* cell), so the escape helper only rewrites that to `\|`. Newlines
|
|
42
|
+
* pass through — AsciiDoc continues a cell over an embedded newline.
|
|
43
|
+
* - Whitespace-only cells are emitted as just `|` (with a trailing
|
|
44
|
+
* space for inter-cell separation), matching the upstream
|
|
45
|
+
* "protect against needless spaces" branch.
|
|
46
|
+
* - Expanded mode never emits the `(N rows)` footer; only user-set
|
|
47
|
+
* footers appear (matches upstream `print_asciidoc_vertical`).
|
|
48
|
+
*/
|
|
49
|
+
// INT2, INT4, INT8, FLOAT4, FLOAT8, NUMERIC, INTERVAL.
|
|
50
|
+
const NUMERIC_OIDS = new Set([21, 23, 20, 700, 701, 1700, 1186]);
|
|
51
|
+
export const asciidocPrinter = {
|
|
52
|
+
format: 'asciidoc',
|
|
53
|
+
printQuery(rs, opts, out) {
|
|
54
|
+
const topt = opts.topt;
|
|
55
|
+
if (topt.expanded === 'on') {
|
|
56
|
+
return printExpanded(rs, opts, out);
|
|
57
|
+
}
|
|
58
|
+
return printFlat(rs, opts, out);
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
const printFlat = (rs, opts, out) => {
|
|
62
|
+
const topt = opts.topt;
|
|
63
|
+
const tuplesOnly = topt.tuplesOnly;
|
|
64
|
+
const startTable = topt.startTable;
|
|
65
|
+
const stopTable = topt.stopTable;
|
|
66
|
+
const nullPrint = opts.nullPrint !== '' ? opts.nullPrint : topt.nullPrint;
|
|
67
|
+
const title = opts.title ?? topt.title;
|
|
68
|
+
const footers = opts.footers ?? topt.footers;
|
|
69
|
+
const headers = rs.fields.map((f) => f.name);
|
|
70
|
+
const aligns = rs.fields.map((f) => NUMERIC_OIDS.has(f.dataTypeID) ? 'r' : 'l');
|
|
71
|
+
const ncols = rs.fields.length;
|
|
72
|
+
const cells = rs.rows.map((row) => row.map((cell) => renderCell(cell, nullPrint, topt.numericLocale)));
|
|
73
|
+
let buf = '';
|
|
74
|
+
if (startTable) {
|
|
75
|
+
// Force a paragraph break (upstream always emits a leading "\n").
|
|
76
|
+
buf += '\n';
|
|
77
|
+
if (!tuplesOnly && title) {
|
|
78
|
+
buf += '.' + title + '\n';
|
|
79
|
+
}
|
|
80
|
+
buf += '[';
|
|
81
|
+
if (!tuplesOnly)
|
|
82
|
+
buf += 'options="header",';
|
|
83
|
+
buf += 'cols="';
|
|
84
|
+
buf += aligns.map((a) => (a === 'r' ? '>l' : '<l')).join(',');
|
|
85
|
+
buf += '"';
|
|
86
|
+
buf += borderClause(topt.border);
|
|
87
|
+
buf += ']\n';
|
|
88
|
+
buf += '|====\n';
|
|
89
|
+
if (!tuplesOnly) {
|
|
90
|
+
headers.forEach((h, idx) => {
|
|
91
|
+
if (idx !== 0)
|
|
92
|
+
buf += ' ';
|
|
93
|
+
buf += '^l|' + escapeAsciidoc(h);
|
|
94
|
+
});
|
|
95
|
+
buf += '\n';
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
for (const row of cells) {
|
|
99
|
+
row.forEach((value, idx) => {
|
|
100
|
+
if (idx !== 0)
|
|
101
|
+
buf += ' ';
|
|
102
|
+
buf += '|';
|
|
103
|
+
if (isWhitespaceOnly(value)) {
|
|
104
|
+
// The upstream code emits a trailing space only for cells
|
|
105
|
+
// that are not the last in their row.
|
|
106
|
+
if (idx !== ncols - 1)
|
|
107
|
+
buf += ' ';
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
buf += escapeAsciidoc(value);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
buf += '\n';
|
|
114
|
+
}
|
|
115
|
+
buf += '|====\n';
|
|
116
|
+
if (stopTable && !tuplesOnly) {
|
|
117
|
+
const effective = effectiveFooters(rs, topt, footers);
|
|
118
|
+
if (effective.length > 0) {
|
|
119
|
+
buf += '\n....\n';
|
|
120
|
+
for (const f of effective)
|
|
121
|
+
buf += f + '\n';
|
|
122
|
+
buf += '....\n';
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
out.write(buf);
|
|
126
|
+
return Promise.resolve();
|
|
127
|
+
};
|
|
128
|
+
const printExpanded = (rs, opts, out) => {
|
|
129
|
+
const topt = opts.topt;
|
|
130
|
+
const tuplesOnly = topt.tuplesOnly;
|
|
131
|
+
const startTable = topt.startTable;
|
|
132
|
+
const stopTable = topt.stopTable;
|
|
133
|
+
const nullPrint = opts.nullPrint !== '' ? opts.nullPrint : topt.nullPrint;
|
|
134
|
+
const title = opts.title ?? topt.title;
|
|
135
|
+
const footers = opts.footers ?? topt.footers;
|
|
136
|
+
const headers = rs.fields.map((f) => f.name);
|
|
137
|
+
const aligns = rs.fields.map((f) => NUMERIC_OIDS.has(f.dataTypeID) ? 'r' : 'l');
|
|
138
|
+
const cells = rs.rows.map((row) => row.map((cell) => renderCell(cell, nullPrint, topt.numericLocale)));
|
|
139
|
+
let buf = '';
|
|
140
|
+
if (startTable) {
|
|
141
|
+
buf += '\n';
|
|
142
|
+
if (!tuplesOnly && title) {
|
|
143
|
+
buf += '.' + title + '\n';
|
|
144
|
+
}
|
|
145
|
+
buf += '[cols="h,l"';
|
|
146
|
+
buf += borderClause(topt.border);
|
|
147
|
+
buf += ']\n';
|
|
148
|
+
buf += '|====\n';
|
|
149
|
+
}
|
|
150
|
+
let record = topt.prior + 1;
|
|
151
|
+
cells.forEach((row) => {
|
|
152
|
+
if (!tuplesOnly) {
|
|
153
|
+
buf += `2+^|Record ${String(record)}\n`;
|
|
154
|
+
record += 1;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
buf += '2+|\n';
|
|
158
|
+
}
|
|
159
|
+
row.forEach((value, idx) => {
|
|
160
|
+
buf += '<l|' + escapeAsciidoc(headers[idx]);
|
|
161
|
+
buf += ' ' + (aligns[idx] === 'r' ? '>l' : '<l') + '|';
|
|
162
|
+
if (isWhitespaceOnly(value)) {
|
|
163
|
+
buf += ' ';
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
buf += escapeAsciidoc(value);
|
|
167
|
+
}
|
|
168
|
+
buf += '\n';
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
buf += '|====\n';
|
|
172
|
+
if (stopTable && !tuplesOnly) {
|
|
173
|
+
// Expanded mode does NOT emit the default "(N rows)" footer —
|
|
174
|
+
// only user-supplied footers (matches print_asciidoc_vertical).
|
|
175
|
+
if (footers && footers.length > 0) {
|
|
176
|
+
buf += '\n....\n';
|
|
177
|
+
for (const f of footers)
|
|
178
|
+
buf += f + '\n';
|
|
179
|
+
buf += '....\n';
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
out.write(buf);
|
|
183
|
+
return Promise.resolve();
|
|
184
|
+
};
|
|
185
|
+
const borderClause = (border) => {
|
|
186
|
+
switch (border) {
|
|
187
|
+
case 0:
|
|
188
|
+
return ',frame="none",grid="none"';
|
|
189
|
+
case 1:
|
|
190
|
+
return ',frame="none"';
|
|
191
|
+
case 2:
|
|
192
|
+
return ',frame="all",grid="all"';
|
|
193
|
+
default:
|
|
194
|
+
return '';
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
const effectiveFooters = (rs, topt, footers) => {
|
|
198
|
+
if (footers && footers.length > 0)
|
|
199
|
+
return footers;
|
|
200
|
+
if (topt.defaultFooter) {
|
|
201
|
+
const n = rs.rows.length;
|
|
202
|
+
return [`(${String(n)} ${n === 1 ? 'row' : 'rows'})`];
|
|
203
|
+
}
|
|
204
|
+
return [];
|
|
205
|
+
};
|
|
206
|
+
const isWhitespaceOnly = (s) => {
|
|
207
|
+
if (s.length === 0)
|
|
208
|
+
return true;
|
|
209
|
+
for (const ch of s) {
|
|
210
|
+
if (ch !== ' ' && ch !== '\t')
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
return true;
|
|
214
|
+
};
|
|
215
|
+
const escapeAsciidoc = (input) => {
|
|
216
|
+
// Only `|` is structurally hostile (closes a cell). Newlines and
|
|
217
|
+
// every other character pass through; AsciiDoc treats embedded `\n`
|
|
218
|
+
// as a soft line break within a cell.
|
|
219
|
+
let out = '';
|
|
220
|
+
for (const ch of input) {
|
|
221
|
+
if (ch === '|')
|
|
222
|
+
out += '\\|';
|
|
223
|
+
else
|
|
224
|
+
out += ch;
|
|
225
|
+
}
|
|
226
|
+
return out;
|
|
227
|
+
};
|
|
228
|
+
const renderCell = (cell, nullPrint, numericLocale) => {
|
|
229
|
+
if (cell === null || cell === undefined)
|
|
230
|
+
return nullPrint;
|
|
231
|
+
if (typeof cell === 'string') {
|
|
232
|
+
return formatNumericLocale(cell, numericLocale);
|
|
233
|
+
}
|
|
234
|
+
if (typeof cell === 'number' || typeof cell === 'bigint') {
|
|
235
|
+
return formatNumericLocale(cell.toString(), numericLocale);
|
|
236
|
+
}
|
|
237
|
+
if (typeof cell === 'boolean')
|
|
238
|
+
return cell ? 't' : 'f';
|
|
239
|
+
if (cell instanceof Date)
|
|
240
|
+
return cell.toISOString();
|
|
241
|
+
if (cell instanceof Uint8Array) {
|
|
242
|
+
let hex = '\\x';
|
|
243
|
+
for (const b of cell)
|
|
244
|
+
hex += b.toString(16).padStart(2, '0');
|
|
245
|
+
return hex;
|
|
246
|
+
}
|
|
247
|
+
return JSON.stringify(cell);
|
|
248
|
+
};
|