@timbrix/cli 0.1.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.
Files changed (104) hide show
  1. package/README.md +319 -0
  2. package/bin/run.js +5 -0
  3. package/dist/commands/api-keys/create.d.ts +12 -0
  4. package/dist/commands/api-keys/create.d.ts.map +1 -0
  5. package/dist/commands/api-keys/create.js +65 -0
  6. package/dist/commands/api-keys/delete.d.ts +14 -0
  7. package/dist/commands/api-keys/delete.d.ts.map +1 -0
  8. package/dist/commands/api-keys/delete.js +55 -0
  9. package/dist/commands/api-keys/get.d.ts +13 -0
  10. package/dist/commands/api-keys/get.d.ts.map +1 -0
  11. package/dist/commands/api-keys/get.js +46 -0
  12. package/dist/commands/api-keys/list.d.ts +10 -0
  13. package/dist/commands/api-keys/list.d.ts.map +1 -0
  14. package/dist/commands/api-keys/list.js +61 -0
  15. package/dist/commands/login.d.ts +11 -0
  16. package/dist/commands/login.d.ts.map +1 -0
  17. package/dist/commands/login.js +67 -0
  18. package/dist/commands/logout.d.ts +7 -0
  19. package/dist/commands/logout.d.ts.map +1 -0
  20. package/dist/commands/logout.js +19 -0
  21. package/dist/commands/oauth-apps/create.d.ts +12 -0
  22. package/dist/commands/oauth-apps/create.d.ts.map +1 -0
  23. package/dist/commands/oauth-apps/create.js +96 -0
  24. package/dist/commands/oauth-apps/delete.d.ts +13 -0
  25. package/dist/commands/oauth-apps/delete.d.ts.map +1 -0
  26. package/dist/commands/oauth-apps/delete.js +49 -0
  27. package/dist/commands/oauth-apps/get.d.ts +10 -0
  28. package/dist/commands/oauth-apps/get.d.ts.map +1 -0
  29. package/dist/commands/oauth-apps/get.js +41 -0
  30. package/dist/commands/oauth-apps/list.d.ts +10 -0
  31. package/dist/commands/oauth-apps/list.d.ts.map +1 -0
  32. package/dist/commands/oauth-apps/list.js +55 -0
  33. package/dist/commands/organizations/create.d.ts +11 -0
  34. package/dist/commands/organizations/create.d.ts.map +1 -0
  35. package/dist/commands/organizations/create.js +69 -0
  36. package/dist/commands/organizations/delete.d.ts +13 -0
  37. package/dist/commands/organizations/delete.d.ts.map +1 -0
  38. package/dist/commands/organizations/delete.js +50 -0
  39. package/dist/commands/organizations/get.d.ts +10 -0
  40. package/dist/commands/organizations/get.d.ts.map +1 -0
  41. package/dist/commands/organizations/get.js +46 -0
  42. package/dist/commands/organizations/list.d.ts +7 -0
  43. package/dist/commands/organizations/list.d.ts.map +1 -0
  44. package/dist/commands/organizations/list.js +40 -0
  45. package/dist/commands/products/create.d.ts +17 -0
  46. package/dist/commands/products/create.d.ts.map +1 -0
  47. package/dist/commands/products/create.js +112 -0
  48. package/dist/commands/products/delete.d.ts +12 -0
  49. package/dist/commands/products/delete.d.ts.map +1 -0
  50. package/dist/commands/products/delete.js +52 -0
  51. package/dist/commands/products/get.d.ts +11 -0
  52. package/dist/commands/products/get.d.ts.map +1 -0
  53. package/dist/commands/products/get.js +54 -0
  54. package/dist/commands/products/list.d.ts +13 -0
  55. package/dist/commands/products/list.d.ts.map +1 -0
  56. package/dist/commands/products/list.js +75 -0
  57. package/dist/commands/products/update.d.ts +18 -0
  58. package/dist/commands/products/update.d.ts.map +1 -0
  59. package/dist/commands/products/update.js +86 -0
  60. package/dist/commands/update.d.ts +16 -0
  61. package/dist/commands/update.d.ts.map +1 -0
  62. package/dist/commands/update.js +91 -0
  63. package/dist/commands/webhooks/create.d.ts +11 -0
  64. package/dist/commands/webhooks/create.d.ts.map +1 -0
  65. package/dist/commands/webhooks/create.js +120 -0
  66. package/dist/commands/webhooks/delete.d.ts +14 -0
  67. package/dist/commands/webhooks/delete.d.ts.map +1 -0
  68. package/dist/commands/webhooks/delete.js +55 -0
  69. package/dist/commands/webhooks/get.d.ts +13 -0
  70. package/dist/commands/webhooks/get.d.ts.map +1 -0
  71. package/dist/commands/webhooks/get.js +45 -0
  72. package/dist/commands/webhooks/list.d.ts +10 -0
  73. package/dist/commands/webhooks/list.d.ts.map +1 -0
  74. package/dist/commands/webhooks/list.js +49 -0
  75. package/dist/config/auth.d.ts +31 -0
  76. package/dist/config/auth.d.ts.map +1 -0
  77. package/dist/config/auth.js +57 -0
  78. package/dist/help.d.ts +16 -0
  79. package/dist/help.d.ts.map +1 -0
  80. package/dist/help.js +22 -0
  81. package/dist/hooks/init/update-check.d.ts +8 -0
  82. package/dist/hooks/init/update-check.d.ts.map +1 -0
  83. package/dist/hooks/init/update-check.js +9 -0
  84. package/dist/index.d.ts +2 -0
  85. package/dist/index.d.ts.map +1 -0
  86. package/dist/index.js +1 -0
  87. package/dist/utils/client.d.ts +6 -0
  88. package/dist/utils/client.d.ts.map +1 -0
  89. package/dist/utils/client.js +18 -0
  90. package/dist/utils/error.d.ts +6 -0
  91. package/dist/utils/error.d.ts.map +1 -0
  92. package/dist/utils/error.js +15 -0
  93. package/dist/utils/logo.d.ts +14 -0
  94. package/dist/utils/logo.d.ts.map +1 -0
  95. package/dist/utils/logo.js +27 -0
  96. package/dist/utils/table.d.ts +6 -0
  97. package/dist/utils/table.d.ts.map +1 -0
  98. package/dist/utils/table.js +30 -0
  99. package/dist/utils/update-notifier.d.ts +13 -0
  100. package/dist/utils/update-notifier.d.ts.map +1 -0
  101. package/dist/utils/update-notifier.js +19 -0
  102. package/oclif.manifest.json +1054 -0
  103. package/package.json +71 -0
  104. package/theme.json +27 -0
