neon 2.37.1 → 2.38.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 +10 -3
- package/dist/auth_context.js +16 -0
- package/dist/commands/auth.js +13 -0
- package/dist/index.js +10 -1
- package/package.json +13 -6
package/README.md
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
# Neon CLI
|
|
2
|
+
|
|
3
|
+
The `neon` package is a command-line interface that lets you manage [Neon Serverless Postgres](https://neon.tech/) directly from the terminal. For the complete documentation, see [Neon CLI](https://neon.tech/docs/reference/neon-cli).
|
|
4
|
+
|
|
5
|
+
The legacy `neonctl` package is a lightweight compatibility package that depends
|
|
6
|
+
on this package and invokes the same CLI entry point. The implementation and
|
|
7
|
+
build artifacts live only here.
|
|
2
8
|
|
|
3
9
|
## Install the Neon CLI
|
|
4
10
|
|
|
@@ -18,7 +24,7 @@ brew install neonctl
|
|
|
18
24
|
|
|
19
25
|
**Binary (macOS, Linux, Windows)**
|
|
20
26
|
|
|
21
|
-
Download a binary
|
|
27
|
+
Download a `neon-<platform>` binary from the [releases page](https://github.com/neondatabase/neon-pkgs/releases), which carries one asset per platform for each `neon@<version>` tag.
|
|
22
28
|
|
|
23
29
|
### Upgrade
|
|
24
30
|
|
|
@@ -706,4 +712,5 @@ bun run test:conformance:matrix # run across PG 14/15/16/17/18 locally (require
|
|
|
706
712
|
|
|
707
713
|
## Releasing
|
|
708
714
|
|
|
709
|
-
Maintainers: see [
|
|
715
|
+
Maintainers: see the repository's [release skill](../../.claude/skills/release/SKILL.md)
|
|
716
|
+
for the Changesets bump and external publish flow.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
let current = null;
|
|
2
|
+
export const setAuthContext = (context) => {
|
|
3
|
+
current = context;
|
|
4
|
+
};
|
|
5
|
+
export const getAuthContext = () => current;
|
|
6
|
+
/**
|
|
7
|
+
* The config directory whose credentials a 401 should clear, or `null` to leave
|
|
8
|
+
* stored credentials alone.
|
|
9
|
+
*
|
|
10
|
+
* An API key passed on the command line never touches the stored OAuth token,
|
|
11
|
+
* so a 401 on that key says nothing about whether the stored credentials are
|
|
12
|
+
* still good — clearing them would sign the user out of an account the failed
|
|
13
|
+
* request never used. The directory comes from the context rather than the
|
|
14
|
+
* default so that `--config-dir` isolates the deletion too.
|
|
15
|
+
*/
|
|
16
|
+
export const credentialsToClearOn401 = (context) => context?.source === "stored-credentials" ? context.configDir : null;
|
package/dist/commands/auth.js
CHANGED
|
@@ -3,6 +3,7 @@ import { existsSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { getApiClient } from "../api.js";
|
|
5
5
|
import { auth, refreshToken } from "../auth.js";
|
|
6
|
+
import { setAuthContext } from "../auth_context.js";
|
|
6
7
|
import { CREDENTIALS_FILE } from "../config.js";
|
|
7
8
|
import { isConfigInit, isCurrentBranchProbe } from "../context.js";
|
|
8
9
|
import { isCi } from "../env.js";
|
|
@@ -129,6 +130,10 @@ export const ensureAuth = async (props) => {
|
|
|
129
130
|
if (props.apiKey || props._[0] === "auth") {
|
|
130
131
|
if (props.apiKey) {
|
|
131
132
|
log.debug("Using an API key to authorize requests");
|
|
133
|
+
setAuthContext({
|
|
134
|
+
source: "api-key",
|
|
135
|
+
configDir: props.configDir,
|
|
136
|
+
});
|
|
132
137
|
}
|
|
133
138
|
props.apiClient = getApiClient({
|
|
134
139
|
apiKey: props.apiKey,
|
|
@@ -149,6 +154,10 @@ export const ensureAuth = async (props) => {
|
|
|
149
154
|
if (result) {
|
|
150
155
|
props.apiKey = result.apiKey;
|
|
151
156
|
props.apiClient = result.apiClient;
|
|
157
|
+
setAuthContext({
|
|
158
|
+
source: "stored-credentials",
|
|
159
|
+
configDir: props.configDir,
|
|
160
|
+
});
|
|
152
161
|
return;
|
|
153
162
|
}
|
|
154
163
|
}
|
|
@@ -189,6 +198,10 @@ export const ensureAuth = async (props) => {
|
|
|
189
198
|
apiKey,
|
|
190
199
|
apiHost: props.apiHost,
|
|
191
200
|
});
|
|
201
|
+
setAuthContext({
|
|
202
|
+
source: "stored-credentials",
|
|
203
|
+
configDir: props.configDir,
|
|
204
|
+
});
|
|
192
205
|
};
|
|
193
206
|
/**
|
|
194
207
|
* Deletes the credentials file at the specified path
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { hideBin } from "yargs/helpers";
|
|
|
4
4
|
import { analyticsMiddleware, closeAnalytics, getAnalyticsEventProperties, initAnalyticsClientMiddleware, sendError, trackEvent, } from "./analytics.js";
|
|
5
5
|
import { isNeonApiError, messageFromBody } from "./api.js";
|
|
6
6
|
import { defaultClientID } from "./auth.js";
|
|
7
|
+
import { credentialsToClearOn401, getAuthContext } from "./auth_context.js";
|
|
7
8
|
import { deleteCredentials, ensureAuth } from "./commands/auth.js";
|
|
8
9
|
import commands from "./commands/index.js";
|
|
9
10
|
import { defaultDir, ensureConfigDir } from "./config.js";
|
|
@@ -175,9 +176,17 @@ async function handleError(msg, err) {
|
|
|
175
176
|
}
|
|
176
177
|
else if (err.status === 401) {
|
|
177
178
|
sendError(err, "AUTH_FAILED");
|
|
179
|
+
const configDir = credentialsToClearOn401(getAuthContext());
|
|
180
|
+
// The request was authorized with a key the user supplied, so there
|
|
181
|
+
// is nothing of ours to clear and nothing to retry — the same key
|
|
182
|
+
// would just be rejected again.
|
|
183
|
+
if (configDir === null) {
|
|
184
|
+
log.error("Authentication failed: the Neon API rejected the API key. Check --api-key or NEON_API_KEY.");
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
178
187
|
log.info("Authentication failed, deleting credentials...");
|
|
179
188
|
try {
|
|
180
|
-
deleteCredentials(
|
|
189
|
+
deleteCredentials(configDir);
|
|
181
190
|
return true; // Allow retry for auth failures
|
|
182
191
|
}
|
|
183
192
|
catch (deleteErr) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neon",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.38.1",
|
|
4
4
|
"description": "CLI tool for Neon Serverless Postgres",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"neon",
|
|
@@ -21,8 +21,13 @@
|
|
|
21
21
|
},
|
|
22
22
|
"type": "module",
|
|
23
23
|
"main": "dist/index.js",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": "./dist/index.js",
|
|
26
|
+
"./cli": "./dist/cli.js",
|
|
27
|
+
"./dist/*": "./dist/*",
|
|
28
|
+
"./package.json": "./package.json"
|
|
29
|
+
},
|
|
24
30
|
"bin": {
|
|
25
|
-
"neonctl": "dist/cli.js",
|
|
26
31
|
"neon": "dist/cli.js"
|
|
27
32
|
},
|
|
28
33
|
"files": [
|
|
@@ -42,7 +47,7 @@
|
|
|
42
47
|
"cliui": "8.0.1",
|
|
43
48
|
"diff": "5.2.0",
|
|
44
49
|
"fflate": "^0.8.3",
|
|
45
|
-
"neon-init": "0.20.
|
|
50
|
+
"neon-init": "0.20.3",
|
|
46
51
|
"open": "^10.2.0",
|
|
47
52
|
"openid-client": "6.8.1",
|
|
48
53
|
"pg-protocol": "^1.14.0",
|
|
@@ -53,8 +58,8 @@
|
|
|
53
58
|
"yargs": "17.7.2",
|
|
54
59
|
"@neon/sdk": "1.3.0",
|
|
55
60
|
"@neon/config": "0.10.0",
|
|
56
|
-
"@neon/
|
|
57
|
-
"@neon/
|
|
61
|
+
"@neon/env": "0.11.8",
|
|
62
|
+
"@neon/config-runtime": "0.10.0"
|
|
58
63
|
},
|
|
59
64
|
"optionalDependencies": {
|
|
60
65
|
"esbuild": "0.28.1"
|
|
@@ -83,7 +88,8 @@
|
|
|
83
88
|
"strip-ansi": "7.1.0",
|
|
84
89
|
"tsx": "4.22.3",
|
|
85
90
|
"typescript": "^5.9.0",
|
|
86
|
-
"vitest": "^3.0.9"
|
|
91
|
+
"vitest": "^3.0.9",
|
|
92
|
+
"@neon/e2e-harness": "0.0.0"
|
|
87
93
|
},
|
|
88
94
|
"publishConfig": {
|
|
89
95
|
"access": "public",
|
|
@@ -113,6 +119,7 @@
|
|
|
113
119
|
"lint:fix": "pnpm typecheck && biome check src --write",
|
|
114
120
|
"test": "pnpm --filter neonctl... build && vitest run",
|
|
115
121
|
"test:ci": "pnpm build && vitest run",
|
|
122
|
+
"test:e2e": "pnpm build && vitest run --config vitest.e2e.config.ts",
|
|
116
123
|
"test:conformance": "vitest run --config tests/psql-conformance/vitest.config.ts"
|
|
117
124
|
}
|
|
118
125
|
}
|