neonctl 2.22.0 → 2.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/README.md +242 -16
  2. package/analytics.js +5 -2
  3. package/commands/branches.js +9 -1
  4. package/commands/checkout.js +249 -0
  5. package/commands/connection_string.js +15 -2
  6. package/commands/data_api.js +286 -0
  7. package/commands/functions.js +277 -0
  8. package/commands/index.js +12 -0
  9. package/commands/link.js +667 -0
  10. package/commands/neon_auth.js +1013 -0
  11. package/commands/projects.js +9 -1
  12. package/commands/psql.js +62 -0
  13. package/commands/set_context.js +7 -2
  14. package/context.js +86 -14
  15. package/functions_api.js +44 -0
  16. package/index.js +3 -0
  17. package/package.json +60 -51
  18. package/psql/cli.js +51 -0
  19. package/psql/command/cmd_cond.js +437 -0
  20. package/psql/command/cmd_connect.js +815 -0
  21. package/psql/command/cmd_copy.js +1025 -0
  22. package/psql/command/cmd_describe.js +1810 -0
  23. package/psql/command/cmd_format.js +909 -0
  24. package/psql/command/cmd_io.js +2187 -0
  25. package/psql/command/cmd_lo.js +385 -0
  26. package/psql/command/cmd_meta.js +970 -0
  27. package/psql/command/cmd_misc.js +187 -0
  28. package/psql/command/cmd_pipeline.js +1141 -0
  29. package/psql/command/cmd_restrict.js +171 -0
  30. package/psql/command/cmd_show.js +751 -0
  31. package/psql/command/dispatch.js +343 -0
  32. package/psql/command/inputQueue.js +42 -0
  33. package/psql/command/shared.js +71 -0
  34. package/psql/complete/filenames.js +139 -0
  35. package/psql/complete/index.js +104 -0
  36. package/psql/complete/matcher.js +314 -0
  37. package/psql/complete/psqlVars.js +247 -0
  38. package/psql/complete/queries.js +491 -0
  39. package/psql/complete/rules.js +2387 -0
  40. package/psql/core/common.js +1250 -0
  41. package/psql/core/help.js +576 -0
  42. package/psql/core/mainloop.js +1353 -0
  43. package/psql/core/prompt.js +437 -0
  44. package/psql/core/settings.js +684 -0
  45. package/psql/core/sqlHelp.js +1066 -0
  46. package/psql/core/startup.js +840 -0
  47. package/psql/core/syncVars.js +116 -0
  48. package/psql/core/variables.js +287 -0
  49. package/psql/describe/formatters.js +1277 -0
  50. package/psql/describe/processNamePattern.js +270 -0
  51. package/psql/describe/queries.js +2373 -0
  52. package/psql/describe/versionGate.js +43 -0
  53. package/psql/index.js +2005 -0
  54. package/psql/io/history.js +299 -0
  55. package/psql/io/input.js +120 -0
  56. package/psql/io/lineEditor/buffer.js +323 -0
  57. package/psql/io/lineEditor/complete.js +227 -0
  58. package/psql/io/lineEditor/filename.js +159 -0
  59. package/psql/io/lineEditor/index.js +891 -0
  60. package/psql/io/lineEditor/keymap.js +738 -0
  61. package/psql/io/lineEditor/vt100.js +363 -0
  62. package/psql/io/pgpass.js +202 -0
  63. package/psql/io/pgservice.js +194 -0
  64. package/psql/io/psqlrc.js +422 -0
  65. package/psql/print/aligned.js +1756 -0
  66. package/psql/print/asciidoc.js +248 -0
  67. package/psql/print/crosstab.js +460 -0
  68. package/psql/print/csv.js +92 -0
  69. package/psql/print/html.js +258 -0
  70. package/psql/print/json.js +96 -0
  71. package/psql/print/latex.js +396 -0
  72. package/psql/print/pager.js +265 -0
  73. package/psql/print/troff.js +258 -0
  74. package/psql/print/unaligned.js +118 -0
  75. package/psql/print/units.js +135 -0
  76. package/psql/scanner/slash.js +513 -0
  77. package/psql/scanner/sql.js +910 -0
  78. package/psql/scanner/stringutils.js +390 -0
  79. package/psql/types/backslash.js +1 -0
  80. package/psql/types/connection.js +1 -0
  81. package/psql/types/index.js +7 -0
  82. package/psql/types/printer.js +1 -0
  83. package/psql/types/repl.js +1 -0
  84. package/psql/types/scanner.js +24 -0
  85. package/psql/types/settings.js +1 -0
  86. package/psql/types/variables.js +1 -0
  87. package/psql/wire/connection.js +2844 -0
  88. package/psql/wire/copy.js +108 -0
  89. package/psql/wire/notify.js +59 -0
  90. package/psql/wire/pipeline.js +519 -0
  91. package/psql/wire/protocol.js +466 -0
  92. package/psql/wire/sasl.js +296 -0
  93. package/psql/wire/tls.js +596 -0
  94. package/test_utils/fixtures.js +1 -0
  95. package/utils/enrichers.js +18 -1
  96. package/utils/esbuild.js +147 -0
  97. package/utils/middlewares.js +1 -1
  98. package/utils/psql.js +107 -11
  99. package/utils/zip.js +4 -0
  100. package/writer.js +1 -1
  101. package/commands/auth.test.js +0 -211
  102. package/commands/branches.test.js +0 -460
  103. package/commands/connection_string.test.js +0 -196
  104. package/commands/databases.test.js +0 -39
  105. package/commands/help.test.js +0 -9
  106. package/commands/init.test.js +0 -56
  107. package/commands/ip_allow.test.js +0 -59
  108. package/commands/operations.test.js +0 -7
  109. package/commands/orgs.test.js +0 -7
  110. package/commands/projects.test.js +0 -144
  111. package/commands/roles.test.js +0 -37
  112. package/commands/set_context.test.js +0 -159
  113. package/commands/vpc_endpoints.test.js +0 -69
  114. package/env.test.js +0 -55
  115. package/utils/formats.test.js +0 -32
  116. 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
+ };