neon 2.38.5 → 2.39.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 +3 -1
- package/dist/commands/config.js +5 -1
- package/dist/commands/dev.js +9 -3
- package/dist/dev/functions.js +3 -0
- package/dist/utils/esbuild.js +14 -7
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Neon CLI
|
|
2
2
|
|
|
3
|
-
The `neon` package is a command-line interface that lets you manage [Neon
|
|
3
|
+
The `neon` package is a command-line interface that lets you manage [Neon](https://neon.tech/) — Lakebase Postgres, Object Storage, Functions, Managed Better Auth, and the AI Gateway — directly from the terminal. For the complete documentation, see [Neon CLI](https://neon.tech/docs/reference/neon-cli).
|
|
4
4
|
|
|
5
5
|
The legacy `neonctl` package is a lightweight compatibility package that depends
|
|
6
6
|
on this package and invokes the same CLI entry point. The implementation and
|
|
@@ -529,6 +529,8 @@ neon deploy --branch my-feature --update-existing
|
|
|
529
529
|
|
|
530
530
|
Function deploys declared under `preview.functions` are bundled by neon's own esbuild helper and uploaded as part of `apply`, so the policy stays declarative and the packaged CLI never has to embed esbuild's native binary.
|
|
531
531
|
|
|
532
|
+
When a package cannot be bundled — a native addon with no esbuild loader, or an optional peer dependency a library references on an untaken code path — list it in that function's `externalPackages` and the bundler leaves the import alone. `neon dev` honours the same list. It does not make the package resolvable in the deployed archive (there is no `node_modules` next to the bundle), so it only unblocks an import that is never evaluated — a dependency the handler actually calls has to be bundled, and a natively-backed one cannot be. See [`@neon/config`](../config/README.md#unbundleable-dependencies-externalpackages).
|
|
533
|
+
|
|
532
534
|
## Scaffold a project (`bootstrap`)
|
|
533
535
|
|
|
534
536
|
`neon bootstrap` copies a Neon starter template into a new (or current) directory — conceptually like `degit`, but it only pulls from a small set of templates we maintain in the public [`neondatabase/examples`](https://github.com/neondatabase/examples) repo. It requires no Neon login: it just downloads files from GitHub.
|
package/dist/commands/config.js
CHANGED
|
@@ -24,7 +24,11 @@ import { autoPullEnvAfterPin } from "./env.js";
|
|
|
24
24
|
* out of config-runtime's static module graph — and therefore out of the packaged
|
|
25
25
|
* neonctl snapshot, which resolves esbuild dynamically at deploy time.
|
|
26
26
|
*/
|
|
27
|
-
const neonctlBundler = async (fn) => zipBundle(await bundleEntry(fn.source
|
|
27
|
+
const neonctlBundler = async (fn) => zipBundle(await bundleEntry(fn.source, {
|
|
28
|
+
...(fn.externalPackages
|
|
29
|
+
? { externalPackages: fn.externalPackages }
|
|
30
|
+
: {}),
|
|
31
|
+
}));
|
|
28
32
|
const INSPECT_FIELDS = ["project", "branch", "config"];
|
|
29
33
|
/**
|
|
30
34
|
* Shared `--env` flag for `config plan|apply` and `deploy`. Loads a `.env` into
|
package/dist/commands/dev.js
CHANGED
|
@@ -182,10 +182,14 @@ const plannedToUnit = (fn, branchEnv, searchBase) => {
|
|
|
182
182
|
// base) so reconcile can tell a real change from a no-op save. A search-mode function
|
|
183
183
|
// re-planned with a different base must hash identically, or it would be needlessly
|
|
184
184
|
// restarted — see reconcile().
|
|
185
|
+
...(fn.externalPackages
|
|
186
|
+
? { externalPackages: fn.externalPackages }
|
|
187
|
+
: {}),
|
|
185
188
|
configKey: JSON.stringify({
|
|
186
189
|
source: fn.source,
|
|
187
190
|
port: fn.port ?? null,
|
|
188
191
|
env: fn.env,
|
|
192
|
+
externalPackages: fn.externalPackages ?? null,
|
|
189
193
|
}),
|
|
190
194
|
};
|
|
191
195
|
};
|
|
@@ -229,7 +233,7 @@ const runSupervisor = async (units, options = {}) => {
|
|
|
229
233
|
const bundleAndStart = async (r) => {
|
|
230
234
|
let bundlePath;
|
|
231
235
|
try {
|
|
232
|
-
bundlePath = await writeBundle(r.unit.source, r.unit.bundleDir);
|
|
236
|
+
bundlePath = await writeBundle(r.unit.source, r.unit.bundleDir, r.unit.externalPackages);
|
|
233
237
|
}
|
|
234
238
|
catch (err) {
|
|
235
239
|
r.status = "error";
|
|
@@ -477,8 +481,10 @@ const spawnChild = (unit, runtimePath, bundlePath) => {
|
|
|
477
481
|
detached: true,
|
|
478
482
|
});
|
|
479
483
|
};
|
|
480
|
-
const writeBundle = async (source, bundleDir) => {
|
|
481
|
-
const files = await bundleEntry(source
|
|
484
|
+
const writeBundle = async (source, bundleDir, externalPackages) => {
|
|
485
|
+
const files = await bundleEntry(source, {
|
|
486
|
+
...(externalPackages ? { externalPackages } : {}),
|
|
487
|
+
});
|
|
482
488
|
mkdirSync(bundleDir, { recursive: true });
|
|
483
489
|
// bundleEntry emits a single `index.mjs` (no source map). The `.mjs` extension makes Node
|
|
484
490
|
// load it as ESM directly, so no `package.json` `"type": "module"` marker is needed.
|
package/dist/dev/functions.js
CHANGED
|
@@ -36,6 +36,9 @@ export const resolveFunctionsFromConfig = async (cwd, branchName) => {
|
|
|
36
36
|
? { port: devPort(fn.dev) }
|
|
37
37
|
: {}),
|
|
38
38
|
env: { ...fn.env },
|
|
39
|
+
...(fn.externalPackages
|
|
40
|
+
? { externalPackages: [...fn.externalPackages] }
|
|
41
|
+
: {}),
|
|
39
42
|
};
|
|
40
43
|
});
|
|
41
44
|
return { configPath, functions: planned };
|
package/dist/utils/esbuild.js
CHANGED
|
@@ -29,7 +29,7 @@ const toFilesByBasename = (files) => {
|
|
|
29
29
|
out[basename(f.path)] = f.contents;
|
|
30
30
|
return out;
|
|
31
31
|
};
|
|
32
|
-
const bundleViaModule = async (source, loadEsbuild) => {
|
|
32
|
+
const bundleViaModule = async (source, loadEsbuild, externalPackages) => {
|
|
33
33
|
// esbuild is resolved by a COMPUTED specifier, never the literal string
|
|
34
34
|
// 'esbuild'. Both rollup (bundle step) and @yao-pkg/pkg (binary step)
|
|
35
35
|
// statically scan for literal import()/require() calls and would otherwise
|
|
@@ -66,6 +66,8 @@ const bundleViaModule = async (source, loadEsbuild) => {
|
|
|
66
66
|
// Functions runtime has no node_modules). Node built-ins stay external on
|
|
67
67
|
// platform:'node'. The banner re-creates require/__filename/__dirname for bundled CJS.
|
|
68
68
|
banner: { js: ESM_CJS_INTEROP_BANNER },
|
|
69
|
+
// Only what the policy declared unbundleable; everything else is still inlined.
|
|
70
|
+
external: [...externalPackages],
|
|
69
71
|
logLevel: "silent",
|
|
70
72
|
})
|
|
71
73
|
.catch((err) => {
|
|
@@ -113,7 +115,7 @@ const runEsbuild = (bin, args) => new Promise((resolve, reject) => {
|
|
|
113
115
|
resolve({ code, stderr });
|
|
114
116
|
});
|
|
115
117
|
});
|
|
116
|
-
const bundleViaBinary = async (source) => {
|
|
118
|
+
const bundleViaBinary = async (source, externalPackages) => {
|
|
117
119
|
const bin = resolveEsbuild();
|
|
118
120
|
const outDir = mkdtempSync(join(tmpdir(), "neon-fn-bundle-"));
|
|
119
121
|
const outfile = join(outDir, "index.mjs");
|
|
@@ -126,6 +128,8 @@ const bundleViaBinary = async (source) => {
|
|
|
126
128
|
"--format=esm",
|
|
127
129
|
"--platform=node",
|
|
128
130
|
`--banner:js=${ESM_CJS_INTEROP_BANNER}`,
|
|
131
|
+
// One flag per package, mirroring the module path's `external` array.
|
|
132
|
+
...externalPackages.map((pkg) => `--external:${pkg}`),
|
|
129
133
|
"--log-level=error",
|
|
130
134
|
]);
|
|
131
135
|
if (code !== 0) {
|
|
@@ -144,15 +148,18 @@ const bundleViaBinary = async (source) => {
|
|
|
144
148
|
// Bundle `source` into the files the Functions archive expects, keyed by
|
|
145
149
|
// basename. npm installs bundle in-process via the esbuild module; the packaged
|
|
146
150
|
// binary (and platforms esbuild can't run on) shell out to an esbuild binary.
|
|
147
|
-
export const bundleEntry = async (source,
|
|
148
|
-
|
|
149
|
-
|
|
151
|
+
export const bundleEntry = async (source, options = {}) => {
|
|
152
|
+
const isPackaged = options.isPackaged ?? defaultDeps.isPackaged;
|
|
153
|
+
const loadEsbuild = options.loadEsbuild ?? defaultDeps.loadEsbuild;
|
|
154
|
+
const externalPackages = options.externalPackages ?? [];
|
|
155
|
+
if (isPackaged())
|
|
156
|
+
return bundleViaBinary(source, externalPackages);
|
|
150
157
|
try {
|
|
151
|
-
return await bundleViaModule(source,
|
|
158
|
+
return await bundleViaModule(source, loadEsbuild, externalPackages);
|
|
152
159
|
}
|
|
153
160
|
catch (err) {
|
|
154
161
|
if (err instanceof ModuleNotAvailable)
|
|
155
|
-
return bundleViaBinary(source);
|
|
162
|
+
return bundleViaBinary(source, externalPackages);
|
|
156
163
|
throw err;
|
|
157
164
|
}
|
|
158
165
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neon",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "CLI tool for Neon
|
|
3
|
+
"version": "2.39.1",
|
|
4
|
+
"description": "CLI tool for Neon, the cloud backend primitives built around Lakebase Postgres",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"neon",
|
|
7
7
|
"neonctl",
|
|
@@ -47,7 +47,6 @@
|
|
|
47
47
|
"cliui": "8.0.1",
|
|
48
48
|
"diff": "5.2.0",
|
|
49
49
|
"fflate": "^0.8.3",
|
|
50
|
-
"neon-init": "0.20.4",
|
|
51
50
|
"open": "^10.2.0",
|
|
52
51
|
"openid-client": "6.8.1",
|
|
53
52
|
"pg-protocol": "^1.14.0",
|
|
@@ -57,9 +56,10 @@
|
|
|
57
56
|
"yaml": "^2.9.0",
|
|
58
57
|
"yargs": "17.7.2",
|
|
59
58
|
"@neon/sdk": "1.4.0",
|
|
60
|
-
"@neon/config": "0.
|
|
61
|
-
"@neon/config-runtime": "0.
|
|
62
|
-
"@neon/env": "0.
|
|
59
|
+
"@neon/config": "0.12.0",
|
|
60
|
+
"@neon/config-runtime": "0.12.0",
|
|
61
|
+
"@neon/env": "0.13.0",
|
|
62
|
+
"neon-init": "0.20.5"
|
|
63
63
|
},
|
|
64
64
|
"optionalDependencies": {
|
|
65
65
|
"esbuild": "0.28.1"
|