neonctl 2.37.1 → 2.38.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.
Files changed (159) hide show
  1. package/README.md +15 -700
  2. package/bin/cli.js +3 -0
  3. package/package.json +8 -75
  4. package/dist/analytics.js +0 -168
  5. package/dist/api.js +0 -720
  6. package/dist/auth.js +0 -125
  7. package/dist/callback.html +0 -60
  8. package/dist/cli.js +0 -9
  9. package/dist/commands/api.js +0 -278
  10. package/dist/commands/auth.js +0 -214
  11. package/dist/commands/bootstrap.js +0 -481
  12. package/dist/commands/branches.js +0 -488
  13. package/dist/commands/bucket.js +0 -549
  14. package/dist/commands/checkout.js +0 -321
  15. package/dist/commands/config.js +0 -626
  16. package/dist/commands/connection_string.js +0 -172
  17. package/dist/commands/data_api.js +0 -284
  18. package/dist/commands/databases.js +0 -82
  19. package/dist/commands/deploy.js +0 -26
  20. package/dist/commands/dev.js +0 -698
  21. package/dist/commands/diff.js +0 -222
  22. package/dist/commands/env.js +0 -189
  23. package/dist/commands/functions.js +0 -373
  24. package/dist/commands/index.js +0 -62
  25. package/dist/commands/init.js +0 -73
  26. package/dist/commands/inspect.js +0 -65
  27. package/dist/commands/ip_allow.js +0 -137
  28. package/dist/commands/link.js +0 -1121
  29. package/dist/commands/neon_auth.js +0 -1028
  30. package/dist/commands/operations.js +0 -28
  31. package/dist/commands/orgs.js +0 -24
  32. package/dist/commands/projects.js +0 -413
  33. package/dist/commands/psql.js +0 -62
  34. package/dist/commands/roles.js +0 -65
  35. package/dist/commands/schema_diff.js +0 -151
  36. package/dist/commands/set_context.js +0 -29
  37. package/dist/commands/snapshots.js +0 -455
  38. package/dist/commands/status.js +0 -40
  39. package/dist/commands/user.js +0 -15
  40. package/dist/commands/vpc_endpoints.js +0 -134
  41. package/dist/config.js +0 -11
  42. package/dist/config_format.js +0 -72
  43. package/dist/context.js +0 -231
  44. package/dist/current_branch_fast_path.js +0 -55
  45. package/dist/dev/env.js +0 -244
  46. package/dist/dev/functions.js +0 -70
  47. package/dist/dev/inputs.js +0 -63
  48. package/dist/dev/runtime.js +0 -146
  49. package/dist/env.js +0 -36
  50. package/dist/env_file.js +0 -159
  51. package/dist/errors.js +0 -80
  52. package/dist/functions_api.js +0 -48
  53. package/dist/help.js +0 -146
  54. package/dist/index.js +0 -240
  55. package/dist/log.js +0 -18
  56. package/dist/parameters.gen.js +0 -480
  57. package/dist/pkg.js +0 -25
  58. package/dist/psql/cli.js +0 -53
  59. package/dist/psql/command/cmd_cond.js +0 -437
  60. package/dist/psql/command/cmd_connect.js +0 -820
  61. package/dist/psql/command/cmd_copy.js +0 -1035
  62. package/dist/psql/command/cmd_describe.js +0 -1815
  63. package/dist/psql/command/cmd_format.js +0 -948
  64. package/dist/psql/command/cmd_io.js +0 -2193
  65. package/dist/psql/command/cmd_lo.js +0 -393
  66. package/dist/psql/command/cmd_meta.js +0 -969
  67. package/dist/psql/command/cmd_misc.js +0 -187
  68. package/dist/psql/command/cmd_pipeline.js +0 -1148
  69. package/dist/psql/command/cmd_restrict.js +0 -171
  70. package/dist/psql/command/cmd_show.js +0 -766
  71. package/dist/psql/command/dispatch.js +0 -343
  72. package/dist/psql/command/inputQueue.js +0 -42
  73. package/dist/psql/command/shared.js +0 -71
  74. package/dist/psql/complete/filenames.js +0 -139
  75. package/dist/psql/complete/index.js +0 -104
  76. package/dist/psql/complete/matcher.js +0 -315
  77. package/dist/psql/complete/psqlVars.js +0 -249
  78. package/dist/psql/complete/queries.js +0 -493
  79. package/dist/psql/complete/rules.js +0 -2424
  80. package/dist/psql/core/common.js +0 -1253
  81. package/dist/psql/core/help.js +0 -576
  82. package/dist/psql/core/mainloop.js +0 -1360
  83. package/dist/psql/core/prompt.js +0 -439
  84. package/dist/psql/core/settings.js +0 -686
  85. package/dist/psql/core/sqlHelp.js +0 -1066
  86. package/dist/psql/core/startup.js +0 -846
  87. package/dist/psql/core/syncVars.js +0 -116
  88. package/dist/psql/core/variables.js +0 -287
  89. package/dist/psql/describe/formatters.js +0 -1330
  90. package/dist/psql/describe/processNamePattern.js +0 -270
  91. package/dist/psql/describe/queries.js +0 -2452
  92. package/dist/psql/describe/versionGate.js +0 -44
  93. package/dist/psql/index.js +0 -2030
  94. package/dist/psql/io/history.js +0 -299
  95. package/dist/psql/io/input.js +0 -120
  96. package/dist/psql/io/lineEditor/buffer.js +0 -325
  97. package/dist/psql/io/lineEditor/complete.js +0 -227
  98. package/dist/psql/io/lineEditor/filename.js +0 -159
  99. package/dist/psql/io/lineEditor/index.js +0 -893
  100. package/dist/psql/io/lineEditor/keymap.js +0 -745
  101. package/dist/psql/io/lineEditor/vt100.js +0 -363
  102. package/dist/psql/io/pgpass.js +0 -202
  103. package/dist/psql/io/pgservice.js +0 -194
  104. package/dist/psql/io/psqlrc.js +0 -422
  105. package/dist/psql/print/aligned.js +0 -1748
  106. package/dist/psql/print/asciidoc.js +0 -230
  107. package/dist/psql/print/crosstab.js +0 -463
  108. package/dist/psql/print/csv.js +0 -76
  109. package/dist/psql/print/html.js +0 -240
  110. package/dist/psql/print/json.js +0 -96
  111. package/dist/psql/print/latex.js +0 -379
  112. package/dist/psql/print/pager.js +0 -267
  113. package/dist/psql/print/troff.js +0 -240
  114. package/dist/psql/print/unaligned.js +0 -99
  115. package/dist/psql/print/units.js +0 -188
  116. package/dist/psql/scanner/slash.js +0 -515
  117. package/dist/psql/scanner/sql.js +0 -914
  118. package/dist/psql/scanner/stringutils.js +0 -394
  119. package/dist/psql/types/backslash.js +0 -1
  120. package/dist/psql/types/connection.js +0 -1
  121. package/dist/psql/types/index.js +0 -7
  122. package/dist/psql/types/printer.js +0 -1
  123. package/dist/psql/types/repl.js +0 -1
  124. package/dist/psql/types/scanner.js +0 -24
  125. package/dist/psql/types/settings.js +0 -1
  126. package/dist/psql/types/variables.js +0 -1
  127. package/dist/psql/wire/connection.js +0 -2857
  128. package/dist/psql/wire/copy.js +0 -108
  129. package/dist/psql/wire/notify.js +0 -59
  130. package/dist/psql/wire/pipeline.js +0 -521
  131. package/dist/psql/wire/protocol.js +0 -466
  132. package/dist/psql/wire/sasl.js +0 -294
  133. package/dist/psql/wire/tls.js +0 -602
  134. package/dist/storage_api.js +0 -147
  135. package/dist/test_utils/fixtures.js +0 -121
  136. package/dist/test_utils/oauth_server.js +0 -9
  137. package/dist/types.js +0 -1
  138. package/dist/utils/ai_gateway_notice.js +0 -180
  139. package/dist/utils/api_enums.js +0 -33
  140. package/dist/utils/auth.js +0 -5
  141. package/dist/utils/branch_notice.js +0 -22
  142. package/dist/utils/branch_picker.js +0 -103
  143. package/dist/utils/compute_units.js +0 -28
  144. package/dist/utils/config_diff.js +0 -185
  145. package/dist/utils/enrichers.js +0 -161
  146. package/dist/utils/esbuild.js +0 -158
  147. package/dist/utils/formats.js +0 -18
  148. package/dist/utils/git_diff.js +0 -90
  149. package/dist/utils/inspect_db.js +0 -153
  150. package/dist/utils/inspect_queries.js +0 -372
  151. package/dist/utils/middlewares.js +0 -20
  152. package/dist/utils/openapi.js +0 -114
  153. package/dist/utils/package_manager.js +0 -68
  154. package/dist/utils/point_in_time.js +0 -56
  155. package/dist/utils/psql.js +0 -120
  156. package/dist/utils/string.js +0 -5
  157. package/dist/utils/ui.js +0 -59
  158. package/dist/utils/zip.js +0 -4
  159. package/dist/writer.js +0 -97
