neon 8.14.0 → 8.15.1

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 (47) hide show
  1. package/README.md +4 -2
  2. package/dist/_chunks/{auth-DPSDYYtG.js → auth-rup6nemJ.js} +38 -1
  3. package/dist/_chunks/{checkout-C6VMMgY6.js → checkout-BpOcFaAi.js} +2 -2
  4. package/dist/_chunks/{config-7SIE_C5O.js → config-BjCm5cfr.js} +56 -4
  5. package/dist/_chunks/{deploy-DmKZcAnR.js → deploy-DmEEhux0.js} +1 -1
  6. package/dist/_chunks/{dev-Dv0HKcFF.js → dev-DlUJFzRs.js} +1 -1
  7. package/dist/_chunks/{docs-CClmgj_Z.js → docs-BpLiSTmm.js} +1 -1
  8. package/dist/_chunks/{git-Dxw9w9dK.js → git-j6xSVo3e.js} +2 -2
  9. package/dist/_chunks/{init-BOOGv-mD.js → init-CcVJb492.js} +1 -1
  10. package/dist/_chunks/{link-CcwTXRny.js → link-nAiuWKfg.js} +1 -1
  11. package/dist/_chunks/{plugins-CKOcBuuP.js → plugins-B2Gym8Lw.js} +2 -2
  12. package/dist/_chunks/{profile-H0d7gFrX.js → profile-BAlM625e.js} +1 -1
  13. package/dist/_chunks/{status-DS_yUXFo.js → status-BC4XXuuE.js} +1 -1
  14. package/dist/analytics.js +4 -2
  15. package/dist/api.js +2 -2
  16. package/dist/auth_recovery.js +1 -1
  17. package/dist/commands/auth.js +1 -1
  18. package/dist/commands/checkout.js +1 -1
  19. package/dist/commands/config.js +1 -1
  20. package/dist/commands/deploy.js +1 -1
  21. package/dist/commands/dev.js +1 -1
  22. package/dist/commands/docs.js +1 -1
  23. package/dist/commands/functions_new.js +3 -4
  24. package/dist/commands/git.js +1 -1
  25. package/dist/commands/index.js +12 -12
  26. package/dist/commands/init.js +1 -1
  27. package/dist/commands/link.js +1 -1
  28. package/dist/commands/plugins.js +1 -1
  29. package/dist/commands/profile.js +1 -1
  30. package/dist/commands/status.js +1 -1
  31. package/dist/config_format.js +9 -1
  32. package/dist/config_template.js +36 -9
  33. package/dist/env.js +19 -4
  34. package/dist/index.js +1 -1
  35. package/dist/init/auth.js +23 -2
  36. package/dist/init/copy.js +3 -2
  37. package/dist/init/link.js +2 -2
  38. package/dist/init/run.js +49 -18
  39. package/dist/init/tooling.js +1 -1
  40. package/dist/init/wizard.js +5 -5
  41. package/dist/plugins/child_env.js +10 -0
  42. package/dist/plugins/plan.js +14 -14
  43. package/dist/plugins/run.js +2 -8
  44. package/dist/plugins/targets.js +129 -11
  45. package/dist/update_notifier.js +7 -4
  46. package/dist/utils/service_picker.js +1 -1
  47. package/package.json +6 -6
