neon 2.38.1 → 2.38.2

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.
@@ -82,7 +82,7 @@ export const pull = async (props, opts = {}) => {
82
82
  // Reuse `neon dev`'s tiered resolver (neon.ts policy -> plan gate -> fetchEnv, else
83
83
  // pullConfig -> fetchEnv). Unlike dev, an unresolved context or failure is surfaced —
84
84
  // `env pull` is an explicit action, so it should error rather than write nothing.
85
- const vars = await resolveNeonEnvVars({
85
+ const { vars, credential } = await resolveNeonEnvVars({
86
86
  cwd,
87
87
  projectId: props.projectId,
88
88
  branchId,
@@ -107,6 +107,15 @@ export const pull = async (props, opts = {}) => {
107
107
  if (removed.length > 0) {
108
108
  log.info("Removed %d stale Neon variable%s not enabled on this branch: %s", removed.length, removed.length === 1 ? "" : "s", removed.join(", "));
109
109
  }
110
+ // A new credential means the values that back object storage / the AI Gateway just
111
+ // changed, so anything else holding the old ones (a deployed preview, a second checkout)
112
+ // needs the new values. Name the keys rather than leaving the user to diff the file.
113
+ if (credential?.issued) {
114
+ log.info("Issued a new branch credential — these now hold fresh values: %s", credential.keys.join(", "));
115
+ if (credential.revoked.length > 0) {
116
+ log.info("Revoked the credential it replaced (%s).", credential.revoked.join(", "));
117
+ }
118
+ }
110
119
  // A dotenv file *we* create holds live branch credentials (DATABASE_URL, Auth keys, service
111
120
  // tokens), so ignore it the same way the `.neon` context file is — otherwise a fresh repo is
112
121
  // one `git add -A` away from committing them. Only on creation: re-adding the entry on every
@@ -128,7 +137,12 @@ export const pull = async (props, opts = {}) => {
128
137
  gateway: { baseUrl: gatewayBaseUrl, token: gatewayToken },
129
138
  });
130
139
  }
131
- return { status: "written", written, file: targetPath };
140
+ return {
141
+ status: "written",
142
+ written,
143
+ file: targetPath,
144
+ ...(credential && credential.keys.length > 0 ? { credential } : {}),
145
+ };
132
146
  };
133
147
  /**
134
148
  * Pull a freshly-pinned branch's Neon env vars into a local `.env`, bundled into `link` and
@@ -162,8 +176,14 @@ export const autoPullEnvAfterPin = async (props) => {
162
176
  */
163
177
  export const renderAgentPullNote = (result) => {
164
178
  switch (result.status) {
165
- case "written":
166
- return ` Pulled ${result.written.length} Neon env var${result.written.length === 1 ? "" : "s"} into ${result.file}.`;
179
+ case "written": {
180
+ // Call out a re-issued credential: an agent that already wrote the old storage /
181
+ // gateway values somewhere else has to update them.
182
+ const credential = result.credential?.issued
183
+ ? ` Issued a new branch credential, so ${result.credential.keys.join(", ")} changed.`
184
+ : "";
185
+ return ` Pulled ${result.written.length} Neon env var${result.written.length === 1 ? "" : "s"} into ${result.file}.${credential}`;
186
+ }
167
187
  case "empty":
168
188
  return " No Neon env vars to pull for this branch yet.";
169
189
  case "skipped":
package/dist/dev/env.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { loadConfigFromFile } from "@neon/config";
2
2
  import { plan, pullConfig } from "@neon/config-runtime";
3
- import { fetchEnv, toEntries } from "@neon/env";
3
+ import { fetchEnvReusingSecrets, } from "@neon/env/runtime";
4
4
  import { log } from "../log.js";
5
5
  /** The API-targeting options every runtime call forwards from the context. */
6
6
  const apiOptions = (ctx) => ({
@@ -102,7 +102,8 @@ export const resolveNeonEnvVars = async (ctx) => {
102
102
  */
103
103
  export const resolveDevEnv = async (ctx) => {
104
104
  try {
105
- return { vars: await resolveNeonEnvVars(ctx) };
105
+ const { vars, credential } = await resolveNeonEnvVars(ctx);
106
+ return { vars, credential };
106
107
  }
107
108
  catch (err) {
108
109
  if (err instanceof DevEnvMismatchError)
@@ -178,15 +179,12 @@ const assertPolicyMatchesBranch = async (config, ctx) => {
178
179
  const isMissingResource = (change) => change.kind === "service" &&
179
180
  change.action === "create" &&
180
181
  !change.identifier.startsWith("function:");
181
- const fetchAndProject = async (config, ctx) => {
182
- const env = await fetchEnv(config, {
183
- projectId: ctx.projectId,
184
- branch: ctx.branchId,
185
- ...apiOptions(ctx),
186
- ...(ctx.env ? { env: ctx.env } : {}),
187
- });
188
- return toEntries(env);
189
- };
182
+ const fetchAndProject = async (config, ctx) => fetchEnvReusingSecrets(config, {
183
+ projectId: ctx.projectId,
184
+ branch: ctx.branchId,
185
+ ...apiOptions(ctx),
186
+ ...(ctx.env ? { env: ctx.env } : {}),
187
+ });
190
188
  /**
191
189
  * Load a `neon.ts` policy if one exists on the path from `cwd` up to the repo
192
190
  * root. Returns `null` when there is none (the common "no config" case), and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neon",
3
- "version": "2.38.1",
3
+ "version": "2.38.2",
4
4
  "description": "CLI tool for Neon Serverless Postgres",
5
5
  "keywords": [
6
6
  "neon",
@@ -58,8 +58,8 @@
58
58
  "yargs": "17.7.2",
59
59
  "@neon/sdk": "1.3.0",
60
60
  "@neon/config": "0.10.0",
61
- "@neon/env": "0.11.8",
62
- "@neon/config-runtime": "0.10.0"
61
+ "@neon/config-runtime": "0.10.0",
62
+ "@neon/env": "0.12.0"
63
63
  },
64
64
  "optionalDependencies": {
65
65
  "esbuild": "0.28.1"