neon 8.11.0 → 8.11.2

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.
Files changed (106) hide show
  1. package/README.md +1 -1
  2. package/dist/_chunks/api-GbEaBZJ5.js +388 -0
  3. package/dist/_chunks/api_keys-CNnnugbQ.js +281 -0
  4. package/dist/_chunks/ask-DVwy0eUL.js +155 -0
  5. package/dist/_chunks/auth-CIUtXByB.js +495 -0
  6. package/dist/_chunks/bootstrap-wPZWa1sT.js +499 -0
  7. package/dist/_chunks/branches-BNa1xX1L.js +460 -0
  8. package/dist/_chunks/bucket-BCdryTkD.js +409 -0
  9. package/dist/_chunks/checkout-CXIOydqZ.js +348 -0
  10. package/dist/_chunks/claim-DqAvAvDm.js +473 -0
  11. package/dist/_chunks/config-BH_qRHiG.js +1113 -0
  12. package/dist/_chunks/connection_string-DB4awPzZ.js +154 -0
  13. package/dist/_chunks/credentials-BSjE9fRR.js +146 -0
  14. package/dist/_chunks/data_api-Djxj5ZQD.js +263 -0
  15. package/dist/_chunks/databases-Dok4wru7.js +84 -0
  16. package/dist/_chunks/deploy-D7B0Xfjg.js +33 -0
  17. package/dist/_chunks/dev-CSvxAecE.js +945 -0
  18. package/dist/_chunks/diff-DhxxbdQE.js +178 -0
  19. package/dist/_chunks/docs-CrVybkTP.js +197 -0
  20. package/dist/_chunks/env-5HS5qQGd.js +284 -0
  21. package/dist/_chunks/feedback-CMayyTa8.js +88 -0
  22. package/dist/_chunks/functions-Q0zuvtnk.js +464 -0
  23. package/dist/_chunks/git-H32TNt6M.js +356 -0
  24. package/dist/_chunks/init-BkA6RilG.js +111 -0
  25. package/dist/_chunks/inspect-g0wekylj.js +90 -0
  26. package/dist/_chunks/ip_allow-5lLFvIuE.js +106 -0
  27. package/dist/_chunks/link-BgtkOBws.js +936 -0
  28. package/dist/_chunks/logs-DWkpjzIH.js +291 -0
  29. package/dist/_chunks/mcp-Bo-7TKc7.js +253 -0
  30. package/dist/_chunks/neon_auth-CBs1_3qu.js +822 -0
  31. package/dist/_chunks/open-CX3BT3Tp.js +33 -0
  32. package/dist/_chunks/operations-D4I-AxVs.js +37 -0
  33. package/dist/_chunks/orgs-xGfANwHQ.js +52 -0
  34. package/dist/_chunks/plugins-DqD7BDO1.js +169 -0
  35. package/dist/_chunks/profile-yXOiKk9R.js +672 -0
  36. package/dist/_chunks/projects-BwI2Uo0z.js +439 -0
  37. package/dist/_chunks/psql-BM-doe8e.js +64 -0
  38. package/dist/_chunks/realtime-BRqIyGR-.js +79 -0
  39. package/dist/_chunks/roles-B4w3YT_7.js +79 -0
  40. package/dist/_chunks/set_context-DbrwoImy.js +38 -0
  41. package/dist/_chunks/skills-DyiBXKS3.js +255 -0
  42. package/dist/_chunks/snapshots-RJBzW8GM.js +338 -0
  43. package/dist/_chunks/status-DV8Z2kw3.js +44 -0
  44. package/dist/_chunks/triggers-BrRo1z4b.js +302 -0
  45. package/dist/_chunks/user-dlOGXbX9.js +60 -0
  46. package/dist/_chunks/vpc_endpoints-CNb0YfMo.js +105 -0
  47. package/dist/auth_recovery.js +1 -1
  48. package/dist/commands/api.js +1 -388
  49. package/dist/commands/api_keys.js +1 -281
  50. package/dist/commands/ask.js +1 -155
  51. package/dist/commands/auth.js +1 -495
  52. package/dist/commands/bootstrap.js +1 -499
  53. package/dist/commands/branches.js +1 -460
  54. package/dist/commands/bucket.js +1 -409
  55. package/dist/commands/checkout.js +1 -348
  56. package/dist/commands/claim.js +1 -473
  57. package/dist/commands/config.js +1 -1113
  58. package/dist/commands/connection_string.js +1 -154
  59. package/dist/commands/credentials.js +1 -146
  60. package/dist/commands/data_api.js +1 -263
  61. package/dist/commands/databases.js +1 -84
  62. package/dist/commands/deploy.js +1 -33
  63. package/dist/commands/dev.js +1 -945
  64. package/dist/commands/diff.js +1 -178
  65. package/dist/commands/docs.js +1 -197
  66. package/dist/commands/env.js +1 -284
  67. package/dist/commands/feedback.js +1 -88
  68. package/dist/commands/functions.js +1 -464
  69. package/dist/commands/functions_new.js +6 -6
  70. package/dist/commands/git.js +1 -356
  71. package/dist/commands/index.js +45 -45
  72. package/dist/commands/init.js +1 -111
  73. package/dist/commands/inspect.js +1 -90
  74. package/dist/commands/ip_allow.js +1 -106
  75. package/dist/commands/link.js +1 -936
  76. package/dist/commands/logs.js +1 -291
  77. package/dist/commands/mcp.js +1 -253
  78. package/dist/commands/neon_auth.js +1 -822
  79. package/dist/commands/open.js +1 -33
  80. package/dist/commands/operations.js +1 -37
  81. package/dist/commands/orgs.js +1 -52
  82. package/dist/commands/plugins.js +1 -169
  83. package/dist/commands/profile.js +1 -672
  84. package/dist/commands/projects.js +1 -439
  85. package/dist/commands/psql.js +1 -64
  86. package/dist/commands/realtime.js +1 -79
  87. package/dist/commands/roles.js +1 -79
  88. package/dist/commands/set_context.js +1 -38
  89. package/dist/commands/skills.js +1 -255
  90. package/dist/commands/snapshots.js +1 -338
  91. package/dist/commands/status.js +1 -44
  92. package/dist/commands/subscribe.js +1 -1
  93. package/dist/commands/triggers.js +1 -302
  94. package/dist/commands/user.js +1 -60
  95. package/dist/commands/vpc_endpoints.js +1 -105
  96. package/dist/functions/registry.js +29 -151
  97. package/dist/functions/source.js +42 -2
  98. package/dist/index.js +1 -1
  99. package/dist/init/auth.js +3 -3
  100. package/dist/init/link.js +2 -2
  101. package/dist/init/run.js +3 -3
  102. package/dist/init/tooling.js +3 -3
  103. package/dist/mcp/mint.js +1 -1
  104. package/dist/test_utils/registry.js +1 -2
  105. package/dist/utils/package_manager.js +1 -0
  106. package/package.json +4 -2