@@ -0,0 +1,67 @@
1
+ import { input, password } from "@inquirer/prompts";
2
+ import { Command, Flags } from "@oclif/core";
3
+ import chalk from "chalk";
4
+ import ky from "ky";
5
+ import ora from "ora";
6
+ import { AuthManager } from "../config/auth.js";
7
+ import { getErrorMessage } from "../utils/error.js";
8
+ import { displayLogo } from "../utils/logo.js";
9
+ export default class Login extends Command {
10
+ static description = "Authenticate with Timbrix API";
11
+ static examples = [
12
+ "<%= config.bin %> <%= command.id %>",
13
+ "<%= config.bin %> <%= command.id %> --email user@example.com",
14
+ ];
15
+ static flags = {
16
+ email: Flags.string({
17
+ char: "e",
18
+ description: "Email address",
19
+ }),
20
+ "base-url": Flags.string({
21
+ char: "u",
22
+ description: "API base URL",
23
+ default: "http://localhost:3001/api",
24
+ }),
25
+ };
26
+ async run() {
27
+ const { flags } = await this.parse(Login);
28
+ // Display logo
29
+ displayLogo();
30
+ try {
31
+ // Get email
32
+ const email = flags.email ||
33
+ (await input({
34
+ message: "Email:",
35
+ validate: (value) => {
36
+ if (!value.includes("@")) {
37
+ return "Please enter a valid email address";
38
+ }
39
+ return true;
40
+ },
41
+ }));
42
+ // Get password
43
+ const userPassword = await password({
44
+ message: "Password:",
45
+ mask: "*",
46
+ });
47
+ // Authenticate
48
+ const spinner = ora("Authenticating...").start();
49
+ const response = await ky
50
+ .post(`${flags["base-url"]}/auth/login`, {
51
+ json: {
52
+ email,
53
+ password: userPassword,
54
+ },
55
+ })
56
+ .json();
57
+ // Save credentials
58
+ AuthManager.save(response.access_token, email, flags["base-url"]);
59
+ spinner.succeed(chalk.green("✓ Logged in successfully!"));
60
+ this.log(chalk.gray(`\nConfig saved to: ${AuthManager.getConfigPath()}`));
61
+ this.log(chalk.gray(`Authenticated as: ${email}`));
62
+ }
63
+ catch (error) {
64
+ this.error(chalk.red(`Authentication failed: ${getErrorMessage(error)}`));
65
+ }
66
+ }
67
+ }
@@ -0,0 +1,7 @@
1
+ import { Command } from "@oclif/core";
2
+ export default class Logout extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ run(): Promise<void>;
6
+ }
7
+ //# sourceMappingURL=logout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAIrC,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,OAAO;IACzC,OAAgB,WAAW,SAA4B;IAEvD,OAAgB,QAAQ,WAA0C;IAErD,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAclC"}
@@ -0,0 +1,19 @@
1
+ import { Command } from "@oclif/core";
2
+ import chalk from "chalk";
3
+ import { AuthManager } from "../config/auth.js";
4
+ export default class Logout extends Command {
5
+ static description = "Logout from Timbrix API";
6
+ static examples = ["<%= config.bin %> <%= command.id %>"];
7
+ async run() {
8
+ if (!AuthManager.isAuthenticated()) {
9
+ this.log(chalk.yellow("You are not logged in"));
10
+ return;
11
+ }
12
+ const email = AuthManager.getEmail();
13
+ AuthManager.clear();
14
+ this.log(chalk.green("✓ Logged out successfully!"));
15
+ if (email) {
16
+ this.log(chalk.gray(`Removed credentials for: ${email}`));
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,12 @@
1
+ import { Command } from "@oclif/core";
2
+ export default class OAuthAppsCreate extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
+ "redirect-uri": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ };
10
+ run(): Promise<void>;
11
+ }
12
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/oauth-apps/create.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAS,MAAM,aAAa,CAAA;AAmB5C,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,OAAO;IAClD,OAAgB,WAAW,SAAmC;IAE9D,OAAgB,QAAQ,WAGvB;IAED,OAAgB,KAAK;;;;MAapB;IAEY,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA4ElC"}
@@ -0,0 +1,96 @@
1
+ import { checkbox, input } from "@inquirer/prompts";
2
+ import { Command, Flags } from "@oclif/core";
3
+ import chalk from "chalk";
4
+ import ora from "ora";
5
+ import { createClient } from "../../utils/client.js";
6
+ import { getErrorMessage } from "../../utils/error.js";
7
+ const AVAILABLE_SCOPES = [
8
+ { value: "read:user", name: "Read user profile" },
9
+ { value: "write:user", name: "Write user profile" },
10
+ { value: "read:organization", name: "Read organization data" },
11
+ { value: "write:organization", name: "Write organization data" },
12
+ { value: "read:members", name: "Read organization members" },
13
+ { value: "write:members", name: "Manage organization members" },
14
+ { value: "read:webhooks", name: "Read webhooks" },
15
+ { value: "write:webhooks", name: "Manage webhooks" },
16
+ { value: "admin:organization", name: "Full organization admin access" },
17
+ ];
18
+ export default class OAuthAppsCreate extends Command {
19
+ static description = "Create a new OAuth application";
20
+ static examples = [
21
+ "<%= config.bin %> <%= command.id %>",
22
+ "<%= config.bin %> <%= command.id %> --name 'My Integration' --redirect-uri https://example.com/callback",
23
+ ];
24
+ static flags = {
25
+ name: Flags.string({
26
+ char: "n",
27
+ description: "Application name",
28
+ }),
29
+ description: Flags.string({
30
+ char: "d",
31
+ description: "Application description",
32
+ }),
33
+ "redirect-uri": Flags.string({
34
+ char: "r",
35
+ description: "Redirect URI for OAuth flow",
36
+ }),
37
+ };
38
+ async run() {
39
+ const { flags } = await this.parse(OAuthAppsCreate);
40
+ const client = createClient();
41
+ try {
42
+ const name = flags.name ||
43
+ (await input({
44
+ message: "Application name:",
45
+ validate: (value) => value.length >= 1 || "Name is required",
46
+ }));
47
+ const description = flags.description ||
48
+ (await input({
49
+ message: "Description (optional):",
50
+ }));
51
+ const redirectUri = flags["redirect-uri"] ||
52
+ (await input({
53
+ message: "Redirect URI (optional, required for Authorization Code flow):",
54
+ validate: (value) => {
55
+ if (!value)
56
+ return true;
57
+ try {
58
+ new URL(value);
59
+ return true;
60
+ }
61
+ catch {
62
+ return "Please enter a valid URL";
63
+ }
64
+ },
65
+ }));
66
+ const scopes = await checkbox({
67
+ message: "Select OAuth scopes:",
68
+ choices: AVAILABLE_SCOPES,
69
+ required: true,
70
+ });
71
+ if (scopes.length === 0) {
72
+ this.error("You must select at least one scope");
73
+ }
74
+ const spinner = ora("Creating OAuth app...").start();
75
+ const app = await client.oauth.createApp({
76
+ name,
77
+ description: description || undefined,
78
+ redirectUri: redirectUri || undefined,
79
+ scopes: scopes,
80
+ });
81
+ spinner.succeed(chalk.green("✓ OAuth app created successfully!"));
82
+ this.log(chalk.gray("\nOAuth App Details:"));
83
+ this.log(` ${chalk.bold("Client ID:")} ${app.clientId}`);
84
+ this.log(` ${chalk.bold("Client Secret:")} ${app.clientSecret}`);
85
+ this.log(` ${chalk.bold("Name:")} ${app.name}`);
86
+ this.log(` ${chalk.bold("Scopes:")} ${app.scopes.join(", ")}`);
87
+ if (app.redirectUri) {
88
+ this.log(` ${chalk.bold("Redirect URI:")} ${app.redirectUri}`);
89
+ }
90
+ this.log(chalk.yellow("\n⚠️ Save the client secret now — it won't be shown again!"));
91
+ }
92
+ catch (error) {
93
+ this.error(chalk.red(`Failed to create OAuth app: ${getErrorMessage(error)}`));
94
+ }
95
+ }
96
+ }
@@ -0,0 +1,13 @@
1
+ import { Command } from "@oclif/core";
2
+ export default class OAuthAppsDelete extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ clientId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
13
+ //# sourceMappingURL=delete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../../src/commands/oauth-apps/delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,aAAa,CAAA;AAOlD,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,OAAO;IAClD,OAAgB,WAAW,SAC0C;IAErE,OAAgB,QAAQ,WAGvB;IAED,OAAgB,IAAI;;MAKnB;IAED,OAAgB,KAAK;;MAMpB;IAEY,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA+BlC"}
@@ -0,0 +1,49 @@
1
+ import { Command, Args, Flags } from "@oclif/core";
2
+ import { confirm } from "@inquirer/prompts";
3
+ import chalk from "chalk";
4
+ import ora from "ora";
5
+ import { createClient } from "../../utils/client.js";
6
+ import { getErrorMessage } from "../../utils/error.js";
7
+ export default class OAuthAppsDelete extends Command {
8
+ static description = "Delete an OAuth application and revoke all its tokens (PERMANENT)";
9
+ static examples = [
10
+ "<%= config.bin %> <%= command.id %> app_abc123",
11
+ "<%= config.bin %> <%= command.id %> app_abc123 --force",
12
+ ];
13
+ static args = {
14
+ clientId: Args.string({
15
+ description: "OAuth application client ID",
16
+ required: true,
17
+ }),
18
+ };
19
+ static flags = {
20
+ force: Flags.boolean({
21
+ char: "f",
22
+ description: "Skip confirmation prompt",
23
+ default: false,
24
+ }),
25
+ };
26
+ async run() {
27
+ const { args, flags } = await this.parse(OAuthAppsDelete);
28
+ const client = createClient();
29
+ try {
30
+ if (!flags.force) {
31
+ const confirmed = await confirm({
32
+ message: chalk.yellow(`Delete OAuth app "${args.clientId}"? All associated tokens will be revoked. This cannot be undone.`),
33
+ default: false,
34
+ });
35
+ if (!confirmed) {
36
+ this.log(chalk.gray("Deletion cancelled"));
37
+ return;
38
+ }
39
+ }
40
+ const spinner = ora("Deleting OAuth app...").start();
41
+ await client.oauth.deleteApp(args.clientId);
42
+ spinner.succeed(chalk.green("✓ OAuth app deleted successfully!"));
43
+ this.log(chalk.gray("\nAll associated tokens have been revoked."));
44
+ }
45
+ catch (error) {
46
+ this.error(chalk.red(`Failed to delete OAuth app: ${getErrorMessage(error)}`));
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,10 @@
1
+ import { Command } from "@oclif/core";
2
+ export default class OAuthAppsGet extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ clientId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=get.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../../src/commands/oauth-apps/get.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,MAAM,aAAa,CAAA;AAM3C,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,OAAO;IAC/C,OAAgB,WAAW,SAAkC;IAE7D,OAAgB,QAAQ,WAAqD;IAE7E,OAAgB,IAAI;;MAKnB;IAEY,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAkClC"}
@@ -0,0 +1,41 @@
1
+ import { Command, Args } from "@oclif/core";
2
+ import chalk from "chalk";
3
+ import ora from "ora";
4
+ import { createClient } from "../../utils/client.js";
5
+ import { getErrorMessage } from "../../utils/error.js";
6
+ export default class OAuthAppsGet extends Command {
7
+ static description = "Get OAuth application details";
8
+ static examples = ["<%= config.bin %> <%= command.id %> app_abc123"];
9
+ static args = {
10
+ clientId: Args.string({
11
+ description: "OAuth application client ID",
12
+ required: true,
13
+ }),
14
+ };
15
+ async run() {
16
+ const { args } = await this.parse(OAuthAppsGet);
17
+ const client = createClient();
18
+ const spinner = ora("Fetching OAuth app...").start();
19
+ try {
20
+ const app = await client.oauth.getApp(args.clientId);
21
+ spinner.stop();
22
+ this.log(chalk.cyan.bold("\nOAuth App Details:"));
23
+ this.log(` ${chalk.bold("Client ID:")} ${app.clientId}`);
24
+ this.log(` ${chalk.bold("Name:")} ${app.name}`);
25
+ if (app.description) {
26
+ this.log(` ${chalk.bold("Description:")} ${app.description}`);
27
+ }
28
+ this.log(` ${chalk.bold("Scopes:")} ${app.scopes.join(", ")}`);
29
+ this.log(` ${chalk.bold("Active:")} ${app.isActive ? chalk.green("Yes") : chalk.red("No")}`);
30
+ if (app.redirectUri) {
31
+ this.log(` ${chalk.bold("Redirect URI:")} ${app.redirectUri}`);
32
+ }
33
+ this.log(` ${chalk.bold("Created:")} ${new Date(app.createdAt).toLocaleString()}`);
34
+ this.log(` ${chalk.bold("Updated:")} ${new Date(app.updatedAt).toLocaleString()}`);
35
+ }
36
+ catch (error) {
37
+ spinner.fail(chalk.red("Failed to fetch OAuth app"));
38
+ this.error(getErrorMessage(error));
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,10 @@
1
+ import { Command } from "@oclif/core";
2
+ export default class OAuthAppsList extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ org: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/oauth-apps/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAS,MAAM,aAAa,CAAA;AAQ5C,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,OAAO;IAChD,OAAgB,WAAW,SAAgD;IAE3E,OAAgB,QAAQ,WAEvB;IAED,OAAgB,KAAK;;MAMpB;IAEY,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA6ClC"}
@@ -0,0 +1,55 @@
1
+ import { Command, Flags } from "@oclif/core";
2
+ import chalk from "chalk";
3
+ import ora from "ora";
4
+ import { createClient } from "../../utils/client.js";
5
+ import { getErrorMessage } from "../../utils/error.js";
6
+ import { createTable, truncate } from "../../utils/table.js";
7
+ export default class OAuthAppsList extends Command {
8
+ static description = "List OAuth applications for an organization";
9
+ static examples = [
10
+ "<%= config.bin %> <%= command.id %> --org acme-corp-id",
11
+ ];
12
+ static flags = {
13
+ org: Flags.string({
14
+ char: "o",
15
+ description: "Organization ID",
16
+ required: true,
17
+ }),
18
+ };
19
+ async run() {
20
+ const { flags } = await this.parse(OAuthAppsList);
21
+ const client = createClient();
22
+ const spinner = ora("Fetching OAuth apps...").start();
23
+ try {
24
+ const apps = await client.oauth.listApps(flags.org);
25
+ spinner.stop();
26
+ if (apps.length === 0) {
27
+ this.log(chalk.yellow("No OAuth apps found"));
28
+ this.log(chalk.gray(`\nCreate an OAuth app with: timbrix oauth-apps create --org ${flags.org}`));
29
+ return;
30
+ }
31
+ const table = createTable([
32
+ "Client ID",
33
+ "Name",
34
+ "Scopes",
35
+ "Active",
36
+ "Created",
37
+ ]);
38
+ apps.forEach((app) => {
39
+ table.push([
40
+ truncate(app.clientId, 24),
41
+ truncate(app.name, 30),
42
+ app.scopes.length.toString(),
43
+ app.isActive ? chalk.green("✓") : chalk.red("✗"),
44
+ new Date(app.createdAt).toLocaleDateString(),
45
+ ]);
46
+ });
47
+ this.log(table.toString());
48
+ this.log(chalk.gray(`\nTotal: ${apps.length} OAuth app(s)`));
49
+ }
50
+ catch (error) {
51
+ spinner.fail(chalk.red("Failed to fetch OAuth apps"));
52
+ this.error(getErrorMessage(error));
53
+ }
54
+ }
55
+ }
@@ -0,0 +1,11 @@
1
+ import { Command } from "@oclif/core";
2
+ export default class OrganizationsCreate extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ slug: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
+ };
9
+ run(): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/organizations/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAS,MAAM,aAAa,CAAA;AAO5C,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,OAAO;IACtD,OAAgB,WAAW,SAA8B;IAEzD,OAAgB,QAAQ,WAGvB;IAED,OAAgB,KAAK;;;MASpB;IAEY,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAuDlC"}
@@ -0,0 +1,69 @@
1
+ import { Command, Flags } from "@oclif/core";
2
+ import { input } from "@inquirer/prompts";
3
+ import { createClient } from "../../utils/client.js";
4
+ import { getErrorMessage } from "../../utils/error.js";
5
+ import chalk from "chalk";
6
+ import ora from "ora";
7
+ export default class OrganizationsCreate extends Command {
8
+ static description = "Create a new organization";
9
+ static examples = [
10
+ "<%= config.bin %> <%= command.id %>",
11
+ "<%= config.bin %> <%= command.id %> --name 'Acme Corp' --slug acme-corp",
12
+ ];
13
+ static flags = {
14
+ name: Flags.string({
15
+ char: "n",
16
+ description: "Organization name",
17
+ }),
18
+ slug: Flags.string({
19
+ char: "s",
20
+ description: "Organization slug (URL-friendly identifier)",
21
+ }),
22
+ };
23
+ async run() {
24
+ const { flags } = await this.parse(OrganizationsCreate);
25
+ const client = createClient();
26
+ try {
27
+ // Get organization name
28
+ const name = flags.name ||
29
+ (await input({
30
+ message: "Organization name:",
31
+ validate: (value) => {
32
+ if (value.length < 3) {
33
+ return "Name must be at least 3 characters";
34
+ }
35
+ return true;
36
+ },
37
+ }));
38
+ // Get slug
39
+ const slug = flags.slug ||
40
+ (await input({
41
+ message: "Organization slug:",
42
+ default: name
43
+ .toLowerCase()
44
+ .replace(/[^a-z0-9]+/g, "-")
45
+ .replace(/^-|-$/g, ""),
46
+ validate: (value) => {
47
+ if (!/^[a-z0-9-]+$/.test(value)) {
48
+ return "Slug must contain only lowercase letters, numbers, and hyphens";
49
+ }
50
+ return true;
51
+ },
52
+ }));
53
+ const spinner = ora("Creating organization...").start();
54
+ const organization = await client.organizations.create({
55
+ name,
56
+ slug,
57
+ });
58
+ spinner.succeed(chalk.green("✓ Organization created successfully!"));
59
+ this.log(chalk.gray("\nOrganization Details:"));
60
+ this.log(` ${chalk.bold("ID:")} ${organization.id}`);
61
+ this.log(` ${chalk.bold("Name:")} ${organization.name}`);
62
+ this.log(` ${chalk.bold("Slug:")} ${organization.slug}`);
63
+ this.log(` ${chalk.bold("Plan:")} ${organization.plan}`);
64
+ }
65
+ catch (error) {
66
+ this.error(chalk.red(`Failed to create organization: ${getErrorMessage(error)}`));
67
+ }
68
+ }
69
+ }
@@ -0,0 +1,13 @@
1
+ import { Command } from "@oclif/core";
2
+ export default class OrganizationsDelete extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ slug: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
13
+ //# sourceMappingURL=delete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../../src/commands/organizations/delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,aAAa,CAAA;AAOlD,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,OAAO;IACtD,OAAgB,WAAW,SAAuC;IAElE,OAAgB,QAAQ,WAGvB;IAED,OAAgB,IAAI;;MAKnB;IAED,OAAgB,KAAK;;MAMpB;IAEY,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAoClC"}
@@ -0,0 +1,50 @@
1
+ import { Command, Args, Flags } from "@oclif/core";
2
+ import { confirm } from "@inquirer/prompts";
3
+ import { createClient } from "../../utils/client.js";
4
+ import { getErrorMessage } from "../../utils/error.js";
5
+ import chalk from "chalk";
6
+ import ora from "ora";
7
+ export default class OrganizationsDelete extends Command {
8
+ static description = "Delete an organization (PERMANENT)";
9
+ static examples = [
10
+ "<%= config.bin %> <%= command.id %> acme-corp",
11
+ "<%= config.bin %> <%= command.id %> acme-corp --force",
12
+ ];
13
+ static args = {
14
+ slug: Args.string({
15
+ description: "Organization slug",
16
+ required: true,
17
+ }),
18
+ };
19
+ static flags = {
20
+ force: Flags.boolean({
21
+ char: "f",
22
+ description: "Skip confirmation prompt",
23
+ default: false,
24
+ }),
25
+ };
26
+ async run() {
27
+ const { args, flags } = await this.parse(OrganizationsDelete);
28
+ const client = createClient();
29
+ try {
30
+ // Confirm deletion
31
+ if (!flags.force) {
32
+ const confirmed = await confirm({
33
+ message: chalk.yellow(`Are you sure you want to delete organization '${args.slug}'? This action cannot be undone.`),
34
+ default: false,
35
+ });
36
+ if (!confirmed) {
37
+ this.log(chalk.gray("Deletion cancelled"));
38
+ return;
39
+ }
40
+ }
41
+ const spinner = ora("Deleting organization...").start();
42
+ await client.organizations.delete(args.slug);
43
+ spinner.succeed(chalk.green("✓ Organization deleted successfully!"));
44
+ this.log(chalk.gray("\nAll associated data (members, webhooks, API keys) has been removed."));
45
+ }
46
+ catch (error) {
47
+ this.error(chalk.red(`Failed to delete organization: ${getErrorMessage(error)}`));
48
+ }
49
+ }
50
+ }
@@ -0,0 +1,10 @@
1
+ import { Command } from "@oclif/core";
2
+ export default class OrganizationsGet extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=get.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../../src/commands/organizations/get.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,MAAM,aAAa,CAAA;AAM3C,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,OAAO;IACnD,OAAgB,WAAW,SAAmC;IAE9D,OAAgB,QAAQ,WAEvB;IAED,OAAgB,IAAI;;MAKnB;IAEY,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAqClC"}
@@ -0,0 +1,46 @@
1
+ import { Command, Args } from "@oclif/core";
2
+ import { createClient } from "../../utils/client.js";
3
+ import { getErrorMessage } from "../../utils/error.js";
4
+ import chalk from "chalk";
5
+ import ora from "ora";
6
+ export default class OrganizationsGet extends Command {
7
+ static description = "Get organization details by ID";
8
+ static examples = [
9
+ "<%= config.bin %> <%= command.id %> acme-corp-id",
10
+ ];
11
+ static args = {
12
+ id: Args.string({
13
+ description: "Organization ID",
14
+ required: true,
15
+ }),
16
+ };
17
+ async run() {
18
+ const { args } = await this.parse(OrganizationsGet);
19
+ const client = createClient();
20
+ const spinner = ora("Fetching organization...").start();
21
+ try {
22
+ const org = await client.organizations.get(args.id);
23
+ spinner.stop();
24
+ this.log(chalk.cyan.bold("\nOrganization Details:"));
25
+ this.log(` ${chalk.bold("ID:")} ${org.id}`);
26
+ this.log(` ${chalk.bold("Name:")} ${org.legal.name || chalk.gray("—")}`);
27
+ this.log(` ${chalk.bold("Slug:")} ${org.slug}`);
28
+ this.log(` ${chalk.bold("Production Ready:")} ${org.is_production_ready ? chalk.green("Yes") : chalk.yellow("No")}`);
29
+ this.log(` ${chalk.bold("Created:")} ${new Date(org.created_at).toLocaleString()}`);
30
+ this.log(` ${chalk.bold("Updated:")} ${new Date(org.updated_at).toLocaleString()}`);
31
+ if (org.logo_url) {
32
+ this.log(` ${chalk.bold("Logo:")} ${org.logo_url}`);
33
+ }
34
+ if (org.legal.rfc) {
35
+ this.log(` ${chalk.bold("RFC:")} ${org.legal.rfc}`);
36
+ }
37
+ if (org.legal.legal_name) {
38
+ this.log(` ${chalk.bold("Legal Name:")} ${org.legal.legal_name}`);
39
+ }
40
+ }
41
+ catch (error) {
42
+ spinner.fail(chalk.red("Failed to fetch organization"));
43
+ this.error(getErrorMessage(error));
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,7 @@
1
+ import { Command } from "@oclif/core";
2
+ export default class OrganizationsList extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ run(): Promise<void>;
6
+ }
7
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/organizations/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAQrC,MAAM,CAAC,OAAO,OAAO,iBAAkB,SAAQ,OAAO;IACpD,OAAgB,WAAW,SAA2B;IAEtD,OAAgB,QAAQ,WAA0C;IAErD,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAuClC"}