neon 8.4.5 → 8.6.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 (79) hide show
  1. package/README.md +18 -9
  2. package/dist/_chunks/{env-4WGRW2nw.js → env-BNm69Qh8.js} +2 -5
  3. package/dist/commands/config.js +11 -28
  4. package/dist/commands/dev.js +93 -27
  5. package/dist/commands/env.js +2 -3
  6. package/dist/commands/init.js +1 -2
  7. package/dist/commands/link.js +1 -1
  8. package/dist/commands/manifest.js +1 -3
  9. package/dist/commands/subscribe.js +16 -16
  10. package/dist/credential_io.js +1 -2
  11. package/dist/dev/env.js +1 -2
  12. package/dist/dev/runtime.js +8 -0
  13. package/dist/env_file.js +9 -1
  14. package/dist/index.js +1 -1
  15. package/dist/init/auth.js +1 -4
  16. package/dist/init/choices.js +21 -7
  17. package/dist/init/copy.js +21 -7
  18. package/dist/init/run.js +25 -16
  19. package/dist/plugins/run.js +2 -1
  20. package/dist/psql/command/cmd_io.js +1 -2
  21. package/dist/psql/command/cmd_pipeline.js +1 -2
  22. package/dist/psql/core/common.js +1 -2
  23. package/dist/psql/core/startup.js +1 -2
  24. package/dist/psql/index.js +1 -2
  25. package/dist/psql/types/index.js +1 -2
  26. package/dist/skills/catalog.js +5 -0
  27. package/dist/utils/hooks.js +0 -2
  28. package/dist/utils/staging.js +1 -14
  29. package/{LICENSE → dist/vendor/postgres-meta/LICENSE} +0 -1
  30. package/dist/vendor/postgres-meta/constants.js +14 -0
  31. package/dist/vendor/postgres-meta/lib/PostgresMeta.js +49 -0
  32. package/dist/vendor/postgres-meta/lib/PostgresMetaColumnPrivileges.js +85 -0
  33. package/dist/vendor/postgres-meta/lib/PostgresMetaColumns.js +235 -0
  34. package/dist/vendor/postgres-meta/lib/PostgresMetaConfig.js +16 -0
  35. package/dist/vendor/postgres-meta/lib/PostgresMetaExtensions.js +79 -0
  36. package/dist/vendor/postgres-meta/lib/PostgresMetaForeignTables.js +81 -0
  37. package/dist/vendor/postgres-meta/lib/PostgresMetaFunctions.js +173 -0
  38. package/dist/vendor/postgres-meta/lib/PostgresMetaIndexes.js +42 -0
  39. package/dist/vendor/postgres-meta/lib/PostgresMetaMaterializedViews.js +84 -0
  40. package/dist/vendor/postgres-meta/lib/PostgresMetaPolicies.js +120 -0
  41. package/dist/vendor/postgres-meta/lib/PostgresMetaPublications.js +193 -0
  42. package/dist/vendor/postgres-meta/lib/PostgresMetaRelationships.js +87 -0
  43. package/dist/vendor/postgres-meta/lib/PostgresMetaRoles.js +203 -0
  44. package/dist/vendor/postgres-meta/lib/PostgresMetaSchemas.js +105 -0
  45. package/dist/vendor/postgres-meta/lib/PostgresMetaTablePrivileges.js +91 -0
  46. package/dist/vendor/postgres-meta/lib/PostgresMetaTables.js +183 -0
  47. package/dist/vendor/postgres-meta/lib/PostgresMetaTriggers.js +156 -0
  48. package/dist/vendor/postgres-meta/lib/PostgresMetaTypes.js +22 -0
  49. package/dist/vendor/postgres-meta/lib/PostgresMetaVersion.js +20 -0
  50. package/dist/vendor/postgres-meta/lib/PostgresMetaViews.js +83 -0
  51. package/dist/vendor/postgres-meta/lib/constants.js +8 -0
  52. package/dist/vendor/postgres-meta/lib/db.js +147 -0
  53. package/dist/vendor/postgres-meta/lib/generators.js +106 -0
  54. package/dist/vendor/postgres-meta/lib/helpers.js +26 -0
  55. package/dist/vendor/postgres-meta/lib/index.js +1 -0
  56. package/dist/vendor/postgres-meta/lib/sql/column_privileges.sql.js +154 -0
  57. package/dist/vendor/postgres-meta/lib/sql/columns.sql.js +123 -0
  58. package/dist/vendor/postgres-meta/lib/sql/common.js +1 -0
  59. package/dist/vendor/postgres-meta/lib/sql/config.sql.js +32 -0
  60. package/dist/vendor/postgres-meta/lib/sql/extensions.sql.js +20 -0
  61. package/dist/vendor/postgres-meta/lib/sql/foreign_tables.sql.js +20 -0
  62. package/dist/vendor/postgres-meta/lib/sql/functions.sql.js +141 -0
  63. package/dist/vendor/postgres-meta/lib/sql/indexes.sql.js +51 -0
  64. package/dist/vendor/postgres-meta/lib/sql/materialized_views.sql.js +21 -0
  65. package/dist/vendor/postgres-meta/lib/sql/policies.sql.js +53 -0
  66. package/dist/vendor/postgres-meta/lib/sql/publications.sql.js +46 -0
  67. package/dist/vendor/postgres-meta/lib/sql/roles.sql.js +40 -0
  68. package/dist/vendor/postgres-meta/lib/sql/schemas.sql.js +26 -0
  69. package/dist/vendor/postgres-meta/lib/sql/table.sql.js +109 -0
  70. package/dist/vendor/postgres-meta/lib/sql/table_privileges.sql.js +85 -0
  71. package/dist/vendor/postgres-meta/lib/sql/table_relationships.sql.js +52 -0
  72. package/dist/vendor/postgres-meta/lib/sql/triggers.sql.js +64 -0
  73. package/dist/vendor/postgres-meta/lib/sql/types.sql.js +65 -0
  74. package/dist/vendor/postgres-meta/lib/sql/version.sql.js +15 -0
  75. package/dist/vendor/postgres-meta/lib/sql/views.sql.js +22 -0
  76. package/dist/vendor/postgres-meta/lib/sql/views_key_dependencies.sql.js +198 -0
  77. package/dist/vendor/postgres-meta/lib/types.js +1 -0
  78. package/dist/vendor/postgres-meta/templates/typescript.js +608 -0
  79. package/package.json +12 -5
