deploro 0.3.3 → 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 +132 -0
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -493,6 +493,128 @@ async function tokenRevokeCommand(id, opts) {
493
493
  await apiRequestNoProject(`/api/auth/tokens/${encodeURIComponent(id)}`, { method: "DELETE" });
494
494
  console.log(`\u2713 Token ${id} revoked`);
495
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
+ }
496
618
 
497
619
  // src/commands/migrate.ts
498
620
  import { readFileSync as readFileSync2 } from "fs";
@@ -851,6 +973,16 @@ auth.command("whoami").description("Show the current identity, and \u2014 for a
851
973
  auth.command("users").description("List platform users").action(authUsersCommand);
852
974
  auth.command("invite <email>").description("Invite a user by email").option("--admin", "Grant admin role").action(authInviteCommand);
853
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);
854
986
  var token = program.command("token").description("Personal access token commands");
855
987
  token.command("list").description("List your personal access tokens").action(tokenListCommand);
856
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.3",
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": {