neon 4.15.0 → 4.17.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 +48 -5
- package/dist/_chunks/{env-DsakkOVZ.js → env-B75xufe_.js} +57 -64
- package/dist/_chunks/{env_services-CAWrZTWa.js → env_services-CbARRnq9.js} +66 -11
- package/dist/analytics.js +11 -9
- package/dist/api.js +79 -0
- package/dist/commands/bootstrap.js +38 -34
- package/dist/commands/credentials.js +146 -0
- package/dist/commands/dev.js +8 -10
- package/dist/commands/env.js +6 -6
- package/dist/commands/index.js +4 -0
- package/dist/commands/init.js +233 -23
- package/dist/commands/link.js +27 -16
- package/dist/commands/triggers.js +182 -0
- package/dist/context.js +1 -0
- package/dist/dev/env.js +1 -1
- package/dist/env_services.js +1 -1
- package/dist/init/child.js +2 -1
- package/dist/init/choices.js +46 -0
- package/dist/init/chrome.js +25 -2
- package/dist/init/plan.js +42 -7
- package/dist/init/template_title.js +15 -0
- package/dist/init/tooling.js +5 -1
- package/dist/init/wizard.js +58 -6
- package/package.json +5 -5
|
@@ -8,14 +8,14 @@ import { FALLBACK_TEMPLATES, ensureTargetUsable, fetchTemplates, findTemplate, s
|
|
|
8
8
|
import { spawnCliChild } from "../init/child.js";
|
|
9
9
|
import { agentSetupDoneLabel, formatInitDone, printInitBanner, printInitDone, shouldPrintInitBanner } from "../init/chrome.js";
|
|
10
10
|
import { coerceAgentFlag } from "../utils/agent_flag.js";
|
|
11
|
-
import { assertNamedAgentTooling, chooseYesAgentTooling, initPluginAgents, initSkillsMcpAgents, postScaffoldActions, projectContextFile, resolveNamedAgents } from "../init/plan.js";
|
|
11
|
+
import { assertNamedAgentTooling, chooseYesAgentTooling, initPluginAgents, initSkillsMcpAgents, planLinkStep, postScaffoldActions, projectContextFile, resolveNamedAgents } from "../init/plan.js";
|
|
12
|
+
import { formatTemplateTitle } from "../init/template_title.js";
|
|
12
13
|
import { pickAgentSetupInteractively } from "../init/wizard.js";
|
|
13
14
|
import { runAgentTooling, runInitSteps } from "../init/tooling.js";
|
|
14
15
|
import { helpCsv, helpEpilogue } from "../utils/help_text.js";
|
|
15
16
|
import { formatInstallCommand, inferPackageManager, installArgs, installedPackageManagers, resolvePackageManager, runCommand } from "../utils/package_manager.js";
|
|
16
17
|
import { existsSync } from "node:fs";
|
|
17
18
|
import { join, relative, resolve } from "node:path";
|
|
18
|
-
import chalk from "chalk";
|
|
19
19
|
import prompts from "prompts";
|
|
20
20
|
//#region src/commands/bootstrap.ts
|
|
21
21
|
var bootstrap_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -102,20 +102,19 @@ const handler = async (props) => {
|
|
|
102
102
|
}
|
|
103
103
|
return;
|
|
104
104
|
}
|
|
105
|
-
if (shouldPrintInitBanner(props.default)) printInitBanner();
|
|
105
|
+
if (props.printBanner !== false && shouldPrintInitBanner(props.default)) printInitBanner();
|
|
106
106
|
const named = resolveNamedAgents(props.agent ?? []);
|
|
107
107
|
if (props.agentSetup !== false) assertNamedAgentTooling(named, "bootstrap", {
|
|
108
108
|
...props.directory !== void 0 && props.directory.length > 0 ? { directory: props.directory } : {},
|
|
109
109
|
...props.default ? { yes: true } : {}
|
|
110
110
|
});
|
|
111
|
-
const templates = await resolveTemplateList(props);
|
|
112
111
|
const interactive = !props.default && Boolean(process.stdout.isTTY) && !isCi();
|
|
113
|
-
const template = await resolveSelectedTemplate(props, interactive,
|
|
112
|
+
const template = props.selectedTemplate ?? await resolveSelectedTemplate(props, interactive, await resolveTemplateList(props));
|
|
114
113
|
const targetDir = await resolveTargetDir(props, interactive, template);
|
|
115
114
|
ensureTargetUsable(targetDir, props.force);
|
|
116
115
|
await scaffold(template, targetDir);
|
|
117
116
|
printScaffolded(template, targetDir);
|
|
118
|
-
|
|
117
|
+
return runPostScaffoldSteps(props, targetDir, interactive, template, named);
|
|
119
118
|
};
|
|
120
119
|
/**
|
|
121
120
|
* The template list to choose from. When --template is given we try the
|
|
@@ -123,18 +122,6 @@ const handler = async (props) => {
|
|
|
123
122
|
* remote manifest if the id isn't one of the defaults.
|
|
124
123
|
*/
|
|
125
124
|
const resolveTemplateList = async (props) => props.template && findTemplate(FALLBACK_TEMPLATES, props.template) ? FALLBACK_TEMPLATES : fetchTemplates();
|
|
126
|
-
/**
|
|
127
|
-
* The picker label for a template: the title first, then the Neon services it
|
|
128
|
-
* uses as a dim, italic suffix, e.g. "Hono API … Postgres · Functions". The
|
|
129
|
-
* suffix is styled with chalk.dim (and italic) only — never a foreground color —
|
|
130
|
-
* so it survives the cyan/underline `prompts` paints over the focused row: dim
|
|
131
|
-
* and italic reset with their own SGRs, leaving the row's color and underline
|
|
132
|
-
* intact. Descriptions are intentionally omitted to keep the picker uncluttered.
|
|
133
|
-
*/
|
|
134
|
-
const formatTemplateTitle = (template) => {
|
|
135
|
-
if (!template.services || template.services.length === 0) return template.title;
|
|
136
|
-
return `${template.title} ${chalk.dim.italic(template.services.join(" · "))}`;
|
|
137
|
-
};
|
|
138
125
|
const resolveSelectedTemplate = async (props, interactive, templates) => {
|
|
139
126
|
if (props.template) {
|
|
140
127
|
const template = findTemplate(templates, props.template);
|
|
@@ -188,20 +175,19 @@ const scaffold = async (template, targetDir) => {
|
|
|
188
175
|
log.info("Scaffolded %d files into %s.", filesWritten, targetDir);
|
|
189
176
|
return filesWritten;
|
|
190
177
|
};
|
|
178
|
+
const nestedResult = (template, targetDir, hasNeonConfig, outcome) => ({
|
|
179
|
+
templateTitle: template.title,
|
|
180
|
+
targetDir,
|
|
181
|
+
hasNeonConfig,
|
|
182
|
+
...outcome
|
|
183
|
+
});
|
|
191
184
|
const runPostScaffoldSteps = async (props, targetDir, interactive, template, named) => {
|
|
192
185
|
const inferred = inferPackageManager(targetDir);
|
|
193
186
|
const defaultPm = resolvePackageManager(targetDir);
|
|
194
187
|
const neonConfig = hasNeonConfig(targetDir);
|
|
195
|
-
if (props.default)
|
|
196
|
-
await runDefaultSteps(props, targetDir, defaultPm, neonConfig, template, named);
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
188
|
+
if (props.default) return runDefaultSteps(props, targetDir, defaultPm, neonConfig, template, named);
|
|
199
189
|
if (!interactive) {
|
|
200
|
-
|
|
201
|
-
heading: "Project scaffolded.",
|
|
202
|
-
template,
|
|
203
|
-
targetDir,
|
|
204
|
-
pm: defaultPm,
|
|
190
|
+
const outcome = {
|
|
205
191
|
installed: false,
|
|
206
192
|
installFailed: false,
|
|
207
193
|
gitFailed: false,
|
|
@@ -209,10 +195,18 @@ const runPostScaffoldSteps = async (props, targetDir, interactive, template, nam
|
|
|
209
195
|
agentSetup: "skip",
|
|
210
196
|
linked: false,
|
|
211
197
|
skippedLinkForDeps: false,
|
|
212
|
-
suggestLink: true,
|
|
213
198
|
agentsRan: false
|
|
199
|
+
};
|
|
200
|
+
finishPostScaffold({
|
|
201
|
+
heading: "Project scaffolded.",
|
|
202
|
+
template,
|
|
203
|
+
targetDir,
|
|
204
|
+
pm: defaultPm,
|
|
205
|
+
...outcome,
|
|
206
|
+
suggestLink: true,
|
|
207
|
+
skipPrint: props.skipDoneSummary === true
|
|
214
208
|
});
|
|
215
|
-
return;
|
|
209
|
+
return nestedResult(template, targetDir, neonConfig, outcome);
|
|
216
210
|
}
|
|
217
211
|
let pm = defaultPm;
|
|
218
212
|
const wantInstall = props.install && await confirm(installPrompt(inferred));
|
|
@@ -239,8 +233,10 @@ const runPostScaffoldSteps = async (props, targetDir, interactive, template, nam
|
|
|
239
233
|
targetDir,
|
|
240
234
|
pm,
|
|
241
235
|
...outcome,
|
|
242
|
-
suggestLink: !outcome.linked
|
|
236
|
+
suggestLink: !outcome.linked,
|
|
237
|
+
skipPrint: props.skipDoneSummary === true
|
|
243
238
|
});
|
|
239
|
+
return nestedResult(template, targetDir, neonConfig, outcome);
|
|
244
240
|
};
|
|
245
241
|
const installPrompt = (inferred) => inferred ? `Install dependencies with ${inferred}?` : "Install dependencies?";
|
|
246
242
|
/** `link --yes` still asks for a project unless one is already linked. */
|
|
@@ -265,11 +261,16 @@ const runDefaultSteps = async (props, targetDir, pm, neonConfig, template, named
|
|
|
265
261
|
targetDir,
|
|
266
262
|
pm,
|
|
267
263
|
...outcome,
|
|
268
|
-
suggestLink: !outcome.linked
|
|
264
|
+
suggestLink: !outcome.linked,
|
|
265
|
+
skipPrint: props.skipDoneSummary === true
|
|
269
266
|
});
|
|
267
|
+
return nestedResult(template, targetDir, neonConfig, outcome);
|
|
270
268
|
};
|
|
271
269
|
const executePostScaffold = async (props, targetDir, choices) => {
|
|
272
|
-
const kids =
|
|
270
|
+
const kids = {
|
|
271
|
+
...bootstrapChildren(props, targetDir),
|
|
272
|
+
...props.narrate ? { narrate: props.narrate } : {}
|
|
273
|
+
};
|
|
273
274
|
let installed = false;
|
|
274
275
|
let installFailed = false;
|
|
275
276
|
let gitFailed = false;
|
|
@@ -321,7 +322,10 @@ const executePostScaffold = async (props, targetDir, choices) => {
|
|
|
321
322
|
logSkippedLink(choices.pm);
|
|
322
323
|
continue;
|
|
323
324
|
}
|
|
324
|
-
await runInitSteps([
|
|
325
|
+
await runInitSteps([props.linkNoConfig === true ? planLinkStep({
|
|
326
|
+
yes: choices.yes,
|
|
327
|
+
extra: props.linkExtra
|
|
328
|
+
}) : choices.yes ? ["link", "--yes"] : ["link"]], {
|
|
325
329
|
cwd: targetDir,
|
|
326
330
|
...kids
|
|
327
331
|
});
|
|
@@ -450,7 +454,7 @@ const printDoneSummary = (input) => {
|
|
|
450
454
|
}));
|
|
451
455
|
};
|
|
452
456
|
const finishPostScaffold = (input) => {
|
|
453
|
-
printDoneSummary(input);
|
|
457
|
+
if (!input.skipPrint) printDoneSummary(input);
|
|
454
458
|
if (input.installFailed || input.gitFailed) throw new Error("Setup did not finish.");
|
|
455
459
|
};
|
|
456
460
|
const isCurrentDir = (targetDir) => relative(process.cwd(), targetDir) === "";
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { t as __exportAll } from "../_chunks/rolldown-runtime-8H4AJuhK.js";
|
|
2
|
+
import { log } from "../log.js";
|
|
3
|
+
import { isNeonApiError, messageFromBody, retryOnLock } from "../api.js";
|
|
4
|
+
import { writer } from "../writer.js";
|
|
5
|
+
import { branchIdFromProps, fillSingleProject } from "../utils/enrichers.js";
|
|
6
|
+
//#region src/commands/credentials.ts
|
|
7
|
+
var credentials_exports = /* @__PURE__ */ __exportAll({
|
|
8
|
+
aliases: () => aliases,
|
|
9
|
+
builder: () => builder,
|
|
10
|
+
command: () => command,
|
|
11
|
+
create: () => create,
|
|
12
|
+
describe: () => describe,
|
|
13
|
+
handler: () => handler,
|
|
14
|
+
list: () => list,
|
|
15
|
+
reveal: () => reveal,
|
|
16
|
+
revoke: () => revoke,
|
|
17
|
+
rotate: () => rotate
|
|
18
|
+
});
|
|
19
|
+
const CREDENTIAL_SCOPES = [
|
|
20
|
+
"storage:read",
|
|
21
|
+
"storage:write",
|
|
22
|
+
"ai_gateway:invoke",
|
|
23
|
+
"functions:invoke"
|
|
24
|
+
];
|
|
25
|
+
const LIST_FIELDS = [
|
|
26
|
+
"token_id",
|
|
27
|
+
"name",
|
|
28
|
+
"principal_type",
|
|
29
|
+
"scopes",
|
|
30
|
+
"created_at"
|
|
31
|
+
];
|
|
32
|
+
const SECRET_META_FIELDS = [
|
|
33
|
+
"token_id",
|
|
34
|
+
"name",
|
|
35
|
+
"scopes"
|
|
36
|
+
];
|
|
37
|
+
const renderColumns = { scopes: (c) => (c.scopes ?? []).join(", ") };
|
|
38
|
+
/** Translate a token-id 404 into a resource-specific message; re-throw everything else. */
|
|
39
|
+
async function withCredentialNotFound(tokenId, branchId, run) {
|
|
40
|
+
try {
|
|
41
|
+
return await run();
|
|
42
|
+
} catch (err) {
|
|
43
|
+
if (isNeonApiError(err) && err.status === 404) {
|
|
44
|
+
if ((messageFromBody(err.data) ?? "").includes("platform credentials not available")) throw err;
|
|
45
|
+
throw new Error(`Credential ${tokenId} not found on branch ${branchId}.`);
|
|
46
|
+
}
|
|
47
|
+
throw err;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Secrets are shown only once (create/rotate) or on demand (reveal). Table
|
|
52
|
+
* output keeps them off the grid so they stay one selectable line; json/yaml
|
|
53
|
+
* keep them on the object for scripts.
|
|
54
|
+
*/
|
|
55
|
+
const reportSecrets = (props, data, warning) => {
|
|
56
|
+
const out = writer(props);
|
|
57
|
+
if (props.output === "table") {
|
|
58
|
+
out.write(data, { fields: SECRET_META_FIELDS });
|
|
59
|
+
out.end();
|
|
60
|
+
const apiToken = "api_token" in data && typeof data.api_token === "string" ? data.api_token : "";
|
|
61
|
+
const secretKey = "s3_secret_access_key" in data && typeof data.s3_secret_access_key === "string" ? data.s3_secret_access_key : "";
|
|
62
|
+
out.text(`api_token: ${apiToken}\n`);
|
|
63
|
+
out.text(`s3_secret_access_key: ${secretKey}\n`);
|
|
64
|
+
} else out.end(data, { fields: [
|
|
65
|
+
"token_id",
|
|
66
|
+
"name",
|
|
67
|
+
"scopes",
|
|
68
|
+
"api_token",
|
|
69
|
+
"s3_secret_access_key"
|
|
70
|
+
] });
|
|
71
|
+
log.warning(warning);
|
|
72
|
+
};
|
|
73
|
+
const command = "credentials";
|
|
74
|
+
const describe = "Manage branch credentials";
|
|
75
|
+
const aliases = ["credential"];
|
|
76
|
+
const builder = (argv) => argv.usage("$0 credentials <sub-command> [options]").options({
|
|
77
|
+
"project-id": {
|
|
78
|
+
describe: "Project ID",
|
|
79
|
+
type: "string"
|
|
80
|
+
},
|
|
81
|
+
branch: {
|
|
82
|
+
describe: "Branch ID or name",
|
|
83
|
+
type: "string"
|
|
84
|
+
}
|
|
85
|
+
}).middleware(fillSingleProject).command("list", "List credentials on the branch", (yargs) => yargs, (args) => list(args)).command("create", "Issue a scoped credential on the branch", (yargs) => yargs.options({
|
|
86
|
+
name: {
|
|
87
|
+
describe: "Label for the credential",
|
|
88
|
+
type: "string"
|
|
89
|
+
},
|
|
90
|
+
scope: {
|
|
91
|
+
describe: "Capability to grant. Repeatable. Values: storage:read, storage:write, ai_gateway:invoke, functions:invoke",
|
|
92
|
+
type: "string",
|
|
93
|
+
array: true,
|
|
94
|
+
choices: CREDENTIAL_SCOPES,
|
|
95
|
+
demandOption: true
|
|
96
|
+
}
|
|
97
|
+
}), (args) => create(args)).command("reveal <tokenId>", "Show a credential's api_token and s3_secret_access_key", (yargs) => yargs.positional("tokenId", {
|
|
98
|
+
describe: "Credential token id (nak_live_<32hex>)",
|
|
99
|
+
type: "string"
|
|
100
|
+
}), (args) => reveal(args)).command("rotate <tokenId>", "Replace a credential's secrets in place. The token id is unchanged.", (yargs) => yargs.positional("tokenId", {
|
|
101
|
+
describe: "Credential token id (nak_live_<32hex>)",
|
|
102
|
+
type: "string"
|
|
103
|
+
}), (args) => rotate(args)).command("revoke <tokenId>", "Revoke a credential", (yargs) => yargs.positional("tokenId", {
|
|
104
|
+
describe: "Credential token id (nak_live_<32hex>)",
|
|
105
|
+
type: "string"
|
|
106
|
+
}), (args) => revoke(args));
|
|
107
|
+
const handler = (args) => {
|
|
108
|
+
return args;
|
|
109
|
+
};
|
|
110
|
+
const list = async (props) => {
|
|
111
|
+
const branchId = await branchIdFromProps(props);
|
|
112
|
+
const { data } = await props.apiClient.listCredentials(props.projectId, branchId);
|
|
113
|
+
writer(props).end(data.credentials, {
|
|
114
|
+
fields: LIST_FIELDS,
|
|
115
|
+
renderColumns,
|
|
116
|
+
emptyMessage: "No credentials found on this branch."
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
const create = async (props) => {
|
|
120
|
+
const branchId = await branchIdFromProps(props);
|
|
121
|
+
const scopes = (Array.isArray(props.scope) ? props.scope : [props.scope]).filter((scope) => CREDENTIAL_SCOPES.some((allowed) => allowed === scope));
|
|
122
|
+
if (scopes.length === 0) throw new Error("Pass at least one --scope. Values: storage:read, storage:write, ai_gateway:invoke, functions:invoke");
|
|
123
|
+
const { data } = await retryOnLock(() => props.apiClient.createCredential(props.projectId, branchId, {
|
|
124
|
+
scopes,
|
|
125
|
+
principal_type: "user",
|
|
126
|
+
...props.name !== void 0 ? { name: props.name } : {}
|
|
127
|
+
}));
|
|
128
|
+
reportSecrets(props, data, "Store these secrets now: they are not shown again unless you run neon credentials reveal.");
|
|
129
|
+
};
|
|
130
|
+
const reveal = async (props) => {
|
|
131
|
+
const branchId = await branchIdFromProps(props);
|
|
132
|
+
const { data } = await withCredentialNotFound(props.tokenId, branchId, () => props.apiClient.revealCredential(props.projectId, branchId, props.tokenId));
|
|
133
|
+
reportSecrets(props, data, "These are live secrets. Treat them like a password.");
|
|
134
|
+
};
|
|
135
|
+
const rotate = async (props) => {
|
|
136
|
+
const branchId = await branchIdFromProps(props);
|
|
137
|
+
const { data } = await withCredentialNotFound(props.tokenId, branchId, () => retryOnLock(() => props.apiClient.rotateCredential(props.projectId, branchId, props.tokenId)));
|
|
138
|
+
reportSecrets(props, data, "Store the new secrets now: a retry mints another pair and does not recover a lost response. A replica may briefly accept the previous secret.");
|
|
139
|
+
};
|
|
140
|
+
const revoke = async (props) => {
|
|
141
|
+
const branchId = await branchIdFromProps(props);
|
|
142
|
+
await withCredentialNotFound(props.tokenId, branchId, () => retryOnLock(() => props.apiClient.revokeCredential(props.projectId, branchId, props.tokenId)));
|
|
143
|
+
log.info(`Credential ${props.tokenId} revoked`);
|
|
144
|
+
};
|
|
145
|
+
//#endregion
|
|
146
|
+
export { aliases, builder, command, create, describe, handler, list, reveal, revoke, rotate, credentials_exports as t };
|
package/dist/commands/dev.js
CHANGED
|
@@ -2,11 +2,11 @@ import { t as __exportAll } from "../_chunks/rolldown-runtime-8H4AJuhK.js";
|
|
|
2
2
|
import { log } from "../log.js";
|
|
3
3
|
import { getCliName } from "../utils/cli_name.js";
|
|
4
4
|
import { readEnvFile, resolveEnvFilePath } from "../env_file.js";
|
|
5
|
-
import {
|
|
5
|
+
import { y as functionBaseUrlKey } from "../_chunks/env_services-CbARRnq9.js";
|
|
6
6
|
import { isClaimableEnvTarget } from "../claimable/state.js";
|
|
7
7
|
import { branchIdResolve } from "../utils/enrichers.js";
|
|
8
8
|
import { bundleEntry } from "../utils/esbuild.js";
|
|
9
|
-
import { a as resolveDevEnv } from "../_chunks/env-
|
|
9
|
+
import { a as resolveDevEnv } from "../_chunks/env-B75xufe_.js";
|
|
10
10
|
import { findConfigFunctionBySource, resolveFunctionsFromConfig } from "../dev/functions.js";
|
|
11
11
|
import { resolveWatchInputs } from "../dev/inputs.js";
|
|
12
12
|
import { existsSync, mkdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
@@ -95,21 +95,19 @@ const devEnvContext = (props, branchId, cwd) => {
|
|
|
95
95
|
};
|
|
96
96
|
};
|
|
97
97
|
/**
|
|
98
|
-
* Say when
|
|
98
|
+
* Say when this run obtained credential secrets it did not already hold.
|
|
99
99
|
*
|
|
100
|
-
* `dev`
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
* `NEON_AI_GATEWAY_TOKEN` reads as "fetched", not "just created, and the last one is still
|
|
104
|
-
* live". The note names the one action that stops it, so it disappears once followed.
|
|
100
|
+
* `dev` writes no file. With platform defaults, each start re-reveals the same secrets until
|
|
101
|
+
* `env pull` persists them. In a region with no defaults, each start mints another credential
|
|
102
|
+
* and cannot revoke the last one. The note names the one action that stops either loop.
|
|
105
103
|
*/
|
|
106
104
|
const reportDevCredential = (credential) => {
|
|
107
105
|
if (!credential?.issued) return;
|
|
108
106
|
if (credential.revoked.length > 0) {
|
|
109
|
-
log.info("
|
|
107
|
+
log.info("Wrote credential secrets — %s changed. Revoked the leftover it replaced (%s).", credential.keys.join(", "), credential.revoked.join(", "));
|
|
110
108
|
return;
|
|
111
109
|
}
|
|
112
|
-
log.warning(`
|
|
110
|
+
log.warning(`Resolved credential secrets for this run (%s) without writing them to a file. Run \`${getCliName()} env pull\` once so restarts reuse them instead of revealing or minting again.`, credential.keys.join(", "));
|
|
113
111
|
};
|
|
114
112
|
const handler = async (props) => {
|
|
115
113
|
if (props.source !== void 0) {
|
package/dist/commands/env.js
CHANGED
|
@@ -4,12 +4,12 @@ import { ensureGitignored } from "../context.js";
|
|
|
4
4
|
import { getCliName } from "../utils/cli_name.js";
|
|
5
5
|
import { deprecatedServiceMessage, parseServices, servicesFlagValue, servicesOption } from "../neon_services.js";
|
|
6
6
|
import { mergeEnvFile, readEnvFile, resolveEnvFilePath } from "../env_file.js";
|
|
7
|
-
import { a as envKeysForSelection, c as ownedEnvServiceKeys, f as NEON_ENV_VAR_KEYS, i as ENV_PULL_SERVICES, l as parseEnvPullKeys, o as envPullFlagValue, r as ENV_PULL_KEY_HELP
|
|
7
|
+
import { a as envKeysForSelection, b as isFunctionBaseUrlKey, c as ownedEnvServiceKeys, f as NEON_ENV_VAR_KEYS, i as ENV_PULL_SERVICES, l as parseEnvPullKeys, o as envPullFlagValue, r as ENV_PULL_KEY_HELP } from "../_chunks/env_services-CbARRnq9.js";
|
|
8
8
|
import { isClaimableEnvTarget } from "../claimable/state.js";
|
|
9
9
|
import { fillSingleProject, resolveBranchRef } from "../utils/enrichers.js";
|
|
10
10
|
import { warnAiGateway } from "../utils/ai_gateway_notice.js";
|
|
11
11
|
import { announceTargetBranch } from "../utils/branch_notice.js";
|
|
12
|
-
import { i as dropClaimableUnsupported, o as resolveNeonEnvVars } from "../_chunks/env-
|
|
12
|
+
import { i as dropClaimableUnsupported, o as resolveNeonEnvVars } from "../_chunks/env-B75xufe_.js";
|
|
13
13
|
import { existsSync } from "node:fs";
|
|
14
14
|
import chalk from "chalk";
|
|
15
15
|
//#region src/commands/env.ts
|
|
@@ -67,7 +67,7 @@ const builder = (argv) => argv.usage("$0 env <sub-command> [options]").options({
|
|
|
67
67
|
" 2. neon.ts, when this directory has one — including derived function",
|
|
68
68
|
" URLs (the function does not have to be deployed).",
|
|
69
69
|
" 3. Otherwise everything the branch has, plus the AI Gateway —",
|
|
70
|
-
" which
|
|
70
|
+
" which pulls the default AI Gateway credential.",
|
|
71
71
|
"",
|
|
72
72
|
"On an unclaimed Claimable Neon project, neon.ts is still the source",
|
|
73
73
|
"of truth when it only declares Postgres, Auth, and the Data API.",
|
|
@@ -78,8 +78,8 @@ const builder = (argv) => argv.usage("$0 env <sub-command> [options]").options({
|
|
|
78
78
|
"and writes nothing for them.",
|
|
79
79
|
"",
|
|
80
80
|
"The pull bundled into link / checkout / config apply follows 2 and 3",
|
|
81
|
-
"without the AI Gateway, so it never
|
|
82
|
-
"for. Run `env pull` to add it."
|
|
81
|
+
"without the AI Gateway, so it never writes a gateway token you did",
|
|
82
|
+
"not ask for. Run `env pull` to add it."
|
|
83
83
|
].join("\n")).example("$0 env pull", "Write the linked branch's Neon vars into .env.local (or .env if present)").example("$0 env pull --branch preview --file .env.preview", "Pull a specific branch into a specific file").example("$0 env pull -s ai-gateway -s postgres", "Pull only the AI Gateway and Postgres variables").example("$0 env pull -e DATABASE_URL", "Pull only the pooled Postgres connection string").example("$0 env pull -s auth -e DATABASE_URL", "Pull all Auth variables plus DATABASE_URL").example("$0 env pull -s functions", "Pull NEON_FUNCTION_<SLUG>_BASE_URL for every deployed function").example("$0 env pull -e NEON_FUNCTION_HELLO_BASE_URL", "Write that function's production invocation URL (no deploy required)").strict(), async (args) => {
|
|
84
84
|
const rawServices = servicesFlagValue(args.service);
|
|
85
85
|
const rawEnvKeys = envPullFlagValue(args.env);
|
|
@@ -164,7 +164,7 @@ const pull = async (props, opts = {}) => {
|
|
|
164
164
|
log.info("Pulled %d Neon variable%s into %s: %s", written.length, written.length === 1 ? "" : "s", targetPath, written.join(", "));
|
|
165
165
|
if (removed.length > 0) log.info("Removed %d stale Neon variable%s not enabled on this branch: %s", removed.length, removed.length === 1 ? "" : "s", removed.join(", "));
|
|
166
166
|
if (credential?.issued) {
|
|
167
|
-
log.info("
|
|
167
|
+
log.info("Wrote credential secrets — these now hold fresh values: %s", credential.keys.join(", "));
|
|
168
168
|
if (credential.revoked.length > 0) log.info("Revoked the credential it replaced (%s).", credential.revoked.join(", "));
|
|
169
169
|
else if (credential.superseded.length > 0) log.info("Left the credential it replaced live (%s): an explicitly scoped pull can't tell which other variables still use it. Revoke it in the Neon Console if nothing does.", credential.superseded.join(", "));
|
|
170
170
|
}
|
package/dist/commands/index.js
CHANGED
|
@@ -12,6 +12,7 @@ import { t as link_exports } from "./link.js";
|
|
|
12
12
|
import { t as checkout_exports } from "./checkout.js";
|
|
13
13
|
import { t as claim_exports } from "./claim.js";
|
|
14
14
|
import { t as connection_string_exports } from "./connection_string.js";
|
|
15
|
+
import { t as credentials_exports } from "./credentials.js";
|
|
15
16
|
import { t as data_api_exports } from "./data_api.js";
|
|
16
17
|
import { t as databases_exports } from "./databases.js";
|
|
17
18
|
import { t as deploy_exports } from "./deploy.js";
|
|
@@ -35,6 +36,7 @@ import { t as set_context_exports } from "./set_context.js";
|
|
|
35
36
|
import { t as skills_exports } from "./skills.js";
|
|
36
37
|
import { t as snapshots_exports } from "./snapshots.js";
|
|
37
38
|
import { t as status_exports } from "./status.js";
|
|
39
|
+
import { t as triggers_exports } from "./triggers.js";
|
|
38
40
|
import { t as user_exports } from "./user.js";
|
|
39
41
|
import { t as vpc_endpoints_exports } from "./vpc_endpoints.js";
|
|
40
42
|
//#region src/commands/index.ts
|
|
@@ -70,6 +72,8 @@ var commands_default = [
|
|
|
70
72
|
ask_exports,
|
|
71
73
|
data_api_exports,
|
|
72
74
|
functions_exports,
|
|
75
|
+
triggers_exports,
|
|
76
|
+
credentials_exports,
|
|
73
77
|
dev_exports,
|
|
74
78
|
diff_exports,
|
|
75
79
|
config_exports,
|