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.
- package/README.md +70 -5
- package/dist/_chunks/auth_selection-DGgq6ifc.js +83 -0
- package/dist/_chunks/cmd_pipeline-CUbBO9U_.js +2818 -0
- package/dist/_chunks/credentials-MYdHdKah.js +188 -0
- package/dist/_chunks/env-NbA61JR3.js +585 -0
- package/dist/_chunks/env_services-Tz9G4JeT.js +531 -0
- package/dist/_chunks/paths-DMq0Lt7a.js +151 -0
- package/dist/_chunks/profiles-Ir29rqns.js +217 -0
- package/dist/_chunks/psql-DWH-kc69.js +2169 -0
- package/dist/_chunks/rolldown-runtime-D7D4PA-g.js +13 -0
- package/dist/_chunks/secure_file-BucZj4yQ.js +39 -0
- package/dist/analytics.js +163 -207
- package/dist/api.js +815 -758
- package/dist/auth.js +121 -141
- package/dist/auth_context.js +39 -53
- package/dist/cli.js +4 -7
- package/dist/commands/api.js +220 -250
- package/dist/commands/api_keys.js +251 -314
- package/dist/commands/auth.js +283 -328
- package/dist/commands/bootstrap.js +372 -437
- package/dist/commands/branches.js +304 -455
- package/dist/commands/bucket.js +374 -514
- package/dist/commands/checkout.js +213 -298
- package/dist/commands/config.js +573 -690
- package/dist/commands/connection_string.js +137 -165
- package/dist/commands/data_api.js +238 -260
- package/dist/commands/databases.js +67 -76
- package/dist/commands/deploy.js +31 -25
- package/dist/commands/dev.js +639 -719
- package/dist/commands/diff.js +156 -200
- package/dist/commands/env.js +255 -305
- package/dist/commands/functions.js +275 -355
- package/dist/commands/index.js +70 -65
- package/dist/commands/init.js +84 -119
- package/dist/commands/inspect.js +55 -55
- package/dist/commands/ip_allow.js +88 -120
- package/dist/commands/link.js +874 -1019
- package/dist/commands/logs.js +291 -0
- package/dist/commands/neon_auth.js +725 -933
- package/dist/commands/operations.js +34 -25
- package/dist/commands/orgs.js +28 -18
- package/dist/commands/profile.js +615 -846
- package/dist/commands/projects.js +313 -373
- package/dist/commands/psql.js +60 -58
- package/dist/commands/roles.js +55 -58
- package/dist/commands/schema_diff.js +87 -131
- package/dist/commands/set_context.js +34 -26
- package/dist/commands/snapshots.js +288 -413
- package/dist/commands/status.js +41 -37
- package/dist/commands/user.js +21 -10
- package/dist/commands/vpc_endpoints.js +85 -113
- package/dist/config.js +7 -6
- package/dist/config_format.js +50 -66
- package/dist/config_template.js +128 -157
- package/dist/context.js +183 -235
- package/dist/current_branch_fast_path.js +40 -49
- package/dist/dev/env.js +2 -446
- package/dist/dev/functions.js +54 -68
- package/dist/dev/inputs.js +46 -58
- package/dist/dev/runtime.js +135 -164
- package/dist/dev/websocket.js +766 -959
- package/dist/env.js +27 -33
- package/dist/env_file.js +118 -132
- package/dist/env_services.js +2 -51
- package/dist/errors.js +57 -68
- package/dist/functions_api.js +45 -43
- package/dist/help.js +189 -140
- package/dist/index.js +182 -257
- package/dist/init/agents.js +137 -118
- package/dist/init/auth.js +58 -68
- package/dist/init/bootstrap.js +325 -396
- package/dist/init/build_config.js +4 -2
- package/dist/init/detect_agent.js +56 -101
- package/dist/init/editors.js +35 -52
- package/dist/init/enrich_output.js +51 -66
- package/dist/init/extension.js +134 -171
- package/dist/init/inspect.js +179 -266
- package/dist/init/interactive.js +510 -622
- package/dist/init/neonctl.js +117 -168
- package/dist/init/orchestrate.js +157 -173
- package/dist/init/phases/auth.js +188 -202
- package/dist/init/phases/cleanup.js +23 -23
- package/dist/init/phases/db.js +251 -277
- package/dist/init/phases/getting_started.js +213 -223
- package/dist/init/phases/mcp.js +174 -224
- package/dist/init/phases/migrations.js +247 -248
- package/dist/init/phases/neon_auth.js +114 -133
- package/dist/init/phases/setup.js +546 -703
- package/dist/init/phases/skills.js +75 -86
- package/dist/init/phases/status.js +72 -67
- package/dist/init/resolve_context.js +102 -99
- package/dist/init/route_command.js +91 -98
- package/dist/init/skills.js +174 -218
- package/dist/init/vsix.js +77 -99
- package/dist/log.js +17 -16
- package/dist/neon_services.js +104 -129
- package/dist/parameters.gen.js +481 -471
- package/dist/pkg.js +17 -19
- package/dist/profile_keys.js +44 -47
- package/dist/psql/cli.js +44 -47
- package/dist/psql/command/cmd_cond.js +231 -406
- package/dist/psql/command/cmd_connect.js +557 -764
- package/dist/psql/command/cmd_copy.js +728 -984
- package/dist/psql/command/cmd_describe.js +1499 -1688
- package/dist/psql/command/cmd_format.js +733 -905
- package/dist/psql/command/cmd_io.js +2 -2193
- package/dist/psql/command/cmd_lo.js +297 -359
- package/dist/psql/command/cmd_meta.js +727 -878
- package/dist/psql/command/cmd_misc.js +138 -172
- package/dist/psql/command/cmd_pipeline.js +2 -1148
- package/dist/psql/command/cmd_restrict.js +119 -155
- package/dist/psql/command/cmd_show.js +529 -688
- package/dist/psql/command/dispatch.js +260 -325
- package/dist/psql/command/inputQueue.js +35 -33
- package/dist/psql/command/shared.js +49 -63
- package/dist/psql/complete/filenames.js +90 -133
- package/dist/psql/complete/index.js +59 -97
- package/dist/psql/complete/matcher.js +236 -300
- package/dist/psql/complete/psqlVars.js +218 -223
- package/dist/psql/complete/queries.js +159 -177
- package/dist/psql/complete/rules.js +1493 -2299
- package/dist/psql/core/common.js +2 -1253
- package/dist/psql/core/help.js +456 -546
- package/dist/psql/core/mainloop.js +692 -1303
- package/dist/psql/core/prompt.js +391 -408
- package/dist/psql/core/settings.js +429 -644
- package/dist/psql/core/sqlHelp.js +480 -554
- package/dist/psql/core/startup.js +2 -846
- package/dist/psql/core/syncVars.js +67 -110
- package/dist/psql/core/variables.js +156 -278
- package/dist/psql/describe/formatters.js +884 -1285
- package/dist/psql/describe/processNamePattern.js +173 -260
- package/dist/psql/describe/queries.js +1368 -2403
- package/dist/psql/describe/versionGate.js +32 -41
- package/dist/psql/index.js +2 -2030
- package/dist/psql/io/history.js +232 -271
- package/dist/psql/io/input.js +103 -108
- package/dist/psql/io/lineEditor/buffer.js +238 -319
- package/dist/psql/io/lineEditor/complete.js +135 -213
- package/dist/psql/io/lineEditor/filename.js +139 -148
- package/dist/psql/io/lineEditor/index.js +653 -870
- package/dist/psql/io/lineEditor/keymap.js +544 -702
- package/dist/psql/io/lineEditor/vt100.js +294 -341
- package/dist/psql/io/pgpass.js +158 -187
- package/dist/psql/io/pgservice.js +146 -183
- package/dist/psql/io/psqlrc.js +328 -403
- package/dist/psql/print/aligned.js +1020 -1683
- package/dist/psql/print/asciidoc.js +180 -214
- package/dist/psql/print/crosstab.js +281 -442
- package/dist/psql/print/csv.js +48 -70
- package/dist/psql/print/html.js +195 -226
- package/dist/psql/print/json.js +75 -88
- package/dist/psql/print/latex.js +291 -364
- package/dist/psql/print/pager.js +171 -242
- package/dist/psql/print/troff.js +194 -226
- package/dist/psql/print/unaligned.js +69 -95
- package/dist/psql/print/units.js +167 -169
- package/dist/psql/scanner/slash.js +428 -483
- package/dist/psql/scanner/sql.js +445 -889
- package/dist/psql/scanner/stringutils.js +309 -379
- package/dist/psql/types/index.js +8 -7
- package/dist/psql/types/scanner.js +25 -22
- package/dist/psql/wire/connection.js +2042 -2803
- package/dist/psql/wire/copy.js +84 -100
- package/dist/psql/wire/notify.js +39 -59
- package/dist/psql/wire/pipeline.js +305 -518
- package/dist/psql/wire/protocol.js +349 -417
- package/dist/psql/wire/sasl.js +180 -265
- package/dist/psql/wire/tls.js +400 -561
- package/dist/storage_api.js +115 -129
- package/dist/test_utils/fixtures.js +94 -113
- package/dist/test_utils/oauth_server.js +10 -7
- package/dist/test_utils/project_dir.js +33 -0
- package/dist/utils/ai_gateway_notice.js +131 -162
- package/dist/utils/api_enums.js +21 -28
- package/dist/utils/auth.js +10 -4
- package/dist/utils/branch_notice.js +20 -19
- package/dist/utils/branch_picker.js +83 -89
- package/dist/utils/cli_name.js +15 -12
- package/dist/utils/compute_units.js +20 -27
- package/dist/utils/config_diff.js +127 -158
- package/dist/utils/enrichers.js +95 -148
- package/dist/utils/esbuild.js +130 -189
- package/dist/utils/flags.js +35 -47
- package/dist/utils/formats.js +8 -15
- package/dist/utils/git_diff.js +69 -80
- package/dist/utils/inspect_db.js +101 -143
- package/dist/utils/inspect_queries.js +179 -142
- package/dist/utils/middlewares.js +39 -45
- package/dist/utils/openapi.js +87 -99
- package/dist/utils/package_manager.js +312 -110
- package/dist/utils/point_in_time.js +49 -53
- package/dist/utils/psql.js +89 -106
- package/dist/utils/service_picker.js +55 -58
- package/dist/utils/string.js +5 -5
- package/dist/utils/ui.js +38 -55
- package/dist/utils/write_sync.js +26 -35
- package/dist/utils/zip.js +4 -3
- package/dist/writer.js +67 -87
- package/package.json +11 -6
- package/dist/_shared/auth_selection.js +0 -86
- package/dist/_shared/credentials.js +0 -209
- package/dist/_shared/env-core/env.js +0 -558
- package/dist/_shared/env-core/reuse-secrets.js +0 -223
- package/dist/_shared/paths.js +0 -148
- package/dist/_shared/profiles.js +0 -276
- package/dist/_shared/secure_file.js +0 -43
|
@@ -1,388 +1,308 @@
|
|
|
1
|
-
import {
|
|
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 {
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
"slug",
|
|
30
|
+
"name",
|
|
31
|
+
"status",
|
|
32
|
+
"invocation_url",
|
|
33
|
+
"created_at"
|
|
27
34
|
];
|
|
28
35
|
const DEPLOYMENT_FIELDS = [
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
49
|
-
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}), (args) =>
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
-
|
|
136
|
-
|
|
123
|
+
const handler = (args) => {
|
|
124
|
+
return args;
|
|
137
125
|
};
|
|
138
126
|
const parseEnv = (entries) => {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
|
|
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
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
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
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
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
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
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
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
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 };
|