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
package/dist/utils/enrichers.js
CHANGED
|
@@ -1,159 +1,106 @@
|
|
|
1
1
|
import { isNeonApiError, messageFromBody } from "../api.js";
|
|
2
2
|
import { isConfigInit, isCurrentBranchProbe } from "../context.js";
|
|
3
3
|
import { looksLikeBranchId } from "./formats.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const branchData = data.branches.find((b) => b.name === branch);
|
|
13
|
-
if (!branchData) {
|
|
14
|
-
throw new Error(`Branch ${branch} not found.\nAvailable branches: ${data.branches
|
|
15
|
-
.map((b) => b.name)
|
|
16
|
-
.join(", ")}`);
|
|
17
|
-
}
|
|
18
|
-
return branchData.id;
|
|
4
|
+
//#region src/utils/enrichers.ts
|
|
5
|
+
const branchIdResolve = async ({ branch, apiClient, projectId }) => {
|
|
6
|
+
branch = branch.toString();
|
|
7
|
+
if (looksLikeBranchId(branch)) return branch;
|
|
8
|
+
const { data } = await apiClient.listProjectBranches({ projectId });
|
|
9
|
+
const branchData = data.branches.find((b) => b.name === branch);
|
|
10
|
+
if (!branchData) throw new Error(`Branch ${branch} not found.\nAvailable branches: ${data.branches.map((b) => b.name).join(", ")}`);
|
|
11
|
+
return branchData.id;
|
|
19
12
|
};
|
|
20
13
|
const getBranchIdFromProps = async (props) => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const { data } = await props.apiClient.listProjectBranches({
|
|
32
|
-
projectId: props.projectId,
|
|
33
|
-
});
|
|
34
|
-
const defaultBranch = data.branches.find((b) => b.default);
|
|
35
|
-
if (defaultBranch) {
|
|
36
|
-
return defaultBranch.id;
|
|
37
|
-
}
|
|
38
|
-
throw new Error("No default branch found");
|
|
14
|
+
const branch = "branch" in props && typeof props.branch === "string" ? props.branch : props.id;
|
|
15
|
+
if (branch) return await branchIdResolve({
|
|
16
|
+
branch,
|
|
17
|
+
apiClient: props.apiClient,
|
|
18
|
+
projectId: props.projectId
|
|
19
|
+
});
|
|
20
|
+
const { data } = await props.apiClient.listProjectBranches({ projectId: props.projectId });
|
|
21
|
+
const defaultBranch = data.branches.find((b) => b.default);
|
|
22
|
+
if (defaultBranch) return defaultBranch.id;
|
|
23
|
+
throw new Error("No default branch found");
|
|
39
24
|
};
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
25
|
+
const branchIdFromProps = async (props) => {
|
|
26
|
+
props.branchId = await getBranchIdFromProps(props);
|
|
27
|
+
return props.branchId;
|
|
43
28
|
};
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
const defaultBranch = branches.find((b) => b.default);
|
|
72
|
-
if (!defaultBranch) {
|
|
73
|
-
throw new Error("No default branch found");
|
|
74
|
-
}
|
|
75
|
-
return {
|
|
76
|
-
branchId: defaultBranch.id,
|
|
77
|
-
branchName: defaultBranch.name ?? defaultBranch.id,
|
|
78
|
-
usedDefault: true,
|
|
79
|
-
};
|
|
29
|
+
const resolveBranchRef = async (props) => {
|
|
30
|
+
const branch = typeof props.branch === "string" ? props.branch : props.id;
|
|
31
|
+
const { data } = await props.apiClient.listProjectBranches({ projectId: props.projectId });
|
|
32
|
+
const branches = data.branches;
|
|
33
|
+
if (branch) {
|
|
34
|
+
const ref = branch.toString();
|
|
35
|
+
const found = looksLikeBranchId(ref) ? branches.find((b) => b.id === ref) : branches.find((b) => b.name === ref);
|
|
36
|
+
if (found) return {
|
|
37
|
+
branchId: found.id,
|
|
38
|
+
branchName: found.name ?? found.id,
|
|
39
|
+
usedDefault: false
|
|
40
|
+
};
|
|
41
|
+
if (looksLikeBranchId(ref)) return {
|
|
42
|
+
branchId: ref,
|
|
43
|
+
branchName: ref,
|
|
44
|
+
usedDefault: false
|
|
45
|
+
};
|
|
46
|
+
throw new Error(`Branch ${ref} not found.\nAvailable branches: ${branches.map((b) => b.name).join(", ")}`);
|
|
47
|
+
}
|
|
48
|
+
const defaultBranch = branches.find((b) => b.default);
|
|
49
|
+
if (!defaultBranch) throw new Error("No default branch found");
|
|
50
|
+
return {
|
|
51
|
+
branchId: defaultBranch.id,
|
|
52
|
+
branchName: defaultBranch.name ?? defaultBranch.id,
|
|
53
|
+
usedDefault: true
|
|
54
|
+
};
|
|
80
55
|
};
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
throw new Error(`No databases found for the branch: ${props.branchId}`);
|
|
92
|
-
}
|
|
93
|
-
if (databases.length === 1) {
|
|
94
|
-
return databases[0].name;
|
|
95
|
-
}
|
|
96
|
-
throw new Error(`Multiple databases found for the branch, please provide one with the --database option: ${databases.map((d) => d.name).join(", ")}`);
|
|
56
|
+
const resolveSingleDatabase = async (props) => {
|
|
57
|
+
const { data } = await props.apiClient.listProjectBranchDatabases(props.projectId, props.branchId);
|
|
58
|
+
const databases = data.databases;
|
|
59
|
+
if (props.database !== void 0) {
|
|
60
|
+
if (!databases.find((d) => d.name === props.database)) throw new Error(`Database not found: ${props.database}. Available databases on branch ${props.branchId}: ${databases.map((d) => d.name).join(", ")}`);
|
|
61
|
+
return props.database;
|
|
62
|
+
}
|
|
63
|
+
if (databases.length === 0) throw new Error(`No databases found for the branch: ${props.branchId}`);
|
|
64
|
+
if (databases.length === 1) return databases[0].name;
|
|
65
|
+
throw new Error(`Multiple databases found for the branch, please provide one with the --database option: ${databases.map((d) => d.name).join(", ")}`);
|
|
97
66
|
};
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
});
|
|
126
|
-
if (data.projects.length === 0) {
|
|
127
|
-
throw new Error("No projects found");
|
|
128
|
-
}
|
|
129
|
-
if (data.projects.length > 1) {
|
|
130
|
-
throw new Error(`Multiple projects found, please provide one with the --project-id option`);
|
|
131
|
-
}
|
|
132
|
-
return {
|
|
133
|
-
...props,
|
|
134
|
-
projectId: data.projects[0].id,
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
catch (error) {
|
|
138
|
-
// If the API error is about missing org_id, provide a user-friendly message
|
|
139
|
-
if (isNeonApiError(error) &&
|
|
140
|
-
error.status === 400 &&
|
|
141
|
-
messageFromBody(error.data)?.includes("org_id is required")) {
|
|
142
|
-
throw new Error("Multiple projects found, please provide one with the --project-id option");
|
|
143
|
-
}
|
|
144
|
-
throw error;
|
|
145
|
-
}
|
|
67
|
+
const fillSingleProject = async (props) => {
|
|
68
|
+
if (isCurrentBranchProbe(props)) return props;
|
|
69
|
+
if (isConfigInit(props)) return props;
|
|
70
|
+
if (props.projectId) return {
|
|
71
|
+
...props,
|
|
72
|
+
projectId: props.projectId
|
|
73
|
+
};
|
|
74
|
+
let orgId = props.orgId;
|
|
75
|
+
if (!orgId) {
|
|
76
|
+
const { data: orgsData } = await props.apiClient.getCurrentUserOrganizations();
|
|
77
|
+
if (orgsData.organizations.length === 1) orgId = orgsData.organizations[0].id;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const { data } = await props.apiClient.listProjects({
|
|
81
|
+
limit: 2,
|
|
82
|
+
org_id: orgId
|
|
83
|
+
});
|
|
84
|
+
if (data.projects.length === 0) throw new Error("No projects found");
|
|
85
|
+
if (data.projects.length > 1) throw new Error(`Multiple projects found, please provide one with the --project-id option`);
|
|
86
|
+
return {
|
|
87
|
+
...props,
|
|
88
|
+
projectId: data.projects[0].id
|
|
89
|
+
};
|
|
90
|
+
} catch (error) {
|
|
91
|
+
if (isNeonApiError(error) && error.status === 400 && messageFromBody(error.data)?.includes("org_id is required")) throw new Error("Multiple projects found, please provide one with the --project-id option");
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
146
94
|
};
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
throw new Error(`Multiple organizations found, please provide one with the --org-id option`);
|
|
157
|
-
}
|
|
158
|
-
return { ...props, orgId: data.organizations[0].id };
|
|
95
|
+
const fillSingleOrg = async (props) => {
|
|
96
|
+
if (props.orgId) return props;
|
|
97
|
+
const { data } = await props.apiClient.getCurrentUserOrganizations();
|
|
98
|
+
if (data.organizations.length === 0) throw new Error("No organizations found");
|
|
99
|
+
if (data.organizations.length > 1) throw new Error(`Multiple organizations found, please provide one with the --org-id option`);
|
|
100
|
+
return {
|
|
101
|
+
...props,
|
|
102
|
+
orgId: data.organizations[0].id
|
|
103
|
+
};
|
|
159
104
|
};
|
|
105
|
+
//#endregion
|
|
106
|
+
export { branchIdFromProps, branchIdResolve, fillSingleOrg, fillSingleProject, resolveBranchRef, resolveSingleDatabase };
|
package/dist/utils/esbuild.js
CHANGED
|
@@ -1,210 +1,151 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { globalInstallCommand, resolveInvokingPackageManager } from "./package_manager.js";
|
|
2
2
|
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
3
|
import { basename, join } from "node:path";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { spawn } from "node:child_process";
|
|
5
6
|
import which from "which";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
// `Dynamic require of "x" is not supported`. Re-create those globals via `createRequire`
|
|
13
|
-
// so CJS and ESM dependencies coexist in the single `index.mjs`.
|
|
7
|
+
//#region src/utils/esbuild.ts
|
|
8
|
+
const notFoundMessage = () => {
|
|
9
|
+
const install = globalInstallCommand(resolveInvokingPackageManager(), "esbuild");
|
|
10
|
+
const how = install ? `install esbuild and ensure it is on your PATH (e.g. \`${install.command} ${install.args.join(" ")}\`), or ` : "put an esbuild binary on your PATH, or ";
|
|
11
|
+
return `esbuild not found. neon ships esbuild for most platforms, so this is unexpected. ${how[0].toUpperCase()}${how.slice(1)}set NEON_ESBUILD_PATH to an esbuild binary.`;
|
|
12
|
+
};
|
|
14
13
|
const ESM_CJS_INTEROP_BANNER = "import{createRequire as ___cr}from'module';import{fileURLToPath as ___f}from'url';import{dirname as ___d}from'path';const require=___cr(import.meta.url);const __filename=___f(import.meta.url);const __dirname=___d(__filename);";
|
|
15
14
|
const defaultDeps = {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
loadEsbuild: (name) => import(name),
|
|
15
|
+
isPackaged: () => process.pkg !== void 0,
|
|
16
|
+
loadEsbuild: (name) => import(name)
|
|
19
17
|
};
|
|
20
|
-
|
|
21
|
-
// or not installed). Tells bundleEntry to fall back to the binary; never shown
|
|
22
|
-
// to the user.
|
|
23
|
-
class ModuleNotAvailable extends Error {
|
|
24
|
-
}
|
|
18
|
+
var ModuleNotAvailable = class extends Error {};
|
|
25
19
|
const message = (err) => err instanceof Error ? err.message : String(err);
|
|
26
20
|
const toFilesByBasename = (files) => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return out;
|
|
21
|
+
const out = {};
|
|
22
|
+
for (const f of files) out[basename(f.path)] = f.contents;
|
|
23
|
+
return out;
|
|
31
24
|
};
|
|
32
25
|
const bundleViaModule = async (source, loadEsbuild, externalPackages) => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
minify: true,
|
|
63
|
-
format: "esm",
|
|
64
|
-
platform: "node",
|
|
65
|
-
// Bundle dependencies into the entry so the deployed archive is self-contained (the
|
|
66
|
-
// Functions runtime has no node_modules). Node built-ins stay external on
|
|
67
|
-
// platform:'node'. The banner re-creates require/__filename/__dirname for bundled CJS.
|
|
68
|
-
banner: { js: ESM_CJS_INTEROP_BANNER },
|
|
69
|
-
// Only what the policy declared unbundleable; everything else is still inlined.
|
|
70
|
-
external: [...externalPackages],
|
|
71
|
-
// Reveals which packages were inlined, so a deploy can report an undeclared
|
|
72
|
-
// native dependency. Free here — esbuild is already running.
|
|
73
|
-
metafile: true,
|
|
74
|
-
logLevel: "silent",
|
|
75
|
-
})
|
|
76
|
-
.catch((err) => {
|
|
77
|
-
throw new Error(`Failed to bundle function from ${source}. ${message(err)}`.trim());
|
|
78
|
-
});
|
|
79
|
-
const files = result.outputFiles ?? [];
|
|
80
|
-
// write:false with one entry always yields index.mjs (no source map — we don't emit one);
|
|
81
|
-
// an empty set means the API contract changed under us — fail loud rather than ship an
|
|
82
|
-
// empty archive.
|
|
83
|
-
if (files.length === 0) {
|
|
84
|
-
throw new Error(`Failed to bundle function from ${source}. esbuild produced no output.`);
|
|
85
|
-
}
|
|
86
|
-
return {
|
|
87
|
-
files: toFilesByBasename(files),
|
|
88
|
-
...(result.metafile ? { metafile: result.metafile } : {}),
|
|
89
|
-
warnings: [],
|
|
90
|
-
};
|
|
26
|
+
const name = ["es", "build"].join("");
|
|
27
|
+
let esbuild;
|
|
28
|
+
try {
|
|
29
|
+
esbuild = await loadEsbuild(name);
|
|
30
|
+
} catch {
|
|
31
|
+
throw new ModuleNotAvailable();
|
|
32
|
+
}
|
|
33
|
+
const result = await esbuild.build({
|
|
34
|
+
entryPoints: [source],
|
|
35
|
+
bundle: true,
|
|
36
|
+
outfile: "index.mjs",
|
|
37
|
+
write: false,
|
|
38
|
+
minify: true,
|
|
39
|
+
format: "esm",
|
|
40
|
+
platform: "node",
|
|
41
|
+
banner: { js: ESM_CJS_INTEROP_BANNER },
|
|
42
|
+
external: [...externalPackages],
|
|
43
|
+
metafile: true,
|
|
44
|
+
logLevel: "silent"
|
|
45
|
+
}).catch((err) => {
|
|
46
|
+
throw new Error(`Failed to bundle function from ${source}. ${message(err)}`.trim());
|
|
47
|
+
});
|
|
48
|
+
const files = result.outputFiles ?? [];
|
|
49
|
+
if (files.length === 0) throw new Error(`Failed to bundle function from ${source}. esbuild produced no output.`);
|
|
50
|
+
return {
|
|
51
|
+
files: toFilesByBasename(files),
|
|
52
|
+
...result.metafile ? { metafile: result.metafile } : {},
|
|
53
|
+
warnings: []
|
|
54
|
+
};
|
|
91
55
|
};
|
|
92
|
-
// Find the esbuild binary at deploy time. An explicit override is authoritative
|
|
93
|
-
// (so it fails loudly if wrong); otherwise prefer the host PATH, then a locally
|
|
94
|
-
// installed copy.
|
|
95
56
|
const resolveEsbuild = () => {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
// a devDependency. In `npm i -g` and pkg installs the PATH branch above wins.
|
|
107
|
-
const local = join(process.cwd(), "node_modules", ".bin", "esbuild");
|
|
108
|
-
if (existsSync(local))
|
|
109
|
-
return local;
|
|
110
|
-
throw new Error(NOT_FOUND);
|
|
57
|
+
const override = process.env.NEON_ESBUILD_PATH;
|
|
58
|
+
if (override) {
|
|
59
|
+
if (existsSync(override)) return override;
|
|
60
|
+
throw new Error(`NEON_ESBUILD_PATH is set to ${override}, but no file exists there. Point it at an esbuild binary, or unset it to use the one neon ships.`);
|
|
61
|
+
}
|
|
62
|
+
const onPath = which.sync("esbuild", { nothrow: true });
|
|
63
|
+
if (onPath) return onPath;
|
|
64
|
+
const local = join(process.cwd(), "node_modules", ".bin", "esbuild");
|
|
65
|
+
if (existsSync(local)) return local;
|
|
66
|
+
throw new Error(notFoundMessage());
|
|
111
67
|
};
|
|
112
68
|
const runEsbuild = (bin, args) => new Promise((resolve, reject) => {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
69
|
+
const child = spawn(bin, args, { stdio: [
|
|
70
|
+
"ignore",
|
|
71
|
+
"ignore",
|
|
72
|
+
"pipe"
|
|
73
|
+
] });
|
|
74
|
+
let stderr = "";
|
|
75
|
+
child.stderr.on("data", (chunk) => {
|
|
76
|
+
stderr += chunk.toString();
|
|
77
|
+
});
|
|
78
|
+
child.on("error", reject);
|
|
79
|
+
child.on("close", (code) => {
|
|
80
|
+
resolve({
|
|
81
|
+
code,
|
|
82
|
+
stderr
|
|
83
|
+
});
|
|
84
|
+
});
|
|
124
85
|
});
|
|
125
86
|
const bundleViaBinary = async (source, externalPackages) => {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
finally {
|
|
159
|
-
rmSync(outDir, { recursive: true, force: true });
|
|
160
|
-
}
|
|
87
|
+
const bin = resolveEsbuild();
|
|
88
|
+
const outDir = mkdtempSync(join(tmpdir(), "neon-fn-bundle-"));
|
|
89
|
+
const outfile = join(outDir, "index.mjs");
|
|
90
|
+
const metafilePath = join(outDir, "meta.json");
|
|
91
|
+
try {
|
|
92
|
+
const { code, stderr } = await runEsbuild(bin, [
|
|
93
|
+
source,
|
|
94
|
+
"--bundle",
|
|
95
|
+
`--outfile=${outfile}`,
|
|
96
|
+
"--minify",
|
|
97
|
+
"--format=esm",
|
|
98
|
+
"--platform=node",
|
|
99
|
+
`--banner:js=${ESM_CJS_INTEROP_BANNER}`,
|
|
100
|
+
...externalPackages.map((pkg) => `--external:${pkg}`),
|
|
101
|
+
`--metafile=${metafilePath}`,
|
|
102
|
+
"--log-level=error"
|
|
103
|
+
]);
|
|
104
|
+
if (code !== 0) throw new Error(`Failed to bundle function from ${source}. ${stderr.trim()}`.trim());
|
|
105
|
+
const metafile = readMetafile(metafilePath);
|
|
106
|
+
return {
|
|
107
|
+
files: { "index.mjs": new Uint8Array(readFileSync(outfile)) },
|
|
108
|
+
...metafile.metafile ? { metafile: metafile.metafile } : {},
|
|
109
|
+
warnings: metafile.warnings
|
|
110
|
+
};
|
|
111
|
+
} finally {
|
|
112
|
+
rmSync(outDir, {
|
|
113
|
+
recursive: true,
|
|
114
|
+
force: true
|
|
115
|
+
});
|
|
116
|
+
}
|
|
161
117
|
};
|
|
162
118
|
/**
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
119
|
+
* Read the metafile the binary path asked esbuild to write.
|
|
120
|
+
*
|
|
121
|
+
* We always pass `--metafile`, so an unreadable one means esbuild did not do what it was
|
|
122
|
+
* told. That is worth saying rather than swallowing — but not worth failing a deploy over,
|
|
123
|
+
* because the metafile only powers an advisory report. Reported and skipped.
|
|
124
|
+
*/
|
|
169
125
|
const readMetafile = (path) => {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
if (typeof parsed !== "object" || parsed === null) {
|
|
184
|
-
return {
|
|
185
|
-
warnings: [
|
|
186
|
-
"esbuild wrote a metafile that is not an object. The bundle is unaffected; " +
|
|
187
|
-
"this deploy cannot check for an undeclared native dependency.",
|
|
188
|
-
],
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
return { metafile: parsed, warnings: [] };
|
|
126
|
+
let parsed;
|
|
127
|
+
try {
|
|
128
|
+
parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
129
|
+
} catch (cause) {
|
|
130
|
+
return { warnings: [`esbuild was asked for a metafile but none could be read (${message(cause)}). The bundle is unaffected; this deploy cannot check for an undeclared native dependency.`] };
|
|
131
|
+
}
|
|
132
|
+
if (typeof parsed !== "object" || parsed === null) return { warnings: ["esbuild wrote a metafile that is not an object. The bundle is unaffected; this deploy cannot check for an undeclared native dependency."] };
|
|
133
|
+
return {
|
|
134
|
+
metafile: parsed,
|
|
135
|
+
warnings: []
|
|
136
|
+
};
|
|
192
137
|
};
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}
|
|
205
|
-
catch (err) {
|
|
206
|
-
if (err instanceof ModuleNotAvailable)
|
|
207
|
-
return bundleViaBinary(source, external);
|
|
208
|
-
throw err;
|
|
209
|
-
}
|
|
138
|
+
const bundleEntry = async (source, options = {}) => {
|
|
139
|
+
const isPackaged = options.isPackaged ?? defaultDeps.isPackaged;
|
|
140
|
+
const loadEsbuild = options.loadEsbuild ?? defaultDeps.loadEsbuild;
|
|
141
|
+
const external = options.externalPackages ?? [];
|
|
142
|
+
if (isPackaged()) return bundleViaBinary(source, external);
|
|
143
|
+
try {
|
|
144
|
+
return await bundleViaModule(source, loadEsbuild, external);
|
|
145
|
+
} catch (err) {
|
|
146
|
+
if (err instanceof ModuleNotAvailable) return bundleViaBinary(source, external);
|
|
147
|
+
throw err;
|
|
148
|
+
}
|
|
210
149
|
};
|
|
150
|
+
//#endregion
|
|
151
|
+
export { bundleEntry };
|