neon 3.0.0 → 3.1.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 +70 -5
- package/dist/_chunks/auth_selection-DGgq6ifc.js +83 -0
- package/dist/_chunks/cmd_pipeline-CUbBO9U_.js +2818 -0
- package/dist/_chunks/credentials-MYdHdKah.js +188 -0
- package/dist/_chunks/env-NbA61JR3.js +585 -0
- package/dist/_chunks/env_services-Tz9G4JeT.js +531 -0
- package/dist/_chunks/paths-DMq0Lt7a.js +151 -0
- package/dist/_chunks/profiles-Ir29rqns.js +217 -0
- package/dist/_chunks/psql-DWH-kc69.js +2169 -0
- package/dist/_chunks/rolldown-runtime-D7D4PA-g.js +13 -0
- package/dist/_chunks/secure_file-BucZj4yQ.js +39 -0
- package/dist/analytics.js +163 -207
- package/dist/api.js +815 -758
- package/dist/auth.js +121 -141
- package/dist/auth_context.js +39 -53
- package/dist/cli.js +4 -7
- package/dist/commands/api.js +220 -250
- package/dist/commands/api_keys.js +251 -314
- package/dist/commands/auth.js +283 -328
- package/dist/commands/bootstrap.js +372 -437
- package/dist/commands/branches.js +304 -455
- package/dist/commands/bucket.js +374 -514
- package/dist/commands/checkout.js +213 -298
- package/dist/commands/config.js +573 -690
- package/dist/commands/connection_string.js +137 -165
- package/dist/commands/data_api.js +238 -260
- package/dist/commands/databases.js +67 -76
- package/dist/commands/deploy.js +31 -25
- package/dist/commands/dev.js +639 -719
- package/dist/commands/diff.js +156 -200
- package/dist/commands/env.js +255 -305
- package/dist/commands/functions.js +275 -355
- package/dist/commands/index.js +70 -65
- package/dist/commands/init.js +84 -119
- package/dist/commands/inspect.js +55 -55
- package/dist/commands/ip_allow.js +88 -120
- package/dist/commands/link.js +874 -1019
- package/dist/commands/logs.js +291 -0
- package/dist/commands/neon_auth.js +725 -933
- package/dist/commands/operations.js +34 -25
- package/dist/commands/orgs.js +28 -18
- package/dist/commands/profile.js +615 -846
- package/dist/commands/projects.js +313 -373
- package/dist/commands/psql.js +60 -58
- package/dist/commands/roles.js +55 -58
- package/dist/commands/schema_diff.js +87 -131
- package/dist/commands/set_context.js +34 -26
- package/dist/commands/snapshots.js +288 -413
- package/dist/commands/status.js +41 -37
- package/dist/commands/user.js +21 -10
- package/dist/commands/vpc_endpoints.js +85 -113
- package/dist/config.js +7 -6
- package/dist/config_format.js +50 -66
- package/dist/config_template.js +128 -157
- package/dist/context.js +183 -235
- package/dist/current_branch_fast_path.js +40 -49
- package/dist/dev/env.js +2 -446
- package/dist/dev/functions.js +54 -68
- package/dist/dev/inputs.js +46 -58
- package/dist/dev/runtime.js +135 -164
- package/dist/dev/websocket.js +766 -959
- package/dist/env.js +27 -33
- package/dist/env_file.js +118 -132
- package/dist/env_services.js +2 -51
- package/dist/errors.js +57 -68
- package/dist/functions_api.js +45 -43
- package/dist/help.js +189 -140
- package/dist/index.js +182 -257
- package/dist/init/agents.js +137 -118
- package/dist/init/auth.js +58 -68
- package/dist/init/bootstrap.js +325 -396
- package/dist/init/build_config.js +4 -2
- package/dist/init/detect_agent.js +56 -101
- package/dist/init/editors.js +35 -52
- package/dist/init/enrich_output.js +51 -66
- package/dist/init/extension.js +134 -171
- package/dist/init/inspect.js +179 -266
- package/dist/init/interactive.js +510 -622
- package/dist/init/neonctl.js +117 -168
- package/dist/init/orchestrate.js +157 -173
- package/dist/init/phases/auth.js +188 -202
- package/dist/init/phases/cleanup.js +23 -23
- package/dist/init/phases/db.js +251 -277
- package/dist/init/phases/getting_started.js +213 -223
- package/dist/init/phases/mcp.js +174 -224
- package/dist/init/phases/migrations.js +247 -248
- package/dist/init/phases/neon_auth.js +114 -133
- package/dist/init/phases/setup.js +546 -703
- package/dist/init/phases/skills.js +75 -86
- package/dist/init/phases/status.js +72 -67
- package/dist/init/resolve_context.js +102 -99
- package/dist/init/route_command.js +91 -98
- package/dist/init/skills.js +174 -218
- package/dist/init/vsix.js +77 -99
- package/dist/log.js +17 -16
- package/dist/neon_services.js +104 -129
- package/dist/parameters.gen.js +481 -471
- package/dist/pkg.js +17 -19
- package/dist/profile_keys.js +44 -47
- package/dist/psql/cli.js +44 -47
- package/dist/psql/command/cmd_cond.js +231 -406
- package/dist/psql/command/cmd_connect.js +557 -764
- package/dist/psql/command/cmd_copy.js +728 -984
- package/dist/psql/command/cmd_describe.js +1499 -1688
- package/dist/psql/command/cmd_format.js +733 -905
- package/dist/psql/command/cmd_io.js +2 -2193
- package/dist/psql/command/cmd_lo.js +297 -359
- package/dist/psql/command/cmd_meta.js +727 -878
- package/dist/psql/command/cmd_misc.js +138 -172
- package/dist/psql/command/cmd_pipeline.js +2 -1148
- package/dist/psql/command/cmd_restrict.js +119 -155
- package/dist/psql/command/cmd_show.js +529 -688
- package/dist/psql/command/dispatch.js +260 -325
- package/dist/psql/command/inputQueue.js +35 -33
- package/dist/psql/command/shared.js +49 -63
- package/dist/psql/complete/filenames.js +90 -133
- package/dist/psql/complete/index.js +59 -97
- package/dist/psql/complete/matcher.js +236 -300
- package/dist/psql/complete/psqlVars.js +218 -223
- package/dist/psql/complete/queries.js +159 -177
- package/dist/psql/complete/rules.js +1493 -2299
- package/dist/psql/core/common.js +2 -1253
- package/dist/psql/core/help.js +456 -546
- package/dist/psql/core/mainloop.js +692 -1303
- package/dist/psql/core/prompt.js +391 -408
- package/dist/psql/core/settings.js +429 -644
- package/dist/psql/core/sqlHelp.js +480 -554
- package/dist/psql/core/startup.js +2 -846
- package/dist/psql/core/syncVars.js +67 -110
- package/dist/psql/core/variables.js +156 -278
- package/dist/psql/describe/formatters.js +884 -1285
- package/dist/psql/describe/processNamePattern.js +173 -260
- package/dist/psql/describe/queries.js +1368 -2403
- package/dist/psql/describe/versionGate.js +32 -41
- package/dist/psql/index.js +2 -2030
- package/dist/psql/io/history.js +232 -271
- package/dist/psql/io/input.js +103 -108
- package/dist/psql/io/lineEditor/buffer.js +238 -319
- package/dist/psql/io/lineEditor/complete.js +135 -213
- package/dist/psql/io/lineEditor/filename.js +139 -148
- package/dist/psql/io/lineEditor/index.js +653 -870
- package/dist/psql/io/lineEditor/keymap.js +544 -702
- package/dist/psql/io/lineEditor/vt100.js +294 -341
- package/dist/psql/io/pgpass.js +158 -187
- package/dist/psql/io/pgservice.js +146 -183
- package/dist/psql/io/psqlrc.js +328 -403
- package/dist/psql/print/aligned.js +1020 -1683
- package/dist/psql/print/asciidoc.js +180 -214
- package/dist/psql/print/crosstab.js +281 -442
- package/dist/psql/print/csv.js +48 -70
- package/dist/psql/print/html.js +195 -226
- package/dist/psql/print/json.js +75 -88
- package/dist/psql/print/latex.js +291 -364
- package/dist/psql/print/pager.js +171 -242
- package/dist/psql/print/troff.js +194 -226
- package/dist/psql/print/unaligned.js +69 -95
- package/dist/psql/print/units.js +167 -169
- package/dist/psql/scanner/slash.js +428 -483
- package/dist/psql/scanner/sql.js +445 -889
- package/dist/psql/scanner/stringutils.js +309 -379
- package/dist/psql/types/index.js +8 -7
- package/dist/psql/types/scanner.js +25 -22
- package/dist/psql/wire/connection.js +2042 -2803
- package/dist/psql/wire/copy.js +84 -100
- package/dist/psql/wire/notify.js +39 -59
- package/dist/psql/wire/pipeline.js +305 -518
- package/dist/psql/wire/protocol.js +349 -417
- package/dist/psql/wire/sasl.js +180 -265
- package/dist/psql/wire/tls.js +400 -561
- package/dist/storage_api.js +115 -129
- package/dist/test_utils/fixtures.js +94 -113
- package/dist/test_utils/oauth_server.js +10 -7
- package/dist/test_utils/project_dir.js +33 -0
- package/dist/utils/ai_gateway_notice.js +131 -162
- package/dist/utils/api_enums.js +21 -28
- package/dist/utils/auth.js +10 -4
- package/dist/utils/branch_notice.js +20 -19
- package/dist/utils/branch_picker.js +83 -89
- package/dist/utils/cli_name.js +15 -12
- package/dist/utils/compute_units.js +20 -27
- package/dist/utils/config_diff.js +127 -158
- package/dist/utils/enrichers.js +95 -148
- package/dist/utils/esbuild.js +130 -189
- package/dist/utils/flags.js +35 -47
- package/dist/utils/formats.js +8 -15
- package/dist/utils/git_diff.js +69 -80
- package/dist/utils/inspect_db.js +101 -143
- package/dist/utils/inspect_queries.js +179 -142
- package/dist/utils/middlewares.js +39 -45
- package/dist/utils/openapi.js +87 -99
- package/dist/utils/package_manager.js +312 -110
- package/dist/utils/point_in_time.js +49 -53
- package/dist/utils/psql.js +89 -106
- package/dist/utils/service_picker.js +55 -58
- package/dist/utils/string.js +5 -5
- package/dist/utils/ui.js +38 -55
- package/dist/utils/write_sync.js +26 -35
- package/dist/utils/zip.js +4 -3
- package/dist/writer.js +67 -87
- package/package.json +11 -6
- package/dist/_shared/auth_selection.js +0 -86
- package/dist/_shared/credentials.js +0 -209
- package/dist/_shared/env-core/env.js +0 -558
- package/dist/_shared/env-core/reuse-secrets.js +0 -223
- package/dist/_shared/paths.js +0 -148
- package/dist/_shared/profiles.js +0 -276
- package/dist/_shared/secure_file.js +0 -43
package/dist/psql/print/csv.js
CHANGED
|
@@ -1,76 +1,54 @@
|
|
|
1
1
|
import { boolDisplayOf, renderCellValue } from "./units.js";
|
|
2
|
+
//#region src/psql/print/csv.ts
|
|
2
3
|
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
},
|
|
4
|
+
* RFC 4180 CSV printer.
|
|
5
|
+
*
|
|
6
|
+
* Mirrors print.c `print_csv_text` / `print_csv_vertical`.
|
|
7
|
+
*
|
|
8
|
+
* - Field separator defaults to `,`; honors `topt.csvFieldSep`. The
|
|
9
|
+
* separator must be a single character and may not be `"`, `\n`, or
|
|
10
|
+
* `\r` (matches the psql `\pset csv_fieldsep` check).
|
|
11
|
+
* - Line ending is always `\n` regardless of `topt.recordSep`, since
|
|
12
|
+
* `print_csv_text` writes `'\n'` literally.
|
|
13
|
+
* - Header row is printed only when `startTable && !tuplesOnly`
|
|
14
|
+
* (matches `print_csv_text` — see the `start_table && !tuples_only`
|
|
15
|
+
* guard upstream). `\pset tuples_only true` suppresses the header.
|
|
16
|
+
* - No footer in CSV.
|
|
17
|
+
* - Expanded mode (`print_csv_vertical`) prints `name,value` lines and
|
|
18
|
+
* never emits a standalone header row.
|
|
19
|
+
*
|
|
20
|
+
* Quoting rule (from `csv_print_field`): wrap in double quotes if the
|
|
21
|
+
* value contains the separator, a `"`, `\n`, or `\r`; inside quotes,
|
|
22
|
+
* double the embedded `"`. We additionally quote `\.` (psql's COPY
|
|
23
|
+
* sentinel) when the separator is `\` or `.`, matching upstream.
|
|
24
|
+
*/
|
|
25
|
+
const csvPrinter = {
|
|
26
|
+
format: "csv",
|
|
27
|
+
printQuery(rs, opts, out) {
|
|
28
|
+
const topt = opts.topt;
|
|
29
|
+
const sep = topt.csvFieldSep !== void 0 && topt.csvFieldSep !== "" ? topt.csvFieldSep : ",";
|
|
30
|
+
if (sep.length !== 1 || sep === "\"" || sep === "\n" || sep === "\r") throw new RangeError(`csv_fieldsep must be a single character other than '"', '\\n', or '\\r' (got ${JSON.stringify(sep)})`);
|
|
31
|
+
const nullPrint = opts.nullPrint !== "" ? opts.nullPrint : topt.nullPrint;
|
|
32
|
+
const expanded = topt.expanded === "on";
|
|
33
|
+
const headers = rs.fields.map((f) => f.name);
|
|
34
|
+
const boolDisplay = boolDisplayOf(topt);
|
|
35
|
+
const cells = rs.rows.map((row) => row.map((cell, i) => renderCell(cell, nullPrint, topt.numericLocale, rs.fields[i]?.dataTypeID, boolDisplay)));
|
|
36
|
+
let outBuf = "";
|
|
37
|
+
if (expanded) for (const row of cells) row.forEach((value, colIdx) => {
|
|
38
|
+
outBuf += csvField(headers[colIdx], sep) + sep + csvField(value, sep) + "\n";
|
|
39
|
+
});
|
|
40
|
+
else {
|
|
41
|
+
if (topt.startTable && !topt.tuplesOnly) outBuf += headers.map((h) => csvField(h, sep)).join(sep) + "\n";
|
|
42
|
+
for (const row of cells) outBuf += row.map((c) => csvField(c, sep)).join(sep) + "\n";
|
|
43
|
+
}
|
|
44
|
+
out.write(outBuf);
|
|
45
|
+
return Promise.resolve();
|
|
46
|
+
}
|
|
63
47
|
};
|
|
64
48
|
const renderCell = (cell, nullPrint, numericLocale, dataTypeID, boolDisplay) => renderCellValue(cell, nullPrint, numericLocale, dataTypeID, boolDisplay);
|
|
65
49
|
const csvField = (value, sep) => {
|
|
66
|
-
|
|
67
|
-
|
|
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, '""')}"`;
|
|
50
|
+
if (!(value.includes(sep) || value.includes("\"") || value.includes("\n") || value.includes("\r") || value === "\\." || sep === "\\" || sep === ".")) return value;
|
|
51
|
+
return `"${value.replace(/"/g, "\"\"")}"`;
|
|
76
52
|
};
|
|
53
|
+
//#endregion
|
|
54
|
+
export { csvPrinter };
|
package/dist/psql/print/html.js
CHANGED
|
@@ -1,240 +1,209 @@
|
|
|
1
1
|
import { boolDisplayOf, renderCellValue } from "./units.js";
|
|
2
|
+
//#region src/psql/print/html.ts
|
|
2
3
|
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
4
|
+
* HTML printer.
|
|
5
|
+
*
|
|
6
|
+
* Mirrors print.c `print_html_text` and `print_html_vertical`.
|
|
7
|
+
*
|
|
8
|
+
* Output shape (flat):
|
|
9
|
+
* <table border="1">
|
|
10
|
+
* <caption>title</caption>
|
|
11
|
+
* <tr>
|
|
12
|
+
* <th align="center">col</th>
|
|
13
|
+
* ...
|
|
14
|
+
* </tr>
|
|
15
|
+
* <tr valign="top">
|
|
16
|
+
* <td align="left">val</td>
|
|
17
|
+
* ...
|
|
18
|
+
* </tr>
|
|
19
|
+
* ...
|
|
20
|
+
* </table>
|
|
21
|
+
* <p>(N rows)<br />
|
|
22
|
+
* footer<br />
|
|
23
|
+
* </p>
|
|
24
|
+
*
|
|
25
|
+
* Output shape (expanded, `\pset expanded on`):
|
|
26
|
+
* <table border="1">
|
|
27
|
+
* <caption>title</caption>
|
|
28
|
+
*
|
|
29
|
+
* <tr><td colspan="2" align="center">Record 1</td></tr>
|
|
30
|
+
* <tr valign="top">
|
|
31
|
+
* <th>col</th>
|
|
32
|
+
* <td align="left">val</td>
|
|
33
|
+
* </tr>
|
|
34
|
+
* ...
|
|
35
|
+
* </table>
|
|
36
|
+
* <p>user footer<br />
|
|
37
|
+
* </p>
|
|
38
|
+
*
|
|
39
|
+
* - `topt.tableAttr` is appended to the opening `<table>` tag.
|
|
40
|
+
* - `topt.border` becomes the `border="..."` value.
|
|
41
|
+
* - `topt.startTable` / `stopTable` gate the prologue/epilogue, allowing
|
|
42
|
+
* chunked streaming. For this WP both default to true, so the full
|
|
43
|
+
* document is emitted in one call.
|
|
44
|
+
* - Right-align numeric columns based on the PG type-OID heuristic
|
|
45
|
+
* (`NUMERIC_OIDS`), matching how `print_aligned_text` derives the
|
|
46
|
+
* `aligns` array upstream.
|
|
47
|
+
* - Cells that are whitespace-only render ` ` so the cell still
|
|
48
|
+
* takes layout space (verbatim upstream behavior).
|
|
49
|
+
* - Expanded mode renders a `<tr><td colspan="2" align="center">Record
|
|
50
|
+
* N</td></tr>` separator before each row (or ` ` placeholder
|
|
51
|
+
* when `tuplesOnly`); it never emits the default `(N rows)` footer.
|
|
52
|
+
*/
|
|
53
|
+
const NUMERIC_OIDS = /* @__PURE__ */ new Set([
|
|
54
|
+
21,
|
|
55
|
+
23,
|
|
56
|
+
20,
|
|
57
|
+
700,
|
|
58
|
+
701,
|
|
59
|
+
1700,
|
|
60
|
+
1186
|
|
61
|
+
]);
|
|
62
|
+
const htmlPrinter = {
|
|
63
|
+
format: "html",
|
|
64
|
+
printQuery(rs, opts, out) {
|
|
65
|
+
if (opts.topt.expanded === "on") return printExpanded(rs, opts, out);
|
|
66
|
+
return printFlat(rs, opts, out);
|
|
67
|
+
}
|
|
63
68
|
};
|
|
64
69
|
const printFlat = (rs, opts, out) => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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();
|
|
70
|
+
const topt = opts.topt;
|
|
71
|
+
const tuplesOnly = topt.tuplesOnly;
|
|
72
|
+
const startTable = topt.startTable;
|
|
73
|
+
const stopTable = topt.stopTable;
|
|
74
|
+
const nullPrint = opts.nullPrint !== "" ? opts.nullPrint : topt.nullPrint;
|
|
75
|
+
const title = opts.title ?? topt.title;
|
|
76
|
+
const footers = opts.footers ?? topt.footers;
|
|
77
|
+
const headers = rs.fields.map((f) => f.name);
|
|
78
|
+
const aligns = rs.fields.map((f) => NUMERIC_OIDS.has(f.dataTypeID) ? "right" : "left");
|
|
79
|
+
const boolDisplay = boolDisplayOf(topt);
|
|
80
|
+
const cells = rs.rows.map((row) => row.map((cell, i) => renderCell(cell, nullPrint, topt.numericLocale, rs.fields[i]?.dataTypeID, boolDisplay)));
|
|
81
|
+
let buf = "";
|
|
82
|
+
if (startTable) {
|
|
83
|
+
buf += `<table border="${String(topt.border)}"`;
|
|
84
|
+
if (topt.tableAttr) buf += ` ${topt.tableAttr}`;
|
|
85
|
+
buf += ">\n";
|
|
86
|
+
if (!tuplesOnly && title) buf += " <caption>" + escapeHtml(title) + "</caption>\n";
|
|
87
|
+
if (!tuplesOnly) {
|
|
88
|
+
buf += " <tr>\n";
|
|
89
|
+
for (const h of headers) buf += " <th align=\"center\">" + escapeHtml(h) + "</th>\n";
|
|
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)) buf += " ";
|
|
98
|
+
else buf += escapeHtml(value);
|
|
99
|
+
buf += "</td>\n";
|
|
100
|
+
});
|
|
101
|
+
buf += " </tr>\n";
|
|
102
|
+
}
|
|
103
|
+
if (stopTable) {
|
|
104
|
+
buf += "</table>\n";
|
|
105
|
+
if (!tuplesOnly) {
|
|
106
|
+
const effective = effectiveFooters(rs, topt, footers);
|
|
107
|
+
if (effective.length > 0) {
|
|
108
|
+
buf += "<p>";
|
|
109
|
+
for (const f of effective) buf += escapeHtml(f) + "<br />\n";
|
|
110
|
+
buf += "</p>";
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
buf += "\n";
|
|
114
|
+
}
|
|
115
|
+
out.write(buf);
|
|
116
|
+
return Promise.resolve();
|
|
126
117
|
};
|
|
127
118
|
const printExpanded = (rs, opts, out) => {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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();
|
|
119
|
+
const topt = opts.topt;
|
|
120
|
+
const tuplesOnly = topt.tuplesOnly;
|
|
121
|
+
const startTable = topt.startTable;
|
|
122
|
+
const stopTable = topt.stopTable;
|
|
123
|
+
const nullPrint = opts.nullPrint !== "" ? opts.nullPrint : topt.nullPrint;
|
|
124
|
+
const title = opts.title ?? topt.title;
|
|
125
|
+
const footers = opts.footers ?? topt.footers;
|
|
126
|
+
const headers = rs.fields.map((f) => f.name);
|
|
127
|
+
const aligns = rs.fields.map((f) => NUMERIC_OIDS.has(f.dataTypeID) ? "right" : "left");
|
|
128
|
+
const boolDisplay = boolDisplayOf(topt);
|
|
129
|
+
const cells = rs.rows.map((row) => row.map((cell, i) => renderCell(cell, nullPrint, topt.numericLocale, rs.fields[i]?.dataTypeID, boolDisplay)));
|
|
130
|
+
let buf = "";
|
|
131
|
+
if (startTable) {
|
|
132
|
+
buf += `<table border="${String(topt.border)}"`;
|
|
133
|
+
if (topt.tableAttr) buf += ` ${topt.tableAttr}`;
|
|
134
|
+
buf += ">\n";
|
|
135
|
+
if (!tuplesOnly && title) buf += " <caption>" + escapeHtml(title) + "</caption>\n";
|
|
136
|
+
}
|
|
137
|
+
let record = topt.prior + 1;
|
|
138
|
+
cells.forEach((row) => {
|
|
139
|
+
if (!tuplesOnly) {
|
|
140
|
+
buf += `\n <tr><td colspan="2" align="center">Record ${String(record)}</td></tr>\n`;
|
|
141
|
+
record += 1;
|
|
142
|
+
} else buf += "\n <tr><td colspan=\"2\"> </td></tr>\n";
|
|
143
|
+
row.forEach((value, idx) => {
|
|
144
|
+
buf += " <tr valign=\"top\">\n";
|
|
145
|
+
buf += " <th>" + escapeHtml(headers[idx]) + "</th>\n";
|
|
146
|
+
buf += ` <td align="${aligns[idx]}">`;
|
|
147
|
+
if (isWhitespaceOnly(value)) buf += " ";
|
|
148
|
+
else buf += escapeHtml(value);
|
|
149
|
+
buf += "</td>\n";
|
|
150
|
+
buf += " </tr>\n";
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
if (stopTable) {
|
|
154
|
+
buf += "</table>\n";
|
|
155
|
+
if (!tuplesOnly && footers && footers.length > 0) {
|
|
156
|
+
buf += "<p>";
|
|
157
|
+
for (const f of footers) buf += escapeHtml(f) + "<br />\n";
|
|
158
|
+
buf += "</p>";
|
|
159
|
+
}
|
|
160
|
+
buf += "\n";
|
|
161
|
+
}
|
|
162
|
+
out.write(buf);
|
|
163
|
+
return Promise.resolve();
|
|
187
164
|
};
|
|
188
165
|
const effectiveFooters = (rs, topt, footers) => {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
return [];
|
|
166
|
+
if (footers && footers.length > 0) return footers;
|
|
167
|
+
if (topt.defaultFooter) {
|
|
168
|
+
const n = rs.rows.length;
|
|
169
|
+
return [`(${String(n)} ${n === 1 ? "row" : "rows"})`];
|
|
170
|
+
}
|
|
171
|
+
return [];
|
|
196
172
|
};
|
|
197
173
|
const isWhitespaceOnly = (s) => {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
if (ch !== " " && ch !== "\t")
|
|
202
|
-
return false;
|
|
203
|
-
}
|
|
204
|
-
return true;
|
|
174
|
+
if (s.length === 0) return true;
|
|
175
|
+
for (const ch of s) if (ch !== " " && ch !== " ") return false;
|
|
176
|
+
return true;
|
|
205
177
|
};
|
|
206
178
|
const escapeHtml = (input) => {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
}
|
|
235
|
-
if (ch !== " ")
|
|
236
|
-
leadingSpace = false;
|
|
237
|
-
}
|
|
238
|
-
return out;
|
|
179
|
+
let out = "";
|
|
180
|
+
let leadingSpace = true;
|
|
181
|
+
for (const ch of input) {
|
|
182
|
+
switch (ch) {
|
|
183
|
+
case "&":
|
|
184
|
+
out += "&";
|
|
185
|
+
break;
|
|
186
|
+
case "<":
|
|
187
|
+
out += "<";
|
|
188
|
+
break;
|
|
189
|
+
case ">":
|
|
190
|
+
out += ">";
|
|
191
|
+
break;
|
|
192
|
+
case "\"":
|
|
193
|
+
out += """;
|
|
194
|
+
break;
|
|
195
|
+
case "\n":
|
|
196
|
+
out += "<br />\n";
|
|
197
|
+
break;
|
|
198
|
+
case " ":
|
|
199
|
+
out += leadingSpace ? " " : " ";
|
|
200
|
+
break;
|
|
201
|
+
default: out += ch;
|
|
202
|
+
}
|
|
203
|
+
if (ch !== " ") leadingSpace = false;
|
|
204
|
+
}
|
|
205
|
+
return out;
|
|
239
206
|
};
|
|
240
207
|
const renderCell = (cell, nullPrint, numericLocale, dataTypeID, boolDisplay) => renderCellValue(cell, nullPrint, numericLocale, dataTypeID, boolDisplay);
|
|
208
|
+
//#endregion
|
|
209
|
+
export { htmlPrinter };
|