neon 8.1.0 → 8.2.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 CHANGED
@@ -474,11 +474,11 @@ The resolved branch is then written (by name) to the same `.neon` file `link` us
474
474
 
475
475
  ```bash
476
476
  $ neon checkout main --project-id polished-snowflake-12345678
477
- INFO: Checked out branch br-main-branch-87654321 on project polished-snowflake-12345678. Updated /path/to/cwd/.neon.
477
+ Checked out branch br-main-branch-87654321 on project polished-snowflake-12345678. Updated /path/to/cwd/.neon.
478
478
 
479
479
  $ neon checkout dev --create --project-id polished-snowflake-12345678
480
- INFO: Created branch dev (br-dev-branch-12345678).
481
- INFO: Checked out branch br-dev-branch-12345678 on project polished-snowflake-12345678. Updated /path/to/cwd/.neon.
480
+ Created branch dev (br-dev-branch-12345678).
481
+ Checked out branch br-dev-branch-12345678 on project polished-snowflake-12345678. Updated /path/to/cwd/.neon.
482
482
 
483
483
  $ cat .neon
484
484
  {
@@ -698,9 +698,9 @@ Each command prints what it changed and the next step:
698
698
 
699
699
  ```
700
700
  $ neon config add function sendemail
701
- INFO: Created functions/sendemail.ts.
702
- INFO: Updated neon.ts: added functions.sendemail.
703
- INFO: Next: `neon dev` to run it locally, `neon config apply` to deploy.
701
+ Created functions/sendemail.ts.
702
+ Updated neon.ts: added functions.sendemail.
703
+ Next: `neon dev` to run it locally, `neon config apply` to deploy.
704
704
  ```
705
705
 
706
706
  - **Functions** take a slug of 1-20 lowercase letters and digits, the same rule `plan` enforces. The handler file is written first and an existing file is never overwritten, so pointing `--source` at code you already have works. A `.js` `neon.ts` gets a `.js` handler.
@@ -740,11 +740,18 @@ neon deploy
740
740
 
741
741
  The branch is chosen with `--branch <id|name>`; without it the project's default branch is used. The policy is the `neon.ts` in the project directory (next to `.neon`, or the current directory without one); pass `--config <path>` to point at another file.
742
742
 
743
- **Apply-only flags** (also available on `deploy`):
743
+ **Confirmations** (also on `deploy`). Two things need a yes before `apply` changes anything: applying to a branch Neon marks as protected, and overriding settings the branch already has (compute, TTL, `protected`, Data API settings, custom-domain targets, and disabling an existing Data API). Adding services and deploying functions is not an override, so on an unprotected branch it never asks. In a terminal, `apply` shows the settings it would override and asks once, default No. Without a terminal (CI, agents, pipes) or with `-o json|yaml`, it exits 1 before changing anything and names the flag to pass:
744
744
 
745
- - `--update-existing` (`-y`, `--yes`) — auto-confirm overriding existing remote settings on the branch. Without it, drift on settings already present remotely (compute, TTL, `protected`) is reported as a **conflict** and `apply` makes no changes until you resolve it or pass this flag.
746
- - `--allow-protected` — auto-confirm applying to a branch Neon marks as protected. Without it, `apply` refuses to touch a protected branch.
747
- **Output**: `status` prints the project, branch, and reverse-engineered config. `plan` / `apply` render a **`git diff`-style report** (matching [`neon diff`](#diff)): service changes (Neon Auth, Data API, buckets, functions) list as green `+` additions, while **branch setting changes** (TTL, `protected`, compute) show grouped under a `~ <branch>` header, one sorted `field → value` line each. A bare `apply` that hits drift on settings already present remotely prints those as a sorted **before→after** diff (`current → desired`, old in red / new in green) and exits non-zero until you pass `--update-existing`. Pass `--output json` (or `--output yaml`) to emit the full machine-readable result (`PushResult`) instead, for piping into other tools or CI.
745
+ - `--update-existing` — override settings that differ from `neon.ts`.
746
+ - `--allow-protected` — apply to a protected branch.
747
+ - `-y`, `--yes` — both.
748
+
749
+ ```bash
750
+ neon deploy --env .env.prod --allow-protected # production main is protected, no drift expected
751
+ neon deploy -y # protected branch and drift, no questions
752
+ ```
753
+
754
+ **Output**: `status` prints the project, branch, and reverse-engineered config. `plan` / `apply` render a **`git diff`-style report** (matching [`neon diff`](#diff)): service changes (Neon Auth, Data API, buckets, functions) list as green `+` additions, while **branch setting changes** (TTL, `protected`, compute) show grouped under a `~ <branch>` header, one sorted `field → value` line each. When `apply` would override settings already present remotely, it prints them as a sorted **before→after** diff (`current → desired`, old in red / new in green) before asking or, without a terminal, before exiting non-zero. Pass `--output json` (or `--output yaml`) to emit the full machine-readable result (`PushResult`) instead, for piping into other tools or CI.
748
755
 
749
756
  **`config status --current-branch`** (alias `neon status --current-branch`) prints _only_ the branch pinned in the local `.neon` file — no network, no auth, no analytics — and exits non-zero when none is pinned. This behavior lets it safely drive a shell prompt. Example [starship](https://starship.rs) segment:
750
757
 
@@ -1342,7 +1349,7 @@ Project proj-in-org
1342
1349
 
1343
1350
  napi_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1344
1351
  WARNING: Store this key now: it is not shown again.
1345
- INFO: Limited to proj-in-org: it cannot create projects, mint API keys, or read any other project. It can still change and delete everything inside that project.
1352
+ Limited to proj-in-org: it cannot create projects, mint API keys, or read any other project. It can still change and delete everything inside that project.
1346
1353
  ```
