neon 3.0.0 → 3.1.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 (207) hide show
  1. package/README.md +70 -5
  2. package/dist/_chunks/auth_selection-DGgq6ifc.js +83 -0
  3. package/dist/_chunks/cmd_pipeline-CUbBO9U_.js +2818 -0
  4. package/dist/_chunks/credentials-MYdHdKah.js +188 -0
  5. package/dist/_chunks/env-NbA61JR3.js +585 -0
  6. package/dist/_chunks/env_services-Tz9G4JeT.js +531 -0
  7. package/dist/_chunks/paths-DMq0Lt7a.js +151 -0
  8. package/dist/_chunks/profiles-Ir29rqns.js +217 -0
  9. package/dist/_chunks/psql-DWH-kc69.js +2169 -0
  10. package/dist/_chunks/rolldown-runtime-D7D4PA-g.js +13 -0
  11. package/dist/_chunks/secure_file-BucZj4yQ.js +39 -0
  12. package/dist/analytics.js +163 -207
  13. package/dist/api.js +815 -758
  14. package/dist/auth.js +121 -141
  15. package/dist/auth_context.js +39 -53
  16. package/dist/cli.js +4 -7
  17. package/dist/commands/api.js +220 -250
  18. package/dist/commands/api_keys.js +251 -314
  19. package/dist/commands/auth.js +283 -328
  20. package/dist/commands/bootstrap.js +372 -437
  21. package/dist/commands/branches.js +304 -455
  22. package/dist/commands/bucket.js +374 -514
  23. package/dist/commands/checkout.js +213 -298
  24. package/dist/commands/config.js +573 -690
  25. package/dist/commands/connection_string.js +137 -165
  26. package/dist/commands/data_api.js +238 -260
  27. package/dist/commands/databases.js +67 -76
  28. package/dist/commands/deploy.js +31 -25
  29. package/dist/commands/dev.js +639 -719
  30. package/dist/commands/diff.js +156 -200
  31. package/dist/commands/env.js +255 -305
  32. package/dist/commands/functions.js +275 -355
  33. package/dist/commands/index.js +70 -65
  34. package/dist/commands/init.js +84 -119
  35. package/dist/commands/inspect.js +55 -55
  36. package/dist/commands/ip_allow.js +88 -120
  37. package/dist/commands/link.js +874 -1019
  38. package/dist/commands/logs.js +291 -0
  39. package/dist/commands/neon_auth.js +725 -933
  40. package/dist/commands/operations.js +34 -25
  41. package/dist/commands/orgs.js +28 -18
  42. package/dist/commands/profile.js +615 -846
  43. package/dist/commands/projects.js +313 -373
  44. package/dist/commands/psql.js +60 -58
  45. package/dist/commands/roles.js +55 -58
  46. package/dist/commands/schema_diff.js +87 -131
  47. package/dist/commands/set_context.js +34 -26
  48. package/dist/commands/snapshots.js +288 -413
  49. package/dist/commands/status.js +41 -37
  50. package/dist/commands/user.js +21 -10
  51. package/dist/commands/vpc_endpoints.js +85 -113
  52. package/dist/config.js +7 -6
  53. package/dist/config_format.js +50 -66
  54. package/dist/config_template.js +128 -157
  55. package/dist/context.js +183 -235
  56. package/dist/current_branch_fast_path.js +40 -49
  57. package/dist/dev/env.js +2 -446
  58. package/dist/dev/functions.js +54 -68
  59. package/dist/dev/inputs.js +46 -58
  60. package/dist/dev/runtime.js +135 -164
  61. package/dist/dev/websocket.js +766 -959
  62. package/dist/env.js +27 -33
  63. package/dist/env_file.js +118 -132
  64. package/dist/env_services.js +2 -51
  65. package/dist/errors.js +57 -68
  66. package/dist/functions_api.js +45 -43
  67. package/dist/help.js +189 -140
  68. package/dist/index.js +182 -257
  69. package/dist/init/agents.js +137 -118
  70. package/dist/init/auth.js +58 -68
  71. package/dist/init/bootstrap.js +325 -396
  72. package/dist/init/build_config.js +4 -2
  73. package/dist/init/detect_agent.js +56 -101
  74. package/dist/init/editors.js +35 -52
  75. package/dist/init/enrich_output.js +51 -66
  76. package/dist/init/extension.js +134 -171
  77. package/dist/init/inspect.js +179 -266
  78. package/dist/init/interactive.js +510 -622
  79. package/dist/init/neonctl.js +117 -168
  80. package/dist/init/orchestrate.js +157 -173
  81. package/dist/init/phases/auth.js +188 -202
  82. package/dist/init/phases/cleanup.js +23 -23
  83. package/dist/init/phases/db.js +251 -277
  84. package/dist/init/phases/getting_started.js +213 -223
  85. package/dist/init/phases/mcp.js +174 -224
  86. package/dist/init/phases/migrations.js +247 -248
  87. package/dist/init/phases/neon_auth.js +114 -133
  88. package/dist/init/phases/setup.js +546 -703
  89. package/dist/init/phases/skills.js +75 -86
  90. package/dist/init/phases/status.js +72 -67
  91. package/dist/init/resolve_context.js +102 -99
  92. package/dist/init/route_command.js +91 -98
  93. package/dist/init/skills.js +174 -218
  94. package/dist/init/vsix.js +77 -99
  95. package/dist/log.js +17 -16
  96. package/dist/neon_services.js +104 -129
  97. package/dist/parameters.gen.js +481 -471
  98. package/dist/pkg.js +17 -19
  99. package/dist/profile_keys.js +44 -47
  100. package/dist/psql/cli.js +44 -47
  101. package/dist/psql/command/cmd_cond.js +231 -406
  102. package/dist/psql/command/cmd_connect.js +557 -764
  103. package/dist/psql/command/cmd_copy.js +728 -984
  104. package/dist/psql/command/cmd_describe.js +1499 -1688
  105. package/dist/psql/command/cmd_format.js +733 -905
  106. package/dist/psql/command/cmd_io.js +2 -2193
  107. package/dist/psql/command/cmd_lo.js +297 -359
  108. package/dist/psql/command/cmd_meta.js +727 -878
  109. package/dist/psql/command/cmd_misc.js +138 -172
  110. package/dist/psql/command/cmd_pipeline.js +2 -1148
  111. package/dist/psql/command/cmd_restrict.js +119 -155
  112. package/dist/psql/command/cmd_show.js +529 -688
  113. package/dist/psql/command/dispatch.js +260 -325
  114. package/dist/psql/command/inputQueue.js +35 -33
  115. package/dist/psql/command/shared.js +49 -63
  116. package/dist/psql/complete/filenames.js +90 -133
  117. package/dist/psql/complete/index.js +59 -97
  118. package/dist/psql/complete/matcher.js +236 -300
  119. package/dist/psql/complete/psqlVars.js +218 -223
  120. package/dist/psql/complete/queries.js +159 -177
  121. package/dist/psql/complete/rules.js +1493 -2299
  122. package/dist/psql/core/common.js +2 -1253
  123. package/dist/psql/core/help.js +456 -546
  124. package/dist/psql/core/mainloop.js +692 -1303
  125. package/dist/psql/core/prompt.js +391 -408
  126. package/dist/psql/core/settings.js +429 -644
  127. package/dist/psql/core/sqlHelp.js +480 -554
  128. package/dist/psql/core/startup.js +2 -846
  129. package/dist/psql/core/syncVars.js +67 -110
  130. package/dist/psql/core/variables.js +156 -278
  131. package/dist/psql/describe/formatters.js +884 -1285
  132. package/dist/psql/describe/processNamePattern.js +173 -260
  133. package/dist/psql/describe/queries.js +1368 -2403
  134. package/dist/psql/describe/versionGate.js +32 -41
  135. package/dist/psql/index.js +2 -2030
  136. package/dist/psql/io/history.js +232 -271
  137. package/dist/psql/io/input.js +103 -108
  138. package/dist/psql/io/lineEditor/buffer.js +238 -319
  139. package/dist/psql/io/lineEditor/complete.js +135 -213
  140. package/dist/psql/io/lineEditor/filename.js +139 -148
  141. package/dist/psql/io/lineEditor/index.js +653 -870
  142. package/dist/psql/io/lineEditor/keymap.js +544 -702
  143. package/dist/psql/io/lineEditor/vt100.js +294 -341
  144. package/dist/psql/io/pgpass.js +158 -187
  145. package/dist/psql/io/pgservice.js +146 -183
  146. package/dist/psql/io/psqlrc.js +328 -403
  147. package/dist/psql/print/aligned.js +1020 -1683
  148. package/dist/psql/print/asciidoc.js +180 -214
  149. package/dist/psql/print/crosstab.js +281 -442
  150. package/dist/psql/print/csv.js +48 -70
  151. package/dist/psql/print/html.js +195 -226
  152. package/dist/psql/print/json.js +75 -88
  153. package/dist/psql/print/latex.js +291 -364
  154. package/dist/psql/print/pager.js +171 -242
  155. package/dist/psql/print/troff.js +194 -226
  156. package/dist/psql/print/unaligned.js +69 -95
  157. package/dist/psql/print/units.js +167 -169
  158. package/dist/psql/scanner/slash.js +428 -483
  159. package/dist/psql/scanner/sql.js +445 -889
  160. package/dist/psql/scanner/stringutils.js +309 -379
  161. package/dist/psql/types/index.js +8 -7
  162. package/dist/psql/types/scanner.js +25 -22
  163. package/dist/psql/wire/connection.js +2042 -2803
  164. package/dist/psql/wire/copy.js +84 -100
  165. package/dist/psql/wire/notify.js +39 -59
  166. package/dist/psql/wire/pipeline.js +305 -518
  167. package/dist/psql/wire/protocol.js +349 -417
  168. package/dist/psql/wire/sasl.js +180 -265
  169. package/dist/psql/wire/tls.js +400 -561
  170. package/dist/storage_api.js +115 -129
  171. package/dist/test_utils/fixtures.js +94 -113
  172. package/dist/test_utils/oauth_server.js +10 -7
  173. package/dist/test_utils/project_dir.js +33 -0
  174. package/dist/utils/ai_gateway_notice.js +131 -162
  175. package/dist/utils/api_enums.js +21 -28
  176. package/dist/utils/auth.js +10 -4
  177. package/dist/utils/branch_notice.js +20 -19
  178. package/dist/utils/branch_picker.js +83 -89
  179. package/dist/utils/cli_name.js +15 -12
  180. package/dist/utils/compute_units.js +20 -27
  181. package/dist/utils/config_diff.js +127 -158
  182. package/dist/utils/enrichers.js +95 -148
  183. package/dist/utils/esbuild.js +130 -189
  184. package/dist/utils/flags.js +35 -47
  185. package/dist/utils/formats.js +8 -15
  186. package/dist/utils/git_diff.js +69 -80
  187. package/dist/utils/inspect_db.js +101 -143
  188. package/dist/utils/inspect_queries.js +179 -142
  189. package/dist/utils/middlewares.js +39 -45
  190. package/dist/utils/openapi.js +87 -99
  191. package/dist/utils/package_manager.js +312 -110
  192. package/dist/utils/point_in_time.js +49 -53
  193. package/dist/utils/psql.js +89 -106
  194. package/dist/utils/service_picker.js +55 -58
  195. package/dist/utils/string.js +5 -5
  196. package/dist/utils/ui.js +38 -55
  197. package/dist/utils/write_sync.js +26 -35
  198. package/dist/utils/zip.js +4 -3
  199. package/dist/writer.js +67 -87
  200. package/package.json +11 -6
  201. package/dist/_shared/auth_selection.js +0 -86
  202. package/dist/_shared/credentials.js +0 -209
  203. package/dist/_shared/env-core/env.js +0 -558
  204. package/dist/_shared/env-core/reuse-secrets.js +0 -223
  205. package/dist/_shared/paths.js +0 -148
  206. package/dist/_shared/profiles.js +0 -276
  207. package/dist/_shared/secure_file.js +0 -43
