@geneverse/workctl 0.2.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/LICENSE +21 -0
- package/README.md +340 -0
- package/dist/packages/capabilities/assistant/src/commands.d.ts +10 -0
- package/dist/packages/capabilities/assistant/src/commands.js +33 -0
- package/dist/packages/capabilities/assistant/src/commands.js.map +1 -0
- package/dist/packages/capabilities/assistant/src/index.d.ts +2 -0
- package/dist/packages/capabilities/assistant/src/index.js +3 -0
- package/dist/packages/capabilities/assistant/src/index.js.map +1 -0
- package/dist/packages/capabilities/assistant/src/status.d.ts +18 -0
- package/dist/packages/capabilities/assistant/src/status.js +48 -0
- package/dist/packages/capabilities/assistant/src/status.js.map +1 -0
- package/dist/packages/capabilities/jenkins/src/commands.d.ts +9 -0
- package/dist/packages/capabilities/jenkins/src/commands.js +43 -0
- package/dist/packages/capabilities/jenkins/src/commands.js.map +1 -0
- package/dist/packages/capabilities/jenkins/src/definition.d.ts +10 -0
- package/dist/packages/capabilities/jenkins/src/definition.js +59 -0
- package/dist/packages/capabilities/jenkins/src/definition.js.map +1 -0
- package/dist/packages/capabilities/jenkins/src/index.d.ts +2 -0
- package/dist/packages/capabilities/jenkins/src/index.js +3 -0
- package/dist/packages/capabilities/jenkins/src/index.js.map +1 -0
- package/dist/packages/capabilities/jira/src/adapters/filesystem/config.store.d.ts +2 -0
- package/dist/packages/capabilities/jira/src/adapters/filesystem/config.store.js +43 -0
- package/dist/packages/capabilities/jira/src/adapters/filesystem/config.store.js.map +1 -0
- package/dist/packages/capabilities/jira/src/adapters/filesystem/local.paths.d.ts +16 -0
- package/dist/packages/capabilities/jira/src/adapters/filesystem/local.paths.js +46 -0
- package/dist/packages/capabilities/jira/src/adapters/filesystem/local.paths.js.map +1 -0
- package/dist/packages/capabilities/jira/src/adapters/filesystem/sync-lock.d.ts +2 -0
- package/dist/packages/capabilities/jira/src/adapters/filesystem/sync-lock.js +120 -0
- package/dist/packages/capabilities/jira/src/adapters/filesystem/sync-lock.js.map +1 -0
- package/dist/packages/capabilities/jira/src/adapters/jira/jira.client.d.ts +31 -0
- package/dist/packages/capabilities/jira/src/adapters/jira/jira.client.js +344 -0
- package/dist/packages/capabilities/jira/src/adapters/jira/jira.client.js.map +1 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/catalog.d.ts +9 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/catalog.js +17 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/catalog.js.map +1 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/orchestrator.d.ts +14 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/orchestrator.js +116 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/orchestrator.js.map +1 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/scraper.d.ts +32 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/scraper.js +2 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/scraper.js.map +1 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/v1/detect.d.ts +2 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/v1/detect.js +45 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/v1/detect.js.map +1 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/v1/extract.d.ts +3 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/v1/extract.js +115 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/v1/extract.js.map +1 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/v1/index.d.ts +2 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/v1/index.js +27 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/v1/index.js.map +1 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/v1/navigation.d.ts +3 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/v1/navigation.js +104 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/v1/navigation.js.map +1 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/v1/ready.d.ts +2 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/v1/ready.js +47 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/v1/ready.js.map +1 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/v1/shared.d.ts +4 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/v1/shared.js +5 -0
- package/dist/packages/capabilities/jira/src/adapters/kawari/v1/shared.js.map +1 -0
- package/dist/packages/capabilities/jira/src/adapters/terminal/node-cli.io.d.ts +2 -0
- package/dist/packages/capabilities/jira/src/adapters/terminal/node-cli.io.js +40 -0
- package/dist/packages/capabilities/jira/src/adapters/terminal/node-cli.io.js.map +1 -0
- package/dist/packages/capabilities/jira/src/batch-interaction.d.ts +53 -0
- package/dist/packages/capabilities/jira/src/batch-interaction.js +201 -0
- package/dist/packages/capabilities/jira/src/batch-interaction.js.map +1 -0
- package/dist/packages/capabilities/jira/src/capability.d.ts +16 -0
- package/dist/packages/capabilities/jira/src/capability.js +56 -0
- package/dist/packages/capabilities/jira/src/capability.js.map +1 -0
- package/dist/packages/capabilities/jira/src/cli/contracts.d.ts +42 -0
- package/dist/packages/capabilities/jira/src/cli/contracts.js +2 -0
- package/dist/packages/capabilities/jira/src/cli/contracts.js.map +1 -0
- package/dist/packages/capabilities/jira/src/cli/errors.d.ts +3 -0
- package/dist/packages/capabilities/jira/src/cli/errors.js +7 -0
- package/dist/packages/capabilities/jira/src/cli/errors.js.map +1 -0
- package/dist/packages/capabilities/jira/src/cli/program.d.ts +6 -0
- package/dist/packages/capabilities/jira/src/cli/program.js +48 -0
- package/dist/packages/capabilities/jira/src/cli/program.js.map +1 -0
- package/dist/packages/capabilities/jira/src/cli/run-cli.d.ts +2 -0
- package/dist/packages/capabilities/jira/src/cli/run-cli.js +72 -0
- package/dist/packages/capabilities/jira/src/cli/run-cli.js.map +1 -0
- package/dist/packages/capabilities/jira/src/commands/audit-links/audit-links.command.d.ts +2 -0
- package/dist/packages/capabilities/jira/src/commands/audit-links/audit-links.command.js +165 -0
- package/dist/packages/capabilities/jira/src/commands/audit-links/audit-links.command.js.map +1 -0
- package/dist/packages/capabilities/jira/src/commands/audit-links/audit-links.service.d.ts +30 -0
- package/dist/packages/capabilities/jira/src/commands/audit-links/audit-links.service.js +174 -0
- package/dist/packages/capabilities/jira/src/commands/audit-links/audit-links.service.js.map +1 -0
- package/dist/packages/capabilities/jira/src/commands/command-context.d.ts +10 -0
- package/dist/packages/capabilities/jira/src/commands/command-context.js +2 -0
- package/dist/packages/capabilities/jira/src/commands/command-context.js.map +1 -0
- package/dist/packages/capabilities/jira/src/commands/config-show/config-show.command.d.ts +2 -0
- package/dist/packages/capabilities/jira/src/commands/config-show/config-show.command.js +26 -0
- package/dist/packages/capabilities/jira/src/commands/config-show/config-show.command.js.map +1 -0
- package/dist/packages/capabilities/jira/src/commands/configure/configure.command.d.ts +2 -0
- package/dist/packages/capabilities/jira/src/commands/configure/configure.command.js +26 -0
- package/dist/packages/capabilities/jira/src/commands/configure/configure.command.js.map +1 -0
- package/dist/packages/capabilities/jira/src/commands/configure/configure.service.d.ts +42 -0
- package/dist/packages/capabilities/jira/src/commands/configure/configure.service.js +205 -0
- package/dist/packages/capabilities/jira/src/commands/configure/configure.service.js.map +1 -0
- package/dist/packages/capabilities/jira/src/commands/doctor/doctor.command.d.ts +2 -0
- package/dist/packages/capabilities/jira/src/commands/doctor/doctor.command.js +17 -0
- package/dist/packages/capabilities/jira/src/commands/doctor/doctor.command.js.map +1 -0
- package/dist/packages/capabilities/jira/src/commands/doctor/doctor.service.d.ts +18 -0
- package/dist/packages/capabilities/jira/src/commands/doctor/doctor.service.js +84 -0
- package/dist/packages/capabilities/jira/src/commands/doctor/doctor.service.js.map +1 -0
- package/dist/packages/capabilities/jira/src/commands/rollback/rollback.command.d.ts +2 -0
- package/dist/packages/capabilities/jira/src/commands/rollback/rollback.command.js +198 -0
- package/dist/packages/capabilities/jira/src/commands/rollback/rollback.command.js.map +1 -0
- package/dist/packages/capabilities/jira/src/commands/rollback/rollback.service.d.ts +37 -0
- package/dist/packages/capabilities/jira/src/commands/rollback/rollback.service.js +112 -0
- package/dist/packages/capabilities/jira/src/commands/rollback/rollback.service.js.map +1 -0
- package/dist/packages/capabilities/jira/src/commands/sync/audit-export.service.d.ts +18 -0
- package/dist/packages/capabilities/jira/src/commands/sync/audit-export.service.js +96 -0
- package/dist/packages/capabilities/jira/src/commands/sync/audit-export.service.js.map +1 -0
- package/dist/packages/capabilities/jira/src/commands/sync/preview.service.d.ts +23 -0
- package/dist/packages/capabilities/jira/src/commands/sync/preview.service.js +201 -0
- package/dist/packages/capabilities/jira/src/commands/sync/preview.service.js.map +1 -0
- package/dist/packages/capabilities/jira/src/commands/sync/sync.command.d.ts +2 -0
- package/dist/packages/capabilities/jira/src/commands/sync/sync.command.js +537 -0
- package/dist/packages/capabilities/jira/src/commands/sync/sync.command.js.map +1 -0
- package/dist/packages/capabilities/jira/src/commands/sync/verification.service.d.ts +34 -0
- package/dist/packages/capabilities/jira/src/commands/sync/verification.service.js +164 -0
- package/dist/packages/capabilities/jira/src/commands/sync/verification.service.js.map +1 -0
- package/dist/packages/capabilities/jira/src/config.d.ts +37 -0
- package/dist/packages/capabilities/jira/src/config.js +217 -0
- package/dist/packages/capabilities/jira/src/config.js.map +1 -0
- package/dist/packages/capabilities/jira/src/dependencies.d.ts +2 -0
- package/dist/packages/capabilities/jira/src/dependencies.js +92 -0
- package/dist/packages/capabilities/jira/src/dependencies.js.map +1 -0
- package/dist/packages/capabilities/jira/src/domain/date-range.d.ts +10 -0
- package/dist/packages/capabilities/jira/src/domain/date-range.js +63 -0
- package/dist/packages/capabilities/jira/src/domain/date-range.js.map +1 -0
- package/dist/packages/capabilities/jira/src/domain/marker.d.ts +20 -0
- package/dist/packages/capabilities/jira/src/domain/marker.js +100 -0
- package/dist/packages/capabilities/jira/src/domain/marker.js.map +1 -0
- package/dist/packages/capabilities/jira/src/domain/timesheet-entry.d.ts +45 -0
- package/dist/packages/capabilities/jira/src/domain/timesheet-entry.js +117 -0
- package/dist/packages/capabilities/jira/src/domain/timesheet-entry.js.map +1 -0
- package/dist/packages/capabilities/jira/src/index.d.ts +5 -0
- package/dist/packages/capabilities/jira/src/index.js +4 -0
- package/dist/packages/capabilities/jira/src/index.js.map +1 -0
- package/dist/packages/capabilities/jira/src/ports/jira.d.ts +49 -0
- package/dist/packages/capabilities/jira/src/ports/jira.js +11 -0
- package/dist/packages/capabilities/jira/src/ports/jira.js.map +1 -0
- package/dist/packages/capabilities/jira/src/ports/sync-lock.d.ts +6 -0
- package/dist/packages/capabilities/jira/src/ports/sync-lock.js +7 -0
- package/dist/packages/capabilities/jira/src/ports/sync-lock.js.map +1 -0
- package/dist/packages/capabilities/jira/src/ports/timesheet.d.ts +11 -0
- package/dist/packages/capabilities/jira/src/ports/timesheet.js +7 -0
- package/dist/packages/capabilities/jira/src/ports/timesheet.js.map +1 -0
- package/dist/packages/capabilities/jira/src/presentation.d.ts +37 -0
- package/dist/packages/capabilities/jira/src/presentation.js +111 -0
- package/dist/packages/capabilities/jira/src/presentation.js.map +1 -0
- package/dist/packages/cli/src/bin.d.ts +2 -0
- package/dist/packages/cli/src/bin.js +4 -0
- package/dist/packages/cli/src/bin.js.map +1 -0
- package/dist/packages/cli/src/commands/browsers/browsers.command.d.ts +7 -0
- package/dist/packages/cli/src/commands/browsers/browsers.command.js +22 -0
- package/dist/packages/cli/src/commands/browsers/browsers.command.js.map +1 -0
- package/dist/packages/cli/src/commands/browsers/browsers.service.d.ts +16 -0
- package/dist/packages/cli/src/commands/browsers/browsers.service.js +37 -0
- package/dist/packages/cli/src/commands/browsers/browsers.service.js.map +1 -0
- package/dist/packages/cli/src/commands/setup/setup.command.d.ts +4 -0
- package/dist/packages/cli/src/commands/setup/setup.command.js +41 -0
- package/dist/packages/cli/src/commands/setup/setup.command.js.map +1 -0
- package/dist/packages/cli/src/commands/setup/setup.service.d.ts +23 -0
- package/dist/packages/cli/src/commands/setup/setup.service.js +32 -0
- package/dist/packages/cli/src/commands/setup/setup.service.js.map +1 -0
- package/dist/packages/cli/src/commands/update/update.command.d.ts +7 -0
- package/dist/packages/cli/src/commands/update/update.command.js +34 -0
- package/dist/packages/cli/src/commands/update/update.command.js.map +1 -0
- package/dist/packages/cli/src/commands/update/update.service.d.ts +35 -0
- package/dist/packages/cli/src/commands/update/update.service.js +134 -0
- package/dist/packages/cli/src/commands/update/update.service.js.map +1 -0
- package/dist/packages/cli/src/index.d.ts +1 -0
- package/dist/packages/cli/src/index.js +2 -0
- package/dist/packages/cli/src/index.js.map +1 -0
- package/dist/packages/cli/src/program.d.ts +21 -0
- package/dist/packages/cli/src/program.js +74 -0
- package/dist/packages/cli/src/program.js.map +1 -0
- package/dist/packages/cli/src/release-version.d.ts +1 -0
- package/dist/packages/cli/src/release-version.js +2 -0
- package/package.json +57 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import * as clack from "@clack/prompts";
|
|
2
|
+
import { ConfigFileError, readStoredConfig, validateConfig, } from "../../config.js";
|
|
3
|
+
const DEFAULTS = {
|
|
4
|
+
jiraBaseUrl: "https://iamblockchain.atlassian.net",
|
|
5
|
+
timesheetUrl: "https://kawari.iamconsulting.co.th/time_sheet",
|
|
6
|
+
timezone: "Asia/Bangkok",
|
|
7
|
+
};
|
|
8
|
+
export class SetupCancelledError extends Error {
|
|
9
|
+
constructor() {
|
|
10
|
+
super("Setup cancelled; configuration was not changed.");
|
|
11
|
+
this.name = "SetupCancelledError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function unwrap(value) {
|
|
15
|
+
if (clack.isCancel(value)) {
|
|
16
|
+
clack.cancel("Setup cancelled; configuration was not changed.");
|
|
17
|
+
throw new SetupCancelledError();
|
|
18
|
+
}
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
export const clackSetupPrompts = {
|
|
22
|
+
intro: clack.intro,
|
|
23
|
+
text: async (options) => unwrap(await clack.text(options)),
|
|
24
|
+
password: async (options) => unwrap(await clack.password({ ...options, mask: "•" })),
|
|
25
|
+
confirm: async (options) => unwrap(await clack.confirm(options)),
|
|
26
|
+
multiselect: async (options) => unwrap(await clack.multiselect({
|
|
27
|
+
message: options.message,
|
|
28
|
+
options: [...options.options],
|
|
29
|
+
...(options.initialValues ? { initialValues: [...options.initialValues] } : {}),
|
|
30
|
+
...(options.required !== undefined ? { required: options.required } : {}),
|
|
31
|
+
})),
|
|
32
|
+
note: clack.note,
|
|
33
|
+
outro: clack.outro,
|
|
34
|
+
};
|
|
35
|
+
export function hasValidStoredConfig(configPath) {
|
|
36
|
+
try {
|
|
37
|
+
validateConfig(readStoredConfig(configPath));
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function required(label) {
|
|
45
|
+
return (value) => value?.trim() ? undefined : `${label} is required`;
|
|
46
|
+
}
|
|
47
|
+
function urlValidator(kind) {
|
|
48
|
+
return (value) => {
|
|
49
|
+
const missing = required(kind === "jira" ? "Jira URL" : "Timesheet URL")(value);
|
|
50
|
+
if (missing)
|
|
51
|
+
return missing;
|
|
52
|
+
try {
|
|
53
|
+
const url = new URL(value);
|
|
54
|
+
if (url.protocol !== "https:" || url.username || url.password) {
|
|
55
|
+
return "Enter an HTTPS URL without credentials";
|
|
56
|
+
}
|
|
57
|
+
if (kind === "jira" && (url.pathname !== "/" || url.search || url.hash)) {
|
|
58
|
+
return "Enter only the Jira HTTPS origin";
|
|
59
|
+
}
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return "Enter a valid HTTPS URL";
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export async function runSetup(configPath, interactive, dependencies, prompts = clackSetupPrompts, mode = "full") {
|
|
68
|
+
if (mode === "compact" && hasValidStoredConfig(configPath))
|
|
69
|
+
return;
|
|
70
|
+
if (!interactive)
|
|
71
|
+
throw new Error("workctl jira configure requires an interactive terminal.");
|
|
72
|
+
let stored;
|
|
73
|
+
let introduced = false;
|
|
74
|
+
try {
|
|
75
|
+
stored = readStoredConfig(configPath);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
if (!(error instanceof ConfigFileError))
|
|
79
|
+
throw error;
|
|
80
|
+
prompts.intro("workctl jira configure");
|
|
81
|
+
introduced = true;
|
|
82
|
+
prompts.note(error.message, "Invalid configuration file");
|
|
83
|
+
const reset = await prompts.confirm({
|
|
84
|
+
message: "Reset the invalid configuration and start from defaults?",
|
|
85
|
+
initialValue: false,
|
|
86
|
+
});
|
|
87
|
+
if (!reset)
|
|
88
|
+
throw new SetupCancelledError();
|
|
89
|
+
stored = {};
|
|
90
|
+
}
|
|
91
|
+
if (!introduced)
|
|
92
|
+
prompts.intro(mode === "compact" ? "workctl setup · jira" : "workctl jira configure");
|
|
93
|
+
let jiraBaseUrl = stored.jiraBaseUrl ?? DEFAULTS.jiraBaseUrl;
|
|
94
|
+
let jiraEmail = stored.jiraEmail ?? "";
|
|
95
|
+
let jiraApiToken = stored.jiraApiToken ?? "";
|
|
96
|
+
let timesheetUrl = stored.timesheetUrl ?? DEFAULTS.timesheetUrl;
|
|
97
|
+
let timezone = stored.timezone ?? DEFAULTS.timezone;
|
|
98
|
+
let projects = isLinkAuditProjects(stored.linkAudit) ? { ...stored.linkAudit.projects } : {};
|
|
99
|
+
const sections = mode === "compact"
|
|
100
|
+
? ["credentials"]
|
|
101
|
+
: await prompts.multiselect({
|
|
102
|
+
message: "Select configuration sections to edit",
|
|
103
|
+
options: [
|
|
104
|
+
{ value: "credentials", label: "Jira credentials" },
|
|
105
|
+
{ value: "services", label: "Service defaults" },
|
|
106
|
+
{ value: "linkAudit", label: "Link Status Audit" },
|
|
107
|
+
],
|
|
108
|
+
initialValues: jiraEmail && jiraApiToken ? [] : ["credentials"],
|
|
109
|
+
required: false,
|
|
110
|
+
});
|
|
111
|
+
if (sections.includes("services")) {
|
|
112
|
+
jiraBaseUrl = await prompts.text({
|
|
113
|
+
message: "Jira base URL",
|
|
114
|
+
initialValue: jiraBaseUrl,
|
|
115
|
+
validate: urlValidator("jira"),
|
|
116
|
+
});
|
|
117
|
+
timesheetUrl = await prompts.text({
|
|
118
|
+
message: "Kawari timesheet URL",
|
|
119
|
+
initialValue: timesheetUrl,
|
|
120
|
+
validate: urlValidator("timesheet"),
|
|
121
|
+
});
|
|
122
|
+
timezone = await prompts.text({
|
|
123
|
+
message: "Timezone",
|
|
124
|
+
initialValue: timezone,
|
|
125
|
+
validate: (value) => value?.trim() === "Asia/Bangkok"
|
|
126
|
+
? undefined
|
|
127
|
+
: "Timezone must be Asia/Bangkok",
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
if (sections.includes("credentials")) {
|
|
131
|
+
jiraEmail = await prompts.text({
|
|
132
|
+
message: "Jira email",
|
|
133
|
+
...(jiraEmail ? { initialValue: jiraEmail } : {}),
|
|
134
|
+
validate: required("Jira email"),
|
|
135
|
+
});
|
|
136
|
+
const enteredToken = await prompts.password({
|
|
137
|
+
message: jiraApiToken
|
|
138
|
+
? "Jira API token (press Enter to keep the configured token)"
|
|
139
|
+
: "Jira API token",
|
|
140
|
+
validate: jiraApiToken ? () => undefined : required("Jira API token"),
|
|
141
|
+
});
|
|
142
|
+
jiraApiToken = enteredToken.trim() || jiraApiToken;
|
|
143
|
+
}
|
|
144
|
+
if (!jiraEmail || !jiraApiToken) {
|
|
145
|
+
throw new Error("Jira credentials are required; select Jira credentials to configure them.");
|
|
146
|
+
}
|
|
147
|
+
if (sections.includes("linkAudit")) {
|
|
148
|
+
const client = dependencies.createJiraClient(jiraBaseUrl, jiraEmail, jiraApiToken);
|
|
149
|
+
const availableProjects = await client.listProjects();
|
|
150
|
+
const selectedKeys = await prompts.multiselect({
|
|
151
|
+
message: "Select Jira projects in the Link Audit Scope",
|
|
152
|
+
options: availableProjects.map((project) => ({
|
|
153
|
+
value: project.key,
|
|
154
|
+
label: `${project.key} — ${project.name}`,
|
|
155
|
+
})),
|
|
156
|
+
initialValues: Object.keys(projects),
|
|
157
|
+
required: false,
|
|
158
|
+
});
|
|
159
|
+
projects = {};
|
|
160
|
+
for (const projectKey of selectedKeys) {
|
|
161
|
+
const statuses = await client.listProjectStatuses(projectKey);
|
|
162
|
+
const selectedStatuses = await prompts.multiselect({
|
|
163
|
+
message: `Select Done Statuses for ${projectKey}`,
|
|
164
|
+
options: statuses.map((status) => ({ value: status.name, label: status.name })),
|
|
165
|
+
initialValues: isLinkAuditProjects(stored.linkAudit)
|
|
166
|
+
? stored.linkAudit.projects[projectKey]?.doneStatuses ?? []
|
|
167
|
+
: [],
|
|
168
|
+
required: true,
|
|
169
|
+
});
|
|
170
|
+
projects[projectKey] = { doneStatuses: selectedStatuses };
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const config = validateConfig({
|
|
174
|
+
jiraBaseUrl,
|
|
175
|
+
jiraEmail,
|
|
176
|
+
jiraApiToken,
|
|
177
|
+
timesheetUrl,
|
|
178
|
+
timezone,
|
|
179
|
+
...(Object.keys(projects).length > 0 ? { linkAudit: { projects } } : {}),
|
|
180
|
+
});
|
|
181
|
+
prompts.note([
|
|
182
|
+
`Jira base URL: ${config.jiraBaseUrl}`,
|
|
183
|
+
`Jira email: ${config.jiraEmail}`,
|
|
184
|
+
"Jira API token: <redacted>",
|
|
185
|
+
`Timesheet URL: ${config.timesheetUrl}`,
|
|
186
|
+
`Timezone: ${config.timezone}`,
|
|
187
|
+
...(config.linkAudit
|
|
188
|
+
? [`Link Audit Scope: ${Object.keys(config.linkAudit.projects).join(", ")}`]
|
|
189
|
+
: []),
|
|
190
|
+
`Config path: ${configPath}`,
|
|
191
|
+
].join("\n"), "Configuration summary");
|
|
192
|
+
const save = await prompts.confirm({
|
|
193
|
+
message: "Save this configuration?",
|
|
194
|
+
initialValue: true,
|
|
195
|
+
});
|
|
196
|
+
if (!save)
|
|
197
|
+
throw new SetupCancelledError();
|
|
198
|
+
await dependencies.writeConfig(configPath, config);
|
|
199
|
+
prompts.outro("Configuration saved. Run `workctl jira doctor` to verify your setup.");
|
|
200
|
+
}
|
|
201
|
+
function isLinkAuditProjects(value) {
|
|
202
|
+
return typeof value === "object" && value !== null &&
|
|
203
|
+
"projects" in value && typeof value.projects === "object" && value.projects !== null;
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=configure.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configure.service.js","sourceRoot":"","sources":["../../../../../../../packages/capabilities/jira/src/commands/configure/configure.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,EACL,eAAe,EAEf,gBAAgB,EAChB,cAAc,GACf,MAAM,iBAAiB,CAAC;AAGzB,MAAM,QAAQ,GAAG;IACf,WAAW,EAAE,qCAAqC;IAClD,YAAY,EAAE,+CAA+C;IAC7D,QAAQ,EAAE,cAAc;CAChB,CAAC;AAEX,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C;QACE,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACzD,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAoCD,SAAS,MAAM,CAAI,KAAiB;IAClC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,KAAK,CAAC,MAAM,CAAC,iDAAiD,CAAC,CAAC;QAChE,MAAM,IAAI,mBAAmB,EAAE,CAAC;IAClC,CAAC;IACD,OAAO,KAAU,CAAC;AACpB,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAiB;IAC7C,KAAK,EAAE,KAAK,CAAC,KAAK;IAClB,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1D,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,QAAQ,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;IACpF,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAChE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,WAAW,CAAC;QAC7D,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;QAC7B,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/E,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1E,CAAC,CAAC;IACH,IAAI,EAAE,KAAK,CAAC,IAAI;IAChB,KAAK,EAAE,KAAK,CAAC,KAAK;CACnB,CAAC;AAEF,MAAM,UAAU,oBAAoB,CAAC,UAAkB;IACrD,IAAI,CAAC;QACH,cAAc,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,KAAa;IAC7B,OAAO,CAAC,KAAyB,EAAsB,EAAE,CACvD,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,KAAK,cAAc,CAAC;AACvD,CAAC;AAED,SAAS,YAAY,CAAC,IAA0B;IAC9C,OAAO,CAAC,KAAyB,EAAsB,EAAE;QACvD,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,CAAC;QAChF,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAM,CAAC,CAAC;YAC5B,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;gBAC9D,OAAO,wCAAwC,CAAC;YAClD,CAAC;YACD,IAAI,IAAI,KAAK,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxE,OAAO,kCAAkC,CAAC;YAC5C,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,yBAAyB,CAAC;QACnC,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,UAAkB,EAClB,WAAoB,EACpB,YAAmC,EACnC,UAAwB,iBAAiB,EACzC,OAA2B,MAAM;IAEjC,IAAI,IAAI,KAAK,SAAS,IAAI,oBAAoB,CAAC,UAAU,CAAC;QAAE,OAAO;IACnE,IAAI,CAAC,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAE9F,IAAI,MAAM,CAAC;IACX,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,IAAI,CAAC;QACH,MAAM,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,CAAC,KAAK,YAAY,eAAe,CAAC;YAAE,MAAM,KAAK,CAAC;QACrD,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QACxC,UAAU,GAAG,IAAI,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,4BAA4B,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC;YAClC,OAAO,EAAE,0DAA0D;YACnE,YAAY,EAAE,KAAK;SACpB,CAAC,CAAC;QACH,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,mBAAmB,EAAE,CAAC;QAC5C,MAAM,GAAG,EAAE,CAAC;IACd,CAAC;IAED,IAAI,CAAC,UAAU;QAAE,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC;IACvG,IAAI,WAAW,GAAG,MAAM,CAAC,WAAW,IAAI,QAAQ,CAAC,WAAW,CAAC;IAC7D,IAAI,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC;IACvC,IAAI,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC;IAC7C,IAAI,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,QAAQ,CAAC,YAAY,CAAC;IAChE,IAAI,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC;IACpD,IAAI,QAAQ,GAAG,mBAAmB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAE7F,MAAM,QAAQ,GAAG,IAAI,KAAK,SAAS;QACjC,CAAC,CAAC,CAAC,aAAa,CAAC;QACjB,CAAC,CAAC,MAAM,OAAO,CAAC,WAAW,CAAC;YAC1B,OAAO,EAAE,uCAAuC;YAChD,OAAO,EAAE;gBACP,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,kBAAkB,EAAE;gBACnD,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,kBAAkB,EAAE;gBAChD,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAmB,EAAE;aACnD;YACD,aAAa,EAAE,SAAS,IAAI,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;YAC/D,QAAQ,EAAE,KAAK;SAChB,CAAC,CAAC;IAEL,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAClC,WAAW,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;YAC/B,OAAO,EAAE,eAAe;YACxB,YAAY,EAAE,WAAW;YACzB,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAC;SAC/B,CAAC,CAAC;QACH,YAAY,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;YAChC,OAAO,EAAE,sBAAsB;YAC/B,YAAY,EAAE,YAAY;YAC1B,QAAQ,EAAE,YAAY,CAAC,WAAW,CAAC;SACpC,CAAC,CAAC;QACH,QAAQ,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;YAC5B,OAAO,EAAE,UAAU;YACnB,YAAY,EAAE,QAAQ;YACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,cAAc;gBACnD,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,+BAA+B;SACpC,CAAC,CAAC;IACL,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QACrC,SAAS,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;YAC7B,OAAO,EAAE,YAAY;YACrB,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjD,QAAQ,EAAE,QAAQ,CAAC,YAAY,CAAC;SACjC,CAAC,CAAC;QACH,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC;YAC1C,OAAO,EAAE,YAAY;gBACnB,CAAC,CAAC,2DAA2D;gBAC7D,CAAC,CAAC,gBAAgB;YACpB,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC;SACtE,CAAC,CAAC;QACH,YAAY,GAAG,YAAY,CAAC,IAAI,EAAE,IAAI,YAAY,CAAC;IACrD,CAAC;IACD,IAAI,CAAC,SAAS,IAAI,CAAC,YAAY,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;IAC/F,CAAC;IAED,IAAI,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,YAAY,CAAC,gBAAgB,CAAC,WAAW,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;QACnF,MAAM,iBAAiB,GAAG,MAAM,MAAM,CAAC,YAAY,EAAE,CAAC;QACtD,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;YAC7C,OAAO,EAAE,8CAA8C;YACvD,OAAO,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBAC3C,KAAK,EAAE,OAAO,CAAC,GAAG;gBAClB,KAAK,EAAE,GAAG,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE;aAC1C,CAAC,CAAC;YACH,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;YACpC,QAAQ,EAAE,KAAK;SAChB,CAAC,CAAC;QACH,QAAQ,GAAG,EAAE,CAAC;QACd,KAAK,MAAM,UAAU,IAAI,YAAY,EAAE,CAAC;YACtC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;YAC9D,MAAM,gBAAgB,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;gBACjD,OAAO,EAAE,4BAA4B,UAAU,EAAE;gBACjD,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;gBAC/E,aAAa,EAAE,mBAAmB,CAAC,MAAM,CAAC,SAAS,CAAC;oBAClD,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,YAAY,IAAI,EAAE;oBAC3D,CAAC,CAAC,EAAE;gBACN,QAAQ,EAAE,IAAI;aACf,CAAC,CAAC;YACH,QAAQ,CAAC,UAAU,CAAC,GAAG,EAAE,YAAY,EAAE,gBAAgB,EAAE,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,cAAc,CAAC;QAC5B,WAAW;QACX,SAAS;QACT,YAAY;QACZ,YAAY;QACZ,QAAQ;QACR,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACzE,CAAC,CAAC;IACH,OAAO,CAAC,IAAI,CACV;QACE,kBAAkB,MAAM,CAAC,WAAW,EAAE;QACtC,eAAe,MAAM,CAAC,SAAS,EAAE;QACjC,4BAA4B;QAC5B,kBAAkB,MAAM,CAAC,YAAY,EAAE;QACvC,aAAa,MAAM,CAAC,QAAQ,EAAE;QAC9B,GAAG,CAAC,MAAM,CAAC,SAAS;YAClB,CAAC,CAAC,CAAC,qBAAqB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5E,CAAC,CAAC,EAAE,CAAC;QACP,gBAAgB,UAAU,EAAE;KAC7B,CAAC,IAAI,CAAC,IAAI,CAAC,EACZ,uBAAuB,CACxB,CAAC;IACF,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC;QACjC,OAAO,EAAE,0BAA0B;QACnC,YAAY,EAAE,IAAI;KACnB,CAAC,CAAC;IACH,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,mBAAmB,EAAE,CAAC;IAC3C,MAAM,YAAY,CAAC,WAAW,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACnD,OAAO,CAAC,KAAK,CAAC,sEAAsE,CAAC,CAAC;AACxF,CAAC;AAED,SAAS,mBAAmB,CAC1B,KAAc;IAEd,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAChD,UAAU,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC;AACzF,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CommanderError } from "commander";
|
|
2
|
+
import { CliInteractionError } from "../../cli/errors.js";
|
|
3
|
+
export function registerDoctorCommand({ program, dependencies, effectiveConfig, output }) {
|
|
4
|
+
program
|
|
5
|
+
.command("doctor")
|
|
6
|
+
.description("check local configuration, Jira access, and browser installation")
|
|
7
|
+
.action(async () => {
|
|
8
|
+
if (!dependencies.doctor)
|
|
9
|
+
throw new CliInteractionError("workctl jira doctor is unavailable.");
|
|
10
|
+
const checks = await dependencies.doctor(effectiveConfig().config);
|
|
11
|
+
output(`${checks.map((check) => `${check.ok ? "PASS" : "FAIL"} ${check.name}: ${check.detail}`).join("\n")}\n`, "Doctor");
|
|
12
|
+
if (checks.some((check) => !check.ok)) {
|
|
13
|
+
throw new CommanderError(1, "doctor.failed", "One or more doctor checks failed.");
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=doctor.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.command.js","sourceRoot":"","sources":["../../../../../../../packages/capabilities/jira/src/commands/doctor/doctor.command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAG1D,MAAM,UAAU,qBAAqB,CACnC,EAAE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,EAAkB;IAElE,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,kEAAkE,CAAC;SAC/E,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,IAAI,CAAC,YAAY,CAAC,MAAM;YAAE,MAAM,IAAI,mBAAmB,CAAC,qCAAqC,CAAC,CAAC;QAC/F,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,MAAM,CAAC,CAAC;QACnE,MAAM,CACJ,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CACtB,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,EAAE,CAChE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAChB,QAAQ,CACT,CAAC;QACF,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,cAAc,CAAC,CAAC,EAAE,eAAe,EAAE,mCAAmC,CAAC,CAAC;QACpF,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AppConfig } from "../../config.js";
|
|
2
|
+
export interface DoctorPaths {
|
|
3
|
+
root: string;
|
|
4
|
+
configRoot: string;
|
|
5
|
+
configFile: string;
|
|
6
|
+
}
|
|
7
|
+
export interface DoctorCheck {
|
|
8
|
+
name: string;
|
|
9
|
+
ok: boolean;
|
|
10
|
+
detail: string;
|
|
11
|
+
}
|
|
12
|
+
export interface DoctorDependencies {
|
|
13
|
+
authenticateJira(config: AppConfig): Promise<void>;
|
|
14
|
+
browserExecutablePath(): string;
|
|
15
|
+
platform?: NodeJS.Platform;
|
|
16
|
+
}
|
|
17
|
+
export declare function runDoctor(config: AppConfig, paths: DoctorPaths, dependencies: DoctorDependencies): Promise<DoctorCheck[]>;
|
|
18
|
+
export declare const playwrightExecutablePath: () => string;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { access, stat } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { chromium } from "playwright";
|
|
5
|
+
async function permissionCheck(name, target, expectedMode, platform) {
|
|
6
|
+
if (platform === "win32") {
|
|
7
|
+
try {
|
|
8
|
+
await access(target, constants.R_OK | constants.W_OK);
|
|
9
|
+
return { name, ok: true, detail: `${target} is accessible` };
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return { name, ok: false, detail: `${target} does not exist or is not accessible` };
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const details = await stat(target);
|
|
17
|
+
const mode = details.mode & 0o777;
|
|
18
|
+
return mode === expectedMode
|
|
19
|
+
? { name, ok: true, detail: `${target} (${mode.toString(8)})` }
|
|
20
|
+
: {
|
|
21
|
+
name,
|
|
22
|
+
ok: false,
|
|
23
|
+
detail: `${target} has mode ${mode.toString(8)}; expected ${expectedMode.toString(8)}`,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return { name, ok: false, detail: `${target} does not exist` };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export async function runDoctor(config, paths, dependencies) {
|
|
31
|
+
const platform = dependencies.platform ?? process.platform;
|
|
32
|
+
const checks = [];
|
|
33
|
+
checks.push(await permissionCheck("Config directory", paths.configRoot, 0o700, platform));
|
|
34
|
+
checks.push(await permissionCheck("Config file", paths.configFile, 0o600, platform));
|
|
35
|
+
const dataProbe = paths.root;
|
|
36
|
+
try {
|
|
37
|
+
await access(dataProbe, constants.R_OK | constants.W_OK);
|
|
38
|
+
checks.push({ name: "Data directory", ok: true, detail: `${dataProbe} is accessible` });
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
try {
|
|
42
|
+
const home = path.dirname(path.dirname(paths.configRoot));
|
|
43
|
+
await access(home, constants.R_OK | constants.W_OK);
|
|
44
|
+
checks.push({
|
|
45
|
+
name: "Data directory",
|
|
46
|
+
ok: true,
|
|
47
|
+
detail: `${dataProbe} will be created on first use`,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
checks.push({
|
|
52
|
+
name: "Data directory",
|
|
53
|
+
ok: false,
|
|
54
|
+
detail: `${dataProbe} cannot be created or accessed`,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
await dependencies.authenticateJira(config);
|
|
60
|
+
checks.push({ name: "Jira authentication", ok: true, detail: "credentials accepted" });
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
checks.push({
|
|
64
|
+
name: "Jira authentication",
|
|
65
|
+
ok: false,
|
|
66
|
+
detail: error instanceof Error ? error.message : "authentication failed",
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
const executable = dependencies.browserExecutablePath();
|
|
70
|
+
try {
|
|
71
|
+
await access(executable, platform === "win32" ? constants.F_OK : constants.X_OK);
|
|
72
|
+
checks.push({ name: "Playwright Chromium", ok: true, detail: executable });
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
checks.push({
|
|
76
|
+
name: "Playwright Chromium",
|
|
77
|
+
ok: false,
|
|
78
|
+
detail: "browser is missing; run `workctl browsers install`",
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return checks;
|
|
82
|
+
}
|
|
83
|
+
export const playwrightExecutablePath = () => chromium.executablePath();
|
|
84
|
+
//# sourceMappingURL=doctor.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.service.js","sourceRoot":"","sources":["../../../../../../../packages/capabilities/jira/src/commands/doctor/doctor.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { CommanderError } from "commander";
|
|
2
|
+
import { resolveDateRange } from "../../domain/date-range.js";
|
|
3
|
+
import { classifyGrid } from "../../domain/timesheet-entry.js";
|
|
4
|
+
import { JiraClientError } from "../../ports/jira.js";
|
|
5
|
+
import { formatHours } from "../../presentation.js";
|
|
6
|
+
import { CliInteractionError } from "../../cli/errors.js";
|
|
7
|
+
import { createRollbackPreview, formatRollbackPreview, } from "./rollback.service.js";
|
|
8
|
+
const JIRA_KEY = /^[A-Z][A-Z0-9]*-\d+$/;
|
|
9
|
+
export function registerRollbackCommand({ program, io, dependencies, effectiveConfig }) {
|
|
10
|
+
const interaction = io.interaction ?? io.batchInteraction;
|
|
11
|
+
const info = (message) => {
|
|
12
|
+
if (interaction)
|
|
13
|
+
interaction.info(message.trimEnd());
|
|
14
|
+
else
|
|
15
|
+
io.stdout(message);
|
|
16
|
+
};
|
|
17
|
+
const success = (message) => {
|
|
18
|
+
if (interaction)
|
|
19
|
+
interaction.success(message.trimEnd());
|
|
20
|
+
else
|
|
21
|
+
io.stdout(message);
|
|
22
|
+
};
|
|
23
|
+
const failure = (message, title = "Error") => {
|
|
24
|
+
if (interaction)
|
|
25
|
+
interaction.errorBlock(title, message.trimEnd());
|
|
26
|
+
else
|
|
27
|
+
io.stderr(message);
|
|
28
|
+
};
|
|
29
|
+
program
|
|
30
|
+
.command("rollback")
|
|
31
|
+
.description("delete tool-managed Jira worklogs and restore remaining estimates")
|
|
32
|
+
.option("--from <date>", "start date in YYYY-MM-DD format")
|
|
33
|
+
.option("--to <date>", "end date in YYYY-MM-DD format")
|
|
34
|
+
.option("--issue <key>", "also search a previous Jira issue key (repeatable)", (value, previous) => [...previous, value], [])
|
|
35
|
+
.option("--dry-run", "show rollback candidates without deleting worklogs")
|
|
36
|
+
.action(async (options) => {
|
|
37
|
+
const supplementalKeys = options.issue.map((key) => key.trim().toUpperCase());
|
|
38
|
+
const invalidKey = supplementalKeys.find((key) => !JIRA_KEY.test(key));
|
|
39
|
+
if (invalidKey) {
|
|
40
|
+
throw new CommanderError(2, "rollback.invalidIssue", `Invalid Jira issue key "${invalidKey}".`);
|
|
41
|
+
}
|
|
42
|
+
if (!dependencies.readCurrentJiraAccount || !dependencies.deleteJiraWorklog) {
|
|
43
|
+
throw new CliInteractionError("Jira worklog rollback is unavailable.");
|
|
44
|
+
}
|
|
45
|
+
const config = effectiveConfig().config;
|
|
46
|
+
let range = resolveDateRange(options.from, options.to);
|
|
47
|
+
if (options.from === undefined && options.to === undefined && interaction) {
|
|
48
|
+
const selectedRange = await interaction.requestDateRange("rollback", range);
|
|
49
|
+
if (!selectedRange)
|
|
50
|
+
return;
|
|
51
|
+
range = selectedRange;
|
|
52
|
+
}
|
|
53
|
+
interaction?.begin("rollback", range.from, range.to);
|
|
54
|
+
interaction?.startLoading("Opening Kawari timesheet");
|
|
55
|
+
let inspection;
|
|
56
|
+
try {
|
|
57
|
+
inspection = await dependencies.inspect(config.timesheetUrl, range.from.slice(0, 7));
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
interaction?.failLoading("Failed to load Kawari timesheet");
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
const classified = classifyGrid(inspection.grid, range);
|
|
64
|
+
const batchEntries = [...classified.eligible, ...classified.unmapped];
|
|
65
|
+
const entryCount = batchEntries.length +
|
|
66
|
+
classified.invalid.length +
|
|
67
|
+
classified.zeroDuration.length;
|
|
68
|
+
const batchHours = batchEntries.reduce((total, entry) => total + entry.duration, 0);
|
|
69
|
+
interaction?.stopLoading(`Loaded ${entryCount} ${entryCount === 1 ? "entry" : "entries"} · ${formatHours(batchHours)}`);
|
|
70
|
+
if (classified.invalid.length > 0) {
|
|
71
|
+
throw new CommanderError(1, "rollback.blocked", "Invalid Timesheet Entries block the rollback batch.");
|
|
72
|
+
}
|
|
73
|
+
const issueKeys = [
|
|
74
|
+
...new Set([
|
|
75
|
+
...classified.eligible.flatMap((entry) => entry.jiraKey ? [entry.jiraKey] : []),
|
|
76
|
+
...supplementalKeys,
|
|
77
|
+
]),
|
|
78
|
+
];
|
|
79
|
+
const account = await dependencies.readCurrentJiraAccount(config);
|
|
80
|
+
const issues = [];
|
|
81
|
+
for (const [index, issueKey] of issueKeys.entries()) {
|
|
82
|
+
const message = `Loading rollback worklogs · ${issueKey} · ${index + 1}/${issueKeys.length}`;
|
|
83
|
+
if (interaction) {
|
|
84
|
+
if (index === 0)
|
|
85
|
+
interaction.startLoading(message);
|
|
86
|
+
else
|
|
87
|
+
interaction.updateLoading(message);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
io.stdout(`${message}\n`);
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
issues.push(await dependencies.readJiraIssue(config, issueKey));
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
interaction?.failLoading("Could not load rollback worklogs");
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (issueKeys.length > 0)
|
|
101
|
+
interaction?.stopLoading("Loaded rollback worklogs");
|
|
102
|
+
const preview = createRollbackPreview(classified.eligible, issues, account.accountId);
|
|
103
|
+
const presentation = {
|
|
104
|
+
color: io.color === true,
|
|
105
|
+
...(io.terminalWidth ? { terminalWidth: io.terminalWidth } : {}),
|
|
106
|
+
};
|
|
107
|
+
const formattedPreview = formatRollbackPreview(preview, presentation);
|
|
108
|
+
if (interaction)
|
|
109
|
+
interaction.note("Rollback preview", formattedPreview.trimEnd());
|
|
110
|
+
else
|
|
111
|
+
io.stdout(formattedPreview);
|
|
112
|
+
if (preview.blockers.length > 0) {
|
|
113
|
+
throw new CommanderError(1, "rollback.blocked", "Rollback blockers must be resolved before any worklog is deleted.");
|
|
114
|
+
}
|
|
115
|
+
if (options.dryRun) {
|
|
116
|
+
interaction?.complete("Rollback dry run complete. No Jira worklogs were changed.");
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (preview.candidates.length === 0) {
|
|
120
|
+
interaction?.complete("Rollback complete. No matching worklogs were found.");
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (!interaction && !io.requestApproval) {
|
|
124
|
+
throw new CommanderError(1, "rollback.interactiveRequired", "Jira worklog rollback requires an interactive terminal.");
|
|
125
|
+
}
|
|
126
|
+
const expected = `delete ${preview.candidates.length}`;
|
|
127
|
+
const approved = interaction
|
|
128
|
+
? await interaction.confirmWorklogDeletion(preview.candidates.length)
|
|
129
|
+
: (await io.requestApproval(`Type "${expected}" to permanently delete these worklogs: `))
|
|
130
|
+
.trim() === expected;
|
|
131
|
+
if (!approved) {
|
|
132
|
+
if (interaction)
|
|
133
|
+
interaction.cancelled("Cancelled; no Jira worklogs were deleted.");
|
|
134
|
+
else
|
|
135
|
+
io.stdout("Cancelled; no Jira worklogs were deleted.\n");
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const results = [];
|
|
139
|
+
for (const candidate of preview.candidates) {
|
|
140
|
+
try {
|
|
141
|
+
await dependencies.deleteJiraWorklog(config, candidate.issueKey, candidate.worklogId);
|
|
142
|
+
results.push({ ...candidate, status: "Succeeded", detail: "Deleted" });
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
results.push({
|
|
146
|
+
...candidate,
|
|
147
|
+
status: "Failed",
|
|
148
|
+
detail: error instanceof JiraClientError
|
|
149
|
+
? error.message
|
|
150
|
+
: `Could not delete worklog ${candidate.worklogId}.`,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
let verificationFailed = false;
|
|
155
|
+
let unresolvedWorklogIds;
|
|
156
|
+
try {
|
|
157
|
+
const verifiedIssues = await Promise.all(issueKeys.map((issueKey) => dependencies.readJiraIssue(config, issueKey)));
|
|
158
|
+
const remainingIds = new Set(verifiedIssues.flatMap((issue) => issue.worklogs.map((worklog) => worklog.id)));
|
|
159
|
+
unresolvedWorklogIds = preview.candidates
|
|
160
|
+
.filter((candidate) => remainingIds.has(candidate.worklogId))
|
|
161
|
+
.map((candidate) => candidate.worklogId);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
verificationFailed = true;
|
|
165
|
+
unresolvedWorklogIds = preview.candidates.map((candidate) => candidate.worklogId);
|
|
166
|
+
}
|
|
167
|
+
const receipt = {
|
|
168
|
+
command: "rollback",
|
|
169
|
+
from: range.from,
|
|
170
|
+
to: range.to,
|
|
171
|
+
estimateAdjustment: "auto",
|
|
172
|
+
candidates: preview.candidates,
|
|
173
|
+
results,
|
|
174
|
+
unresolvedWorklogIds,
|
|
175
|
+
};
|
|
176
|
+
try {
|
|
177
|
+
const destination = await dependencies.writeRollbackReceipt(receipt);
|
|
178
|
+
info(`Rollback receipt: ${destination}\n`);
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
throw new CliInteractionError("Worklogs were processed, but the rollback receipt could not be written.");
|
|
182
|
+
}
|
|
183
|
+
const failed = results.filter((result) => result.status === "Failed");
|
|
184
|
+
for (const result of results) {
|
|
185
|
+
const message = `${result.status.toUpperCase()} ${result.issueKey} worklog ${result.worklogId} ` +
|
|
186
|
+
`${formatHours(result.hours)}: ${result.detail}\n`;
|
|
187
|
+
if (result.status === "Succeeded")
|
|
188
|
+
success(message);
|
|
189
|
+
else
|
|
190
|
+
failure(message, "Rollback failed");
|
|
191
|
+
}
|
|
192
|
+
if (failed.length > 0 || unresolvedWorklogIds.length > 0 || verificationFailed) {
|
|
193
|
+
throw new CommanderError(1, "rollback.partialFailure", "One or more Jira worklogs could not be deleted and verified.");
|
|
194
|
+
}
|
|
195
|
+
interaction?.complete("Rollback complete and verified.");
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=rollback.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rollback.command.js","sourceRoot":"","sources":["../../../../../../../packages/capabilities/jira/src/commands/rollback/rollback.command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type PresentationOptions } from "../../presentation.js";
|
|
2
|
+
import type { JiraIssueSnapshot } from "../../ports/jira.js";
|
|
3
|
+
import type { TimesheetEntry } from "../../domain/timesheet-entry.js";
|
|
4
|
+
export type RollbackCandidateKind = "Matched" | "Conflict";
|
|
5
|
+
export interface RollbackCandidate {
|
|
6
|
+
kind: RollbackCandidateKind;
|
|
7
|
+
sourceIdentity: string;
|
|
8
|
+
issueKey: string;
|
|
9
|
+
worklogId: string;
|
|
10
|
+
date: string;
|
|
11
|
+
hours: number;
|
|
12
|
+
}
|
|
13
|
+
export interface RollbackBlocker {
|
|
14
|
+
issueKey: string;
|
|
15
|
+
worklogId: string;
|
|
16
|
+
reason: string;
|
|
17
|
+
}
|
|
18
|
+
export interface RollbackPreview {
|
|
19
|
+
candidates: RollbackCandidate[];
|
|
20
|
+
blockers: RollbackBlocker[];
|
|
21
|
+
}
|
|
22
|
+
export interface RollbackDeleteResult extends RollbackCandidate {
|
|
23
|
+
status: "Succeeded" | "Failed";
|
|
24
|
+
detail: string;
|
|
25
|
+
}
|
|
26
|
+
export interface RollbackReceipt {
|
|
27
|
+
command: "rollback";
|
|
28
|
+
from: string;
|
|
29
|
+
to: string;
|
|
30
|
+
estimateAdjustment: "auto";
|
|
31
|
+
candidates: readonly RollbackCandidate[];
|
|
32
|
+
results: readonly RollbackDeleteResult[];
|
|
33
|
+
unresolvedWorklogIds: readonly string[];
|
|
34
|
+
}
|
|
35
|
+
export declare function createRollbackPreview(entries: readonly TimesheetEntry[], issues: readonly JiraIssueSnapshot[], currentAccountId: string): RollbackPreview;
|
|
36
|
+
export declare function formatRollbackPreview(preview: RollbackPreview, options?: PresentationOptions): string;
|
|
37
|
+
export declare function writeRollbackReceipt(directory: string, receipt: RollbackReceipt, now?: Date): Promise<string>;
|