@bussolabs/closeyourit-cli 0.14.0 → 0.16.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 (39) hide show
  1. package/README.md +17 -0
  2. package/dist/commands/matrix/categories/create.d.ts +13 -0
  3. package/dist/commands/matrix/categories/create.js +33 -0
  4. package/dist/commands/matrix/categories/delete.d.ts +13 -0
  5. package/dist/commands/matrix/categories/delete.js +27 -0
  6. package/dist/commands/matrix/categories/list.d.ts +12 -0
  7. package/dist/commands/matrix/categories/list.js +27 -0
  8. package/dist/commands/matrix/categories/update.d.ts +14 -0
  9. package/dist/commands/matrix/categories/update.js +37 -0
  10. package/dist/commands/matrix/cells/clear.d.ts +18 -0
  11. package/dist/commands/matrix/cells/clear.js +34 -0
  12. package/dist/commands/matrix/cells/set.d.ts +15 -0
  13. package/dist/commands/matrix/cells/set.js +42 -0
  14. package/dist/commands/matrix/features/create.d.ts +16 -0
  15. package/dist/commands/matrix/features/create.js +40 -0
  16. package/dist/commands/matrix/features/delete.d.ts +13 -0
  17. package/dist/commands/matrix/features/delete.js +27 -0
  18. package/dist/commands/matrix/features/list.d.ts +13 -0
  19. package/dist/commands/matrix/features/list.js +35 -0
  20. package/dist/commands/matrix/features/show.d.ts +10 -0
  21. package/dist/commands/matrix/features/show.js +33 -0
  22. package/dist/commands/matrix/features/update.d.ts +17 -0
  23. package/dist/commands/matrix/features/update.js +45 -0
  24. package/dist/commands/matrix/list.d.ts +9 -0
  25. package/dist/commands/matrix/list.js +18 -0
  26. package/dist/commands/matrix/show.d.ts +16 -0
  27. package/dist/commands/matrix/show.js +63 -0
  28. package/dist/commands/matrix/statuses.d.ts +6 -0
  29. package/dist/commands/matrix/statuses.js +22 -0
  30. package/dist/commands/tickets/lease/claim.d.ts +14 -0
  31. package/dist/commands/tickets/lease/claim.js +71 -0
  32. package/dist/commands/tickets/lease/release.d.ts +13 -0
  33. package/dist/commands/tickets/lease/release.js +52 -0
  34. package/dist/commands/tickets/lease/renew.d.ts +14 -0
  35. package/dist/commands/tickets/lease/renew.js +71 -0
  36. package/dist/lib/lease.d.ts +44 -0
  37. package/dist/lib/lease.js +61 -0
  38. package/oclif.manifest.json +3929 -2997
  39. package/package.json +5 -2
package/README.md CHANGED
@@ -105,6 +105,9 @@ CLOSEYOURIT_TOKEN=cyi_u_… CLOSEYOURIT_API_URL=https://www.closeyour.it \
105
105
  | `tickets watch\|unwatch <id> --project <id\|key>` | Watch / stop watching a ticket (its notifications). |
106
106
  | `tickets branch <id\|code> --project <id\|key>` | Create a GitHub branch from a ticket (name prefixed with the ticket code). |
107
107
  | `tickets pr <id\|code> --project <id\|key>` | Open a GitHub pull request from a ticket (head = the ticket branch). |
108
+ | `tickets lease claim <id\|code> --project <id\|key> [--ttl <seconds>] [--run-id <id>]` | Claim the working lease on a ticket (server default TTL: 8h). Exits non-zero on a 409, naming the current holder and its expiry. |
109
+ | `tickets lease renew <id\|code> --project <id\|key> [--ttl <seconds>] [--run-id <id>]` | Extend your own lease before it expires. |
110
+ | `tickets lease release <id\|code> --project <id\|key> [--run-id <id>]` | Release your own lease so someone else can claim the ticket. |
108
111
  | `ideas delete <id> --project <id\|key> --confirm` | Delete an idea (author always allowed; others need ideas.delete). |
109
112
  | `ideas archive\|unarchive <id> --project <id\|key>` | Archive an idea (open → archived) / reopen it. |
110
113
  | `ideas case-update <idea-id> <case-id> --project <id\|key> [--title] [--description]` | Update a case (example) of an idea. |