@@ -1,388 +1,308 @@
1
- import { existsSync, statSync } from "node:fs";
2
- import { dirname, join } from "node:path";
3
- import { describeNativeFinding, findUndeclaredNativePackages, } from "@neon/config-runtime";
4
- import { isNeonApiError, retryOnLock } from "../api.js";
5
- import { createDeployment, deleteFunction, getFunction, listFunctions, } from "../functions_api.js";
1
+ import { t as __exportAll } from "../_chunks/rolldown-runtime-D7D4PA-g.js";
6
2
  import { log } from "../log.js";
3
+ import { isNeonApiError, retryOnLock } from "../api.js";
7
4
  import { getCliName } from "../utils/cli_name.js";
5
+ import { createDeployment, deleteFunction, getFunction, listFunctions } from "../functions_api.js";
6
+ import { writer } from "../writer.js";
8
7
  import { branchIdFromProps, fillSingleProject } from "../utils/enrichers.js";
9
8
  import { bundleEntry } from "../utils/esbuild.js";
10
9
  import { zipBundle } from "../utils/zip.js";
11
- import { writer } from "../writer.js";
10
+ import { existsSync, statSync } from "node:fs";
11
+ import { dirname, join } from "node:path";
12
+ import { describeNativeFinding, findUndeclaredNativePackages } from "@neon/config-runtime";
13
+ //#region src/commands/functions.ts
14
+ var functions_exports = /* @__PURE__ */ __exportAll({
15
+ aliases: () => aliases,
16
+ builder: () => builder,
17
+ command: () => command,
18
+ describe: () => describe,
19
+ handler: () => handler
20
+ });
12
21
  const FUNCTION_FIELDS = [
13
- "slug",
14
- "name",
15
- "invocation_url",
16
- "created_at",
22
+ "slug",
23
+ "name",
24
+ "invocation_url",
25
+ "created_at"
17
26
  ];