1347
1354
 
1348
1355
  `--org-id` and `--project-id` are mutually exclusive. A project-scoped key *is* an organization key, and its organization is looked up from the project rather than chosen separately. With neither flag you get an account key.
@@ -242,7 +242,7 @@ const withdraw = async (props, orgId, keyId) => {
242
242
  const { data } = orgId ? await props.apiClient.revokeOrgApiKey(orgId, keyId) : await props.apiClient.revokeApiKey(keyId);
243
243
  return data.revoked === true && data.id === keyId;
244
244
  } catch (err) {
245
- log.error("Failed to revoke API key %d: %s", keyId, err instanceof Error ? err.message : String(err));
245
+ log.warning("Failed to revoke API key %d: %s", keyId, err instanceof Error ? err.message : String(err));
246
246
  return false;
247
247
  }
248
248
  };
@@ -451,7 +451,7 @@ const ensureAuth = async (props) => {
451
451
  }
452
452
  if (props._[0] === "me") {
453
453
  const state = loaded === null ? "has no stored credential" : "holds a session that has expired";
454
- process.stderr.write(`Not signed in: profile "${selection.profile}" ${state}. Run \`${getCliName()} login --profile ${selection.profile}\` to sign in, or use an API key with --api-key or NEON_API_KEY.\n`);
454
+ log.info(`Not signed in: profile "${selection.profile}" ${state}. Run \`${getCliName()} login --profile ${selection.profile}\` to sign in, or use an API key with --api-key or NEON_API_KEY.`);
455
455
  process.exitCode = 1;
456
456
  return;
457
457
  }
