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.
Files changed (198) hide show
  1. package/README.md +54 -0
  2. package/dist/_shared/auth_selection.js +76 -79
  3. package/dist/_shared/credentials.js +166 -187
  4. package/dist/_shared/env-core/env.js +395 -0
  5. package/dist/_shared/env-core/reuse-secrets.js +179 -0
  6. package/dist/_shared/paths.js +129 -126
  7. package/dist/_shared/profiles.js +192 -242
  8. package/dist/_shared/secure_file.js +36 -38
  9. package/dist/_virtual/_rolldown/runtime.js +13 -0
  10. package/dist/analytics.js +163 -207
  11. package/dist/api.js +815 -758
  12. package/dist/auth.js +121 -141
  13. package/dist/auth_context.js +39 -53
  14. package/dist/cli.js +4 -7
  15. package/dist/commands/api.js +220 -250
  16. package/dist/commands/api_keys.js +251 -314
  17. package/dist/commands/auth.js +283 -328
  18. package/dist/commands/bootstrap.js +372 -437
  19. package/dist/commands/branches.js +304 -455
  20. package/dist/commands/bucket.js +374 -514
  21. package/dist/commands/checkout.js +213 -298
  22. package/dist/commands/config.js +575 -658
  23. package/dist/commands/connection_string.js +137 -165
  24. package/dist/commands/data_api.js +238 -260
  25. package/dist/commands/databases.js +67 -76
  26. package/dist/commands/deploy.js +31 -25
  27. package/dist/commands/dev.js +642 -681
  28. package/dist/commands/diff.js +156 -200
  29. package/dist/commands/env.js +243 -303
  30. package/dist/commands/functions.js +275 -341
  31. package/dist/commands/index.js +70 -65
  32. package/dist/commands/init.js +84 -119
  33. package/dist/commands/inspect.js +55 -55
  34. package/dist/commands/ip_allow.js +88 -120
  35. package/dist/commands/link.js +874 -1019
  36. package/dist/commands/logs.js +291 -0
  37. package/dist/commands/neon_auth.js +725 -933
  38. package/dist/commands/operations.js +34 -25
  39. package/dist/commands/orgs.js +28 -18
  40. package/dist/commands/profile.js +614 -845
  41. package/dist/commands/projects.js +313 -373
  42. package/dist/commands/psql.js +60 -58
  43. package/dist/commands/roles.js +55 -58
  44. package/dist/commands/schema_diff.js +87 -131
  45. package/dist/commands/set_context.js +34 -26
  46. package/dist/commands/snapshots.js +288 -413
  47. package/dist/commands/status.js +41 -37
  48. package/dist/commands/user.js +21 -10
  49. package/dist/commands/vpc_endpoints.js +85 -113
  50. package/dist/config.js +7 -6
  51. package/dist/config_format.js +50 -66
  52. package/dist/config_template.js +128 -157
  53. package/dist/context.js +183 -235
  54. package/dist/current_branch_fast_path.js +40 -49
  55. package/dist/dev/env.js +313 -394
  56. package/dist/dev/functions.js +54 -64
  57. package/dist/dev/inputs.js +46 -58
  58. package/dist/dev/runtime.js +135 -164
  59. package/dist/dev/websocket.js +766 -959
  60. package/dist/env.js +27 -33
  61. package/dist/env_file.js +118 -132
  62. package/dist/env_services.js +36 -38
  63. package/dist/errors.js +57 -68
  64. package/dist/functions_api.js +45 -43
  65. package/dist/help.js +189 -140
  66. package/dist/index.js +182 -257
  67. package/dist/init/agents.js +137 -118
  68. package/dist/init/auth.js +58 -68
  69. package/dist/init/bootstrap.js +325 -396
  70. package/dist/init/build_config.js +4 -2
  71. package/dist/init/detect_agent.js +56 -101
  72. package/dist/init/editors.js +35 -52
  73. package/dist/init/enrich_output.js +51 -66
  74. package/dist/init/extension.js +134 -171
  75. package/dist/init/inspect.js +179 -266
  76. package/dist/init/interactive.js +510 -622
  77. package/dist/init/neonctl.js +117 -168
  78. package/dist/init/orchestrate.js +157 -173
  79. package/dist/init/phases/auth.js +188 -202
  80. package/dist/init/phases/cleanup.js +23 -23
  81. package/dist/init/phases/db.js +251 -277
  82. package/dist/init/phases/getting_started.js +213 -223
  83. package/dist/init/phases/mcp.js +174 -224
  84. package/dist/init/phases/migrations.js +247 -248
  85. package/dist/init/phases/neon_auth.js +114 -133
  86. package/dist/init/phases/setup.js +546 -703
  87. package/dist/init/phases/skills.js +75 -86
  88. package/dist/init/phases/status.js +72 -67
  89. package/dist/init/resolve_context.js +102 -99
  90. package/dist/init/route_command.js +91 -98
  91. package/dist/init/skills.js +174 -218
  92. package/dist/init/vsix.js +77 -99
  93. package/dist/log.js +17 -16
  94. package/dist/neon_services.js +104 -129
  95. package/dist/parameters.gen.js +481 -471
  96. package/dist/pkg.js +17 -19
  97. package/dist/profile_keys.js +44 -47
  98. package/dist/psql/cli.js +44 -47
  99. package/dist/psql/command/cmd_cond.js +231 -406
  100. package/dist/psql/command/cmd_connect.js +557 -764
  101. package/dist/psql/command/cmd_copy.js +727 -983
  102. package/dist/psql/command/cmd_describe.js +1499 -1688
  103. package/dist/psql/command/cmd_format.js +733 -905
  104. package/dist/psql/command/cmd_io.js +1293 -2082
  105. package/dist/psql/command/cmd_lo.js +297 -359
  106. package/dist/psql/command/cmd_meta.js +727 -878
  107. package/dist/psql/command/cmd_misc.js +138 -172
  108. package/dist/psql/command/cmd_pipeline.js +547 -1099
  109. package/dist/psql/command/cmd_restrict.js +119 -155
  110. package/dist/psql/command/cmd_show.js +529 -688
  111. package/dist/psql/command/dispatch.js +261 -325
  112. package/dist/psql/command/inputQueue.js +35 -33
  113. package/dist/psql/command/shared.js +49 -63
  114. package/dist/psql/complete/filenames.js +90 -133
  115. package/dist/psql/complete/index.js +59 -97
  116. package/dist/psql/complete/matcher.js +236 -300
  117. package/dist/psql/complete/psqlVars.js +218 -223
  118. package/dist/psql/complete/queries.js +159 -177
  119. package/dist/psql/complete/rules.js +1493 -2299
  120. package/dist/psql/core/common.js +762 -1180
  121. package/dist/psql/core/help.js +456 -546
  122. package/dist/psql/core/mainloop.js +692 -1302
  123. package/dist/psql/core/prompt.js +391 -408
  124. package/dist/psql/core/settings.js +429 -644
  125. package/dist/psql/core/sqlHelp.js +480 -554
  126. package/dist/psql/core/startup.js +626 -815
  127. package/dist/psql/core/syncVars.js +67 -110
  128. package/dist/psql/core/variables.js +156 -278
  129. package/dist/psql/describe/formatters.js +884 -1285
  130. package/dist/psql/describe/processNamePattern.js +173 -260
  131. package/dist/psql/describe/queries.js +1368 -2403
  132. package/dist/psql/describe/versionGate.js +32 -41
  133. package/dist/psql/index.js +1414 -1927
  134. package/dist/psql/io/history.js +232 -271
  135. package/dist/psql/io/input.js +103 -108
  136. package/dist/psql/io/lineEditor/buffer.js +238 -319
  137. package/dist/psql/io/lineEditor/complete.js +135 -213
  138. package/dist/psql/io/lineEditor/filename.js +139 -148
  139. package/dist/psql/io/lineEditor/index.js +653 -870
  140. package/dist/psql/io/lineEditor/keymap.js +544 -702
  141. package/dist/psql/io/lineEditor/vt100.js +294 -341
  142. package/dist/psql/io/pgpass.js +158 -187
  143. package/dist/psql/io/pgservice.js +146 -183
  144. package/dist/psql/io/psqlrc.js +328 -403
  145. package/dist/psql/print/aligned.js +1020 -1683
  146. package/dist/psql/print/asciidoc.js +180 -214
  147. package/dist/psql/print/crosstab.js +281 -442
  148. package/dist/psql/print/csv.js +48 -70
  149. package/dist/psql/print/html.js +195 -226
  150. package/dist/psql/print/json.js +75 -88
  151. package/dist/psql/print/latex.js +291 -364
  152. package/dist/psql/print/pager.js +171 -242
  153. package/dist/psql/print/troff.js +194 -226
  154. package/dist/psql/print/unaligned.js +69 -95
  155. package/dist/psql/print/units.js +167 -169
  156. package/dist/psql/scanner/slash.js +428 -483
  157. package/dist/psql/scanner/sql.js +445 -889
  158. package/dist/psql/scanner/stringutils.js +309 -379
  159. package/dist/psql/types/index.js +2 -7
  160. package/dist/psql/types/scanner.js +25 -22
  161. package/dist/psql/wire/connection.js +2042 -2803
  162. package/dist/psql/wire/copy.js +84 -100
  163. package/dist/psql/wire/notify.js +39 -59
  164. package/dist/psql/wire/pipeline.js +305 -518
  165. package/dist/psql/wire/protocol.js +349 -417
  166. package/dist/psql/wire/sasl.js +180 -265
  167. package/dist/psql/wire/tls.js +400 -561
  168. package/dist/storage_api.js +115 -129
  169. package/dist/test_utils/fixtures.js +94 -113
  170. package/dist/test_utils/oauth_server.js +10 -7
  171. package/dist/test_utils/project_dir.js +33 -0
  172. package/dist/utils/ai_gateway_notice.js +131 -162
  173. package/dist/utils/api_enums.js +21 -28
  174. package/dist/utils/auth.js +10 -4
  175. package/dist/utils/branch_notice.js +20 -19
  176. package/dist/utils/branch_picker.js +83 -89
  177. package/dist/utils/cli_name.js +15 -12
  178. package/dist/utils/compute_units.js +20 -27
  179. package/dist/utils/config_diff.js +127 -158
  180. package/dist/utils/enrichers.js +95 -148
  181. package/dist/utils/esbuild.js +133 -147
  182. package/dist/utils/flags.js +35 -47
  183. package/dist/utils/formats.js +8 -15
  184. package/dist/utils/git_diff.js +69 -80
  185. package/dist/utils/inspect_db.js +101 -143
  186. package/dist/utils/inspect_queries.js +179 -142
  187. package/dist/utils/middlewares.js +37 -44
  188. package/dist/utils/openapi.js +87 -99
  189. package/dist/utils/package_manager.js +312 -110
  190. package/dist/utils/point_in_time.js +49 -53
  191. package/dist/utils/psql.js +89 -106
  192. package/dist/utils/service_picker.js +55 -58
  193. package/dist/utils/string.js +5 -5
  194. package/dist/utils/ui.js +38 -55
  195. package/dist/utils/write_sync.js +26 -35
  196. package/dist/utils/zip.js +4 -3
  197. package/dist/writer.js +67 -87
  198. 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
