neon 8.0.10 → 8.0.11

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.
@@ -18,6 +18,7 @@ var functions_exports = /* @__PURE__ */ __exportAll({
18
18
  aliases: () => aliases,
19
19
  builder: () => builder,
20
20
  command: () => command,
21
+ deploymentPollDelay: () => deploymentPollDelay,
21
22
  describe: () => describe,
22
23
  handler: () => handler
23
24
  });
@@ -39,33 +40,54 @@ const LIST_TABLE_FIELDS = [
39
40
  "slug",
40
41
  "name",
41
42
  "status",
42
- "invocation_url",
43
+ "URL",
43
44
  "created_at"
44
45
  ];
45
- const DEPLOYMENT_FIELDS = [
46
+ const DEPLOY_RESULT_FIELDS = [
46
47
  "id",
47
48
  "status",
49
+ "invocation_url",
48
50
  "runtime",
49
51
  "memory_mib",
50
52
  "created_at"
51
53
  ];
52
- const DEPLOY_RESULT_FIELDS = [
53
- "id",
54
+ const DEPLOYMENT_TABLE_FIELDS = [
55
+ "deployment_id",
54
56
  "status",
55
- "invocation_url",
56
57
  "runtime",
57
- "memory_mib",
58
+ "memory",
59
+ "created_at"
60
+ ];
61
+ const deploymentTableView = (dep) => ({
62
+ deployment_id: dep.id,
63
+ status: dep.status,
64
+ runtime: dep.runtime,
65
+ memory: `${dep.memory_mib} MiB`,
66
+ created_at: dep.created_at
67
+ });
68
+ const FUNCTION_TABLE_FIELDS = [
69
+ "slug",
70
+ "name",
71
+ "URL",
58
72
  "created_at"
59
73
  ];
60
74
  const writeDeploymentErrorSection = (out, dep) => {
61
75
  if (dep.status === "failed" && dep.error) out.write({ reason: dep.error }, {
62
76
  fields: ["reason"],
63
- title: "deployment error"
77
+ title: "Deployment error"
64
78
  });
65
79
  };
66
80
  const SLUG_PATTERN = /^[a-z0-9]{1,20}$/;
67
81
  const SLUG_HELP = "Use 1-20 lowercase letters and digits (no hyphens or other characters).";
68
- const POLL_INTERVAL_MS = Number(process.env.NEON_FUNCTIONS_POLL_INTERVAL_MS) || 2e3;
82
+ const POLL_INTERVAL_OVERRIDE_MS = Number(process.env.NEON_FUNCTIONS_POLL_INTERVAL_MS) || void 0;
83
+ const FIRST_POLL_DELAY_MS = 200;
84
+ const POLL_INTERVAL_MS = 2e3;
85
+ /**
86
+ * Delay before poll `attempt` (zero-based). A small function's deployment is usually done
87
+ * within a few hundred milliseconds of the POST, so the first check comes soon and longer
88
+ * builds back off to the steady interval.
89
+ */
90
+ const deploymentPollDelay = (attempt, override = POLL_INTERVAL_OVERRIDE_MS) => override ?? Math.min(FIRST_POLL_DELAY_MS * 2 ** attempt, POLL_INTERVAL_MS);
69
91
  const POLL_TIMEOUT_MS = Number(process.env.NEON_FUNCTIONS_POLL_TIMEOUT_MS) || 6e5;
70
92
  const command = "functions";
71
93
  const describe = "Manage Neon Functions";
@@ -157,11 +179,21 @@ const parseEnv = (entries) => {
157
179
  };
158
180
  const statusHint = (slug, projectId, branchId) => `Check status with: ${getCliName()} function get ${slug} --project-id ${projectId} --branch ${branchId}`;
159
181
  const emitDeployResult = (props, deployment, fn) => {
182
+ if (props.output === "json" || props.output === "yaml") {
183
+ writer(props).write({
184
+ ...deployment,
185
+ invocation_url: fn?.invocation_url
186
+ }, { fields: DEPLOY_RESULT_FIELDS }).end();
187
+ return;
188
+ }
160
189
  const out = writer(props).write({
161
- ...deployment,
162
- invocation_url: fn?.invocation_url
163
- }, { fields: DEPLOY_RESULT_FIELDS });
164
- if (props.output !== "json" && props.output !== "yaml") writeDeploymentErrorSection(out, deployment);
190
+ URL: fn?.invocation_url,
191
+ ...deploymentTableView(deployment)
192
+ }, {
193
+ fields: ["URL", ...DEPLOYMENT_TABLE_FIELDS],
194
+ title: `Function ${props.slug}`
195
+ });
196
+ writeDeploymentErrorSection(out, deployment);
165
197
  out.end();
166
198
  };
167
199
  const isTransient = (err) => isNeonApiError(err) && (err.status === void 0 || err.status === 404 || err.status >= 500);
