deploro 0.3.2 → 0.3.4

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 (2) hide show
  1. package/dist/index.js +148 -0
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -391,6 +391,21 @@ async function authInviteCommand(email, opts) {
391
391
  console.log(` Accept URL: ${data.acceptUrl}`);
392
392
  }
393
393
  }
394
+ async function authSiteUrlCommand(url, opts) {
395
+ const config = requireProject();
396
+ if (!url && !opts.clear) {
397
+ const data2 = await apiRequest(
398
+ `/api/projects/${config.projectId}/auth/settings`
399
+ );
400
+ console.log(data2.site_url ?? "(not set \u2014 confirmation links fall back to this project's own deployment URL)");
401
+ return;
402
+ }
403
+ const data = await apiRequest(
404
+ `/api/projects/${config.projectId}/auth/settings`,
405
+ { method: "PUT", body: JSON.stringify({ site_url: opts.clear ? null : url }) }
406
+ );
407
+ console.log(opts.clear ? "\u2713 Site URL cleared" : `\u2713 Site URL set to ${data.site_url}`);
408
+ }
394
409
  async function authWhoamiCommand() {
395
410
  requireConfig();
396
411
  const data = await apiRequestNoProject("/api/auth/whoami");
@@ -478,6 +493,128 @@ async function tokenRevokeCommand(id, opts) {
478
493
  await apiRequestNoProject(`/api/auth/tokens/${encodeURIComponent(id)}`, { method: "DELETE" });
479
494
  console.log(`\u2713 Token ${id} revoked`);
480
495
  }
496
+ function isEmailProvider(provider) {
497
+ return provider === "email" || provider === "email_password";
498
+ }
499
+ async function authProvidersListCommand() {
500
+ const config = requireProject();
501
+ const data = await apiRequest(
502
+ `/api/projects/${config.projectId}/auth/providers`
503
+ );
504
+ const known = [
505
+ "email",
506
+ "email_password",
507
+ "google",
508
+ "github",
509
+ "facebook",
510
+ "twitter",
511
+ "discord",
512
+ "microsoft",
513
+ "linkedin",
514
+ "slack",
515
+ "gitlab",
516
+ "twitch",
517
+ "spotify",
518
+ "reddit",
519
+ "dropbox",
520
+ "notion",
521
+ "apple"
522
+ ];
523
+ const byProvider = new Map(data.providers.map((p) => [p.provider, p]));
524
+ const rows = known.map((provider) => {
525
+ const row = byProvider.get(provider);
526
+ const enabled = row?.enabled ?? false;
527
+ const configured = isEmailProvider(provider) || !!(row?.client_id && row?.client_secret);
528
+ return {
529
+ provider,
530
+ status: enabled && configured ? "active" : enabled ? "setup required" : "disabled"
531
+ };
532
+ });
533
+ table(rows);
534
+ }
535
+ async function authProviderEnableCommand(provider, enabled) {
536
+ const config = requireProject();
537
+ await apiRequest(
538
+ `/api/projects/${config.projectId}/auth/providers/${encodeURIComponent(provider)}`,
539
+ { method: "PUT", body: JSON.stringify({ enabled }) }
540
+ );
541
+ console.log(`\u2713 ${provider} ${enabled ? "enabled" : "disabled"}`);
542
+ }
543
+ async function authProviderConfigureCommand(provider, opts) {
544
+ const config = requireProject();
545
+ if (isEmailProvider(provider)) {
546
+ console.error(
547
+ `'${provider}' doesn't take OAuth credentials \u2014 it just needs enabling.
548
+ Run: deploro auth providers enable ${provider}`
549
+ );
550
+ process.exit(1);
551
+ }
552
+ if (!opts.clientId || !opts.clientSecret) {
553
+ console.error("Both --client-id and --client-secret are required.");
554
+ process.exit(1);
555
+ }
556
+ if (provider === "apple" && (!opts.teamId || !opts.keyId)) {
557
+ console.error("Apple also requires --team-id and --key-id (--client-secret is the .p8 private key contents).");
558
+ process.exit(1);
559
+ }
560
+ await apiRequest(
561
+ `/api/projects/${config.projectId}/auth/providers/${encodeURIComponent(provider)}`,
562
+ {
563
+ method: "PUT",
564
+ body: JSON.stringify({
565
+ client_id: opts.clientId,
566
+ client_secret: opts.clientSecret,
567
+ ...provider === "apple" ? { extra_config: { team_id: opts.teamId, key_id: opts.keyId } } : {}
568
+ })
569
+ }
570
+ );
571
+ console.log(`\u2713 ${provider} credentials saved (still needs enabling \u2014 run: deploro auth providers enable ${provider})`);
572
+ }
573
+ async function authEndUsersListCommand(opts) {
574
+ const config = requireProject();
575
+ const page = Math.max(1, Number(opts.page ?? 1) || 1);
576
+ const data = await apiRequest(
577
+ `/api/projects/${config.projectId}/auth/users?page=${page}`
578
+ );
579
+ table(
580
+ data.users.map((u) => ({
581
+ id: u.id,
582
+ email: u.email ?? "",
583
+ name: u.name ?? "",
584
+ methods: u.providers.join(", "),
585
+ verified: u.email_verified,
586
+ lastLogin: u.last_login_at ? u.last_login_at.slice(0, 10) : "never"
587
+ }))
588
+ );
589
+ console.log(`
590
+ ${data.total} total end user(s), page ${data.page}`);
591
+ }
592
+ async function authEndUserAddCommand(email, opts) {
593
+ const config = requireProject();
594
+ const data = await apiRequest(
595
+ `/api/projects/${config.projectId}/auth/users`,
596
+ { method: "POST", body: JSON.stringify({ email, name: opts.name }) }
597
+ );
598
+ console.log(`\u2713 Added ${data.user.email}`);
599
+ console.log(" A confirmation email was sent \u2014 they can't sign in until they click the link (one time, first use only).");
600
+ }
601
+ async function authEndUserDeleteCommand(id, opts) {
602
+ const config = requireProject();
603
+ await confirmOrDie(`Delete end user ${id}? This removes every sign-in method and session linked to them.`, opts.yes);
604
+ await apiRequest(`/api/projects/${config.projectId}/auth/users/${encodeURIComponent(id)}`, { method: "DELETE" });
605
+ console.log(`\u2713 End user ${id} deleted`);
606
+ }
607
+ async function authStatsCommand() {
608
+ const config = requireProject();
609
+ const data = await apiRequest(`/api/projects/${config.projectId}/auth/stats`);
610
+ console.log(`Total end users : ${data.total_users}`);
611
+ console.log(`Active sessions : ${data.sessions_active}`);
612
+ console.log(`Providers enabled : ${data.providers_enabled}`);
613
+ if (data.users_by_provider.length > 0) {
614
+ console.log("\nBy sign-in method:");
615
+ table(data.users_by_provider.map((p) => ({ provider: p.provider, users: p.count })));
616
+ }
617
+ }
481
618
 
482
619
  // src/commands/migrate.ts
483
620
  import { readFileSync as readFileSync2 } from "fs";
@@ -835,6 +972,17 @@ var auth = program.command("auth").description("Auth management commands");
835
972
  auth.command("whoami").description("Show the current identity, and \u2014 for a token login \u2014 exactly what it's scoped to").action(authWhoamiCommand);
836
973
  auth.command("users").description("List platform users").action(authUsersCommand);
837
974
  auth.command("invite <email>").description("Invite a user by email").option("--admin", "Grant admin role").action(authInviteCommand);
975
+ auth.command("site-url [url]").description("Get or set the active project's Auth Site URL (where end-user confirmation-email links redirect back to)").option("--clear", "Clear the Site URL \u2014 confirmation links fall back to the project's own deployment URL").action(authSiteUrlCommand);
976
+ auth.command("stats").description("Show Auth-as-a-Service stats for the active project's end users").action(authStatsCommand);
977
+ var authProviders = auth.command("providers").description("Manage the active project's end-user sign-in providers");
978
+ authProviders.command("list").description("List sign-in providers and their status").action(authProvidersListCommand);
979
+ authProviders.command("enable <provider>").description("Enable a sign-in provider (e.g. email, email_password, google, github, apple, ...)").action((provider) => authProviderEnableCommand(provider, true));
980
+ authProviders.command("disable <provider>").description("Disable a sign-in provider").action((provider) => authProviderEnableCommand(provider, false));
981
+ authProviders.command("configure <provider>").description("Set OAuth client credentials for a provider (not applicable to email / email_password)").option("--client-id <id>", "OAuth client ID").option("--client-secret <secret>", "OAuth client secret (Apple: the .p8 private key contents)").option("--team-id <id>", "Apple only \u2014 Team ID").option("--key-id <id>", "Apple only \u2014 Key ID").action(authProviderConfigureCommand);
982
+ var authEndUsers = auth.command("end-users").description("Manage the active project's end users (your app's sign-ups)");
983
+ authEndUsers.command("list").description("List end users").option("--page <n>", "Page number", "1").action(authEndUsersListCommand);
984
+ authEndUsers.command("add <email>").description("Manually add an end user \u2014 sends a confirmation email; they can't sign in until they click it").option("--name <name>", "Display name").action(authEndUserAddCommand);
985
+ authEndUsers.command("delete <id>").description("Delete an end user and all their sign-in methods/sessions").option("--yes", "Skip confirmation prompt").action(authEndUserDeleteCommand);
838
986
  var token = program.command("token").description("Personal access token commands");
839
987
  token.command("list").description("List your personal access tokens").action(tokenListCommand);
840
988
  token.command("create <name>").description("Create a new project-scoped personal access token").option("--read", "Grant read scope").option("--write", "Grant write scope").option("--project <slugs>", "Comma-separated project slugs/ids/names (defaults to the active project)").option("--days <n>", "Expiry in days (1-365)", "90").action(tokenCreateCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deploro",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "Command-line interface for the Deploro developer platform — manage projects, databases, deployments, and hosting from your terminal.",
5
5
  "type": "module",
6
6
  "bin": {