- import { INTERNAL_VSX_GALLERY } from "./build_config.js";
10
- export const NEON_EXTENSION_ID = "databricks.neon-local-connect";
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
- * Downloads a .vsix file for the Neon extension.
14
- *
15
- * Strategy:
16
- * 1. If NEON_VSX_GALLERY_URL is set, download from the corporate proxy gallery
17
- * 2. Otherwise, download from the public Open VSX API
18
- *
19
- * Returns the path to the temp .vsix file, or null on failure.
20
- */
21
- export async function downloadVsix() {
22
- // Runtime env var takes priority, then build-time baked value
23
- const proxyGallery = process.env.NEON_VSX_GALLERY_URL || INTERNAL_VSX_GALLERY || "";
24
- if (proxyGallery) {
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
- * Downloads from a VS Code marketplace-compatible gallery API (corporate proxy).
31
- * Uses the VS Code extensionquery POST API to find the VSIX download URL.
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
- const [publisher, name] = NEON_EXTENSION_ID.split(".");
35
- const baseUrl = galleryUrl.replace(/\/+$/, "");
36
- const queryUrl = `${baseUrl}/extensionquery`;
37
- try {
38
- // Query the marketplace API for the extension
39
- const queryRes = await fetch(queryUrl, {
40
- method: "POST",
41
- headers: {
42
- "Content-Type": "application/json",
43
- Accept: "application/json;api-version=6.1-preview.1",
44
- },
45
- body: JSON.stringify({
46
- filters: [
47
- {
48
- criteria: [
49
- { filterType: 7, value: `${publisher}.${name}` },
50
- ],
51
- },
52
- ],
53
- flags: 914,
54
- }),
55
- signal: AbortSignal.timeout(15000),
56
- });
57
- if (!queryRes.ok)
58
- return null;
59
- const data = (await queryRes.json());
60
- // Find the VSIX download URL from the response
61
- const extension = data.results?.[0]?.extensions?.[0];
62
- const latestVersion = extension?.versions?.[0];
63
- const vsixFile = latestVersion?.files?.find((f) => f.assetType === "Microsoft.VisualStudio.Services.VSIXPackage");
64
- if (!vsixFile?.source)
65
- return null;
66
- // Download the VSIX
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
- * Downloads from the public Open VSX API.
84
- */
67
+ * Downloads from the public Open VSX API.
68
+ */
85
69
  async function downloadFromOpenVsx() {
86
- const [publisher, name] = NEON_EXTENSION_ID.split(".");
87
- const metaUrl = `${OPEN_VSX_API}/${publisher}/${name}/latest`;
88
- try {
89
- const metaRes = await fetch(metaUrl, {
90
- signal: AbortSignal.timeout(10000),
91
- });
92
- if (!metaRes.ok)
93
- return null;
94
- const meta = (await metaRes.json());
95
- const downloadUrl = meta.files?.download;
96
- if (!downloadUrl)
97
- return null;
98
- const vsixRes = await fetch(downloadUrl, {
99
- signal: AbortSignal.timeout(30000),
100
- });
101
- if (!vsixRes.ok || !vsixRes.body)
102
- return null;
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
- export const log = {
4
- debug: (...args) => {
5
- if (isDebug()) {
6
- process.stderr.write(`DEBUG: ${format(...args)}\n`);
7
- }
8
- },
9
- warning: (...args) => {
10
- process.stderr.write(`WARNING: ${format(...args)}\n`);
11
- },
12
- info: (...args) => {
13
- process.stderr.write(`INFO: ${format(...args)}\n`);
14
- },
15
- error: (...args) => {
16
- process.stderr.write(`ERROR: ${format(...args)}\n`);
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 };
@@ -1,143 +1,118 @@
1
+ //#region src/neon_services.ts
1
2
  /**
2
- * Every Neon service a `--service` flag can name, spelled the way a user types it — one
3
- * vocabulary for the whole CLI.
4
- *
5
- * Kebab-case rather than the `neon.ts` field names (`aiGateway`, `buckets`) so a flag reads
6
- * like a flag, and the full product name rather than a shortening (`object-storage`, not
7
- * `storage`) so nothing is ambiguous when read on its own.
8
- *
9
- * Commands take a **subset** of this via {@link ParseServicesOptions.allowed} — `config init`
10
- * can only declare what a `neon.ts` has a field for, `env pull` can only pull what produces
11
- * env vars — but the spelling of a service never varies between them. The order here is the
12
- * canonical one: parsing sorts into it, so a command's output never depends on the order the
13
- * flags were typed in.
14
- *
15
- * Not to be confused with `NeonFeature` in `init/bootstrap.ts`, which is what a *template*
16
- * requires. That list comes from remote manifests (`neondatabase/examples/bootstrap.yaml`),
17
- * spells Postgres `database`, and is not ours to rename.
18
- */
19
- export const NEON_SERVICES = [
20
- "postgres",
21
- "auth",
22
- "data-api",
23
- "functions",
24
- "object-storage",
25
- "ai-gateway",
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
- * Spellings that used to be canonical, and the service they now mean. Accepted so a scripted
29
- * `--services storage` keeps working, warned about so it does not quietly become a second
30
- * vocabulary, and absent from help text, errors, and docs so nobody learns it fresh.
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
- export const NO_SERVICES = "none";
35
+ const NO_SERVICES = "none";
38
36
  /**
39
- * What to tell someone still using a retired spelling. A message rather than a log call, so
40
- * the parser stays free of the CLI's writer and each command can surface it in its own voice.
41
- */
42
- export const deprecatedServiceMessage = (used, canonical) => `"${used}" is the old name for "${canonical}" and still works, but it will be removed. ` +
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
- * Parse the raw values of a services flag into a canonical selection.
46
- *
47
- * Accepts the flag repeated (`-s auth -s postgres`) and comma-separated
48
- * (`-s auth,postgres`), since both read naturally and users will try either. The result is
49
- * deduplicated and sorted into {@link NEON_SERVICES} order, so what a command does never
50
- * depends on typing order.
51
- *
52
- * An unrecognized name is rejected rather than dropped: a typo would otherwise act on
53
- * everything *except* the service that was asked for, and report success. A name that is a
54
- * real service but not one this command supports says so specifically — "functions has no env
55
- * variables" is a different problem from a typo, and has a different fix.
56
- */
57
- export const parseServices = (raw, options) => {
58
- const { allowed, flag, noneMeans, whyUnavailable = {}, onDeprecated, } = options;
59
- const supported = `Supported values: ${allowed.join(", ")}${noneMeans !== undefined ? `, ${NO_SERVICES}` : ""}.`;
60
- const names = raw
61
- .flatMap((value) => value.split(","))
62
- .map((name) => name.trim())
63
- .filter((name) => name !== "");
64
- if (names.length === 0) {
65
- throw new Error(`${flag} needs at least one service. ${supported}`);
66
- }
67
- if (noneMeans !== undefined && names.includes(NO_SERVICES)) {
68
- // Deduplicate before deciding it was combined with something: a repeated value is
69
- // a no-op everywhere else in this parser, so `-s none -s none` must be too.
70
- if (new Set(names).size > 1) {
71
- throw new Error(`${flag} ${NO_SERVICES} cannot be combined with other services.`);
72
- }
73
- return [];
74
- }
75
- // Canonicalize first and unconditionally, so a retired spelling is reported against the
76
- // service it means rather than as a word nobody recognizes.
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
- * The sentences explaining why a selection was refused. A real Neon service this command
97
- * cannot act on is a different mistake from a typo — different cause, different fix — so the
98
- * two are never answered with the same word, and each service carries its reason where the
99
- * command supplied one.
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
- const known = unsupported.filter((name) => NEON_SERVICES.some((service) => service === name));
103
- const unknown = unsupported.filter((name) => !known.some((service) => service === name));
104
- return [
105
- unknown.length > 0
106
- ? `Unknown service${unknown.length === 1 ? "" : "s"} ${unknown.join(", ")}.`
107
- : undefined,
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 = ["s", "service", "services"];
90
+ const SERVICE_FLAG_NAMES = [
91
+ "s",
92
+ "service",
93
+ "services"
94
+ ];
118
95
  /**
119
- * The yargs option for a services flag, so every command that has one accepts the same
120
- * spellings (`-s`, `--service`, `--services`) and the same value syntax. `key` is the name the
121
- * command reads off `argv`; the rest become aliases.
122
- */
123
- export const servicesOption = (params) => ({
124
- alias: SERVICE_FLAG_NAMES.filter((name) => name !== params.key),
125
- describe: [
126
- `${params.describe}: ${params.allowed.join(", ")}.`,
127
- params.noneMeans !== undefined
128
- ? `Pass "${NO_SERVICES}" for ${params.noneMeans}.`
129
- : undefined,
130
- "Repeat the flag or comma-separate.",
131
- params.also,
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
- * Narrow a yargs value for a services flag to the raw strings, or `undefined` when the flag
140
- * was not given. `argv` is untyped at the handler, and `string: true` only guarantees the
141
- * element type when the flag was actually parsed as an array.
142
- */
143
- export const servicesFlagValue = (value) => Array.isArray(value) ? value.map(String) : undefined;
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 };