@@ -1,76 +0,0 @@
1
- import { boolDisplayOf, renderCellValue } from "./units.js";
2
- /**
3
- * RFC 4180 CSV printer.
4
- *
5
- * Mirrors print.c `print_csv_text` / `print_csv_vertical`.
6
- *
7
- * - Field separator defaults to `,`; honors `topt.csvFieldSep`. The
8
- * separator must be a single character and may not be `"`, `\n`, or
9
- * `\r` (matches the psql `\pset csv_fieldsep` check).
10
- * - Line ending is always `\n` regardless of `topt.recordSep`, since
11
- * `print_csv_text` writes `'\n'` literally.
12
- * - Header row is printed only when `startTable && !tuplesOnly`
13
- * (matches `print_csv_text` — see the `start_table && !tuples_only`
14
- * guard upstream). `\pset tuples_only true` suppresses the header.
15
- * - No footer in CSV.
16
- * - Expanded mode (`print_csv_vertical`) prints `name,value` lines and
17
- * never emits a standalone header row.
18
- *
19
- * Quoting rule (from `csv_print_field`): wrap in double quotes if the
20
- * value contains the separator, a `"`, `\n`, or `\r`; inside quotes,
21
- * double the embedded `"`. We additionally quote `\.` (psql's COPY
22
- * sentinel) when the separator is `\` or `.`, matching upstream.
23
- */
24
- export const csvPrinter = {
25
- format: "csv",
26
- printQuery(rs, opts, out) {
27
- const topt = opts.topt;
28
- const sep = topt.csvFieldSep !== undefined && topt.csvFieldSep !== ""
29
- ? topt.csvFieldSep
30
- : ",";
31
- if (sep.length !== 1 || sep === '"' || sep === "\n" || sep === "\r") {
32
- throw new RangeError(`csv_fieldsep must be a single character other than '"', '\\n', or '\\r' (got ${JSON.stringify(sep)})`);
33
- }
34
- const nullPrint = opts.nullPrint !== "" ? opts.nullPrint : topt.nullPrint;
35
- const expanded = topt.expanded === "on";
36
- const headers = rs.fields.map((f) => f.name);
37
- const boolDisplay = boolDisplayOf(topt);
38
- const cells = rs.rows.map((row) => row.map((cell, i) => renderCell(cell, nullPrint, topt.numericLocale, rs.fields[i]?.dataTypeID, boolDisplay)));
39
- let outBuf = "";
40
- if (expanded) {
41
- for (const row of cells) {
42
- row.forEach((value, colIdx) => {
43
- outBuf +=
44
- csvField(headers[colIdx], sep) +
45
- sep +
46
- csvField(value, sep) +
47
- "\n";
48
- });
49
- }
50
- }
51
- else {
52
- // Header is gated on startTable && !tuplesOnly (cf. print.c).
53
- if (topt.startTable && !topt.tuplesOnly) {
54
- outBuf += headers.map((h) => csvField(h, sep)).join(sep) + "\n";
55
- }
56
- for (const row of cells) {
57
- outBuf += row.map((c) => csvField(c, sep)).join(sep) + "\n";
58
- }
59
- }
60
- out.write(outBuf);
61
- return Promise.resolve();
62
- },
63
- };
64
- const renderCell = (cell, nullPrint, numericLocale, dataTypeID, boolDisplay) => renderCellValue(cell, nullPrint, numericLocale, dataTypeID, boolDisplay);
65
- const csvField = (value, sep) => {
66
- const needsQuote = value.includes(sep) ||
67
- value.includes('"') ||
68
- value.includes("\n") ||
69
- value.includes("\r") ||
70
- value === "\\." ||
71
- sep === "\\" ||
72
- sep === ".";
73
- if (!needsQuote)
74
- return value;
75
- return `"${value.replace(/"/g, '""')}"`;
76
- };
@@ -1,240 +0,0 @@
1
- import { boolDisplayOf, renderCellValue } from "./units.js";
2
- /**
3
- * HTML printer.
4
- *
5
- * Mirrors print.c `print_html_text` and `print_html_vertical`.
6
- *
7
- * Output shape (flat):
8
- * <table border="1">
9
- * <caption>title</caption>
10
- * <tr>
11
- * <th align="center">col</th>
12
- * ...
13
- * </tr>
14
- * <tr valign="top">
15
- * <td align="left">val</td>
16
- * ...
17
- * </tr>
18
- * ...
19
- * </table>
20
- * <p>(N rows)<br />
21
- * footer<br />
22
- * </p>
23
- *
24
- * Output shape (expanded, `\pset expanded on`):
25
- * <table border="1">
26
- * <caption>title</caption>
27
- *
28
- * <tr><td colspan="2" align="center">Record 1</td></tr>
29
- * <tr valign="top">
30
- * <th>col</th>
31
- * <td align="left">val</td>
32
- * </tr>
33
- * ...
34
- * </table>
35
- * <p>user footer<br />
36
- * </p>
37
- *
38
- * - `topt.tableAttr` is appended to the opening `<table>` tag.
39
- * - `topt.border` becomes the `border="..."` value.
40
- * - `topt.startTable` / `stopTable` gate the prologue/epilogue, allowing
41
- * chunked streaming. For this WP both default to true, so the full
42
- * document is emitted in one call.
43
- * - Right-align numeric columns based on the PG type-OID heuristic
44
- * (`NUMERIC_OIDS`), matching how `print_aligned_text` derives the
45
- * `aligns` array upstream.
46
- * - Cells that are whitespace-only render `&nbsp; ` so the cell still
47
- * takes layout space (verbatim upstream behavior).
48
- * - Expanded mode renders a `<tr><td colspan="2" align="center">Record
49
- * N</td></tr>` separator before each row (or `&nbsp;` placeholder
50
- * when `tuplesOnly`); it never emits the default `(N rows)` footer.
51
- */
52
- // INT2, INT4, INT8, FLOAT4, FLOAT8, NUMERIC, INTERVAL.
53
- const NUMERIC_OIDS = new Set([21, 23, 20, 700, 701, 1700, 1186]);
54
- export const htmlPrinter = {
55
- format: "html",
56
- printQuery(rs, opts, out) {
57
- const topt = opts.topt;
58
- if (topt.expanded === "on") {
59
- return printExpanded(rs, opts, out);
60
- }
61
- return printFlat(rs, opts, out);
62
- },
63
- };
64
- const printFlat = (rs, opts, out) => {
65
- const topt = opts.topt;
66
- const tuplesOnly = topt.tuplesOnly;
67
- const startTable = topt.startTable;
68
- const stopTable = topt.stopTable;
69
- const nullPrint = opts.nullPrint !== "" ? opts.nullPrint : topt.nullPrint;
70
- const title = opts.title ?? topt.title;
71
- const footers = opts.footers ?? topt.footers;
72
- const headers = rs.fields.map((f) => f.name);
73
- const aligns = rs.fields.map((f) => NUMERIC_OIDS.has(f.dataTypeID) ? "right" : "left");
74
- const boolDisplay = boolDisplayOf(topt);
75
- const cells = rs.rows.map((row) => row.map((cell, i) => renderCell(cell, nullPrint, topt.numericLocale, rs.fields[i]?.dataTypeID, boolDisplay)));
76
- let buf = "";
77
- if (startTable) {
78
- buf += `<table border="${String(topt.border)}"`;
79
- if (topt.tableAttr)
80
- buf += ` ${topt.tableAttr}`;
81
- buf += ">\n";
82
- if (!tuplesOnly && title) {
83
- buf += " <caption>" + escapeHtml(title) + "</caption>\n";
84
- }
85
- if (!tuplesOnly) {
86
- buf += " <tr>\n";
87
- for (const h of headers) {
88
- buf += ' <th align="center">' + escapeHtml(h) + "</th>\n";
89
- }
90
- buf += " </tr>\n";
91
- }
92
- }
93
- for (const row of cells) {
94
- buf += ' <tr valign="top">\n';
95
- row.forEach((value, idx) => {
96
- buf += ` <td align="${aligns[idx]}">`;
97
- if (isWhitespaceOnly(value)) {
98
- buf += "&nbsp; ";
99
- }
100
- else {
101
- buf += escapeHtml(value);
102
- }
103
- buf += "</td>\n";
104
- });
105
- buf += " </tr>\n";
106
- }
107
- if (stopTable) {
108
- buf += "</table>\n";
109
- if (!tuplesOnly) {
110
- const effective = effectiveFooters(rs, topt, footers);
111
- if (effective.length > 0) {
112
- buf += "<p>";
113
- for (const f of effective) {
114
- buf += escapeHtml(f) + "<br />\n";
115
- }
116
- buf += "</p>";
117
- }
118
- }
119
- // Upstream `print_html_text` finishes with an unconditional
120
- // `fputc('\n', fout)` AFTER the (optional) `<p>...</p>` block. The
121
- // trailing newline appears regardless of footers / tuplesOnly.
122
- buf += "\n";
123
- }
124
- out.write(buf);
125
- return Promise.resolve();
126
- };
127
- const printExpanded = (rs, opts, out) => {
128
- const topt = opts.topt;
129
- const tuplesOnly = topt.tuplesOnly;
130
- const startTable = topt.startTable;
131
- const stopTable = topt.stopTable;
132
- const nullPrint = opts.nullPrint !== "" ? opts.nullPrint : topt.nullPrint;
133
- const title = opts.title ?? topt.title;
134
- const footers = opts.footers ?? topt.footers;
135
- const headers = rs.fields.map((f) => f.name);
136
- const aligns = rs.fields.map((f) => NUMERIC_OIDS.has(f.dataTypeID) ? "right" : "left");
137
- const boolDisplay = boolDisplayOf(topt);
138
- const cells = rs.rows.map((row) => row.map((cell, i) => renderCell(cell, nullPrint, topt.numericLocale, rs.fields[i]?.dataTypeID, boolDisplay)));
139
- let buf = "";
140
- if (startTable) {
141
- buf += `<table border="${String(topt.border)}"`;
142
- if (topt.tableAttr)
143
- buf += ` ${topt.tableAttr}`;
144
- buf += ">\n";
145
- if (!tuplesOnly && title) {
146
- buf += " <caption>" + escapeHtml(title) + "</caption>\n";
147
- }
148
- }
149
- let record = topt.prior + 1;
150
- cells.forEach((row) => {
151
- if (!tuplesOnly) {
152
- buf += `\n <tr><td colspan="2" align="center">Record ${String(record)}</td></tr>\n`;
153
- record += 1;
154
- }
155
- else {
156
- buf += '\n <tr><td colspan="2">&nbsp;</td></tr>\n';
157
- }
158
- row.forEach((value, idx) => {
159
- buf += ' <tr valign="top">\n';
160
- buf += " <th>" + escapeHtml(headers[idx]) + "</th>\n";
161
- buf += ` <td align="${aligns[idx]}">`;
162
- if (isWhitespaceOnly(value)) {
163
- buf += "&nbsp; ";
164
- }
165
- else {
166
- buf += escapeHtml(value);
167
- }
168
- buf += "</td>\n";
169
- buf += " </tr>\n";
170
- });
171
- });
172
- if (stopTable) {
173
- buf += "</table>\n";
174
- // Expanded mode never emits the default "(N rows)" footer; only
175
- // user-supplied footers appear (matches print_html_vertical).
176
- if (!tuplesOnly && footers && footers.length > 0) {
177
- buf += "<p>";
178
- for (const f of footers) {
179
- buf += escapeHtml(f) + "<br />\n";
180
- }
181
- buf += "</p>";
182
- }
183
- buf += "\n";
184
- }
185
- out.write(buf);
186
- return Promise.resolve();
187
- };
188
- const effectiveFooters = (rs, topt, footers) => {
189
- if (footers && footers.length > 0)
190
- return footers;
191
- if (topt.defaultFooter) {
192
- const n = rs.rows.length;
193
- return [`(${String(n)} ${n === 1 ? "row" : "rows"})`];
194
- }
195
- return [];
196
- };
197
- const isWhitespaceOnly = (s) => {
198
- if (s.length === 0)
199
- return true;
200
- for (const ch of s) {
201
- if (ch !== " " && ch !== "\t")
202
- return false;
203
- }
204
- return true;
205
- };
206
- const escapeHtml = (input) => {
207
- // Upstream `html_escaped_print` walks the string byte-by-byte and
208
- // converts leading spaces (per line) to `&nbsp;` so EXPLAIN output
209
- // stays indented. We replicate that with a stateful pass.
210
- let out = "";
211
- let leadingSpace = true;
212
- for (const ch of input) {
213
- switch (ch) {
214
- case "&":
215
- out += "&amp;";
216
- break;
217
- case "<":
218
- out += "&lt;";
219
- break;
220
- case ">":
221
- out += "&gt;";
222
- break;
223
- case '"':
224
- out += "&quot;";
225
- break;
226
- case "\n":
227
- out += "<br />\n";
228
- break;
229
- case " ":
230
- out += leadingSpace ? "&nbsp;" : " ";
231
- break;
232
- default:
233
- out += ch;
234
- }
235
- if (ch !== " ")
236
- leadingSpace = false;
237
- }
238
- return out;
239
- };
240
- const renderCell = (cell, nullPrint, numericLocale, dataTypeID, boolDisplay) => renderCellValue(cell, nullPrint, numericLocale, dataTypeID, boolDisplay);
@@ -1,96 +0,0 @@
1
- /**
2
- * JSON printer (used by `\gset`, `\gdesc`, and `--json` callers later
3
- * in the WP plan).
4
- *
5
- * Output shape:
6
- * [{ "col": value, ... }, ...]
7
- *
8
- * - Default emits a single-line array; `topt.expanded === 'on'`
9
- * pretty-prints with two-space indentation.
10
- * - SQL NULL → JSON null.
11
- * - Numeric column data types (INT2/4/8, FLOAT4/8, NUMERIC) are
12
- * parsed to JSON numbers when the string is a finite JS number.
13
- * Anything outside `Number.isFinite` (large NUMERIC, NaN, Inf) is
14
- * preserved as a string so we never silently lose precision.
15
- * - Booleans, dates, bytea, and unknown objects render as their
16
- * natural JSON forms (boolean / ISO string / hex-prefixed string /
17
- * stringified).
18
- *
19
- * Output is deterministic: column key order matches `rs.fields`; we
20
- * never reorder rows.
21
- */
22
- // PostgreSQL type OIDs for the numeric family that map cleanly to
23
- // JSON numbers. NUMERIC is included but guarded by isFinite().
24
- const NUMERIC_TYPE_OIDS = new Set([
25
- 21, // INT2
26
- 23, // INT4
27
- 20, // INT8
28
- 700, // FLOAT4
29
- 701, // FLOAT8
30
- 1700, // NUMERIC
31
- ]);
32
- export const jsonPrinter = {
33
- format: "json",
34
- printQuery(rs, opts, out) {
35
- const pretty = opts.topt.expanded === "on";
36
- const objects = rs.rows.map((row) => {
37
- const obj = {};
38
- rs.fields.forEach((field, idx) => {
39
- obj[field.name] = renderCell(row[idx], field.dataTypeID);
40
- });
41
- return obj;
42
- });
43
- const serialized = pretty
44
- ? JSON.stringify(objects, null, 2)
45
- : JSON.stringify(objects);
46
- out.write(serialized + "\n");
47
- return Promise.resolve();
48
- },
49
- };
50
- const renderCell = (cell, dataTypeID) => {
51
- if (cell === null || cell === undefined)
52
- return null;
53
- if (typeof cell === "number") {
54
- return Number.isFinite(cell) ? cell : cell.toString();
55
- }
56
- if (typeof cell === "bigint") {
57
- // Preserve as string when outside safe integer range.
58
- const asNum = Number(cell);
59
- return BigInt(asNum) === cell ? asNum : cell.toString();
60
- }
61
- if (typeof cell === "boolean")
62
- return cell;
63
- if (cell instanceof Date)
64
- return cell.toISOString();
65
- if (cell instanceof Uint8Array) {
66
- let hex = "\\x";
67
- for (const b of cell)
68
- hex += b.toString(16).padStart(2, "0");
69
- return hex;
70
- }
71
- if (typeof cell === "string") {
72
- if (NUMERIC_TYPE_OIDS.has(dataTypeID)) {
73
- const parsed = Number(cell);
74
- if (Number.isFinite(parsed) && String(parsed) === normalize(cell)) {
75
- return parsed;
76
- }
77
- }
78
- return cell;
79
- }
80
- return cell;
81
- };
82
- /**
83
- * Normalize a numeric string so the `String(parsed) === normalize(cell)`
84
- * round-trip is stable: strip a single leading `+`, drop trailing zeros
85
- * after a decimal point, drop a trailing bare decimal point, and drop a
86
- * leading zero before a multi-digit integer.
87
- */
88
- const normalize = (s) => {
89
- let v = s;
90
- if (v.startsWith("+"))
91
- v = v.slice(1);
92
- if (v.includes(".")) {
93
- v = v.replace(/0+$/, "").replace(/\.$/, "");
94
- }
95
- return v;
96
- };