neon 5.0.0 → 6.0.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.
@@ -2,9 +2,30 @@ import { CONFIG_INIT_SERVICES } from "../config_template.js";
2
2
  import prompts from "prompts";
3
3
  //#region src/utils/service_picker.ts
4
4
  /**
5
- * The picker's rows, in {@link CONFIG_INIT_SERVICES} order. Titles use the product names from
6
- * the CLI's README ("Managed Better Auth", "Object Storage") rather than the `neon.ts` field
7
- * names, since this is the list a user reads before they've seen a policy.
5
+ * Re-select Postgres after each render. `prompts` lets space unselect a selected
6
+ * row even when `disabled` is set, and `disabled` also strikethroughs the title.
7
+ */
8
+ const keepPostgresSelected = (prompt) => {
9
+ if (typeof prompt !== "object" || prompt === null || !("value" in prompt)) return;
10
+ const rows = prompt.value;
11
+ if (!Array.isArray(rows)) return;
12
+ for (const row of rows) {
13
+ if (!isChoiceRow(row) || row.value !== "postgres") continue;
14
+ row.selected = true;
15
+ }
16
+ };
17
+ const isChoiceRow = (row) => typeof row === "object" && row !== null && "value" in row && "selected" in row;
18
+ const POSTGRES_SERVICE_CHOICE = {
19
+ value: "postgres",
20
+ title: "Postgres (always included)",
21
+ description: "Every Neon project includes a Postgres database.",
22
+ selected: true
23
+ };
24
+ /**
25
+ * The picker's rows, in {@link CONFIG_INIT_SERVICES} order after the locked Postgres
26
+ * row. Titles use the product names from the CLI's README ("Managed Better Auth",
27
+ * "Object Storage") rather than the `neon.ts` field names, since this is the list a
28
+ * user reads before they've seen a policy.
8
29
  */
9
30
  const CHOICES = [
10
31
  {
@@ -41,7 +62,7 @@ const CHOICES = [
41
62
  * Callers guard the TTY themselves (see `initCmd`); this function assumes it may prompt.
42
63
  */
43
64
  const pickServicesInteractively = async () => {
44
- const { services } = await prompts({
65
+ const question = {
45
66
  onState: (state) => {
46
67
  if (state.aborted) {
47
68
  process.stdout.write("\x1B[?25h");
@@ -49,18 +70,23 @@ const pickServicesInteractively = async () => {
49
70
  process.exit(1);
50
71
  }
51
72
  },
73
+ onRender() {
74
+ keepPostgresSelected(this);
75
+ },
52
76
  type: "multiselect",
53
77
  name: "services",
54
78
  message: "Which Neon services should neon.ts declare? (space to toggle, enter to confirm)",
55
79
  instructions: false,
56
- choices: CHOICES.map((choice) => ({
80
+ cursor: 1,
81
+ choices: [POSTGRES_SERVICE_CHOICE, ...CHOICES.map((choice) => ({
57
82
  value: choice.value,
58
83
  title: choice.title,
59
84
  description: choice.description
60
- }))
61
- });
85
+ }))]
86
+ };
87
+ const { services } = await prompts(question);
62
88
  if (!Array.isArray(services)) throw new Error("Aborted: no services selected.");
63
89
  return CONFIG_INIT_SERVICES.filter((service) => services.includes(service));
64
90
  };
65
91
  //#endregion
66
- export { pickServicesInteractively };
92
+ export { POSTGRES_SERVICE_CHOICE, keepPostgresSelected, pickServicesInteractively };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neon",
3
- "version": "5.0.0",
3
+ "version": "6.0.0",
4
4
  "description": "CLI tool for Neon, the cloud backend primitives built around Lakebase Postgres",
5
5
  "keywords": [
6
6
  "neon",
@@ -58,14 +58,15 @@
58
58
  "pg-protocol": "^1.14.0",
59
59
  "picocolors": "^1.1.1",
60
60
  "prompts": "2.4.2",
61
+ "semver": "7.7.2",
61
62
  "undici": "^7.28.0",
62
63
  "which": "3.0.1",
63
64
  "yaml": "^2.9.0",
64
65
  "yargs": "17.7.2",
65
66
  "yoctocolors": "^2.1.2",
66
- "@neon/config": "1.7.2",
67
- "@neon/sdk": "6.0.0",
68
- "@neon/config-runtime": "1.6.2"
67
+ "@neon/config": "1.7.3",
68
+ "@neon/config-runtime": "1.6.3",
69
+ "@neon/sdk": "6.1.0"
69
70
  },
70
71
  "optionalDependencies": {
71
72
  "@napi-rs/keyring": "1.3.0",
@@ -82,6 +83,7 @@
82
83
  "@types/express": "4.17.21",
83
84
  "@types/node": "^20.19.0",
84
85
  "@types/prompts": "2.4.9",
86
+ "@types/semver": "7.7.1",
85
87
  "@types/which": "3.0.4",
86
88
  "@types/yargs": "^17.0.35",
87
89
  "@vitest/coverage-v8": "^3.0.9",
@@ -98,7 +100,7 @@
98
100
  "typescript": "^5.9.0",
99
101
  "vitest": "^3.0.9",
100
102
  "@neon-internals/cli-core": "0.0.0",
101
- "@neon-internals/env-core": "0.0.21",
103
+ "@neon-internals/env-core": "0.0.22",
102
104
  "@neon/e2e-harness": "0.0.0",
103
105
  "@neon/functions": "0.11.0"
104
106
  },
@@ -1,36 +0,0 @@
1
- import { getAgentDisplayName } from "../mcp/agents.js";
2
- import "../init/agents.js";
3
- import { canPickAgentsInteractively } from "../utils/agent_picker.js";
4
- import { NEON_PLUGIN_NAME } from "./run.js";
5
- import prompts from "prompts";
6
- //#region src/plugins/wizard.ts
7
- const restoreCursorOnAbort = (state) => {
8
- if (state.aborted) {
9
- process.stdout.write("\x1B[?25h");
10
- process.stdout.write("\n");
11
- process.exit(1);
12
- }
13
- };
14
- const pluginsInstallSummary = (options) => {
15
- const rows = [
16
- ["Scope", options.scope === "project" ? "project" : "user"],
17
- ["Agents", options.agents.map(getAgentDisplayName).join(", ")],
18
- ["Plugin", NEON_PLUGIN_NAME]
19
- ];
20
- const labelWidth = Math.max(...rows.map(([label]) => label.length));
21
- return rows.map(([label, value]) => `${label.padEnd(labelWidth)} ${value}`).join("\n");
22
- };
23
- const confirmPluginsInstall = async (options) => {
24
- if (!canPickAgentsInteractively()) return true;
25
- process.stdout.write(`\n${pluginsInstallSummary(options)}\n\n`);
26
- const { ok } = await prompts({
27
- onState: restoreCursorOnAbort,
28
- type: "confirm",
29
- name: "ok",
30
- message: "Install the Neon plugin into these agents?",
31
- initial: true
32
- });
33
- return ok === true;
34
- };
35
- //#endregion
36
- export { confirmPluginsInstall, pluginsInstallSummary };