package/dist/dev/env.js CHANGED
@@ -1,2 +1 @@
1
- import { a as resolveDevEnv, i as dropClaimableUnsupported, n as MissingBranchContextError, o as resolveNeonEnvVars, r as ServiceNotOnBranchError, t as DevEnvMismatchError } from "../_chunks/env-4WGRW2nw.js";
2
- export { DevEnvMismatchError, MissingBranchContextError, ServiceNotOnBranchError, dropClaimableUnsupported, resolveDevEnv, resolveNeonEnvVars };
1
+ export { t as DevEnvMismatchError, n as MissingBranchContextError, r as ServiceNotOnBranchError, i as dropClaimableUnsupported, a as resolveDevEnv, o as resolveNeonEnvVars } from "../_chunks/env-BNm69Qh8.js";
@@ -121,6 +121,14 @@ const portSelectionFromEnv = (env) => {
121
121
  mode: "explicit",
122
122
  port: parsePort(explicit, "NEON_DEV_PORT")
123
123
  };
124
+ const searchBase = env.NEON_DEV_PORT_BASE;
125
+ if (searchBase !== void 0 && searchBase !== "") {
126
+ const from = Number(searchBase);
127
+ return {
128
+ mode: "search",
129
+ from: Number.isInteger(from) ? from : DEFAULT_SEARCH_BASE
130
+ };
131
+ }
124
132
  const injected = env.PORT;
