@bussolabs/closeyourit-cli 0.0.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 (99) hide show
  1. package/README.md +99 -0
  2. package/bin/run.js +2 -0
  3. package/dist/base.d.ts +34 -0
  4. package/dist/base.js +85 -0
  5. package/dist/commands/errors/list.d.ts +11 -0
  6. package/dist/commands/errors/list.js +36 -0
  7. package/dist/commands/errors/mute.d.ts +12 -0
  8. package/dist/commands/errors/mute.js +22 -0
  9. package/dist/commands/errors/reopen.d.ts +12 -0
  10. package/dist/commands/errors/reopen.js +22 -0
  11. package/dist/commands/errors/resolve.d.ts +12 -0
  12. package/dist/commands/errors/resolve.js +22 -0
  13. package/dist/commands/errors/show.d.ts +12 -0
  14. package/dist/commands/errors/show.js +23 -0
  15. package/dist/commands/errors/unmute.d.ts +12 -0
  16. package/dist/commands/errors/unmute.js +22 -0
  17. package/dist/commands/groups/create.d.ts +12 -0
  18. package/dist/commands/groups/create.js +31 -0
  19. package/dist/commands/groups/list.d.ts +9 -0
  20. package/dist/commands/groups/list.js +19 -0
  21. package/dist/commands/invitations/create.d.ts +12 -0
  22. package/dist/commands/invitations/create.js +38 -0
  23. package/dist/commands/invitations/list.d.ts +9 -0
  24. package/dist/commands/invitations/list.js +24 -0
  25. package/dist/commands/invitations/revoke.d.ts +9 -0
  26. package/dist/commands/invitations/revoke.js +20 -0
  27. package/dist/commands/login.d.ts +9 -0
  28. package/dist/commands/login.js +63 -0
  29. package/dist/commands/logout.d.ts +6 -0
  30. package/dist/commands/logout.js +17 -0
  31. package/dist/commands/members/list.d.ts +9 -0
  32. package/dist/commands/members/list.js +24 -0
  33. package/dist/commands/metrics/list.d.ts +11 -0
  34. package/dist/commands/metrics/list.js +36 -0
  35. package/dist/commands/metrics/show.d.ts +12 -0
  36. package/dist/commands/metrics/show.js +23 -0
  37. package/dist/commands/projects/create.d.ts +15 -0
  38. package/dist/commands/projects/create.js +49 -0
  39. package/dist/commands/projects/list.d.ts +9 -0
  40. package/dist/commands/projects/list.js +19 -0
  41. package/dist/commands/projects/set-environments.d.ts +11 -0
  42. package/dist/commands/projects/set-environments.js +42 -0
  43. package/dist/commands/projects/show.d.ts +9 -0
  44. package/dist/commands/projects/show.js +22 -0
  45. package/dist/commands/roles/create.d.ts +13 -0
  46. package/dist/commands/roles/create.js +36 -0
  47. package/dist/commands/roles/delete.d.ts +9 -0
  48. package/dist/commands/roles/delete.js +21 -0
  49. package/dist/commands/roles/list.d.ts +9 -0
  50. package/dist/commands/roles/list.js +23 -0
  51. package/dist/commands/roles/show.d.ts +9 -0
  52. package/dist/commands/roles/show.js +25 -0
  53. package/dist/commands/roles/update.d.ts +14 -0
  54. package/dist/commands/roles/update.js +44 -0
  55. package/dist/commands/teams/add-member.d.ts +10 -0
  56. package/dist/commands/teams/add-member.js +26 -0
  57. package/dist/commands/teams/create.d.ts +16 -0
  58. package/dist/commands/teams/create.js +50 -0
  59. package/dist/commands/teams/delete.d.ts +9 -0
  60. package/dist/commands/teams/delete.js +21 -0
  61. package/dist/commands/teams/list.d.ts +9 -0
  62. package/dist/commands/teams/list.js +27 -0
  63. package/dist/commands/teams/remove-member.d.ts +10 -0
  64. package/dist/commands/teams/remove-member.js +26 -0
  65. package/dist/commands/teams/show.d.ts +9 -0
  66. package/dist/commands/teams/show.js +27 -0
  67. package/dist/commands/teams/update.d.ts +17 -0
  68. package/dist/commands/teams/update.js +54 -0
  69. package/dist/commands/tickets/create.d.ts +18 -0
  70. package/dist/commands/tickets/create.js +51 -0
  71. package/dist/commands/tickets/list.d.ts +10 -0
  72. package/dist/commands/tickets/list.js +24 -0
  73. package/dist/commands/tickets/show.d.ts +12 -0
  74. package/dist/commands/tickets/show.js +23 -0
  75. package/dist/commands/tokens/create.d.ts +11 -0
  76. package/dist/commands/tokens/create.js +34 -0
  77. package/dist/commands/tokens/list.d.ts +9 -0
  78. package/dist/commands/tokens/list.js +25 -0
  79. package/dist/commands/tokens/revoke.d.ts +12 -0
  80. package/dist/commands/tokens/revoke.js +22 -0
  81. package/dist/commands/tokens/rotate.d.ts +12 -0
  82. package/dist/commands/tokens/rotate.js +28 -0
  83. package/dist/commands/whoami.d.ts +6 -0
  84. package/dist/commands/whoami.js +19 -0
  85. package/dist/errors/error-codes.d.ts +35 -0
  86. package/dist/errors/error-codes.js +40 -0
  87. package/dist/lib/api.d.ts +28 -0
  88. package/dist/lib/api.js +81 -0
  89. package/dist/lib/browser.d.ts +2 -0
  90. package/dist/lib/browser.js +32 -0
  91. package/dist/lib/config.d.ts +20 -0
  92. package/dist/lib/config.js +93 -0
  93. package/dist/lib/device-flow.d.ts +28 -0
  94. package/dist/lib/device-flow.js +62 -0
  95. package/dist/lib/output.d.ts +4 -0
  96. package/dist/lib/output.js +21 -0
  97. package/oclif.manifest.json +1954 -0
  98. package/opencli.json +229 -0
  99. package/package.json +34 -0
