@bussolabs/closeyourit-cli 0.0.3 → 0.0.5
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.
- package/README.md +1 -0
- package/dist/commands/alerts/create.d.ts +18 -0
- package/dist/commands/alerts/create.js +48 -0
- package/dist/commands/alerts/delete.d.ts +12 -0
- package/dist/commands/alerts/delete.js +25 -0
- package/dist/commands/alerts/list.d.ts +9 -0
- package/dist/commands/alerts/list.js +24 -0
- package/dist/commands/alerts/show.d.ts +9 -0
- package/dist/commands/alerts/show.js +21 -0
- package/dist/commands/alerts/update.d.ts +19 -0
- package/dist/commands/alerts/update.js +53 -0
- package/dist/commands/environments/create.d.ts +15 -0
- package/dist/commands/environments/create.js +37 -0
- package/dist/commands/environments/delete.d.ts +12 -0
- package/dist/commands/environments/delete.js +26 -0
- package/dist/commands/environments/list.d.ts +9 -0
- package/dist/commands/environments/list.js +25 -0
- package/dist/commands/environments/update.d.ts +16 -0
- package/dist/commands/environments/update.js +45 -0
- package/dist/commands/errors/promote.d.ts +12 -0
- package/dist/commands/errors/promote.js +24 -0
- package/dist/commands/groups/delete.d.ts +12 -0
- package/dist/commands/groups/delete.js +26 -0
- package/dist/commands/groups/update.d.ts +13 -0
- package/dist/commands/groups/update.js +35 -0
- package/dist/commands/invitations/resend.d.ts +9 -0
- package/dist/commands/invitations/resend.js +25 -0
- package/dist/commands/logs/list.d.ts +13 -0
- package/dist/commands/logs/list.js +51 -0
- package/dist/commands/members/set-access.d.ts +13 -0
- package/dist/commands/members/set-access.js +44 -0
- package/dist/commands/members/set-role.d.ts +12 -0
- package/dist/commands/members/set-role.js +32 -0
- package/dist/commands/metrics/promote.d.ts +12 -0
- package/dist/commands/metrics/promote.js +24 -0
- package/dist/commands/milestones/create.d.ts +14 -0
- package/dist/commands/milestones/create.js +38 -0
- package/dist/commands/milestones/delete.d.ts +13 -0
- package/dist/commands/milestones/delete.js +27 -0
- package/dist/commands/milestones/list.d.ts +10 -0
- package/dist/commands/milestones/list.js +29 -0
- package/dist/commands/milestones/show.d.ts +12 -0
- package/dist/commands/milestones/show.js +23 -0
- package/dist/commands/milestones/update.d.ts +17 -0
- package/dist/commands/milestones/update.js +45 -0
- package/dist/commands/monitors/create.d.ts +15 -0
- package/dist/commands/monitors/create.js +43 -0
- package/dist/commands/monitors/delete.d.ts +13 -0
- package/dist/commands/monitors/delete.js +27 -0
- package/dist/commands/monitors/list.d.ts +10 -0
- package/dist/commands/monitors/list.js +29 -0
- package/dist/commands/monitors/pause.d.ts +12 -0
- package/dist/commands/monitors/pause.js +21 -0
- package/dist/commands/monitors/resume.d.ts +12 -0
- package/dist/commands/monitors/resume.js +21 -0
- package/dist/commands/monitors/show.d.ts +12 -0
- package/dist/commands/monitors/show.js +23 -0
- package/dist/commands/monitors/update.d.ts +17 -0
- package/dist/commands/monitors/update.js +45 -0
- package/dist/commands/org/show.d.ts +6 -0
- package/dist/commands/org/show.js +16 -0
- package/dist/commands/org/update.d.ts +11 -0
- package/dist/commands/org/update.js +35 -0
- package/dist/commands/platforms/create.d.ts +15 -0
- package/dist/commands/platforms/create.js +36 -0
- package/dist/commands/platforms/delete.d.ts +12 -0
- package/dist/commands/platforms/delete.js +26 -0
- package/dist/commands/platforms/list.d.ts +9 -0
- package/dist/commands/platforms/list.js +25 -0
- package/dist/commands/platforms/update.d.ts +16 -0
- package/dist/commands/platforms/update.js +45 -0
- package/dist/commands/projects/create.d.ts +1 -1
- package/dist/commands/projects/create.js +3 -4
- package/dist/commands/projects/delete.d.ts +10 -0
- package/dist/commands/projects/delete.js +24 -0
- package/dist/commands/projects/update.d.ts +14 -0
- package/dist/commands/projects/update.js +37 -0
- package/dist/commands/tickets/assign.d.ts +14 -0
- package/dist/commands/tickets/assign.js +38 -0
- package/dist/commands/tickets/attach.d.ts +13 -0
- package/dist/commands/tickets/attach.js +48 -0
- package/dist/commands/tickets/comment-delete.d.ts +14 -0
- package/dist/commands/tickets/comment-delete.js +30 -0
- package/dist/commands/tickets/comment.d.ts +13 -0
- package/dist/commands/tickets/comment.js +29 -0
- package/dist/commands/tickets/delete.d.ts +13 -0
- package/dist/commands/tickets/delete.js +27 -0
- package/dist/commands/tickets/detach.d.ts +14 -0
- package/dist/commands/tickets/detach.js +30 -0
- package/dist/commands/tickets/milestone.d.ts +14 -0
- package/dist/commands/tickets/milestone.js +38 -0
- package/dist/commands/tickets/status.d.ts +13 -0
- package/dist/commands/tickets/status.js +27 -0
- package/dist/commands/tickets/unvote.d.ts +12 -0
- package/dist/commands/tickets/unvote.js +24 -0
- package/dist/commands/tickets/update.d.ts +25 -0
- package/dist/commands/tickets/update.js +71 -0
- package/dist/commands/tickets/vote.d.ts +12 -0
- package/dist/commands/tickets/vote.js +24 -0
- package/dist/lib/api.d.ts +17 -0
- package/dist/lib/api.js +40 -12
- package/oclif.manifest.json +3388 -559
- package/package.json +52 -14
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base';
|
|
2
|
+
export default class TicketsCommentDelete 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
|
+
static flags: {
|
|
9
|
+
'comment-id': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
confirm: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
project: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<unknown>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
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 TicketsCommentDelete extends base_1.BaseCommand {
|
|
6
|
+
static args = {
|
|
7
|
+
id: core_1.Args.string({ description: 'Ticket id', required: true }),
|
|
8
|
+
};
|
|
9
|
+
static description = 'Delete a comment from a ticket (author, or with tickets.comment.delete_any)';
|
|
10
|
+
static examples = [
|
|
11
|
+
'<%= config.bin %> tickets comment-delete <ticket-id> --project acme-api --comment-id <id> --confirm',
|
|
12
|
+
];
|
|
13
|
+
static flags = {
|
|
14
|
+
...base_1.projectFlag,
|
|
15
|
+
'comment-id': core_1.Flags.string({ description: 'Comment id to delete', required: true }),
|
|
16
|
+
confirm: core_1.Flags.boolean({ description: 'Required: confirm the irreversible deletion' }),
|
|
17
|
+
};
|
|
18
|
+
async run() {
|
|
19
|
+
const { args, flags } = await this.parse(TicketsCommentDelete);
|
|
20
|
+
if (!flags.confirm) {
|
|
21
|
+
this.error('Refusing to delete without --confirm (the action is irreversible).', { exit: 2 });
|
|
22
|
+
}
|
|
23
|
+
const projectId = await this.resolveProjectId(flags.project);
|
|
24
|
+
await this.api.delete(`/cli/v1/projects/${projectId}/tickets/${args.id}/comments/${flags['comment-id']}`);
|
|
25
|
+
if (!this.jsonEnabled())
|
|
26
|
+
this.log(`Deleted comment ${flags['comment-id']}`);
|
|
27
|
+
return { deleted: flags['comment-id'] };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.default = TicketsCommentDelete;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base';
|
|
2
|
+
export default class TicketsComment 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
|
+
static flags: {
|
|
9
|
+
body: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
project: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<unknown>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
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 TicketsComment extends base_1.BaseCommand {
|
|
7
|
+
static args = {
|
|
8
|
+
id: core_1.Args.string({ description: 'Ticket id', required: true }),
|
|
9
|
+
};
|
|
10
|
+
static description = 'Add a comment to a ticket';
|
|
11
|
+
static examples = [
|
|
12
|
+
'<%= config.bin %> tickets comment <ticket-id> --project acme-api --body "Reproduced on staging"',
|
|
13
|
+
];
|
|
14
|
+
static flags = {
|
|
15
|
+
...base_1.projectFlag,
|
|
16
|
+
body: core_1.Flags.string({ description: 'Comment body', required: true }),
|
|
17
|
+
};
|
|
18
|
+
async run() {
|
|
19
|
+
const { args, flags } = await this.parse(TicketsComment);
|
|
20
|
+
const projectId = await this.resolveProjectId(flags.project);
|
|
21
|
+
const res = await this.api.post(`/cli/v1/projects/${projectId}/tickets/${args.id}/comments`, { body: flags.body });
|
|
22
|
+
if (!this.jsonEnabled()) {
|
|
23
|
+
this.log('Comment added:');
|
|
24
|
+
this.log((0, output_1.renderRecord)(res.data ?? {}));
|
|
25
|
+
}
|
|
26
|
+
return res;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.default = TicketsComment;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base';
|
|
2
|
+
export default class TicketsDelete 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
|
+
confirm: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
project: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<unknown>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
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 TicketsDelete extends base_1.BaseCommand {
|
|
6
|
+
static description = 'Delete a ticket (irreversible)';
|
|
7
|
+
static examples = ['<%= config.bin %> tickets delete <ticket-id> --project acme-api --confirm'];
|
|
8
|
+
static args = {
|
|
9
|
+
id: core_1.Args.string({ description: 'Ticket id', required: true }),
|
|
10
|
+
};
|
|
11
|
+
static flags = {
|
|
12
|
+
...base_1.projectFlag,
|
|
13
|
+
confirm: core_1.Flags.boolean({ description: 'Required: confirm the irreversible deletion' }),
|
|
14
|
+
};
|
|
15
|
+
async run() {
|
|
16
|
+
const { args, flags } = await this.parse(TicketsDelete);
|
|
17
|
+
if (!flags.confirm) {
|
|
18
|
+
this.error('Refusing to delete without --confirm (the action is irreversible).', { exit: 2 });
|
|
19
|
+
}
|
|
20
|
+
const projectId = await this.resolveProjectId(flags.project);
|
|
21
|
+
await this.api.delete(`/cli/v1/projects/${projectId}/tickets/${args.id}`);
|
|
22
|
+
if (!this.jsonEnabled())
|
|
23
|
+
this.log(`Deleted ticket ${args.id}`);
|
|
24
|
+
return { deleted: args.id };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.default = TicketsDelete;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base';
|
|
2
|
+
export default class TicketsDetach 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
|
+
attachment: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
confirm: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
project: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<unknown>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
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 TicketsDetach extends base_1.BaseCommand {
|
|
6
|
+
static description = 'Remove an attachment from a ticket (irreversible)';
|
|
7
|
+
static examples = [
|
|
8
|
+
'<%= config.bin %> tickets detach <ticket-id> --project acme-api --attachment <attachment-id> --confirm',
|
|
9
|
+
];
|
|
10
|
+
static args = {
|
|
11
|
+
id: core_1.Args.string({ description: 'Ticket id', required: true }),
|
|
12
|
+
};
|
|
13
|
+
static flags = {
|
|
14
|
+
...base_1.projectFlag,
|
|
15
|
+
attachment: core_1.Flags.string({ description: 'Attachment id to remove', required: true }),
|
|
16
|
+
confirm: core_1.Flags.boolean({ description: 'Required: confirm the irreversible deletion' }),
|
|
17
|
+
};
|
|
18
|
+
async run() {
|
|
19
|
+
const { args, flags } = await this.parse(TicketsDetach);
|
|
20
|
+
if (!flags.confirm) {
|
|
21
|
+
this.error('Refusing to delete without --confirm (the action is irreversible).', { exit: 2 });
|
|
22
|
+
}
|
|
23
|
+
const projectId = await this.resolveProjectId(flags.project);
|
|
24
|
+
await this.api.delete(`/cli/v1/projects/${encodeURIComponent(projectId)}/tickets/${encodeURIComponent(args.id)}/attachments/${encodeURIComponent(flags.attachment)}`);
|
|
25
|
+
if (!this.jsonEnabled())
|
|
26
|
+
this.log(`Removed attachment ${flags.attachment} from ticket ${args.id}`);
|
|
27
|
+
return { detached: flags.attachment, ticket: args.id };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.default = TicketsDetach;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base';
|
|
2
|
+
export default class TicketsMilestone 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
|
+
'milestone-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
clear: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
project: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<unknown>;
|
|
14
|
+
}
|
|
@@ -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
|
+
const output_1 = require("../../lib/output");
|
|
6
|
+
class TicketsMilestone extends base_1.BaseCommand {
|
|
7
|
+
// PUT .../milestone sets; DELETE .../milestone removes. --clear picks the DELETE verb.
|
|
8
|
+
static description = 'Set or clear a ticket milestone (--clear)';
|
|
9
|
+
static examples = [
|
|
10
|
+
'<%= config.bin %> tickets milestone <ticket-id> --project acme-api --milestone-id <milestone-id>',
|
|
11
|
+
'<%= config.bin %> tickets milestone <ticket-id> --project acme-api --clear',
|
|
12
|
+
];
|
|
13
|
+
static args = {
|
|
14
|
+
id: core_1.Args.string({ description: 'Ticket id', required: true }),
|
|
15
|
+
};
|
|
16
|
+
static flags = {
|
|
17
|
+
...base_1.projectFlag,
|
|
18
|
+
'milestone-id': core_1.Flags.string({ description: 'Milestone id (of this project)', exclusive: ['clear'] }),
|
|
19
|
+
clear: core_1.Flags.boolean({ description: 'Remove the current milestone (DELETE)', exclusive: ['milestone-id'] }),
|
|
20
|
+
};
|
|
21
|
+
async run() {
|
|
22
|
+
const { args, flags } = await this.parse(TicketsMilestone);
|
|
23
|
+
if (!flags.clear && flags['milestone-id'] === undefined) {
|
|
24
|
+
this.error('Provide --milestone-id <id> or --clear.', { exit: 2 });
|
|
25
|
+
}
|
|
26
|
+
const projectId = await this.resolveProjectId(flags.project);
|
|
27
|
+
const path = `/cli/v1/projects/${projectId}/tickets/${args.id}/milestone`;
|
|
28
|
+
const res = flags.clear
|
|
29
|
+
? await this.api.delete(path)
|
|
30
|
+
: await this.api.put(path, { milestone_id: flags['milestone-id'] });
|
|
31
|
+
if (!this.jsonEnabled()) {
|
|
32
|
+
this.log(flags.clear ? `Ticket ${args.id} milestone cleared:` : `Ticket ${args.id} milestone set:`);
|
|
33
|
+
this.log((0, output_1.renderRecord)(res.data ?? {}));
|
|
34
|
+
}
|
|
35
|
+
return res;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.default = TicketsMilestone;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base';
|
|
2
|
+
export default class TicketsStatus 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
|
+
'status-id': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
project: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<unknown>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
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 TicketsStatus extends base_1.BaseCommand {
|
|
7
|
+
static description = 'Change a ticket status';
|
|
8
|
+
static examples = ['<%= config.bin %> tickets status <ticket-id> --project acme-api --status-id <status-id>'];
|
|
9
|
+
static args = {
|
|
10
|
+
id: core_1.Args.string({ description: 'Ticket id', required: true }),
|
|
11
|
+
};
|
|
12
|
+
static flags = {
|
|
13
|
+
...base_1.projectFlag,
|
|
14
|
+
'status-id': core_1.Flags.string({ description: 'Target status lookup id', required: true }),
|
|
15
|
+
};
|
|
16
|
+
async run() {
|
|
17
|
+
const { args, flags } = await this.parse(TicketsStatus);
|
|
18
|
+
const projectId = await this.resolveProjectId(flags.project);
|
|
19
|
+
const res = await this.api.put(`/cli/v1/projects/${projectId}/tickets/${args.id}/status`, { status_id: flags['status-id'] });
|
|
20
|
+
if (!this.jsonEnabled()) {
|
|
21
|
+
this.log(`Ticket ${args.id} status updated:`);
|
|
22
|
+
this.log((0, output_1.renderRecord)(res.data ?? {}));
|
|
23
|
+
}
|
|
24
|
+
return res;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.default = TicketsStatus;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base';
|
|
2
|
+
export default class TicketsUnvote 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
|
+
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,24 @@
|
|
|
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 TicketsUnvote extends base_1.BaseCommand {
|
|
6
|
+
static args = {
|
|
7
|
+
id: core_1.Args.string({ description: 'Ticket id', required: true }),
|
|
8
|
+
};
|
|
9
|
+
static description = 'Remove your upvote from a ticket (idempotent)';
|
|
10
|
+
static examples = ['<%= config.bin %> tickets unvote <ticket-id> --project acme-api'];
|
|
11
|
+
static flags = { ...base_1.projectFlag };
|
|
12
|
+
async run() {
|
|
13
|
+
const { args, flags } = await this.parse(TicketsUnvote);
|
|
14
|
+
const projectId = await this.resolveProjectId(flags.project);
|
|
15
|
+
const res = await this.api.delete(`/cli/v1/projects/${projectId}/tickets/${args.id}/vote`);
|
|
16
|
+
if (!this.jsonEnabled()) {
|
|
17
|
+
const p = res.data ?? {};
|
|
18
|
+
const count = p.votes_count;
|
|
19
|
+
this.log(`Removed vote from ticket ${args.id}${count === undefined ? '' : ` (${count} votes)`}`);
|
|
20
|
+
}
|
|
21
|
+
return res;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.default = TicketsUnvote;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base';
|
|
2
|
+
export default class TicketsUpdate 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
|
+
title: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
kind: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
description: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
weight: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
|
+
'step-given': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
14
|
+
'step-when': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
15
|
+
'step-then': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
16
|
+
'step-expected': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
17
|
+
'status-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
18
|
+
'priority-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
|
+
'assignee-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
20
|
+
'milestone-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
21
|
+
'platform-id': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
22
|
+
project: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
23
|
+
};
|
|
24
|
+
run(): Promise<unknown>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
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 TicketsUpdate extends base_1.BaseCommand {
|
|
7
|
+
// PUT /cli/v1/projects/:p/tickets/:id maps to Ticketing::UpdateTicket, a full replace:
|
|
8
|
+
// fields you omit are cleared server-side. Pass the complete desired state, not a partial patch.
|
|
9
|
+
static description = 'Update a ticket (full replace — fields you omit are cleared server-side)';
|
|
10
|
+
static examples = [
|
|
11
|
+
'<%= config.bin %> tickets update <ticket-id> --project acme-api --title "New title"',
|
|
12
|
+
'<%= config.bin %> tickets update <ticket-id> -p acme-api --title "Login bug" --kind bug --step-given "logged out" --step-when "I submit" --step-then "it 500s" --step-expected "dashboard loads"',
|
|
13
|
+
];
|
|
14
|
+
static args = {
|
|
15
|
+
id: core_1.Args.string({ description: 'Ticket id', required: true }),
|
|
16
|
+
};
|
|
17
|
+
static flags = {
|
|
18
|
+
...base_1.projectFlag,
|
|
19
|
+
title: core_1.Flags.string({ description: 'Ticket title' }),
|
|
20
|
+
kind: core_1.Flags.string({ description: 'Ticket kind (bug, feature, improvement)' }),
|
|
21
|
+
description: core_1.Flags.string({ description: 'Free-form description' }),
|
|
22
|
+
weight: core_1.Flags.string({ description: 'Story points (positive integer)' }),
|
|
23
|
+
'step-given': core_1.Flags.string({ description: 'Given (precondition)' }),
|
|
24
|
+
'step-when': core_1.Flags.string({ description: 'When (action)' }),
|
|
25
|
+
'step-then': core_1.Flags.string({ description: 'Then (outcome)' }),
|
|
26
|
+
'step-expected': core_1.Flags.string({ description: 'Expected result' }),
|
|
27
|
+
'status-id': core_1.Flags.string({ description: 'Status lookup id' }),
|
|
28
|
+
'priority-id': core_1.Flags.string({ description: 'Priority lookup id' }),
|
|
29
|
+
'assignee-id': core_1.Flags.string({ description: 'Assignee account id' }),
|
|
30
|
+
'milestone-id': core_1.Flags.string({ description: 'Milestone id (of this project)' }),
|
|
31
|
+
'platform-id': core_1.Flags.string({ description: 'Affected platform id (repeatable)', multiple: true }),
|
|
32
|
+
};
|
|
33
|
+
async run() {
|
|
34
|
+
const { args, flags } = await this.parse(TicketsUpdate);
|
|
35
|
+
const projectId = await this.resolveProjectId(flags.project);
|
|
36
|
+
const body = {};
|
|
37
|
+
if (flags.title !== undefined)
|
|
38
|
+
body.title = flags.title;
|
|
39
|
+
if (flags.kind !== undefined)
|
|
40
|
+
body.kind = flags.kind;
|
|
41
|
+
if (flags.description !== undefined)
|
|
42
|
+
body.description = flags.description;
|
|
43
|
+
if (flags.weight !== undefined)
|
|
44
|
+
body.weight = flags.weight;
|
|
45
|
+
if (flags['step-given'] !== undefined)
|
|
46
|
+
body.step_given = flags['step-given'];
|
|
47
|
+
if (flags['step-when'] !== undefined)
|
|
48
|
+
body.step_when = flags['step-when'];
|
|
49
|
+
if (flags['step-then'] !== undefined)
|
|
50
|
+
body.step_then = flags['step-then'];
|
|
51
|
+
if (flags['step-expected'] !== undefined)
|
|
52
|
+
body.step_expected = flags['step-expected'];
|
|
53
|
+
if (flags['status-id'] !== undefined)
|
|
54
|
+
body.status_id = flags['status-id'];
|
|
55
|
+
if (flags['priority-id'] !== undefined)
|
|
56
|
+
body.priority_id = flags['priority-id'];
|
|
57
|
+
if (flags['assignee-id'] !== undefined)
|
|
58
|
+
body.assignee_id = flags['assignee-id'];
|
|
59
|
+
if (flags['milestone-id'] !== undefined)
|
|
60
|
+
body.milestone_id = flags['milestone-id'];
|
|
61
|
+
if (flags['platform-id'] !== undefined)
|
|
62
|
+
body.platform_ids = flags['platform-id'];
|
|
63
|
+
const res = await this.api.put(`/cli/v1/projects/${projectId}/tickets/${args.id}`, body);
|
|
64
|
+
if (!this.jsonEnabled()) {
|
|
65
|
+
this.log('Ticket updated:');
|
|
66
|
+
this.log((0, output_1.renderRecord)(res.data ?? {}));
|
|
67
|
+
}
|
|
68
|
+
return res;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.default = TicketsUpdate;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base';
|
|
2
|
+
export default class TicketsVote 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
|
+
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,24 @@
|
|
|
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 TicketsVote extends base_1.BaseCommand {
|
|
6
|
+
static args = {
|
|
7
|
+
id: core_1.Args.string({ description: 'Ticket id', required: true }),
|
|
8
|
+
};
|
|
9
|
+
static description = 'Upvote a ticket (idempotent)';
|
|
10
|
+
static examples = ['<%= config.bin %> tickets vote <ticket-id> --project acme-api'];
|
|
11
|
+
static flags = { ...base_1.projectFlag };
|
|
12
|
+
async run() {
|
|
13
|
+
const { args, flags } = await this.parse(TicketsVote);
|
|
14
|
+
const projectId = await this.resolveProjectId(flags.project);
|
|
15
|
+
const res = await this.api.put(`/cli/v1/projects/${projectId}/tickets/${args.id}/vote`);
|
|
16
|
+
if (!this.jsonEnabled()) {
|
|
17
|
+
const p = res.data ?? {};
|
|
18
|
+
const count = p.votes_count;
|
|
19
|
+
this.log(`Voted ticket ${args.id}${count === undefined ? '' : ` (${count} votes)`}`);
|
|
20
|
+
}
|
|
21
|
+
return res;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.default = TicketsVote;
|
package/dist/lib/api.d.ts
CHANGED
|
@@ -15,11 +15,28 @@ export interface Envelope<T = unknown> {
|
|
|
15
15
|
data: T;
|
|
16
16
|
meta?: Record<string, unknown>;
|
|
17
17
|
}
|
|
18
|
+
/** A single file part for a multipart upload. */
|
|
19
|
+
export interface UploadFile {
|
|
20
|
+
/** Multipart field name (e.g. "files[]"). */
|
|
21
|
+
field: string;
|
|
22
|
+
filename: string;
|
|
23
|
+
data: Blob;
|
|
24
|
+
}
|
|
18
25
|
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
19
26
|
export declare class CliApi {
|
|
20
27
|
private readonly config;
|
|
21
28
|
constructor(config: CliConfig);
|
|
22
29
|
request<T = unknown>(method: HttpMethod, path: string, opts?: RequestOptions): Promise<Envelope<T>>;
|
|
30
|
+
/**
|
|
31
|
+
* Upload one or more files as multipart/form-data.
|
|
32
|
+
* The boundary Content-Type is derived by fetch from the FormData body — never set it by hand.
|
|
33
|
+
*/
|
|
34
|
+
upload<T = unknown>(method: 'POST' | 'PUT', path: string, files: UploadFile[], opts?: RequestOptions): Promise<Envelope<T>>;
|
|
35
|
+
private resolveUrl;
|
|
36
|
+
/** Build the shared Accept + Authorization headers; throws (before any fetch) if an authed call has no token. */
|
|
37
|
+
private authHeaders;
|
|
38
|
+
/** Parse the response body and map the error envelope to an ApiRequestError. Shared by request() and upload(). */
|
|
39
|
+
private handleResponse;
|
|
23
40
|
get<T = unknown>(path: string, opts?: RequestOptions): Promise<Envelope<T>>;
|
|
24
41
|
post<T = unknown>(path: string, body?: unknown, opts?: RequestOptions): Promise<Envelope<T>>;
|
|
25
42
|
put<T = unknown>(path: string, body?: unknown, opts?: RequestOptions): Promise<Envelope<T>>;
|
package/dist/lib/api.js
CHANGED
|
@@ -22,18 +22,9 @@ class CliApi {
|
|
|
22
22
|
this.config = config;
|
|
23
23
|
}
|
|
24
24
|
async request(method, path, opts = {}) {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
'Content-Type': 'application/json',
|
|
29
|
-
};
|
|
30
|
-
if (auth) {
|
|
31
|
-
if (!this.config.token) {
|
|
32
|
-
throw new ApiRequestError(401, error_codes_1.ErrorCodes.Auth.notLoggedIn, 'Not logged in. Run "closeyourit login".');
|
|
33
|
-
}
|
|
34
|
-
headers.Authorization = `Bearer ${this.config.token}`;
|
|
35
|
-
}
|
|
36
|
-
const url = this.config.apiUrl.replace(/\/+$/, '') + path;
|
|
25
|
+
const headers = this.authHeaders(opts.auth !== false);
|
|
26
|
+
headers['Content-Type'] = 'application/json';
|
|
27
|
+
const url = this.resolveUrl(path);
|
|
37
28
|
let res;
|
|
38
29
|
try {
|
|
39
30
|
res = await fetch(url, {
|
|
@@ -45,6 +36,43 @@ class CliApi {
|
|
|
45
36
|
catch (err) {
|
|
46
37
|
throw new ApiRequestError(0, error_codes_1.ErrorCodes.Network.requestFailed, `Request to ${url} failed: ${err.message}`);
|
|
47
38
|
}
|
|
39
|
+
return this.handleResponse(res);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Upload one or more files as multipart/form-data.
|
|
43
|
+
* The boundary Content-Type is derived by fetch from the FormData body — never set it by hand.
|
|
44
|
+
*/
|
|
45
|
+
async upload(method, path, files, opts = {}) {
|
|
46
|
+
const headers = this.authHeaders(opts.auth !== false);
|
|
47
|
+
const form = new FormData();
|
|
48
|
+
for (const file of files)
|
|
49
|
+
form.append(file.field, file.data, file.filename);
|
|
50
|
+
const url = this.resolveUrl(path);
|
|
51
|
+
let res;
|
|
52
|
+
try {
|
|
53
|
+
res = await fetch(url, { method, headers, body: form });
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
throw new ApiRequestError(0, error_codes_1.ErrorCodes.Network.requestFailed, `Request to ${url} failed: ${err.message}`);
|
|
57
|
+
}
|
|
58
|
+
return this.handleResponse(res);
|
|
59
|
+
}
|
|
60
|
+
resolveUrl(path) {
|
|
61
|
+
return this.config.apiUrl.replace(/\/+$/, '') + path;
|
|
62
|
+
}
|
|
63
|
+
/** Build the shared Accept + Authorization headers; throws (before any fetch) if an authed call has no token. */
|
|
64
|
+
authHeaders(auth) {
|
|
65
|
+
const headers = { Accept: 'application/json' };
|
|
66
|
+
if (auth) {
|
|
67
|
+
if (!this.config.token) {
|
|
68
|
+
throw new ApiRequestError(401, error_codes_1.ErrorCodes.Auth.notLoggedIn, 'Not logged in. Run "closeyourit login".');
|
|
69
|
+
}
|
|
70
|
+
headers.Authorization = `Bearer ${this.config.token}`;
|
|
71
|
+
}
|
|
72
|
+
return headers;
|
|
73
|
+
}
|
|
74
|
+
/** Parse the response body and map the error envelope to an ApiRequestError. Shared by request() and upload(). */
|
|
75
|
+
async handleResponse(res) {
|
|
48
76
|
const text = await res.text();
|
|
49
77
|
let json = {};
|
|
50
78
|
if (text.length > 0) {
|