package/README.md CHANGED
@@ -673,7 +673,7 @@ export default defineConfig({
673
673
 
674
674
  ### Getting a `neon.ts` (`config init`)
675
675
 
676
- `neon config init` scaffolds the policy and installs `@neon/config` / `@neon/env`, so a project can go straight to `plan` / `apply`. It is purely local — no auth, no API calls. In an interactive terminal it asks which services the policy should declare:
676
+ `neon config init` scaffolds the policy and installs `@neon/config` / `@neon/env`, so a project can go straight to `plan` / `apply`. It is local — no auth and no API calls — except `--services data-api`, which reads the linked branch's Data API with a credential already on hand (never a login) so the scaffold declares the right auth. In an interactive terminal it asks which services the policy should declare:
677
677
 
678
678
  ```
679
679
  ? Which Neon services should neon.ts declare? (space to toggle, enter to confirm) ›
@@ -1056,6 +1056,8 @@ On a TTY the command asks which agents, then installs. Detected agents start sel
1056
1056
 
1057
1057
  Default scope is `project`. `--global` is `user`. On macOS and Linux, Cursor and Claude Code store the plugin cache under `~/.claude/plugins`; on Windows, Cursor installs into Cursor extensions. `project` vs `user` is the scope field the plugins CLI records, not a directory in the repo. VS Code, GitHub Copilot CLI, and Grok Build only install user-level: they are skipped at the default scope with a warning, and a VS Code-only project fails if nothing else is selected. Pass `--global` for those.
1058
1058
 
1059
+ GitHub Copilot CLI and Grok Build install through their own CLIs (`copilot`, `grok`), so `neon plugins` runs `copilot --version` or `grok --version` first. A command that is missing, fails, or (for Copilot) is older than 0.0.400 is skipped with a warning under `-y`, fails an explicit `--agent`, and in `neon init` gets Neon skills and MCP instead of the plugin. The other agents install by writing files, so their detected config directory is enough.
1060
+
1059
1061
  Supported agents with a plugins mapping: `claude-code`, `claude-desktop`, `codex`, `cursor`, `github-copilot-cli`, `grok-build`, `vscode`. `claude-desktop` installs as Claude Code; detecting both produces one install and lists both names in the table. `mcporter` is a known MCP name that is then skipped.
1060
1062
 
1061
1063
  The plugins CLI installs every plugin it finds in the Neon plugin package. Today that is `neon-postgres` from `neondatabase/agent-skills`. It includes the Neon MCP server (`https://mcp.neon.tech/mcp`) and these skills: `neon`, `neon-ai-gateway`, `neon-auth`, `neon-functions`, `neon-object-storage`, `neon-postgres`, `neon-postgres-branches`, `neon-postgres-egress-optimizer`, `neon-realtime`. It does not include `neon-postgres-agent-platforms`.
@@ -1122,7 +1124,7 @@ Without a template, a terminal asks which one to use; anything else exits with t
1122
1124
 
1123
1125
  A template's `layout` decides what you get. `router` writes one module per operation plus a generated `index.ts` that dispatches on the URL path, and declares one function. `separate` declares each operation as its own function under the slug the template gives it. Without `--operation` or `--all-operations`, a TTY asks which operations to include and anything else uses the template's recommended ones.
1124
1126
 
1125
- Variables a template needs are declared on each function in `neon.ts` (`env: { API_KEY: process.env.API_KEY! }`) and added, without values, to `.env.example` next to it. Values are never written to `.env` or `.env.local` for you: a blank placeholder there would deploy as an empty string and delete the live value. Put the real value in the file `env pull` uses and deploy with `neon config apply --env .env.local`. `neon dev` reads function env from your shell, so export it there as well.
1127
+ Variables a template needs are declared on each function in `neon.ts` (`env: { API_KEY: process.env.API_KEY! }`) and added, without values, to `.env.example` next to it. Values are never written to `.env` or `.env.local` for you: a blank placeholder there would deploy as an empty string and delete the live value. Put the real value in the file `env pull` uses and deploy with `neon config apply --env .env.local`. `neon dev` loads it automatically.
1126
1128
 
1127
1129
  Nothing is written until every check passes: a file that already exists with different contents needs `--force`, and a slug `neon.ts` already declares needs `--slug`, `--force`, or `--no-add-to-config`. A `separate` template sets its own slugs, so `--slug` only changes its directory; remove the existing declarations from `neon.ts`, or use `--force` or `--no-add-to-config`.
1128
1130
 
@@ -28,6 +28,7 @@ var auth_exports = /* @__PURE__ */ __exportAll({
28
28
  deleteCredentialsAt: () => deleteCredentialsAt,
29
29
  describe: () => describe,
30
30
  ensureAuth: () => ensureAuth,
31
+ existingApiClient: () => existingApiClient,
31
32
  handler: () => handler,
32
33
  isAccessTokenUsable: () => isAccessTokenUsable,
33
34
  locationForAuth: () => locationForAuth,
@@ -288,6 +289,42 @@ const usableCredential = async (props, at) => {
288
289
  return null;
289
290
  }
290
291
  };
292
+ /**
293
+ * The API client for a credential this invocation already holds — the `--api-key` flag or
294
+ * `NEON_API_KEY`, or the selected profile's stored key or OAuth session, refreshed when
295
+ * expired — along with the key it uses. Never starts a login, so a read that only enriches a
296
+ * local file cannot interrupt it. Null when there is no such credential.
297
+ *
298
+ * Selection follows {@link ensureAuth} exactly; only the fallback differs. `ensureAuth` may
299
+ * log in, and a caller that is only reading a branch to improve a scaffold must not.
300
+ */
301
+ const existingApiClient = async (props) => {
302
+ const selection = selectCredential({
303
+ ...credentialInputs(),
304
+ profileFlag: props.profile
305
+ });
306
+ if (selection.source !== "profile") return {
307
+ apiKey: selection.apiKey,
308
+ apiClient: getApiClient({
309
+ apiKey: selection.apiKey,
310
+ apiHost: props.apiHost
311
+ })
312
+ };
313
+ const usable = await usableCredential({
314
+ configDir: props.configDir,
315
+ apiHost: props.apiHost,
316
+ oauthHost: props.oauthHost ?? process.env.NEON_OAUTH_HOST ?? "https://oauth2.neon.tech",
317
+ clientId: props.clientId ?? "neonctl"
318
+ }, locationForAuth(props.configDir, selection.profile));
319
+ if (usable === null) return null;
320
+ return {
321
+ apiKey: usable.apiKey,
322
+ apiClient: getApiClient({
323
+ apiKey: usable.apiKey,
324
+ apiHost: props.apiHost
325
+ })
326
+ };
327
+ };
291
328
  const ensureAuth = async (props) => {
292
329
  if (props._.length === 0 || props.help) return;
293
330
  if (isCurrentBranchProbe(props)) return;
@@ -491,4 +528,4 @@ const deleteCredentialsAt = (at, configDir) => {
491
528
  }
492
529
  };
493
530
  const md5hash = (s) => createHash("md5").update(s).digest("hex");
494
- export { command as a, ensureAuth as c, locationForAuth as d, refreshStoredCredentials as f, builder as i, handler as l, authFlow as n, deleteCredentialsAt as o, usableCredential as p, auth_exports as r, describe as s, aliases as t, isAccessTokenUsable as u };
531
+ export { command as a, ensureAuth as c, isAccessTokenUsable as d, locationForAuth as f, builder as i, existingApiClient as l, usableCredential as m, authFlow as n, deleteCredentialsAt as o, refreshStoredCredentials as p, auth_exports as r, describe as s, aliases as t, handler as u };
@@ -12,8 +12,8 @@ import { fillSingleProject, listAllProjectBranches } from "../utils/enrichers.js
12
12
  import { buildCheckoutEvent, readGitContext } from "../utils/git.js";
13
13
  import { buildHookBranch, loadHookConfig, resolveHookEnv, runCheckoutAfterHook, runCheckoutBeforeHook, runCreateAfterHook, runCreateBeforeHook } from "../utils/hooks.js";
14
14
  import { n as autoPullEnvAfterPin } from "./env-BOt9AZ1j.js";
15
- import { a as applyPolicyOnCreate, f as envFlag, l as createBranchFromPolicyOnCheckout } from "./config-7SIE_C5O.js";
16
- import { i as handler$1 } from "./link-CcwTXRny.js";
15
+ import { a as applyPolicyOnCreate, f as envFlag, l as createBranchFromPolicyOnCheckout } from "./config-BjCm5cfr.js";
16
+ import { i as handler$1 } from "./link-nAiuWKfg.js";
17
17
  import chalk from "chalk";
18
18
  import prompts from "prompts";
19
19
  // src/commands/checkout.ts
@@ -2,10 +2,13 @@ import { t as __exportAll } from "./rolldown-runtime-BJohB4LM.js";
2
2
  import { isCi, isInteractiveTerminal } from "../env.js";
3
3
  import { log } from "../log.js";
4
4
  import { getApiClient } from "../api.js";
5
+ import { r as defaultDir } from "./paths-B55ZfOg1.js";
6
+ import "../config.js";
5
7
  import { contextBranch, ensureDirectoryGitignored, readContextFile } from "../context.js";
6
8
  import { getCliName } from "../utils/cli_name.js";
9
+ import { l as existingApiClient } from "./auth-rup6nemJ.js";
7
10
  import { NEON_SERVICES, NEON_SERVICE_LABELS, deprecatedServiceMessage, servicesFlagValue, servicesOption } from "../neon_services.js";
8
- import { FUNCTION_FILENAME, FUNCTION_SLUG, FUNCTION_TEMPLATE, REQUIRED_PACKAGES, parseConfigInitServices, renderFunctionSource, renderNeonConfig, renderNeonConfigFromView } from "../config_template.js";
11
+ import { FUNCTION_FILENAME, FUNCTION_SLUG, FUNCTION_TEMPLATE, REQUIRED_PACKAGES, dataApiChoiceFromView, parseConfigInitServices, renderFunctionSource, renderNeonConfig, renderNeonConfigFromView } from "../config_template.js";
9
12
  import { TYPESCRIPT_EXTENSION, asRelativeModulePath, editNeonConfig } from "../config_edit.js";
10
13
  import { toNeonConfigView } from "../config_format.js";
11
14
  import { declaredNeonServices } from "../config_services.js";
@@ -208,6 +211,53 @@ const seedFromBranch = async (props) => {
208
211
  branchName: live.branch.name
209
212
  };
210
213
  };
214
+ /**
215
+ * Which `dataApi` entry to scaffold for `data-api`. A linked branch whose Data API already
216
+ * verifies an external IdP gets the external form, so the policy does not go on to enable
217
+ * Neon Auth over it on the first `neon deploy`. The read goes through {@link liveConfigView},
218
+ * the same path as `--from-branch`, so both agree on what the branch has.
219
+ *
220
+ * Anything short of a clear answer — no project to read, no credentials, a failed read, no
221
+ * Data API on the branch — falls back to today's Neon Auth scaffold. The read must never make
222
+ * `init` fail: a user without the Data API loses nothing, and one with it is told how to fix
223
+ * the file by hand.
224
+ */
225
+ const resolveInitDataApiChoice = async (props) => {
226
+ const { projectId } = props;
227
+ if (!projectId) return { kind: "neon" };
228
+ try {
229
+ const access = props.apiClient ? {
230
+ apiClient: props.apiClient,
231
+ apiKey: props.apiKey
232
+ } : await existingApiClient({
233
+ configDir: props.configDir ?? defaultDir,
234
+ apiHost: props.apiHost ?? "https://console.neon.tech/api/v2",
235
+ ...props.profile !== void 0 ? { profile: props.profile } : {},
236
+ ...props.oauthHost !== void 0 ? { oauthHost: props.oauthHost } : {},
237
+ ...props.clientId !== void 0 ? { clientId: props.clientId } : {}
238
+ });
239
+ if (access === null) {
240
+ log.warning("Not signed in, so the Data API on the linked branch could not be read; declaring it with Neon Auth. If it verifies an external identity provider, set dataApi.authProvider to \"external\" in neon.ts before deploying.");
241
+ return { kind: "neon" };
242
+ }
243
+ const ref = await resolveBranchRef({
244
+ apiClient: access.apiClient,
245
+ projectId,
246
+ ...props.branch !== void 0 ? { branch: props.branch } : {}
247
+ });
248
+ const { view } = await liveConfigView({
249
+ projectId,
250
+ branchId: ref.branchId,
251
+ ...access.apiKey ? { apiKey: access.apiKey } : {},
252
+ ...props.apiHost ? { apiHost: props.apiHost } : {},
253
+ ...props.runtimeApi ? { runtimeApi: props.runtimeApi } : {}
254
+ });
255
+ return view.dataApi === void 0 ? { kind: "neon" } : dataApiChoiceFromView(view.dataApi);
256
+ } catch (error) {
257
+ log.warning("Couldn't read the Data API on the linked branch (%s); declaring it with Neon Auth. If it verifies an external identity provider, set dataApi.authProvider to \"external\" in neon.ts before deploying.", error instanceof Error ? error.message : String(error));
258
+ return { kind: "neon" };
259
+ }
260
+ };
211
261
  /** The install command to print, prefixed with a `cd` when the project is not the cwd. */
212
262
  const installCommandFrom = (dir, pm, missing, options) => {
213
263
  const command = formatInstallCommand(pm, [...missing], options);
@@ -265,7 +315,8 @@ const initCmd = async (props) => {
265
315
  }
266
316
  } else {
267
317
  const services = await resolveServices(props);
268
- writeFileSync(join(cwd, "neon.ts"), renderNeonConfig(services));
318
+ const dataApi = services.includes("data-api") ? await resolveInitDataApiChoice(props) : void 0;
319
+ writeFileSync(join(cwd, "neon.ts"), renderNeonConfig(services, dataApi ? { dataApi } : {}));
269
320
  if (!props.silent) {
270
321
  if (services.length === 0) log.info("Created neon.ts with a starter policy.");
271
322
  else {
@@ -273,6 +324,7 @@ const initCmd = async (props) => {
273
324
  log.info("Created neon.ts declaring %s.", declared.join(", "));
274
325
  }
275
326
  }
327
+ if (dataApi?.kind === "external") log.info("The branch's Data API verifies an external identity provider%s, so neon.ts declares it with authProvider \"external\" and does not enable Neon Auth.", dataApi.providerName ? ` (${dataApi.providerName})` : "");
276
328
  if (services.includes("functions")) scaffoldFunction(cwd);
277
329
  }
278
330
  await ensureConfigPackages(cwd, props);
@@ -445,7 +497,7 @@ const builder = (argv) => argv.usage("$0 config <sub-command> [options]").option
445
497
  }), (args) => applyCmd(args)).command("add", "Add a service, function, or bucket to neon.ts (creates it if missing)", (yargs) => yargs.command("auth", "Enable Neon Auth (auth: true)", addSharedOptions, (args) => addCmd(addProps(args, {
446
498
  kind: "service",
447
499
  service: "auth"
448
- }))).command("data-api", "Enable the Data API (dataApi: true) and Neon Auth, which the default provider requires", addSharedOptions, (args) => addCmd(addProps(args, {
500
+ }))).command("data-api", "Enable the Data API (dataApi: true) and Neon Auth, which the default provider requires. For an external identity provider, set dataApi.authProvider to \"external\" instead", addSharedOptions, (args) => addCmd(addProps(args, {
449
501
  kind: "service",
450
502
  service: "data-api"
451
503
  }))).command("ai-gateway", "Enable the AI Gateway (aiGateway: true)", addSharedOptions, (args) => addCmd(addProps(args, {
@@ -502,7 +554,7 @@ const builder = (argv) => argv.usage("$0 config <sub-command> [options]").option
502
554
  also: "postgres alone writes the starter policy; every branch has Postgres. Omitted: pick interactively on a terminal, starter policy in CI or without a TTY."
503
555
  }),
504
556
  "from-branch": {
505
- describe: "Seed neon.ts from a branch's live Neon state instead of asking. Uses the branch pinned in .neon, or --branch <name|id>, or the project's default branch. The only mode of `config init` that calls the Neon API.",
557
+ describe: "Seed neon.ts from a branch's live Neon state instead of asking. Uses the branch pinned in .neon, or --branch <name|id>, or the project's default branch. Needs credentials and a project.",
506
558
  type: "boolean",
507
559
  conflicts: "services"
508
560
  }
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-BJohB4LM.js";
2
2
  import { fillSingleProject } from "../utils/enrichers.js";
3
- import { f as envFlag, i as applyFlags, p as envPullFlag, r as applyCmd } from "./config-7SIE_C5O.js";
3
+ import { f as envFlag, i as applyFlags, p as envPullFlag, r as applyCmd } from "./config-BjCm5cfr.js";
4
4
  import { DEPLOY_COMMANDS_EPILOGUE } from "../commands/deploy_help.js";
5
5
  // src/commands/deploy.ts
6
6
  var deploy_exports = /* @__PURE__ */ __exportAll({
@@ -9,7 +9,7 @@ import { findConfigFunctionBySource, resolveFunctionsFromConfig } from "../dev/f
9
9
  import { resolveWatchInputs } from "../dev/inputs.js";
10
10
  import { branchIdResolve } from "../utils/enrichers.js";
11
11
  import { bundleEntry } from "../utils/esbuild.js";
12
- import { f as envFlag } from "./config-7SIE_C5O.js";
12
+ import { f as envFlag } from "./config-BjCm5cfr.js";
13
13
  import { existsSync, mkdirSync, rmSync, statSync, writeFileSync } from "node:fs";
14
14
  import { basename, dirname, join, relative, resolve } from "node:path";
15
15
  import { fileURLToPath } from "node:url";
@@ -128,7 +128,7 @@ function siteSearchHeaders(opts) {
128
128
  "Content-Type": "application/json",
129
129
  "User-Agent": `neon/${opts.version}`,
130
130
  "x-caller-source": "cli",
131
- ...opts.agent ? { "x-caller-client": encodeURIComponent(opts.agent) } : {},
131
+ ...opts.analytics && opts.agent ? { "x-caller-client": encodeURIComponent(opts.agent) } : {},
132
132
  ...opts.analytics ? {} : { "x-caller-analytics": "off" }
133
133
  };
134
134
  }
@@ -5,8 +5,8 @@ import { CONTEXT_FILE, contextBranch, gitBranchMap, gitBranchMapping, isUnfollow
5
5
  import { writer } from "../writer.js";
6
6
  import { neonSafeBranchName } from "../utils/branch_name.js";
7
7
  import { currentGitBranch, gitPull, gitRepoRoot, hasUpstream, installPostCheckoutHook, isGitRepo, isManagedHook, localGitBranches, postCheckoutHookPath, readGitContext, removePostCheckoutHook } from "../utils/git.js";
8
- import { o as quoteFlagValue } from "./link-CcwTXRny.js";
9
- import { o as handler$1 } from "./checkout-C6VMMgY6.js";
8
+ import { o as quoteFlagValue } from "./link-nAiuWKfg.js";
9
+ import { o as handler$1 } from "./checkout-BpOcFaAi.js";
10
10
  import { existsSync } from "node:fs";
11
11
  import { join } from "node:path";
12
12
  import chalk from "chalk";
@@ -53,7 +53,7 @@ const builder = (yargs) => yargs.usage("$0 init [options]").option("context-file
53
53
  key: "services",
54
54
  allowed: NEON_SERVICES,
55
55
  describe: "Services to declare in neon.ts",
56
- also: "postgres alone writes the starter policy; every branch has Postgres. Implies creating neon.ts. Cannot be combined with --no-config."
56
+ also: "postgres alone writes the starter policy; every branch has Postgres. data-api also declares auth unless the linked branch's Data API already uses an external identity provider. Implies creating neon.ts. Cannot be combined with --no-config."
57
57
  })).option("org-id", {
58
58
  describe: "Forwarded to link: organization ID to link to",
59
59
  type: "string"
@@ -14,7 +14,7 @@ import { createBranch, pickBranchInteractively } from "../utils/branch_picker.js
14
14
  import { looksLikeBranchId } from "../utils/formats.js";
15
15
  import { listAllProjectBranches } from "../utils/enrichers.js";
16
16
  import { n as autoPullEnvAfterPin } from "./env-BOt9AZ1j.js";
17
- import { h as initCmd } from "./config-7SIE_C5O.js";
17
+ import { h as initCmd } from "./config-BjCm5cfr.js";
18
18
  import { formatLinkSummary } from "../commands/link_output.js";
19
19
  import { r as REGIONS } from "./projects-a3X4OFEJ.js";
20
20
  import prompts from "prompts";
@@ -5,7 +5,7 @@ import { helpCsv, helpEpilogue } from "../utils/help_text.js";
5
5
  import { getAgentDisplayName } from "../mcp/agents.js";
6
6
  import { NEON_MCP_URL } from "../mcp/install.js";
7
7
  import "../init/agents.js";
8
- import { pluginsInstallableAgents } from "../plugins/targets.js";
8
+ import { pluginsCommandProblemText, pluginsInstallableAgents } from "../plugins/targets.js";
9
9
  import { writer } from "../writer.js";
10
10
  import { noPassthrough } from "../utils/flags.js";
11
11
  import { AGENT_PLUGIN_SKIP_MESSAGE } from "../init/copy.js";
@@ -77,7 +77,7 @@ const installPlugins = async (options) => {
77
77
  });
78
78
  for (const agent of plan.skipped) log.warning("Skipping %s: no plugins mapping.", getAgentDisplayName(agent));
79
79
  for (const agent of plan.userScopeSkipped) log.warning("Skipping %s: plugins are user-level. Pass --global.", getAgentDisplayName(agent));
80
- for (const { agent, command } of plan.missingCommands) log.warning("Skipping %s: the plugin installs through \"%s\", which was not found on PATH.", getAgentDisplayName(agent), command);
80
+ for (const row of plan.unusableCommands) log.warning("Skipping %s: the plugin installs through \"%s\", which %s.", getAgentDisplayName(row.agent), row.command.name, pluginsCommandProblemText(row));
81
81
  const rows = [];
82
82
  const failed = [];
83
83
  const scope = scopeLabel(plan.scope);
@@ -10,7 +10,7 @@ import { _ as upsertProfile, a as canDropProfilesFile, c as listProfiles, d as n
10
10
  import { auth, revokeToken } from "../auth.js";
11
11
  import { t as credentialInputs } from "./auth_selection-CwGLN9Qz.js";
12
12
  import { readOutgoingCredential, retirePreviousCredential, revokeTokenSet, withdrawKey } from "../retire_credential.js";
13
- import { n as authFlow, p as usableCredential } from "./auth-DPSDYYtG.js";
13
+ import { m as usableCredential, n as authFlow } from "./auth-rup6nemJ.js";
14
14
  import { identityFromAuthDetails, isApiKeyMethod, mintedKeyName, notAnApiKeyMessage } from "../profile_keys.js";
15
15
  import { writer } from "../writer.js";
16
16
  import { noPassthrough, single } from "../utils/flags.js";
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-BJohB4LM.js";
2
2
  import { fillSingleProject } from "../utils/enrichers.js";
3
- import { y as status } from "./config-7SIE_C5O.js";
3
+ import { y as status } from "./config-BjCm5cfr.js";
4
4
  // src/commands/status.ts
5
5
  var status_exports = /* @__PURE__ */ __exportAll({
6
6
  builder: () => builder,
package/dist/analytics.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { a as OAUTH, t as storeFor } from "./_chunks/credential_io-DbeSh3Pl.js";
2
- import { getCliAgent, getGithubEnvVars, isCi } from "./env.js";
2
+ import { getCliAgent, getGithubEnvVars, getTty, isCi } from "./env.js";
3
3
  import { log } from "./log.js";
4
4
  import { getOrCreateAnonymousId } from "./anonymous_id.js";
5
5
  import pkg_default from "./pkg.js";
@@ -248,7 +248,8 @@ const settleErrorReports = async (deadline) => {
248
248
  const getErrorAnalyticsEventContext = (_args) => ({
249
249
  version: pkg_default.version,
250
250
  ci: isCi(),
251
- agent: getCliAgent(process.env)
251
+ agent: getCliAgent(process.env),
252
+ tty: getTty()
252
253
  });
253
254
  const CREDENTIAL_TOKEN_ID = /\bnak_live_[0-9a-f]+\b/gi;
254
255
  const redactCredentialTokenIds = (text) => text.replace(CREDENTIAL_TOKEN_ID, "nak_live_<redacted>");
@@ -353,6 +354,7 @@ const getAnalyticsEventProperties = (args) => ({
353
354
  flags: { output: args.output },
354
355
  ci: isCi(),
355
356
  agent: getCliAgent(process.env),
357
+ tty: getTty(),
356
358
  githubEnvVars: getGithubEnvVars(process.env)
357
359
  });
358
360
  export { analyticsIdentity, analyticsMiddleware, closeAnalytics, commandSuccessProperties, getAnalyticsEventProperties, getErrorAnalyticsEventProperties, initAnalyticsClientMiddleware, isAnalyticsActive, recordCommandSuccessExtras, recordScaffoldedTemplate, redactCredentialTokenIds, sendError, storedCredentialAttribution, takeCommandSuccessExtras, telemetryCredential, trackCommandSuccess, trackEvent, useAnalyticsClientForTests };
package/dist/api.js CHANGED
@@ -288,7 +288,7 @@ async function readJsonBody(response) {
288
288
  }
289
289
  }
290
290
  const getApiClient = ({ apiKey, apiHost, requestTimeoutMs = REQUEST_TIMEOUT_MS }) => {
291
- const baseUrl = apiHost ?? DEFAULT_API_HOST;
291
+ const baseUrl = apiHost ?? "https://console.neon.tech/api/v2";
292
292
  const fetchWithTimeout = makeTimedFetch(validateRequestTimeout(requestTimeoutMs));
293
293
  const client = createClient(createConfig({
294
294
  auth: () => apiKey,
@@ -1079,4 +1079,4 @@ const getApiClient = ({ apiKey, apiHost, requestTimeoutMs = REQUEST_TIMEOUT_MS }
1079
1079
  }))
1080
1080
  };
1081
1081
  };
1082
- export { ContentType, NeonApiError, UnreadableResponseError, codeFromBody, getApiClient, isNeonApiError, messageFromBody, retryOnLock };
1082
+ export { ContentType, DEFAULT_API_HOST, NeonApiError, UnreadableResponseError, codeFromBody, getApiClient, isNeonApiError, messageFromBody, retryOnLock };
@@ -2,7 +2,7 @@ import { t as storeFor } from "./_chunks/credential_io-DbeSh3Pl.js";
2
2
  import { log } from "./log.js";
3
3
  import { authFailureMessage, getAuthContext, locationFromContext } from "./auth_context.js";
4
4
  import { AuthRefreshError } from "./auth.js";
5
- import { f as refreshStoredCredentials, u as isAccessTokenUsable } from "./_chunks/auth-DPSDYYtG.js";
5
+ import { d as isAccessTokenUsable, p as refreshStoredCredentials } from "./_chunks/auth-rup6nemJ.js";
6
6
  // src/auth_recovery.ts
7
7
  const supersededOnDisk = (rejectedToken) => {
8
8
  if (rejectedToken === void 0) return false;
@@ -1 +1 @@
1
- export { t as aliases, n as authFlow, i as builder, a as command, o as deleteCredentialsAt, s as describe, c as ensureAuth, l as handler, u as isAccessTokenUsable, d as locationForAuth, f as refreshStoredCredentials, p as usableCredential } from "../_chunks/auth-DPSDYYtG.js";
1
+ export { t as aliases, n as authFlow, i as builder, a as command, o as deleteCredentialsAt, s as describe, c as ensureAuth, l as existingApiClient, u as handler, d as isAccessTokenUsable, f as locationForAuth, p as refreshStoredCredentials, m as usableCredential } from "../_chunks/auth-rup6nemJ.js";
@@ -1 +1 @@
1
- export { t as builder, r as command, i as describe, a as formatCheckoutPolicyFailure, o as handler } from "../_chunks/checkout-C6VMMgY6.js";
1
+ export { t as builder, r as command, i as describe, a as formatCheckoutPolicyFailure, o as handler } from "../_chunks/checkout-BpOcFaAi.js";
@@ -1 +1 @@
1
- export { t as ConfigInstallFailed, n as addCmd, r as applyCmd, i as applyFlags, a as applyPolicyOnCreate, o as builder, s as command, l as createBranchFromPolicyOnCheckout, u as describe, d as ensureConfigPackages, f as envFlag, p as envPullFlag, m as handler, h as initCmd, g as installCommandFrom, _ as missingDependencies, v as planCmd, y as status } from "../_chunks/config-7SIE_C5O.js";
1
+ export { t as ConfigInstallFailed, n as addCmd, r as applyCmd, i as applyFlags, a as applyPolicyOnCreate, o as builder, s as command, l as createBranchFromPolicyOnCheckout, u as describe, d as ensureConfigPackages, f as envFlag, p as envPullFlag, m as handler, h as initCmd, g as installCommandFrom, _ as missingDependencies, v as planCmd, y as status } from "../_chunks/config-BjCm5cfr.js";
@@ -1 +1 @@
1
- export { t as builder, n as command, i as describe, a as handler } from "../_chunks/deploy-DmKZcAnR.js";
1
+ export { t as builder, n as command, i as describe, a as handler } from "../_chunks/deploy-DmEEhux0.js";
@@ -1 +1 @@
1
- export { t as builder, n as captureShellEnv, r as command, i as describe, a as devBundleDir, o as devEnvContext, c as diffUnits, l as formatEnvFiles, u as formatEnvSummary, d as handler, f as loadDevEnvFiles, p as localFunctionUrlEnv, m as planFunctionsToUnits, h as reportDevCredential, g as sourceFunctionUrlOverlay } from "../_chunks/dev-Dv0HKcFF.js";
1
+ export { t as builder, n as captureShellEnv, r as command, i as describe, a as devBundleDir, o as devEnvContext, c as diffUnits, l as formatEnvFiles, u as formatEnvSummary, d as handler, f as loadDevEnvFiles, p as localFunctionUrlEnv, m as planFunctionsToUnits, h as reportDevCredential, g as sourceFunctionUrlOverlay } from "../_chunks/dev-DlUJFzRs.js";
@@ -1 +1 @@
1
- export { t as DEFAULT_SITE_SEARCH_URL, n as MAX_LIMIT, r as MAX_QUERY_LENGTH, i as SITE_SEARCH_CATEGORIES, a as builder, o as command, s as describe, l as formatSearchResults, u as parseSearchHits, d as resolveSiteSearchUrl, f as siteSearchHeaders } from "../_chunks/docs-CClmgj_Z.js";
1
+ export { t as DEFAULT_SITE_SEARCH_URL, n as MAX_LIMIT, r as MAX_QUERY_LENGTH, i as SITE_SEARCH_CATEGORIES, a as builder, o as command, s as describe, l as formatSearchResults, u as parseSearchHits, d as resolveSiteSearchUrl, f as siteSearchHeaders } from "../_chunks/docs-BpLiSTmm.js";
@@ -8,7 +8,7 @@ import { writer } from "../writer.js";
8
8
  import { formatInitDone, printInitDone } from "../init/chrome.js";
9
9
  import { FUNCTION_SLUG_PATTERN, deriveFunctionSlug } from "../utils/function_slug.js";
10
10
  import { displayPath } from "./env_output.js";
11
- import { _ as missingDependencies, d as ensureConfigPackages, g as installCommandFrom } from "../_chunks/config-7SIE_C5O.js";
11
+ import { _ as missingDependencies, d as ensureConfigPackages, g as installCommandFrom } from "../_chunks/config-BjCm5cfr.js";
12
12
  import { recommendedOperations } from "../functions/registry.js";
13
13
  import { collidingFiles, operationsFromFlags, planConfigRegistration, planEnvExample, planScaffold, writeScaffold } from "../functions/scaffold.js";
14
14
  import { describeRegistrySource, openRegistry } from "../functions/source.js";
@@ -169,9 +169,8 @@ const scaffoldFromTemplate = async (options) => {
169
169
  const envFile = displayPath(resolveEnvFilePath(location), cwd);
170
170
  const names = environment.join(", ");
171
171
  if (variables && register) {
172
- const them = environment.length === 1 ? "it" : "them";
173
- nextSteps.push(`Set ${variables} in ${envFile}. \`${cli} dev\` reads ${them} from your shell, so export ${them} there too.`);
174
- next.push(`Set ${names} in ${envFile}, and export ${them} for ${cli} dev`);
172
+ nextSteps.push(`Set ${variables} in ${envFile} (\`${cli} dev\` loads it automatically).`);
173
+ next.push(`Set ${names} in ${envFile} (${cli} dev loads it automatically)`);
175
174
  } else if (variables) {
176
175
  nextSteps.push(`Set ${variables} in your shell.`);
177
176
  next.push(`Set ${names} in your shell`);
@@ -1 +1 @@
1
- export { t as aliases, n as builder, r as cleanup, i as command, a as describe, s as handler, c as install, l as partitionBranchesToPrune, u as status, d as sync, f as uninstall } from "../_chunks/git-Dxw9w9dK.js";
1
+ export { t as aliases, n as builder, r as cleanup, i as command, a as describe, s as handler, c as install, l as partitionBranchesToPrune, u as status, d as sync, f as uninstall } from "../_chunks/git-j6xSVo3e.js";
@@ -1,31 +1,31 @@
1
- import { r as auth_exports } from "../_chunks/auth-DPSDYYtG.js";
1
+ import { r as auth_exports } from "../_chunks/auth-rup6nemJ.js";
2
2
  import { t as api_exports } from "../_chunks/api-1MKsfpY3.js";
3
3
  import { n as api_keys_exports } from "../_chunks/api_keys-6Xnxl7a8.js";
4
4
  import { n as ask_exports } from "../_chunks/ask-Xlek1Pxh.js";
5
5
  import { o as env_exports } from "../_chunks/env-BOt9AZ1j.js";
6
- import { c as config_exports } from "../_chunks/config-7SIE_C5O.js";
6
+ import { c as config_exports } from "../_chunks/config-BjCm5cfr.js";
7
7
  import { u as projects_exports } from "../_chunks/projects-a3X4OFEJ.js";
8
- import { a as link_exports } from "../_chunks/link-CcwTXRny.js";
8
+ import { a as link_exports } from "../_chunks/link-nAiuWKfg.js";
9
9
  import { o as mcp_exports } from "../_chunks/mcp-BznTRK3w.js";
10
- import { c as plugins_exports } from "../_chunks/plugins-CKOcBuuP.js";
10
+ import { c as plugins_exports } from "../_chunks/plugins-B2Gym8Lw.js";
11
11
  import { l as skills_exports } from "../_chunks/skills-DKgafm65.js";
12
12
  import { t as bootstrap_exports } from "../_chunks/bootstrap-BDkvsAVJ.js";
13
13
  import { r as branches_exports } from "../_chunks/branches-Bp-5z1lM.js";
14
14
  import { n as bucket_exports } from "../_chunks/bucket-D06bvDSa.js";
15
- import { n as checkout_exports } from "../_chunks/checkout-C6VMMgY6.js";
15
+ import { n as checkout_exports } from "../_chunks/checkout-BpOcFaAi.js";
16
16
  import { o as claim_exports } from "../_chunks/claim-DlLZmcq0.js";
17
17
  import { a as connection_string_exports } from "../_chunks/connection_string-C9e7N4xk.js";
18
18
  import { a as credentials_exports } from "../_chunks/credentials-BMBNmW0t.js";
19
19
  import { r as data_api_exports } from "../_chunks/data_api-CHDwvMTG.js";
20
20
  import { o as databases_exports } from "../_chunks/databases-DC2h6IW2.js";
21
- import { r as deploy_exports } from "../_chunks/deploy-DmKZcAnR.js";
22
- import { s as dev_exports } from "../_chunks/dev-Dv0HKcFF.js";
21
+ import { r as deploy_exports } from "../_chunks/deploy-DmEEhux0.js";
22
+ import { s as dev_exports } from "../_chunks/dev-DlUJFzRs.js";
23
23
  import { i as diff_exports } from "../_chunks/diff-dnxneH0u.js";
24
- import { c as docs_exports } from "../_chunks/docs-CClmgj_Z.js";
24
+ import { c as docs_exports } from "../_chunks/docs-BpLiSTmm.js";
25
25
  import { o as feedback_exports } from "../_chunks/feedback-mQmdTRFn.js";
26
26
  import { o as functions_exports } from "../_chunks/functions-3ypiRwZK.js";
27
- import { o as git_exports } from "../_chunks/git-Dxw9w9dK.js";
28
- import { a as init_exports } from "../_chunks/init-BOOGv-mD.js";
27
+ import { o as git_exports } from "../_chunks/git-j6xSVo3e.js";
28
+ import { a as init_exports } from "../_chunks/init-CcVJb492.js";
29
29
  import { o as inspect_exports } from "../_chunks/inspect-yFAb61qo.js";
30
30
  import { a as ip_allow_exports } from "../_chunks/ip_allow-DBdxNEUa.js";
31
31
  import { l as logs_exports } from "../_chunks/logs-BB4uvblR.js";
@@ -33,13 +33,13 @@ import { a as neon_auth_exports } from "../_chunks/neon_auth-Dw-ucM5Y.js";
33
33
  import { a as open_exports } from "../_chunks/open-T2nI89Oh.js";
34
34
  import { s as operations_exports } from "../_chunks/operations-CzaR_uqx.js";
35
35
  import { o as orgs_exports } from "../_chunks/orgs-Dpbr-K0A.js";
36
- import { o as profile_exports } from "../_chunks/profile-H0d7gFrX.js";
36
+ import { o as profile_exports } from "../_chunks/profile-BAlM625e.js";
37
37
  import { a as psql_exports } from "../_chunks/psql-Bce4X0NG.js";
38
38
  import { s as realtime_exports } from "../_chunks/realtime-BwtzYf5a.js";
39
39
  import { l as roles_exports } from "../_chunks/roles-xRuu0462.js";
40
40
  import { a as set_context_exports } from "../_chunks/set_context-ompB6d2D.js";
41
41
  import { s as snapshots_exports } from "../_chunks/snapshots-DxNhjcco.js";
42
- import { a as status_exports } from "../_chunks/status-DS_yUXFo.js";
42
+ import { a as status_exports } from "../_chunks/status-BC4XXuuE.js";
43
43
  import { d as triggers_exports } from "../_chunks/triggers-BfvyeJUC.js";
44
44
  import { s as user_exports } from "../_chunks/user-D9mC430O.js";
45
45
  import { i as vpc_endpoints_exports } from "../_chunks/vpc_endpoints-C-Y4WK2M.js";
@@ -1 +1 @@
1
- export { t as builder, n as command, r as describe, i as handler } from "../_chunks/init-BOOGv-mD.js";
1
+ export { t as builder, n as command, r as describe, i as handler } from "../_chunks/init-CcVJb492.js";
@@ -1 +1 @@
1
- export { t as builder, n as command, r as describe, i as handler, o as quoteFlagValue, s as runLink, c as shouldOfferConfigInit } from "../_chunks/link-CcwTXRny.js";
1
+ export { t as builder, n as command, r as describe, i as handler, o as quoteFlagValue, s as runLink, c as shouldOfferConfigInit } from "../_chunks/link-nAiuWKfg.js";
@@ -1 +1 @@
1
- export { t as aliases, n as builder, r as command, i as describe, a as handler, o as installPlugins, s as pluginsInstallError, l as reportPluginsInstall } from "../_chunks/plugins-CKOcBuuP.js";
1
+ export { t as aliases, n as builder, r as command, i as describe, a as handler, o as installPlugins, s as pluginsInstallError, l as reportPluginsInstall } from "../_chunks/plugins-B2Gym8Lw.js";
@@ -1 +1 @@
1
- export { t as aliases, n as builder, r as command, i as describe, a as handler } from "../_chunks/profile-H0d7gFrX.js";
1
+ export { t as aliases, n as builder, r as command, i as describe, a as handler } from "../_chunks/profile-BAlM625e.js";
@@ -1 +1 @@
1
- export { t as builder, n as command, r as describe, i as handler } from "../_chunks/status-DS_yUXFo.js";
1
+ export { t as builder, n as command, r as describe, i as handler } from "../_chunks/status-BC4XXuuE.js";
@@ -28,7 +28,7 @@ const formatDurationSeconds = (totalSeconds) => {
28
28
  const toNeonConfigView = (resolved, preview) => {
29
29
  const view = {};
30
30
  if (resolved.authEnabled) view.auth = true;
31
- if (resolved.dataApiEnabled) view.dataApi = true;
31
+ if (resolved.dataApiEnabled) view.dataApi = toDataApiView(resolved.dataApi);
32
32
  const previewView = toPreviewView(preview);
33
33
  if (previewView) view.preview = previewView;
34
34
  const branch = {};
@@ -39,6 +39,14 @@ const toNeonConfigView = (resolved, preview) => {
39
39
  if (Object.keys(branch).length > 0) view.branch = branch;
40
40
  return view;
41
41
  };
42
+ const toDataApiView = (dataApi) => {
43
+ if (dataApi?.authProvider !== "external") return true;
44
+ const view = { authProvider: "external" };
45
+ if (dataApi.jwksUrl !== void 0) view.jwksUrl = dataApi.jwksUrl;
46
+ if (dataApi.providerName !== void 0) view.providerName = dataApi.providerName;
47
+ if (dataApi.jwtAudience !== void 0) view.jwtAudience = dataApi.jwtAudience;
48
+ return view;
49
+ };
42
50
  const toPreviewView = (preview) => {
43
51
  if (!preview) return void 0;
44
52
  const out = {};
@@ -18,8 +18,9 @@ const REQUIRED_PACKAGES = [CONFIG_PACKAGE, ENV_PACKAGE];
18
18
  * from these names to the `neon.ts` fields (`aiGateway`, `functions`, `buckets`, `dataApi`).
19
19
  *
20
20
  * Postgres is absent because every branch has it, so there is nothing to declare. Selecting
21
- * `data-api` also writes `auth: true`: the default Data API provider requires Neon Auth, and
22
- * `defineConfig` type-errors the file without it.
21
+ * `data-api` also writes `auth: true` unless the caller says the Data API verifies an external
22
+ * provider (see {@link DataApiTemplateChoice}): the default Data API provider requires Neon
23
+ * Auth, and `defineConfig` type-errors the file without it.
23
24
  */
24
25
  const CONFIG_INIT_SERVICES = NEON_SERVICES.filter((service) => service !== "postgres");
25
26
  /**
@@ -64,18 +65,44 @@ const renderGaServices = (services) => {
64
65
  if (lines.length === 0) return "";
65
66
  return `${lines.join("\n")}\n`;
66
67
  };
68
+ /** The template choice for a view's `dataApi` entry (`config status` / `--from-branch`). */
69
+ const dataApiChoiceFromView = (dataApi) => {
70
+ if (dataApi === true) return { kind: "neon" };
71
+ const { authProvider: _provider, ...wiring } = dataApi;
72
+ return {
73
+ kind: "external",
74
+ ...wiring
75
+ };
76
+ };
77
+ /**
78
+ * The `dataApi` entry, ending in a newline. The external form carries whatever wiring is
79
+ * known; without a JWKS URL it still type-checks (the URL is optional) and still declares the
80
+ * Data API, so a comment says where the URL lives rather than inventing one.
81
+ */
82
+ const renderDataApiEntry = (choice) => {
83
+ if (choice.kind === "neon") return `${at(1, "dataApi: true,").join("\n")}\n`;
84
+ const fields = at(2, `authProvider: "external",`);
85
+ if (choice.jwksUrl === void 0) fields.push(...at(2, "// The JWKS URL is registered on the project; add `jwksUrl` to declare it here too."));
86
+ else fields.push(...at(2, `jwksUrl: ${renderScalar(choice.jwksUrl)},`));
87
+ if (choice.providerName !== void 0) fields.push(...at(2, `providerName: ${renderScalar(choice.providerName)},`));
88
+ if (choice.jwtAudience !== void 0) fields.push(...at(2, `jwtAudience: ${renderScalar(choice.jwtAudience)},`));
89
+ return `${block(1, "dataApi", fields).join("\n")}\n`;
90
+ };
67
91
  /**
68
92
  * Render the `neon.ts` policy `config init` writes. With no services this is the starter
69
93
  * policy — an explicit `auth: false`, no service keys beyond that, and a `branch` closure that gives
70
94
  * new non-default branches a 7-day TTL — so the picker's "skip everything" answer and a
71
95
  * non-interactive run produce the identical file.
72
96
  *
73
- * `data-api` writes `dataApi: true` and forces `auth: true`. The default provider is Neon
74
- * Auth; omitting auth is a `defineConfig` type error rather than a deploy-time surprise.
97
+ * `data-api` writes `dataApi: true` and forces `auth: true` unless `options.dataApi` says the
98
+ * branch's Data API verifies an external provider. The default provider is Neon Auth;
99
+ * omitting auth is a `defineConfig` type error rather than a deploy-time surprise.
75
100
  */
76
- const renderNeonConfig = (services) => {
77
- const auth = services.includes("auth") || services.includes("data-api");
78
- const dataApi = services.includes("data-api") ? " dataApi: true,\n" : "";
101
+ const renderNeonConfig = (services, options = {}) => {
102
+ const dataApiChoice = options.dataApi ?? { kind: "neon" };
103
+ const declaresDataApi = services.includes("data-api");
104
+ const auth = services.includes("auth") || declaresDataApi && dataApiChoice.kind !== "external";
105
+ const dataApi = declaresDataApi ? renderDataApiEntry(dataApiChoice) : "";
79
106
  const realtimeDeclaration = services.includes("realtime") ? " preview: {\n realtime: true,\n },\n" : "";
80
107
  return `import { defineConfig } from "${CONFIG_PACKAGE}/v1";
81
108
 
@@ -154,7 +181,7 @@ const renderSeededGaServices = (view, branchName) => {
154
181
  * than an empty `defineConfig({})`: seeding found nothing, and the caller says so.
155
182
  */
156
183
  const renderNeonConfigFromView = (view, branchName) => {
157
- const services = [view.auth ? " auth: true," : "", view.dataApi ? " dataApi: true," : ""].filter((line) => line !== "");
184
+ const services = [view.auth ? " auth: true," : "", view.dataApi ? renderDataApiEntry(dataApiChoiceFromView(view.dataApi)).trimEnd() : ""].filter((line) => line !== "");
158
185
  const gaServices = renderSeededGaServices(view, branchName);
159
186
  const branch = renderSeededBranch(view);
160
187
  if (services.length === 0 && gaServices === "" && branch === "") return {
@@ -202,4 +229,4 @@ const renderFunctionSource = (slug, language) => {
202
229
  `;
203
230
  };
204
231
  const FUNCTION_TEMPLATE = renderFunctionSource(FUNCTION_SLUG, "ts");
205
- export { BUCKET_NAME, CONFIG_INIT_SERVICES, CONFIG_PACKAGE, ENV_PACKAGE, FUNCTION_FILENAME, FUNCTION_NAME, FUNCTION_SLUG, FUNCTION_TEMPLATE, REQUIRED_PACKAGES, parseConfigInitServices, renderFunctionSource, renderKey, renderNeonConfig, renderNeonConfigFromView };
232
+ export { BUCKET_NAME, CONFIG_INIT_SERVICES, CONFIG_PACKAGE, ENV_PACKAGE, FUNCTION_FILENAME, FUNCTION_NAME, FUNCTION_SLUG, FUNCTION_TEMPLATE, REQUIRED_PACKAGES, dataApiChoiceFromView, parseConfigInitServices, renderFunctionSource, renderKey, renderNeonConfig, renderNeonConfigFromView };