package/README.md ADDED
@@ -0,0 +1,99 @@
1
+ # closeyourit-cli
2
+
3
+ `closeyourit` (alias `cyi`) is the command-line interface for [CloseYourIt](https://www.closeyour.it).
4
+ Authenticate with your user token and manage projects, error monitoring, ingest tokens, tickets and
5
+ performance metrics straight from your terminal — handy for CI pipelines and SDK setup.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install -g @bussolabs/closeyourit-cli
11
+ # or run without installing
12
+ npx @bussolabs/closeyourit-cli --help
13
+ ```
14
+
15
+ ## Getting started
16
+
17
+ ```bash
18
+ closeyourit login # device flow: opens your browser, enter the shown code
19
+ closeyourit whoami # confirm who you are and which org/token is active
20
+ closeyourit projects list
21
+ ```
22
+
23
+ `login` uses the OAuth 2.0 device authorization grant: it prints a short user code and a verification
24
+ URL (and opens it in your browser), then polls until you approve. The resulting token, account and
25
+ organization are stored locally.
26
+
27
+ ## Commands
28
+
29
+ | Command | Description |
30
+ | --- | --- |
31
+ | `login [--api-url <url>]` | Authenticate via device flow, store the token. |
32
+ | `logout` | Clear the locally stored token and identity. |
33
+ | `whoami` | Show account, organization, token prefix and permissions. |
34
+ | `projects list [--page]` | List visible projects. |
35
+ | `projects show <id\|key>` | Show one project. |
36
+ | `projects create <name> [--group <id\|name>] [--key] [--color] [--description]` | Create a project (key derived from the name if omitted). |
37
+ | `groups list [--page]` | List groups (macro-projects) in your org. |
38
+ | `groups create <name> [--color]` | Create a group (container of related projects, e.g. "DriverOne"). |
39
+ | `roles list\|show <id\|name>` | List roles / show a role with its permission keys. |
40
+ | `roles create <name> [--permission <key>…] [--color]` | Create an RBAC role (bundle of permission keys). |
41
+ | `roles update <id\|name> [--name] [--permission <key>…] [--color]` | Update a role (permissions REPLACE the set). |
42
+ | `roles delete <id\|name>` | Delete a role. |
43
+ | `teams list\|show <id\|name>` | List teams / show a team (roles, scope, members). |
44
+ | `teams create <name> [--role <id\|name>…] [--group <id\|name>…] [--project <id\|key>…] [--member <email\|id>…] [--color]` | Create a team with roles + group/project scope + members. |
45
+ | `teams update <id\|name> [--name] [--role…] [--group…] [--project…] [--member…]` | Update a team (each dimension REPLACES its set). |
46
+ | `teams add-member\|remove-member <team> <email\|id>` | Add/remove one person, keeping the others. |
47
+ | `teams delete <id\|name>` | Delete a team. |
48
+ | `members list [--page]` | List org members (resolve email → account id). |
49
+ | `invitations create <email> [--role customer\|member\|admin]` | Invite a person; prints the acceptance link (once). |
50
+ | `invitations list [--page]` | List invitations. |
51
+ | `invitations revoke <id>` | Revoke a pending invitation. |
52
+ | `errors list --project <id\|key> [--status] [--page]` | List error groups. |
53
+ | `errors show <id> --project <id\|key>` | Show one error group. |
54
+ | `errors resolve\|reopen\|mute\|unmute <id> --project <id\|key>` | Triage an error group. |
55
+ | `tokens list --project <id\|key>` | List ingest tokens. |
56
+ | `tokens create --project <id\|key> --name <name> --environment-id <id>` | Create a token (secret shown once). |
57
+ | `tokens rotate <id> --project <id\|key>` | Rotate a token (new secret shown once). |
58
+ | `tokens revoke <id> --project <id\|key>` | Revoke a token. |
59
+ | `tickets list --project <id\|key> [--page]` | List tickets. |
60
+ | `tickets show <id> --project <id\|key>` | Show one ticket. |
61
+ | `tickets create --project <id\|key> --title <t> [--kind] [--step-*] [--description] [--status-id] [--priority-id]` | Create a ticket. |
62
+ | `metrics list --project <id\|key> [--kind] [--page]` | List metric groups. |
63
+ | `metrics show <id> --project <id\|key>` | Show one metric group. |
64
+
65
+ Every command accepts `--json` for machine-readable output and `--help` for usage details.
66
+ `--project` accepts either a project UUID or its key (matched case-insensitively).
67
+
68
+ ## Configuration
69
+
70
+ The CLI stores its state in:
71
+
72
+ ```
73
+ ~/.config/closeyourit/config.json (mode 0600)
74
+ ```
75
+
76
+ It holds the backend URL, your token and a cached copy of your account/organization. Use `logout`
77
+ to clear it locally; revoke the token on the server at `/account/cli/tokens`.
78
+
79
+ ## Environment variables
80
+
81
+ | Variable | Purpose | Default |
82
+ | --- | --- | --- |
83
+ | `CLOSEYOURIT_API_URL` | Default backend base URL (overridden by a persisted `--api-url`). | `https://www.closeyour.it` |
84
+ | `CLOSEYOURIT_CONFIG_DIR` | Directory holding `config.json`. | `~/.config/closeyourit` |
85
+
86
+ ## Development
87
+
88
+ Toolchain is pinned with [mise](https://mise.jdx.dev) (`mise.toml`): Node 24 + pnpm.
89
+
90
+ ```bash
91
+ mise install
92
+ mise exec -- pnpm install
93
+ mise exec -- pnpm build # tsc -> dist/
94
+ mise exec -- pnpm test # vitest (fetch mocked)
95
+ ./bin/run.js --help # run the built CLI
96
+ ```
97
+
98
+ The machine-readable command surface lives in [`opencli.json`](./opencli.json)
99
+ ([OpenCLI](https://opencli.org)).
package/bin/run.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('@oclif/core').execute({dir: __dirname})
package/dist/base.d.ts ADDED
@@ -0,0 +1,34 @@
1
+ import { Command, type Interfaces } from '@oclif/core';
2
+ import { type CliConfig } from './lib/config';
3
+ import { CliApi } from './lib/api';
4
+ export declare const UUID_RE: RegExp;
5
+ /** Shared `--project <id|key>` flag (required). */
6
+ export declare const projectFlag: {
7
+ project: Interfaces.OptionFlag<string, Interfaces.CustomOptions>;
8
+ };
9
+ /** Shared `--page` flag. */
10
+ export declare const pageFlag: {
11
+ page: Interfaces.OptionFlag<number, Interfaces.CustomOptions>;
12
+ };
13
+ export declare abstract class BaseCommand extends Command {
14
+ static enableJsonFlag: boolean;
15
+ protected cfg: CliConfig;
16
+ protected api: CliApi;
17
+ init(): Promise<void>;
18
+ /** Resolve a project reference (UUID passes through; otherwise matched by key). */
19
+ protected resolveProjectId(value: string): Promise<string>;
20
+ /** Resolve a role reference (UUID passes through; otherwise matched by name, case-insensitive). */
21
+ protected resolveRoleId(value: string): Promise<string>;
22
+ /** Resolve a group reference (UUID passes through; otherwise matched by name). */
23
+ protected resolveGroupId(value: string): Promise<string>;
24
+ /** Resolve a team reference (UUID passes through; otherwise matched by name). */
25
+ protected resolveTeamId(value: string): Promise<string>;
26
+ /** Resolve a member reference (UUID account id passes through; otherwise matched by email). */
27
+ protected resolveMemberId(value: string): Promise<string>;
28
+ /** Resolve each value of a list to an id, preserving order. */
29
+ protected resolveAll(values: string[], resolve: (value: string) => Promise<string>): Promise<string[]>;
30
+ /** Resolve an `{id, name}` reference by name (UUID passes through). */
31
+ private resolveByName;
32
+ /** Print `code: message` for API errors, then exit non-zero. */
33
+ protected catch(error: Interfaces.CommandError): Promise<unknown>;
34
+ }
package/dist/base.js ADDED
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BaseCommand = exports.pageFlag = exports.projectFlag = exports.UUID_RE = void 0;
4
+ const core_1 = require("@oclif/core");
5
+ const config_1 = require("./lib/config");
6
+ const api_1 = require("./lib/api");
7
+ const error_codes_1 = require("./errors/error-codes");
8
+ exports.UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
9
+ /** Shared `--project <id|key>` flag (required). */
10
+ exports.projectFlag = {
11
+ project: core_1.Flags.string({ char: 'p', description: 'Project id (UUID) or key', required: true }),
12
+ };
13
+ /** Shared `--page` flag. */
14
+ exports.pageFlag = {
15
+ page: core_1.Flags.integer({ description: 'Page number', default: 1 }),
16
+ };
17
+ class BaseCommand extends core_1.Command {
18
+ static enableJsonFlag = true;
19
+ cfg;
20
+ api;
21
+ async init() {
22
+ await super.init();
23
+ this.cfg = (0, config_1.loadConfig)();
24
+ this.api = new api_1.CliApi(this.cfg);
25
+ }
26
+ /** Resolve a project reference (UUID passes through; otherwise matched by key). */
27
+ async resolveProjectId(value) {
28
+ if (exports.UUID_RE.test(value))
29
+ return value;
30
+ const res = await this.api.get('/cli/v1/projects');
31
+ const projects = res.data ?? [];
32
+ const match = projects.find((project) => (project.key ?? '').toLowerCase() === value.toLowerCase());
33
+ if (!match) {
34
+ throw new api_1.ApiRequestError(404, error_codes_1.ErrorCodes.Project.notFound, `Project not found: ${value}`);
35
+ }
36
+ return match.id;
37
+ }
38
+ /** Resolve a role reference (UUID passes through; otherwise matched by name, case-insensitive). */
39
+ resolveRoleId(value) {
40
+ return this.resolveByName('/cli/v1/roles', value, error_codes_1.ErrorCodes.Role.notFound, 'Role');
41
+ }
42
+ /** Resolve a group reference (UUID passes through; otherwise matched by name). */
43
+ resolveGroupId(value) {
44
+ return this.resolveByName('/cli/v1/groups', value, error_codes_1.ErrorCodes.Group.notFound, 'Group');
45
+ }
46
+ /** Resolve a team reference (UUID passes through; otherwise matched by name). */
47
+ resolveTeamId(value) {
48
+ return this.resolveByName('/cli/v1/teams', value, error_codes_1.ErrorCodes.Team.notFound, 'Team');
49
+ }
50
+ /** Resolve a member reference (UUID account id passes through; otherwise matched by email). */
51
+ async resolveMemberId(value) {
52
+ if (exports.UUID_RE.test(value))
53
+ return value;
54
+ const res = await this.api.get('/cli/v1/members');
55
+ const match = (res.data ?? []).find((m) => (m.email ?? '').toLowerCase() === value.toLowerCase());
56
+ if (!match) {
57
+ throw new api_1.ApiRequestError(404, error_codes_1.ErrorCodes.Member.notFound, `Member not found: ${value}`);
58
+ }
59
+ return match.account_id;
60
+ }
61
+ /** Resolve each value of a list to an id, preserving order. */
62
+ resolveAll(values, resolve) {
63
+ return Promise.all(values.map((value) => resolve(value)));
64
+ }
65
+ /** Resolve an `{id, name}` reference by name (UUID passes through). */
66
+ async resolveByName(path, value, code, label) {
67
+ if (exports.UUID_RE.test(value))
68
+ return value;
69
+ const res = await this.api.get(path);
70
+ const match = (res.data ?? []).find((row) => (row.name ?? '').toLowerCase() === value.toLowerCase());
71
+ if (!match) {
72
+ throw new api_1.ApiRequestError(404, code, `${label} not found: ${value}`);
73
+ }
74
+ return match.id;
75
+ }
76
+ /** Print `code: message` for API errors, then exit non-zero. */
77
+ async catch(error) {
78
+ if (error instanceof api_1.ApiRequestError) {
79
+ this.logToStderr(`${error.code}: ${error.message}`);
80
+ return this.exit(1);
81
+ }
82
+ return super.catch(error);
83
+ }
84
+ }
85
+ exports.BaseCommand = BaseCommand;
@@ -0,0 +1,11 @@
1
+ import { BaseCommand } from '../../base';
2
+ export default class ErrorsList extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ status: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
7
+ page: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
8
+ project: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
9
+ };
10
+ run(): Promise<unknown>;
11
+ }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_1 = require("../../base");
5
+ const output_1 = require("../../lib/output");
6
+ class ErrorsList extends base_1.BaseCommand {
7
+ static description = 'List error groups for a project';
8
+ static examples = [
9
+ '<%= config.bin %> errors list --project acme-api',
10
+ '<%= config.bin %> errors list -p acme-api --status unresolved --json',
11
+ ];
12
+ static flags = {
13
+ ...base_1.projectFlag,
14
+ ...base_1.pageFlag,
15
+ status: core_1.Flags.string({ description: 'Filter by status (e.g. unresolved, resolved, muted)' }),
16
+ };
17
+ async run() {
18
+ const { flags } = await this.parse(ErrorsList);
19
+ const projectId = await this.resolveProjectId(flags.project);
20
+ const query = new URLSearchParams({ page: String(flags.page) });
21
+ if (flags.status)
22
+ query.set('status', flags.status);
23
+ const res = await this.api.get(`/cli/v1/projects/${projectId}/error_groups?${query.toString()}`);
24
+ const groups = res.data ?? [];
25
+ if (!this.jsonEnabled()) {
26
+ this.log((0, output_1.renderTable)(['ID', 'TITLE', 'STATUS', 'EVENTS'], groups.map((group) => [
27
+ String(group.id ?? ''),
28
+ String(group.title ?? ''),
29
+ String(group.status ?? ''),
30
+ String(group.events_count ?? ''),
31
+ ])));
32
+ }
33
+ return res;
34
+ }
35
+ }
36
+ exports.default = ErrorsList;
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from '../../base';
2
+ export default class ErrorsMute extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ project: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ };
11
+ run(): Promise<unknown>;
12
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_1 = require("../../base");
5
+ class ErrorsMute extends base_1.BaseCommand {
6
+ static description = 'Mute an error group';
7
+ static examples = ['<%= config.bin %> errors mute <group-id> --project acme-api'];
8
+ static args = {
9
+ id: core_1.Args.string({ description: 'Error group id', required: true }),
10
+ };
11
+ static flags = { ...base_1.projectFlag };
12
+ async run() {
13
+ const { args, flags } = await this.parse(ErrorsMute);
14
+ const projectId = await this.resolveProjectId(flags.project);
15
+ const res = await this.api.put(`/cli/v1/projects/${projectId}/error_groups/${args.id}/mute`);
16
+ if (!this.jsonEnabled()) {
17
+ this.log(`Error group ${args.id} muted.`);
18
+ }
19
+ return res;
20
+ }
21
+ }
22
+ exports.default = ErrorsMute;
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from '../../base';
2
+ export default class ErrorsReopen extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ project: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ };
11
+ run(): Promise<unknown>;
12
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_1 = require("../../base");
5
+ class ErrorsReopen extends base_1.BaseCommand {
6
+ static description = 'Reopen a resolved error group';
7
+ static examples = ['<%= config.bin %> errors reopen <group-id> --project acme-api'];
8
+ static args = {
9
+ id: core_1.Args.string({ description: 'Error group id', required: true }),
10
+ };
11
+ static flags = { ...base_1.projectFlag };
12
+ async run() {
13
+ const { args, flags } = await this.parse(ErrorsReopen);
14
+ const projectId = await this.resolveProjectId(flags.project);
15
+ const res = await this.api.delete(`/cli/v1/projects/${projectId}/error_groups/${args.id}/resolution`);
16
+ if (!this.jsonEnabled()) {
17
+ this.log(`Error group ${args.id} reopened.`);
18
+ }
19
+ return res;
20
+ }
21
+ }
22
+ exports.default = ErrorsReopen;
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from '../../base';
2
+ export default class ErrorsResolve extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ project: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ };
11
+ run(): Promise<unknown>;
12
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_1 = require("../../base");
5
+ class ErrorsResolve extends base_1.BaseCommand {
6
+ static description = 'Mark an error group as resolved';
7
+ static examples = ['<%= config.bin %> errors resolve <group-id> --project acme-api'];
8
+ static args = {
9
+ id: core_1.Args.string({ description: 'Error group id', required: true }),
10
+ };
11
+ static flags = { ...base_1.projectFlag };
12
+ async run() {
13
+ const { args, flags } = await this.parse(ErrorsResolve);
14
+ const projectId = await this.resolveProjectId(flags.project);
15
+ const res = await this.api.put(`/cli/v1/projects/${projectId}/error_groups/${args.id}/resolution`);
16
+ if (!this.jsonEnabled()) {
17
+ this.log(`Error group ${args.id} marked as resolved.`);
18
+ }
19
+ return res;
20
+ }
21
+ }
22
+ exports.default = ErrorsResolve;
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from '../../base';
2
+ export default class ErrorsShow extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ project: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ };
11
+ run(): Promise<unknown>;
12
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_1 = require("../../base");
5
+ const output_1 = require("../../lib/output");
6
+ class ErrorsShow extends base_1.BaseCommand {
7
+ static description = 'Show a single error group';
8
+ static examples = ['<%= config.bin %> errors show <group-id> --project acme-api'];
9
+ static args = {
10
+ id: core_1.Args.string({ description: 'Error group id', required: true }),
11
+ };
12
+ static flags = { ...base_1.projectFlag };
13
+ async run() {
14
+ const { args, flags } = await this.parse(ErrorsShow);
15
+ const projectId = await this.resolveProjectId(flags.project);
16
+ const res = await this.api.get(`/cli/v1/projects/${projectId}/error_groups/${args.id}`);
17
+ if (!this.jsonEnabled()) {
18
+ this.log((0, output_1.renderRecord)(res.data ?? {}));
19
+ }
20
+ return res;
21
+ }
22
+ }
23
+ exports.default = ErrorsShow;
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from '../../base';
2
+ export default class ErrorsUnmute extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ project: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ };
11
+ run(): Promise<unknown>;
12
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_1 = require("../../base");
5
+ class ErrorsUnmute extends base_1.BaseCommand {
6
+ static description = 'Unmute an error group';
7
+ static examples = ['<%= config.bin %> errors unmute <group-id> --project acme-api'];
8
+ static args = {
9
+ id: core_1.Args.string({ description: 'Error group id', required: true }),
10
+ };
11
+ static flags = { ...base_1.projectFlag };
12
+ async run() {
13
+ const { args, flags } = await this.parse(ErrorsUnmute);
14
+ const projectId = await this.resolveProjectId(flags.project);
15
+ const res = await this.api.delete(`/cli/v1/projects/${projectId}/error_groups/${args.id}/mute`);
16
+ if (!this.jsonEnabled()) {
17
+ this.log(`Error group ${args.id} unmuted.`);
18
+ }
19
+ return res;
20
+ }
21
+ }
22
+ exports.default = ErrorsUnmute;
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from '../../base';
2
+ export default class GroupsCreate extends BaseCommand {
3
+ static args: {
4
+ name: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ color: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ };
11
+ run(): Promise<unknown>;
12
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_1 = require("../../base");
5
+ const output_1 = require("../../lib/output");
6
+ class GroupsCreate extends base_1.BaseCommand {
7
+ static args = {
8
+ name: core_1.Args.string({ description: 'Group name', required: true }),
9
+ };
10
+ static description = 'Create a group (a container of related projects, e.g. "DriverOne")';
11
+ static examples = [
12
+ '<%= config.bin %> groups create DriverOne',
13
+ '<%= config.bin %> groups create DriverOne --color indigo',
14
+ ];
15
+ static flags = {
16
+ color: core_1.Flags.string({ description: 'Color label' }),
17
+ };
18
+ async run() {
19
+ const { args, flags } = await this.parse(GroupsCreate);
20
+ const body = { name: args.name };
21
+ if (flags.color !== undefined)
22
+ body.color = flags.color;
23
+ const res = await this.api.post('/cli/v1/groups', body);
24
+ if (!this.jsonEnabled()) {
25
+ this.log('Group created:');
26
+ this.log((0, output_1.renderRecord)(res.data ?? {}));
27
+ }
28
+ return res;
29
+ }
30
+ }
31
+ exports.default = GroupsCreate;
@@ -0,0 +1,9 @@
1
+ import { BaseCommand } from '../../base';
2
+ export default class GroupsList extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ page: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
7
+ };
8
+ run(): Promise<unknown>;
9
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const base_1 = require("../../base");
4
+ const output_1 = require("../../lib/output");
5
+ class GroupsList extends base_1.BaseCommand {
6
+ static description = 'List the groups (macro-projects) in your organization';
7
+ static examples = ['<%= config.bin %> groups list', '<%= config.bin %> groups list --page 2 --json'];
8
+ static flags = { ...base_1.pageFlag };
9
+ async run() {
10
+ const { flags } = await this.parse(GroupsList);
11
+ const res = await this.api.get(`/cli/v1/groups?page=${flags.page}`);
12
+ const groups = res.data ?? [];
13
+ if (!this.jsonEnabled()) {
14
+ this.log((0, output_1.renderTable)(['NAME', 'COLOR', 'ID'], groups.map((group) => [String(group.name ?? ''), String(group.color ?? ''), String(group.id ?? '')])));
15
+ }
16
+ return res;
17
+ }
18
+ }
19
+ exports.default = GroupsList;
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from '../../base';
2
+ export default class InvitationsCreate extends BaseCommand {
3
+ static args: {
4
+ email: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ role: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ };
11
+ run(): Promise<unknown>;
12
+ }
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_1 = require("../../base");
5
+ class InvitationsCreate extends base_1.BaseCommand {
6
+ static args = {
7
+ email: core_1.Args.string({ description: 'Email address to invite', required: true }),
8
+ };
9
+ static description = 'Invite a person to the organization. Prints the acceptance link (shown only once).';
10
+ static examples = [
11
+ '<%= config.bin %> invitations create client@acme.com',
12
+ '<%= config.bin %> invitations create teammate@acme.com --role member',
13
+ ];
14
+ static flags = {
15
+ role: core_1.Flags.string({
16
+ default: 'customer',
17
+ description: 'Membership role',
18
+ options: ['customer', 'member', 'admin'],
19
+ }),
20
+ };
21
+ async run() {
22
+ const { args, flags } = await this.parse(InvitationsCreate);
23
+ const res = await this.api.post('/cli/v1/invitations', {
24
+ email: args.email,
25
+ role: flags.role,
26
+ });
27
+ const invitation = res.data ?? {};
28
+ if (!this.jsonEnabled()) {
29
+ this.log(`Invitation created for ${invitation.email ?? args.email} (role: ${invitation.role ?? flags.role}).`);
30
+ this.log('');
31
+ this.log(` accept link: ${invitation.accept_url ?? '-'}`);
32
+ this.log('');
33
+ this.warn('Email delivery is not wired in production — send this link to the invitee manually.');
34
+ }
35
+ return res;
36
+ }
37
+ }
38
+ exports.default = InvitationsCreate;
@@ -0,0 +1,9 @@
1
+ import { BaseCommand } from '../../base';
2
+ export default class InvitationsList extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ page: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
7
+ };
8
+ run(): Promise<unknown>;
9
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const base_1 = require("../../base");
4
+ const output_1 = require("../../lib/output");
5
+ class InvitationsList extends base_1.BaseCommand {
6
+ static description = 'List the pending/accepted invitations of your organization';
7
+ static examples = ['<%= config.bin %> invitations list', '<%= config.bin %> invitations list --json'];
8
+ static flags = { ...base_1.pageFlag };
9
+ async run() {
10
+ const { flags } = await this.parse(InvitationsList);
11
+ const res = await this.api.get(`/cli/v1/invitations?page=${flags.page}`);
12
+ const invitations = res.data ?? [];
13
+ if (!this.jsonEnabled()) {
14
+ this.log((0, output_1.renderTable)(['EMAIL', 'ROLE', 'ACCEPTED', 'ID'], invitations.map((invitation) => [
15
+ String(invitation.email ?? ''),
16
+ String(invitation.role ?? ''),
17
+ invitation.accepted_at ? 'yes' : 'no',
18
+ String(invitation.id ?? ''),
19
+ ])));
20
+ }
21
+ return res;
22
+ }
23
+ }
24
+ exports.default = InvitationsList;
@@ -0,0 +1,9 @@
1
+ import { BaseCommand } from '../../base';
2
+ export default class InvitationsRevoke extends BaseCommand {
3
+ static args: {
4
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ run(): Promise<unknown>;
9
+ }