125
133
  if (injected !== void 0 && injected !== "") return {
126
134
  mode: "explicit",
package/dist/env_file.js CHANGED
@@ -15,6 +15,14 @@ const resolveEnvFilePath = (location, file) => {
15
15
  return join(dir, ".env.local");
16
16
  };
17
17
  /**
18
+ * The dotenv files `neon dev` loads by default, in load order: the project directory's
19
+ * `.env`, then `.env.local`, whose values override it. Missing files are skipped.
20
+ */
21
+ const defaultDevEnvFiles = (location) => {
22
+ const dir = projectDir(location);
23
+ return [join(dir, ".env"), join(dir, ".env.local")].filter((path) => existsSync(path));
24
+ };
25
+ /**
18
26
  * Merge `updates` into the dotenv content at `path`, preserving every other line
19
27
  * (comments, blank lines, unrelated keys) and the file's existing order. Keys present in
20
28
  * both are updated in place; keys only in `updates` are appended. A non-existent file is
@@ -145,4 +153,4 @@ const trimTrailingBlank = (lines) => {
145
153
  return out;
146
154
  };
147
155
  //#endregion
148
- export { loadEnvFileIntoProcess, mergeEnvContent, mergeEnvFile, readEnvFile, resolveEnvFilePath };
156
+ export { defaultDevEnvFiles, loadEnvFileIntoProcess, mergeEnvContent, mergeEnvFile, readEnvFile, resolveEnvFilePath };
package/dist/index.js CHANGED
@@ -12,13 +12,13 @@ import { getCliName } from "./utils/cli_name.js";
12
12
  import { ensureAuth } from "./commands/auth.js";
13
13
  import { recoverFrom401 } from "./auth_recovery.js";
14
14
  import { UsageError, failOnUsageError, isBareParentCommand, showHelp, showUsageErrorHelp } from "./help.js";
15
- import { stagingFeaturesEnabledForArgv } from "./utils/staging.js";
16
15
  import { lazyCommands, preloadCommand } from "./commands/manifest.js";
17
16
  import { rewriteUnknownAgentArg } from "./init/plan.js";
18
17
  import { recoverFromSSO } from "./sso_recovery.js";
19
18
  import { notifyIfUpdateAvailable } from "./update_notifier.js";
20
19
  import { fillInArgs, resolveApiKeyFromEnv } from "./utils/middlewares.js";
21
20
  import { collapseRepeatedFlags, declaredOptions } from "./utils/repeated_flags.js";
21
+ import { stagingFeaturesEnabledForArgv } from "./utils/staging.js";
22
22
  import yargs from "yargs";
23
23
  import { hideBin } from "yargs/helpers";
24
24
  //#region src/index.ts
package/dist/init/auth.js CHANGED
@@ -61,10 +61,7 @@ const runAuthenticatedMcp = async (options) => {
61
61
  const pullInitEnv = async (props) => {
62
62
  const authenticated = authContext(props, ["env", "pull"]);
63
63
  await ensureAuth(authenticated);
64
- const opts = {
65
- announce: true,
66
- implyAiGateway: true
67
- };
64
+ const opts = { announce: true };
68
65
  try {
69
66
  return await pull(authenticated, opts);
70
67
  } catch (error) {
@@ -1,3 +1,5 @@
1
+ import { FUNCTION_SLUG } from "../config_template.js";
2
+ import { l as functionBaseUrlKey } from "../_chunks/env-BpP3Dqpe.js";
1
3
  //#region src/init/choices.ts
2
4
  const INIT_CONFIG_SERVICES_CONFLICT = "--no-config cannot be combined with --services.";
3
5
  const resolveInitConfigChoice = (input) => {
@@ -21,11 +23,23 @@ const configPlanFromResolution = (resolution, accepted) => {
21
23
  if (resolution.kind === "skip") return { kind: "skip" };
22
24
  return resolution;
23
25
  };
24
- const shouldRefreshEnvAfterNewConfig = (input) => input.wroteNewFile && typeof input.projectId === "string" && input.projectId.length > 0 && typeof input.branch === "string" && input.branch.length > 0;
25
- const shouldPullEnvAfterInitConfig = (input) => !input.extraServices && !input.alreadyPulled && shouldRefreshEnvAfterNewConfig({
26
- wroteNewFile: input.wroteNewFile,
27
- ...input.projectId !== void 0 ? { projectId: input.projectId } : {},
28
- ...input.branch !== void 0 ? { branch: input.branch } : {}
29
- });
26
+ /**
27
+ * A neon.ts policy pull fails while the branch lacks a declared service. These two need
28
+ * no `deploy`: the AI Gateway exists on every branch, and function URLs derive from the
29
+ * branch host.
30
+ */
31
+ const DEPLOY_FREE_SERVICES = /* @__PURE__ */ new Set(["ai-gateway", "functions"]);
32
+ const needsDeploy = (declared) => declared.some((service) => !DEPLOY_FREE_SERVICES.has(service));
33
+ const initEnvPullAfterConfig = (input) => {
34
+ if (!input.projectId || !input.branch) return { kind: "skip" };
35
+ if (!input.linkDeferredPull && !input.wroteNewFile) return { kind: "skip" };
36
+ if (input.claimable && input.declared.length > 0) return { kind: "skip" };
37
+ if (!needsDeploy(input.declared)) return { kind: "policy" };
38
+ return {
39
+ kind: "services",
40
+ services: input.declared.includes("ai-gateway") ? ["postgres", "ai-gateway"] : ["postgres"],
41
+ envKeys: input.declared.includes("functions") ? [functionBaseUrlKey(FUNCTION_SLUG)] : []
42
+ };
43
+ };
30
44
  //#endregion
31
- export { INIT_CONFIG_SERVICES_CONFLICT, configPlanFromResolution, resolveInitConfigChoice, shouldPullEnvAfterInitConfig, shouldRefreshEnvAfterNewConfig };
45
+ export { INIT_CONFIG_SERVICES_CONFLICT, configPlanFromResolution, initEnvPullAfterConfig, resolveInitConfigChoice };
package/dist/init/copy.js CHANGED
@@ -99,16 +99,22 @@ const offlinePinNext = (input) => [
99
99
  ...input.envPull !== void 0 ? ["Then pull the branch's environment variables:", input.envPull] : []
100
100
  ];
101
101
  const skippedLinkNext = () => ["To connect this directory to a Neon project:", `${getCliName()} link`];
102
- const extraServicesNext = () => [
103
- "Review neon.ts and confirm the linked project and branch before deploying.",
102
+ const extraServicesNext = (input) => [
104
103
  "Preview the changes:",
105
104
  `${getCliName()} config plan`,
106
105
  "",
107
- "Deploy when the changes and target are correct:",
106
+ "Deploy when the changes and target are correct. Deploy also pulls the branch's environment variables:",
108
107
  `${getCliName()} deploy`,
109
108
  "",
110
- "Refresh local environment variables after deployment:",
111
- `${getCliName()} env pull`
109
+ "Optional, once deployed:",
110
+ ...input.functions ? [
111
+ "Run Neon Functions locally:",
112
+ `${getCliName()} dev`,
113
+ ""
114
+ ] : [],
115
+ "Work on a development branch created from neon.ts:",
116
+ `${getCliName()} checkout dev --create`,
117
+ ...input.skills ? ["", "Set up the services declared in neon.ts with your coding agent. The Neon agent skills cover best practices for each one."] : []
112
118
  ];
113
119
  const existingConfigNext = () => ["The existing Neon config was preserved. Refresh environment variables when its declared services are available:", `${getCliName()} env pull`];
114
120
  const claimableNext = (expiresAt) => [
@@ -128,10 +134,18 @@ const claimableThenServicesNext = (expiresAt) => [
128
134
  "Refresh local environment variables:",
129
135
  `${getCliName()} env pull`
130
136
  ];
131
- const installFailedNext = (command) => ({
137
+ const installFailedNext = (command, envPull) => ({
132
138
  heading: HEADING_FAILED,
133
139
  body: "Could not install the Neon dependencies.",
134
- next: ["Install the dependencies, then run neon init again:", command]
140
+ next: [
141
+ "Install the dependencies, then run neon init again:",
142
+ command,
143
+ ...envPull ? [
144
+ "",
145
+ "Then pull the branch's environment variables:",
146
+ `${getCliName()} env pull`
147
+ ] : []
148
+ ]
135
149
  });
136
150
  const MCP_API_KEY_NEEDS_AUTH = "API-key MCP setup needs a Neon credential to mint the key. Sign in with `neon login` or pass a personal API key.";
137
151
  /** `mcp` is the `neon mcp` invocation without an auth flag. */
package/dist/init/run.js CHANGED
@@ -9,7 +9,6 @@ import { getCliName } from "../utils/cli_name.js";
9
9
  import { servicesFlagValue } from "../neon_services.js";
10
10
  import { CONFIG_INIT_SERVICES, parseConfigInitServices } from "../config_template.js";
11
11
  import { hasNeonConfigFile, neonConfigFilename } from "../project.js";
12
- import { assertRealtimeAvailable } from "../utils/staging.js";
13
12
  import { getAgentDisplayName } from "../mcp/agents.js";
14
13
  import { mcpInstallableAgents } from "../mcp/targets.js";
15
14
  import { missingPluginsCommands, pluginsInstallableAgents } from "../plugins/targets.js";
@@ -27,7 +26,7 @@ import { InitCancelled, raceSigint, restoreCursor } from "./cancelled.js";
27
26
  import { pickAgentSetupInteractively, pickInitAgentsInteractively, pickInitConfigInteractively, pickInitMcpAuthInteractively, pickInitMcpConfigLocationInteractively, pickInitModeInteractively, pickInitPackageManagerInteractively, pickInitProjectSetupInteractively, pickInitServicesInteractively, pickInitSkillsInteractively } from "./wizard.js";
28
27
  import { runToolingSteps } from "./tooling.js";
29
28
  import { create } from "../commands/claim.js";
30
- import { INIT_CONFIG_SERVICES_CONFLICT, configPlanFromResolution, resolveInitConfigChoice, shouldPullEnvAfterInitConfig } from "./choices.js";
29
+ import { INIT_CONFIG_SERVICES_CONFLICT, configPlanFromResolution, initEnvPullAfterConfig, resolveInitConfigChoice } from "./choices.js";
31
30
  import { detectInitEnvironment } from "./detect.js";
32
31
  import { createInitFunnel, emitInitStart, finishInitFunnel, initStartProperties } from "./funnel.js";
33
32
  import { assertAgentSetupFlags, hasInitMcpFlags, inferInitAgentSetup, resolveInitMode } from "./mode.js";
@@ -184,7 +183,7 @@ const runInit = async (props) => {
184
183
  };
185
184
  const servicesFlag = servicesFlagValue(props.services);
186
185
  if (props.config === false && servicesFlag !== void 0) throw new Error(INIT_CONFIG_SERVICES_CONFLICT);
187
- if (servicesFlag !== void 0 && parseConfigInitServices(servicesFlag).includes("realtime")) assertRealtimeAvailable(props.apiHost);
186
+ if (servicesFlag !== void 0) parseConfigInitServices(servicesFlag);
188
187
  const linkInputs = {
189
188
  ...props.orgId ? { orgId: props.orgId } : {},
190
189
  ...props.projectId ? { projectId: props.projectId } : {},
@@ -370,7 +369,6 @@ const runInit = async (props) => {
370
369
  });
371
370
  if (toolingSteps.length > 0) await runTooling(toolingSteps, earlyTooling);
372
371
  let projectSetup = "skip";
373
- let linkedNow = false;
374
372
  let claimExpiresAt;
375
373
  const noLink = props.link === false;
376
374
  const linkByDefault = detection.authenticated || hasExplicitLinkInputs && !yes;
@@ -395,6 +393,7 @@ const runInit = async (props) => {
395
393
  funnel.link = "skipped";
396
394
  } else if (props.pickProjectSetup !== void 0 || detection.interactive) projectSetup = await (props.pickProjectSetup ?? pickInitProjectSetupInteractively)();
397
395
  else throw new Error(NON_TTY_LINK_NEEDS_AUTH);
396
+ const deferLinkPull = !existingConfig && props.config !== false;
398
397
  const linkProps = {
399
398
  apiClient: props.apiClient,
400
399
  apiKey: props.apiKey,
@@ -405,6 +404,7 @@ const runInit = async (props) => {
405
404
  clear: false,
406
405
  checks: true,
407
406
  envPull: true,
407
+ deferEnvPull: deferLinkPull,
408
408
  config: false,
409
409
  cwd,
410
410
  ...linkInputs,
@@ -426,13 +426,11 @@ const runInit = async (props) => {
426
426
  apiKey: props.apiKey,
427
427
  ...props.profile !== void 0 ? { profile: props.profile } : {}
428
428
  });
429
- linkedNow = true;
430
429
  funnel.link = "claimable";
431
430
  claimExpiresAt = readLinkedClaimableCredentials(configDir, readContextFile(contextFile))?.expiresAt;
432
431
  } else if (projectSetup === "link") {
433
432
  printInitProgress(detection.authenticated ? PROGRESS.link : PROGRESS.auth);
434
433
  await (props.linkProject ?? runAuthenticatedLink)(linkProps);
435
- linkedNow = true;
436
434
  funnel.link = "linked";
437
435
  }
438
436
  const pinnedOffline = funnel.link === "skipped" && !noLink && linkInputs.orgId !== void 0 && linkInputs.projectId !== void 0 && linkInputs.branch !== void 0 && linkInputs.projectName === void 0 && linkInputs.regionId === void 0;
@@ -442,7 +440,6 @@ const runInit = async (props) => {
442
440
  checks: false,
443
441
  envPull: false
444
442
  });
445
- linkedNow = true;
446
443
  funnel.link = "linked";
447
444
  }
448
445
  if (delayMcp && tooling.setup !== "skip" && props.mcpProjectScoped === true && funnel.link === "skipped" && !noLink) mcpState.deferredPin = linkInputs.projectId !== void 0 ? quoteFlagValue(linkInputs.projectId) : "<project-id>";
@@ -502,11 +499,13 @@ const runInit = async (props) => {
502
499
  };
503
500
  let wroteNewFile = false;
504
501
  let extraServices = false;
502
+ let declared = [];
505
503
  let selectedServices = null;
504
+ const linkDeferredPull = deferLinkPull && projectSetup === "link" && funnel.link === "linked";
506
505
  if (configPlan.kind === "write") {
507
506
  const planned = existingConfig ? void 0 : configPlan.services ?? ["postgres"];
508
507
  if (planned !== void 0) {
509
- const declared = parseConfigInitServices(planned);
508
+ declared = parseConfigInitServices(planned);
510
509
  extraServices = declared.length > 0;
511
510
  selectedServices = expandTelemetryServices(declared);
512
511
  funnel.services = selectedServices;
@@ -529,7 +528,7 @@ const runInit = async (props) => {
529
528
  });
530
529
  } catch (error) {
531
530
  if (error instanceof ConfigInstallFailed) {
532
- const failed = installFailedNext(error.command);
531
+ const failed = installFailedNext(error.command, linkDeferredPull);
533
532
  printInitDone(formatInitDone({
534
533
  heading: failed.heading,
535
534
  body: failed.body,
@@ -547,14 +546,15 @@ const runInit = async (props) => {
547
546
  const context = readContextFile(contextFile);
548
547
  const branch = contextBranch(context);
549
548
  const linked = isLinked(contextFile);
550
- const alreadyPulled = linkedNow && funnel.link === "linked" && !pinnedOffline;
551
- if (funnel.link !== "skipped" && !pinnedOffline && shouldPullEnvAfterInitConfig({
549
+ const envPullPlan = funnel.link === "skipped" || pinnedOffline ? { kind: "skip" } : initEnvPullAfterConfig({
550
+ linkDeferredPull,
552
551
  wroteNewFile,
553
- extraServices,
554
- alreadyPulled,
552
+ declared,
553
+ claimable: funnel.link === "claimable",
555
554
  ...typeof context.projectId === "string" ? { projectId: context.projectId } : {},
556
555
  ...branch !== void 0 ? { branch } : {}
557
- })) try {
556
+ });
557
+ if (envPullPlan.kind !== "skip") try {
558
558
  if (typeof context.projectId !== "string" || typeof branch !== "string") throw new Error("Env pull requires a linked project and branch.");
559
559
  printInitProgress(PROGRESS.env);
560
560
  await raceSigint((props.envPull ?? pullInitEnv)({
@@ -562,7 +562,11 @@ const runInit = async (props) => {
562
562
  output: props.output,
563
563
  cwd,
564
564
  projectId: context.projectId,
565
- branch
565
+ branch,
566
+ ...envPullPlan.kind === "services" ? {
567
+ services: envPullPlan.services,
568
+ envKeys: envPullPlan.envKeys
569
+ } : {}
566
570
  }));
567
571
  } catch (error) {
568
572
  if (error instanceof InitCancelled) throw error;
@@ -618,7 +622,10 @@ const runInit = async (props) => {
618
622
  next.push(...claimableNext(claimExpiresAt));
619
623
  } else if (pendingServices) {
620
624
  if (next.length > 0) next.push("");
621
- next.push(...extraServicesNext());
625
+ next.push(...extraServicesNext({
626
+ skills: installsSkills(reportedTooling()),
627
+ functions: declared.includes("functions")
628
+ }));
622
629
  } else if (pendingExisting) {
623
630
  if (next.length > 0) next.push("");
624
631
  next.push(...existingConfigNext());
@@ -699,6 +706,8 @@ const withoutMcp = (tooling) => {
699
706
  };
700
707
  return tooling;
701
708
  };
709
+ /** The Neon plugin bundles the skills. */
710
+ const installsSkills = (tooling) => tooling.setup === "skills-mcp" ? tooling.skillsAgents.length > 0 : tooling.setup !== "skip";
702
711
  const agentsFromTooling = (tooling) => {
703
712
  switch (tooling.setup) {
704
713
  case "skip": return [];
@@ -12,7 +12,8 @@ const PLUGIN_SKILLS = [
12
12
  "neon-object-storage",
13
13
  "neon-postgres",
14
14
  "neon-postgres-branches",
15
- "neon-postgres-egress-optimizer"
15
+ "neon-postgres-egress-optimizer",
16
+ "neon-realtime"
16
17
  ];
17
18
  const PLUGINS_CLI_TIMEOUT_MS = 12e4;
18
19
  const pluginsChildEnv = (base = process.env) => {
@@ -1,2 +1 @@
1
- import { A as cmdPrint, C as cmdGdesc, D as cmdInclude, E as cmdGx, F as registerIoCommands, M as cmdWrite, N as formatWatchTimestamp, O as cmdIncludeRel, P as getQueryFout, S as cmdG, T as cmdGset, b as WATCH_TEST_CONTROLLER, j as cmdWatch, k as cmdOut, w as cmdGexec, x as clearPipelineGateErrors, y as DEFAULT_WATCH_INTERVAL } from "../../_chunks/cmd_pipeline-CEk93dGN.js";
2
- export { DEFAULT_WATCH_INTERVAL, WATCH_TEST_CONTROLLER, clearPipelineGateErrors, cmdG, cmdGdesc, cmdGexec, cmdGset, cmdGx, cmdInclude, cmdIncludeRel, cmdOut, cmdPrint, cmdWatch, cmdWrite, formatWatchTimestamp, getQueryFout, registerIoCommands };
1
+ export { y as DEFAULT_WATCH_INTERVAL, b as WATCH_TEST_CONTROLLER, x as clearPipelineGateErrors, S as cmdG, C as cmdGdesc, w as cmdGexec, T as cmdGset, E as cmdGx, D as cmdInclude, O as cmdIncludeRel, k as cmdOut, A as cmdPrint, j as cmdWatch, M as cmdWrite, N as formatWatchTimestamp, P as getQueryFout, F as registerIoCommands } from "../../_chunks/cmd_pipeline-CEk93dGN.js";
@@ -1,2 +1 @@
1
- import { C as cmdGdesc, _ as stagedNamedBindPresent, a as cmdFlush, c as cmdParse, d as cmdSyncPipeline, f as consumeBindState, g as registerPipelineCommands, h as lookupPrepared, i as cmdEndPipeline, l as cmdSendPipeline, m as getPipelineState, n as cmdBindNamed, o as cmdFlushRequest, p as dropPrepared, r as cmdClosePrepared, s as cmdGetResults, t as cmdBind, u as cmdStartPipeline, v as stashPrepared } from "../../_chunks/cmd_pipeline-CEk93dGN.js";
2
- export { cmdBind, cmdBindNamed, cmdClosePrepared, cmdEndPipeline, cmdFlush, cmdFlushRequest, cmdGdesc, cmdGetResults, cmdParse, cmdSendPipeline, cmdStartPipeline, cmdSyncPipeline, consumeBindState, dropPrepared, getPipelineState, lookupPrepared, registerPipelineCommands, stagedNamedBindPresent, stashPrepared };
1
+ export { t as cmdBind, n as cmdBindNamed, r as cmdClosePrepared, i as cmdEndPipeline, a as cmdFlush, o as cmdFlushRequest, C as cmdGdesc, s as cmdGetResults, c as cmdParse, l as cmdSendPipeline, u as cmdStartPipeline, d as cmdSyncPipeline, f as consumeBindState, p as dropPrepared, m as getPipelineState, h as lookupPrepared, g as registerPipelineCommands, _ as stagedNamedBindPresent, v as stashPrepared } from "../../_chunks/cmd_pipeline-CEk93dGN.js";
@@ -1,2 +1 @@
1
- import { B as psqlExec, G as writeQueryError, H as renderResultSet, I as __testing, L as captureLastError, R as executeAndPrint, U as sendQuery, V as refreshErrorVars, W as stripLeadingCommentsAndWS, z as pickOut } from "../../_chunks/cmd_pipeline-CEk93dGN.js";
2
- export { __testing, captureLastError, executeAndPrint, pickOut, psqlExec, refreshErrorVars, renderResultSet, sendQuery, stripLeadingCommentsAndWS, writeQueryError };
1
+ export { I as __testing, L as captureLastError, R as executeAndPrint, z as pickOut, B as psqlExec, V as refreshErrorVars, H as renderResultSet, U as sendQuery, W as stripLeadingCommentsAndWS, G as writeQueryError } from "../../_chunks/cmd_pipeline-CEk93dGN.js";
@@ -1,2 +1 @@
1
- import { f as CLIENT_VERSION, h as parseStartupArgs, m as formatParseError, p as applyStartupArgs } from "../../_chunks/psql-BNljLda2.js";
2
- export { CLIENT_VERSION, applyStartupArgs, formatParseError, parseStartupArgs };
1
+ export { f as CLIENT_VERSION, p as applyStartupArgs, m as formatParseError, h as parseStartupArgs } from "../../_chunks/psql-BNljLda2.js";
@@ -1,2 +1 @@
1
- import { a as mergeConnectOptions, c as parseConnectionUriService, d as serviceEntryToConnectOptions, i as looksLikeConnectionString, l as parseConninfo, n as envConnectionDefaults, o as parseConnectionUri, r as libpqConnectionDefaults, s as parseConnectionUriPartial, t as defaultClientCertDefaults, u as runPsql } from "../_chunks/psql-BNljLda2.js";
2
- export { defaultClientCertDefaults, envConnectionDefaults, libpqConnectionDefaults, looksLikeConnectionString, mergeConnectOptions, parseConnectionUri, parseConnectionUriPartial, parseConnectionUriService, parseConninfo, runPsql, serviceEntryToConnectOptions };
1
+ export { t as defaultClientCertDefaults, n as envConnectionDefaults, r as libpqConnectionDefaults, i as looksLikeConnectionString, a as mergeConnectOptions, o as parseConnectionUri, s as parseConnectionUriPartial, c as parseConnectionUriService, l as parseConninfo, u as runPsql, d as serviceEntryToConnectOptions } from "../_chunks/psql-BNljLda2.js";
@@ -1,8 +1,7 @@
1
- import { initialScanState, isContinueStatus } from "./scanner.js";
1
+ export { initialScanState, isContinueStatus } from "./scanner.js";
2
2
  import "./backslash.js";
3
3
  import "./connection.js";
4
4
  import "./printer.js";
5
5
  import "./repl.js";
6
6
  import "./settings.js";
7
7
  import "./variables.js";
8
- export { initialScanState, isContinueStatus };
@@ -43,6 +43,11 @@ const NEON_SKILL_CATALOG = [
43
43
  source: AGENT_SKILLS_SOURCE,
44
44
  defaultSelected: true
45
45
  },
46
+ {
47
+ skill: "neon-realtime",
48
+ source: AGENT_SKILLS_SOURCE,
49
+ defaultSelected: true
50
+ },
46
51
  {
47
52
  skill: "neon-postgres-agent-platforms",
48
53
  source: PLATFORMS_SKILLS_SOURCE,
@@ -1,7 +1,6 @@
1
1
  import { log } from "../log.js";
2
2
  import { loadProjectConfig } from "../project.js";
3
3
  import { s as fetchEnvKeys } from "../_chunks/env-BpP3Dqpe.js";
4
- import { assertPolicyAvailable } from "./staging.js";
5
4
  import { runHook } from "@neon/config-runtime";
6
5
  //#region src/utils/hooks.ts
7
6
  /**
@@ -150,7 +149,6 @@ const runAfter = async (label, run) => {
150
149
  * postgres only, since nothing else is declared enabled).
151
150
  */
152
151
  const resolveHookEnv = async (config, options) => {
153
- assertPolicyAvailable(config, options.apiHost);
154
152
  try {
155
153
  const resolved = await fetchEnvKeys(config, options, null);
156
154
  return shapeHookEnv(resolved);
@@ -7,7 +7,6 @@ import { Parser, hideBin } from "yargs/helpers";
7
7
  * hidden from help and fail with a "coming soon" message.
8
8
  */
9
9
  const STAGING_API_HOST = "https://console-stage.neon.build/api/v2";
10
- const REALTIME_COMING_SOON = `Neon Realtime is coming soon! For now it only works on Neon's staging API: set NEON_API_HOST=${STAGING_API_HOST} or pass --api-host.`;
11
10
  /** `NEON_STAGING_API_HOST` lets the CLI's tests treat their local mock API as staging. */
12
11
  const stagingHostname = () => new URL(process.env.NEON_STAGING_API_HOST ?? "https://console-stage.neon.build/api/v2").hostname;
13
12
  const isStagingApiHost = (apiHost) => apiHost !== void 0 && URL.canParse(apiHost) && new URL(apiHost).hostname === stagingHostname();
@@ -26,8 +25,6 @@ const stagingFeaturesEnabledForArgv = (args = hideBin(process.argv)) => {
26
25
  };
27
26
  /** `apiHost` is a command's resolved host; without one, the host this process was invoked with. */
28
27
  const stagingFeaturesEnabled = (apiHost) => apiHost === void 0 ? stagingFeaturesEnabledForArgv() : isStagingApiHost(apiHost);
29
- /** Service names to list in help: Realtime only on staging. */
30
- const listedServices = (services) => stagingFeaturesEnabledForArgv() ? services : services.filter((service) => service !== "realtime");
31
28
  /** A hard stop: callers that degrade other failures to warnings let this one through. */
32
29
  var StagingOnlyError = class extends Error {
33
30
  constructor(..._args) {
@@ -35,15 +32,5 @@ var StagingOnlyError = class extends Error {
35
32
  this.name = "StagingOnlyError";
36
33
  }
37
34
  };
38
- const assertRealtimeAvailable = (apiHost) => {
39
- if (!stagingFeaturesEnabled(apiHost)) throw new StagingOnlyError(REALTIME_COMING_SOON);
40
- };
41
- /**
42
- * A `neon.ts` with any `preview.realtime` value reads the Realtime API, which production
43
- * does not serve. `false` reads it too, to disable Realtime on the branch.
44
- */
45
- const assertPolicyAvailable = (config, apiHost) => {
46
- if (config.preview?.realtime !== void 0) assertRealtimeAvailable(apiHost);
47
- };
48
35
  //#endregion
49
- export { REALTIME_COMING_SOON, STAGING_API_HOST, StagingOnlyError, assertPolicyAvailable, assertRealtimeAvailable, isStagingApiHost, listedServices, stagingFeaturesEnabled, stagingFeaturesEnabledForArgv };
36
+ export { STAGING_API_HOST, StagingOnlyError, isStagingApiHost, stagingFeaturesEnabled, stagingFeaturesEnabledForArgv };
@@ -1,4 +1,3 @@
1
-
2
1
  Apache License
3
2
  Version 2.0, January 2004
4
3
  http://www.apache.org/licenses/
@@ -0,0 +1,14 @@
1
+ //#region src/vendor/postgres-meta/constants.ts
2
+ const GENERATE_TYPES_DEFAULT_SCHEMA = process.env.PG_META_GENERATE_TYPES_DEFAULT_SCHEMA || "public";
3
+ const VALID_UNNAMED_FUNCTION_ARG_TYPES = /* @__PURE__ */ new Set([
4
+ 114,
5
+ 3802,
6
+ 25
7
+ ]);
8
+ const VALID_FUNCTION_ARGS_MODE = /* @__PURE__ */ new Set([
9
+ "in",
10
+ "inout",
11
+ "variadic"
12
+ ]);
13
+ //#endregion
14
+ export { GENERATE_TYPES_DEFAULT_SCHEMA, VALID_FUNCTION_ARGS_MODE, VALID_UNNAMED_FUNCTION_ARG_TYPES };
@@ -0,0 +1,49 @@
1
+ import PostgresMetaColumnPrivileges from "./PostgresMetaColumnPrivileges.js";
2
+ import PostgresMetaTables from "./PostgresMetaTables.js";
3
+ import PostgresMetaColumns from "./PostgresMetaColumns.js";
4
+ import PostgresMetaConfig from "./PostgresMetaConfig.js";
5
+ import PostgresMetaExtensions from "./PostgresMetaExtensions.js";
6
+ import PostgresMetaForeignTables from "./PostgresMetaForeignTables.js";
7
+ import PostgresMetaFunctions from "./PostgresMetaFunctions.js";
8
+ import PostgresMetaIndexes from "./PostgresMetaIndexes.js";
9
+ import PostgresMetaMaterializedViews from "./PostgresMetaMaterializedViews.js";
10
+ import PostgresMetaPolicies from "./PostgresMetaPolicies.js";
11
+ import PostgresMetaPublications from "./PostgresMetaPublications.js";
12
+ import PostgresMetaRelationships from "./PostgresMetaRelationships.js";
13
+ import PostgresMetaRoles from "./PostgresMetaRoles.js";
14
+ import PostgresMetaSchemas from "./PostgresMetaSchemas.js";
15
+ import PostgresMetaTablePrivileges from "./PostgresMetaTablePrivileges.js";
16
+ import PostgresMetaTriggers from "./PostgresMetaTriggers.js";
17
+ import PostgresMetaTypes from "./PostgresMetaTypes.js";
18
+ import PostgresMetaVersion from "./PostgresMetaVersion.js";
19
+ import PostgresMetaViews from "./PostgresMetaViews.js";
20
+ import { init } from "./db.js";
21
+ //#region src/vendor/postgres-meta/lib/PostgresMeta.ts
22
+ var PostgresMeta = class {
23
+ constructor(config) {
24
+ const { query, end } = init(config);
25
+ this.query = query;
26
+ this.end = end;
27
+ this.columnPrivileges = new PostgresMetaColumnPrivileges(this.query);
28
+ this.columns = new PostgresMetaColumns(this.query);
29
+ this.config = new PostgresMetaConfig(this.query);
30
+ this.extensions = new PostgresMetaExtensions(this.query);
31
+ this.foreignTables = new PostgresMetaForeignTables(this.query);
32
+ this.functions = new PostgresMetaFunctions(this.query);
33
+ this.indexes = new PostgresMetaIndexes(this.query);
34
+ this.materializedViews = new PostgresMetaMaterializedViews(this.query);
35
+ this.policies = new PostgresMetaPolicies(this.query);
36
+ this.publications = new PostgresMetaPublications(this.query);
37
+ this.relationships = new PostgresMetaRelationships(this.query);
38
+ this.roles = new PostgresMetaRoles(this.query);
39
+ this.schemas = new PostgresMetaSchemas(this.query);
40
+ this.tablePrivileges = new PostgresMetaTablePrivileges(this.query);
41
+ this.tables = new PostgresMetaTables(this.query);
42
+ this.triggers = new PostgresMetaTriggers(this.query);
43
+ this.types = new PostgresMetaTypes(this.query);
44
+ this.version = new PostgresMetaVersion(this.query);
45
+ this.views = new PostgresMetaViews(this.query);
46
+ }
47
+ };
48
+ //#endregion
49
+ export { PostgresMeta as default };
@@ -0,0 +1,85 @@
1
+ import { DEFAULT_SYSTEM_SCHEMAS } from "./constants.js";
2
+ import { filterByList, filterByValue } from "./helpers.js";
3
+ import { COLUMN_PRIVILEGES_SQL } from "./sql/column_privileges.sql.js";
4
+ import { ident, literal } from "pg-format";
5
+ //#region src/vendor/postgres-meta/lib/PostgresMetaColumnPrivileges.ts
6
+ var PostgresMetaColumnPrivileges = class {
7
+ constructor(query) {
8
+ this.query = query;
9
+ }
10
+ async list({ includeSystemSchemas = false, includedSchemas, excludedSchemas, limit, offset } = {}) {
11
+ const schemaFilter = filterByList(includedSchemas, excludedSchemas, !includeSystemSchemas ? DEFAULT_SYSTEM_SCHEMAS : void 0);
12
+ const sql = COLUMN_PRIVILEGES_SQL({
13
+ schemaFilter,
14
+ limit,
15
+ offset
16
+ });
17
+ return await this.query(sql);
18
+ }
19
+ async grant(grants) {
20
+ let sql = `
21
+ do $$
22
+ declare
23
+ col record;
24
+ begin
25
+ ${grants.map(({ privilege_type, column_id, grantee, is_grantable }) => {
26
+ const [relationId, columnNumber] = column_id.split(".");
27
+ return `
28
+ select *
29
+ from pg_attribute a
30
+ where a.attrelid = ${literal(relationId)}
31
+ and a.attnum = ${literal(columnNumber)}
32
+ into col;
33
+ execute format(
34
+ 'grant ${privilege_type} (%I) on %s to ${grantee.toLowerCase() === "public" ? "public" : ident(grantee)} ${is_grantable ? "with grant option" : ""}',
35
+ col.attname,
36
+ col.attrelid::regclass
37
+ );`;
38
+ }).join("\n")}
39
+ end $$;
40
+ `;
41
+ const { data, error } = await this.query(sql);
42
+ if (error) return {
43
+ data,
44
+ error
45
+ };
46
+ const columnIds = [...new Set(grants.map(({ column_id }) => column_id))];
47
+ const columnIdsFilter = filterByValue(columnIds);
48
+ sql = COLUMN_PRIVILEGES_SQL({ columnIdsFilter });
49
+ return await this.query(sql);
50
+ }
51
+ async revoke(revokes) {
52
+ let sql = `
53
+ do $$
54
+ declare
55
+ col record;
56
+ begin
57
+ ${revokes.map(({ privilege_type, column_id, grantee }) => {
58
+ const [relationId, columnNumber] = column_id.split(".");
59
+ return `
60
+ select *
61
+ from pg_attribute a
62
+ where a.attrelid = ${literal(relationId)}
63
+ and a.attnum = ${literal(columnNumber)}
64
+ into col;
65
+ execute format(
66
+ 'revoke ${privilege_type} (%I) on %s from ${grantee.toLowerCase() === "public" ? "public" : ident(grantee)}',
67
+ col.attname,
68
+ col.attrelid::regclass
69
+ );`;
70
+ }).join("\n")}
71
+ end $$;
72
+ `;
73
+ const { data, error } = await this.query(sql);
74
+ if (error) return {
75
+ data,
76
+ error
77
+ };
78
+ const columnIds = [...new Set(revokes.map(({ column_id }) => column_id))];
79
+ const columnIdsFilter = filterByValue(columnIds);
80
+ sql = COLUMN_PRIVILEGES_SQL({ columnIdsFilter });
81
+ return await this.query(sql);
82
+ }
83
+ };
84
+ //#endregion
85
+ export { PostgresMetaColumnPrivileges as default };