@@ -215,9 +247,11 @@ const deploy = async (props) => {
215
247
  let resolved;
216
248
  let resolvedFn;
217
249
  const deadline = Date.now() + POLL_TIMEOUT_MS;
250
+ let attempt = 0;
218
251
  try {
219
252
  while (!interrupted && Date.now() < deadline) {
220
- await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
253
+ await new Promise((r) => setTimeout(r, deploymentPollDelay(attempt)));
254
+ attempt += 1;
221
255
  if (interrupted) break;
222
256
  let fn;
223
257
  try {
@@ -253,7 +287,7 @@ const deploy = async (props) => {
253
287
  return;
254
288
  }
255
289
  if (resolved.status === "completed") {
256
- log.info(`Function deployment ${props.slug}/${resolved.id} completed.`);
290
+ if (props.output === "json" || props.output === "yaml") log.info(`Function deployment ${props.slug}/${resolved.id} completed.`);
257
291
  return;
258
292
  }
259
293
  if (resolved.status === "failed") throw new Error(`Function deployment ${props.slug}/${resolved.id} failed.`);
@@ -267,34 +301,37 @@ const get = async (props) => {
267
301
  writer(props).end(fn, { fields: FUNCTION_FIELDS });
268
302
  return;
269
303
  }
270
- const out = writer(props).write(fn, {
271
- fields: FUNCTION_FIELDS,
272
- title: "function"
304
+ const out = writer(props).write({
305
+ ...fn,
306
+ URL: fn.invocation_url
307
+ }, {
308
+ fields: FUNCTION_TABLE_FIELDS,
309
+ title: "Function"
273
310
  });
274
311
  const current = fn.current_deployment;
275
312
  const active = fn.active_deployment;
276
313
  if (current && active && current.id === active.id) {
277
- out.write(current, {
278
- fields: DEPLOYMENT_FIELDS,
279
- title: "deployment (current, active)"
314
+ out.write(deploymentTableView(current), {
315
+ fields: DEPLOYMENT_TABLE_FIELDS,
316
+ title: "Deployment (current, active)"
280
317
  });
281
318
  writeDeploymentErrorSection(out, current);
282
319
  } else {
283
320
  if (current) {
284
- out.write(current, {
285
- fields: DEPLOYMENT_FIELDS,
286
- title: "current deployment"
321
+ out.write(deploymentTableView(current), {
322
+ fields: DEPLOYMENT_TABLE_FIELDS,
323
+ title: "Current deployment"
287
324
  });
288
325
  writeDeploymentErrorSection(out, current);
289
326
  }
290
- if (active) out.write(active, {
291
- fields: DEPLOYMENT_FIELDS,
292
- title: "active deployment"
327
+ if (active) out.write(deploymentTableView(active), {
328
+ fields: DEPLOYMENT_TABLE_FIELDS,
329
+ title: "Active deployment"
293
330
  });
294
331
  }
295
332
  if (props.listEnvVariables) out.write((fn.active_deployment?.environment ?? []).map((name) => ({ name })), {
296
333
  fields: ["name"],
297
- title: "environment",
334
+ title: "Environment",
298
335
  emptyMessage: "No environment variables on the active deployment."
299
336
  });
300
337
  out.end();
@@ -329,7 +366,8 @@ const list = async (props) => {
329
366
  }
330
367
  writer(props).end(functions.map((fn) => ({
331
368
  ...fn,
332
- status: fn.current_deployment?.status ?? ""
369
+ status: fn.current_deployment?.status ?? "",
370
+ URL: fn.invocation_url
333
371
  })), {
334
372
  fields: LIST_TABLE_FIELDS,
335
373
  emptyMessage: "No functions found on this branch."
@@ -376,4 +414,4 @@ const deleteDomain = async (props) => {
376
414
  log.info(`Custom domain ${props.domain} deleted from branch ${branchId}`);
377
415
  };
378
416
  //#endregion
379
- export { aliases, builder, command, describe, handler, functions_exports as t };
417
+ export { aliases, builder, command, deploymentPollDelay, describe, handler, functions_exports as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neon",
3
- "version": "8.0.10",
3
+ "version": "8.0.11",
4
4
  "description": "CLI tool for Neon, the cloud backend primitives built around Lakebase Postgres",
5
5
  "keywords": [
6
6
  "neon",
@@ -65,8 +65,8 @@
65
65
  "yargs": "17.7.2",
66
66
  "yoctocolors": "^2.1.2",
67
67
  "@neon/config": "1.8.4",
68
- "@neon/config-runtime": "1.7.6",
69
- "@neon/sdk": "7.0.1"
68
+ "@neon/sdk": "7.0.1",
69
+ "@neon/config-runtime": "1.7.6"
70
70
  },
71
71
  "optionalDependencies": {
72
72
  "@napi-rs/keyring": "1.3.0",
@@ -100,8 +100,8 @@
100
100
  "typescript": "^5.9.0",
101
101
  "vitest": "^3.0.9",
102
102
  "@neon-internals/cli-core": "0.0.0",
103
- "@neon/e2e-harness": "0.0.0",
104
103
  "@neon-internals/env-core": "0.0.27",
104
+ "@neon/e2e-harness": "0.0.0",
105
105
  "@neon/functions": "0.11.0"
106
106
  },
107
107
  "publishConfig": {