neon 2.45.0 → 2.46.0
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 +62 -1
- package/dist/_shared/paths.js +3 -4
- package/dist/commands/bootstrap.js +12 -11
- package/dist/commands/checkout.js +7 -6
- package/dist/commands/config.js +2 -1
- package/dist/commands/data_api.js +4 -3
- package/dist/commands/env.js +5 -4
- package/dist/commands/functions.js +3 -2
- package/dist/commands/init.js +82 -37
- package/dist/commands/ip_allow.js +3 -2
- package/dist/commands/link.js +17 -16
- package/dist/commands/projects.js +3 -2
- package/dist/commands/set_context.js +5 -4
- package/dist/current_branch_fast_path.js +2 -1
- package/dist/dev/env.js +8 -7
- package/dist/index.js +2 -2
- package/dist/init/agents.js +127 -0
- package/dist/init/auth.js +77 -0
- package/dist/init/bootstrap.js +448 -0
- package/dist/init/build_config.js +2 -0
- package/dist/init/detect_agent.js +108 -0
- package/dist/init/editors.js +62 -0
- package/dist/init/enrich_output.js +71 -0
- package/dist/init/extension.js +191 -0
- package/dist/init/inspect.js +287 -0
- package/dist/init/interactive.js +651 -0
- package/dist/init/neonctl.js +184 -0
- package/dist/init/orchestrate.js +190 -0
- package/dist/init/phases/auth.js +209 -0
- package/dist/init/phases/cleanup.js +27 -0
- package/dist/init/phases/db.js +283 -0
- package/dist/init/phases/getting_started.js +228 -0
- package/dist/init/phases/mcp.js +227 -0
- package/dist/init/phases/migrations.js +251 -0
- package/dist/init/phases/neon_auth.js +135 -0
- package/dist/init/phases/setup.js +729 -0
- package/dist/init/phases/skills.js +89 -0
- package/dist/init/phases/status.js +70 -0
- package/dist/init/resolve_context.js +107 -0
- package/dist/init/route_command.js +100 -0
- package/dist/init/skills.js +248 -0
- package/dist/init/types.js +1 -0
- package/dist/init/vsix.js +111 -0
- package/dist/psql/command/cmd_meta.js +2 -2
- package/dist/psql/core/mainloop.js +1 -1
- package/dist/psql/core/startup.js +1 -1
- package/dist/psql/core/syncVars.js +3 -3
- package/dist/psql/index.js +1 -1
- package/dist/utils/cli_name.js +14 -0
- package/dist/utils/esbuild.js +1 -1
- package/dist/utils/write_sync.js +39 -0
- package/package.json +18 -12
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared VSIX download utilities for extension installation.
|
|
3
|
+
* Supports corporate proxy via NEON_VSX_GALLERY_URL env var.
|
|
4
|
+
*/
|
|
5
|
+
import { createWriteStream } from "node:fs";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { pipeline } from "node:stream/promises";
|
|
9
|
+
import { INTERNAL_VSX_GALLERY } from "./build_config.js";
|
|
10
|
+
export const NEON_EXTENSION_ID = "databricks.neon-local-connect";
|
|
11
|
+
const OPEN_VSX_API = "https://open-vsx.org/api";
|
|
12
|
+
/**
|
|
13
|
+
* Downloads a .vsix file for the Neon extension.
|
|
14
|
+
*
|
|
15
|
+
* Strategy:
|
|
16
|
+
* 1. If NEON_VSX_GALLERY_URL is set, download from the corporate proxy gallery
|
|
17
|
+
* 2. Otherwise, download from the public Open VSX API
|
|
18
|
+
*
|
|
19
|
+
* Returns the path to the temp .vsix file, or null on failure.
|
|
20
|
+
*/
|
|
21
|
+
export async function downloadVsix() {
|
|
22
|
+
// Runtime env var takes priority, then build-time baked value
|
|
23
|
+
const proxyGallery = process.env.NEON_VSX_GALLERY_URL || INTERNAL_VSX_GALLERY || "";
|
|
24
|
+
if (proxyGallery) {
|
|
25
|
+
return downloadFromGallery(proxyGallery);
|
|
26
|
+
}
|
|
27
|
+
return downloadFromOpenVsx();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Downloads from a VS Code marketplace-compatible gallery API (corporate proxy).
|
|
31
|
+
* Uses the VS Code extensionquery POST API to find the VSIX download URL.
|
|
32
|
+
*/
|
|
33
|
+
async function downloadFromGallery(galleryUrl) {
|
|
34
|
+
const [publisher, name] = NEON_EXTENSION_ID.split(".");
|
|
35
|
+
const baseUrl = galleryUrl.replace(/\/+$/, "");
|
|
36
|
+
const queryUrl = `${baseUrl}/extensionquery`;
|
|
37
|
+
try {
|
|
38
|
+
// Query the marketplace API for the extension
|
|
39
|
+
const queryRes = await fetch(queryUrl, {
|
|
40
|
+
method: "POST",
|
|
41
|
+
headers: {
|
|
42
|
+
"Content-Type": "application/json",
|
|
43
|
+
Accept: "application/json;api-version=6.1-preview.1",
|
|
44
|
+
},
|
|
45
|
+
body: JSON.stringify({
|
|
46
|
+
filters: [
|
|
47
|
+
{
|
|
48
|
+
criteria: [
|
|
49
|
+
{ filterType: 7, value: `${publisher}.${name}` },
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
flags: 914,
|
|
54
|
+
}),
|
|
55
|
+
signal: AbortSignal.timeout(15000),
|
|
56
|
+
});
|
|
57
|
+
if (!queryRes.ok)
|
|
58
|
+
return null;
|
|
59
|
+
const data = (await queryRes.json());
|
|
60
|
+
// Find the VSIX download URL from the response
|
|
61
|
+
const extension = data.results?.[0]?.extensions?.[0];
|
|
62
|
+
const latestVersion = extension?.versions?.[0];
|
|
63
|
+
const vsixFile = latestVersion?.files?.find((f) => f.assetType === "Microsoft.VisualStudio.Services.VSIXPackage");
|
|
64
|
+
if (!vsixFile?.source)
|
|
65
|
+
return null;
|
|
66
|
+
// Download the VSIX
|
|
67
|
+
const vsixRes = await fetch(vsixFile.source, {
|
|
68
|
+
signal: AbortSignal.timeout(30000),
|
|
69
|
+
redirect: "follow",
|
|
70
|
+
});
|
|
71
|
+
if (!vsixRes.ok || !vsixRes.body)
|
|
72
|
+
return null;
|
|
73
|
+
const tmpPath = join(tmpdir(), `${NEON_EXTENSION_ID}-proxy.vsix`);
|
|
74
|
+
const fileStream = createWriteStream(tmpPath);
|
|
75
|
+
await pipeline(vsixRes.body, fileStream);
|
|
76
|
+
return tmpPath;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Downloads from the public Open VSX API.
|
|
84
|
+
*/
|
|
85
|
+
async function downloadFromOpenVsx() {
|
|
86
|
+
const [publisher, name] = NEON_EXTENSION_ID.split(".");
|
|
87
|
+
const metaUrl = `${OPEN_VSX_API}/${publisher}/${name}/latest`;
|
|
88
|
+
try {
|
|
89
|
+
const metaRes = await fetch(metaUrl, {
|
|
90
|
+
signal: AbortSignal.timeout(10000),
|
|
91
|
+
});
|
|
92
|
+
if (!metaRes.ok)
|
|
93
|
+
return null;
|
|
94
|
+
const meta = (await metaRes.json());
|
|
95
|
+
const downloadUrl = meta.files?.download;
|
|
96
|
+
if (!downloadUrl)
|
|
97
|
+
return null;
|
|
98
|
+
const vsixRes = await fetch(downloadUrl, {
|
|
99
|
+
signal: AbortSignal.timeout(30000),
|
|
100
|
+
});
|
|
101
|
+
if (!vsixRes.ok || !vsixRes.body)
|
|
102
|
+
return null;
|
|
103
|
+
const tmpPath = join(tmpdir(), `${NEON_EXTENSION_ID}-${meta.version ?? "latest"}.vsix`);
|
|
104
|
+
const fileStream = createWriteStream(tmpPath);
|
|
105
|
+
await pipeline(vsixRes.body, fileStream);
|
|
106
|
+
return tmpPath;
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -754,12 +754,12 @@ PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
|
|
754
754
|
* here on purpose (see the project's LICENSE file for terms).
|
|
755
755
|
*/
|
|
756
756
|
const NEON_NOTICE = `
|
|
757
|
-
This is an embedded psql reimplementation that ships with
|
|
757
|
+
This is an embedded psql reimplementation that ships with neon, the
|
|
758
758
|
command-line interface for Neon (https://neon.tech). Neon is part of
|
|
759
759
|
Databricks (https://www.databricks.com).
|
|
760
760
|
|
|
761
761
|
It is an independent reimplementation of psql and is not affiliated with
|
|
762
|
-
or endorsed by the PostgreSQL Global Development Group. See the
|
|
762
|
+
or endorsed by the PostgreSQL Global Development Group. See the neon
|
|
763
763
|
LICENSE file for distribution terms.
|
|
764
764
|
`;
|
|
765
765
|
/**
|
|
@@ -246,7 +246,7 @@ const isHelpKeyword = (line) => {
|
|
|
246
246
|
const stripped = trimmed.replace(/;+\s*$/u, "").trimEnd();
|
|
247
247
|
return stripped === "help";
|
|
248
248
|
};
|
|
249
|
-
const HELP_TEXT = "You are using psql-ts, the embedded TypeScript psql in
|
|
249
|
+
const HELP_TEXT = "You are using psql-ts, the embedded TypeScript psql in neon.\n" +
|
|
250
250
|
"Type: \\copyright for distribution terms\n" +
|
|
251
251
|
" \\h for help with SQL commands\n" +
|
|
252
252
|
" \\? for help with psql commands\n" +
|
|
@@ -223,7 +223,7 @@ export const CLIENT_VERSION = "1.0.0";
|
|
|
223
223
|
// `embedded-ts` label in place of a real PG build number since this is a
|
|
224
224
|
// reimplementation, not a compiled psql. Distinct from the `:VERSION` psql
|
|
225
225
|
// variable (the client-identity string seeded from CLIENT_VERSION).
|
|
226
|
-
const VERSION_STRING = `psql (PostgreSQL) embedded-ts (
|
|
226
|
+
const VERSION_STRING = `psql (PostgreSQL) embedded-ts (neon ${CLIENT_VERSION})`;
|
|
227
227
|
const pushAction = (acts, a) => {
|
|
228
228
|
acts.push(a);
|
|
229
229
|
};
|
|
@@ -85,16 +85,16 @@ export const syncConnectionVars = (vars, conn) => {
|
|
|
85
85
|
* identifier is real and traceable to the shipped binary, while keeping
|
|
86
86
|
* upstream's variable *shapes*:
|
|
87
87
|
*
|
|
88
|
-
* - `VERSION` → `psql-ts (
|
|
88
|
+
* - `VERSION` → `psql-ts (neon) <clientVersion>` — a banner that
|
|
89
89
|
* names the implementation so users can tell they are on the embedded
|
|
90
|
-
* TS port, mirroring the startup banner's `psql-ts (
|
|
90
|
+
* TS port, mirroring the startup banner's `psql-ts (neon, …)` shape.
|
|
91
91
|
* - `VERSION_NAME` → `<clientVersion>` (e.g. `2.22.0`).
|
|
92
92
|
* - `VERSION_NUM` → the same version mapped into PG's NNMMPP integer form
|
|
93
93
|
* (`2.22.0` → `22200`) via {@link clientVersionNum}, so a script doing a
|
|
94
94
|
* numeric `:VERSION_NUM` comparison gets a monotonic integer.
|
|
95
95
|
*/
|
|
96
96
|
export const setStartupVars = (vars, clientVersion) => {
|
|
97
|
-
vars.set("VERSION", `psql-ts (
|
|
97
|
+
vars.set("VERSION", `psql-ts (neon) ${clientVersion}`);
|
|
98
98
|
vars.set("VERSION_NAME", clientVersion);
|
|
99
99
|
vars.set("VERSION_NUM", String(clientVersionNum(clientVersion)));
|
|
100
100
|
};
|
package/dist/psql/index.js
CHANGED
|
@@ -337,7 +337,7 @@ const writeStartupBanner = (connection, out) => {
|
|
|
337
337
|
// Client identifier. Matches upstream's `psql (18.4, server X.Y)` shape
|
|
338
338
|
// but signals that this is the embedded TS implementation so users can tell
|
|
339
339
|
// when they're on the fallback path.
|
|
340
|
-
out.write(`psql-ts (
|
|
340
|
+
out.write(`psql-ts (neon, server ${serverVersion})\n`);
|
|
341
341
|
const tls = connection.getTlsInfo();
|
|
342
342
|
if (tls) {
|
|
343
343
|
const parts = [
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { basename } from "node:path";
|
|
2
|
+
/**
|
|
3
|
+
* The name this CLI was invoked as: `neon` (current) or `neonctl` (legacy alias).
|
|
4
|
+
*
|
|
5
|
+
* Use this for any user-facing string that suggests a command to run — help text,
|
|
6
|
+
* error hints, and especially `--agent` `next_command_template` values, which an agent
|
|
7
|
+
* executes verbatim. Hardcoding `neonctl` breaks those on installs of the `neon` package,
|
|
8
|
+
* which no longer ships a `neonctl` binary (removed in `neon@2.38.0`).
|
|
9
|
+
*
|
|
10
|
+
* Derived from `process.argv[1]`, which is fixed for the process lifetime, so the result
|
|
11
|
+
* is stable whether this is called at module load or per invocation. Mirrors the name used
|
|
12
|
+
* for yargs `.scriptName()` in `index.ts`.
|
|
13
|
+
*/
|
|
14
|
+
export const getCliName = () => basename(process.argv[1] ?? "") === "neonctl" ? "neonctl" : "neon";
|
package/dist/utils/esbuild.js
CHANGED
|
@@ -3,7 +3,7 @@ import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { basename, join } from "node:path";
|
|
5
5
|
import which from "which";
|
|
6
|
-
const NOT_FOUND = "esbuild not found.
|
|
6
|
+
const NOT_FOUND = "esbuild not found. neon ships esbuild for most platforms; if you see " +
|
|
7
7
|
"this, install esbuild and ensure it is on your PATH (e.g. `npm i -g " +
|
|
8
8
|
"esbuild`), or set NEON_ESBUILD_PATH to an esbuild binary.";
|
|
9
9
|
// Prepended to the ESM bundle. Bundled dependencies are frequently CommonJS, but an ESM
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { writeSync } from "node:fs";
|
|
2
|
+
/**
|
|
3
|
+
* Write `text` to a file descriptor and do not return until all of it is out.
|
|
4
|
+
*
|
|
5
|
+
* `process.stdout.write` is asynchronous when stdout is a pipe — which it is whenever the
|
|
6
|
+
* caller is an agent or a script capturing output — so a `process.exit()` on the next line
|
|
7
|
+
* discards whatever has not been flushed. The caller sees an exit code and empty stdout.
|
|
8
|
+
*
|
|
9
|
+
* Use this for any final message that is followed by `process.exit`.
|
|
10
|
+
*/
|
|
11
|
+
export function writeAllSync(fd, text) {
|
|
12
|
+
let buffer = Buffer.from(text, "utf8");
|
|
13
|
+
while (buffer.length > 0) {
|
|
14
|
+
try {
|
|
15
|
+
buffer = buffer.subarray(writeSync(fd, buffer));
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
const code = err.code;
|
|
19
|
+
if (code === "EAGAIN") {
|
|
20
|
+
// Wait for the reader rather than spinning on it. A pipe nobody is draining
|
|
21
|
+
// would otherwise burn a core until it is; failure output is small enough
|
|
22
|
+
// that this should never be reached, which is the reason to bound it rather
|
|
23
|
+
// than assume so.
|
|
24
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 5);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
// The reader closed the pipe (`neon … | head`). There is nobody left to tell,
|
|
28
|
+
// and this is the last thing the process does, so stop rather than throw.
|
|
29
|
+
if (code === "EPIPE")
|
|
30
|
+
return;
|
|
31
|
+
// Anything else means the write did not happen and the caller is about to exit
|
|
32
|
+
// as though it had. Swallowing it turns a lost payload into an apparent success.
|
|
33
|
+
throw err;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** File descriptors, named so call sites read as the stream they mean. */
|
|
38
|
+
export const STDOUT_FD = 1;
|
|
39
|
+
export const STDERR_FD = 2;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neon",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.46.0",
|
|
4
4
|
"description": "CLI tool for Neon, the cloud backend primitives built around Lakebase Postgres",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"neon",
|
|
@@ -39,6 +39,8 @@
|
|
|
39
39
|
"node": ">=20.19.0"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
+
"@clack/core": "0.4.2",
|
|
43
|
+
"@clack/prompts": "0.10.1",
|
|
42
44
|
"@hono/node-server": "2.0.4",
|
|
43
45
|
"@segment/analytics-node": "1.3.0",
|
|
44
46
|
"chalk": "5.3.0",
|
|
@@ -46,20 +48,22 @@
|
|
|
46
48
|
"cli-table": "0.3.11",
|
|
47
49
|
"cliui": "8.0.1",
|
|
48
50
|
"diff": "5.2.0",
|
|
51
|
+
"execa": "^9.5.2",
|
|
49
52
|
"fflate": "^0.8.3",
|
|
50
53
|
"open": "^10.2.0",
|
|
51
54
|
"openid-client": "6.8.1",
|
|
52
55
|
"pg-protocol": "^1.14.0",
|
|
56
|
+
"picocolors": "^1.1.1",
|
|
53
57
|
"prompts": "2.4.2",
|
|
54
58
|
"undici": "^7.28.0",
|
|
55
59
|
"which": "3.0.1",
|
|
56
60
|
"yaml": "^2.9.0",
|
|
57
61
|
"yargs": "17.7.2",
|
|
62
|
+
"yoctocolors": "^2.1.2",
|
|
58
63
|
"@neon/sdk": "1.5.0",
|
|
59
|
-
"@neon/config": "0.14.
|
|
60
|
-
"@neon/config-runtime": "0.12.
|
|
61
|
-
"neon
|
|
62
|
-
"@neon/env": "0.14.0"
|
|
64
|
+
"@neon/config": "0.14.1",
|
|
65
|
+
"@neon/config-runtime": "0.12.5",
|
|
66
|
+
"@neon/env": "0.14.1"
|
|
63
67
|
},
|
|
64
68
|
"optionalDependencies": {
|
|
65
69
|
"esbuild": "0.28.1"
|
|
@@ -111,15 +115,17 @@
|
|
|
111
115
|
},
|
|
112
116
|
"scripts": {
|
|
113
117
|
"generateParams": "tsx generateOptionsFromSpec.ts",
|
|
118
|
+
"codegen": "node ../../scripts/sync-shared.mjs . && node scripts/set-vsx-gallery.mjs",
|
|
114
119
|
"clean": "rm -rf dist",
|
|
115
|
-
"build": "
|
|
120
|
+
"build": "pnpm codegen && pnpm generateParams && pnpm clean && tsc -p tsconfig.build.json && cp src/*.html ./dist",
|
|
121
|
+
"build:internal": "node ../../scripts/sync-shared.mjs . && node scripts/set-vsx-gallery.mjs https://cursor-vsx-proxy.cloud.databricks.com/gallery && pnpm generateParams && pnpm clean && tsc -p tsconfig.build.json && cp src/*.html ./dist",
|
|
116
122
|
"bundle": "node pkg.js",
|
|
117
|
-
"typecheck": "
|
|
118
|
-
"lint": "
|
|
123
|
+
"typecheck": "pnpm codegen && tsc --noEmit",
|
|
124
|
+
"lint": "pnpm codegen && pnpm typecheck && biome check src",
|
|
119
125
|
"lint:fix": "pnpm typecheck && biome check src --write",
|
|
120
|
-
"test": "
|
|
121
|
-
"test:ci": "
|
|
122
|
-
"test:e2e": "
|
|
123
|
-
"test:conformance": "
|
|
126
|
+
"test": "pnpm codegen && pnpm --filter neonctl... build && vitest run",
|
|
127
|
+
"test:ci": "pnpm codegen && pnpm build && vitest run",
|
|
128
|
+
"test:e2e": "pnpm codegen && pnpm build && vitest run --config vitest.e2e.config.ts",
|
|
129
|
+
"test:conformance": "pnpm codegen && vitest run --config tests/psql-conformance/vitest.config.ts"
|
|
124
130
|
}
|
|
125
131
|
}
|