18
27
  const FUNCTIONS_LIST_LIMIT = 100;
19
- // Table columns for `functions list`. `status` is a derived field (the
20
- // table writer reads flat fields only): the current deployment's status.
21
28
  const LIST_TABLE_FIELDS = [
22
- "slug",
23
- "name",
24
- "status",
25
- "invocation_url",
26
- "created_at",
29
+ "slug",
30
+ "name",
31
+ "status",
32
+ "invocation_url",
33
+ "created_at"
27
34
  ];
28
35
  const DEPLOYMENT_FIELDS = [
29
- "id",
30
- "status",
31
- "runtime",
32
- "memory_mib",
33
- "created_at",
36
+ "id",
37
+ "status",
38
+ "runtime",
39
+ "memory_mib",
40
+ "created_at"
34
41
  ];
35
- // Deploy emits the resolved deployment plus the function's invocation_url, so a
36
- // successful `functions deploy` tells the user exactly where to call the function.
37
42
  const DEPLOY_RESULT_FIELDS = [
38
- "id",
39
- "status",
40
- "invocation_url",
41
- "runtime",
42
- "memory_mib",
43
- "created_at",
43
+ "id",
44
+ "status",
45
+ "invocation_url",
46
+ "runtime",
47
+ "memory_mib",
48
+ "created_at"
44
49
  ];