@@ -1,822 +1 @@
1
- import { t as __exportAll } from "../_chunks/rolldown-runtime-8H4AJuhK.js";
2
- import { codeFromBody, isNeonApiError, retryOnLock } from "../api.js";
3
- import { stripAnsi } from "../human_table.js";
4
- import { writer } from "../writer.js";
5
- import { noPassthrough, single } from "../utils/flags.js";
6
- import { NeonAuthEmailVerificationMethod, NeonAuthOauthProviderId, NeonAuthOauthProviderType, NeonAuthSupportedAuthProvider } from "../utils/api_enums.js";
7
- import { branchIdFromProps, fillSingleProject, resolveBranchFromProps } from "../utils/enrichers.js";
8
- import chalk from "chalk";
9
- //#region src/commands/neon_auth.ts
10
- var neon_auth_exports = /* @__PURE__ */ __exportAll({
11
- builder: () => builder,
12
- command: () => command,
13
- describe: () => describe,
14
- handler: () => handler
15
- });
16
- const writeStyled = (text, stream = process.stdout) => {
17
- stream.write(process.env.NO_COLOR ? stripAnsi(text) : text);
18
- };
19
- const printKvBlock = (title, entries) => {
20
- const labels = entries.map(([key]) => key.trimEnd());
21
- const width = Math.max(0, ...labels.map((label) => label.length));
22
- let text = `\n${chalk.green(title)}\n`;
23
- entries.forEach(([, value], i) => {
24
- text += ` ${chalk.green(labels[i].padEnd(width))} ${value ?? ""}\n`;
25
- });
26
- writeStyled(`${text}\n`);
27
- };
28
- const printMessage = (message) => {
29
- writeStyled(`\n${chalk.green(message)}\n\n`);
30
- };
31
- const INTEGRATION_RESPONSE_FIELDS = [
32
- "auth_provider",
33
- "db_name",
34
- "base_url",
35
- "schema_name",
36
- "table_name",
37
- "jwks_url"
38
- ];
39
- const INTEGRATION_STATUS_FIELDS = [
40
- "auth_provider",
41
- "branch_id",
42
- "db_name",
43
- "base_url",
44
- "created_at",
45
- "jwks_url"
46
- ];
47
- const OAUTH_PROVIDER_FIELDS = [
48
- "id",
49
- "type",
50
- "client_id"
51
- ];
52
- const ALLOW_LOCALHOST_FIELDS = ["allow_localhost"];
53
- const SUPPORTED_OAUTH_PROVIDERS = [
54
- NeonAuthOauthProviderId.Google,
55
- NeonAuthOauthProviderId.Github,
56
- NeonAuthOauthProviderId.Vercel
57
- ];
58
- const DOMAIN_FIELDS = ["domain"];
59
- const EMAIL_PASSWORD_FIELDS = [
60
- "enabled",
61
- "email_verification_method",
62
- "require_email_verification",
63
- "auto_sign_in_after_verification",
64
- "send_verification_email_on_sign_up",
65
- "send_verification_email_on_sign_in",
66
- "disable_sign_up"
67
- ];
68
- const EMAIL_PROVIDER_FIELDS = [
69
- "type",
70
- "host",
71
- "port",
72
- "username",
73
- "sender_email",
74
- "sender_name"
75
- ];
76
- const ORGANIZATION_FIELDS = [
77
- "enabled",
78
- "organization_limit",
79
- "creator_role"
80
- ];
81
- const WEBHOOK_FIELDS = [
82
- "enabled",
83
- "webhook_url",
84
- "enabled_events",
85
- "timeout_seconds"
86
- ];
87
- const TEST_EMAIL_FIELDS = ["success", "error_message"];
88
- const command = "neon-auth";
89
- const describe = "Manage Neon Auth";
90
- const builder = (argv) => {
91
- return argv.usage("$0 neon-auth <sub-command> [options]").options({
92
- "project-id": {
93
- describe: "Project ID",
94
- type: "string"
95
- },
96
- branch: {
97
- describe: "Branch ID or name",
98
- type: "string"
99
- }
100
- }).middleware(fillSingleProject).command("enable", "Enable Neon Auth on a branch", (yargs) => yargs.options({ "database-name": {
101
- describe: "Database name to use for auth data",
102
- type: "string"
103
- } }), async (args) => {
104
- await enable(args);
105
- }).command("status", "Get Neon Auth status for a branch", (yargs) => yargs, async (args) => {
106
- await status(args);
107
- }).command("disable", "Disable Neon Auth on a branch", (yargs) => yargs.options({ "delete-data": {
108
- describe: "Permanently delete all Neon Auth data and schema from the database",
109
- type: "boolean",
110
- default: false
111
- } }), async (args) => {
112
- await disable(args);
113
- }).command("oauth-provider", "Manage OAuth providers", (yargs) => {
114
- return yargs.usage("$0 neon-auth oauth-provider <sub-command> [options]").command("list", "List OAuth providers", (yargs) => yargs, async (args) => {
115
- await oauthProviderList(args);
116
- }).command("add", "Add an OAuth provider", (yargs) => yargs.options({
117
- "provider-id": {
118
- describe: `OAuth provider ID. Supported values: ${SUPPORTED_OAUTH_PROVIDERS.join(", ")}`,
119
- type: "string",
120
- choices: SUPPORTED_OAUTH_PROVIDERS,
121
- demandOption: true
122
- },
123
- "oauth-client-id": {
124
- describe: "OAuth client ID from your provider app. Omit to use Neon's shared OAuth app.",
125
- type: "string"
126
- },
127
- "oauth-client-secret": {
128
- describe: "OAuth client secret from your provider app. Omit to use Neon's shared OAuth app.",
129
- type: "string"
130
- }
131
- }), async (args) => {
132
- await oauthProviderAdd(args);
133
- }).command("update", "Update an OAuth provider", (yargs) => yargs.options({
134
- "provider-id": {
135
- describe: `OAuth provider ID. Supported values: ${SUPPORTED_OAUTH_PROVIDERS.join(", ")}`,
136
- type: "string",
137
- choices: SUPPORTED_OAUTH_PROVIDERS,
138
- demandOption: true
139
- },
140
- "oauth-client-id": {
141
- describe: "OAuth client ID from your provider app. Omit to use Neon's shared OAuth app.",
142
- type: "string"
143
- },
144
- "oauth-client-secret": {
145
- describe: "OAuth client secret from your provider app. Omit to use Neon's shared OAuth app.",
146
- type: "string"
147
- }
148
- }), async (args) => {
149
- await oauthProviderUpdate(args);
150
- }).command("delete", "Delete an OAuth provider", (yargs) => yargs.options({ "provider-id": {
151
- describe: `OAuth provider ID. Supported values: ${SUPPORTED_OAUTH_PROVIDERS.join(", ")}`,
152
- type: "string",
153
- choices: SUPPORTED_OAUTH_PROVIDERS,
154
- demandOption: true
155
- } }), async (args) => {
156
- await oauthProviderDelete(args);
157
- });
158
- }).command("domain", "Manage redirect URI trusted domains", (yargs) => {
159
- return yargs.usage("$0 neon-auth domain <sub-command> [options]").command("list", "List trusted domains", (yargs) => yargs, async (args) => {
160
- await domainList(args);
161
- }).command("add <domain>", "Add a trusted domain", (yargs) => yargs.usage("$0 neon-auth domain add <domain> [options]").positional("domain", {
162
- describe: "Domain to add",
163
- type: "string",
164
- demandOption: true
165
- }), async (args) => {
166
- await domainAdd(args);
167
- }).command("delete <domain>", "Delete a trusted domain", (yargs) => yargs.usage("$0 neon-auth domain delete <domain> [options]").positional("domain", {
168
- describe: "Domain to delete",
169
- type: "string",
170
- demandOption: true
171
- }), async (args) => {
172
- await domainDelete(args);
173
- }).command("allow-localhost", "Manage localhost connection settings", (yargs) => yargs.usage("$0 neon-auth domain allow-localhost <sub-command> [options]").command("get", "Get localhost connection setting", (yargs) => yargs, async (args) => {
174
- await allowLocalhostGet(args);
175
- }).command("enable", "Allow localhost connections", (yargs) => yargs, async (args) => {
176
- await allowLocalhostEnable(args);
177
- }).command("disable", "Restrict localhost connections", (yargs) => yargs, async (args) => {
178
- await allowLocalhostDisable(args);
179
- }));
180
- }).command("config", "Manage Neon Auth configuration", (yargs) => {
181
- return yargs.usage("$0 neon-auth config <sub-command> [options]").command("email-password", "Manage email and password authentication settings", (yargs) => {
182
- return yargs.usage("$0 neon-auth config email-password <sub-command> [options]").command("get", "Get email and password config", (yargs) => yargs, async (args) => {
183
- await emailPasswordGet(args);
184
- }).command("update", "Update email and password config", (yargs) => yargs.options({
185
- enabled: {
186
- describe: "Enable email and password authentication",
187
- type: "boolean"
188
- },
189
- "email-verification-method": {
190
- describe: "Email verification method",
191
- type: "string",
192
- choices: Object.values(NeonAuthEmailVerificationMethod)
193
- },
194
- "require-email-verification": {
195
- describe: "Require email verification before users can sign in",
196
- type: "boolean"
197
- },
198
- "auto-sign-in-after-verification": {
199
- describe: "Auto sign in users after verifying their email",
200
- type: "boolean"
201
- },
202
- "send-verification-email-on-sign-up": {
203
- describe: "Send verification email on sign up",
204
- type: "boolean"
205
- },
206
- "send-verification-email-on-sign-in": {
207
- describe: "Send verification email on sign in",
208
- type: "boolean"
209
- },
210
- "disable-sign-up": {
211
- describe: "Disable new user sign ups",
212
- type: "boolean"
213
- }
214
- }), async (args) => {
215
- await emailPasswordUpdate(args);
216
- });
217
- }).command("email-provider", "Manage email provider configuration", (yargs) => {
218
- return yargs.usage("$0 neon-auth config email-provider <sub-command> [options]").command("get", "Get email provider config", (yargs) => yargs, async (args) => {
219
- await emailProviderGet(args);
220
- }).command("update", "Update email provider config", (yargs) => yargs.options({
221
- type: {
222
- describe: "Email provider type",
223
- type: "string",
224
- choices: ["standard", "shared"],
225
- demandOption: true
226
- },
227
- host: {
228
- describe: "SMTP host (required for standard)",
229
- type: "string"
230
- },
231
- port: {
232
- describe: "SMTP port (required for standard)",
233
- type: "number"
234
- },
235
- username: {
236
- describe: "SMTP username (required for standard)",
237
- type: "string"
238
- },
239
- password: {
240
- describe: "SMTP password (required for standard)",
241
- type: "string"
242
- },
243
- "sender-email": {
244
- describe: "Sender email address",
245
- type: "string"
246
- },
247
- "sender-name": {
248
- describe: "Sender display name",
249
- type: "string"
250
- }
251
- }), async (args) => {
252
- await emailProviderUpdate(args);
253
- }).command("test", "Send a test message through the saved custom SMTP provider", (yargs) => yargs.options({ "recipient-email": {
254
- describe: "Email address to deliver the test message to",
255
- type: "string",
256
- demandOption: true,
257
- coerce: single("recipient-email", { required: true })
258
- } }).strict().check(noPassthrough("neon-auth config email-provider test")).epilogue([
259
- "Save the provider first with",
260
- "`neon neon-auth config email-provider update --type standard`.",
261
- "A shared provider, a missing configuration, or a",
262
- "non-Better-Auth integration is rejected by the API."
263
- ].join("\n")), async (args) => {
264
- await emailProviderTest(args);
265
- });
266
- }).command("organization", "Manage organization plugin settings", (yargs) => {
267
- return yargs.usage("$0 neon-auth config organization <sub-command> [options]").command("get", "Get organization plugin config", (yargs) => yargs, async (args) => {
268
- await organizationGet(args);
269
- }).command("update", "Update organization plugin config", (yargs) => yargs.options({
270
- enabled: {
271
- describe: "Enable the organization plugin",
272
- type: "boolean"
273
- },
274
- limit: {
275
- describe: "Maximum number of organizations a user can create",
276
- type: "number"
277
- },
278
- "creator-role": {
279
- describe: "Role assigned to organization creator",
280
- type: "string",
281
- choices: ["admin", "owner"]
282
- }
283
- }), async (args) => {
284
- await organizationUpdate(args);
285
- });
286
- }).command("webhook", "Manage webhook configuration", (yargs) => {
287
- return yargs.usage("$0 neon-auth config webhook <sub-command> [options]").command("get", "Get webhook config", (yargs) => yargs, async (args) => {
288
- await webhookGet(args);
289
- }).command("update", "Update webhook config", (yargs) => yargs.options({
290
- enabled: {
291
- describe: "Enable webhooks",
292
- type: "boolean",
293
- demandOption: true
294
- },
295
- url: {
296
- describe: "Webhook endpoint URL",
297
- type: "string"
298
- },
299
- "enabled-events": {
300
- describe: "Events to enable",
301
- type: "string",
302
- choices: [
303
- "user.before_create",
304
- "user.created",
305
- "send.otp",
306
- "send.magic_link"
307
- ],
308
- array: true
309
- },
310
- timeout: {
311
- describe: "Webhook timeout in seconds (1-10)",
312
- type: "number"
313
- }
314
- }), async (args) => {
315
- await webhookUpdate(args);
316
- });
317
- });
318
- }).command("plugins", "View Neon Auth plugin configurations", (yargs) => {
319
- return yargs.usage("$0 neon-auth plugins <sub-command> [options]").command("list", "List all plugin configurations", (yargs) => yargs, async (args) => {
320
- await pluginsList(args);
321
- }).command("get <plugin-name>", "Get a specific plugin configuration", (yargs) => yargs.usage("$0 neon-auth plugins get <plugin-name> [options]").positional("plugin-name", {
322
- describe: "Plugin name (e.g. organization, email_provider, email_and_password, oauth_providers, allow_localhost)",
323
- type: "string",
324
- demandOption: true
325
- }), async (args) => {
326
- await pluginsGet(args);
327
- });
328
- }).command("user", "Manage Neon Auth users", (yargs) => {
329
- return yargs.usage("$0 neon-auth user <sub-command> [options]").command("create", "Create an auth user", (yargs) => yargs.options({
330
- email: {
331
- describe: "User email address",
332
- type: "string",
333
- demandOption: true
334
- },
335
- name: {
336
- describe: "User display name (defaults to email if not provided)",
337
- type: "string"
338
- }
339
- }), async (args) => {
340
- await userCreate(args);
341
- }).command("delete <user-id>", "Delete an auth user", (yargs) => yargs.usage("$0 neon-auth user delete <user-id> [options]").positional("user-id", {
342
- describe: "ID of the user to delete",
343
- type: "string",
344
- demandOption: true
345
- }), async (args) => {
346
- await userDelete(args);
347
- }).command("set-role <user-id>", "Set roles for an auth user", (yargs) => yargs.usage("$0 neon-auth user set-role <user-id> [options]").positional("user-id", {
348
- describe: "ID of the user to update",
349
- type: "string",
350
- demandOption: true
351
- }).options({ roles: {
352
- describe: "Roles to assign",
353
- type: "string",
354
- array: true,
355
- demandOption: true
356
- } }), async (args) => {
357
- await userSetRole(args);
358
- });
359
- });
360
- };
361
- const handler = (args) => {
362
- return args;
363
- };
364
- const resolveBranch = async (props) => {
365
- return props.branchId ?? await branchIdFromProps(props);
366
- };
367
- /** The branch name is only known when it was resolved from a listing, not from an id. */
368
- const resolveBranchWithName = async (props) => {
369
- if (props.branchId) return { branchId: props.branchId };
370
- const { branchId, branch } = await resolveBranchFromProps(props);
371
- return {
372
- branchId,
373
- branchName: branch?.name
374
- };
375
- };
376
- const enable = async (props) => {
377
- const branchId = await resolveBranch(props);
378
- let data;
379
- let alreadyEnabled = false;
380
- try {
381
- ({data} = await retryOnLock(() => props.apiClient.createNeonAuth(props.projectId, branchId, {
382
- auth_provider: NeonAuthSupportedAuthProvider.BetterAuth,
383
- database_name: props.databaseName
384
- })));
385
- } catch (err) {
386
- if (!(isNeonApiError(err) && err.status === 409)) throw err;
387
- try {
388
- ({data} = await props.apiClient.getNeonAuth(props.projectId, branchId));
389
- } catch (readErr) {
390
- if (isNeonApiError(readErr) && readErr.status === 404) throw err;
391
- throw readErr;
392
- }
393
- alreadyEnabled = true;
394
- }
395
- if (props.output === "json" || props.output === "yaml") {
396
- writer(props).end(data, { fields: INTEGRATION_RESPONSE_FIELDS });
397
- return;
398
- }
399
- const d = data;
400
- printKvBlock(alreadyEnabled ? "Neon Auth is already enabled" : "Neon Auth enabled", [
401
- ["Auth Provider:", data.auth_provider],
402
- ...d.db_name ? [["Database:", d.db_name]] : [],
403
- ["Base URL:", data.base_url],
404
- ...d.schema_name ? [["Schema Name:", d.schema_name]] : [],
405
- ...d.table_name ? [["Table Name:", d.table_name]] : [],
406
- ["JWKS URL:", data.jwks_url]
407
- ]);
408
- if (data.base_url) {
409
- writeStyled(` ${chalk.green("Set this environment variable in your application:")}\n`);
410
- writeStyled(` NEON_AUTH_BASE_URL=${data.base_url}\n\n`);
411
- }
412
- };
413
- const status = async (props) => {
414
- const { branchId, branchName } = await resolveBranchWithName(props);
415
- let data;
416
- try {
417
- ({data} = await props.apiClient.getNeonAuth(props.projectId, branchId));
418
- } catch (err) {
419
- if (isNeonApiError(err) && err.status === 404) {
420
- printMessage("Neon Auth is not configured for this branch");
421
- return;
422
- }
423
- throw err;
424
- }
425
- if (props.output === "json" || props.output === "yaml") {
426
- writer(props).end(data, { fields: INTEGRATION_STATUS_FIELDS });
427
- return;
428
- }
429
- printKvBlock("Neon Auth status", [
430
- ["Auth Provider:", data.auth_provider],
431
- ["Branch:", branchName ? `${branchName} (${data.branch_id})` : data.branch_id],
432
- ["Database:", data.db_name],
433
- ["Base URL:", data.base_url],
434
- ["Created At:", data.created_at],
435
- ["JWKS URL:", data.jwks_url]
436
- ]);
437
- };
438
- const disable = async (props) => {
439
- const branchId = await resolveBranch(props);
440
- await retryOnLock(() => props.apiClient.disableNeonAuth(props.projectId, branchId, { delete_data: props.deleteData }));
441
- printMessage("Neon Auth has been disabled");
442
- };
443
- const SHARED_PROVIDER_DISCLAIMER = "Shared keys are created by the Neon team for development only and should not be used for production apps. It helps you get started, but will show Neon branding (logo and name) on the OAuth consent screen.";
444
- const oauthProviderList = async (props) => {
445
- const branchId = await resolveBranch(props);
446
- const { data } = await props.apiClient.listBranchNeonAuthOauthProviders(props.projectId, branchId);
447
- if (data.providers.length === 0 && props.output === "table") {
448
- printMessage("No OAuth providers are configured for this branch.");
449
- return;
450
- }
451
- writer(props).end(data.providers, { fields: OAUTH_PROVIDER_FIELDS });
452
- if (data.providers.some((p) => p.type === NeonAuthOauthProviderType.Shared) && props.output === "table") writeStyled(`\n${chalk.yellow("Caution:")} ${SHARED_PROVIDER_DISCLAIMER}\n\n`);
453
- };
454
- const oauthProviderAdd = async (props) => {
455
- const branchId = await resolveBranch(props);
456
- const baseUrlRequest = callbackBaseUrl(props, branchId, props.providerId);
457
- let data;
458
- try {
459
- ({data} = await props.apiClient.addBranchNeonAuthOauthProvider(props.projectId, branchId, {
460
- id: props.providerId,
461
- client_id: props.oauthClientId,
462
- client_secret: props.oauthClientSecret
463
- }));
464
- } catch (err) {
465
- if (isNeonApiError(err) && codeFromBody(err.data) === "INVALID_SHARED_OAUTH_PROVIDER") throw new Error(`The "${props.providerId}" provider requires your own OAuth app credentials.\nRe-run with --oauth-client-id and --oauth-client-secret to provide them.\nCreate an OAuth app at your provider and use those credentials.`);
466
- throw err;
467
- }
468
- if (props.output === "json" || props.output === "yaml") writer(props).end(data, { fields: OAUTH_PROVIDER_FIELDS });
469
- else printKvBlock("OAuth provider added", [
470
- ["ID:", data.id],
471
- ["Type:", data.type],
472
- ...data.client_id ? [["Client ID:", data.client_id]] : []
473
- ]);
474
- printCallbackInstructions(props.providerId, await baseUrlRequest);
475
- };
476
- const oauthProviderUpdate = async (props) => {
477
- const branchId = await resolveBranch(props);
478
- const baseUrlRequest = callbackBaseUrl(props, branchId, props.providerId);
479
- let data;
480
- try {
481
- ({data} = await props.apiClient.updateBranchNeonAuthOauthProvider(props.projectId, branchId, props.providerId, {
482
- client_id: props.oauthClientId,
483
- client_secret: props.oauthClientSecret
484
- }));
485
- } catch (err) {
486
- if (isNeonApiError(err) && codeFromBody(err.data) === "INVALID_SHARED_OAUTH_PROVIDER") throw new Error(`The "${props.providerId}" provider requires your own OAuth app credentials.\nRe-run with --oauth-client-id and --oauth-client-secret to provide them.\nCreate an OAuth app at your provider and use those credentials.`);
487
- throw err;
488
- }
489
- if (props.output === "json" || props.output === "yaml") writer(props).end(data, { fields: OAUTH_PROVIDER_FIELDS });
490
- else printKvBlock("OAuth provider updated", [
491
- ["ID:", data.id],
492
- ["Type:", data.type],
493
- ...data.client_id ? [["Client ID:", data.client_id]] : []
494
- ]);
495
- printCallbackInstructions(props.providerId, await baseUrlRequest);
496
- };
497
- const CALLBACK_INSTRUCTIONS = {
498
- github: {
499
- lead: "Create an OAuth app in the GitHub Developer Portal and add the following authorization callback URL:",
500
- urlLabel: "callback/github"
501
- },
502
- vercel: {
503
- lead: "Create a Vercel App in your Vercel Dashboard and add the following authorization callback URL:",
504
- urlLabel: "callback/vercel"
505
- },
506
- google: {
507
- lead: "Get Google credentials by creating an OAuth client in Google Cloud Console > Credentials, and add the following authorized redirect URL:",
508
- urlLabel: "callback/google"
509
- }
510
- };
511
- /**
512
- * Starts the base-URL read for the callback instructions, or resolves to undefined when none
513
- * apply. It runs alongside the provider write (adding a provider does not change the base URL)
514
- * and never rejects: a failed read prints no instructions, as before.
515
- */
516
- const callbackBaseUrl = (props, branchId, providerId) => {
517
- if (!CALLBACK_INSTRUCTIONS[providerId]) return Promise.resolve(void 0);
518
- if (props.output === "json" || props.output === "yaml") return Promise.resolve(void 0);
519
- return props.apiClient.getNeonAuth(props.projectId, branchId).then(({ data }) => data.base_url, () => void 0);
520
- };
521
- const printCallbackInstructions = (providerId, baseUrl) => {
522
- const instructions = CALLBACK_INSTRUCTIONS[providerId];
523
- if (!instructions || !baseUrl) return;
524
- const callbackUrl = `${baseUrl.replace(/\/$/, "")}/${instructions.urlLabel}`;
525
- printKvBlock(instructions.lead, [["URL:", callbackUrl]]);
526
- };
527
- const oauthProviderDelete = async (props) => {
528
- const branchId = await resolveBranch(props);
529
- await props.apiClient.deleteBranchNeonAuthOauthProvider(props.projectId, branchId, props.providerId);
530
- printMessage(`OAuth provider "${props.providerId}" deleted`);
531
- };
532
- const domainList = async (props) => {
533
- const branchId = await resolveBranch(props);
534
- const { data } = await props.apiClient.listBranchNeonAuthTrustedDomains(props.projectId, branchId);
535
- if (data.domains.length === 0 && props.output === "table") {
536
- printMessage("No trusted domains are configured for this branch.");
537
- return;
538
- }
539
- writer(props).end(data.domains, { fields: DOMAIN_FIELDS });
540
- };
541
- const validateDomainUri = (domain) => {
542
- let url;
543
- try {
544
- url = new URL(domain);
545
- } catch {
546
- throw new Error(`Invalid domain URI "${domain}". Must be a full URI including scheme, e.g. https://${domain}`);
547
- }
548
- if (!["http:", "https:"].includes(url.protocol)) throw new Error(`Invalid domain URI "${domain}". Must use http or https scheme, e.g. https://${url.host}`);
549
- };
550
- const domainAdd = async (props) => {
551
- validateDomainUri(props.domain);
552
- const branchId = await resolveBranch(props);
553
- await props.apiClient.addBranchNeonAuthTrustedDomain(props.projectId, branchId, {
554
- domain: props.domain,
555
- auth_provider: NeonAuthSupportedAuthProvider.BetterAuth
556
- });
557
- printMessage(`Domain "${props.domain}" added`);
558
- };
559
- const domainDelete = async (props) => {
560
- validateDomainUri(props.domain);
561
- const branchId = await resolveBranch(props);
562
- const { data: existing } = await props.apiClient.listBranchNeonAuthTrustedDomains(props.projectId, branchId);
563
- if (!existing.domains.some((d) => d.domain === props.domain)) throw new Error(`Domain "${props.domain}" is not in the trusted domains list.`);
564
- await props.apiClient.deleteBranchNeonAuthTrustedDomain(props.projectId, branchId, {
565
- auth_provider: NeonAuthSupportedAuthProvider.BetterAuth,
566
- domains: [{ domain: props.domain }]
567
- });
568
- printMessage(`Domain "${props.domain}" deleted`);
569
- };
570
- const allowLocalhostGet = async (props) => {
571
- const branchId = await resolveBranch(props);
572
- const { data } = await props.apiClient.getNeonAuthAllowLocalhost(props.projectId, branchId);
573
- if (props.output === "json" || props.output === "yaml") {
574
- writer(props).end(data, { fields: ALLOW_LOCALHOST_FIELDS });
575
- return;
576
- }
577
- printKvBlock("Localhost connection settings", [["Allow localhost:", String(data.allow_localhost)]]);
578
- };
579
- const allowLocalhostEnable = async (props) => {
580
- const branchId = await resolveBranch(props);
581
- await props.apiClient.updateNeonAuthAllowLocalhost(props.projectId, branchId, { allow_localhost: true });
582
- printMessage("Localhost connections allowed");
583
- };
584
- const allowLocalhostDisable = async (props) => {
585
- const branchId = await resolveBranch(props);
586
- await props.apiClient.updateNeonAuthAllowLocalhost(props.projectId, branchId, { allow_localhost: false });
587
- printMessage("Localhost connections restricted");
588
- };
589
- const printEmailPasswordEntries = (data) => [
590
- ["Enabled:", String(data.enabled)],
591
- ["Verification Method:", data.email_verification_method],
592
- ["Require Verification:", String(data.require_email_verification)],
593
- ["Auto Sign In After Verify: ", String(data.auto_sign_in_after_verification)],
594
- ["Send Email On Sign Up: ", String(data.send_verification_email_on_sign_up)],
595
- ["Send Email On Sign In: ", String(data.send_verification_email_on_sign_in)],
596
- ["Disable Sign Up:", String(data.disable_sign_up)]
597
- ];
598
- const emailPasswordGet = async (props) => {
599
- const branchId = await resolveBranch(props);
600
- const { data } = await props.apiClient.getNeonAuthEmailAndPasswordConfig(props.projectId, branchId);
601
- if (props.output === "json" || props.output === "yaml") {
602
- writer(props).end(data, { fields: EMAIL_PASSWORD_FIELDS });
603
- return;
604
- }
605
- printKvBlock("Email & password auth configuration", printEmailPasswordEntries(data));
606
- };
607
- const emailPasswordUpdate = async (props) => {
608
- const branchId = await resolveBranch(props);
609
- const { data } = await props.apiClient.updateNeonAuthEmailAndPasswordConfig(props.projectId, branchId, {
610
- enabled: props.enabled,
611
- email_verification_method: props.emailVerificationMethod,
612
- require_email_verification: props.requireEmailVerification,
613
- auto_sign_in_after_verification: props.autoSignInAfterVerification,
614
- send_verification_email_on_sign_up: props.sendVerificationEmailOnSignUp,
615
- send_verification_email_on_sign_in: props.sendVerificationEmailOnSignIn,
616
- disable_sign_up: props.disableSignUp
617
- });
618
- if (props.output === "json" || props.output === "yaml") {
619
- writer(props).end(data, { fields: EMAIL_PASSWORD_FIELDS });
620
- return;
621
- }
622
- printKvBlock("Email & password auth configuration updated", printEmailPasswordEntries(data));
623
- };
624
- const printEmailProviderEntries = (data) => [
625
- ["Type:", data.type],
626
- ...data.type === "standard" ? [
627
- ["Host:", data.host],
628
- ["Port: ", data.port != null ? String(data.port) : void 0],
629
- ["Username:", data.username]
630
- ] : [],
631
- ["Sender Email:", data.sender_email],
632
- ["Sender Name:", data.sender_name]
633
- ];
634
- const emailProviderGet = async (props) => {
635
- const branchId = await resolveBranch(props);
636
- const { data } = await props.apiClient.getNeonAuthEmailProvider(props.projectId, branchId);
637
- if (props.output === "json" || props.output === "yaml") {
638
- writer(props).end(data, { fields: EMAIL_PROVIDER_FIELDS });
639
- return;
640
- }
641
- printKvBlock("Email provider configuration", printEmailProviderEntries(data));
642
- };
643
- const emailProviderUpdate = async (props) => {
644
- if (props.type === "standard" && (!props.host || !props.port || !props.username || !props.password)) throw new Error("--host, --port, --username, and --password are required for standard email provider");
645
- const warnSharedSender = props.type === "shared" && (props.senderEmail || props.senderName);
646
- const branchId = await resolveBranch(props);
647
- let config;
648
- if (props.type === "standard") config = {
649
- type: "standard",
650
- host: props.host,
651
- port: props.port,
652
- username: props.username,
653
- password: props.password,
654
- sender_email: props.senderEmail,
655
- sender_name: props.senderName
656
- };
657
- else config = { type: "shared" };
658
- const { data } = await props.apiClient.updateNeonAuthEmailProvider(props.projectId, branchId, config);
659
- if (props.output === "json" || props.output === "yaml") writer(props).end(data, { fields: EMAIL_PROVIDER_FIELDS });
660
- else printKvBlock("Email provider configuration updated", printEmailProviderEntries(data));
661
- if (warnSharedSender) writeStyled(`${chalk.yellow("Warning:")} --sender-email and --sender-name are ignored for the shared email provider. These values only take effect with --type standard.\n\n`, process.stderr);
662
- };
663
- const emailProviderTest = async (props) => {
664
- const branchId = await resolveBranch(props);
665
- const { data } = await props.apiClient.sendNeonAuthEmailProviderTest(props.projectId, branchId, { recipient_email: props.recipientEmail });
666
- if (props.output === "json" || props.output === "yaml") {
667
- writer(props).end(data, { fields: TEST_EMAIL_FIELDS });
668
- if (!data.success) throw new Error(emailProviderTestFailureMessage(props.recipientEmail, data.error_message));
669
- return;
670
- }
671
- if (data.success) {
672
- printMessage(`Test email dispatched to ${props.recipientEmail} using the custom SMTP provider saved on this branch.`);
673
- return;
674
- }
675
- throw new Error(emailProviderTestFailureMessage(props.recipientEmail, data.error_message));
676
- };
677
- const emailProviderTestFailureMessage = (recipientEmail, errorMessage) => {
678
- const header = `Test email could NOT be sent to ${recipientEmail} using the custom SMTP provider saved on this branch.`;
679
- return errorMessage ? `${header}\nUpstream error: ${errorMessage}` : header;
680
- };
681
- const printOrganizationEntries = (data) => [
682
- ["Enabled:", String(data.enabled)],
683
- ["Org Limit:", String(data.organization_limit)],
684
- ["Creator Role:", data.creator_role]
685
- ];
686
- const organizationGet = async (props) => {
687
- const branchId = await resolveBranch(props);
688
- const { data } = await props.apiClient.getNeonAuthPluginConfigs(props.projectId, branchId);
689
- const org = data.organization;
690
- if (!org) {
691
- if (props.output === "json" || props.output === "yaml") {
692
- writer(props).end({}, { fields: ORGANIZATION_FIELDS });
693
- return;
694
- }
695
- printMessage("No organization plugin config found.");
696
- return;
697
- }
698
- if (props.output === "json" || props.output === "yaml") {
699
- writer(props).end(org, { fields: ORGANIZATION_FIELDS });
700
- return;
701
- }
702
- printKvBlock("Organization configuration", printOrganizationEntries(org));
703
- };
704
- const organizationUpdate = async (props) => {
705
- const branchId = await resolveBranch(props);
706
- const { data } = await props.apiClient.updateNeonAuthOrganizationPlugin(props.projectId, branchId, {
707
- enabled: props.enabled,
708
- organization_limit: props.limit,
709
- creator_role: props.creatorRole
710
- });
711
- if (props.output === "json" || props.output === "yaml") {
712
- writer(props).end(data, { fields: ORGANIZATION_FIELDS });
713
- return;
714
- }
715
- printKvBlock("Organization configuration updated", printOrganizationEntries(data));
716
- };
717
- const printWebhookEntries = (data) => [
718
- ["Enabled:", String(data.enabled)],
719
- ["URL:", data.webhook_url ?? ""],
720
- ["Events:", (data.enabled_events ?? []).join(", ")],
721
- ["Timeout (sec): ", data.timeout_seconds != null ? String(data.timeout_seconds) : ""]
722
- ];
723
- const webhookGet = async (props) => {
724
- const branchId = await resolveBranch(props);
725
- const { data } = await props.apiClient.getNeonAuthWebhookConfig(props.projectId, branchId);
726
- if (props.output === "json" || props.output === "yaml") {
727
- writer(props).end(data, { fields: WEBHOOK_FIELDS });
728
- return;
729
- }
730
- printKvBlock("Webhook configuration", printWebhookEntries(data));
731
- };
732
- const webhookUpdate = async (props) => {
733
- const branchId = await resolveBranch(props);
734
- const { data } = await props.apiClient.updateNeonAuthWebhookConfig(props.projectId, branchId, {
735
- enabled: props.enabled,
736
- webhook_url: props.url,
737
- enabled_events: props.enabledEvents,
738
- timeout_seconds: props.timeout
739
- });
740
- if (props.output === "json" || props.output === "yaml") {
741
- writer(props).end(data, { fields: WEBHOOK_FIELDS });
742
- return;
743
- }
744
- printKvBlock("Webhook configuration updated", printWebhookEntries(data));
745
- };
746
- const pluginTitle = (name) => name.replace(/_/g, " ").replace(/^\w/, (c) => c.toUpperCase()) + " configuration";
747
- const formatValue = (v) => {
748
- if (v == null) return "";
749
- if (typeof v === "string") return v;
750
- if (typeof v === "number" || typeof v === "boolean") return String(v);
751
- return JSON.stringify(v);
752
- };
753
- const pluginsList = async (props) => {
754
- const branchId = await resolveBranch(props);
755
- const { data } = await props.apiClient.getNeonAuthPluginConfigs(props.projectId, branchId);
756
- if (props.output === "json" || props.output === "yaml") {
757
- writer(props).end(data, { fields: Object.keys(data) });
758
- return;
759
- }
760
- const summarize = (value) => {
761
- if (value == null) return "not configured";
762
- if (typeof value === "boolean") return String(value);
763
- if (typeof value === "string") return value;
764
- if (typeof value === "number") return String(value);
765
- if (Array.isArray(value)) return value.length === 1 ? "1 item" : `${String(value.length)} items`;
766
- if (typeof value === "object") {
767
- const obj = value;
768
- if ("enabled" in obj) return obj.enabled ? "enabled" : "disabled";
769
- if ("type" in obj) return formatValue(obj.type);
770
- }
771
- return JSON.stringify(value);
772
- };
773
- const entries = Object.entries(data).map(([key, value]) => [key, summarize(value)]);
774
- printKvBlock("Neon Auth plugins", entries);
775
- };
776
- const pluginsGet = async (props) => {
777
- const branchId = await resolveBranch(props);
778
- const { data } = await props.apiClient.getNeonAuthPluginConfigs(props.projectId, branchId);
779
- const plugin = data[props.pluginName];
780
- if (plugin === void 0) {
781
- const available = Object.keys(data).join(", ");
782
- throw new Error(`Unknown plugin "${props.pluginName}". Available plugins: ${available}`);
783
- }
784
- if (props.output === "json" || props.output === "yaml") {
785
- const fields = typeof plugin === "object" && !Array.isArray(plugin) ? Object.keys(plugin) : [];
786
- writer(props).end(plugin, { fields });
787
- return;
788
- }
789
- if (typeof plugin === "object" && !Array.isArray(plugin) && plugin != null) {
790
- const entries = Object.entries(plugin).map(([k, v]) => [`${k}:`, formatValue(v)]);
791
- printKvBlock(pluginTitle(props.pluginName), entries);
792
- } else if (Array.isArray(plugin)) {
793
- const entries = plugin.map((item, i) => [`[${i}]:`, typeof item === "object" ? JSON.stringify(item) : String(item)]);
794
- printKvBlock(pluginTitle(props.pluginName), entries);
795
- } else printKvBlock(pluginTitle(props.pluginName), [["Value:", String(plugin)]]);
796
- };
797
- const userCreate = async (props) => {
798
- const branchId = await resolveBranch(props);
799
- const requestBody = {
800
- email: props.email,
801
- name: props.name ?? props.email
802
- };
803
- const { data } = await props.apiClient.createBranchNeonAuthNewUser(props.projectId, branchId, requestBody);
804
- const displayName = requestBody.name !== props.email ? requestBody.name : void 0;
805
- printKvBlock("User created", [
806
- ["ID:", data.id],
807
- ["Email:", requestBody.email],
808
- ...displayName ? [["Name:", displayName]] : []
809
- ]);
810
- };
811
- const userDelete = async (props) => {
812
- const branchId = await resolveBranch(props);
813
- await props.apiClient.deleteBranchNeonAuthUser(props.projectId, branchId, props.userId);
814
- printMessage(`User "${props.userId}" deleted`);
815
- };
816
- const userSetRole = async (props) => {
817
- const branchId = await resolveBranch(props);
818
- const { data } = await props.apiClient.updateNeonAuthUserRole(props.projectId, branchId, props.userId, { roles: props.roles });
819
- printKvBlock("Roles updated", [["User ID:", data.id], ["Roles:", props.roles.join(", ")]]);
820
- };
821
- //#endregion
822
- export { builder, command, describe, handler, neon_auth_exports as t };
1
+ export { t as builder, n as command, r as describe, i as handler } from "../_chunks/neon_auth-CBs1_3qu.js";