@knpkv/jira-cli 1.4.0 → 1.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/CHANGELOG.md +29 -0
- package/README.md +4 -1
- package/dist/JiraAuth.d.ts +26 -8
- package/dist/JiraAuth.d.ts.map +1 -1
- package/dist/JiraAuth.js +12 -303
- package/dist/JiraAuth.js.map +1 -1
- package/dist/commands/auth.d.ts +1 -12
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +4 -128
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/layers.d.ts +1 -1
- package/dist/commands/layers.d.ts.map +1 -1
- package/package.json +4 -4
- package/skills/jira/SKILL.md +1 -0
- package/src/JiraAuth.ts +28 -468
- package/src/commands/auth.ts +4 -167
- package/test/JiraAuth.test.ts +79 -0
- package/test/authCommand.test.ts +54 -0
- package/vitest.config.integration.ts +4 -1
- package/vitest.config.ts +4 -1
- package/dist/internal/NodeLayers.d.ts +0 -7
- package/dist/internal/NodeLayers.d.ts.map +0 -1
- package/dist/internal/NodeLayers.js +0 -15
- package/dist/internal/NodeLayers.js.map +0 -1
- package/dist/internal/oauthServer.d.ts +0 -72
- package/dist/internal/oauthServer.d.ts.map +0 -1
- package/dist/internal/oauthServer.js +0 -97
- package/dist/internal/oauthServer.js.map +0 -1
- package/dist/internal/openBrowser.d.ts +0 -10
- package/dist/internal/openBrowser.d.ts.map +0 -1
- package/dist/internal/openBrowser.js +0 -17
- package/dist/internal/openBrowser.js.map +0 -1
- package/src/internal/NodeLayers.ts +0 -17
- package/src/internal/oauthServer.ts +0 -187
- package/src/internal/openBrowser.ts +0 -31
- package/test/JiraAuthRefresh.test.ts +0 -269
- package/test/oauthServer.test.ts +0 -172
package/dist/commands/auth.js
CHANGED
|
@@ -1,133 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* **Mental model**
|
|
5
|
-
*
|
|
6
|
-
* - Each command is a standalone `Command.make` that yields into `JiraAuth` service methods.
|
|
7
|
-
* - `create` opens the Atlassian Developer Console; `configure` prompts for client ID/secret.
|
|
2
|
+
* `jira auth`: the shared Atlassian auth commands over {@link JiraAuth}.
|
|
8
3
|
*
|
|
9
4
|
* @internal
|
|
10
5
|
*/
|
|
11
|
-
import {
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
import * as Option from "effect/Option";
|
|
15
|
-
import { openBrowser } from "../internal/openBrowser.js";
|
|
16
|
-
import { JiraAuth } from "../JiraAuth.js";
|
|
17
|
-
// === Auth create command ===
|
|
18
|
-
const createCommand = Command.make("create", {}, () => Effect.gen(function* () {
|
|
19
|
-
yield* Console.log(`
|
|
20
|
-
Creating OAuth app in Atlassian Developer Console...
|
|
21
|
-
|
|
22
|
-
1. Browser will open to create a new OAuth 2.0 (3LO) app
|
|
23
|
-
2. Enter app name (e.g., "Jira CLI")
|
|
24
|
-
3. After creation, go to "Permissions" and add:
|
|
25
|
-
|
|
26
|
-
Jira API:
|
|
27
|
-
- read:jira-work Search and read issues, comments, attachments
|
|
28
|
-
- read:jira-user Read user info for assignee/reporter fields
|
|
29
|
-
|
|
30
|
-
User Identity API:
|
|
31
|
-
- read:me Get your account ID and email for auth
|
|
32
|
-
|
|
33
|
-
4. Go to "Authorization" and set callback URL:
|
|
34
|
-
http://localhost:8585/callback
|
|
35
|
-
5. Go to "Settings" and copy Client ID and Secret
|
|
36
|
-
6. Run: jira auth configure --client-id <ID> --client-secret <SECRET>
|
|
37
|
-
`);
|
|
38
|
-
const url = "https://developer.atlassian.com/console/myapps/create-3lo-app/";
|
|
39
|
-
yield* openBrowser(url).pipe(Effect.catch(() => Effect.void));
|
|
40
|
-
})).pipe(Command.withDescription("Create OAuth app in Atlassian Developer Console"));
|
|
41
|
-
// === Auth configure command ===
|
|
42
|
-
const clientIdOption = Options.String("client-id").pipe(Options.withDescription("OAuth client ID from Atlassian Developer Console"), Options.optional);
|
|
43
|
-
const clientSecretOption = Options.String("client-secret").pipe(Options.withDescription("OAuth client secret"), Options.optional);
|
|
44
|
-
const configureCommand = Command.make("configure", { clientId: clientIdOption, clientSecret: clientSecretOption }, ({ clientId, clientSecret }) => Effect.gen(function* () {
|
|
45
|
-
const auth = yield* JiraAuth;
|
|
46
|
-
const rawClientId = Option.isSome(clientId)
|
|
47
|
-
? clientId.value
|
|
48
|
-
: yield* Prompt.String({ message: "Enter OAuth client ID:" });
|
|
49
|
-
const rawClientSecret = Option.isSome(clientSecret)
|
|
50
|
-
? clientSecret.value
|
|
51
|
-
: yield* Prompt.String({ message: "Enter OAuth client secret:" });
|
|
52
|
-
yield* auth.configure({ clientId: rawClientId, clientSecret: rawClientSecret });
|
|
53
|
-
yield* Console.log("OAuth configured. Run 'jira auth login' to authenticate.");
|
|
54
|
-
})).pipe(Command.withDescription("Configure OAuth client credentials"));
|
|
55
|
-
// === Auth login command ===
|
|
56
|
-
const siteOption = Options.String("site").pipe(Options.withDescription("Jira site URL to use (for accounts with multiple sites)"), Options.optional);
|
|
57
|
-
const loginCommand = Command.make("login", { site: siteOption }, ({ site }) => Effect.gen(function* () {
|
|
58
|
-
const auth = yield* JiraAuth;
|
|
59
|
-
const result = yield* auth.login(Option.isSome(site) ? { siteUrl: site.value } : undefined);
|
|
60
|
-
if (Array.isArray(result) && result.length > 0) {
|
|
61
|
-
yield* Console.log("\nRe-run with --site to select a specific site.");
|
|
62
|
-
}
|
|
63
|
-
})).pipe(Command.withDescription("Authenticate with Atlassian via OAuth"));
|
|
64
|
-
// === Auth logout command ===
|
|
65
|
-
const logoutCommand = Command.make("logout", {}, () => Effect.gen(function* () {
|
|
66
|
-
const auth = yield* JiraAuth;
|
|
67
|
-
yield* auth.logout();
|
|
68
|
-
yield* Console.log("Logged out");
|
|
69
|
-
})).pipe(Command.withDescription("Remove stored authentication"));
|
|
70
|
-
// === Auth status command ===
|
|
71
|
-
const statusCommand = Command.make("status", {}, () => Effect.gen(function* () {
|
|
72
|
-
const auth = yield* JiraAuth;
|
|
73
|
-
const profile = yield* auth.getActiveProfile();
|
|
74
|
-
if (profile) {
|
|
75
|
-
const user = profile.token.user;
|
|
76
|
-
const account = user ? `${user.name} (${user.email})` : "unknown user";
|
|
77
|
-
yield* Console.log(`Active profile: ${profile.name}`);
|
|
78
|
-
yield* Console.log(`Account: ${account}`);
|
|
79
|
-
yield* Console.log(`Site: ${profile.token.site_url}`);
|
|
80
|
-
yield* Console.log(`Profile ID: ${profile.id}`);
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
yield* Console.log("Not logged in. Use 'jira auth login' to authenticate.");
|
|
84
|
-
}
|
|
85
|
-
})).pipe(Command.withDescription("Show authentication status"));
|
|
86
|
-
// === Auth profiles command ===
|
|
87
|
-
const profilesCommand = Command.make("profiles", {}, () => Effect.gen(function* () {
|
|
88
|
-
const auth = yield* JiraAuth;
|
|
89
|
-
const [profiles, active] = yield* Effect.all([auth.listProfiles(), auth.getActiveProfile()]);
|
|
90
|
-
if (profiles.length === 0) {
|
|
91
|
-
yield* Console.log("No auth profiles. Use 'jira auth login' to authenticate.");
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
for (const profile of profiles) {
|
|
95
|
-
const marker = active?.id === profile.id ? "*" : " ";
|
|
96
|
-
yield* Console.log(`${marker} ${profile.id}`);
|
|
97
|
-
yield* Console.log(` ${profile.name}`);
|
|
98
|
-
yield* Console.log(` ${profile.token.site_url}`);
|
|
99
|
-
}
|
|
100
|
-
})).pipe(Command.withDescription("List stored auth profiles"));
|
|
101
|
-
const profileArg = Args.String("profile").pipe(Args.withDescription("Profile ID, name, site URL, cloud ID, or account ID"));
|
|
102
|
-
// === Auth use command ===
|
|
103
|
-
const useCommand = Command.make("use", { profile: profileArg }, ({ profile }) => Effect.gen(function* () {
|
|
104
|
-
const auth = yield* JiraAuth;
|
|
105
|
-
const selected = yield* auth.switchProfile(profile);
|
|
106
|
-
if (!selected) {
|
|
107
|
-
yield* Console.log(`Profile not found: ${profile}`);
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
yield* Console.log(`Active profile: ${selected.name}`);
|
|
111
|
-
})).pipe(Command.withDescription("Switch active auth profile"));
|
|
112
|
-
// === Auth remove command ===
|
|
113
|
-
const removeCommand = Command.make("remove", { profile: profileArg }, ({ profile }) => Effect.gen(function* () {
|
|
114
|
-
const auth = yield* JiraAuth;
|
|
115
|
-
const removed = yield* auth.removeProfile(profile);
|
|
116
|
-
if (!removed) {
|
|
117
|
-
yield* Console.log(`Profile not found: ${profile}`);
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
yield* Console.log(`Removed profile: ${removed.name}`);
|
|
121
|
-
})).pipe(Command.withDescription("Remove stored auth profile"));
|
|
122
|
-
// === Auth command group ===
|
|
123
|
-
export const authCommand = Command.make("auth").pipe(Command.withDescription("Manage OAuth authentication"), Command.withSubcommands([
|
|
124
|
-
createCommand,
|
|
125
|
-
configureCommand,
|
|
126
|
-
loginCommand,
|
|
127
|
-
logoutCommand,
|
|
128
|
-
statusCommand,
|
|
129
|
-
profilesCommand,
|
|
130
|
-
useCommand,
|
|
131
|
-
removeCommand
|
|
132
|
-
]));
|
|
6
|
+
import { makeAuthCommand } from "@knpkv/atlassian-common/cli-auth";
|
|
7
|
+
import { JiraAuth, jiraCliDescriptor } from "../JiraAuth.js";
|
|
8
|
+
export const authCommand = makeAuthCommand(JiraAuth, jiraCliDescriptor, { apiSection: "Jira API" });
|
|
133
9
|
//# sourceMappingURL=auth.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAA;AAClE,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAE5D,MAAM,CAAC,MAAM,WAAW,GAAG,eAAe,CAAC,QAAQ,EAAE,iBAAiB,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAA"}
|
|
@@ -11,7 +11,7 @@ import { VersionService } from "../VersionService.js";
|
|
|
11
11
|
*
|
|
12
12
|
* @category Layers
|
|
13
13
|
*/
|
|
14
|
-
export declare const AppLayer: Layer.Layer<AttachmentService | import("effect/http/HttpClient").HttpClient | IssueService | JiraApiClient | JiraAuth | MarkdownWriter | SiteUrl | VersionService | NodeServices.NodeServices, import("../JiraCliError.js").AuthMissingError | import("@knpkv/atlassian-common
|
|
14
|
+
export declare const AppLayer: Layer.Layer<AttachmentService | import("effect/http/HttpClient").HttpClient | IssueService | JiraApiClient | JiraAuth | MarkdownWriter | SiteUrl | VersionService | NodeServices.NodeServices, import("../JiraCliError.js").AuthMissingError | import("@knpkv/atlassian-common").FileSystemError | import("@knpkv/atlassian-common").HomeDirectoryError | import("@knpkv/atlassian-common").OAuthError | import("effect/PlatformError").PlatformError, never>;
|
|
15
15
|
/**
|
|
16
16
|
* Auth-only layer for auth commands.
|
|
17
17
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layers.d.ts","sourceRoot":"","sources":["../../src/commands/layers.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,YAAY,MAAM,oCAAoC,CAAA;AAClE,OAAO,EAAE,aAAa,EAAiB,MAAM,wBAAwB,CAAA;AAErE,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,EAAE,iBAAiB,EAAmC,MAAM,yBAAyB,CAAA;AAC5F,OAAO,EAAE,YAAY,EAA8B,OAAO,EAAE,MAAM,oBAAoB,CAAA;AACtF,OAAO,EAAE,QAAQ,EAA0B,MAAM,gBAAgB,CAAA;AACjE,OAAO,EAAgC,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACnF,OAAO,EAAgC,cAAc,EAAE,MAAM,sBAAsB,CAAA;AA+FnF;;;;GAIG;AACH,eAAO,MAAM,QAAQ,
|
|
1
|
+
{"version":3,"file":"layers.d.ts","sourceRoot":"","sources":["../../src/commands/layers.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,YAAY,MAAM,oCAAoC,CAAA;AAClE,OAAO,EAAE,aAAa,EAAiB,MAAM,wBAAwB,CAAA;AAErE,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,EAAE,iBAAiB,EAAmC,MAAM,yBAAyB,CAAA;AAC5F,OAAO,EAAE,YAAY,EAA8B,OAAO,EAAE,MAAM,oBAAoB,CAAA;AACtF,OAAO,EAAE,QAAQ,EAA0B,MAAM,gBAAgB,CAAA;AACjE,OAAO,EAAgC,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACnF,OAAO,EAAgC,cAAc,EAAE,MAAM,sBAAsB,CAAA;AA+FnF;;;;GAIG;AACH,eAAO,MAAM,QAAQ,+bASpB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,oLAOzB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,sIAMxB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,SAAU,aAAa,CAAC,MAAM,CAAC,KAAG,MAAM,GAAG,MAAM,GAAG,SAkB5E,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knpkv/jira-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "CLI tool to fetch Jira tickets and export to markdown",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "knpkv",
|
|
@@ -60,9 +60,9 @@
|
|
|
60
60
|
"@effect/platform-node": "4.0.0",
|
|
61
61
|
"gray-matter": "^4.0.3",
|
|
62
62
|
"js-yaml": "5.4.2",
|
|
63
|
-
"@knpkv/agent-skills": "^0.3.
|
|
64
|
-
"@knpkv/
|
|
65
|
-
"@knpkv/
|
|
63
|
+
"@knpkv/agent-skills": "^0.3.3",
|
|
64
|
+
"@knpkv/atlassian-common": "1.7.0",
|
|
65
|
+
"@knpkv/jira-api-client": "2.0.0"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"@effect/vitest": "4.0.0",
|
package/skills/jira/SKILL.md
CHANGED
|
@@ -21,6 +21,7 @@ Use the `jira` binary for Jira Cloud issue export and release-version workflows.
|
|
|
21
21
|
```bash
|
|
22
22
|
jira auth status
|
|
23
23
|
jira auth create
|
|
24
|
+
jira auth manage
|
|
24
25
|
jira auth configure --client-id <id> --client-secret <secret>
|
|
25
26
|
jira auth login
|
|
26
27
|
jira auth login --site https://example.atlassian.net
|