@@ -167,6 +170,20 @@ CLOSEYOURIT_TOKEN=cyi_u_… CLOSEYOURIT_API_URL=https://www.closeyour.it \
167
170
  | `analytics goals create --project <id\|key> --kind pageview_path\|custom_event --display-name <name> [--event-name] [--path-pattern]` | Create a conversion goal. |
168
171
  | `analytics goals delete <id> --project <id\|key> --confirm` | Delete a conversion goal. |
169
172
  | `releases list --project <id\|key> [--page]` | List a project's releases (tracked from CI). |
173
+ | `matrix list [--page]` | List the products whose feature × platform matrix you can see. |
174
+ | `matrix show <product>` | Show the matrix: features in rows, platforms in columns, `status version` per cell (`-` = not set, `?` = released without a version). |
175
+ | `matrix statuses` | List the cell statuses of your org (the codes `matrix cells set` accepts). |
176
+ | `matrix categories list <product> [--page]` | List the feature groups of a product. |
177
+ | `matrix categories create <product> --name <name> [--position]` | Create a feature group. |
178
+ | `matrix categories update <product> <id\|name> [--name] [--position]` | Update a feature group (unpassed fields keep their value). |
179
+ | `matrix categories delete <product> <id\|name> --confirm` | Delete a feature group (only when empty). |
180
+ | `matrix features list <product> [--category] [--page]` | List the features; the REFERENCE column is the `Category/Name` form the other commands take. |
181
+ | `matrix features show <product> <id\|"Category/Name">` | Show one feature and the cells written for it. |
182
+ | `matrix features create <product> --category <id\|name> --name <name> [--description] [--position] [--knowledge-page]` | Create a feature (a row of the matrix). |
183
+ | `matrix features update <product> <id\|"Category/Name"> [--name] [--description] [--position] [--category] [--knowledge-page]` | Update a feature, or move it to another category of the same product. |
184
+ | `matrix features delete <product> <id\|"Category/Name"> --confirm` | Delete a feature and every cell written for it. |
185
+ | `matrix cells set <product> <feature> <platform> --status <code> [--release <version>]` | Write a cell: how far along a feature is on a platform, and since which version. |
186
+ | `matrix cells clear <product> <feature> <platform> --confirm` | Clear a cell: the crossing goes back to "not set". |
170
187
  | `alerts channels list` | List the external alert channels (webhook / Telegram). |
171
188
  | `alerts channels create <name> --kind telegram\|webhook …` | Create a channel (`--bot-token`/`--chat-id` or `--url`/`--secret`). |
