@falldownthesystem/devtool 0.4.0 → 0.5.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.
- package/LICENSE +15 -0
- package/README.md +2 -3
- package/package.json +22 -4
- package/src/clients/confluence.js +171 -63
- package/src/clients/serviceDesk.js +181 -119
- package/src/commands/config.js +10 -27
- package/src/commands/confluence.js +14 -19
- package/src/commands/sd.js +135 -135
- package/src/config/store.js +23 -19
- package/src/formatters/serviceDesk.js +267 -267
- package/src/index.js +1 -1
- package/CLAUDE.md +0 -54
package/src/commands/config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
import { getAll, set, runSetup, configPath,
|
|
2
|
+
import { getAll, set, runSetup, configPath, schema } from '../config/store.js';
|
|
3
3
|
import { heading, field, mask, success, error, divider } from '../utils/output.js';
|
|
4
4
|
|
|
5
5
|
const config = new Command('config')
|
|
@@ -17,29 +17,15 @@ config
|
|
|
17
17
|
.alias('get')
|
|
18
18
|
.description('Show current configuration')
|
|
19
19
|
.action(() => {
|
|
20
|
-
if (!isConfigured()) {
|
|
21
|
-
error('Not configured yet. Run: dev config setup');
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
20
|
const all = getAll();
|
|
26
21
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
field('Base URL', all.jira.baseUrl);
|
|
35
|
-
field('Token', mask(all.jira.token));
|
|
36
|
-
field('Default project', all.jira.defaultProject);
|
|
37
|
-
|
|
38
|
-
heading('Confluence');
|
|
39
|
-
field('Base URL', all.confluence.baseUrl);
|
|
40
|
-
field('Email', all.confluence.email);
|
|
41
|
-
field('Token', mask(all.confluence.token));
|
|
42
|
-
field('Default space', all.confluence.defaultSpace);
|
|
22
|
+
for (const [section, definition] of Object.entries(schema)) {
|
|
23
|
+
heading(definition.title);
|
|
24
|
+
for (const [key, property] of Object.entries(definition.properties)) {
|
|
25
|
+
const value = all[section]?.[key] ?? '';
|
|
26
|
+
field(property.title, property.writeOnly ? mask(value) : value);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
43
29
|
|
|
44
30
|
console.log('');
|
|
45
31
|
divider();
|
|
@@ -51,11 +37,8 @@ config
|
|
|
51
37
|
.command('set <key> <value>')
|
|
52
38
|
.description('Set a config value (e.g. bitbucket.workspace my-ws)')
|
|
53
39
|
.action((key, value) => {
|
|
54
|
-
const validKeys = [
|
|
55
|
-
|
|
56
|
-
'jira.baseUrl', 'jira.token', 'jira.defaultProject',
|
|
57
|
-
'confluence.baseUrl', 'confluence.email', 'confluence.token', 'confluence.defaultSpace',
|
|
58
|
-
];
|
|
40
|
+
const validKeys = Object.entries(schema).flatMap(([section, definition]) =>
|
|
41
|
+
Object.keys(definition.properties).map((key) => `${section}.${key}`));
|
|
59
42
|
if (!validKeys.includes(key)) {
|
|
60
43
|
error(`Invalid key: ${key}`);
|
|
61
44
|
console.log(`Valid keys: ${validKeys.join(', ')}`);
|
|
@@ -57,30 +57,25 @@ confluence.command('pages')
|
|
|
57
57
|
.alias('ls')
|
|
58
58
|
.description('List pages in a space')
|
|
59
59
|
.option('-s, --space <key>', 'Space key (overrides default)')
|
|
60
|
-
.option('--space-id <id>', 'Space ID (
|
|
60
|
+
.option('--space-id <id>', 'Space ID (instead of a key)')
|
|
61
61
|
.action(async function (opts) {
|
|
62
62
|
const mode = getOutputMode(this);
|
|
63
63
|
const s = mode === 'rich' ? spinner('Fetching pages...').start() : null;
|
|
64
64
|
try {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
process.exitCode = 1;
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
spaceId = match.id;
|
|
65
|
+
const spaceId = opts.spaceId;
|
|
66
|
+
const spaceKey = spaceId ? undefined : opts.space || get('confluence.defaultSpace');
|
|
67
|
+
if (!spaceId && !spaceKey) {
|
|
68
|
+
if (s) s.error({ text: 'No space specified' });
|
|
69
|
+
console.error('Specify --space <key>, --space-id <id>, or set confluence.defaultSpace');
|
|
70
|
+
process.exitCode = 1;
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const pages = await listSpacePages({ spaceId, spaceKey });
|
|
74
|
+
if (!pages) {
|
|
75
|
+
if (s) s.error({ text: `Space "${spaceId || spaceKey}" not found` });
|
|
76
|
+
process.exitCode = 1;
|
|
77
|
+
return;
|
|
82
78
|
}
|
|
83
|
-
const pages = await listSpacePages(spaceId);
|
|
84
79
|
if (s) s.success({ text: `${pages.length} page(s) found` });
|
|
85
80
|
if (mode === 'json') outputJson(curatePagesJson(pages));
|
|
86
81
|
else if (mode === 'plain') plainPages(pages);
|
package/src/commands/sd.js
CHANGED
|
@@ -1,135 +1,135 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import {
|
|
3
|
-
getIssue,
|
|
4
|
-
getIssueComments,
|
|
5
|
-
searchIssues,
|
|
6
|
-
getMyIssues,
|
|
7
|
-
listQueues,
|
|
8
|
-
searchByQueue,
|
|
9
|
-
} from '../clients/serviceDesk.js';
|
|
10
|
-
import {
|
|
11
|
-
formatIssueView, formatIssueComments, formatIssueSearch,
|
|
12
|
-
plainIssueView, plainIssueComments, plainIssueSearch,
|
|
13
|
-
curateIssueJson, curateCommentsJson, curateSearchJson,
|
|
14
|
-
formatQueueList, plainQueueList, curateQueuesJson,
|
|
15
|
-
} from '../formatters/serviceDesk.js';
|
|
16
|
-
import { spinner } from '../utils/output.js';
|
|
17
|
-
import { handleError } from '../utils/errors.js';
|
|
18
|
-
import { getOutputMode, outputJson } from '../utils/mode.js';
|
|
19
|
-
|
|
20
|
-
const sd = new Command('sd')
|
|
21
|
-
.alias('servicedesk')
|
|
22
|
-
.description('Jira Service Desk Cloud tickets');
|
|
23
|
-
|
|
24
|
-
sd.command('view <key>')
|
|
25
|
-
.alias('read')
|
|
26
|
-
.description('View ticket details')
|
|
27
|
-
.action(async function (key) {
|
|
28
|
-
const mode = getOutputMode(this);
|
|
29
|
-
const s = mode === 'rich' ? spinner(`Fetching ${key}...`).start() : null;
|
|
30
|
-
try {
|
|
31
|
-
const issue = await getIssue(key);
|
|
32
|
-
if (s) s.success({ text: key });
|
|
33
|
-
if (mode === 'json') outputJson(curateIssueJson(issue));
|
|
34
|
-
else if (mode === 'plain') plainIssueView(issue);
|
|
35
|
-
else formatIssueView(issue);
|
|
36
|
-
} catch (err) {
|
|
37
|
-
if (s) s.error({ text: `Failed to fetch ${key}` });
|
|
38
|
-
handleError(err, `sd view ${key}`);
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
sd.command('comments <key>')
|
|
43
|
-
.description('List ticket comments')
|
|
44
|
-
.action(async function (key) {
|
|
45
|
-
const mode = getOutputMode(this);
|
|
46
|
-
const s = mode === 'rich' ? spinner(`Fetching comments for ${key}...`).start() : null;
|
|
47
|
-
try {
|
|
48
|
-
const comments = await getIssueComments(key);
|
|
49
|
-
if (s) s.success({ text: `${comments.length} comment(s)` });
|
|
50
|
-
if (mode === 'json') outputJson(curateCommentsJson(comments));
|
|
51
|
-
else if (mode === 'plain') plainIssueComments(comments);
|
|
52
|
-
else formatIssueComments(comments);
|
|
53
|
-
} catch (err) {
|
|
54
|
-
if (s) s.error({ text: `Failed to fetch comments for ${key}` });
|
|
55
|
-
handleError(err, `sd comments ${key}`);
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
sd.command('search <jql>')
|
|
60
|
-
.alias('find')
|
|
61
|
-
.description('Search Service Desk tickets with JQL')
|
|
62
|
-
.option('-n, --per-page <number>', 'Results per page', '20')
|
|
63
|
-
.option('--next <token>', 'Continuation token from a previous page')
|
|
64
|
-
.action(async function (jql, opts) {
|
|
65
|
-
const mode = getOutputMode(this);
|
|
66
|
-
const perPage = parseInt(opts.perPage, 10);
|
|
67
|
-
const s = mode === 'rich' ? spinner('Searching...').start() : null;
|
|
68
|
-
try {
|
|
69
|
-
const result = await searchIssues(jql, perPage, opts.next || '');
|
|
70
|
-
if (s) s.success({ text: `${result.issues.length} issue(s) returned` });
|
|
71
|
-
if (mode === 'json') outputJson(curateSearchJson(result));
|
|
72
|
-
else if (mode === 'plain') plainIssueSearch(result);
|
|
73
|
-
else formatIssueSearch(result);
|
|
74
|
-
} catch (err) {
|
|
75
|
-
if (s) s.error({ text: 'Search failed' });
|
|
76
|
-
handleError(err, `sd search "${jql}"`);
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
sd.command('queues')
|
|
81
|
-
.description('List Service Desk queues for the default project')
|
|
82
|
-
.action(async function () {
|
|
83
|
-
const mode = getOutputMode(this);
|
|
84
|
-
const s = mode === 'rich' ? spinner('Fetching queues...').start() : null;
|
|
85
|
-
try {
|
|
86
|
-
const queues = await listQueues();
|
|
87
|
-
if (s) s.success({ text: `${queues.length} queue(s)` });
|
|
88
|
-
if (mode === 'json') outputJson(curateQueuesJson(queues));
|
|
89
|
-
else if (mode === 'plain') plainQueueList(queues);
|
|
90
|
-
else formatQueueList(queues);
|
|
91
|
-
} catch (err) {
|
|
92
|
-
if (s) s.error({ text: 'Failed to fetch queues' });
|
|
93
|
-
handleError(err, 'sd queues');
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
sd.command('queue <nameOrId>')
|
|
98
|
-
.description('Show issues in a Service Desk queue (by name or id)')
|
|
99
|
-
.option('-n, --per-page <number>', 'Results per page', '20')
|
|
100
|
-
.option('--next <token>', 'Continuation token from a previous page')
|
|
101
|
-
.action(async function (nameOrId, opts) {
|
|
102
|
-
const mode = getOutputMode(this);
|
|
103
|
-
const perPage = parseInt(opts.perPage, 10);
|
|
104
|
-
const s = mode === 'rich' ? spinner(`Fetching queue "${nameOrId}"...`).start() : null;
|
|
105
|
-
try {
|
|
106
|
-
const result = await searchByQueue(nameOrId, perPage, opts.next || '');
|
|
107
|
-
if (s) s.success({ text: `${result.issues.length} issue(s) in "${result.queue.name}"` });
|
|
108
|
-
if (mode === 'json') outputJson(curateSearchJson(result));
|
|
109
|
-
else if (mode === 'plain') plainIssueSearch(result);
|
|
110
|
-
else formatIssueSearch(result);
|
|
111
|
-
} catch (err) {
|
|
112
|
-
if (s) s.error({ text: `Failed to fetch queue "${nameOrId}"` });
|
|
113
|
-
handleError(err, `sd queue ${nameOrId}`);
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
sd.command('mine')
|
|
118
|
-
.alias('my')
|
|
119
|
-
.description('Show my open Service Desk tickets')
|
|
120
|
-
.action(async function () {
|
|
121
|
-
const mode = getOutputMode(this);
|
|
122
|
-
const s = mode === 'rich' ? spinner('Fetching my tickets...').start() : null;
|
|
123
|
-
try {
|
|
124
|
-
const result = await getMyIssues();
|
|
125
|
-
if (s) s.success({ text: `${result.issues.length} ticket(s)` });
|
|
126
|
-
if (mode === 'json') outputJson(curateSearchJson(result));
|
|
127
|
-
else if (mode === 'plain') plainIssueSearch(result);
|
|
128
|
-
else formatIssueSearch(result);
|
|
129
|
-
} catch (err) {
|
|
130
|
-
if (s) s.error({ text: 'Failed to fetch tickets' });
|
|
131
|
-
handleError(err, 'sd my tickets');
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
export default sd;
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import {
|
|
3
|
+
getIssue,
|
|
4
|
+
getIssueComments,
|
|
5
|
+
searchIssues,
|
|
6
|
+
getMyIssues,
|
|
7
|
+
listQueues,
|
|
8
|
+
searchByQueue,
|
|
9
|
+
} from '../clients/serviceDesk.js';
|
|
10
|
+
import {
|
|
11
|
+
formatIssueView, formatIssueComments, formatIssueSearch,
|
|
12
|
+
plainIssueView, plainIssueComments, plainIssueSearch,
|
|
13
|
+
curateIssueJson, curateCommentsJson, curateSearchJson,
|
|
14
|
+
formatQueueList, plainQueueList, curateQueuesJson,
|
|
15
|
+
} from '../formatters/serviceDesk.js';
|
|
16
|
+
import { spinner } from '../utils/output.js';
|
|
17
|
+
import { handleError } from '../utils/errors.js';
|
|
18
|
+
import { getOutputMode, outputJson } from '../utils/mode.js';
|
|
19
|
+
|
|
20
|
+
const sd = new Command('sd')
|
|
21
|
+
.alias('servicedesk')
|
|
22
|
+
.description('Jira Service Desk Cloud tickets');
|
|
23
|
+
|
|
24
|
+
sd.command('view <key>')
|
|
25
|
+
.alias('read')
|
|
26
|
+
.description('View ticket details')
|
|
27
|
+
.action(async function (key) {
|
|
28
|
+
const mode = getOutputMode(this);
|
|
29
|
+
const s = mode === 'rich' ? spinner(`Fetching ${key}...`).start() : null;
|
|
30
|
+
try {
|
|
31
|
+
const issue = await getIssue(key);
|
|
32
|
+
if (s) s.success({ text: key });
|
|
33
|
+
if (mode === 'json') outputJson(curateIssueJson(issue));
|
|
34
|
+
else if (mode === 'plain') plainIssueView(issue);
|
|
35
|
+
else formatIssueView(issue);
|
|
36
|
+
} catch (err) {
|
|
37
|
+
if (s) s.error({ text: `Failed to fetch ${key}` });
|
|
38
|
+
handleError(err, `sd view ${key}`);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
sd.command('comments <key>')
|
|
43
|
+
.description('List ticket comments')
|
|
44
|
+
.action(async function (key) {
|
|
45
|
+
const mode = getOutputMode(this);
|
|
46
|
+
const s = mode === 'rich' ? spinner(`Fetching comments for ${key}...`).start() : null;
|
|
47
|
+
try {
|
|
48
|
+
const comments = await getIssueComments(key);
|
|
49
|
+
if (s) s.success({ text: `${comments.length} comment(s)` });
|
|
50
|
+
if (mode === 'json') outputJson(curateCommentsJson(comments));
|
|
51
|
+
else if (mode === 'plain') plainIssueComments(comments);
|
|
52
|
+
else formatIssueComments(comments);
|
|
53
|
+
} catch (err) {
|
|
54
|
+
if (s) s.error({ text: `Failed to fetch comments for ${key}` });
|
|
55
|
+
handleError(err, `sd comments ${key}`);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
sd.command('search <jql>')
|
|
60
|
+
.alias('find')
|
|
61
|
+
.description('Search Service Desk tickets with JQL')
|
|
62
|
+
.option('-n, --per-page <number>', 'Results per page', '20')
|
|
63
|
+
.option('--next <token>', 'Continuation token from a previous page')
|
|
64
|
+
.action(async function (jql, opts) {
|
|
65
|
+
const mode = getOutputMode(this);
|
|
66
|
+
const perPage = parseInt(opts.perPage, 10);
|
|
67
|
+
const s = mode === 'rich' ? spinner('Searching...').start() : null;
|
|
68
|
+
try {
|
|
69
|
+
const result = await searchIssues(jql, perPage, opts.next || '');
|
|
70
|
+
if (s) s.success({ text: `${result.issues.length} issue(s) returned` });
|
|
71
|
+
if (mode === 'json') outputJson(curateSearchJson(result));
|
|
72
|
+
else if (mode === 'plain') plainIssueSearch(result);
|
|
73
|
+
else formatIssueSearch(result);
|
|
74
|
+
} catch (err) {
|
|
75
|
+
if (s) s.error({ text: 'Search failed' });
|
|
76
|
+
handleError(err, `sd search "${jql}"`);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
sd.command('queues')
|
|
81
|
+
.description('List Service Desk queues for the default project')
|
|
82
|
+
.action(async function () {
|
|
83
|
+
const mode = getOutputMode(this);
|
|
84
|
+
const s = mode === 'rich' ? spinner('Fetching queues...').start() : null;
|
|
85
|
+
try {
|
|
86
|
+
const queues = await listQueues();
|
|
87
|
+
if (s) s.success({ text: `${queues.length} queue(s)` });
|
|
88
|
+
if (mode === 'json') outputJson(curateQueuesJson(queues));
|
|
89
|
+
else if (mode === 'plain') plainQueueList(queues);
|
|
90
|
+
else formatQueueList(queues);
|
|
91
|
+
} catch (err) {
|
|
92
|
+
if (s) s.error({ text: 'Failed to fetch queues' });
|
|
93
|
+
handleError(err, 'sd queues');
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
sd.command('queue <nameOrId>')
|
|
98
|
+
.description('Show issues in a Service Desk queue (by name or id)')
|
|
99
|
+
.option('-n, --per-page <number>', 'Results per page', '20')
|
|
100
|
+
.option('--next <token>', 'Continuation token from a previous page')
|
|
101
|
+
.action(async function (nameOrId, opts) {
|
|
102
|
+
const mode = getOutputMode(this);
|
|
103
|
+
const perPage = parseInt(opts.perPage, 10);
|
|
104
|
+
const s = mode === 'rich' ? spinner(`Fetching queue "${nameOrId}"...`).start() : null;
|
|
105
|
+
try {
|
|
106
|
+
const result = await searchByQueue(nameOrId, perPage, opts.next || '');
|
|
107
|
+
if (s) s.success({ text: `${result.issues.length} issue(s) in "${result.queue.name}"` });
|
|
108
|
+
if (mode === 'json') outputJson(curateSearchJson(result));
|
|
109
|
+
else if (mode === 'plain') plainIssueSearch(result);
|
|
110
|
+
else formatIssueSearch(result);
|
|
111
|
+
} catch (err) {
|
|
112
|
+
if (s) s.error({ text: `Failed to fetch queue "${nameOrId}"` });
|
|
113
|
+
handleError(err, `sd queue ${nameOrId}`);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
sd.command('mine')
|
|
118
|
+
.alias('my')
|
|
119
|
+
.description('Show my open Service Desk tickets')
|
|
120
|
+
.action(async function () {
|
|
121
|
+
const mode = getOutputMode(this);
|
|
122
|
+
const s = mode === 'rich' ? spinner('Fetching my tickets...').start() : null;
|
|
123
|
+
try {
|
|
124
|
+
const result = await getMyIssues();
|
|
125
|
+
if (s) s.success({ text: `${result.issues.length} ticket(s)` });
|
|
126
|
+
if (mode === 'json') outputJson(curateSearchJson(result));
|
|
127
|
+
else if (mode === 'plain') plainIssueSearch(result);
|
|
128
|
+
else formatIssueSearch(result);
|
|
129
|
+
} catch (err) {
|
|
130
|
+
if (s) s.error({ text: 'Failed to fetch tickets' });
|
|
131
|
+
handleError(err, 'sd my tickets');
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
export default sd;
|
package/src/config/store.js
CHANGED
|
@@ -2,40 +2,44 @@ import Conf from 'conf';
|
|
|
2
2
|
import * as p from '@clack/prompts';
|
|
3
3
|
import pc from 'picocolors';
|
|
4
4
|
|
|
5
|
-
const schema = {
|
|
5
|
+
export const schema = {
|
|
6
6
|
bitbucket: {
|
|
7
7
|
type: 'object',
|
|
8
|
+
title: 'Bitbucket',
|
|
8
9
|
properties: {
|
|
9
|
-
workspace: { type: 'string' },
|
|
10
|
-
defaultRepo: { type: 'string' },
|
|
11
|
-
email: { type: 'string' },
|
|
12
|
-
token: { type: 'string' },
|
|
10
|
+
workspace: { type: 'string', title: 'Workspace' },
|
|
11
|
+
defaultRepo: { type: 'string', title: 'Default repo' },
|
|
12
|
+
email: { type: 'string', title: 'Email' },
|
|
13
|
+
token: { type: 'string', title: 'Token', writeOnly: true },
|
|
13
14
|
},
|
|
14
15
|
},
|
|
15
16
|
jira: {
|
|
16
17
|
type: 'object',
|
|
18
|
+
title: 'Jira',
|
|
17
19
|
properties: {
|
|
18
|
-
baseUrl: { type: 'string' },
|
|
19
|
-
token: { type: 'string' },
|
|
20
|
-
defaultProject: { type: 'string' },
|
|
20
|
+
baseUrl: { type: 'string', title: 'Base URL' },
|
|
21
|
+
token: { type: 'string', title: 'Token', writeOnly: true },
|
|
22
|
+
defaultProject: { type: 'string', title: 'Default project' },
|
|
21
23
|
},
|
|
22
24
|
},
|
|
23
25
|
confluence: {
|
|
24
26
|
type: 'object',
|
|
27
|
+
title: 'Confluence',
|
|
25
28
|
properties: {
|
|
26
|
-
baseUrl: { type: 'string' },
|
|
27
|
-
email: { type: 'string' },
|
|
28
|
-
token: { type: 'string' },
|
|
29
|
-
defaultSpace: { type: 'string' },
|
|
29
|
+
baseUrl: { type: 'string', title: 'Base URL' },
|
|
30
|
+
email: { type: 'string', title: 'Email' },
|
|
31
|
+
token: { type: 'string', title: 'Token', writeOnly: true },
|
|
32
|
+
defaultSpace: { type: 'string', title: 'Default space' },
|
|
30
33
|
},
|
|
31
34
|
},
|
|
32
35
|
serviceDesk: {
|
|
33
36
|
type: 'object',
|
|
37
|
+
title: 'Service Desk',
|
|
34
38
|
properties: {
|
|
35
|
-
baseUrl: { type: 'string' },
|
|
36
|
-
email: { type: 'string' },
|
|
37
|
-
token: { type: 'string' },
|
|
38
|
-
defaultProject: { type: 'string' },
|
|
39
|
+
baseUrl: { type: 'string', title: 'Base URL' },
|
|
40
|
+
email: { type: 'string', title: 'Email' },
|
|
41
|
+
token: { type: 'string', title: 'Token', writeOnly: true },
|
|
42
|
+
defaultProject: { type: 'string', title: 'Default project' },
|
|
39
43
|
},
|
|
40
44
|
},
|
|
41
45
|
};
|
|
@@ -132,17 +136,17 @@ export async function runSetup() {
|
|
|
132
136
|
|
|
133
137
|
const confluence = await p.group({
|
|
134
138
|
baseUrl: () => p.text({
|
|
135
|
-
message: 'Confluence Cloud
|
|
139
|
+
message: 'Confluence base URL (Cloud or Server/Data Center)',
|
|
136
140
|
placeholder: 'https://company.atlassian.net',
|
|
137
141
|
initialValue: config.get('confluence.baseUrl') || '',
|
|
138
142
|
}),
|
|
139
143
|
email: () => p.text({
|
|
140
|
-
message: 'Confluence account email',
|
|
144
|
+
message: 'Confluence account email (Server/Data Center: username, or empty for a personal access token)',
|
|
141
145
|
placeholder: 'you@company.com',
|
|
142
146
|
initialValue: config.get('confluence.email') || '',
|
|
143
147
|
}),
|
|
144
148
|
token: () => p.password({
|
|
145
|
-
message: 'Confluence API token',
|
|
149
|
+
message: 'Confluence API token (Server/Data Center: personal access token or password)',
|
|
146
150
|
}),
|
|
147
151
|
defaultSpace: () => p.text({
|
|
148
152
|
message: 'Confluence default space key',
|