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.
- package/dist/commands/functions.js +67 -29
- package/package.json +4 -4
|
@@ -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
|
-
"
|
|
43
|
+
"URL",
|
|
43
44
|
"created_at"
|
|
44
45
|
];
|
|
45
|
-
const
|
|
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
|
|
53
|
-
"
|
|
54
|
+
const DEPLOYMENT_TABLE_FIELDS = [
|
|
55
|
+
"deployment_id",
|
|
54
56
|
"status",
|
|
55
|
-
"invocation_url",
|
|
56
57
|
"runtime",
|
|
57
|
-
"
|
|
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: "
|
|
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
|
|
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
|
-
|
|
162
|
-
|
|
163
|
-
}, {
|
|
164
|
-
|
|
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,
|
|
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(
|
|
271
|
-
|
|
272
|
-
|
|
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:
|
|
279
|
-
title: "
|
|
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:
|
|
286
|
-
title: "
|
|
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:
|
|
292
|
-
title: "
|
|
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: "
|
|
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.
|
|
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/
|
|
69
|
-
"@neon/
|
|
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": {
|