172
189
  | `alerts channels delete <id> --confirm` | Delete a channel. |
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from '../../../base';
2
+ export default class MatrixCategoriesCreate extends BaseCommand {
3
+ static args: {
4
+ product: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ name: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ position: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ };
12
+ run(): Promise<unknown>;
13
+ }
@@ -0,0 +1,33 @@
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 MatrixCategoriesCreate extends base_1.BaseCommand {
7
+ static args = {
8
+ product: core_1.Args.string({ description: 'Product id (UUID) or group name', required: true }),
9
+ };
10
+ static description = 'Create a feature group (category) in a product matrix';
11
+ static examples = [
12
+ '<%= config.bin %> matrix categories create CloseYourIt --name Auth',
13
+ '<%= config.bin %> matrix categories create CloseYourIt --name Notifications --position 2',
14
+ ];
15
+ static flags = {
16
+ name: core_1.Flags.string({ description: 'Category name (unique within the product)', required: true }),
17
+ position: core_1.Flags.integer({ description: 'Sort position' }),
18
+ };
19
+ async run() {
20
+ const { args, flags } = await this.parse(MatrixCategoriesCreate);
21
+ const productId = await this.resolveGroupId(args.product);
22
+ const body = { name: flags.name };
23
+ if (flags.position !== undefined)
24
+ body.position = flags.position;
25
+ const res = await this.api.post(`/cli/v1/product/matrix/${encodeURIComponent(productId)}/categories`, body);
26
+ if (!this.jsonEnabled()) {
27
+ this.log('Category created:');
28
+ this.log((0, output_1.renderRecord)(res.data ?? {}));
29
+ }
30
+ return res;
31
+ }
32
+ }
33
+ exports.default = MatrixCategoriesCreate;
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from '../../../base';
2
+ export default class MatrixCategoriesDelete extends BaseCommand {
3
+ static args: {
4
+ product: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
5
+ category: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static description: string;
8
+ static examples: string[];
9
+ static flags: {
10
+ confirm: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
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 MatrixCategoriesDelete extends base_1.BaseCommand {
6
+ static args = {
7
+ product: core_1.Args.string({ description: 'Product id (UUID) or group name', required: true }),
8
+ category: core_1.Args.string({ description: 'Category id (UUID) or name', required: true }),
9
+ };
10
+ static description = 'Delete a feature group (only when empty: move or delete its features first)';
11
+ static examples = ['<%= config.bin %> matrix categories delete CloseYourIt Auth --confirm'];
12
+ static flags = {
13
+ confirm: core_1.Flags.boolean({ description: 'Required: confirm the deletion' }),
14
+ };
15
+ async run() {
16
+ const { args, flags } = await this.parse(MatrixCategoriesDelete);
17
+ if (!flags.confirm) {
18
+ this.error('Refusing to delete without --confirm.', { exit: 2 });
19
+ }
20
+ const productId = await this.resolveGroupId(args.product);
21
+ await this.api.delete(`/cli/v1/product/matrix/${encodeURIComponent(productId)}/categories/${encodeURIComponent(args.category)}`);
22
+ if (!this.jsonEnabled())
23
+ this.log(`Deleted category ${args.category}`);
24
+ return { deleted: args.category };
25
+ }
26
+ }
27
+ exports.default = MatrixCategoriesDelete;
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from '../../../base';
2
+ export default class MatrixCategoriesList extends BaseCommand {
3
+ static args: {
4
+ product: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ page: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ };
11
+ run(): Promise<unknown>;
12
+ }
@@ -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 MatrixCategoriesList extends base_1.BaseCommand {
7
+ static args = {
8
+ product: core_1.Args.string({ description: 'Product id (UUID) or group name', required: true }),
9
+ };
10
+ static description = 'List the feature groups (categories) of a product matrix';
11
+ static examples = ['<%= config.bin %> matrix categories list CloseYourIt'];
12
+ static flags = { ...base_1.pageFlag };
13
+ async run() {
14
+ const { args, flags } = await this.parse(MatrixCategoriesList);
15
+ const productId = await this.resolveGroupId(args.product);
16
+ const res = await this.api.get(`/cli/v1/product/matrix/${encodeURIComponent(productId)}/categories?page=${flags.page}`);
17
+ if (!this.jsonEnabled()) {
18
+ this.log((0, output_1.renderTable)(['NAME', 'POSITION', 'ID'], (res.data ?? []).map((category) => [
19
+ String(category.name ?? ''),
20
+ String(category.position ?? ''),
21
+ String(category.id ?? ''),
22
+ ])));
23
+ }
24
+ return res;
25
+ }
26
+ }
27
+ exports.default = MatrixCategoriesList;
@@ -0,0 +1,14 @@
1
+ import { BaseCommand } from '../../../base';
2
+ export default class MatrixCategoriesUpdate extends BaseCommand {
3
+ static args: {
4
+ product: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
5
+ category: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static description: string;
8
+ static examples: string[];
9
+ static flags: {
10
+ name: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ position: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ };
13
+ run(): Promise<unknown>;
14
+ }
@@ -0,0 +1,37 @@
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 MatrixCategoriesUpdate extends base_1.BaseCommand {
7
+ static args = {
8
+ product: core_1.Args.string({ description: 'Product id (UUID) or group name', required: true }),
9
+ category: core_1.Args.string({ description: 'Category id (UUID) or name', required: true }),
10
+ };
11
+ static description = 'Update a feature group (rename or reorder); unpassed fields keep their value';
12
+ static examples = [
13
+ '<%= config.bin %> matrix categories update CloseYourIt Auth --name "Access"',
14
+ '<%= config.bin %> matrix categories update CloseYourIt Auth --position 1',
15
+ ];
16
+ static flags = {
17
+ name: core_1.Flags.string({ description: 'New name' }),
18
+ position: core_1.Flags.integer({ description: 'Sort position' }),
19
+ };
20
+ async run() {
21
+ const { args, flags } = await this.parse(MatrixCategoriesUpdate);
22
+ const productId = await this.resolveGroupId(args.product);
23
+ const body = {};
24
+ if (flags.name !== undefined)
25
+ body.name = flags.name;
26
+ if (flags.position !== undefined)
27
+ body.position = flags.position;
28
+ // The backend resolves the category by id-or-name within the product, so pass it through.
29
+ const res = await this.api.put(`/cli/v1/product/matrix/${encodeURIComponent(productId)}/categories/${encodeURIComponent(args.category)}`, body);
30
+ if (!this.jsonEnabled()) {
31
+ this.log('Category updated:');
32
+ this.log((0, output_1.renderRecord)(res.data ?? {}));
33
+ }
34
+ return res;
35
+ }
36
+ }
37
+ exports.default = MatrixCategoriesUpdate;
@@ -0,0 +1,18 @@
1
+ import { BaseCommand } from '../../../base';
2
+ export default class MatrixCellsClear extends BaseCommand {
3
+ static args: {
4
+ product: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
5
+ feature: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
6
+ platform: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ /**
9
+ * "Not set" is not the same as "not applicable": the latter is an explicit status you write with
10
+ * `matrix cells set`. Clearing throws away the status and the version, hence --confirm.
11
+ */
12
+ static description: string;
13
+ static examples: string[];
14
+ static flags: {
15
+ confirm: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
16
+ };
17
+ run(): Promise<unknown>;
18
+ }
@@ -0,0 +1,34 @@
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 MatrixCellsClear extends base_1.BaseCommand {
6
+ static args = {
7
+ product: core_1.Args.string({ description: 'Product id (UUID) or group name', required: true }),
8
+ feature: core_1.Args.string({ description: 'Feature id (UUID) or "Category/Name"', required: true }),
9
+ platform: core_1.Args.string({ description: 'Platform id (UUID) or code (e.g. web, ios)', required: true }),
10
+ };
11
+ /**
12
+ * "Not set" is not the same as "not applicable": the latter is an explicit status you write with
13
+ * `matrix cells set`. Clearing throws away the status and the version, hence --confirm.
14
+ */
15
+ static description = 'Clear a matrix cell: the crossing goes back to "not set"';
16
+ static examples = ['<%= config.bin %> matrix cells clear CloseYourIt "Auth/2FA" web --confirm'];
17
+ static flags = {
18
+ confirm: core_1.Flags.boolean({ description: 'Required: confirm clearing the cell' }),
19
+ };
20
+ async run() {
21
+ const { args, flags } = await this.parse(MatrixCellsClear);
22
+ if (!flags.confirm) {
23
+ this.error('Refusing to clear without --confirm.', { exit: 2 });
24
+ }
25
+ const productId = await this.resolveGroupId(args.product);
26
+ const path = `/cli/v1/product/matrix/${encodeURIComponent(productId)}` +
27
+ `/features/${encodeURIComponent(args.feature)}/cells/${encodeURIComponent(args.platform)}`;
28
+ await this.api.delete(path);
29
+ if (!this.jsonEnabled())
30
+ this.log(`Cleared ${args.feature} on ${args.platform}`);
31
+ return { cleared: { feature: args.feature, platform: args.platform } };
32
+ }
33
+ }
34
+ exports.default = MatrixCellsClear;
@@ -0,0 +1,15 @@
1
+ import { BaseCommand } from '../../../base';
2
+ export default class MatrixCellsSet extends BaseCommand {
3
+ static args: {
4
+ product: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
5
+ feature: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
6
+ platform: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static description: string;
9
+ static examples: string[];
10
+ static flags: {
11
+ status: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ release: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
+ };
14
+ run(): Promise<unknown>;
15
+ }
@@ -0,0 +1,42 @@
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 MatrixCellsSet extends base_1.BaseCommand {
6
+ static args = {
7
+ product: core_1.Args.string({ description: 'Product id (UUID) or group name', required: true }),
8
+ feature: core_1.Args.string({ description: 'Feature id (UUID) or "Category/Name"', required: true }),
9
+ platform: core_1.Args.string({ description: 'Platform id (UUID) or code (e.g. web, ios)', required: true }),
10
+ };
11
+ static description = 'Write a matrix cell: how far along a feature is on a platform, and since which version';
12
+ static examples = [
13
+ '<%= config.bin %> matrix cells set CloseYourIt "Auth/2FA" web --status available --release 2.1.0',
14
+ '<%= config.bin %> matrix cells set CloseYourIt "Auth/2FA" ios --status planned',
15
+ ];
16
+ static flags = {
17
+ status: core_1.Flags.string({ description: 'Status code (see: matrix statuses) or id', required: true }),
18
+ release: core_1.Flags.string({
19
+ description: 'Version the feature became available in (a registered release of the product on that platform)',
20
+ }),
21
+ };
22
+ async run() {
23
+ const { args, flags } = await this.parse(MatrixCellsSet);
24
+ const productId = await this.resolveGroupId(args.product);
25
+ const body = { status: flags.status };
26
+ if (flags.release !== undefined)
27
+ body.release = flags.release;
28
+ const path = `/cli/v1/product/matrix/${encodeURIComponent(productId)}` +
29
+ `/features/${encodeURIComponent(args.feature)}/cells/${encodeURIComponent(args.platform)}`;
30
+ const res = await this.api.put(path, body);
31
+ if (!this.jsonEnabled()) {
32
+ // What was saved, in the words the command took: status and release are nested objects, so a
33
+ // flat record dump would drop exactly the two values the user just set.
34
+ const cell = res.data ?? {};
35
+ const where = cell.platform_code ?? args.platform;
36
+ const version = cell.release?.version ?? (cell.release_missing ? 'no version set' : 'no version');
37
+ this.log(`Saved: ${args.feature} on ${where} → ${cell.status?.code ?? flags.status} (${version})`);
38
+ }
39
+ return res;
40
+ }
41
+ }
42
+ exports.default = MatrixCellsSet;
@@ -0,0 +1,16 @@
1
+ import { BaseCommand } from '../../../base';
2
+ export default class MatrixFeaturesCreate extends BaseCommand {
3
+ static args: {
4
+ product: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ category: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ name: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ description: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ position: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
+ 'knowledge-page': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
14
+ };
15
+ run(): Promise<unknown>;
16
+ }
@@ -0,0 +1,40 @@
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 MatrixFeaturesCreate extends base_1.BaseCommand {
7
+ static args = {
8
+ product: core_1.Args.string({ description: 'Product id (UUID) or group name', required: true }),
9
+ };
10
+ static description = 'Create a feature (a row of the matrix) inside a category';
11
+ static examples = [
12
+ '<%= config.bin %> matrix features create CloseYourIt --category Auth --name "2FA"',
13
+ '<%= config.bin %> matrix features create CloseYourIt --category Auth --name "Apple login" --knowledge-page <page-id>',
14
+ ];
15
+ static flags = {
16
+ category: core_1.Flags.string({ description: 'Category id (UUID) or name', required: true }),
17
+ name: core_1.Flags.string({ description: 'Feature name (unique within the category)', required: true }),
18
+ description: core_1.Flags.string({ description: 'What the feature does' }),
19
+ position: core_1.Flags.integer({ description: 'Sort position' }),
20
+ 'knowledge-page': core_1.Flags.string({ description: 'Knowledge page id explaining the feature' }),
21
+ };
22
+ async run() {
23
+ const { args, flags } = await this.parse(MatrixFeaturesCreate);
24
+ const productId = await this.resolveGroupId(args.product);
25
+ const body = { category: flags.category, name: flags.name };
26
+ if (flags.description !== undefined)
27
+ body.description = flags.description;
28
+ if (flags.position !== undefined)
29
+ body.position = flags.position;
30
+ if (flags['knowledge-page'] !== undefined)
31
+ body.knowledge_page_id = flags['knowledge-page'];
32
+ const res = await this.api.post(`/cli/v1/product/matrix/${encodeURIComponent(productId)}/features`, body);
33
+ if (!this.jsonEnabled()) {
34
+ this.log('Feature created:');
35
+ this.log((0, output_1.renderRecord)(res.data ?? {}));
36
+ }
37
+ return res;
38
+ }
39
+ }
40
+ exports.default = MatrixFeaturesCreate;
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from '../../../base';
2
+ export default class MatrixFeaturesDelete extends BaseCommand {
3
+ static args: {
4
+ product: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
5
+ feature: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static description: string;
8
+ static examples: string[];
9
+ static flags: {
10
+ confirm: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
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 MatrixFeaturesDelete extends base_1.BaseCommand {
6
+ static args = {
7
+ product: core_1.Args.string({ description: 'Product id (UUID) or group name', required: true }),
8
+ feature: core_1.Args.string({ description: 'Feature id (UUID) or "Category/Name"', required: true }),
9
+ };
10
+ static description = 'Delete a feature and every cell written for it (irreversible)';
11
+ static examples = ['<%= config.bin %> matrix features delete CloseYourIt "Auth/2FA" --confirm'];
12
+ static flags = {
13
+ confirm: core_1.Flags.boolean({ description: 'Required: confirm the deletion' }),
14
+ };
15
+ async run() {
16
+ const { args, flags } = await this.parse(MatrixFeaturesDelete);
17
+ if (!flags.confirm) {
18
+ this.error('Refusing to delete without --confirm.', { exit: 2 });
19
+ }
20
+ const productId = await this.resolveGroupId(args.product);
21
+ await this.api.delete(`/cli/v1/product/matrix/${encodeURIComponent(productId)}/features/${encodeURIComponent(args.feature)}`);
22
+ if (!this.jsonEnabled())
23
+ this.log(`Deleted feature ${args.feature}`);
24
+ return { deleted: args.feature };
25
+ }
26
+ }
27
+ exports.default = MatrixFeaturesDelete;
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from '../../../base';
2
+ export default class MatrixFeaturesList extends BaseCommand {
3
+ static args: {
4
+ product: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ category: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ page: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ };
12
+ run(): Promise<unknown>;
13
+ }
@@ -0,0 +1,35 @@
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 MatrixFeaturesList extends base_1.BaseCommand {
7
+ static args = {
8
+ product: core_1.Args.string({ description: 'Product id (UUID) or group name', required: true }),
9
+ };
10
+ static description = 'List the features of a product matrix';
11
+ static examples = [
12
+ '<%= config.bin %> matrix features list CloseYourIt',
13
+ '<%= config.bin %> matrix features list CloseYourIt --category Auth',
14
+ ];
15
+ static flags = {
16
+ ...base_1.pageFlag,
17
+ category: core_1.Flags.string({ description: 'Only the features of this category (id or name)' }),
18
+ };
19
+ async run() {
20
+ const { args, flags } = await this.parse(MatrixFeaturesList);
21
+ const productId = await this.resolveGroupId(args.product);
22
+ const query = flags.category ? `&category=${encodeURIComponent(flags.category)}` : '';
23
+ const res = await this.api.get(`/cli/v1/product/matrix/${encodeURIComponent(productId)}/features?page=${flags.page}${query}`);
24
+ if (!this.jsonEnabled()) {
25
+ // REFERENCE is the `Category/Name` form every other matrix command accepts.
26
+ this.log((0, output_1.renderTable)(['REFERENCE', 'DESCRIPTION', 'ID'], (res.data ?? []).map((feature) => [
27
+ `${String(feature.category_name ?? '')}/${String(feature.name ?? '')}`,
28
+ String(feature.description ?? ''),
29
+ String(feature.id ?? ''),
30
+ ])));
31
+ }
32
+ return res;
33
+ }
34
+ }
35
+ exports.default = MatrixFeaturesList;
@@ -0,0 +1,10 @@
1
+ import { BaseCommand } from '../../../base';
2
+ export default class MatrixFeaturesShow extends BaseCommand {
3
+ static args: {
4
+ product: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
5
+ feature: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static description: string;
8
+ static examples: string[];
9
+ run(): Promise<unknown>;
10
+ }
@@ -0,0 +1,33 @@
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 MatrixFeaturesShow extends base_1.BaseCommand {
7
+ static args = {
8
+ product: core_1.Args.string({ description: 'Product id (UUID) or group name', required: true }),
9
+ feature: core_1.Args.string({ description: 'Feature id (UUID) or "Category/Name"', required: true }),
10
+ };
11
+ static description = 'Show one feature and the cells written for it';
12
+ static examples = ['<%= config.bin %> matrix features show CloseYourIt "Auth/2FA"'];
13
+ async run() {
14
+ const { args } = await this.parse(MatrixFeaturesShow);
15
+ const productId = await this.resolveGroupId(args.product);
16
+ const res = await this.api.get(`/cli/v1/product/matrix/${encodeURIComponent(productId)}/features/${encodeURIComponent(args.feature)}`);
17
+ if (!this.jsonEnabled()) {
18
+ const { cells, ...feature } = res.data ?? {};
19
+ this.log((0, output_1.renderRecord)(feature));
20
+ const rows = cells ?? [];
21
+ if (rows.length > 0) {
22
+ this.log('');
23
+ this.log((0, output_1.renderTable)(['PLATFORM', 'STATUS', 'VERSION'], rows.map((cell) => [
24
+ String(cell.platform_code ?? cell.platform_id ?? ''),
25
+ String(cell.status?.code ?? ''),
26
+ cell.release?.version ? String(cell.release.version) : cell.release_missing ? '?' : '-',
27
+ ])));
28
+ }
29
+ }
30
+ return res;
31
+ }
32
+ }
33
+ exports.default = MatrixFeaturesShow;
@@ -0,0 +1,17 @@
1
+ import { BaseCommand } from '../../../base';
2
+ export default class MatrixFeaturesUpdate extends BaseCommand {
3
+ static args: {
4
+ product: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
5
+ feature: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static description: string;
8
+ static examples: string[];
9
+ static flags: {
10
+ name: 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
+ position: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
+ category: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
14
+ 'knowledge-page': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
15
+ };
16
+ run(): Promise<unknown>;
17
+ }
@@ -0,0 +1,45 @@
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 MatrixFeaturesUpdate extends base_1.BaseCommand {
7
+ static args = {
8
+ product: core_1.Args.string({ description: 'Product id (UUID) or group name', required: true }),
9
+ feature: core_1.Args.string({ description: 'Feature id (UUID) or "Category/Name"', required: true }),
10
+ };
11
+ static description = 'Update a feature (rename, move to another category, …); unpassed fields keep their value';
12
+ static examples = [
13
+ '<%= config.bin %> matrix features update CloseYourIt "Auth/2FA" --name "Two-factor"',
14
+ '<%= config.bin %> matrix features update CloseYourIt "Auth/2FA" --category Notifications',
15
+ ];
16
+ static flags = {
17
+ name: core_1.Flags.string({ description: 'New name' }),
18
+ description: core_1.Flags.string({ description: 'What the feature does' }),
19
+ position: core_1.Flags.integer({ description: 'Sort position' }),
20
+ category: core_1.Flags.string({ description: 'Move it to this category (id or name, same product)' }),
21
+ 'knowledge-page': core_1.Flags.string({ description: 'Knowledge page id explaining the feature' }),
22
+ };
23
+ async run() {
24
+ const { args, flags } = await this.parse(MatrixFeaturesUpdate);
25
+ const productId = await this.resolveGroupId(args.product);
26
+ const body = {};
27
+ if (flags.name !== undefined)
28
+ body.name = flags.name;
29
+ if (flags.description !== undefined)
30
+ body.description = flags.description;
31
+ if (flags.position !== undefined)
32
+ body.position = flags.position;
33
+ if (flags.category !== undefined)
34
+ body.category = flags.category;
35
+ if (flags['knowledge-page'] !== undefined)
36
+ body.knowledge_page_id = flags['knowledge-page'];
37
+ const res = await this.api.put(`/cli/v1/product/matrix/${encodeURIComponent(productId)}/features/${encodeURIComponent(args.feature)}`, body);
38
+ if (!this.jsonEnabled()) {
39
+ this.log('Feature updated:');
40
+ this.log((0, output_1.renderRecord)(res.data ?? {}));
41
+ }
42
+ return res;
43
+ }
44
+ }
45
+ exports.default = MatrixFeaturesUpdate;
@@ -0,0 +1,9 @@
1
+ import { BaseCommand } from '../../base';
2
+ export default class MatrixList 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,18 @@
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 MatrixList extends base_1.BaseCommand {
6
+ static description = 'List the products (groups) whose feature matrix you can see';
7
+ static examples = ['<%= config.bin %> matrix list', '<%= config.bin %> matrix list --page 2 --json'];
8
+ static flags = { ...base_1.pageFlag };
9
+ async run() {
10
+ const { flags } = await this.parse(MatrixList);
11
+ const res = await this.api.get(`/cli/v1/product/matrix?page=${flags.page}`);
12
+ if (!this.jsonEnabled()) {
13
+ this.log((0, output_1.renderTable)(['NAME', 'ID'], (res.data ?? []).map((product) => [String(product.name ?? ''), String(product.id ?? '')])));
14
+ }
15
+ return res;
16
+ }
17
+ }
18
+ exports.default = MatrixList;