neon 3.1.0 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -5
- package/dist/{_shared/auth_selection.js → _chunks/auth_selection-DGgq6ifc.js} +3 -3
- package/dist/_chunks/cmd_pipeline-CUbBO9U_.js +2818 -0
- package/dist/{_shared/credentials.js → _chunks/credentials-MYdHdKah.js} +3 -3
- package/dist/_chunks/env-NbA61JR3.js +585 -0
- package/dist/{_shared/env-core/env.js → _chunks/env_services-Tz9G4JeT.js} +179 -43
- package/dist/{_shared/paths.js → _chunks/paths-DMq0Lt7a.js} +2 -2
- package/dist/{_shared/profiles.js → _chunks/profiles-Ir29rqns.js} +4 -13
- package/dist/_chunks/psql-DWH-kc69.js +2169 -0
- package/dist/{_virtual/_rolldown/runtime.js → _chunks/rolldown-runtime-D7D4PA-g.js} +1 -1
- package/dist/{_shared/secure_file.js → _chunks/secure_file-BucZj4yQ.js} +2 -4
- package/dist/analytics.js +2 -2
- package/dist/auth_context.js +1 -1
- package/dist/commands/api.js +2 -2
- package/dist/commands/api_keys.js +2 -2
- package/dist/commands/auth.js +6 -6
- package/dist/commands/bootstrap.js +3 -3
- package/dist/commands/branches.js +2 -2
- package/dist/commands/bucket.js +2 -2
- package/dist/commands/checkout.js +2 -2
- package/dist/commands/config.js +2 -2
- package/dist/commands/connection_string.js +2 -2
- package/dist/commands/data_api.js +2 -2
- package/dist/commands/databases.js +2 -2
- package/dist/commands/deploy.js +2 -2
- package/dist/commands/dev.js +3 -3
- package/dist/commands/diff.js +2 -2
- package/dist/commands/env.js +42 -32
- package/dist/commands/functions.js +2 -2
- package/dist/commands/index.js +33 -33
- package/dist/commands/init.js +3 -3
- package/dist/commands/inspect.js +2 -2
- package/dist/commands/ip_allow.js +2 -2
- package/dist/commands/link.js +2 -2
- package/dist/commands/logs.js +2 -2
- package/dist/commands/neon_auth.js +2 -2
- package/dist/commands/operations.js +2 -2
- package/dist/commands/orgs.js +2 -2
- package/dist/commands/profile.js +7 -7
- package/dist/commands/projects.js +2 -2
- package/dist/commands/psql.js +2 -2
- package/dist/commands/roles.js +2 -2
- package/dist/commands/set_context.js +2 -2
- package/dist/commands/snapshots.js +2 -2
- package/dist/commands/status.js +2 -2
- package/dist/commands/user.js +2 -2
- package/dist/commands/vpc_endpoints.js +2 -2
- package/dist/config.js +1 -1
- package/dist/dev/env.js +1 -364
- package/dist/env_services.js +2 -49
- package/dist/index.js +1 -1
- package/dist/init/auth.js +4 -4
- package/dist/psql/cli.js +1 -1
- package/dist/psql/command/cmd_copy.js +1 -1
- package/dist/psql/command/cmd_io.js +1 -1403
- package/dist/psql/command/cmd_pipeline.js +1 -595
- package/dist/psql/command/dispatch.js +1 -2
- package/dist/psql/core/common.js +1 -834
- package/dist/psql/core/mainloop.js +1 -2
- package/dist/psql/core/startup.js +1 -656
- package/dist/psql/index.js +1 -1516
- package/dist/psql/io/psqlrc.js +1 -1
- package/dist/psql/types/index.js +6 -0
- package/dist/utils/inspect_db.js +1 -1
- package/dist/utils/middlewares.js +2 -1
- package/package.json +6 -3
- package/dist/_shared/env-core/reuse-secrets.js +0 -179
|
@@ -1,13 +1,13 @@
|
|
|
1
|
+
import { NEON_SERVICES } from "../neon_services.js";
|
|
1
2
|
import { ErrorCode, PlatformError, createNeonApiFromOptions, deriveCredentialScopes, resolveConfig } from "@neon/config/v1";
|
|
2
|
-
//#region
|
|
3
|
+
//#region ../../internals/env-core/dist/env.js
|
|
3
4
|
/**
|
|
4
5
|
* The Neon env core — resolving a branch's env from the Neon API, and projecting it into
|
|
5
6
|
* OS-level `{ KEY: value }` pairs.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* a copy rather than an import.
|
|
8
|
+
* Private, and bundled into both consumers: `@neon/env` publishes it as `fetchEnv` /
|
|
9
|
+
* `toEntries`, and the `neon` CLI needs the credential-reuse half in `reuse-secrets.ts`.
|
|
10
|
+
* See `README.md` for why it is not published.
|
|
11
11
|
*
|
|
12
12
|
* The counterpart that reads `process.env` — `parseEnv` and its zod schemas — is not here. It
|
|
13
13
|
* has no consumer outside `@neon/env`, so it stays in that package and imports this.
|
|
@@ -84,8 +84,10 @@ const NEON_ENV_VAR_KEYS = {
|
|
|
84
84
|
baseUrl: "NEON_AI_GATEWAY_BASE_URL"
|
|
85
85
|
}
|
|
86
86
|
};
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
/** Fail loudly when selected-key dependency planning and execution disagree. */
|
|
88
|
+
function requiredValue(value, description) {
|
|
89
|
+
if (value === null) throw new Error(`fetchEnv: missing ${description}.`);
|
|
90
|
+
return value;
|
|
89
91
|
}
|
|
90
92
|
/**
|
|
91
93
|
* The {@link fetchEnv} body, with the key selection as a plain argument and no generic
|
|
@@ -103,31 +105,38 @@ async function fetchEnvKeys(config, options, keys) {
|
|
|
103
105
|
const selection = keys ? new Set(keys) : null;
|
|
104
106
|
const wants = (key) => selection === null || selection.has(key);
|
|
105
107
|
const result = {};
|
|
106
|
-
const [roles, databases] = await Promise.all([api.listBranchRoles(projectId, branch.id), api.listBranchDatabases(projectId, branch.id)]);
|
|
107
|
-
const roleName = pickRoleName(roles, branch, options.roleName);
|
|
108
|
-
const databaseName = pickDatabaseName(databases, branch, options.databaseName);
|
|
109
108
|
const K = NEON_ENV_VAR_KEYS;
|
|
109
|
+
const wantsPooled = wants(K.postgres.databaseUrl);
|
|
110
|
+
const wantsUnpooled = wants(K.postgres.databaseUrlUnpooled);
|
|
110
111
|
const wantsAuth = desired.authEnabled && (wants(K.auth.baseUrl) || wants(K.auth.jwksUrl));
|
|
111
112
|
const wantsDataApi = desired.dataApiEnabled && wants(K.dataApi.url);
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
113
|
+
const gatewayEnabled = desired.preview?.aiGatewayEnabled ?? false;
|
|
114
|
+
const needsUnpooled = wantsUnpooled || gatewayEnabled && wants(K.aiGateway.baseUrl);
|
|
115
|
+
const needsConnectionTarget = wantsPooled || needsUnpooled;
|
|
116
|
+
const needsDatabase = needsConnectionTarget || wantsDataApi;
|
|
117
|
+
const [roles, databases] = await Promise.all([needsConnectionTarget ? api.listBranchRoles(projectId, branch.id) : Promise.resolve([]), needsDatabase ? api.listBranchDatabases(projectId, branch.id) : Promise.resolve([])]);
|
|
118
|
+
const databaseName = needsDatabase ? pickDatabaseName(databases, branch, options.databaseName) : null;
|
|
119
|
+
const connectionTarget = needsConnectionTarget ? {
|
|
120
|
+
roleName: pickRoleName(roles, branch, options.roleName),
|
|
121
|
+
databaseName: requiredValue(databaseName, "database for a selected connection URI")
|
|
122
|
+
} : null;
|
|
123
|
+
const getConnectionUri = (pooled) => {
|
|
124
|
+
const target = requiredValue(connectionTarget, "role and database for a selected connection URI");
|
|
125
|
+
return api.getConnectionUri(projectId, {
|
|
120
126
|
branchId: branch.id,
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
127
|
+
...target,
|
|
128
|
+
pooled
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
const [pooled, unpooled, authSnapshot, dataApiSnapshot] = await Promise.all([
|
|
132
|
+
wantsPooled ? getConnectionUri(true) : Promise.resolve(null),
|
|
133
|
+
needsUnpooled ? getConnectionUri(false) : Promise.resolve(null),
|
|
125
134
|
wantsAuth ? api.getNeonAuth(projectId, branch.id) : Promise.resolve(null),
|
|
126
|
-
wantsDataApi ? api.getNeonDataApi(projectId, branch.id, databaseName) : Promise.resolve(null)
|
|
135
|
+
wantsDataApi ? api.getNeonDataApi(projectId, branch.id, requiredValue(databaseName, "database for the selected Data API URL")) : Promise.resolve(null)
|
|
127
136
|
]);
|
|
128
137
|
const postgres = {};
|
|
129
|
-
if (
|
|
130
|
-
if (
|
|
138
|
+
if (wantsPooled) postgres.databaseUrl = requiredValue(pooled, "pooled connection URI response").uri;
|
|
139
|
+
if (wantsUnpooled) postgres.databaseUrlUnpooled = requiredValue(unpooled, "direct connection URI response").uri;
|
|
131
140
|
if (Object.keys(postgres).length > 0) result.postgres = postgres;
|
|
132
141
|
if (wants(K.branch.name)) result.branch = { name: branch.name };
|
|
133
142
|
if (wantsAuth) {
|
|
@@ -141,18 +150,22 @@ async function fetchEnvKeys(config, options, keys) {
|
|
|
141
150
|
result.auth = auth;
|
|
142
151
|
}
|
|
143
152
|
if (wantsDataApi) {
|
|
144
|
-
if (!dataApiSnapshot)
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
153
|
+
if (!dataApiSnapshot) {
|
|
154
|
+
const selectedDatabase = requiredValue(databaseName, "database for the selected Data API URL");
|
|
155
|
+
throw new PlatformError(ErrorCode.NotFound, [`fetchEnv: branch policy enables dataApi but no Data API integration is enabled on branch ${branch.name} (${branch.id}) database ${selectedDatabase}.`, "Enable it via `apply(config, { projectId, branchId })` or in the Neon Console — then re-run fetchEnv. Or return dataApi.enabled=false."].join(" "), { details: {
|
|
156
|
+
projectId,
|
|
157
|
+
branchId: branch.id,
|
|
158
|
+
databaseName: selectedDatabase
|
|
159
|
+
} });
|
|
160
|
+
}
|
|
149
161
|
result.dataApi = { url: dataApiSnapshot.url };
|
|
150
162
|
}
|
|
151
163
|
const storageEnabled = (desired.preview?.buckets.length ?? 0) > 0;
|
|
152
|
-
const gatewayEnabled = desired.preview?.aiGatewayEnabled ?? false;
|
|
153
164
|
const wantsStorage = storageEnabled && (wants(K.storage.accessKeyId) || wants(K.storage.secretAccessKey) || wants(K.storage.endpoint) || wants(K.storage.region));
|
|
154
165
|
const wantsGateway = gatewayEnabled && (wants(K.aiGateway.apiKey) || wants(K.aiGateway.baseUrl));
|
|
155
|
-
const
|
|
166
|
+
const wantsStorageCredential = storageEnabled && (wants(K.storage.accessKeyId) || wants(K.storage.secretAccessKey));
|
|
167
|
+
const wantsGatewayCredential = gatewayEnabled && wants(K.aiGateway.apiKey);
|
|
168
|
+
const wantsCredential = wantsStorageCredential || wantsGatewayCredential;
|
|
156
169
|
if (wantsStorage || wantsGateway) {
|
|
157
170
|
let storage = null;
|
|
158
171
|
if (wantsStorage) {
|
|
@@ -167,7 +180,10 @@ async function fetchEnvKeys(config, options, keys) {
|
|
|
167
180
|
projectId,
|
|
168
181
|
branchId: branch.id,
|
|
169
182
|
branchName: branch.name,
|
|
170
|
-
scopes: previewCredentialScopes(desired.preview
|
|
183
|
+
scopes: previewCredentialScopes(desired.preview, {
|
|
184
|
+
storage: wantsStorageCredential,
|
|
185
|
+
aiGateway: wantsGatewayCredential
|
|
186
|
+
})
|
|
171
187
|
}) : null;
|
|
172
188
|
if (storage) {
|
|
173
189
|
const storageEnv = {};
|
|
@@ -180,7 +196,7 @@ async function fetchEnvKeys(config, options, keys) {
|
|
|
180
196
|
if (wantsGateway) {
|
|
181
197
|
const gateway = {};
|
|
182
198
|
if (secrets && wants(K.aiGateway.apiKey)) gateway.apiKey = secrets.apiToken;
|
|
183
|
-
if (wants(K.aiGateway.baseUrl)) gateway.baseUrl = aiGatewayBaseUrl(branch.id, unpooled.uri);
|
|
199
|
+
if (wants(K.aiGateway.baseUrl)) gateway.baseUrl = aiGatewayBaseUrl(branch.id, requiredValue(unpooled, "direct connection URI for the selected AI Gateway base URL").uri);
|
|
184
200
|
result.aiGateway = gateway;
|
|
185
201
|
}
|
|
186
202
|
}
|
|
@@ -212,16 +228,14 @@ async function resolveBranchPolicy(config, options, api) {
|
|
|
212
228
|
};
|
|
213
229
|
}
|
|
214
230
|
/**
|
|
215
|
-
* Scopes the branch credential should carry for a resolved branch policy
|
|
216
|
-
* and the AI Gateway *require* a credential; functions never
|
|
217
|
-
*
|
|
218
|
-
* being minted for storage / the AI Gateway, so the one credential can invoke the branch's
|
|
219
|
-
* functions too. Returns `[]` only when nothing credential-bearing is enabled.
|
|
231
|
+
* Scopes the branch credential should carry for a resolved branch policy and optional key
|
|
232
|
+
* selection. Only object storage and the AI Gateway *require* a credential; functions never
|
|
233
|
+
* force one, but `functions:invoke` rides along when another selected feature mints one.
|
|
220
234
|
*/
|
|
221
|
-
function previewCredentialScopes(preview) {
|
|
235
|
+
function previewCredentialScopes(preview, selected) {
|
|
222
236
|
if (!preview) return [];
|
|
223
|
-
const storage = preview.buckets.length > 0;
|
|
224
|
-
const aiGateway = preview.aiGatewayEnabled;
|
|
237
|
+
const storage = preview.buckets.length > 0 && (selected?.storage ?? true);
|
|
238
|
+
const aiGateway = preview.aiGatewayEnabled && (selected?.aiGateway ?? true);
|
|
225
239
|
if (!storage && !aiGateway) return [];
|
|
226
240
|
return deriveCredentialScopes({
|
|
227
241
|
storage,
|
|
@@ -392,4 +406,126 @@ function toEntries(env) {
|
|
|
392
406
|
return out;
|
|
393
407
|
}
|
|
394
408
|
//#endregion
|
|
395
|
-
|
|
409
|
+
//#region src/env_services.ts
|
|
410
|
+
/**
|
|
411
|
+
* The services `env pull --service` can select: every Neon service that produces branch env
|
|
412
|
+
* vars. `functions` is the one left out — a function's env comes from the local `neon.ts`,
|
|
413
|
+
* never from the branch, so there is nothing to pull.
|
|
414
|
+
*/
|
|
415
|
+
const ENV_PULL_SERVICES = NEON_SERVICES.filter((service) => service !== "functions");
|
|
416
|
+
/** Why the services `env pull` leaves out are not selectable, for the refusal message. */
|
|
417
|
+
const ENV_PULL_UNAVAILABLE = { functions: "a function's env comes from your neon.ts, not from the branch, so there is nothing to pull" };
|
|
418
|
+
/** Every OS-level env var `env pull` can write, in stable emit order. */
|
|
419
|
+
const ENV_PULL_KEYS = [
|
|
420
|
+
...Object.values(NEON_ENV_VAR_KEYS.postgres),
|
|
421
|
+
NEON_ENV_VAR_KEYS.branch.name,
|
|
422
|
+
...Object.values(NEON_ENV_VAR_KEYS.auth),
|
|
423
|
+
...Object.values(NEON_ENV_VAR_KEYS.dataApi),
|
|
424
|
+
...Object.values(NEON_ENV_VAR_KEYS.storage),
|
|
425
|
+
...Object.values(NEON_ENV_VAR_KEYS.aiGateway)
|
|
426
|
+
];
|
|
427
|
+
/** The OS-level env vars each service contributes to a pulled `.env`. */
|
|
428
|
+
const SERVICE_ENV_KEYS = {
|
|
429
|
+
postgres: Object.values(NEON_ENV_VAR_KEYS.postgres),
|
|
430
|
+
auth: Object.values(NEON_ENV_VAR_KEYS.auth),
|
|
431
|
+
"data-api": Object.values(NEON_ENV_VAR_KEYS.dataApi),
|
|
432
|
+
"object-storage": Object.values(NEON_ENV_VAR_KEYS.storage),
|
|
433
|
+
"ai-gateway": Object.values(NEON_ENV_VAR_KEYS.aiGateway),
|
|
434
|
+
functions: []
|
|
435
|
+
};
|
|
436
|
+
/**
|
|
437
|
+
* The subset of {@link SERVICE_ENV_KEYS} a pull *owns*, and so may prune from the target file
|
|
438
|
+
* when the branch no longer has it. Object storage is deliberately absent: it is emitted under
|
|
439
|
+
* the third-party `AWS_*` names, which collide with credentials a user may set by hand, so
|
|
440
|
+
* `env pull` only ever writes them.
|
|
441
|
+
*/
|
|
442
|
+
const SERVICE_OWNED_ENV_KEYS = {
|
|
443
|
+
...SERVICE_ENV_KEYS,
|
|
444
|
+
"object-storage": []
|
|
445
|
+
};
|
|
446
|
+
/**
|
|
447
|
+
* Branch identity. Not a service — every branch has a name — so a scoped pull refreshes it
|
|
448
|
+
* alongside whatever services were selected.
|
|
449
|
+
*/
|
|
450
|
+
const BRANCH_ENV_KEY = NEON_ENV_VAR_KEYS.branch.name;
|
|
451
|
+
/** The service that produces a key, or `null` for branch identity. */
|
|
452
|
+
const ENV_KEY_SERVICE = {
|
|
453
|
+
DATABASE_URL: "postgres",
|
|
454
|
+
DATABASE_URL_UNPOOLED: "postgres",
|
|
455
|
+
NEON_BRANCH: null,
|
|
456
|
+
NEON_AUTH_BASE_URL: "auth",
|
|
457
|
+
NEON_AUTH_JWKS_URL: "auth",
|
|
458
|
+
NEON_DATA_API_URL: "data-api",
|
|
459
|
+
AWS_ACCESS_KEY_ID: "object-storage",
|
|
460
|
+
AWS_SECRET_ACCESS_KEY: "object-storage",
|
|
461
|
+
AWS_ENDPOINT_URL_S3: "object-storage",
|
|
462
|
+
AWS_REGION: "object-storage",
|
|
463
|
+
NEON_AI_GATEWAY_TOKEN: "ai-gateway",
|
|
464
|
+
NEON_AI_GATEWAY_BASE_URL: "ai-gateway"
|
|
465
|
+
};
|
|
466
|
+
const serviceForEnvKey = (key) => ENV_KEY_SERVICE[key];
|
|
467
|
+
/** Services that must be resolved to produce the selected env keys. */
|
|
468
|
+
const servicesForEnvKeys = (keys) => ENV_PULL_SERVICES.filter((service) => keys.some((key) => ENV_KEY_SERVICE[key] === service));
|
|
469
|
+
/** Every env var the selected services contribute, plus branch identity. */
|
|
470
|
+
const envServiceKeys = (services) => {
|
|
471
|
+
const keys = /* @__PURE__ */ new Set([BRANCH_ENV_KEY]);
|
|
472
|
+
for (const service of services) for (const key of SERVICE_ENV_KEYS[service]) keys.add(key);
|
|
473
|
+
return keys;
|
|
474
|
+
};
|
|
475
|
+
/**
|
|
476
|
+
* The env vars a pull scoped to `services` may prune. Narrower than the unscoped set on
|
|
477
|
+
* purpose: `env pull -s ai-gateway` says nothing about `DATABASE_URL`, so it must leave it
|
|
478
|
+
* alone rather than treat its absence from this pull as "the branch no longer has it".
|
|
479
|
+
*/
|
|
480
|
+
const ownedEnvServiceKeys = (services) => services.flatMap((service) => SERVICE_OWNED_ENV_KEYS[service]);
|
|
481
|
+
/**
|
|
482
|
+
* The exact env vars an explicit selection writes. Services contribute their complete
|
|
483
|
+
* bundles plus branch identity; `--env` contributes only the named keys. The two selectors
|
|
484
|
+
* compose as a union.
|
|
485
|
+
*/
|
|
486
|
+
const envKeysForSelection = (services, envKeys) => {
|
|
487
|
+
const selected = services.length > 0 ? envServiceKeys(services) : /* @__PURE__ */ new Set();
|
|
488
|
+
for (const key of envKeys) selected.add(key);
|
|
489
|
+
if (selected.has(NEON_ENV_VAR_KEYS.storage.accessKeyId) !== selected.has(NEON_ENV_VAR_KEYS.storage.secretAccessKey)) throw new Error("AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY must be selected together: they are two halves of one newly issued object-storage credential. Add the missing key to --env, or use --service object-storage.");
|
|
490
|
+
return ENV_PULL_KEYS.filter((key) => selected.has(key));
|
|
491
|
+
};
|
|
492
|
+
/** Parse repeated or comma-separated `--env` values into canonical env-key order. */
|
|
493
|
+
const parseEnvPullKeys = (raw, flag) => {
|
|
494
|
+
const names = raw.flatMap((value) => value.split(",")).map((name) => name.trim()).filter((name) => name !== "");
|
|
495
|
+
const supported = `Supported values: ${ENV_PULL_KEYS.join(", ")}.`;
|
|
496
|
+
if (names.length === 0) throw new Error(`${flag} needs at least one env variable. ${supported}`);
|
|
497
|
+
const unknown = names.filter((name) => !ENV_PULL_KEYS.some((key) => key === name));
|
|
498
|
+
if (unknown.length > 0) {
|
|
499
|
+
const displayNames = unknown.map(redactUnknownEnvValue);
|
|
500
|
+
const suggestions = [...new Set(unknown.map(suggestEnvPullKey).filter((key) => key !== null))];
|
|
501
|
+
const suggestion = suggestions.length > 0 ? ` Did you mean ${suggestions.join(" or ")}?` : "";
|
|
502
|
+
throw new Error(`Unknown env variable${unknown.length === 1 ? "" : "s"} ${displayNames.join(", ")}.${suggestion} ${supported}`);
|
|
503
|
+
}
|
|
504
|
+
return ENV_PULL_KEYS.filter((key) => names.includes(key));
|
|
505
|
+
};
|
|
506
|
+
const redactUnknownEnvValue = (value) => {
|
|
507
|
+
const separator = value.indexOf("=");
|
|
508
|
+
if (separator !== -1) {
|
|
509
|
+
const key = value.slice(0, separator);
|
|
510
|
+
return ENV_PULL_KEYS.some((supportedKey) => supportedKey === key) ? `${key}=<redacted>` : "<redacted invalid value>";
|
|
511
|
+
}
|
|
512
|
+
return "<redacted invalid value>";
|
|
513
|
+
};
|
|
514
|
+
const suggestEnvPullKey = (value) => {
|
|
515
|
+
if (value.includes("=")) return null;
|
|
516
|
+
const closest = ENV_PULL_KEYS.map((key) => [key, editDistance(value, key)]).sort((a, b) => a[1] - b[1])[0];
|
|
517
|
+
return closest && closest[1] <= 2 ? closest[0] : null;
|
|
518
|
+
};
|
|
519
|
+
const editDistance = (left, right) => {
|
|
520
|
+
let previous = Array.from({ length: right.length + 1 }, (_, index) => index);
|
|
521
|
+
for (let leftIndex = 1; leftIndex <= left.length; leftIndex += 1) {
|
|
522
|
+
const current = [leftIndex];
|
|
523
|
+
for (let rightIndex = 1; rightIndex <= right.length; rightIndex += 1) current[rightIndex] = Math.min((previous[rightIndex] ?? 0) + 1, (current[rightIndex - 1] ?? 0) + 1, (previous[rightIndex - 1] ?? 0) + (left[leftIndex - 1] === right[rightIndex - 1] ? 0 : 1));
|
|
524
|
+
previous = current;
|
|
525
|
+
}
|
|
526
|
+
return previous[right.length] ?? right.length;
|
|
527
|
+
};
|
|
528
|
+
/** Narrow yargs' array option value without accepting any other runtime shape. */
|
|
529
|
+
const envPullFlagValue = (value) => Array.isArray(value) ? value.map(String) : void 0;
|
|
530
|
+
//#endregion
|
|
531
|
+
export { policyEnvKeys as _, envKeysForSelection as a, toEntries as b, ownedEnvServiceKeys as c, servicesForEnvKeys as d, NEON_ENV_VAR_KEYS as f, fetchEnvKeys as g, credentialName as h, ENV_PULL_UNAVAILABLE as i, parseEnvPullKeys as l, credentialEnvKeys as m, ENV_PULL_KEYS as n, envPullFlagValue as o, createApiFromOptions as p, ENV_PULL_SERVICES as r, envServiceKeys as s, BRANCH_ENV_KEY as t, serviceForEnvKey as u, previewCredentialScopes as v, resolveBranchPolicy as y };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
|
-
//#region
|
|
3
|
+
//#region ../../internals/cli-core/dist/paths.js
|
|
4
4
|
/**
|
|
5
5
|
* # Where the Neon CLIs keep their files on disk
|
|
6
6
|
*
|
|
@@ -148,4 +148,4 @@ const isOwnedCredentialPath = (configDirectory, file) => {
|
|
|
148
148
|
return legacy !== void 0 && isInsideConfigDir(legacy, file);
|
|
149
149
|
};
|
|
150
150
|
//#endregion
|
|
151
|
-
export {
|
|
151
|
+
export { isOwnedCredentialPath as a, isInsideConfigDir as i, credentialsPath as n, resolveConfigFile as o, defaultDir as r, CREDENTIALS_FILE as t };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { writeSecretFile } from "./secure_file.js";
|
|
2
|
-
import { credentialsPath,
|
|
1
|
+
import { t as writeSecretFile } from "./secure_file-BucZj4yQ.js";
|
|
2
|
+
import { n as credentialsPath, o as resolveConfigFile, r as defaultDir } from "./paths-DMq0Lt7a.js";
|
|
3
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
4
|
import { isAbsolute, relative, resolve } from "node:path";
|
|
5
|
-
//#region
|
|
5
|
+
//#region ../../internals/cli-core/dist/profiles.js
|
|
6
6
|
/**
|
|
7
7
|
* # Profiles — several Neon accounts in one config directory
|
|
8
8
|
*
|
|
@@ -180,15 +180,6 @@ const upsertProfile = (dir, name, entry) => {
|
|
|
180
180
|
};
|
|
181
181
|
writeProfiles(path, file);
|
|
182
182
|
};
|
|
183
|
-
/** Remove an entry. Returns false when it wasn't there. */
|
|
184
|
-
const removeProfileEntry = (dir, name) => {
|
|
185
|
-
const path = profilesFilePath(dir);
|
|
186
|
-
const file = readProfiles(dir);
|
|
187
|
-
if (!file?.profiles[name]) return false;
|
|
188
|
-
delete file.profiles[name];
|
|
189
|
-
writeProfiles(path, file);
|
|
190
|
-
return true;
|
|
191
|
-
};
|
|
192
183
|
/**
|
|
193
184
|
* True when only `DEFAULT` is left, so `profiles.json` no longer earns its place. Mirrors
|
|
194
185
|
* lazy creation: a single-account install has no profiles file, before or after.
|
|
@@ -223,4 +214,4 @@ function nonEmpty(value) {
|
|
|
223
214
|
return trimmed === "" ? void 0 : trimmed;
|
|
224
215
|
}
|
|
225
216
|
//#endregion
|
|
226
|
-
export {
|
|
217
|
+
export { newProfileCredentialsPath as a, readProfiles as c, upsertProfile as d, listProfiles as i, resolveProfile as l, assertProfilesUsable as n, onlyDefaultRemains as o, assertValidProfileName as r, profilesFilePath as s, DEFAULT_PROFILE as t, selectProfileName as u };
|