@@ -223,7 +223,7 @@ const resolveBranchId = async (props, projectId, hookCtx) => {
223
223
  if (props.create) return createCheckoutBranch(props, projectId, ref, branches, hookCtx);
224
224
  const missingName = notFoundMessage(ref, branches, { suggestCreate: true });
225
225
  if (isCi() || !process.stdout.isTTY) throw new Error(missingName);
226
- log.error(missingName);
226
+ log.info(missingName);
227
227
  const { create } = await prompts({
228
228
  type: "confirm",
229
229
  name: "create",
@@ -310,7 +310,7 @@ const resolveProjectId = async (props) => {
310
310
  if (autoDetected) return autoDetected;
311
311
  const missingProjectMessage = `Could not determine which Neon project to check out a branch from. Provide one via the --project-id flag or a .neon file (created by \`${getCliName()} link\` / \`${getCliName()} set-context\`).`;
312
312
  if (isCi() || !process.stdout.isTTY) throw new Error(missingProjectMessage);
313
- log.error(missingProjectMessage);
313
+ log.info(missingProjectMessage);
314
314
  const { runLink } = await prompts({
315
315
  type: "confirm",
316
316
  name: "runLink",
@@ -27,7 +27,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
27
27
  import { dirname, join, relative, resolve } from "node:path";
28
28
  import chalk from "chalk";
29
29
  import { packagesToStage, previewGaWarningForConfig, resolveConfig } from "@neon/config";
30
- import { PushConflictError, apply, assertZipWithinLimits, bundleAsIs, createBranch, describeNativeFinding, enforceLimits, findUndeclaredNativePackages, inspect, isPartialBranchCreateError, plan, resolveEsbuildEntry, traceNativePackages, zipFunctionBundle } from "@neon/config-runtime";
30
+ import { PushAbortedError, PushConflictError, apply, assertZipWithinLimits, bundleAsIs, createBranch, describeNativeFinding, enforceLimits, findUndeclaredNativePackages, inspect, isPartialBranchCreateError, plan, resolveEsbuildEntry, traceNativePackages, zipFunctionBundle } from "@neon/config-runtime";
31
31
  //#region src/commands/config.ts
32
32
  var config_exports = /* @__PURE__ */ __exportAll({
33
33
  ConfigInstallFailed: () => ConfigInstallFailed,
@@ -88,13 +88,18 @@ const envFlag = { env: {
88
88
  /** Apply-only flags, exported so `deploy` can reuse the exact same surface. */
89
89
  const applyFlags = {
90
90
  "update-existing": {
91
- alias: ["y", "yes"],
92
- describe: "Auto-confirm overriding existing remote settings on the branch",
91
+ describe: "Override branch settings that differ from neon.ts without asking",
93
92
  type: "boolean",
94
93
  default: false
95
94
  },
96
95
  "allow-protected": {
97
- describe: "Auto-confirm applying to a branch marked protected on Neon",
96
+ describe: "Apply to a branch marked protected on Neon without asking",
97
+ type: "boolean",
98
+ default: false
99
+ },
100
+ yes: {
101
+ alias: "y",
102
+ describe: "Answer yes to every confirmation: --update-existing and --allow-protected",
98
103
  type: "boolean",
99
104
  default: false
100
105
  }
@@ -754,14 +759,8 @@ const applyCmd = async (props) => {
754
759
  ...branch.parentId ? { parentId: branch.parentId } : {},
755
760
  ...branch.expiresAt ? { expiresAt: branch.expiresAt } : {}
756
761
  };
757
- await runDeployBeforeHook({
758
- hooks,
759
- branch: hookBranch,
760
- git,
761
- event,
762
- cwd
763
- });
764
762
  let result;
763
+ let declined = false;
765
764
  try {
766
765
  result = await apply(config, {
767
766
  projectId: props.projectId,
@@ -769,15 +768,29 @@ const applyCmd = async (props) => {
769
768
  ...props.apiKey ? { apiKey: props.apiKey } : {},
770
769
  ...props.apiHost ? { apiHost: props.apiHost } : {},
771
770
  ...props.runtimeApi ? { api: props.runtimeApi } : {},
772
- ...props.updateExisting ? { updateExisting: true } : {},
773
- ...props.allowProtected ? { allowProtectedBranch: true } : {},
771
+ ...props.updateExisting || props.yes ? { updateExisting: true } : {},
772
+ ...props.allowProtected || props.yes ? { allowProtectedBranch: true } : {},
773
+ confirm: async (context) => {
774
+ if (context.overrides.length > 0) reportConflicts(props, context.overrides);
775
+ if (!canPromptForApply(props)) return false;
776
+ const proceed = await askToApply(context);
777
+ declined = !proceed;
778
+ return proceed;
779
+ },
780
+ beforeMutations: () => runDeployBeforeHook({
781
+ hooks,
782
+ branch: hookBranch,
783
+ git,
784
+ event,
785
+ cwd
786
+ }),
774
787
  bundleFunction: neonctlBundler
775
788
  });
776
789
  } catch (err) {
790
+ if (err instanceof PushAbortedError) throw new Error(declined ? `Aborted: nothing was applied to branch "${err.branchName}".` : abortedApplyMessage(err));
777
791
  if (err instanceof PushConflictError) {
778
792
  reportConflicts(props, err.conflicts);
779
- const overrideable = err.conflicts.every((c) => reasonAllowsUpdateExisting(c.reason));
780
- throw new Error(overrideable ? "Branch settings conflict with the policy. Re-run with --update-existing to apply the changes shown above." : "The policy conflicts with remote state. --update-existing will not resolve every conflict shown above.");
793
+ throw new Error("The policy conflicts with remote state. --update-existing will not resolve every conflict shown above.");
781
794
  }
782
795
  throw err;
783
796
  }
@@ -864,6 +877,29 @@ const reportPushResult = (props, result, mode, services) => {
864
877
  if (noChanges) log.info(`No changes — branch ${result.branchName} already matches the policy.`);
865
878
  out.text(`\nUtilized services: ${services.join(", ")}\n`);
866
879
  };
880
+ /** A prompt needs both ends of a terminal, and would corrupt `-o json|yaml` on stdout. */
881
+ const canPromptForApply = (props) => !isCi() && Boolean(process.stdin.isTTY) && Boolean(process.stdout.isTTY) && props.output !== "json" && props.output !== "yaml";
882
+ const askToApply = async (context) => {
883
+ const branch = JSON.stringify(context.branchName);
884
+ const message = context.protectedBranch && context.overrideUpdates ? `Branch ${branch} is protected, and this overrides the settings shown above. Apply anyway?` : context.protectedBranch ? `Branch ${branch} is protected. Apply to it anyway?` : `Override the settings shown above on branch ${branch}?`;
885
+ const { default: prompts } = await import("prompts");
886
+ const { proceed } = await prompts({
887
+ type: "confirm",
888
+ name: "proceed",
889
+ message,
890
+ initial: false
891
+ });
892
+ return proceed === true;
893
+ };
894
+ /** Without a terminal there is no one to ask, so name the flags that answer the question. */
895
+ const abortedApplyMessage = (err) => {
896
+ const branch = JSON.stringify(err.branchName);
897
+ const isProtected = err.reasons.includes("protected-branch");
898
+ const overrides = err.reasons.includes("override-updates");
899
+ if (isProtected && overrides) return `Branch ${branch} is protected and its settings differ from the policy. Re-run with -y (or --allow-protected --update-existing) to apply the changes shown above.`;
900
+ if (isProtected) return `Branch ${branch} is protected. Re-run with --allow-protected (or -y) to apply to it.`;
901
+ return "Branch settings conflict with the policy. Re-run with --update-existing (or -y) to apply the changes shown above.";
902
+ };
867
903
  /**
868
904
  * Render the branch-setting {@link ConflictReport}s a bare `apply` refused to override (drift
869
905
  * without `--update-existing`) as the git-style before→after diff. JSON/YAML output emits the
@@ -4,11 +4,11 @@ import { isClaimableEnvTarget } from "../claimable/state.js";
4
4
  import { getCliName } from "../utils/cli_name.js";
5
5
  import { readEnvFile, resolveEnvFilePath } from "../env_file.js";
6
6
  import { l as functionBaseUrlKey } from "../_chunks/env-HYNFtxu5.js";
7
+ import { branchIdResolve } from "../utils/enrichers.js";
8
+ import { bundleEntry } from "../utils/esbuild.js";
7
9
  import { a as resolveDevEnv } from "../_chunks/env-BWqJqBDJ.js";
8
10
  import { findConfigFunctionBySource, resolveFunctionsFromConfig } from "../dev/functions.js";
9
11
  import { resolveWatchInputs } from "../dev/inputs.js";
10
- import { branchIdResolve } from "../utils/enrichers.js";
11
- import { bundleEntry } from "../utils/esbuild.js";
12
12
  import { existsSync, mkdirSync, rmSync, statSync, writeFileSync } from "node:fs";
13
13
  import { basename, dirname, join, relative, resolve } from "node:path";
14
14
  import { fileURLToPath } from "node:url";
@@ -550,7 +550,7 @@ const reconcileOnce = async (running, replan, ops) => {
550
550
  try {
551
551
  desired = await replan(nextSearchBase(running), keepPortsFromRunning(running));
552
552
  } catch (err) {
553
- log.info(chalk.red("neon.ts change ignored: ") + (err instanceof Error ? err.message : String(err)) + chalk.dim(" (fix it and save again)"));
553
+ log.warning("neon.ts change ignored: " + (err instanceof Error ? err.message : String(err)) + chalk.dim(" (fix it and save again)"));
554
554
  return;
555
555
  }
556
556
  if (ops.isShuttingDown()) return;
@@ -7,10 +7,10 @@ import { deprecatedServiceMessage, parseServices, servicesFlagValue, servicesOpt
7
7
  import { mergeEnvFile, readEnvFile, resolveEnvFilePath } from "../env_file.js";
8
8
  import { t as NEON_ENV_VAR_KEYS, u as isFunctionBaseUrlKey } from "../_chunks/env-HYNFtxu5.js";
9
9
  import { ENV_PULL_KEY_HELP, ENV_PULL_SERVICES, envKeysForSelection, envPullFlagValue, ownedEnvServiceKeys, parseEnvPullKeys } from "../env_services.js";
10
- import { i as dropClaimableUnsupported, o as resolveNeonEnvVars } from "../_chunks/env-BWqJqBDJ.js";
11
10
  import { fillSingleProject, resolveBranchRef } from "../utils/enrichers.js";
12
11
  import { warnAiGateway } from "../utils/ai_gateway_notice.js";
13
12
  import { announceTargetBranch } from "../utils/branch_notice.js";
13
+ import { i as dropClaimableUnsupported, o as resolveNeonEnvVars } from "../_chunks/env-BWqJqBDJ.js";
14
14
  import { formatPulledEnv } from "./env_output.js";
15
15
  import { existsSync } from "node:fs";
16
16
  import chalk from "chalk";
@@ -110,7 +110,7 @@ const uninstall = (_props) => {
110
110
  log.info("Removed the neon git post-checkout hook. Git → Neon sync is off.");
111
111
  break;
112
112
  case "foreign":
113
- log.warning("Left the existing `post-checkout` hook in place (not managed by neon). Git → Neon sync flag cleared.");
113
+ log.info("Left the existing `post-checkout` hook in place (not managed by neon). Git → Neon sync flag cleared.");
114
114
  break;
115
115
  case "absent": log.info("No neon git hook was installed. Git → Neon sync flag cleared.");
116
116
  }
@@ -295,7 +295,7 @@ const cleanup = async (props) => {
295
295
  const orphanNeonNames = new Set(orphaned.map(([, neonBranch]) => neonBranch));
296
296
  const branches = (await props.apiClient.listProjectBranches({ projectId: props.projectId })).data.branches;
297
297
  const { toDelete, skipped } = partitionBranchesToPrune(branches, orphanNeonNames);
298
- for (const { name, reason } of skipped) log.warning("Keeping Neon branch %s (%s) — never auto-deleted.", name, reason);
298
+ for (const { name, reason } of skipped) log.info("Keeping Neon branch %s (%s) — never auto-deleted.", name, reason);
299
299
  if (toDelete.length === 0) {
300
300
  log.info("No orphaned Neon branches to delete.");
301
301
  return;
@@ -466,7 +466,10 @@ const createByMinting = async (props) => {
466
466
  });
467
467
  warnAboutReach(scope);
468
468
  } finally {
469
- if (minted !== void 0 && !keyIsReachable) log.info(await withdrawKey(session, mintedScope, minted.id) ? `Revoked the key that was minted but not stored (id ${minted.id}).` : `Minted key ${minted.id} could be neither stored nor revoked, and may still be live. Remove it with: neon api-keys revoke ${minted.id}${mintedScope.orgId ? ` --org-id ${mintedScope.orgId}` : ""}`);
469
+ if (minted !== void 0 && !keyIsReachable) {
470
+ if (await withdrawKey(session, mintedScope, minted.id)) log.info(`Revoked the key that was minted but not stored (id ${minted.id}).`);
471
+ else log.warning(`Minted key ${minted.id} could be neither stored nor revoked, and may still be live. Remove it with: neon api-keys revoke ${minted.id}${mintedScope.orgId ? ` --org-id ${mintedScope.orgId}` : ""}`);
472
+ }
470
473
  const revoked = await revokeToken(oauthProps, tokenSet);
471
474
  log.info(revoked ? "Signed the browser session back out, so nothing but the key remains." : "Could not sign the browser session back out; it will expire on its own.");
472
475
  }
@@ -604,7 +607,8 @@ const remove = async (props) => {
604
607
  apiKey: stored.apiKey,
605
608
  apiHost: props.apiHost
606
609
  });
607
- log.info(await withdrawKey(client, scope, keyId) ? `Revoked the API key (id ${keyId})` : `Could not revoke the API key (id ${keyId}) — it may still be live. Remove it with: neon api-keys revoke ${keyId}${scope.orgId ? ` --org-id ${scope.orgId}` : ""}`);
610
+ if (await withdrawKey(client, scope, keyId)) log.info(`Revoked the API key (id ${keyId})`);
611
+ else log.warning(`Could not revoke the API key (id ${keyId}) — it may still be live. Remove it with: neon api-keys revoke ${keyId}${scope.orgId ? ` --org-id ${scope.orgId}` : ""}`);
608
612
  }
609
613
  } else if (stored !== null) {
610
614
  const revoked = await revokeTokenSet(stored.tokens, props);
package/dist/log.js CHANGED
@@ -9,7 +9,7 @@ const log = {
9
9
  process.stderr.write(`WARNING: ${format(...args)}\n`);
10
10
  },
11
11
  info: (...args) => {
12
- process.stderr.write(`INFO: ${format(...args)}\n`);
12
+ process.stderr.write(`${format(...args)}\n`);
13
13
  },
14
14
  error: (...args) => {
15
15
  process.stderr.write(`ERROR: ${format(...args)}\n`);
package/dist/mcp/mint.js CHANGED
@@ -14,7 +14,7 @@ const withdraw = async (client, keyId, orgId) => {
14
14
  const { data } = orgId ? await client.revokeOrgApiKey(orgId, keyId) : await client.revokeApiKey(keyId);
15
15
  return data.revoked === true && data.id === keyId;
16
16
  } catch (err) {
17
- log.error("Failed to revoke API key %d: %s", keyId, err instanceof Error ? err.message : String(err));
17
+ log.warning("Failed to revoke API key %d: %s", keyId, err instanceof Error ? err.message : String(err));
18
18
  return false;
19
19
  }
20
20
  };
@@ -57,7 +57,8 @@ const retirePreviousCredential = async (props, name, existing, replacementKey) =
57
57
  apiKey: existing.apiKey,
58
58
  apiHost: props.apiHost
59
59
  });
60
- log.info(await withdrawKey(client, existing.scope, existing.keyId) ? `Revoked the key it replaces (id ${existing.keyId})` : `Could not revoke the key it replaces (id ${existing.keyId}); it may still be live. Remove it with: neon api-keys revoke ${existing.keyId}`);
60
+ if (await withdrawKey(client, existing.scope, existing.keyId)) log.info(`Revoked the key it replaces (id ${existing.keyId})`);
61
+ else log.warning(`Could not revoke the key it replaces (id ${existing.keyId}); it may still be live. Remove it with: neon api-keys revoke ${existing.keyId}`);
61
62
  return;
62
63
  }
63
64
  const revoked = await revokeTokenSet(existing.tokens, props);
@@ -70,7 +71,7 @@ const withdrawKey = async (client, scope, keyId) => {
70
71
  const { data } = scope.orgId ? await client.revokeOrgApiKey(scope.orgId, keyId) : await client.revokeApiKey(keyId);
71
72
  return data.revoked === true && data.id === keyId;
72
73
  } catch (err) {
73
- log.error("Failed to revoke API key %d: %s", keyId, err instanceof Error ? err.message : String(err));
74
+ log.warning("Failed to revoke API key %d: %s", keyId, err instanceof Error ? err.message : String(err));
74
75
  return false;
75
76
  }
76
77
  };
@@ -130,7 +130,6 @@ const renderAppliedChanges = (changes, title, opts) => {
130
130
  lines.push(...renderBranchGroups(byBranch, paint));
131
131
  return lines.join("\n");
132
132
  };
133
- const isOverrideableConflict = (conflict) => conflict.reason.includes("Pass `updateExisting: true`");
134
133
  const CUSTOM_DOMAIN_REASON = /^custom domain "([^"]+)"/;
135
134
  const labeledConflictField = (conflict) => {
136
135
  if (conflict.field !== "customDomain") return conflict.field;
@@ -145,8 +144,7 @@ const renderBranchSettingConflicts = (conflicts, opts) => {
145
144
  const existing = byBranch.get(conflict.identifier) ?? [];
146
145
  byBranch.set(conflict.identifier, [...existing, ...expandField(labeledConflictField(conflict), conflict.current, conflict.desired)]);
147
146
  }
148
- const heading = conflicts.every(isOverrideableConflict) ? "Branch settings differ (re-run with --update-existing to apply)" : "Branch settings differ";
149
- return [paint.title(heading), ...renderBranchGroups(byBranch, paint)].join("\n");
147
+ return [paint.title("Branch settings differ"), ...renderBranchGroups(byBranch, paint)].join("\n");
150
148
  };
151
149
  const renderCustomDomainFollowup = (result, opts) => {
152
150
  const paint = palette(opts.color);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neon",
3
- "version": "8.1.0",
3
+ "version": "8.2.0",
4
4
  "description": "CLI tool for Neon, the cloud backend primitives built around Lakebase Postgres",
5
5
  "keywords": [
6
6
  "neon",
@@ -64,9 +64,9 @@
64
64
  "yaml": "^2.9.0",
65
65
  "yargs": "17.7.2",
66
66
  "yoctocolors": "^2.1.2",
67
- "@neon/config": "1.8.5",
68
- "@neon/config-runtime": "1.7.7",
69
- "@neon/sdk": "7.0.1"
67
+ "@neon/config-runtime": "1.8.0",
68
+ "@neon/sdk": "7.0.1",
69
+ "@neon/config": "1.8.6"
70
70
  },
71
71
  "optionalDependencies": {
72
72
  "@napi-rs/keyring": "1.3.0",
@@ -101,8 +101,8 @@
101
101
  "vitest": "^3.0.9",
102
102
  "@neon-internals/cli-core": "0.0.0",
103
103
  "@neon/e2e-harness": "0.0.0",
104
- "@neon/functions": "0.11.0",
105
- "@neon-internals/env-core": "0.0.28"
104
+ "@neon-internals/env-core": "0.0.29",
105
+ "@neon/functions": "0.11.0"
106
106
  },
107
107
  "publishConfig": {
108
108
  "access": "public",