45
- // In table mode a failed build's reason gets its own "deployment error"
46
- // section after the deployment table; json/yaml carry the raw `error` field.
47
50
  const writeDeploymentErrorSection = (out, dep) => {
48
- if (dep.status === "failed" && dep.error) {
49
- out.write({ reason: dep.error }, { fields: ["reason"], title: "deployment error" });
50
- }
51
+ if (dep.status === "failed" && dep.error) out.write({ reason: dep.error }, {
52
+ fields: ["reason"],
53
+ title: "deployment error"
54
+ });
51
55
  };
52
56
  const SLUG_PATTERN = /^[a-z0-9]{1,20}$/;
53
57
  const SLUG_HELP = "Use 1-20 lowercase letters and digits (no hyphens or other characters).";
54
- // Entry-point discovery order inside --src.
55
- const ENTRY_CANDIDATES = ["index.ts", "index.mjs", "index.js"];
56
- // Overridable so tests can poll fast; defaults to 2s in real use.
57
- const POLL_INTERVAL_MS = Number(process.env.NEON_FUNCTIONS_POLL_INTERVAL_MS) || 2000;
58
- // Upper bound on --wait polling so the CLI never hangs (e.g. if our deployment
59
- // never shows up as current_deployment). Overridable so tests can time out fast;
60
- // defaults to 10 minutes in real use.
61
- const POLL_TIMEOUT_MS = Number(process.env.NEON_FUNCTIONS_POLL_TIMEOUT_MS) || 600000;
62
- export const command = "functions";
63
- export const describe = "Manage Neon Functions";
64
- export const aliases = ["function"];
65
- export const builder = (argv) => argv
66
- .usage("$0 function <sub-command> [options]")
67
- .options({
68
- "project-id": {
69
- describe: "Project ID",
70
- type: "string",
71
- },
72
- branch: {
73
- describe: "Branch ID or name",
74
- type: "string",
75
- },
76
- })
77
- .middleware(fillSingleProject)
78
- .command("deploy <slug>", "Deploy a function from a local directory", (yargs) => yargs
79
- .positional("slug", {
80
- describe: "Function slug (1-20 lowercase letters and digits)",
81
- type: "string",
82
- demandOption: true,
83
- })
84
- .options({
85
- src: {
86
- describe: "Function source: a directory containing index.ts, index.mjs, or index.js, or a path to the entry file",
87
- type: "string",
88
- },
89
- // Removed flags, kept hidden so old invocations fail loudly instead
90
- // of being silently ignored (the CLI has no .strictOptions()).
91
- path: {
92
- type: "string",
93
- hidden: true,
94
- },
95
- entry: {
96
- type: "string",
97
- hidden: true,
98
- },
99
- runtime: {
100
- describe: "Function runtime",
101
- type: "string",
102
- choices: ["nodejs24"],
103
- },
104
- env: {
105
- describe: "Environment variable as KEY=VALUE (repeatable)",
106
- type: "string",
107
- array: true,
108
- },
109
- wait: {
110
- describe: "Wait for the deployment to finish building",
111
- type: "boolean",
112
- default: true,
113
- },
114
- }), (args) => deploy(args))
115
- .command("list", "List functions on the branch", (yargs) => yargs, (args) => list(args))
116
- .command("get <slug>", "Show a function's details", (yargs) => yargs
117
- .positional("slug", {
118
- describe: "Function slug",
119
- type: "string",
120
- demandOption: true,
121
- })
122
- .options({
123
- "list-env-variables": {
124
- describe: "List the environment variable names of the active deployment",
125
- type: "boolean",
126
- alias: "E",
127
- default: false,
128
- },
129
- }), (args) => get(args))
130
- .command("delete <slug>", "Delete a function on the branch", (yargs) => yargs.positional("slug", {
131
- describe: "Function slug",
132
- type: "string",
133
- demandOption: true,
58
+ const ENTRY_CANDIDATES = [
59
+ "index.ts",
60
+ "index.mjs",
61
+ "index.js"
62
+ ];
63
+ const POLL_INTERVAL_MS = Number(process.env.NEON_FUNCTIONS_POLL_INTERVAL_MS) || 2e3;
64
+ const POLL_TIMEOUT_MS = Number(process.env.NEON_FUNCTIONS_POLL_TIMEOUT_MS) || 6e5;
65
+ const command = "functions";
66
+ const describe = "Manage Neon Functions";
67
+ const aliases = ["function"];
68
+ const builder = (argv) => argv.usage("$0 function <sub-command> [options]").options({
69
+ "project-id": {
70
+ describe: "Project ID",
71
+ type: "string"
72
+ },
73
+ branch: {
74
+ describe: "Branch ID or name",
75
+ type: "string"
76
+ }
77
+ }).middleware(fillSingleProject).command("deploy <slug>", "Deploy a function from a local directory", (yargs) => yargs.positional("slug", {
78
+ describe: "Function slug (1-20 lowercase letters and digits)",
79
+ type: "string",
80
+ demandOption: true
81
+ }).options({
82
+ src: {
83
+ describe: "Function source: a directory containing index.ts, index.mjs, or index.js, or a path to the entry file",
84
+ type: "string"
85
+ },
86
+ path: {
87
+ type: "string",
88
+ hidden: true
89
+ },
90
+ entry: {
91
+ type: "string",
92
+ hidden: true
93
+ },
94
+ runtime: {
95
+ describe: "Function runtime",
96
+ type: "string",
97
+ choices: ["nodejs24"]
98
+ },
99
+ env: {
100
+ describe: "Environment variable as KEY=VALUE (repeatable)",
101
+ type: "string",
102
+ array: true
103
+ },
104
+ wait: {
105
+ describe: "Wait for the deployment to finish building",
106
+ type: "boolean",
107
+ default: true
108
+ }
109
+ }), (args) => deploy(args)).command("list", "List functions on the branch", (yargs) => yargs, (args) => list(args)).command("get <slug>", "Show a function's details", (yargs) => yargs.positional("slug", {
110
+ describe: "Function slug",
111
+ type: "string",
112
+ demandOption: true
113
+ }).options({ "list-env-variables": {
114
+ describe: "List the environment variable names of the active deployment",
115
+ type: "boolean",
116
+ alias: "E",
117
+ default: false
118
+ } }), (args) => get(args)).command("delete <slug>", "Delete a function on the branch", (yargs) => yargs.positional("slug", {
119
+ describe: "Function slug",
120
+ type: "string",
121
+ demandOption: true
134
122
  }), (args) => deleteFn(args));
135
- export const handler = (args) => {
136
- return args;
123
+ const handler = (args) => {
124
+ return args;
137
125
  };
138
126
  const parseEnv = (entries) => {
139
- if (!entries || entries.length === 0)
140
- return undefined;
141
- const map = {};
142
- for (const entry of entries) {
143
- const eq = entry.indexOf("=");
144
- if (eq <= 0) {
145
- throw new Error(`Invalid --env value "${entry}". Expected KEY=VALUE.`);
146
- }
147
- map[entry.slice(0, eq)] = entry.slice(eq + 1);
148
- }
149
- return JSON.stringify(map);
127
+ if (!entries || entries.length === 0) return void 0;
128
+ const map = {};
129
+ for (const entry of entries) {
130
+ const eq = entry.indexOf("=");
131
+ if (eq <= 0) throw new Error(`Invalid --env value "${entry}". Expected KEY=VALUE.`);
132
+ map[entry.slice(0, eq)] = entry.slice(eq + 1);
133
+ }
134
+ return JSON.stringify(map);
150
135
  };
151
136
  const statusHint = (slug, projectId, branchId) => `Check status with: ${getCliName()} function get ${slug} --project-id ${projectId} --branch ${branchId}`;
152
- // Emit the resolved deployment together with the function's invocation_url, so the
153
- // deploy output shows where the function is reachable (not just the deployment id).
154
137
  const emitDeployResult = (props, deployment, fn) => {
155
- const out = writer(props).write({ ...deployment, invocation_url: fn?.invocation_url }, { fields: DEPLOY_RESULT_FIELDS });
156
- if (props.output !== "json" && props.output !== "yaml") {
157
- writeDeploymentErrorSection(out, deployment);
158
- }
159
- out.end();
138
+ const out = writer(props).write({
139
+ ...deployment,
140
+ invocation_url: fn?.invocation_url
141
+ }, { fields: DEPLOY_RESULT_FIELDS });
142
+ if (props.output !== "json" && props.output !== "yaml") writeDeploymentErrorSection(out, deployment);
143
+ out.end();
160
144
  };
161
- // A poll error worth retrying: a network error (no HTTP response), a 5xx, or a
162
- // 404 from eventual consistency. Anything else (e.g. 401/403) is surfaced.
163
- const isTransient = (err) => isNeonApiError(err) &&
164
- (err.status === undefined || err.status === 404 || err.status >= 500);
145
+ const isTransient = (err) => isNeonApiError(err) && (err.status === void 0 || err.status === 404 || err.status >= 500);
165
146
  const deploy = async (props) => {
166
- if (props.path !== undefined || props.entry !== undefined) {
167
- throw new Error("--path and --entry were removed. Use --src <dir>; the entry point " +
168
- "is discovered as index.ts, index.mjs, or index.js in that directory.");
169
- }
170
- // At least one deploy option must be passed (--wait is excluded: it controls
171
- // output, not what gets deployed).
172
- const hasOption = props.src !== undefined ||
173
- props.env !== undefined ||
174
- props.runtime !== undefined;
175
- if (!hasOption) {
176
- throw new Error("Provide at least one option to deploy, e.g. --src or --env. " +
177
- `See: ${getCliName()} function deploy --help.`);
178
- }
179
- // Cheap, offline validation first - fail before any network round-trip.
180
- if (!SLUG_PATTERN.test(props.slug)) {
181
- throw new Error(`Invalid function slug "${props.slug}". ${SLUG_HELP}`);
182
- }
183
- const src = props.src ?? ".";
184
- const runtime = props.runtime ?? "nodejs24";
185
- const environment = parseEnv(props.env);
186
- const srcStat = statSync(src, { throwIfNoEntry: false });
187
- if (srcStat === undefined) {
188
- throw new Error(`--src path not found: ${src}.`);
189
- }
190
- // A file is used as the entry point directly; a directory triggers discovery.
191
- const source = srcStat.isFile()
192
- ? src
193
- : ENTRY_CANDIDATES.map((name) => join(src, name)).find((p) => existsSync(p));
194
- if (source === undefined) {
195
- throw new Error(`No entry file found in ${src}. Expected one of: ${ENTRY_CANDIDATES.join(", ")}.`);
196
- }
197
- // Bundle before any network round-trip so a bundling failure fails fast.
198
- const bundled = await bundleEntry(source);
199
- for (const warning of bundled.warnings)
200
- log.warning(warning);
201
- // `--src` bypasses `neon.ts`, so there is no policy to declare anything in and no way to
202
- // stage files here. The advisory still runs: this is the shortest path to a function that
203
- // deploys clean and then fails at invoke, so it is the last place to stay silent.
204
- for (const finding of findUndeclaredNativePackages({
205
- metafile: bundled.metafile,
206
- declared: [],
207
- projectDir: dirname(source),
208
- })) {
209
- log.warning(describeNativeFinding(props.slug, finding));
210
- }
211
- const zip = zipBundle(bundled.files);
212
- const branchId = await branchIdFromProps(props);
213
- // Snapshot the current version before deploy so we can detect the new one
214
- // afterward. A missing function (404) or no deployment yet → undefined.
215
- let before;
216
- try {
217
- const fn = await getFunction(props.apiClient, props.projectId, branchId, props.slug);
218
- before = fn.current_deployment?.id;
219
- }
220
- catch (err) {
221
- if (!(isNeonApiError(err) && err.status === 404))
222
- throw err;
223
- }
224
- await retryOnLock(() => createDeployment(props.apiClient, props.projectId, branchId, props.slug, {
225
- zip,
226
- runtime,
227
- environment,
228
- }));
229
- log.info(`Function deployment triggered for function ${props.slug}.`);
230
- // Best-effort interrupt: a Ctrl-C lands at the next poll boundary. (No
231
- // automated test; mirrors the resolution branches below, verified manually.)
232
- let interrupted = false;
233
- const onSignal = () => {
234
- interrupted = true;
235
- };
236
- process.once("SIGINT", onSignal);
237
- process.once("SIGTERM", onSignal);
238
- // Poll until a NEW version appears (id greater than the snapshot, or
239
- // any version if there was none). --no-wait stops there; --wait stops at a
240
- // terminal status. Bounded by POLL_TIMEOUT_MS so it never hangs.
241
- let resolved;
242
- // The function carries the invocation_url; keep the whole record (not just its
243
- // current_deployment) so we can surface that URL on success.
244
- let resolvedFn;
245
- const deadline = Date.now() + POLL_TIMEOUT_MS;
246
- try {
247
- while (!interrupted && Date.now() < deadline) {
248
- await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
249
- if (interrupted)
250
- break;
251
- // The deploy already succeeded server-side; tolerate transient poll
252
- // failures and retry on the next interval. Surface anything else.
253
- let fn;
254
- try {
255
- fn = await getFunction(props.apiClient, props.projectId, branchId, props.slug);
256
- }
257
- catch (err) {
258
- if (isTransient(err))
259
- continue;
260
- throw err;
261
- }
262
- const dep = fn.current_deployment;
263
- const isNew = dep !== undefined && (before === undefined || dep.id > before);
264
- if (isNew && dep) {
265
- resolved = dep;
266
- resolvedFn = fn;
267
- if (!props.wait)
268
- break;
269
- if (dep.status === "completed" || dep.status === "failed")
270
- break;
271
- }
272
- }
273
- }
274
- finally {
275
- process.removeListener("SIGINT", onSignal);
276
- process.removeListener("SIGTERM", onSignal);
277
- }
278
- if (interrupted) {
279
- log.info(statusHint(props.slug, props.projectId, branchId));
280
- if (resolved)
281
- emitDeployResult(props, resolved, resolvedFn);
282
- return;
283
- }
284
- if (resolved === undefined) {
285
- log.info(statusHint(props.slug, props.projectId, branchId));
286
- throw new Error(`Timed out waiting for the deployment of ${props.slug} to start. It may still be in progress.`);
287
- }
288
- emitDeployResult(props, resolved, resolvedFn);
289
- if (!props.wait) {
290
- log.info(statusHint(props.slug, props.projectId, branchId));
291
- return;
292
- }
293
- if (resolved.status === "completed") {
294
- log.info(`Function deployment ${props.slug}/${resolved.id} completed.`);
295
- return;
296
- }
297
- if (resolved.status === "failed") {
298
- throw new Error(`Function deployment ${props.slug}/${resolved.id} failed.`);
299
- }
300
- // --wait, new version appeared but the deadline hit before it finished.
301
- log.info(statusHint(props.slug, props.projectId, branchId));
302
- throw new Error(`Timed out waiting for function deployment ${props.slug}/${resolved.id} to finish. It may still be building.`);
147
+ if (props.path !== void 0 || props.entry !== void 0) throw new Error("--path and --entry were removed. Use --src <dir>; the entry point is discovered as index.ts, index.mjs, or index.js in that directory.");
148
+ if (!(props.src !== void 0 || props.env !== void 0 || props.runtime !== void 0)) throw new Error(`Provide at least one option to deploy, e.g. --src or --env. See: ${getCliName()} function deploy --help.`);
149
+ if (!SLUG_PATTERN.test(props.slug)) throw new Error(`Invalid function slug "${props.slug}". ${SLUG_HELP}`);
150
+ const src = props.src ?? ".";
151
+ const runtime = props.runtime ?? "nodejs24";
152
+ const environment = parseEnv(props.env);
153
+ const srcStat = statSync(src, { throwIfNoEntry: false });
154
+ if (srcStat === void 0) throw new Error(`--src path not found: ${src}.`);
155
+ const source = srcStat.isFile() ? src : ENTRY_CANDIDATES.map((name) => join(src, name)).find((p) => existsSync(p));
156
+ if (source === void 0) throw new Error(`No entry file found in ${src}. Expected one of: ${ENTRY_CANDIDATES.join(", ")}.`);
157
+ const bundled = await bundleEntry(source);
158
+ for (const warning of bundled.warnings) log.warning(warning);
159
+ for (const finding of findUndeclaredNativePackages({
160
+ metafile: bundled.metafile,
161
+ declared: [],
162
+ projectDir: dirname(source)
163
+ })) log.warning(describeNativeFinding(props.slug, finding));
164
+ const zip = zipBundle(bundled.files);
165
+ const branchId = await branchIdFromProps(props);
166
+ let before;
167
+ try {
168
+ before = (await getFunction(props.apiClient, props.projectId, branchId, props.slug)).current_deployment?.id;
169
+ } catch (err) {
170
+ if (!(isNeonApiError(err) && err.status === 404)) throw err;
171
+ }
172
+ await retryOnLock(() => createDeployment(props.apiClient, props.projectId, branchId, props.slug, {
173
+ zip,
174
+ runtime,
175
+ environment
176
+ }));
177
+ log.info(`Function deployment triggered for function ${props.slug}.`);
178
+ let interrupted = false;
179
+ const onSignal = () => {
180
+ interrupted = true;
181
+ };
182
+ process.once("SIGINT", onSignal);
183
+ process.once("SIGTERM", onSignal);
184
+ let resolved;
185
+ let resolvedFn;
186
+ const deadline = Date.now() + POLL_TIMEOUT_MS;
187
+ try {
188
+ while (!interrupted && Date.now() < deadline) {
189
+ await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
190
+ if (interrupted) break;
191
+ let fn;
192
+ try {
193
+ fn = await getFunction(props.apiClient, props.projectId, branchId, props.slug);
194
+ } catch (err) {
195
+ if (isTransient(err)) continue;
196
+ throw err;
197
+ }
198
+ const dep = fn.current_deployment;
199
+ if (dep !== void 0 && (before === void 0 || dep.id > before) && dep) {
200
+ resolved = dep;
201
+ resolvedFn = fn;
202
+ if (!props.wait) break;
203
+ if (dep.status === "completed" || dep.status === "failed") break;
204
+ }
205
+ }
206
+ } finally {
207
+ process.removeListener("SIGINT", onSignal);
208
+ process.removeListener("SIGTERM", onSignal);
209
+ }
210
+ if (interrupted) {
211
+ log.info(statusHint(props.slug, props.projectId, branchId));
212
+ if (resolved) emitDeployResult(props, resolved, resolvedFn);
213
+ return;
214
+ }
215
+ if (resolved === void 0) {
216
+ log.info(statusHint(props.slug, props.projectId, branchId));
217
+ throw new Error(`Timed out waiting for the deployment of ${props.slug} to start. It may still be in progress.`);
218
+ }
219
+ emitDeployResult(props, resolved, resolvedFn);
220
+ if (!props.wait) {
221
+ log.info(statusHint(props.slug, props.projectId, branchId));
222
+ return;
223
+ }
224
+ if (resolved.status === "completed") {
225
+ log.info(`Function deployment ${props.slug}/${resolved.id} completed.`);
226
+ return;
227
+ }
228
+ if (resolved.status === "failed") throw new Error(`Function deployment ${props.slug}/${resolved.id} failed.`);
229
+ log.info(statusHint(props.slug, props.projectId, branchId));
230
+ throw new Error(`Timed out waiting for function deployment ${props.slug}/${resolved.id} to finish. It may still be building.`);
303
231
  };
304
232
  const get = async (props) => {
305
- const branchId = await branchIdFromProps(props);
306
- const fn = await getFunction(props.apiClient, props.projectId, branchId, props.slug);
307
- if (props.output === "json" || props.output === "yaml") {
308
- writer(props).end(fn, { fields: FUNCTION_FIELDS });
309
- return;
310
- }
311
- const out = writer(props).write(fn, {
312
- fields: FUNCTION_FIELDS,
313
- title: "function",
314
- });
315
- const current = fn.current_deployment;
316
- const active = fn.active_deployment;
317
- if (current && active && current.id === active.id) {
318
- out.write(current, {
319
- fields: DEPLOYMENT_FIELDS,
320
- title: "deployment (current, active)",
321
- });
322
- writeDeploymentErrorSection(out, current);
323
- }
324
- else {
325
- if (current) {
326
- out.write(current, {
327
- fields: DEPLOYMENT_FIELDS,
328
- title: "current deployment",
329
- });
330
- // The failure reason is shown only for the current deployment;
331
- // the active one completed successfully by definition.
332
- writeDeploymentErrorSection(out, current);
333
- }
334
- if (active) {
335
- out.write(active, {
336
- fields: DEPLOYMENT_FIELDS,
337
- title: "active deployment",
338
- });
339
- }
340
- }
341
- if (props.listEnvVariables) {
342
- out.write((fn.active_deployment?.environment ?? []).map((name) => ({ name })), {
343
- fields: ["name"],
344
- title: "environment",
345
- emptyMessage: "No environment variables on the active deployment.",
346
- });
347
- }
348
- out.end();
233
+ const branchId = await branchIdFromProps(props);
234
+ const fn = await getFunction(props.apiClient, props.projectId, branchId, props.slug);
235
+ if (props.output === "json" || props.output === "yaml") {
236
+ writer(props).end(fn, { fields: FUNCTION_FIELDS });
237
+ return;
238
+ }
239
+ const out = writer(props).write(fn, {
240
+ fields: FUNCTION_FIELDS,
241
+ title: "function"
242
+ });
243
+ const current = fn.current_deployment;
244
+ const active = fn.active_deployment;
245
+ if (current && active && current.id === active.id) {
246
+ out.write(current, {
247
+ fields: DEPLOYMENT_FIELDS,
248
+ title: "deployment (current, active)"
249
+ });
250
+ writeDeploymentErrorSection(out, current);
251
+ } else {
252
+ if (current) {
253
+ out.write(current, {
254
+ fields: DEPLOYMENT_FIELDS,
255
+ title: "current deployment"
256
+ });
257
+ writeDeploymentErrorSection(out, current);
258
+ }
259
+ if (active) out.write(active, {
260
+ fields: DEPLOYMENT_FIELDS,
261
+ title: "active deployment"
262
+ });
263
+ }
264
+ if (props.listEnvVariables) out.write((fn.active_deployment?.environment ?? []).map((name) => ({ name })), {
265
+ fields: ["name"],
266
+ title: "environment",
267
+ emptyMessage: "No environment variables on the active deployment."
268
+ });
269
+ out.end();
349
270
  };
350
271
  const deleteFn = async (props) => {
351
- const branchId = await branchIdFromProps(props);
352
- try {
353
- await retryOnLock(() => deleteFunction(props.apiClient, props.projectId, branchId, props.slug));
354
- }
355
- catch (err) {
356
- if (isNeonApiError(err) && err.status === 404) {
357
- throw new Error(`Function "${props.slug}" not found on branch ${branchId}.`);
358
- }
359
- throw err;
360
- }
361
- log.info(`Function ${props.slug} deleted from branch ${branchId}`);
272
+ const branchId = await branchIdFromProps(props);
273
+ try {
274
+ await retryOnLock(() => deleteFunction(props.apiClient, props.projectId, branchId, props.slug));
275
+ } catch (err) {
276
+ if (isNeonApiError(err) && err.status === 404) throw new Error(`Function "${props.slug}" not found on branch ${branchId}.`);
277
+ throw err;
278
+ }
279
+ log.info(`Function ${props.slug} deleted from branch ${branchId}`);
362
280
  };
363
281
  const list = async (props) => {
364
- const branchId = await branchIdFromProps(props);
365
- const functions = [];
366
- let cursor;
367
- for (;;) {
368
- const page = await listFunctions(props.apiClient, props.projectId, branchId, { cursor, limit: FUNCTIONS_LIST_LIMIT });
369
- functions.push(...page.functions);
370
- log.debug("Got %d functions, next cursor: %s", page.functions.length, page.next);
371
- // A server echoing the same cursor would loop forever; treat it as
372
- // the end of the list.
373
- if (!page.next || page.next === cursor)
374
- break;
375
- cursor = page.next;
376
- }
377
- if (props.output === "json" || props.output === "yaml") {
378
- writer(props).end(functions, { fields: FUNCTION_FIELDS });
379
- return;
380
- }
381
- writer(props).end(functions.map((fn) => ({
382
- ...fn,
383
- status: fn.current_deployment?.status ?? "",
384
- })), {
385
- fields: LIST_TABLE_FIELDS,
386
- emptyMessage: "No functions found on this branch.",
387
- });
282
+ const branchId = await branchIdFromProps(props);
283
+ const functions = [];
284
+ let cursor;
285
+ for (;;) {
286
+ const page = await listFunctions(props.apiClient, props.projectId, branchId, {
287
+ cursor,
288
+ limit: FUNCTIONS_LIST_LIMIT
289
+ });
290
+ functions.push(...page.functions);
291
+ log.debug("Got %d functions, next cursor: %s", page.functions.length, page.next);
292
+ if (!page.next || page.next === cursor) break;
293
+ cursor = page.next;
294
+ }
295
+ if (props.output === "json" || props.output === "yaml") {
296
+ writer(props).end(functions, { fields: FUNCTION_FIELDS });
297
+ return;
298
+ }
299
+ writer(props).end(functions.map((fn) => ({
300
+ ...fn,
301
+ status: fn.current_deployment?.status ?? ""
302
+ })), {
303
+ fields: LIST_TABLE_FIELDS,
304
+ emptyMessage: "No functions found on this branch."
305
+ });
388
306
  };
307
+ //#endregion
308
+ export { aliases, builder, command, describe, handler, functions_exports as t };