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/core/prompt.js
CHANGED
|
@@ -1,439 +1,422 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* psql Prompt renderer.
|
|
3
|
-
*
|
|
4
|
-
* TypeScript port of `get_prompt()` from `src/bin/psql/prompt.c`. Walks the
|
|
5
|
-
* prompt template (PROMPT1/PROMPT2/PROMPT3) and expands `%`-escapes against
|
|
6
|
-
* a `PromptContext` snapshot.
|
|
7
|
-
*
|
|
8
|
-
* Differences from upstream:
|
|
9
|
-
*
|
|
10
|
-
* - Upstream takes `promptStatus_t status, ConditionalStack cstack` and
|
|
11
|
-
* pulls everything else off `pset`. We accept an explicit `PromptContext`
|
|
12
|
-
* so the renderer is a pure function (easier to test, no module-level
|
|
13
|
-
* state).
|
|
14
|
-
* - `%s` ("service name") is provided from `settings.vars.SERVICE` per
|
|
15
|
-
* upstream. We keep that behaviour. The WP-07 spec mentions a "current
|
|
16
|
-
* timestamp" semantic for `%s`/`%S` — that is NOT what psql does today,
|
|
17
|
-
* so we follow upstream rather than the spec note.
|
|
18
|
-
* - `%S` is `search_path` from the connection's GUC report (upstream uses
|
|
19
|
-
* `PQparameterStatus(pset.db, "search_path")`). With no Connection yet,
|
|
20
|
-
* we fall back to `?`.
|
|
21
|
-
* - `%#` checks the `IS_SUPERUSER` psql variable (set by upstream's
|
|
22
|
-
* `is_superuser()` via the connect-time hook). Without a Connection we
|
|
23
|
-
* default to non-superuser (`>`).
|
|
24
|
-
* - `%P` outputs `off`/`on`/`abort` to match upstream's literal strings.
|
|
25
|
-
* - `%i` outputs `primary` / `standby` / `?` (upstream reads the GUC
|
|
26
|
-
* `in_hot_standby`); when no connection, `?`. The WP-07 spec asked for
|
|
27
|
-
* "if-state from CondStack" — that conflicts with upstream `%i` and we
|
|
28
|
-
* follow upstream. `%?` remains a no-op marker in upstream too.
|
|
29
|
-
* - `%[`/`%]` are upstream's readline non-printing markers. We strip them
|
|
30
|
-
* (emit nothing) for now; a future WP wiring readline integration can
|
|
31
|
-
* re-introduce them.
|
|
32
|
-
* - Backtick command interpolation (`%`\``cmd`\``) is executed synchronously
|
|
33
|
-
* via `child_process.execSync` on `sh -c <cmd>`. Output is substituted
|
|
34
|
-
* verbatim minus one trailing newline. Errors print to stderr and yield
|
|
35
|
-
* an empty substitution — matching upstream's `get_prompt`, which re-runs
|
|
36
|
-
* the command on every render rather than caching.
|
|
37
|
-
* - Unknown `%X` escapes pass through as literal `X` (the upstream
|
|
38
|
-
* `default:` branch). `%w` width is computed from PROMPT1 when present
|
|
39
|
-
* and consumed by a subsequent PROMPT2 render via the optional
|
|
40
|
-
* `lastPrompt1Width` field on the context.
|
|
41
|
-
*/
|
|
42
1
|
import { execSync } from "node:child_process";
|
|
2
|
+
//#region src/psql/core/prompt.ts
|
|
43
3
|
/**
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
4
|
+
* psql Prompt renderer.
|
|
5
|
+
*
|
|
6
|
+
* TypeScript port of `get_prompt()` from `src/bin/psql/prompt.c`. Walks the
|
|
7
|
+
* prompt template (PROMPT1/PROMPT2/PROMPT3) and expands `%`-escapes against
|
|
8
|
+
* a `PromptContext` snapshot.
|
|
9
|
+
*
|
|
10
|
+
* Differences from upstream:
|
|
11
|
+
*
|
|
12
|
+
* - Upstream takes `promptStatus_t status, ConditionalStack cstack` and
|
|
13
|
+
* pulls everything else off `pset`. We accept an explicit `PromptContext`
|
|
14
|
+
* so the renderer is a pure function (easier to test, no module-level
|
|
15
|
+
* state).
|
|
16
|
+
* - `%s` ("service name") is provided from `settings.vars.SERVICE` per
|
|
17
|
+
* upstream. We keep that behaviour. The WP-07 spec mentions a "current
|
|
18
|
+
* timestamp" semantic for `%s`/`%S` — that is NOT what psql does today,
|
|
19
|
+
* so we follow upstream rather than the spec note.
|
|
20
|
+
* - `%S` is `search_path` from the connection's GUC report (upstream uses
|
|
21
|
+
* `PQparameterStatus(pset.db, "search_path")`). With no Connection yet,
|
|
22
|
+
* we fall back to `?`.
|
|
23
|
+
* - `%#` checks the `IS_SUPERUSER` psql variable (set by upstream's
|
|
24
|
+
* `is_superuser()` via the connect-time hook). Without a Connection we
|
|
25
|
+
* default to non-superuser (`>`).
|
|
26
|
+
* - `%P` outputs `off`/`on`/`abort` to match upstream's literal strings.
|
|
27
|
+
* - `%i` outputs `primary` / `standby` / `?` (upstream reads the GUC
|
|
28
|
+
* `in_hot_standby`); when no connection, `?`. The WP-07 spec asked for
|
|
29
|
+
* "if-state from CondStack" — that conflicts with upstream `%i` and we
|
|
30
|
+
* follow upstream. `%?` remains a no-op marker in upstream too.
|
|
31
|
+
* - `%[`/`%]` are upstream's readline non-printing markers. We strip them
|
|
32
|
+
* (emit nothing) for now; a future WP wiring readline integration can
|
|
33
|
+
* re-introduce them.
|
|
34
|
+
* - Backtick command interpolation (`%`\``cmd`\``) is executed synchronously
|
|
35
|
+
* via `child_process.execSync` on `sh -c <cmd>`. Output is substituted
|
|
36
|
+
* verbatim minus one trailing newline. Errors print to stderr and yield
|
|
37
|
+
* an empty substitution — matching upstream's `get_prompt`, which re-runs
|
|
38
|
+
* the command on every render rather than caching.
|
|
39
|
+
* - Unknown `%X` escapes pass through as literal `X` (the upstream
|
|
40
|
+
* `default:` branch). `%w` width is computed from PROMPT1 when present
|
|
41
|
+
* and consumed by a subsequent PROMPT2 render via the optional
|
|
42
|
+
* `lastPrompt1Width` field on the context.
|
|
43
|
+
*/
|
|
44
|
+
/**
|
|
45
|
+
* Test seam for the prompt-level backtick executor. The default
|
|
46
|
+
* implementation calls `execSync(cmd, { shell: '/bin/sh' })`; tests can
|
|
47
|
+
* replace `.current` with a synchronous mock to avoid actually spawning
|
|
48
|
+
* a child. Same pattern as `BACKTICK_EXECUTOR` in `scanner/slash.ts`.
|
|
49
|
+
*/
|
|
50
|
+
const PROMPT_BACKTICK_EXECUTOR = { current: (cmd) => execSync(cmd, {
|
|
51
|
+
shell: "/bin/sh",
|
|
52
|
+
encoding: "utf8",
|
|
53
|
+
stdio: [
|
|
54
|
+
"ignore",
|
|
55
|
+
"pipe",
|
|
56
|
+
"inherit"
|
|
57
|
+
],
|
|
58
|
+
maxBuffer: 65536
|
|
59
|
+
}) };
|
|
59
60
|
/**
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
* Run a single backtick command and return its stdout, with one trailing
|
|
62
|
+
* newline trimmed. On failure (non-zero exit / spawn error) print the
|
|
63
|
+
* error to stderr and return the empty string so the prompt still renders.
|
|
64
|
+
*/
|
|
64
65
|
const runPromptBacktick = (cmd) => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
return "";
|
|
75
|
-
}
|
|
66
|
+
if (cmd.length === 0) return "";
|
|
67
|
+
try {
|
|
68
|
+
const out = PROMPT_BACKTICK_EXECUTOR.current(cmd);
|
|
69
|
+
return out.endsWith("\n") ? out.slice(0, -1) : out;
|
|
70
|
+
} catch (err) {
|
|
71
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
72
|
+
process.stderr.write(`psql: error: \\!: ${cmd}: ${msg}\n`);
|
|
73
|
+
return "";
|
|
74
|
+
}
|
|
76
75
|
};
|
|
77
76
|
/**
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const isPrompt1 = name === "PROMPT1";
|
|
88
|
-
const out = renderPrompt(template, ctx);
|
|
89
|
-
if (isPrompt1) {
|
|
90
|
-
// Stash the visible width on the context so a subsequent PROMPT2 render
|
|
91
|
-
// sharing this context object can line up with `%w`.
|
|
92
|
-
ctx.lastPrompt1Width = visibleWidth(out);
|
|
93
|
-
}
|
|
94
|
-
return out;
|
|
77
|
+
* Render a prompt by name. Selects the template from
|
|
78
|
+
* `settings.prompt{1,2,3}` and delegates to the escape-walking core.
|
|
79
|
+
*/
|
|
80
|
+
const renderPromptByName = (name, ctx) => {
|
|
81
|
+
const template = name === "PROMPT1" ? ctx.settings.prompt1 : name === "PROMPT2" ? ctx.settings.prompt2 : ctx.settings.prompt3;
|
|
82
|
+
const isPrompt1 = name === "PROMPT1";
|
|
83
|
+
const out = renderPrompt(template, ctx);
|
|
84
|
+
if (isPrompt1) ctx.lastPrompt1Width = visibleWidth(out);
|
|
85
|
+
return out;
|
|
95
86
|
};
|
|
96
87
|
/**
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
const { text, consumed } = expandEscape(escape, template, i, ctx);
|
|
118
|
-
out += text;
|
|
119
|
-
i += consumed;
|
|
120
|
-
}
|
|
121
|
-
return out;
|
|
88
|
+
* Render an arbitrary prompt template. Pure function over `(template, ctx)`.
|
|
89
|
+
*/
|
|
90
|
+
const renderPrompt = (template, ctx) => {
|
|
91
|
+
let out = "";
|
|
92
|
+
let i = 0;
|
|
93
|
+
while (i < template.length) {
|
|
94
|
+
const ch = template[i];
|
|
95
|
+
if (ch !== "%") {
|
|
96
|
+
out += ch;
|
|
97
|
+
i += 1;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
i += 1;
|
|
101
|
+
if (i >= template.length) break;
|
|
102
|
+
const escape = template[i];
|
|
103
|
+
const { text, consumed } = expandEscape(escape, template, i, ctx);
|
|
104
|
+
out += text;
|
|
105
|
+
i += consumed;
|
|
106
|
+
}
|
|
107
|
+
return out;
|
|
122
108
|
};
|
|
123
|
-
const expandEscape = (escape, template,
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
109
|
+
const expandEscape = (escape, template, start, ctx) => {
|
|
110
|
+
const { settings } = ctx;
|
|
111
|
+
const db = settings.db;
|
|
112
|
+
switch (escape) {
|
|
113
|
+
case "%": return {
|
|
114
|
+
text: "%",
|
|
115
|
+
consumed: 1
|
|
116
|
+
};
|
|
117
|
+
case "/": return {
|
|
118
|
+
text: db ? currentDatabase(ctx) : "",
|
|
119
|
+
consumed: 1
|
|
120
|
+
};
|
|
121
|
+
case "~": {
|
|
122
|
+
if (!db) return {
|
|
123
|
+
text: "",
|
|
124
|
+
consumed: 1
|
|
125
|
+
};
|
|
126
|
+
const cdb = currentDatabase(ctx);
|
|
127
|
+
const user = currentUser(ctx);
|
|
128
|
+
const pgdb = process.env.PGDATABASE;
|
|
129
|
+
if (cdb === user || pgdb !== void 0 && pgdb === cdb) return {
|
|
130
|
+
text: "~",
|
|
131
|
+
consumed: 1
|
|
132
|
+
};
|
|
133
|
+
return {
|
|
134
|
+
text: cdb,
|
|
135
|
+
consumed: 1
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
case "M":
|
|
139
|
+
case "m": return {
|
|
140
|
+
text: db ? hostString(ctx, escape === "m") : "",
|
|
141
|
+
consumed: 1
|
|
142
|
+
};
|
|
143
|
+
case ">": return {
|
|
144
|
+
text: db ? portString(ctx) : "",
|
|
145
|
+
consumed: 1
|
|
146
|
+
};
|
|
147
|
+
case "n": return {
|
|
148
|
+
text: db ? currentUser(ctx) : "",
|
|
149
|
+
consumed: 1
|
|
150
|
+
};
|
|
151
|
+
case "p": {
|
|
152
|
+
if (!db) return {
|
|
153
|
+
text: "",
|
|
154
|
+
consumed: 1
|
|
155
|
+
};
|
|
156
|
+
const pid = backendPid(ctx);
|
|
157
|
+
return {
|
|
158
|
+
text: pid !== null ? String(pid) : "",
|
|
159
|
+
consumed: 1
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
case "P": {
|
|
163
|
+
if (!db) return {
|
|
164
|
+
text: "",
|
|
165
|
+
consumed: 1
|
|
166
|
+
};
|
|
167
|
+
const state = ctx.pipelineState ?? "off";
|
|
168
|
+
return {
|
|
169
|
+
text: state === "on" ? "on" : state === "aborted" ? "abort" : "off",
|
|
170
|
+
consumed: 1
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
case "i": {
|
|
174
|
+
if (!db) return {
|
|
175
|
+
text: "",
|
|
176
|
+
consumed: 1
|
|
177
|
+
};
|
|
178
|
+
const hs = parameterStatus(ctx, "in_hot_standby");
|
|
179
|
+
if (hs === void 0) return {
|
|
180
|
+
text: "?",
|
|
181
|
+
consumed: 1
|
|
182
|
+
};
|
|
183
|
+
return {
|
|
184
|
+
text: hs === "on" ? "standby" : "primary",
|
|
185
|
+
consumed: 1
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
case "s": return {
|
|
189
|
+
text: settings.vars.get("SERVICE") ?? "",
|
|
190
|
+
consumed: 1
|
|
191
|
+
};
|
|
192
|
+
case "S":
|
|
193
|
+
if (!db) return {
|
|
194
|
+
text: "?",
|
|
195
|
+
consumed: 1
|
|
196
|
+
};
|
|
197
|
+
return {
|
|
198
|
+
text: parameterStatus(ctx, "search_path") ?? "?",
|
|
199
|
+
consumed: 1
|
|
200
|
+
};
|
|
201
|
+
case "l": return {
|
|
202
|
+
text: String(ctx.lineNumber),
|
|
203
|
+
consumed: 1
|
|
204
|
+
};
|
|
205
|
+
case "w": {
|
|
206
|
+
const width = Math.max(0, ctx.lastPrompt1Width ?? 0);
|
|
207
|
+
return {
|
|
208
|
+
text: db ? " ".repeat(width) : "",
|
|
209
|
+
consumed: 1
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
case "a": return {
|
|
213
|
+
text: "\x07",
|
|
214
|
+
consumed: 1
|
|
215
|
+
};
|
|
216
|
+
case "R": return {
|
|
217
|
+
text: expandR(ctx),
|
|
218
|
+
consumed: 1
|
|
219
|
+
};
|
|
220
|
+
case "x": {
|
|
221
|
+
if (!db) return {
|
|
222
|
+
text: "?",
|
|
223
|
+
consumed: 1
|
|
224
|
+
};
|
|
225
|
+
const tx = ctx.inTransaction ?? "idle";
|
|
226
|
+
if (tx === "in-block") return {
|
|
227
|
+
text: "*",
|
|
228
|
+
consumed: 1
|
|
229
|
+
};
|
|
230
|
+
if (tx === "failed") return {
|
|
231
|
+
text: "!",
|
|
232
|
+
consumed: 1
|
|
233
|
+
};
|
|
234
|
+
if (tx === "unknown") return {
|
|
235
|
+
text: "?",
|
|
236
|
+
consumed: 1
|
|
237
|
+
};
|
|
238
|
+
return {
|
|
239
|
+
text: "",
|
|
240
|
+
consumed: 1
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
case "#": return {
|
|
244
|
+
text: settings.vars.get("IS_SUPERUSER") === "on" ? "#" : ">",
|
|
245
|
+
consumed: 1
|
|
246
|
+
};
|
|
247
|
+
case "?": return {
|
|
248
|
+
text: "",
|
|
249
|
+
consumed: 1
|
|
250
|
+
};
|
|
251
|
+
case "[":
|
|
252
|
+
case "]": return {
|
|
253
|
+
text: "",
|
|
254
|
+
consumed: 1
|
|
255
|
+
};
|
|
256
|
+
case "`": {
|
|
257
|
+
const close = template.indexOf("`", start + 1);
|
|
258
|
+
if (close === -1) return {
|
|
259
|
+
text: "",
|
|
260
|
+
consumed: template.length - start
|
|
261
|
+
};
|
|
262
|
+
const body = template.slice(start + 1, close);
|
|
263
|
+
return {
|
|
264
|
+
text: runPromptBacktick(body),
|
|
265
|
+
consumed: close - start + 1
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
case ":": {
|
|
269
|
+
const close = template.indexOf(":", start + 1);
|
|
270
|
+
if (close === -1) return {
|
|
271
|
+
text: "",
|
|
272
|
+
consumed: template.length - start
|
|
273
|
+
};
|
|
274
|
+
const name = template.slice(start + 1, close);
|
|
275
|
+
return {
|
|
276
|
+
text: settings.vars.get(name) ?? "",
|
|
277
|
+
consumed: close - start + 1
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
case "0":
|
|
281
|
+
case "1":
|
|
282
|
+
case "2":
|
|
283
|
+
case "3":
|
|
284
|
+
case "4":
|
|
285
|
+
case "5":
|
|
286
|
+
case "6":
|
|
287
|
+
case "7": {
|
|
288
|
+
let consumed = 1;
|
|
289
|
+
let body = escape;
|
|
290
|
+
while (consumed < 3 && start + consumed < template.length) {
|
|
291
|
+
const next = template[start + consumed];
|
|
292
|
+
if (next >= "0" && next <= "7") {
|
|
293
|
+
body += next;
|
|
294
|
+
consumed += 1;
|
|
295
|
+
} else break;
|
|
296
|
+
}
|
|
297
|
+
const byte = parseInt(body, 8);
|
|
298
|
+
return {
|
|
299
|
+
text: String.fromCharCode(byte),
|
|
300
|
+
consumed
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
default: return {
|
|
304
|
+
text: escape,
|
|
305
|
+
consumed: 1
|
|
306
|
+
};
|
|
307
|
+
}
|
|
290
308
|
};
|
|
291
309
|
/**
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
310
|
+
* Expand `%R`. PROMPT1 reflects the connection / cond-stack / singleline
|
|
311
|
+
* state. PROMPT2 reflects the scanner's promptStatus — upstream renders a
|
|
312
|
+
* mnemonic character for *why* the parser is still hanging on for more
|
|
313
|
+
* input:
|
|
314
|
+
*
|
|
315
|
+
* - `-` plain continuation (default)
|
|
316
|
+
* - `'` inside a single-quoted string
|
|
317
|
+
* - `"` inside a double-quoted identifier
|
|
318
|
+
* - `$` inside a dollar-quoted block
|
|
319
|
+
* - `*` inside a block comment
|
|
320
|
+
* - `(` inside unmatched parens
|
|
321
|
+
*
|
|
322
|
+
* PROMPT3 is the COPY indicator; upstream falls into the `default` branch
|
|
323
|
+
* and emits nothing — we do the same.
|
|
324
|
+
*/
|
|
307
325
|
const expandR = (ctx) => {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
return '"';
|
|
325
|
-
case "continue-dollar":
|
|
326
|
-
return "$";
|
|
327
|
-
case "comment":
|
|
328
|
-
return "*";
|
|
329
|
-
case "paren":
|
|
330
|
-
return "(";
|
|
331
|
-
case "copy":
|
|
332
|
-
// PROMPT3 / COPY path — upstream emits nothing for %R here.
|
|
333
|
-
return "";
|
|
334
|
-
default:
|
|
335
|
-
return "";
|
|
336
|
-
}
|
|
326
|
+
const { promptStatus, cond, settings } = ctx;
|
|
327
|
+
switch (promptStatus) {
|
|
328
|
+
case "ready":
|
|
329
|
+
if (!isConditionalActive(cond)) return "@";
|
|
330
|
+
if (!settings.db) return "!";
|
|
331
|
+
if (!settings.singleline) return "=";
|
|
332
|
+
return "^";
|
|
333
|
+
case "continue": return "-";
|
|
334
|
+
case "continue-quote": return "'";
|
|
335
|
+
case "continue-dquote": return "\"";
|
|
336
|
+
case "continue-dollar": return "$";
|
|
337
|
+
case "comment": return "*";
|
|
338
|
+
case "paren": return "(";
|
|
339
|
+
case "copy": return "";
|
|
340
|
+
default: return "";
|
|
341
|
+
}
|
|
337
342
|
};
|
|
338
343
|
/**
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
+
* Return `false` if the current `\if` branch is non-active (we're inside a
|
|
345
|
+
* skipped block). Mirrors upstream `conditional_active`. Inactive states are
|
|
346
|
+
* `false`, `else-false`, and `ignored`; everything else (including the
|
|
347
|
+
* sentinel `none` for "no \if active") is treated as active.
|
|
348
|
+
*/
|
|
344
349
|
const isConditionalActive = (cond) => {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
+
const top = cond.top();
|
|
351
|
+
if (!top) return true;
|
|
352
|
+
return ![
|
|
353
|
+
"false",
|
|
354
|
+
"else-false",
|
|
355
|
+
"ignored"
|
|
356
|
+
].includes(top.state);
|
|
350
357
|
};
|
|
351
358
|
/**
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
359
|
+
* Visible width of a rendered prompt — used to seed `%w` on PROMPT2. We
|
|
360
|
+
* subtract ANSI escape sequences and the unicode width is approximated by
|
|
361
|
+
* code-point count (full Unicode width tables live in the printer WP).
|
|
362
|
+
*/
|
|
356
363
|
const visibleWidth = (s) => {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
const lastNl = stripped.lastIndexOf("\n");
|
|
361
|
-
const tail = lastNl === -1 ? stripped : stripped.slice(lastNl + 1);
|
|
362
|
-
// Code-unit count — good enough for ASCII prompts; CJK / surrogate-pair
|
|
363
|
-
// width handling is a printer-WP concern.
|
|
364
|
-
return tail.length;
|
|
364
|
+
const stripped = s.replace(/\x1b\[[0-9;]*[A-Za-z]/g, "");
|
|
365
|
+
const lastNl = stripped.lastIndexOf("\n");
|
|
366
|
+
return (lastNl === -1 ? stripped : stripped.slice(lastNl + 1)).length;
|
|
365
367
|
};
|
|
366
368
|
const currentDatabase = (ctx) => {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
const meta = db;
|
|
373
|
-
if (typeof meta.database === "string" && meta.database.length > 0) {
|
|
374
|
-
return meta.database;
|
|
375
|
-
}
|
|
376
|
-
return parameterStatus(ctx, "database") ?? "";
|
|
369
|
+
const db = ctx.settings.db;
|
|
370
|
+
if (!db) return "";
|
|
371
|
+
const meta = db;
|
|
372
|
+
if (typeof meta.database === "string" && meta.database.length > 0) return meta.database;
|
|
373
|
+
return parameterStatus(ctx, "database") ?? "";
|
|
377
374
|
};
|
|
378
375
|
const currentUser = (ctx) => {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
return meta.user;
|
|
385
|
-
}
|
|
386
|
-
return parameterStatus(ctx, "session_authorization") ?? "";
|
|
376
|
+
const db = ctx.settings.db;
|
|
377
|
+
if (!db) return "";
|
|
378
|
+
const meta = db;
|
|
379
|
+
if (typeof meta.user === "string" && meta.user.length > 0) return meta.user;
|
|
380
|
+
return parameterStatus(ctx, "session_authorization") ?? "";
|
|
387
381
|
};
|
|
388
382
|
const hostString = (ctx, short) => {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
return dot === -1 ? host : host.slice(0, dot);
|
|
403
|
-
}
|
|
404
|
-
return host;
|
|
383
|
+
const db = ctx.settings.db;
|
|
384
|
+
if (!db) return "";
|
|
385
|
+
const meta = db;
|
|
386
|
+
const host = typeof meta.host === "string" ? meta.host : "";
|
|
387
|
+
if (host.length === 0 || host.startsWith("/")) {
|
|
388
|
+
if (host.length === 0 || short) return "[local]";
|
|
389
|
+
return `[local:${host}]`;
|
|
390
|
+
}
|
|
391
|
+
if (short) {
|
|
392
|
+
const dot = host.indexOf(".");
|
|
393
|
+
return dot === -1 ? host : host.slice(0, dot);
|
|
394
|
+
}
|
|
395
|
+
return host;
|
|
405
396
|
};
|
|
406
397
|
const portString = (ctx) => {
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
}
|
|
414
|
-
if (typeof meta.port === "string" && meta.port.length > 0) {
|
|
415
|
-
return meta.port;
|
|
416
|
-
}
|
|
417
|
-
return "";
|
|
398
|
+
const db = ctx.settings.db;
|
|
399
|
+
if (!db) return "";
|
|
400
|
+
const meta = db;
|
|
401
|
+
if (typeof meta.port === "number" && Number.isFinite(meta.port)) return String(meta.port);
|
|
402
|
+
if (typeof meta.port === "string" && meta.port.length > 0) return meta.port;
|
|
403
|
+
return "";
|
|
418
404
|
};
|
|
419
405
|
const backendPid = (ctx) => {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
return meta.pid;
|
|
426
|
-
}
|
|
427
|
-
return null;
|
|
406
|
+
const db = ctx.settings.db;
|
|
407
|
+
if (!db) return null;
|
|
408
|
+
const meta = db;
|
|
409
|
+
if (typeof meta.pid === "number" && Number.isFinite(meta.pid)) return meta.pid;
|
|
410
|
+
return null;
|
|
428
411
|
};
|
|
429
412
|
const parameterStatus = (ctx, name) => {
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
return undefined;
|
|
438
|
-
}
|
|
413
|
+
const db = ctx.settings.db;
|
|
414
|
+
if (!db) return void 0;
|
|
415
|
+
try {
|
|
416
|
+
return db.parameterStatus(name);
|
|
417
|
+
} catch {
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
439
420
|
};
|
|
421
|
+
//#endregion
|
|
422
|
+
export { PROMPT_BACKTICK_EXECUTOR, renderPrompt, renderPromptByName };
|