neon 2.47.0 → 3.1.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.
- package/README.md +54 -0
- package/dist/_shared/auth_selection.js +76 -79
- package/dist/_shared/credentials.js +166 -187
- package/dist/_shared/env-core/env.js +395 -0
- package/dist/_shared/env-core/reuse-secrets.js +179 -0
- package/dist/_shared/paths.js +129 -126
- package/dist/_shared/profiles.js +192 -242
- package/dist/_shared/secure_file.js +36 -38
- package/dist/_virtual/_rolldown/runtime.js +13 -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 +575 -658
- 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 +642 -681
- package/dist/commands/diff.js +156 -200
- package/dist/commands/env.js +243 -303
- package/dist/commands/functions.js +275 -341
- 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 +614 -845
- 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 +313 -394
- package/dist/dev/functions.js +54 -64
- 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 +36 -38
- 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 +727 -983
- 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 +1293 -2082
- 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 +547 -1099
- package/dist/psql/command/cmd_restrict.js +119 -155
- package/dist/psql/command/cmd_show.js +529 -688
- package/dist/psql/command/dispatch.js +261 -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 +762 -1180
- package/dist/psql/core/help.js +456 -546
- package/dist/psql/core/mainloop.js +692 -1302
- 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 +626 -815
- 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 +1414 -1927
- 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 +2 -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 +133 -147
- 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 +37 -44
- 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 +9 -7
package/dist/init/vsix.js
CHANGED
|
@@ -1,111 +1,89 @@
|
|
|
1
|
-
|
|
2
|
-
* Shared VSIX download utilities for extension installation.
|
|
3
|
-
* Supports corporate proxy via NEON_VSX_GALLERY_URL env var.
|
|
4
|
-
*/
|
|
1
|
+
import "./build_config.js";
|
|
5
2
|
import { createWriteStream } from "node:fs";
|
|
6
|
-
import { tmpdir } from "node:os";
|
|
7
3
|
import { join } from "node:path";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
8
5
|
import { pipeline } from "node:stream/promises";
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
//#region src/init/vsix.ts
|
|
7
|
+
/**
|
|
8
|
+
* Shared VSIX download utilities for extension installation.
|
|
9
|
+
* Supports corporate proxy via NEON_VSX_GALLERY_URL env var.
|
|
10
|
+
*/
|
|
11
|
+
const NEON_EXTENSION_ID = "databricks.neon-local-connect";
|
|
11
12
|
const OPEN_VSX_API = "https://open-vsx.org/api";
|
|
12
13
|
/**
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return downloadFromGallery(proxyGallery);
|
|
26
|
-
}
|
|
27
|
-
return downloadFromOpenVsx();
|
|
14
|
+
* Downloads a .vsix file for the Neon extension.
|
|
15
|
+
*
|
|
16
|
+
* Strategy:
|
|
17
|
+
* 1. If NEON_VSX_GALLERY_URL is set, download from the corporate proxy gallery
|
|
18
|
+
* 2. Otherwise, download from the public Open VSX API
|
|
19
|
+
*
|
|
20
|
+
* Returns the path to the temp .vsix file, or null on failure.
|
|
21
|
+
*/
|
|
22
|
+
async function downloadVsix() {
|
|
23
|
+
const proxyGallery = process.env.NEON_VSX_GALLERY_URL || "";
|
|
24
|
+
if (proxyGallery) return downloadFromGallery(proxyGallery);
|
|
25
|
+
return downloadFromOpenVsx();
|
|
28
26
|
}
|
|
29
27
|
/**
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
* Downloads from a VS Code marketplace-compatible gallery API (corporate proxy).
|
|
29
|
+
* Uses the VS Code extensionquery POST API to find the VSIX download URL.
|
|
30
|
+
*/
|
|
33
31
|
async function downloadFromGallery(galleryUrl) {
|
|
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
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const vsixRes = await fetch(vsixFile.source, {
|
|
68
|
-
signal: AbortSignal.timeout(30000),
|
|
69
|
-
redirect: "follow",
|
|
70
|
-
});
|
|
71
|
-
if (!vsixRes.ok || !vsixRes.body)
|
|
72
|
-
return null;
|
|
73
|
-
const tmpPath = join(tmpdir(), `${NEON_EXTENSION_ID}-proxy.vsix`);
|
|
74
|
-
const fileStream = createWriteStream(tmpPath);
|
|
75
|
-
await pipeline(vsixRes.body, fileStream);
|
|
76
|
-
return tmpPath;
|
|
77
|
-
}
|
|
78
|
-
catch {
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
32
|
+
const [publisher, name] = NEON_EXTENSION_ID.split(".");
|
|
33
|
+
const queryUrl = `${galleryUrl.replace(/\/+$/, "")}/extensionquery`;
|
|
34
|
+
try {
|
|
35
|
+
const queryRes = await fetch(queryUrl, {
|
|
36
|
+
method: "POST",
|
|
37
|
+
headers: {
|
|
38
|
+
"Content-Type": "application/json",
|
|
39
|
+
Accept: "application/json;api-version=6.1-preview.1"
|
|
40
|
+
},
|
|
41
|
+
body: JSON.stringify({
|
|
42
|
+
filters: [{ criteria: [{
|
|
43
|
+
filterType: 7,
|
|
44
|
+
value: `${publisher}.${name}`
|
|
45
|
+
}] }],
|
|
46
|
+
flags: 914
|
|
47
|
+
}),
|
|
48
|
+
signal: AbortSignal.timeout(15e3)
|
|
49
|
+
});
|
|
50
|
+
if (!queryRes.ok) return null;
|
|
51
|
+
const vsixFile = (((await queryRes.json()).results?.[0]?.extensions?.[0])?.versions?.[0])?.files?.find((f) => f.assetType === "Microsoft.VisualStudio.Services.VSIXPackage");
|
|
52
|
+
if (!vsixFile?.source) return null;
|
|
53
|
+
const vsixRes = await fetch(vsixFile.source, {
|
|
54
|
+
signal: AbortSignal.timeout(3e4),
|
|
55
|
+
redirect: "follow"
|
|
56
|
+
});
|
|
57
|
+
if (!vsixRes.ok || !vsixRes.body) return null;
|
|
58
|
+
const tmpPath = join(tmpdir(), `${NEON_EXTENSION_ID}-proxy.vsix`);
|
|
59
|
+
const fileStream = createWriteStream(tmpPath);
|
|
60
|
+
await pipeline(vsixRes.body, fileStream);
|
|
61
|
+
return tmpPath;
|
|
62
|
+
} catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
81
65
|
}
|
|
82
66
|
/**
|
|
83
|
-
|
|
84
|
-
|
|
67
|
+
* Downloads from the public Open VSX API.
|
|
68
|
+
*/
|
|
85
69
|
async function downloadFromOpenVsx() {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const tmpPath = join(tmpdir(), `${NEON_EXTENSION_ID}-${meta.version ?? "latest"}.vsix`);
|
|
104
|
-
const fileStream = createWriteStream(tmpPath);
|
|
105
|
-
await pipeline(vsixRes.body, fileStream);
|
|
106
|
-
return tmpPath;
|
|
107
|
-
}
|
|
108
|
-
catch {
|
|
109
|
-
return null;
|
|
110
|
-
}
|
|
70
|
+
const [publisher, name] = NEON_EXTENSION_ID.split(".");
|
|
71
|
+
const metaUrl = `${OPEN_VSX_API}/${publisher}/${name}/latest`;
|
|
72
|
+
try {
|
|
73
|
+
const metaRes = await fetch(metaUrl, { signal: AbortSignal.timeout(1e4) });
|
|
74
|
+
if (!metaRes.ok) return null;
|
|
75
|
+
const meta = await metaRes.json();
|
|
76
|
+
const downloadUrl = meta.files?.download;
|
|
77
|
+
if (!downloadUrl) return null;
|
|
78
|
+
const vsixRes = await fetch(downloadUrl, { signal: AbortSignal.timeout(3e4) });
|
|
79
|
+
if (!vsixRes.ok || !vsixRes.body) return null;
|
|
80
|
+
const tmpPath = join(tmpdir(), `${NEON_EXTENSION_ID}-${meta.version ?? "latest"}.vsix`);
|
|
81
|
+
const fileStream = createWriteStream(tmpPath);
|
|
82
|
+
await pipeline(vsixRes.body, fileStream);
|
|
83
|
+
return tmpPath;
|
|
84
|
+
} catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
111
87
|
}
|
|
88
|
+
//#endregion
|
|
89
|
+
export { NEON_EXTENSION_ID, downloadVsix };
|
package/dist/log.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import { format } from "node:util";
|
|
2
1
|
import { isDebug } from "./env.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
2
|
+
import { format } from "node:util";
|
|
3
|
+
//#region src/log.ts
|
|
4
|
+
const log = {
|
|
5
|
+
debug: (...args) => {
|
|
6
|
+
if (isDebug()) process.stderr.write(`DEBUG: ${format(...args)}\n`);
|
|
7
|
+
},
|
|
8
|
+
warning: (...args) => {
|
|
9
|
+
process.stderr.write(`WARNING: ${format(...args)}\n`);
|
|
10
|
+
},
|
|
11
|
+
info: (...args) => {
|
|
12
|
+
process.stderr.write(`INFO: ${format(...args)}\n`);
|
|
13
|
+
},
|
|
14
|
+
error: (...args) => {
|
|
15
|
+
process.stderr.write(`ERROR: ${format(...args)}\n`);
|
|
16
|
+
}
|
|
18
17
|
};
|
|
18
|
+
//#endregion
|
|
19
|
+
export { log };
|
package/dist/neon_services.js
CHANGED
|
@@ -1,143 +1,118 @@
|
|
|
1
|
+
//#region src/neon_services.ts
|
|
1
2
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
3
|
+
* Every Neon service a `--service` flag can name, spelled the way a user types it — one
|
|
4
|
+
* vocabulary for the whole CLI.
|
|
5
|
+
*
|
|
6
|
+
* Kebab-case rather than the `neon.ts` field names (`aiGateway`, `buckets`) so a flag reads
|
|
7
|
+
* like a flag, and the full product name rather than a shortening (`object-storage`, not
|
|
8
|
+
* `storage`) so nothing is ambiguous when read on its own.
|
|
9
|
+
*
|
|
10
|
+
* Commands take a **subset** of this via {@link ParseServicesOptions.allowed} — `config init`
|
|
11
|
+
* can only declare what a `neon.ts` has a field for, `env pull` can only pull what produces
|
|
12
|
+
* env vars — but the spelling of a service never varies between them. The order here is the
|
|
13
|
+
* canonical one: parsing sorts into it, so a command's output never depends on the order the
|
|
14
|
+
* flags were typed in.
|
|
15
|
+
*
|
|
16
|
+
* Not to be confused with `NeonFeature` in `init/bootstrap.ts`, which is what a *template*
|
|
17
|
+
* requires. That list comes from remote manifests (`neondatabase/examples/bootstrap.yaml`),
|
|
18
|
+
* spells Postgres `database`, and is not ours to rename.
|
|
19
|
+
*/
|
|
20
|
+
const NEON_SERVICES = [
|
|
21
|
+
"postgres",
|
|
22
|
+
"auth",
|
|
23
|
+
"data-api",
|
|
24
|
+
"functions",
|
|
25
|
+
"object-storage",
|
|
26
|
+
"ai-gateway"
|
|
26
27
|
];
|
|
27
28
|
/**
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const DEPRECATED_SERVICE_ALIASES = {
|
|
33
|
-
// `config init --services storage` shipped before the vocabulary was unified.
|
|
34
|
-
storage: "object-storage",
|
|
35
|
-
};
|
|
29
|
+
* Spellings that used to be canonical, and the service they now mean. Accepted so a scripted
|
|
30
|
+
* `--services storage` keeps working, warned about so it does not quietly become a second
|
|
31
|
+
* vocabulary, and absent from help text, errors, and docs so nobody learns it fresh.
|
|
32
|
+
*/
|
|
33
|
+
const DEPRECATED_SERVICE_ALIASES = { storage: "object-storage" };
|
|
36
34
|
/** An explicit empty selection, for commands where "declare nothing" is a real answer. */
|
|
37
|
-
|
|
35
|
+
const NO_SERVICES = "none";
|
|
38
36
|
/**
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
`Use "${canonical}".`;
|
|
37
|
+
* What to tell someone still using a retired spelling. A message rather than a log call, so
|
|
38
|
+
* the parser stays free of the CLI's writer and each command can surface it in its own voice.
|
|
39
|
+
*/
|
|
40
|
+
const deprecatedServiceMessage = (used, canonical) => `"${used}" is the old name for "${canonical}" and still works, but it will be removed. Use "${canonical}".`;
|
|
44
41
|
/**
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const deprecated = new Map();
|
|
78
|
-
const resolved = names.map((name) => {
|
|
79
|
-
const canonical = DEPRECATED_SERVICE_ALIASES[name];
|
|
80
|
-
if (canonical === undefined)
|
|
81
|
-
return name;
|
|
82
|
-
deprecated.set(name, canonical);
|
|
83
|
-
return canonical;
|
|
84
|
-
});
|
|
85
|
-
const unsupported = resolved.filter((name) => !allowed.some((service) => service === name));
|
|
86
|
-
if (unsupported.length > 0) {
|
|
87
|
-
throw new Error(`${unsupportedMessage(unsupported, flag, whyUnavailable)} ${supported}`);
|
|
88
|
-
}
|
|
89
|
-
// Warned only once the selection is valid: a run that fails validation should not also
|
|
90
|
-
// carry a "still works" claim about a value that never took effect.
|
|
91
|
-
for (const [used, canonical] of deprecated)
|
|
92
|
-
onDeprecated?.(used, canonical);
|
|
93
|
-
return NEON_SERVICES.filter((service) => allowed.includes(service) && resolved.includes(service));
|
|
42
|
+
* Parse the raw values of a services flag into a canonical selection.
|
|
43
|
+
*
|
|
44
|
+
* Accepts the flag repeated (`-s auth -s postgres`) and comma-separated
|
|
45
|
+
* (`-s auth,postgres`), since both read naturally and users will try either. The result is
|
|
46
|
+
* deduplicated and sorted into {@link NEON_SERVICES} order, so what a command does never
|
|
47
|
+
* depends on typing order.
|
|
48
|
+
*
|
|
49
|
+
* An unrecognized name is rejected rather than dropped: a typo would otherwise act on
|
|
50
|
+
* everything *except* the service that was asked for, and report success. A name that is a
|
|
51
|
+
* real service but not one this command supports says so specifically — "functions has no env
|
|
52
|
+
* variables" is a different problem from a typo, and has a different fix.
|
|
53
|
+
*/
|
|
54
|
+
const parseServices = (raw, options) => {
|
|
55
|
+
const { allowed, flag, noneMeans, whyUnavailable = {}, onDeprecated } = options;
|
|
56
|
+
const supported = `Supported values: ${allowed.join(", ")}${noneMeans !== void 0 ? `, ${NO_SERVICES}` : ""}.`;
|
|
57
|
+
const names = raw.flatMap((value) => value.split(",")).map((name) => name.trim()).filter((name) => name !== "");
|
|
58
|
+
if (names.length === 0) throw new Error(`${flag} needs at least one service. ${supported}`);
|
|
59
|
+
if (noneMeans !== void 0 && names.includes("none")) {
|
|
60
|
+
if (new Set(names).size > 1) throw new Error(`${flag} ${NO_SERVICES} cannot be combined with other services.`);
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
const deprecated = /* @__PURE__ */ new Map();
|
|
64
|
+
const resolved = names.map((name) => {
|
|
65
|
+
const canonical = DEPRECATED_SERVICE_ALIASES[name];
|
|
66
|
+
if (canonical === void 0) return name;
|
|
67
|
+
deprecated.set(name, canonical);
|
|
68
|
+
return canonical;
|
|
69
|
+
});
|
|
70
|
+
const unsupported = resolved.filter((name) => !allowed.some((service) => service === name));
|
|
71
|
+
if (unsupported.length > 0) throw new Error(`${unsupportedMessage(unsupported, flag, whyUnavailable)} ${supported}`);
|
|
72
|
+
for (const [used, canonical] of deprecated) onDeprecated?.(used, canonical);
|
|
73
|
+
return NEON_SERVICES.filter((service) => allowed.includes(service) && resolved.includes(service));
|
|
94
74
|
};
|
|
95
75
|
/**
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
76
|
+
* The sentences explaining why a selection was refused. A real Neon service this command
|
|
77
|
+
* cannot act on is a different mistake from a typo — different cause, different fix — so the
|
|
78
|
+
* two are never answered with the same word, and each service carries its reason where the
|
|
79
|
+
* command supplied one.
|
|
80
|
+
*/
|
|
101
81
|
const unsupportedMessage = (unsupported, flag, whyUnavailable) => {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
...known.map((service) => {
|
|
109
|
-
const why = whyUnavailable[service];
|
|
110
|
-
return `${service} is not something ${flag} can select${why ? `: ${why}` : ""}.`;
|
|
111
|
-
}),
|
|
112
|
-
]
|
|
113
|
-
.filter((part) => part !== undefined)
|
|
114
|
-
.join(" ");
|
|
82
|
+
const known = unsupported.filter((name) => NEON_SERVICES.some((service) => service === name));
|
|
83
|
+
const unknown = unsupported.filter((name) => !known.some((service) => service === name));
|
|
84
|
+
return [unknown.length > 0 ? `Unknown service${unknown.length === 1 ? "" : "s"} ${unknown.join(", ")}.` : void 0, ...known.map((service) => {
|
|
85
|
+
const why = whyUnavailable[service];
|
|
86
|
+
return `${service} is not something ${flag} can select${why ? `: ${why}` : ""}.`;
|
|
87
|
+
})].filter((part) => part !== void 0).join(" ");
|
|
115
88
|
};
|
|
116
89
|
/** Every spelling of the services flag, so a habit picked up on one command works on another. */
|
|
117
|
-
const SERVICE_FLAG_NAMES = [
|
|
90
|
+
const SERVICE_FLAG_NAMES = [
|
|
91
|
+
"s",
|
|
92
|
+
"service",
|
|
93
|
+
"services"
|
|
94
|
+
];
|
|
118
95
|
/**
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
.filter((part) => part !== undefined)
|
|
134
|
-
.join(" "),
|
|
135
|
-
type: "array",
|
|
136
|
-
string: true,
|
|
96
|
+
* The yargs option for a services flag, so every command that has one accepts the same
|
|
97
|
+
* spellings (`-s`, `--service`, `--services`) and the same value syntax. `key` is the name the
|
|
98
|
+
* command reads off `argv`; the rest become aliases.
|
|
99
|
+
*/
|
|
100
|
+
const servicesOption = (params) => ({
|
|
101
|
+
alias: SERVICE_FLAG_NAMES.filter((name) => name !== params.key),
|
|
102
|
+
describe: [
|
|
103
|
+
`${params.describe}: ${params.allowed.join(", ")}.`,
|
|
104
|
+
params.noneMeans !== void 0 ? `Pass "${NO_SERVICES}" for ${params.noneMeans}.` : void 0,
|
|
105
|
+
"Repeat the flag or comma-separate.",
|
|
106
|
+
params.also
|
|
107
|
+
].filter((part) => part !== void 0).join(" "),
|
|
108
|
+
type: "array",
|
|
109
|
+
string: true
|
|
137
110
|
});
|
|
138
111
|
/**
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
112
|
+
* Narrow a yargs value for a services flag to the raw strings, or `undefined` when the flag
|
|
113
|
+
* was not given. `argv` is untyped at the handler, and `string: true` only guarantees the
|
|
114
|
+
* element type when the flag was actually parsed as an array.
|
|
115
|
+
*/
|
|
116
|
+
const servicesFlagValue = (value) => Array.isArray(value) ? value.map(String) : void 0;
|
|
117
|
+
//#endregion
|
|
118
|
+
export { NEON_SERVICES, NO_SERVICES, deprecatedServiceMessage, parseServices, servicesFlagValue, servicesOption };
|