neon 8.0.11 → 8.1.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 +22 -21
- package/dist/_chunks/{auth_selection-pitMFzDe.js → auth_selection-YX5_KZgD.js} +3 -3
- package/dist/_chunks/{credential_io-D8AR-jvB.js → credential_io-ByNuojoE.js} +2 -2
- package/dist/_chunks/{profiles-CvnFEQyd.js → profiles-DIB1av2Q.js} +2 -2
- package/dist/_shared/auth_selection.js +2 -2
- package/dist/_shared/profiles.js +3 -3
- package/dist/analytics.js +1 -1
- package/dist/auth_context.js +2 -2
- package/dist/auth_recovery.js +2 -2
- package/dist/commands/auth.js +16 -10
- package/dist/commands/checkout.js +12 -1
- package/dist/commands/claim.js +2 -2
- package/dist/commands/config.js +6 -12
- package/dist/commands/dev.js +2 -2
- package/dist/commands/env.js +1 -1
- package/dist/commands/init.js +3 -5
- package/dist/commands/manifest.js +2 -2
- package/dist/commands/mcp.js +1 -1
- package/dist/commands/profile.js +4 -4
- package/dist/commands/user.js +1 -0
- package/dist/config_template.js +10 -8
- package/dist/credential_io.js +1 -1
- package/dist/index.js +1 -1
- package/dist/init/choices.js +2 -6
- package/dist/init/copy.js +3 -3
- package/dist/init/detect.js +3 -3
- package/dist/init/plan.js +2 -3
- package/dist/init/run.js +11 -24
- package/dist/mcp/mint.js +1 -1
- package/dist/neon_services.js +9 -20
- package/dist/retire_credential.js +1 -1
- package/dist/utils/middlewares.js +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -63,10 +63,10 @@ leaves `neon` running the other install, such as npm. While duplicates remain, t
|
|
|
63
63
|
Run the following command to authenticate a connection to Neon:
|
|
64
64
|
|
|
65
65
|
```bash
|
|
66
|
-
neon
|
|
66
|
+
neon login
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
The `
|
|
69
|
+
`neon auth` is an alias of `neon login`. The `login` command launches a browser window where you can authorize the Neon CLI to access your Neon account. Running a Neon CLI command without authenticating with [neon login](https://neon.com/docs/cli/auth) automatically launches the browser authentication process, except for `neon me`, which reports that you are not signed in.
|
|
70
70
|
|
|
71
71
|
Alternatively, you can authenticate a connection with a Neon API key using the `--api-key` option when running a Neon CLI command. For example, an API key is used with the following `neon projects list` command:
|
|
72
72
|
|
|
@@ -76,7 +76,7 @@ neon projects list --api-key <neon_api_key>
|
|
|
76
76
|
|
|
77
77
|
For information about obtaining an Neon API key, see [Authentication](https://neon.com/docs/reference/api/get-started), in the _Neon API Reference_.
|
|
78
78
|
|
|
79
|
-
To check which account and credential a command uses, run `neon me` with the same `--profile` or `--api-key` option and environment as that command. The `Authentication` row names the source, such as `OAuth (profile DEFAULT)`, `API key (profile work)`, `API key (--api-key)`, or `API key (NEON_API_KEY)`.
|
|
79
|
+
To check which account and credential a command uses, run `neon me` with the same `--profile` or `--api-key` option and environment as that command. The `Authentication` row names the source, such as `OAuth (profile DEFAULT)`, `API key (profile work)`, `API key (--api-key)`, or `API key (NEON_API_KEY)`. When no credential is usable, `neon me` exits 1 with `Not signed in` and the `neon login` command to run; it never starts a sign-in itself.
|
|
80
80
|
|
|
81
81
|
## Create a project without an account
|
|
82
82
|
|
|
@@ -658,13 +658,15 @@ neon config init --services data-api
|
|
|
658
658
|
# Repeat the flag instead, and shorten it — every services flag takes all three spellings
|
|
659
659
|
neon config init -s auth -s functions
|
|
660
660
|
|
|
661
|
-
#
|
|
662
|
-
neon config init --services
|
|
661
|
+
# Postgres only: the starter policy, with no prompt
|
|
662
|
+
neon config init --services postgres
|
|
663
663
|
|
|
664
664
|
# Scaffold but print the install command instead of running it
|
|
665
665
|
neon config init --no-install
|
|
666
666
|
```
|
|
667
667
|
|
|
668
|
+
`postgres` declares nothing, since every branch has Postgres, so it can stand alone or sit next to other services. `neon init --services` takes the same values.
|
|
669
|
+
|
|
668
670
|
Object storage is spelled `object-storage` here, matching [`env pull --service`](#env-pull) and the rest of the CLI. The old `storage` still works and warns; it will be removed.
|
|
669
671
|
|
|
670
672
|
Choosing **Functions** also writes the handler the policy points at, since `source` is only resolved when `apply` bundles it — a declared function with no file on disk fails at deploy:
|
|
@@ -740,9 +742,8 @@ The branch is chosen with `--branch <id|name>`; without it the project's default
|
|
|
740
742
|
|
|
741
743
|
**Apply-only flags** (also available on `deploy`):
|
|
742
744
|
|
|
743
|
-
- `--update-existing` — auto-confirm overriding existing remote settings on the branch. Without it, drift on settings already present remotely (compute, TTL, `protected`) is reported as a **conflict** and `apply` makes no changes until you resolve it or pass this flag.
|
|
745
|
+
- `--update-existing` (`-y`, `--yes`) — auto-confirm overriding existing remote settings on the branch. Without it, drift on settings already present remotely (compute, TTL, `protected`) is reported as a **conflict** and `apply` makes no changes until you resolve it or pass this flag.
|
|
744
746
|
- `--allow-protected` — auto-confirm applying to a branch Neon marks as protected. Without it, `apply` refuses to touch a protected branch.
|
|
745
|
-
|
|
746
747
|
**Output**: `status` prints the project, branch, and reverse-engineered config. `plan` / `apply` render a **`git diff`-style report** (matching [`neon diff`](#diff)): service changes (Neon Auth, Data API, buckets, functions) list as green `+` additions, while **branch setting changes** (TTL, `protected`, compute) show grouped under a `~ <branch>` header, one sorted `field → value` line each. A bare `apply` that hits drift on settings already present remotely prints those as a sorted **before→after** diff (`current → desired`, old in red / new in green) and exits non-zero until you pass `--update-existing`. Pass `--output json` (or `--output yaml`) to emit the full machine-readable result (`PushResult`) instead, for piping into other tools or CI.
|
|
747
748
|
|
|
748
749
|
**`config status --current-branch`** (alias `neon status --current-branch`) prints _only_ the branch pinned in the local `.neon` file — no network, no auth, no analytics — and exits non-zero when none is pinned. This behavior lets it safely drive a shell prompt. Example [starship](https://starship.rs) segment:
|
|
@@ -831,7 +832,7 @@ The target directory must be empty unless you pass `--force` (a lone `.git` is i
|
|
|
831
832
|
|
|
832
833
|
Recommended installs the Neon plugin for every detected agent (global config, project folders, and the host CLI). Plugin-capable agents get the plugin; the rest get skills and MCP. If none are detected, it installs the default Neon skills for Cursor and Codex in this directory (`./.agents/skills`) and does not configure MCP. It then links a project when the CLI is authenticated, and writes a default `neon.ts` (Postgres only) using the package manager already in the directory.
|
|
833
834
|
|
|
834
|
-
Unauthenticated `-y` skips linking and prints the next step: sign up at https://neon.com/signup, then `neon
|
|
835
|
+
Unauthenticated `-y` skips linking and prints the next step: sign up at https://neon.com/signup, then `neon login`, `neon link`, or `neon claim create` (no account, expires in 72 hours unless claimed). `-y` never opens a browser. `-y` with `--project-id` or other account flags links when the CLI is already signed in; otherwise it errors and names `neon login` or `--claimable`.
|
|
835
836
|
|
|
836
837
|
Custom asks how to add Neon to coding agents (plugin, skills and MCP separately, or skip), then how to get a project (sign in and link, or a claimable project when you are not signed in), then which services `neon.ts` should declare. Skills and MCP use separate agent pickers, and either can be skipped. Postgres is listed first as always included. The package manager is inferred from the directory; Custom asks only when none is detected. `--skill` selects skills (not the plugin) and skips that picker. MCP flags (`--mcp-config-location`, `--mcp-auth`, `--mcp-project-scoped`) select skills and MCP. `--mcp-config-location` is where the config is written: `global` maps to `neon mcp`, and `project` maps to `neon mcp --project`. With `-y`, the location defaults to `global`; interactive Custom asks. If some selected agents cannot write that location, init warns and skips MCP for those agents while continuing with the supported agents. It fails when none of the selected agents support the location. `--mcp-project-scoped` limits MCP tools to the linked Neon project by passing its ID to `neon mcp --project-id`. Omitted is false, including in Custom; there is no prompt. `--no-agent-setup` skips agent setup.
|
|
837
838
|
|
|
@@ -1198,18 +1199,18 @@ Credential Manager, Linux Secret Service) only when its `profiles.json` pointer
|
|
|
1198
1199
|
That is per profile. Reads never migrate.
|
|
1199
1200
|
|
|
1200
1201
|
```bash
|
|
1201
|
-
neon
|
|
1202
|
-
neon
|
|
1202
|
+
neon login --keyring # sign DEFAULT into the OS keyring
|
|
1203
|
+
neon login --keyring --profile work # sign work into the OS keyring
|
|
1203
1204
|
neon profile create work --keyring # create a named profile in the keyring
|
|
1204
1205
|
neon profile remove work --yes # drop a keyring profile, then create it again as a file
|
|
1205
1206
|
```
|
|
1206
1207
|
|
|
1207
|
-
File to keyring is `neon
|
|
1208
|
+
File to keyring is `neon login --keyring` or `neon profile create … --keyring`: a new
|
|
1208
1209
|
sign-in, then the previous credential is revoked and the owned file is deleted.
|
|
1209
|
-
`create` on an existing name always revokes after a successful write. `
|
|
1210
|
+
`create` on an existing name always revokes after a successful write. `login` revokes
|
|
1210
1211
|
when it writes to the keyring, including a re-login that follows an existing pointer.
|
|
1211
|
-
`
|
|
1212
|
-
|
|
1212
|
+
`login` that overwrites a file does not. Keyring to file is `remove`, then create or
|
|
1213
|
+
log in again. `create` and `login` without `--keyring` follow an existing `"keyring"`
|
|
1213
1214
|
pointer, so a keyring profile cannot leave the OS store until `remove` succeeds.
|
|
1214
1215
|
|
|
1215
1216
|
`--api-key` and `NEON_API_KEY` skip both stores. A GitHub-release `neon-<platform>`
|
|
@@ -1218,7 +1219,7 @@ Use the npm-installed `neon`. Older releases treat the sentinel as a relative pa
|
|
|
1218
1219
|
|
|
1219
1220
|
A `"keyring"` pointer whose OS item cannot be read is not treated as signed-out. Commands that
|
|
1220
1221
|
would otherwise open a browser fail: could not read the OS keyring item. Unlock it and
|
|
1221
|
-
retry, or run `neon
|
|
1222
|
+
retry, or run `neon login --profile DEFAULT`. To reset the profile: `neon profile remove DEFAULT --yes`.
|
|
1222
1223
|
A missing `credentials.json` with no `profiles.json` is still
|
|
1223
1224
|
signed-out, and those commands start OAuth.
|
|
1224
1225
|
|
|
@@ -1258,7 +1259,7 @@ the key never leaves the CLI.
|
|
|
1258
1259
|
**A profile is one kind or the other, never both.** `type` in the credentials file states which:
|
|
1259
1260
|
|
|
1260
1261
|
```json
|
|
1261
|
-
// oauth: what a plain `create` (or `neon
|
|
1262
|
+
// oauth: what a plain `create` (or `neon login --profile`) writes. An absent `type` means this.
|
|
1262
1263
|
{ "access_token": "…", "refresh_token": "…", "expires_at": 1786…, "user_id": "…" }
|
|
1263
1264
|
|
|
1264
1265
|
// api_key: what `--api-key` writes
|
|
@@ -1299,7 +1300,7 @@ Passing both flags fails rather than picking a winner: `--api-key` supplies a cr
|
|
|
1299
1300
|
|
|
1300
1301
|
When both are only environment variables the key wins, which keeps a CI pipeline that injects `NEON_API_KEY` working even if a `NEON_PROFILE` leaks into the environment — but the disregarded profile is named on stderr rather than passed over silently.
|
|
1301
1302
|
|
|
1302
|
-
`neon
|
|
1303
|
+
`neon login` and the `profile` subcommands are outside all of this, because they read the same flags to mean something else: `neon login --profile work` names where to write a credential, and `neon profile create work --api-key …` names one to store.
|
|
1303
1304
|
|
|
1304
1305
|
`neon init` forwards `--profile` and `--config-dir` to agent and config children and uses them directly for its link flow. An explicit `--api-key` is passed to authenticated children through `NEON_API_KEY`, not argv.
|
|
1305
1306
|
|
|
@@ -1387,7 +1388,7 @@ Id Name Project Created At Last Used At Last
|
|
|
1387
1388
|
|
|
1388
1389
|
| Command | Subcommands | Description |
|
|
1389
1390
|
| -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ---------------------------------- |
|
|
1390
|
-
| [
|
|
1391
|
+
| [login](https://neon.com/docs/reference/cli-auth) (`auth`) | | Authenticate |
|
|
1391
1392
|
| claim (`claimable`) | `create`, `status`, `accept`, `list`, `delete` | Manage claimable projects |
|
|
1392
1393
|
| profile | `list`, `create`, `rotate-key`, `remove` | Manage named sets of credentials |
|
|
1393
1394
|
| api-keys | `list`, `create`, `revoke` | Manage API keys |
|
|
@@ -1449,7 +1450,7 @@ Global options are supported with any Neon CLI command.
|
|
|
1449
1450
|
|
|
1450
1451
|
- <a id="config-dir"></a>`--config-dir`
|
|
1451
1452
|
|
|
1452
|
-
Specifies the path to the `neon` configuration directory, which holds the `credentials.json` written by `neon
|
|
1453
|
+
Specifies the path to the `neon` configuration directory, which holds the `credentials.json` written by `neon login` and, when a second profile exists or DEFAULT is keyring, `profiles.json`. The default is `$XDG_CONFIG_HOME/neon`, or `~/.config/neon`; run `neon --help` to see the resolved path. This option is only necessary if you keep your configuration somewhere else.
|
|
1453
1454
|
|
|
1454
1455
|
The directory was called `neonctl` before the CLI was renamed. An existing one is still read, and is used **in place** — nothing is moved or copied, so there is never a second credentials file to go stale. A directory you pass explicitly is used exactly as given and never falls back to the legacy name, so pointing a CI run at a scratch directory cannot pick up local credentials.
|
|
1455
1456
|
|
|
@@ -1462,7 +1463,7 @@ Global options are supported with any Neon CLI command.
|
|
|
1462
1463
|
Selects a named set of credentials, for holding more than one Neon account at a time. A profile is a pointer to a credentials file, recorded in `profiles.json` next to it.
|
|
1463
1464
|
|
|
1464
1465
|
```bash
|
|
1465
|
-
neon
|
|
1466
|
+
neon login --profile work # create it, or sign in again
|
|
1466
1467
|
neon profile list # names, accounts, and where each one's credentials live
|
|
1467
1468
|
neon projects list --profile work
|
|
1468
1469
|
NEON_PROFILE=work neon projects list
|
|
@@ -1472,7 +1473,7 @@ Global options are supported with any Neon CLI command.
|
|
|
1472
1473
|
|
|
1473
1474
|
- <a id="api-key"></a>`--api-key`
|
|
1474
1475
|
|
|
1475
|
-
Specifies your Neon API key. You can authenticate using a Neon API key when running a Neon CLI command instead of using `neon
|
|
1476
|
+
Specifies your Neon API key. You can authenticate using a Neon API key when running a Neon CLI command instead of using `neon login`. For information about obtaining an Neon API key, see [Authentication](https://neon.com/docs/reference/api/get-started), in the _Neon API Reference_.
|
|
1476
1477
|
|
|
1477
1478
|
```bash
|
|
1478
1479
|
neon <command> --api-key <neon_api_key>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./profiles-
|
|
1
|
+
import "./profiles-DIB1av2Q.js";
|
|
2
2
|
//#region ../../internals/cli-core/dist/auth_selection.js
|
|
3
3
|
/**
|
|
4
4
|
* # Which credential an invocation authenticates with
|
|
@@ -32,8 +32,8 @@ import "./profiles-CvnFEQyd.js";
|
|
|
32
32
|
* the environment. It warns instead of staying silent, because a disregarded account
|
|
33
33
|
* selection is precisely what nobody noticed last time.
|
|
34
34
|
*
|
|
35
|
-
* `
|
|
36
|
-
* different meanings — `neon
|
|
35
|
+
* `login` and the `profile` subcommands do not use any of this. They read the same flags with
|
|
36
|
+
* different meanings — `neon login --profile work` names where to *write* a credential, and
|
|
37
37
|
* `neon profile create work --api-key …` names one to *store* — so their callers skip
|
|
38
38
|
* selection entirely rather than passing exemptions down here.
|
|
39
39
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as writeSecretFile } from "./secure_file-BucZj4yQ.js";
|
|
2
2
|
import { a as isOwnedCredentialPath } from "./paths-DMq0Lt7a.js";
|
|
3
|
-
import { f as profilesFilePath, v as CRED_STORAGE_FILE, y as CRED_STORAGE_KEYRING } from "./profiles-
|
|
3
|
+
import { f as profilesFilePath, v as CRED_STORAGE_FILE, y as CRED_STORAGE_KEYRING } from "./profiles-DIB1av2Q.js";
|
|
4
4
|
import { tryLoadKeyring } from "../keyring.js";
|
|
5
5
|
import { existsSync, readFileSync, rmSync } from "node:fs";
|
|
6
6
|
import { dirname } from "node:path";
|
|
@@ -202,7 +202,7 @@ var KeyringUnavailableError = class extends Error {
|
|
|
202
202
|
};
|
|
203
203
|
var KeyringUnreadableError = class extends Error {
|
|
204
204
|
constructor(profile) {
|
|
205
|
-
const replace = `\`neon
|
|
205
|
+
const replace = `\`neon login --profile ${profile}\``;
|
|
206
206
|
super(`Could not read the OS keyring item for profile "${profile}". Unlock the keyring and retry, or run ${replace}. To reset the profile: \`neon profile remove ${profile} --yes\`.`);
|
|
207
207
|
this.name = "KeyringUnreadableError";
|
|
208
208
|
}
|
|
@@ -82,7 +82,7 @@ const inspectProfiles = (dir) => {
|
|
|
82
82
|
*
|
|
83
83
|
* A malformed file is reported through `onWarn` and treated as absent, because for a *read* the
|
|
84
84
|
* worst case is a named profile turning up missing, which is recoverable — whereas throwing
|
|
85
|
-
* would lock the user out of `neon
|
|
85
|
+
* would lock the user out of `neon login` itself. Writing is the opposite: see
|
|
86
86
|
* {@link upsertProfile}, which refuses rather than rebuilding a file it cannot read.
|
|
87
87
|
*/
|
|
88
88
|
const readProfiles = (dir, onWarn = () => {}) => {
|
|
@@ -96,7 +96,7 @@ const readProfiles = (dir, onWarn = () => {}) => {
|
|
|
96
96
|
*
|
|
97
97
|
* Call this **before** anything that writes a credential, opens a browser, or spends an API
|
|
98
98
|
* call. {@link upsertProfile} refuses too, but it runs last: by then `create` has already
|
|
99
|
-
* overwritten `credentials.<name>.json` and revoked the key it replaced, and `neon
|
|
99
|
+
* overwritten `credentials.<name>.json` and revoked the key it replaced, and `neon login
|
|
100
100
|
* --profile` has already signed in over it — a refusal that arrives after the destruction it
|
|
101
101
|
* exists to prevent. The path resolution itself is the unsound part, since with the metadata
|
|
102
102
|
* unreadable the conventional filename is a guess about which account that file belongs to.
|
|
@@ -32,8 +32,8 @@ import "./profiles.js";
|
|
|
32
32
|
* the environment. It warns instead of staying silent, because a disregarded account
|
|
33
33
|
* selection is precisely what nobody noticed last time.
|
|
34
34
|
*
|
|
35
|
-
* `
|
|
36
|
-
* different meanings — `neon
|
|
35
|
+
* `login` and the `profile` subcommands do not use any of this. They read the same flags with
|
|
36
|
+
* different meanings — `neon login --profile work` names where to *write* a credential, and
|
|
37
37
|
* `neon profile create work --api-key …` names one to *store* — so their callers skip
|
|
38
38
|
* selection entirely rather than passing exemptions down here.
|
|
39
39
|
*/
|
package/dist/_shared/profiles.js
CHANGED
|
@@ -13,7 +13,7 @@ import { isAbsolute, relative, resolve } from "node:path";
|
|
|
13
13
|
* ```
|
|
14
14
|
* ~/.config/neon/
|
|
15
15
|
* ├── credentials.json # this IS the DEFAULT profile, not a copy of it
|
|
16
|
-
* ├── credentials.work.json # created by `neon
|
|
16
|
+
* ├── credentials.work.json # created by `neon login --profile work`
|
|
17
17
|
* └── profiles.json # created only once a second profile exists
|
|
18
18
|
* ```
|
|
19
19
|
*
|
|
@@ -105,7 +105,7 @@ const inspectProfiles = (dir) => {
|
|
|
105
105
|
*
|
|
106
106
|
* A malformed file is reported through `onWarn` and treated as absent, because for a *read* the
|
|
107
107
|
* worst case is a named profile turning up missing, which is recoverable — whereas throwing
|
|
108
|
-
* would lock the user out of `neon
|
|
108
|
+
* would lock the user out of `neon login` itself. Writing is the opposite: see
|
|
109
109
|
* {@link upsertProfile}, which refuses rather than rebuilding a file it cannot read.
|
|
110
110
|
*/
|
|
111
111
|
const readProfiles = (dir, onWarn = () => {}) => {
|
|
@@ -119,7 +119,7 @@ const readProfiles = (dir, onWarn = () => {}) => {
|
|
|
119
119
|
*
|
|
120
120
|
* Call this **before** anything that writes a credential, opens a browser, or spends an API
|
|
121
121
|
* call. {@link upsertProfile} refuses too, but it runs last: by then `create` has already
|
|
122
|
-
* overwritten `credentials.<name>.json` and revoked the key it replaced, and `neon
|
|
122
|
+
* overwritten `credentials.<name>.json` and revoked the key it replaced, and `neon login
|
|
123
123
|
* --profile` has already signed in over it — a refusal that arrives after the destruction it
|
|
124
124
|
* exists to prevent. The path resolution itself is the unsound part, since with the metadata
|
|
125
125
|
* unreadable the conventional filename is a guess about which account that file belongs to.
|
package/dist/analytics.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as OAUTH, t as storeFor } from "./_chunks/credential_io-
|
|
1
|
+
import { a as OAUTH, t as storeFor } from "./_chunks/credential_io-ByNuojoE.js";
|
|
2
2
|
import { getCliAgent, getGithubEnvVars, isCi } from "./env.js";
|
|
3
3
|
import { log } from "./log.js";
|
|
4
4
|
import pkg_default from "./pkg.js";
|
package/dist/auth_context.js
CHANGED
|
@@ -31,8 +31,8 @@ const authFailureMessage = (context) => {
|
|
|
31
31
|
if (context?.source === "profile-api-key") return `Authentication failed: the Neon API rejected profile "${profile}"'s API key${where}. Replace it with \`neon profile create ${profile} --mint\`, or store another with \`neon profile create ${profile} --api-key -\`.`;
|
|
32
32
|
if (context?.source === "claimable") return `Authentication failed: Claimable Neon rejected the linked project's short-lived access token${where}. Retry the command to exchange the saved identity assertion again; if it still fails, run \`neon claim status\`.`;
|
|
33
33
|
if (context?.source === "stored-credentials") {
|
|
34
|
-
if (context.storage === "keyring") return `Authentication failed: the Neon API rejected profile "${profile}"'s stored session (OS keyring). Sign in again with \`neon
|
|
35
|
-
return `Authentication failed: the Neon API rejected profile "${profile}"'s stored session${where}. Sign in again with \`neon
|
|
34
|
+
if (context.storage === "keyring") return `Authentication failed: the Neon API rejected profile "${profile}"'s stored session (OS keyring). Sign in again with \`neon login --profile ${profile}\`.`;
|
|
35
|
+
return `Authentication failed: the Neon API rejected profile "${profile}"'s stored session${where}. Sign in again with \`neon login --profile ${profile}\`.`;
|
|
36
36
|
}
|
|
37
37
|
return "Authentication failed: the Neon API rejected the API key. Check --api-key or NEON_API_KEY.";
|
|
38
38
|
};
|
package/dist/auth_recovery.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as storeFor } from "./_chunks/credential_io-
|
|
1
|
+
import { t as storeFor } from "./_chunks/credential_io-ByNuojoE.js";
|
|
2
2
|
import { log } from "./log.js";
|
|
3
3
|
import { authFailureMessage, getAuthContext, locationFromContext } from "./auth_context.js";
|
|
4
4
|
import { AuthRefreshError } from "./auth.js";
|
|
@@ -49,7 +49,7 @@ const recoverFrom401 = async (canRetry) => {
|
|
|
49
49
|
} catch (err) {
|
|
50
50
|
if (err instanceof AuthRefreshError) {
|
|
51
51
|
log.error(err.message);
|
|
52
|
-
if (err.terminal) log.error(`Run \`neon
|
|
52
|
+
if (err.terminal) log.error(`Run \`neon login --profile ${context.profile ?? "DEFAULT"}\` to sign in again.`);
|
|
53
53
|
return false;
|
|
54
54
|
}
|
|
55
55
|
log.debug("Refresh after 401 failed: %s", err instanceof Error ? err.message : "unknown error");
|
package/dist/commands/auth.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { t as __exportAll } from "../_chunks/rolldown-runtime-8H4AJuhK.js";
|
|
2
|
-
import { a as OAUTH, i as API_KEY, l as interpretCredentials, s as credentialLabel, t as storeFor } from "../_chunks/credential_io-
|
|
2
|
+
import { a as OAUTH, i as API_KEY, l as interpretCredentials, s as credentialLabel, t as storeFor } from "../_chunks/credential_io-ByNuojoE.js";
|
|
3
3
|
import { isCi } from "../env.js";
|
|
4
4
|
import { log } from "../log.js";
|
|
5
5
|
import { getApiClient, isNeonApiError } from "../api.js";
|
|
6
6
|
import { setAuthContext } from "../auth_context.js";
|
|
7
7
|
import { a as isOwnedCredentialPath } from "../_chunks/paths-DMq0Lt7a.js";
|
|
8
8
|
import { currentContextFile, isAskCommand, isClaimCommand, isConfigAdd, isConfigInit, isCurrentBranchProbe, isFeedbackCommand, isGitLocalCommand, isInspectDbUrl, isMcpCommand, isMcpOauth, isPluginsCommand, isProfileCommand, isSkillsCommand, isUnfollowedGitHookSync, readContextFile } from "../context.js";
|
|
9
|
-
import { _ as upsertProfile, d as newProfileLocation, g as selectProfileName, h as resolveProfile, i as assertValidProfileName, l as locationForName, m as readProfiles, n as KEYRING_CREDENTIALS, p as profilesUsingPath, r as assertProfilesUsable, s as isKeyringPointer, t as DEFAULT_PROFILE, u as locationOf } from "../_chunks/profiles-
|
|
9
|
+
import { _ as upsertProfile, d as newProfileLocation, g as selectProfileName, h as resolveProfile, i as assertValidProfileName, l as locationForName, m as readProfiles, n as KEYRING_CREDENTIALS, p as profilesUsingPath, r as assertProfilesUsable, s as isKeyringPointer, t as DEFAULT_PROFILE, u as locationOf } from "../_chunks/profiles-DIB1av2Q.js";
|
|
10
10
|
import { extendTokenSet } from "../utils/auth.js";
|
|
11
11
|
import { AuthRefreshError, auth, classifyRefreshFailure, refreshToken } from "../auth.js";
|
|
12
|
-
import { i as selectCredential, n as displacedProfileWarning, t as credentialInputs } from "../_chunks/auth_selection-
|
|
12
|
+
import { i as selectCredential, n as displacedProfileWarning, t as credentialInputs } from "../_chunks/auth_selection-YX5_KZgD.js";
|
|
13
13
|
import { ClaimableClient, ClaimableServiceError } from "../claimable/api.js";
|
|
14
14
|
import { assertionHasExpired, claimableCredentialsExist, claimableCredentialsPath, readLinkedClaimableCredentials, shouldUseClaimableCredentials } from "../claimable/state.js";
|
|
15
15
|
import { withExclusiveLock } from "../refresh_lock.js";
|
|
@@ -45,8 +45,8 @@ const locationForAuth = (configDir, name, keyring, options = {}) => {
|
|
|
45
45
|
if (options.create === true) return newProfileLocation(configDir, name, "file");
|
|
46
46
|
return locationForName(configDir, name);
|
|
47
47
|
};
|
|
48
|
-
const command = "
|
|
49
|
-
const aliases = ["
|
|
48
|
+
const command = "login";
|
|
49
|
+
const aliases = ["auth"];
|
|
50
50
|
const describe = "Sign in with a browser. See --help for API keys and profiles";
|
|
51
51
|
const wrapAuthHelp = (text) => wrapHelpText(text, helpWidth());
|
|
52
52
|
const authHelpEpilogue = () => {
|
|
@@ -54,9 +54,9 @@ const authHelpEpilogue = () => {
|
|
|
54
54
|
return helpEpilogue(wrapAuthHelp("Non-interactive (CI, scripts, agents):"), wrapAuthHelp("Use an existing API key or an API-key profile."), ` ${cli} projects list --profile agent`, wrapAuthHelp(`${cli} profile create <name> --mint needs a browser during setup, then stores an API key and drops the session. It cannot run in CI. Default key is account-wide; --org-id or --project-id (not both) restricts it.`), wrapAuthHelp(`A profile holds a browser session or an API key. Select it with --profile <name> or NEON_PROFILE. List profiles with ${cli} profile list.`), wrapAuthHelp("On commands that use a credential, --api-key or --profile overrides NEON_API_KEY and NEON_PROFILE. Pass either --api-key or --profile, not both. When neither flag is passed and both NEON_API_KEY and NEON_PROFILE are set, the key wins and stderr names the ignored profile. When no flag or environment variable selects a credential, DEFAULT is used."), wrapAuthHelp(`${cli} profile create <name> replaces an existing profile of that name and tries to revoke the credential it held. An imported key with no recorded id stays live. Pick a new name to keep the old profile.`), wrapAuthHelp(`See ${cli} profile --help and ${cli} profile create --help.`));
|
|
55
55
|
};
|
|
56
56
|
const builder = (yargs) => yargs.option("context-file", { hidden: true }).option("keyring", {
|
|
57
|
-
describe: "Store the credential in the OS keyring. Per profile; later
|
|
57
|
+
describe: "Store the credential in the OS keyring. Per profile; a later login without the flag stays there. See `neon profile list`.",
|
|
58
58
|
type: "boolean"
|
|
59
|
-
}).example("$0
|
|
59
|
+
}).example("$0 login", "Sign in with a browser").example("$0 login --profile work", "Save a browser session in profile work").example("$0 projects list --api-key \"$KEY\"", "Use an existing API key for this command").example("NEON_API_KEY=\"$KEY\" $0 projects list", "Use an existing API key from the environment").example("$0 profile create agent --api-key \"$KEY\"", "Store an existing API key").example("echo \"$KEY\" | $0 profile create agent --api-key -", "Store a key read from stdin").example("$0 profile create ci --mint", "Sign in once in a browser and store a new API key").epilogue(authHelpEpilogue());
|
|
60
60
|
const handler = async (args) => {
|
|
61
61
|
await authFlow(args);
|
|
62
62
|
};
|
|
@@ -160,7 +160,7 @@ const fetchIdentity = async (apiClient) => {
|
|
|
160
160
|
...email ? { email } : {}
|
|
161
161
|
};
|
|
162
162
|
} catch (err) {
|
|
163
|
-
if (isNeonApiError(err) && err.status === 401) throw new Error("Signed in, but the Neon API rejected the new access token. Try `neon
|
|
163
|
+
if (isNeonApiError(err) && err.status === 401) throw new Error("Signed in, but the Neon API rejected the new access token. Try `neon login` again.");
|
|
164
164
|
log.warning("Signed in, but could not look up the account: %s", err instanceof Error ? err.message : String(err));
|
|
165
165
|
return {};
|
|
166
166
|
}
|
|
@@ -317,7 +317,7 @@ const ensureAuth = async (props) => {
|
|
|
317
317
|
const isLocalDev = props._[0] === "dev";
|
|
318
318
|
const isBootstrap = props._[0] === "bootstrap";
|
|
319
319
|
const isMcp = isMcpCommand(props);
|
|
320
|
-
if (props._[0] === "auth") {
|
|
320
|
+
if (props._[0] === "login" || props._[0] === "auth") {
|
|
321
321
|
props.apiClient = getApiClient({
|
|
322
322
|
apiKey: props.apiKey,
|
|
323
323
|
apiHost: props.apiHost
|
|
@@ -337,7 +337,7 @@ const ensureAuth = async (props) => {
|
|
|
337
337
|
try {
|
|
338
338
|
token = await client.exchange(stored.identityAssertion);
|
|
339
339
|
} catch (error) {
|
|
340
|
-
if (error instanceof ClaimableServiceError && error.code === "project_claimed") throw new Error("This project was claimed. Run `neon claim status` to drop the local assertion, then `neon
|
|
340
|
+
if (error instanceof ClaimableServiceError && error.code === "project_claimed") throw new Error("This project was claimed. Run `neon claim status` to drop the local assertion, then `neon login` or `neon link`.");
|
|
341
341
|
throw error;
|
|
342
342
|
}
|
|
343
343
|
props.apiKey = token.accessToken;
|
|
@@ -449,6 +449,12 @@ const ensureAuth = async (props) => {
|
|
|
449
449
|
log.debug("mcp: no usable credentials; minting requires auth or --oauth");
|
|
450
450
|
return;
|
|
451
451
|
}
|
|
452
|
+
if (props._[0] === "me") {
|
|
453
|
+
const state = loaded === null ? "has no stored credential" : "holds a session that has expired";
|
|
454
|
+
process.stderr.write(`Not signed in: profile "${selection.profile}" ${state}. Run \`${getCliName()} login --profile ${selection.profile}\` to sign in, or use an API key with --api-key or NEON_API_KEY.\n`);
|
|
455
|
+
process.exitCode = 1;
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
452
458
|
const apiKey = await authFlow({
|
|
453
459
|
...props,
|
|
454
460
|
profile: selection.profile
|
|
@@ -3,6 +3,7 @@ import { isCi } from "../env.js";
|
|
|
3
3
|
import { log } from "../log.js";
|
|
4
4
|
import { isNeonApiError } from "../api.js";
|
|
5
5
|
import { applyContext, contextBranch, readContextFile } from "../context.js";
|
|
6
|
+
import { isClaimableEnvTarget } from "../claimable/state.js";
|
|
6
7
|
import { getCliName } from "../utils/cli_name.js";
|
|
7
8
|
import { loadEnvFileIntoProcess } from "../env_file.js";
|
|
8
9
|
import { createBranch, pickBranchInteractively } from "../utils/branch_picker.js";
|
|
@@ -91,13 +92,19 @@ const handler = async (props) => {
|
|
|
91
92
|
props.id = renamed;
|
|
92
93
|
}
|
|
93
94
|
}
|
|
95
|
+
const orgRead = isClaimableEnvTarget({
|
|
96
|
+
apiHost: props.apiHost,
|
|
97
|
+
contextFile: props.contextFile,
|
|
98
|
+
configDir: props.configDir ?? ""
|
|
99
|
+
}) ? void 0 : resolveOrgId(props, projectId);
|
|
100
|
+
orgRead?.catch(() => void 0);
|
|
94
101
|
const { branchId, branchName, created, policyApplied, policyFailure } = await resolveBranchId(props, projectId, {
|
|
95
102
|
hooks,
|
|
96
103
|
git,
|
|
97
104
|
event,
|
|
98
105
|
cwd
|
|
99
106
|
});
|
|
100
|
-
const orgId = await resolveOrgId(props, projectId);
|
|
107
|
+
const orgId = await (orgRead ?? resolveOrgId(props, projectId));
|
|
101
108
|
applyContext(props.contextFile, {
|
|
102
109
|
projectId,
|
|
103
110
|
...orgId ? { orgId } : {},
|
|
@@ -119,6 +126,10 @@ const handler = async (props) => {
|
|
|
119
126
|
projectId,
|
|
120
127
|
branch: branchId,
|
|
121
128
|
envPull: props.envPull
|
|
129
|
+
}, {
|
|
130
|
+
branchId,
|
|
131
|
+
branchName,
|
|
132
|
+
usedDefault: false
|
|
122
133
|
});
|
|
123
134
|
const needsCreateAfter = created && hooks?.create?.after;
|
|
124
135
|
if (config && (hooks?.checkout?.after || needsCreateAfter)) {
|
package/dist/commands/claim.js
CHANGED
|
@@ -3,7 +3,7 @@ import { isCi } from "../env.js";
|
|
|
3
3
|
import { log } from "../log.js";
|
|
4
4
|
import { getApiClient } from "../api.js";
|
|
5
5
|
import { applyContext, contextBranch, readContextFile } from "../context.js";
|
|
6
|
-
import { t as credentialInputs } from "../_chunks/auth_selection-
|
|
6
|
+
import { t as credentialInputs } from "../_chunks/auth_selection-YX5_KZgD.js";
|
|
7
7
|
import { ClaimableClient, ClaimableServiceError } from "../claimable/api.js";
|
|
8
8
|
import { assertionHasExpired, listClaimableCredentials, readClaimableCredentials, readLinkedClaimableCredentials, removeClaimableCredentials, writeClaimableCredentials } from "../claimable/state.js";
|
|
9
9
|
import { NEON_SERVICES, deprecatedServiceMessage, parseServices, servicesFlagValue, servicesOption } from "../neon_services.js";
|
|
@@ -460,7 +460,7 @@ const finishClaimedContext = (props, projectId, contextMatches) => {
|
|
|
460
460
|
...contextBranch(context) ? { branch: contextBranch(context) } : {}
|
|
461
461
|
});
|
|
462
462
|
}
|
|
463
|
-
log.info("Dropped the local identity assertion. The next command needs `neon
|
|
463
|
+
log.info("Dropped the local identity assertion. The next command needs `neon login` or `neon link`.");
|
|
464
464
|
};
|
|
465
465
|
//#endregion
|
|
466
466
|
export { CLAIM_CREATE_FIELDS, CLAIM_LIST_FIELDS, aliases, builder, claimCreateFields, claimableCapabilities, command, create, describe, handler, claim_exports as t };
|
package/dist/commands/config.js
CHANGED
|
@@ -4,8 +4,8 @@ import { log } from "../log.js";
|
|
|
4
4
|
import { getApiClient } from "../api.js";
|
|
5
5
|
import { contextBranch, ensureDirectoryGitignored, readContextFile } from "../context.js";
|
|
6
6
|
import { getCliName } from "../utils/cli_name.js";
|
|
7
|
-
import { NEON_SERVICE_LABELS, deprecatedServiceMessage,
|
|
8
|
-
import {
|
|
7
|
+
import { NEON_SERVICES, NEON_SERVICE_LABELS, deprecatedServiceMessage, servicesFlagValue, servicesOption } from "../neon_services.js";
|
|
8
|
+
import { FUNCTION_FILENAME, FUNCTION_SLUG, FUNCTION_TEMPLATE, REQUIRED_PACKAGES, parseConfigInitServices, renderFunctionSource, renderNeonConfig, renderNeonConfigFromView } from "../config_template.js";
|
|
9
9
|
import { editNeonConfig } from "../config_edit.js";
|
|
10
10
|
import { toNeonConfigView } from "../config_format.js";
|
|
11
11
|
import { declaredNeonServices } from "../config_services.js";
|
|
@@ -88,6 +88,7 @@ const envFlag = { env: {
|
|
|
88
88
|
/** Apply-only flags, exported so `deploy` can reuse the exact same surface. */
|
|
89
89
|
const applyFlags = {
|
|
90
90
|
"update-existing": {
|
|
91
|
+
alias: ["y", "yes"],
|
|
91
92
|
describe: "Auto-confirm overriding existing remote settings on the branch",
|
|
92
93
|
type: "boolean",
|
|
93
94
|
default: false
|
|
@@ -152,13 +153,7 @@ const missingDependencies = (cwd) => {
|
|
|
152
153
|
* starter policy, which is what `config init` has always written.
|
|
153
154
|
*/
|
|
154
155
|
const resolveServices = async (props) => {
|
|
155
|
-
if (props.services !== void 0) return
|
|
156
|
-
allowed: CONFIG_INIT_SERVICES,
|
|
157
|
-
whyUnavailable: CONFIG_INIT_UNAVAILABLE,
|
|
158
|
-
flag: "--services",
|
|
159
|
-
noneMeans: CONFIG_INIT_NONE_MEANS,
|
|
160
|
-
onDeprecated: (used, canonical) => log.warning(deprecatedServiceMessage(used, canonical))
|
|
161
|
-
});
|
|
156
|
+
if (props.services !== void 0) return parseConfigInitServices(props.services, (used, canonical) => log.warning(deprecatedServiceMessage(used, canonical)));
|
|
162
157
|
if (props.pickServices) return props.pickServices();
|
|
163
158
|
if (isCi() || !process.stdout.isTTY) return [];
|
|
164
159
|
return pickServicesInteractively();
|
|
@@ -475,10 +470,9 @@ const builder = (argv) => argv.usage("$0 config <sub-command> [options]").option
|
|
|
475
470
|
},
|
|
476
471
|
services: servicesOption({
|
|
477
472
|
key: "services",
|
|
478
|
-
allowed:
|
|
479
|
-
noneMeans: CONFIG_INIT_NONE_MEANS,
|
|
473
|
+
allowed: NEON_SERVICES,
|
|
480
474
|
describe: "Services the scaffolded neon.ts declares",
|
|
481
|
-
also: "Omitted: pick interactively on a terminal, starter policy in CI or without a TTY."
|
|
475
|
+
also: "postgres alone writes the starter policy; every branch has Postgres. Omitted: pick interactively on a terminal, starter policy in CI or without a TTY."
|
|
482
476
|
}),
|
|
483
477
|
"from-branch": {
|
|
484
478
|
describe: "Seed neon.ts from a branch's live Neon state instead of asking. Uses the branch pinned in .neon, or --branch <name|id>, or the project's default branch. The only mode of `config init` that calls the Neon API.",
|
package/dist/commands/dev.js
CHANGED
|
@@ -4,11 +4,11 @@ import { isClaimableEnvTarget } from "../claimable/state.js";
|
|
|
4
4
|
import { getCliName } from "../utils/cli_name.js";
|
|
5
5
|
import { readEnvFile, resolveEnvFilePath } from "../env_file.js";
|
|
6
6
|
import { l as functionBaseUrlKey } from "../_chunks/env-HYNFtxu5.js";
|
|
7
|
-
import { branchIdResolve } from "../utils/enrichers.js";
|
|
8
|
-
import { bundleEntry } from "../utils/esbuild.js";
|
|
9
7
|
import { a as resolveDevEnv } from "../_chunks/env-BWqJqBDJ.js";
|
|
10
8
|
import { findConfigFunctionBySource, resolveFunctionsFromConfig } from "../dev/functions.js";
|
|
11
9
|
import { resolveWatchInputs } from "../dev/inputs.js";
|
|
10
|
+
import { branchIdResolve } from "../utils/enrichers.js";
|
|
11
|
+
import { bundleEntry } from "../utils/esbuild.js";
|
|
12
12
|
import { existsSync, mkdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
13
13
|
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
14
14
|
import { fileURLToPath } from "node:url";
|
package/dist/commands/env.js
CHANGED
|
@@ -7,10 +7,10 @@ import { deprecatedServiceMessage, parseServices, servicesFlagValue, servicesOpt
|
|
|
7
7
|
import { mergeEnvFile, readEnvFile, resolveEnvFilePath } from "../env_file.js";
|
|
8
8
|
import { t as NEON_ENV_VAR_KEYS, u as isFunctionBaseUrlKey } from "../_chunks/env-HYNFtxu5.js";
|
|
9
9
|
import { ENV_PULL_KEY_HELP, ENV_PULL_SERVICES, envKeysForSelection, envPullFlagValue, ownedEnvServiceKeys, parseEnvPullKeys } from "../env_services.js";
|
|
10
|
+
import { i as dropClaimableUnsupported, o as resolveNeonEnvVars } from "../_chunks/env-BWqJqBDJ.js";
|
|
10
11
|
import { fillSingleProject, resolveBranchRef } from "../utils/enrichers.js";
|
|
11
12
|
import { warnAiGateway } from "../utils/ai_gateway_notice.js";
|
|
12
13
|
import { announceTargetBranch } from "../utils/branch_notice.js";
|
|
13
|
-
import { i as dropClaimableUnsupported, o as resolveNeonEnvVars } from "../_chunks/env-BWqJqBDJ.js";
|
|
14
14
|
import { formatPulledEnv } from "./env_output.js";
|
|
15
15
|
import { existsSync } from "node:fs";
|
|
16
16
|
import chalk from "chalk";
|
package/dist/commands/init.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { t as __exportAll } from "../_chunks/rolldown-runtime-8H4AJuhK.js";
|
|
2
2
|
import { getCliName } from "../utils/cli_name.js";
|
|
3
3
|
import { helpCsv, helpEpilogue } from "../utils/help_text.js";
|
|
4
|
-
import { servicesOption } from "../neon_services.js";
|
|
5
|
-
import { CONFIG_INIT_NONE_MEANS, CONFIG_INIT_SERVICES } from "../config_template.js";
|
|
4
|
+
import { NEON_SERVICES, servicesOption } from "../neon_services.js";
|
|
6
5
|
import { coerceAgentFlag } from "../utils/agent_flag.js";
|
|
7
6
|
import { initPluginAgents, initSkillsMcpAgents } from "../init/plan.js";
|
|
8
7
|
import { listSkillIds } from "../skills/catalog.js";
|
|
@@ -52,10 +51,9 @@ const builder = (yargs) => yargs.usage("$0 init [options]").option("context-file
|
|
|
52
51
|
describe: "Create neon.ts after linking. Use --no-config to skip. Omitted in Custom: you will be asked"
|
|
53
52
|
}).option("services", servicesOption({
|
|
54
53
|
key: "services",
|
|
55
|
-
allowed:
|
|
54
|
+
allowed: NEON_SERVICES,
|
|
56
55
|
describe: "Services to declare in neon.ts",
|
|
57
|
-
|
|
58
|
-
also: "Implies creating neon.ts. Cannot be combined with --no-config."
|
|
56
|
+
also: "postgres alone writes the starter policy; every branch has Postgres. Implies creating neon.ts. Cannot be combined with --no-config."
|
|
59
57
|
})).option("org-id", {
|
|
60
58
|
describe: "Forwarded to link: organization ID to link to",
|
|
61
59
|
type: "string"
|
|
@@ -11,8 +11,8 @@ import { Parser } from "yargs/helpers";
|
|
|
11
11
|
*/
|
|
12
12
|
const commandManifest = [
|
|
13
13
|
{
|
|
14
|
-
command: "
|
|
15
|
-
aliases: ["
|
|
14
|
+
command: "login",
|
|
15
|
+
aliases: ["auth"],
|
|
16
16
|
describe: "Sign in with a browser. See --help for API keys and profiles",
|
|
17
17
|
load: () => import("./auth.js")
|
|
18
18
|
},
|
package/dist/commands/mcp.js
CHANGED
|
@@ -139,7 +139,7 @@ const setupNeonMcp = async (options) => {
|
|
|
139
139
|
cwd
|
|
140
140
|
}) : void 0;
|
|
141
141
|
if (plan.auth === "api-key" && !existing) {
|
|
142
|
-
if (!options.apiClient || !options.apiKey) throw new Error(`Authentication required. Run \`${getCliName()}
|
|
142
|
+
if (!options.apiClient || !options.apiKey) throw new Error(`Authentication required. Run \`${getCliName()} login\`, pass --api-key or use --oauth to install without a Neon credential.`);
|
|
143
143
|
if (!canPickAgentsInteractively() && options.yes !== true && (options.agent ?? []).length === 0) throw new Error("No interactive terminal. Pass -y to mint into every detected agent, --agent <name> to name them or --oauth to install without minting.");
|
|
144
144
|
}
|
|
145
145
|
let auth;
|
package/dist/commands/profile.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { t as __exportAll } from "../_chunks/rolldown-runtime-8H4AJuhK.js";
|
|
2
2
|
import { t as writeSecretFile } from "../_chunks/secure_file-BucZj4yQ.js";
|
|
3
|
-
import { c as describeScope, d as scopeOf, l as interpretCredentials, n as KEYRING_SERVICE, o as apiKeyCredentials, r as keyringAccount, s as credentialLabel, t as storeFor } from "../_chunks/credential_io-
|
|
3
|
+
import { c as describeScope, d as scopeOf, l as interpretCredentials, n as KEYRING_SERVICE, o as apiKeyCredentials, r as keyringAccount, s as credentialLabel, t as storeFor } from "../_chunks/credential_io-ByNuojoE.js";
|
|
4
4
|
import { isCi } from "../env.js";
|
|
5
5
|
import { log } from "../log.js";
|
|
6
6
|
import { getApiClient, isNeonApiError } from "../api.js";
|
|
7
7
|
import { setAuthContext } from "../auth_context.js";
|
|
8
8
|
import { a as isOwnedCredentialPath, n as credentialsPath } from "../_chunks/paths-DMq0Lt7a.js";
|
|
9
|
-
import { _ as upsertProfile, a as canDropProfilesFile, c as listProfiles, d as newProfileLocation, f as profilesFilePath, g as selectProfileName, h as resolveProfile, i as assertValidProfileName, l as locationForName, m as readProfiles, n as KEYRING_CREDENTIALS, o as credentialsDisplay, p as profilesUsingPath, r as assertProfilesUsable, s as isKeyringPointer, u as locationOf, v as CRED_STORAGE_FILE, y as CRED_STORAGE_KEYRING } from "../_chunks/profiles-
|
|
9
|
+
import { _ as upsertProfile, a as canDropProfilesFile, c as listProfiles, d as newProfileLocation, f as profilesFilePath, g as selectProfileName, h as resolveProfile, i as assertValidProfileName, l as locationForName, m as readProfiles, n as KEYRING_CREDENTIALS, o as credentialsDisplay, p as profilesUsingPath, r as assertProfilesUsable, s as isKeyringPointer, u as locationOf, v as CRED_STORAGE_FILE, y as CRED_STORAGE_KEYRING } from "../_chunks/profiles-DIB1av2Q.js";
|
|
10
10
|
import { auth, revokeToken } from "../auth.js";
|
|
11
|
-
import { t as credentialInputs } from "../_chunks/auth_selection-
|
|
11
|
+
import { t as credentialInputs } from "../_chunks/auth_selection-YX5_KZgD.js";
|
|
12
12
|
import { readOutgoingCredential, retirePreviousCredential, revokeTokenSet, withdrawKey } from "../retire_credential.js";
|
|
13
13
|
import { authFlow, usableCredential } from "./auth.js";
|
|
14
14
|
import { identityFromAuthDetails, isApiKeyMethod, mintedKeyName, notAnApiKeyMessage } from "../profile_keys.js";
|
|
@@ -70,7 +70,7 @@ const builder = (argv) => argv.usage("$0 profile <sub-command> [options]").comma
|
|
|
70
70
|
throw new Error(`--force is no longer a flag. \`neon profile create ${name}\` always replaces an existing profile and revokes the credential it held. Drop --force.`);
|
|
71
71
|
}
|
|
72
72
|
return true;
|
|
73
|
-
}).example("$0 profile create work", "Sign in with the browser, like `neon
|
|
73
|
+
}).example("$0 profile create work", "Sign in with the browser, like `neon login --profile work`").example("$0 profile create work --api-key \"$KEY\"", "Store a key you already have").example("echo \"$KEY\" | $0 profile create work --api-key -", "Or pipe it, so it never reaches the process arguments").example("$0 profile create ci --mint --org-id org-abc-123", "One browser sign-in, then an org-scoped key and no session left behind").example("$0 profile create work --keyring", "Store the credential in the OS keyring instead of a file"), async (args) => await create(args)).command("rotate-key <name>", "Mint a fresh API key for a profile, at the same scope, and revoke the one it replaces", (y) => y.positional("name", {
|
|
74
74
|
describe: "Profile to rotate",
|
|
75
75
|
type: "string",
|
|
76
76
|
demandOption: true
|
package/dist/commands/user.js
CHANGED
|
@@ -17,6 +17,7 @@ const handler = async (args) => {
|
|
|
17
17
|
await me(args);
|
|
18
18
|
};
|
|
19
19
|
const me = async (props) => {
|
|
20
|
+
if (!props.apiClient) return;
|
|
20
21
|
const { data } = await props.apiClient.getCurrentUserInfo();
|
|
21
22
|
if (props.output === "json" || props.output === "yaml") {
|
|
22
23
|
writer(props).end(data, { fields: [
|
package/dist/config_template.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NEON_SERVICES } from "./neon_services.js";
|
|
1
|
+
import { NEON_SERVICES, parseServices } from "./neon_services.js";
|
|
2
2
|
//#region src/config_template.ts
|
|
3
3
|
/**
|
|
4
4
|
* The published npm packages a `neon.ts` project needs — the `@neon/*` org names.
|
|
@@ -23,13 +23,15 @@ const REQUIRED_PACKAGES = [CONFIG_PACKAGE, ENV_PACKAGE];
|
|
|
23
23
|
*/
|
|
24
24
|
const CONFIG_INIT_SERVICES = NEON_SERVICES.filter((service) => service !== "postgres");
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
26
|
+
* Parse `--services` on `init` and `config init` into the services to declare. `postgres` is
|
|
27
|
+
* accepted, alone or with others, and declares nothing: `--services postgres` is how a
|
|
28
|
+
* script asks for the Postgres-only starter policy.
|
|
29
29
|
*/
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
const parseConfigInitServices = (raw, onDeprecated) => parseServices(raw, {
|
|
31
|
+
allowed: NEON_SERVICES,
|
|
32
|
+
flag: "--services",
|
|
33
|
+
...onDeprecated ? { onDeprecated } : {}
|
|
34
|
+
}).filter((service) => service !== "postgres");
|
|
33
35
|
/** Slug, display name, and source path of the function scaffolded for `functions`. */
|
|
34
36
|
const FUNCTION_SLUG = "hello";
|
|
35
37
|
const FUNCTION_NAME = "Hello World";
|
|
@@ -200,4 +202,4 @@ const renderFunctionSource = (slug, language) => {
|
|
|
200
202
|
};
|
|
201
203
|
const FUNCTION_TEMPLATE = renderFunctionSource(FUNCTION_SLUG, "ts");
|
|
202
204
|
//#endregion
|
|
203
|
-
export { BUCKET_NAME,
|
|
205
|
+
export { BUCKET_NAME, CONFIG_INIT_SERVICES, CONFIG_PACKAGE, ENV_PACKAGE, FUNCTION_FILENAME, FUNCTION_NAME, FUNCTION_SLUG, FUNCTION_TEMPLATE, REQUIRED_PACKAGES, parseConfigInitServices, renderFunctionSource, renderKey, renderNeonConfig, renderNeonConfigFromView };
|
package/dist/credential_io.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as storeFor } from "./_chunks/credential_io-
|
|
1
|
+
import { t as storeFor } from "./_chunks/credential_io-ByNuojoE.js";
|
|
2
2
|
export { storeFor };
|
package/dist/index.js
CHANGED
|
@@ -154,7 +154,7 @@ async function handleError(msg, err, canRetry) {
|
|
|
154
154
|
log.error(err.message);
|
|
155
155
|
if (err.terminal) {
|
|
156
156
|
const context = getAuthContext();
|
|
157
|
-
log.error(`Run \`neon
|
|
157
|
+
log.error(`Run \`neon login --profile ${context?.profile ?? "DEFAULT"}\` to sign in again.`);
|
|
158
158
|
}
|
|
159
159
|
sendError(err, "AUTH_FAILED");
|
|
160
160
|
return false;
|
package/dist/init/choices.js
CHANGED
|
@@ -10,7 +10,7 @@ const resolveInitConfigChoice = (input) => {
|
|
|
10
10
|
};
|
|
11
11
|
if (input.yes) return {
|
|
12
12
|
kind: "write",
|
|
13
|
-
services: ["
|
|
13
|
+
services: ["postgres"]
|
|
14
14
|
};
|
|
15
15
|
if (input.flag === true) return { kind: "write" };
|
|
16
16
|
if (input.canAsk) return { kind: "ask" };
|
|
@@ -21,10 +21,6 @@ const configPlanFromResolution = (resolution, accepted) => {
|
|
|
21
21
|
if (resolution.kind === "skip") return { kind: "skip" };
|
|
22
22
|
return resolution;
|
|
23
23
|
};
|
|
24
|
-
const isBareInitServices = (services) => {
|
|
25
|
-
if (services === void 0 || services.length === 0) return true;
|
|
26
|
-
return services.every((service) => service === "none");
|
|
27
|
-
};
|
|
28
24
|
const shouldRefreshEnvAfterNewConfig = (input) => input.wroteNewFile && typeof input.projectId === "string" && input.projectId.length > 0 && typeof input.branch === "string" && input.branch.length > 0;
|
|
29
25
|
const shouldPullEnvAfterInitConfig = (input) => !input.extraServices && !input.alreadyPulled && shouldRefreshEnvAfterNewConfig({
|
|
30
26
|
wroteNewFile: input.wroteNewFile,
|
|
@@ -32,4 +28,4 @@ const shouldPullEnvAfterInitConfig = (input) => !input.extraServices && !input.a
|
|
|
32
28
|
...input.branch !== void 0 ? { branch: input.branch } : {}
|
|
33
29
|
});
|
|
34
30
|
//#endregion
|
|
35
|
-
export { INIT_CONFIG_SERVICES_CONFLICT, configPlanFromResolution,
|
|
31
|
+
export { INIT_CONFIG_SERVICES_CONFLICT, configPlanFromResolution, resolveInitConfigChoice, shouldPullEnvAfterInitConfig, shouldRefreshEnvAfterNewConfig };
|
package/dist/init/copy.js
CHANGED
|
@@ -49,8 +49,8 @@ const SERVICES_MESSAGE = "Which services should neon.ts declare? (space to toggl
|
|
|
49
49
|
const PACKAGE_MANAGER_MESSAGE = "Which package manager should install the Neon dependencies?";
|
|
50
50
|
const NO_AGENTS_FALLBACK_STATUS = "No coding agents detected. Installing the default Neon skills for Cursor and Codex in this directory.";
|
|
51
51
|
const NO_AGENT_SETUP_CONFLICT = "--no-agent-setup cannot be combined with --agent, --skill, or MCP flags.";
|
|
52
|
-
const NON_TTY_LINK_NEEDS_AUTH = "No interactive terminal. Sign in with `neon
|
|
53
|
-
const YES_LINK_NEEDS_AUTH = "-y cannot sign in. Sign in with `neon
|
|
52
|
+
const NON_TTY_LINK_NEEDS_AUTH = "No interactive terminal. Sign in with `neon login`, then re-run, or pass --claimable.";
|
|
53
|
+
const YES_LINK_NEEDS_AUTH = "-y cannot sign in. Sign in with `neon login`, then re-run, or pass --claimable.";
|
|
54
54
|
const MCP_SCOPED_NEEDS_PROJECT = "--mcp-project-scoped requires a linked project. Link a project first, or omit --mcp-project-scoped.";
|
|
55
55
|
const namedAgentsUnavailable = (ids) => `--agent ${ids.join(", ")} cannot install this tooling. Pass agents that support it, or omit --agent.`;
|
|
56
56
|
const mcpConfigLocationUnavailable = (ids, location) => location === "project" ? `--agent ${ids.join(", ")} cannot install project-level MCP config. Use --mcp-config-location global, or choose an agent that supports project config.` : `--agent ${ids.join(", ")} cannot install global MCP config. Choose an agent that supports global config.`;
|
|
@@ -80,7 +80,7 @@ const PROGRESS = {
|
|
|
80
80
|
const unattendedUnauthedNext = () => [
|
|
81
81
|
"Link a project with a Neon account and an authenticated CLI.",
|
|
82
82
|
"Sign up: https://neon.com/signup",
|
|
83
|
-
`${getCliName()}
|
|
83
|
+
`${getCliName()} login`,
|
|
84
84
|
`${getCliName()} link`,
|
|
85
85
|
"",
|
|
86
86
|
"Or create a claimable project without an account. It expires in 72 hours unless claimed.",
|
package/dist/init/detect.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { t as storeFor } from "../_chunks/credential_io-
|
|
1
|
+
import { t as storeFor } from "../_chunks/credential_io-ByNuojoE.js";
|
|
2
2
|
import { isCi } from "../env.js";
|
|
3
|
-
import { h as resolveProfile, u as locationOf } from "../_chunks/profiles-
|
|
4
|
-
import { i as selectCredential, t as credentialInputs } from "../_chunks/auth_selection-
|
|
3
|
+
import { h as resolveProfile, u as locationOf } from "../_chunks/profiles-DIB1av2Q.js";
|
|
4
|
+
import { i as selectCredential, t as credentialInputs } from "../_chunks/auth_selection-YX5_KZgD.js";
|
|
5
5
|
import { detectInstalledAgents, uniqueAgentIds } from "../mcp/agents.js";
|
|
6
6
|
import "./agents.js";
|
|
7
7
|
import { directoryIsEmpty } from "./plan.js";
|
package/dist/init/plan.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { getCliName } from "../utils/cli_name.js";
|
|
2
|
-
import { NO_SERVICES } from "../neon_services.js";
|
|
3
2
|
import { tryResolveAddMcpAgentId, uniqueAgentIds } from "../mcp/agents.js";
|
|
4
3
|
import { mcpInstallableAgents } from "../mcp/targets.js";
|
|
5
4
|
import { supportsSkills } from "./agents.js";
|
|
@@ -363,13 +362,13 @@ const planConfigInitStep = (input) => {
|
|
|
363
362
|
"config",
|
|
364
363
|
"init",
|
|
365
364
|
"--services",
|
|
366
|
-
input.services.length === 0 ?
|
|
365
|
+
input.services.length === 0 ? "postgres" : input.services.join(",")
|
|
367
366
|
];
|
|
368
367
|
if (input.yes) return [
|
|
369
368
|
"config",
|
|
370
369
|
"init",
|
|
371
370
|
"--services",
|
|
372
|
-
|
|
371
|
+
"postgres"
|
|
373
372
|
];
|
|
374
373
|
return ["config", "init"];
|
|
375
374
|
};
|
package/dist/init/run.js
CHANGED
|
@@ -6,8 +6,8 @@ import { recordCommandSuccessExtras, takeCommandSuccessExtras } from "../analyti
|
|
|
6
6
|
import "../claimable/api.js";
|
|
7
7
|
import { readLinkedClaimableCredentials } from "../claimable/state.js";
|
|
8
8
|
import { getCliName } from "../utils/cli_name.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { servicesFlagValue } from "../neon_services.js";
|
|
10
|
+
import { CONFIG_INIT_SERVICES, parseConfigInitServices } from "../config_template.js";
|
|
11
11
|
import { hasNeonConfigFile, neonConfigFilename } from "../project.js";
|
|
12
12
|
import { getAgentDisplayName } from "../mcp/agents.js";
|
|
13
13
|
import { mcpInstallableAgents } from "../mcp/targets.js";
|
|
@@ -24,7 +24,7 @@ import { InitCancelled, raceSigint, restoreCursor } from "./cancelled.js";
|
|
|
24
24
|
import { pickAgentSetupInteractively, pickInitAgentsInteractively, pickInitConfigInteractively, pickInitMcpAuthInteractively, pickInitMcpConfigLocationInteractively, pickInitModeInteractively, pickInitPackageManagerInteractively, pickInitProjectSetupInteractively, pickInitServicesInteractively, pickInitSkillsInteractively } from "./wizard.js";
|
|
25
25
|
import { runToolingSteps } from "./tooling.js";
|
|
26
26
|
import { create } from "../commands/claim.js";
|
|
27
|
-
import { INIT_CONFIG_SERVICES_CONFLICT, configPlanFromResolution,
|
|
27
|
+
import { INIT_CONFIG_SERVICES_CONFLICT, configPlanFromResolution, resolveInitConfigChoice, shouldPullEnvAfterInitConfig } from "./choices.js";
|
|
28
28
|
import { detectInitEnvironment } from "./detect.js";
|
|
29
29
|
import { createInitFunnel, emitInitStart, finishInitFunnel, initStartProperties } from "./funnel.js";
|
|
30
30
|
import { assertAgentSetupFlags, hasInitMcpFlags, inferInitAgentSetup, resolveInitMode } from "./mode.js";
|
|
@@ -34,17 +34,6 @@ const isLinked = (contextFile) => {
|
|
|
34
34
|
const projectId = readContextFile(contextFile).projectId;
|
|
35
35
|
return typeof projectId === "string" && projectId.length > 0;
|
|
36
36
|
};
|
|
37
|
-
const parsedInitServices = (raw) => {
|
|
38
|
-
const values = servicesFlagValue(raw);
|
|
39
|
-
if (values === void 0) return;
|
|
40
|
-
return parseServices(values, {
|
|
41
|
-
allowed: CONFIG_INIT_SERVICES,
|
|
42
|
-
whyUnavailable: CONFIG_INIT_UNAVAILABLE,
|
|
43
|
-
flag: "--services",
|
|
44
|
-
noneMeans: CONFIG_INIT_NONE_MEANS,
|
|
45
|
-
onDeprecated: (used, canonical) => log.warning(deprecatedServiceMessage(used, canonical))
|
|
46
|
-
});
|
|
47
|
-
};
|
|
48
37
|
const expandTelemetryServices = (services) => {
|
|
49
38
|
if (services.includes("data-api") && !services.includes("auth")) return CONFIG_INIT_SERVICES.filter((service) => service === "auth" || services.includes(service));
|
|
50
39
|
return [...services];
|
|
@@ -172,8 +161,9 @@ const runInit = async (props) => {
|
|
|
172
161
|
...props.forceAuth !== void 0 ? { forceAuth: props.forceAuth } : {},
|
|
173
162
|
...props.allowUnsafeTls !== void 0 ? { allowUnsafeTls: props.allowUnsafeTls } : {}
|
|
174
163
|
};
|
|
175
|
-
const servicesFlag =
|
|
164
|
+
const servicesFlag = servicesFlagValue(props.services);
|
|
176
165
|
if (props.config === false && servicesFlag !== void 0) throw new Error(INIT_CONFIG_SERVICES_CONFLICT);
|
|
166
|
+
if (servicesFlag !== void 0) parseConfigInitServices(servicesFlag);
|
|
177
167
|
const linkInputs = {
|
|
178
168
|
...props.orgId ? { orgId: props.orgId } : {},
|
|
179
169
|
...props.projectId ? { projectId: props.projectId } : {},
|
|
@@ -459,25 +449,22 @@ const runInit = async (props) => {
|
|
|
459
449
|
const picked = await (props.pickServices ?? pickInitServicesInteractively)();
|
|
460
450
|
configPlan = {
|
|
461
451
|
kind: "write",
|
|
462
|
-
services: picked.length === 0 ? ["
|
|
452
|
+
services: picked.length === 0 ? ["postgres"] : picked
|
|
463
453
|
};
|
|
464
454
|
}
|
|
465
455
|
if (recommended && configPlan.kind === "write" && !existingConfig) configPlan = {
|
|
466
456
|
kind: "write",
|
|
467
|
-
services: servicesFlag ?? ["
|
|
457
|
+
services: servicesFlag ?? ["postgres"]
|
|
468
458
|
};
|
|
469
459
|
let wroteNewFile = false;
|
|
470
460
|
let extraServices = false;
|
|
471
461
|
let selectedServices = null;
|
|
472
462
|
if (configPlan.kind === "write") {
|
|
473
|
-
const planned = existingConfig ? void 0 : configPlan.services ?? ["
|
|
463
|
+
const planned = existingConfig ? void 0 : configPlan.services ?? ["postgres"];
|
|
474
464
|
if (planned !== void 0) {
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
flag: "--services",
|
|
479
|
-
noneMeans: CONFIG_INIT_NONE_MEANS
|
|
480
|
-
})) : [];
|
|
465
|
+
const declared = parseConfigInitServices(planned);
|
|
466
|
+
extraServices = declared.length > 0;
|
|
467
|
+
selectedServices = expandTelemetryServices(declared);
|
|
481
468
|
funnel.services = selectedServices;
|
|
482
469
|
wroteNewFile = true;
|
|
483
470
|
} else selectedServices = null;
|
package/dist/mcp/mint.js
CHANGED
|
@@ -4,7 +4,7 @@ import { getCliName } from "../utils/cli_name.js";
|
|
|
4
4
|
import { mintedKeyName } from "../profile_keys.js";
|
|
5
5
|
import { orgIdForProject } from "../commands/api_keys.js";
|
|
6
6
|
//#region src/mcp/mint.ts
|
|
7
|
-
const cannotMintMessage = "This CLI credential cannot mint API keys. Organization and project-scoped keys cannot create other keys. Sign in with `neon
|
|
7
|
+
const cannotMintMessage = "This CLI credential cannot mint API keys. Organization and project-scoped keys cannot create other keys. Sign in with `neon login` or pass a personal API key.";
|
|
8
8
|
function mintedKeyRevokeCommand(key) {
|
|
9
9
|
return key.orgId ? `${getCliName()} api-keys revoke ${key.id} --org-id ${key.orgId}` : `${getCliName()} api-keys revoke ${key.id}`;
|
|
10
10
|
}
|
package/dist/neon_services.js
CHANGED
|
@@ -40,8 +40,6 @@ const NEON_SERVICE_LABELS = {
|
|
|
40
40
|
* vocabulary, and absent from help text, errors, and docs so nobody learns it fresh.
|
|
41
41
|
*/
|
|
42
42
|
const DEPRECATED_SERVICE_ALIASES = { storage: "object-storage" };
|
|
43
|
-
/** An explicit empty selection, for commands where "declare nothing" is a real answer. */
|
|
44
|
-
const NO_SERVICES = "none";
|
|
45
43
|
/**
|
|
46
44
|
* What to tell someone still using a retired spelling. A message rather than a log call, so
|
|
47
45
|
* the parser stays free of the CLI's writer and each command can surface it in its own voice.
|
|
@@ -57,18 +55,14 @@ const deprecatedServiceMessage = (used, canonical) => `"${used}" is the old name
|
|
|
57
55
|
*
|
|
58
56
|
* An unrecognized name is rejected rather than dropped: a typo would otherwise act on
|
|
59
57
|
* everything *except* the service that was asked for, and report success. A name that is a
|
|
60
|
-
* real service but not one this command supports says so
|
|
61
|
-
*
|
|
58
|
+
* real service but not one this command supports says so, since that is a different problem
|
|
59
|
+
* from a typo.
|
|
62
60
|
*/
|
|
63
61
|
const parseServices = (raw, options) => {
|
|
64
|
-
const { allowed, flag,
|
|
65
|
-
const supported = `Supported values: ${allowed.join(", ")}
|
|
62
|
+
const { allowed, flag, onDeprecated } = options;
|
|
63
|
+
const supported = `Supported values: ${allowed.join(", ")}.`;
|
|
66
64
|
const names = raw.flatMap((value) => value.split(",")).map((name) => name.trim()).filter((name) => name !== "");
|
|
67
65
|
if (names.length === 0) throw new Error(`${flag} needs at least one service. ${supported}`);
|
|
68
|
-
if (noneMeans !== void 0 && names.includes("none")) {
|
|
69
|
-
if (new Set(names).size > 1) throw new Error(`${flag} ${NO_SERVICES} cannot be combined with other services.`);
|
|
70
|
-
return [];
|
|
71
|
-
}
|
|
72
66
|
const deprecated = /* @__PURE__ */ new Map();
|
|
73
67
|
const resolved = names.map((name) => {
|
|
74
68
|
const canonical = DEPRECATED_SERVICE_ALIASES[name];
|
|
@@ -77,23 +71,19 @@ const parseServices = (raw, options) => {
|
|
|
77
71
|
return canonical;
|
|
78
72
|
});
|
|
79
73
|
const unsupported = resolved.filter((name) => !allowed.some((service) => service === name));
|
|
80
|
-
if (unsupported.length > 0) throw new Error(`${unsupportedMessage(unsupported, flag
|
|
74
|
+
if (unsupported.length > 0) throw new Error(`${unsupportedMessage(unsupported, flag)} ${supported}`);
|
|
81
75
|
for (const [used, canonical] of deprecated) onDeprecated?.(used, canonical);
|
|
82
76
|
return NEON_SERVICES.filter((service) => allowed.includes(service) && resolved.includes(service));
|
|
83
77
|
};
|
|
84
78
|
/**
|
|
85
79
|
* The sentences explaining why a selection was refused. A real Neon service this command
|
|
86
80
|
* cannot act on is a different mistake from a typo — different cause, different fix — so the
|
|
87
|
-
* two are never answered with the same word
|
|
88
|
-
* command supplied one.
|
|
81
|
+
* two are never answered with the same word.
|
|
89
82
|
*/
|
|
90
|
-
const unsupportedMessage = (unsupported, flag
|
|
83
|
+
const unsupportedMessage = (unsupported, flag) => {
|
|
91
84
|
const known = unsupported.filter((name) => NEON_SERVICES.some((service) => service === name));
|
|
92
85
|
const unknown = unsupported.filter((name) => !known.some((service) => service === name));
|
|
93
|
-
return [unknown.length > 0 ? `Unknown service${unknown.length === 1 ? "" : "s"} ${unknown.join(", ")}.` : void 0, ...known.map((service) => {
|
|
94
|
-
const why = whyUnavailable[service];
|
|
95
|
-
return `${service} is not something ${flag} can select${why ? `: ${why}` : ""}.`;
|
|
96
|
-
})].filter((part) => part !== void 0).join(" ");
|
|
86
|
+
return [unknown.length > 0 ? `Unknown service${unknown.length === 1 ? "" : "s"} ${unknown.join(", ")}.` : void 0, ...known.map((service) => `${service} is not something ${flag} can select.`)].filter((part) => part !== void 0).join(" ");
|
|
97
87
|
};
|
|
98
88
|
/** Every spelling of the services flag, so a habit picked up on one command works on another. */
|
|
99
89
|
const SERVICE_FLAG_NAMES = [
|
|
@@ -110,7 +100,6 @@ const servicesOption = (params) => ({
|
|
|
110
100
|
alias: SERVICE_FLAG_NAMES.filter((name) => name !== params.key),
|
|
111
101
|
describe: [
|
|
112
102
|
`${params.describe}: ${params.allowed.join(", ")}.`,
|
|
113
|
-
params.noneMeans !== void 0 ? `Pass "${NO_SERVICES}" for ${params.noneMeans}.` : void 0,
|
|
114
103
|
"Repeat the flag or comma-separate.",
|
|
115
104
|
params.also
|
|
116
105
|
].filter((part) => part !== void 0).join(" "),
|
|
@@ -124,4 +113,4 @@ const servicesOption = (params) => ({
|
|
|
124
113
|
*/
|
|
125
114
|
const servicesFlagValue = (value) => Array.isArray(value) ? value.map(String) : void 0;
|
|
126
115
|
//#endregion
|
|
127
|
-
export { NEON_SERVICES, NEON_SERVICE_LABELS,
|
|
116
|
+
export { NEON_SERVICES, NEON_SERVICE_LABELS, deprecatedServiceMessage, parseServices, servicesFlagValue, servicesOption };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as OAUTH, d as scopeOf, i as API_KEY, l as interpretCredentials, t as storeFor, u as isSameCredential } from "./_chunks/credential_io-
|
|
1
|
+
import { a as OAUTH, d as scopeOf, i as API_KEY, l as interpretCredentials, t as storeFor, u as isSameCredential } from "./_chunks/credential_io-ByNuojoE.js";
|
|
2
2
|
import { log } from "./log.js";
|
|
3
3
|
import { getApiClient } from "./api.js";
|
|
4
4
|
import { revokeToken } from "./auth.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as recordCredentialInputs } from "../_chunks/auth_selection-
|
|
1
|
+
import { r as recordCredentialInputs } from "../_chunks/auth_selection-YX5_KZgD.js";
|
|
2
2
|
//#region src/utils/middlewares.ts
|
|
3
3
|
/**
|
|
4
4
|
* Forwarding Yargs's default would turn ambient configuration into an explicit child override.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neon",
|
|
3
|
-
"version": "8.0
|
|
3
|
+
"version": "8.1.0",
|
|
4
4
|
"description": "CLI tool for Neon, the cloud backend primitives built around Lakebase Postgres",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"neon",
|
|
@@ -64,9 +64,9 @@
|
|
|
64
64
|
"yaml": "^2.9.0",
|
|
65
65
|
"yargs": "17.7.2",
|
|
66
66
|
"yoctocolors": "^2.1.2",
|
|
67
|
-
"@neon/config": "1.8.
|
|
68
|
-
"@neon/
|
|
69
|
-
"@neon/
|
|
67
|
+
"@neon/config": "1.8.5",
|
|
68
|
+
"@neon/config-runtime": "1.7.7",
|
|
69
|
+
"@neon/sdk": "7.0.1"
|
|
70
70
|
},
|
|
71
71
|
"optionalDependencies": {
|
|
72
72
|
"@napi-rs/keyring": "1.3.0",
|
|
@@ -100,9 +100,9 @@
|
|
|
100
100
|
"typescript": "^5.9.0",
|
|
101
101
|
"vitest": "^3.0.9",
|
|
102
102
|
"@neon-internals/cli-core": "0.0.0",
|
|
103
|
-
"@neon-internals/env-core": "0.0.27",
|
|
104
103
|
"@neon/e2e-harness": "0.0.0",
|
|
105
|
-
"@neon/functions": "0.11.0"
|
|
104
|
+
"@neon/functions": "0.11.0",
|
|
105
|
+
"@neon-internals/env-core": "0.0.28"
|
|
106
106
|
},
|
|
107
107
|
"publishConfig": {
|
|
108
108
|
"access": "public",
|