@knpkv/jira-cli 1.4.1 → 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 CHANGED
@@ -1,5 +1,23 @@
1
1
  # @knpkv/jira-cli
2
2
 
3
+ ## 1.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#472](https://github.com/knpkv/npm/pull/472) [`d12c336`](https://github.com/knpkv/npm/commit/d12c3364e56abb7cfd32aa693c5406788a67e3f5) Thanks [@konopkov](https://github.com/konopkov)! - One shared `auth` command group for jira and confluence: `makeAuthCommand(service, descriptor, options)` in `@knpkv/atlassian-common/cli-auth`. Each CLI exports one descriptor (`jiraCliDescriptor`, `confluenceCliDescriptor`: command name, product name, login scopes) that feeds both its auth and its `auth` commands.
8
+
9
+ - `jira auth create` lists every scope `jira auth login` requests. It previously listed three of five (missing `write:jira-work` and `manage:jira-project`), so an app set up from its instructions could not log in.
10
+ - `jira auth manage` is new: it opens the developer console with the scope and callback checklist.
11
+ - `confluence auth profiles`, `auth use <profile>` and `auth remove <profile>` are new; the docs already described them.
12
+ - `confluence auth status` prints the active profile, account, site and profile ID.
13
+ - `auth create` and `auth manage` print the URL first and exit non-zero when no browser opens (jira's `create` used to ignore that).
14
+
15
+ ### Patch Changes
16
+
17
+ - Updated dependencies [[`d12c336`](https://github.com/knpkv/npm/commit/d12c3364e56abb7cfd32aa693c5406788a67e3f5)]:
18
+ - @knpkv/atlassian-common@1.7.0
19
+ - @knpkv/agent-skills@0.3.3
20
+
3
21
  ## 1.4.1
4
22
 
5
23
  ### Patch Changes
package/README.md CHANGED
@@ -22,7 +22,9 @@ cd packages/jira-cli && pnpm link --global
22
22
  jira auth create
23
23
  ```
24
24
 
25
- Opens Atlassian Developer Console. Create a new OAuth 2.0 (3LO) app with:
25
+ Prints the URL and opens the Atlassian Developer Console (the command fails if no browser
26
+ opens; finish from the printed URL). Create a new OAuth 2.0 (3LO) app with the scopes it
27
+ prints, which are exactly the ones `jira auth login` requests:
26
28
 
27
29
  **Permissions:**
28
30
 
@@ -252,6 +254,7 @@ set, including surplus copies of a URL that _is_ desired. Other categories are n
252
254
 
253
255
  ```bash
254
256
  jira auth create # Open Atlassian console to create OAuth app
257
+ jira auth manage # Open the console to edit the app's scopes
255
258
  jira auth configure # Set client ID and secret
256
259
  jira auth login # Authenticate via OAuth
257
260
  jira auth profiles # List stored accounts/sites
@@ -17,6 +17,7 @@
17
17
  * @module
18
18
  */
19
19
  import type { OAuthError } from "@knpkv/atlassian-common/auth";
20
+ import { type AtlassianCliDescriptor } from "@knpkv/atlassian-common/cli-auth";
20
21
  import type { AuthProfile, FileSystemError, HomeDirectoryError, OAuthConfig, OAuthUser } from "@knpkv/atlassian-common/config";
21
22
  import * as Context from "effect/Context";
22
23
  import type * as Effect from "effect/Effect";
@@ -98,6 +99,8 @@ declare const JiraAuth_base: Context.ServiceClass<JiraAuth, "@knpkv/jira-cli/Jir
98
99
  */
99
100
  export declare class JiraAuth extends JiraAuth_base {
100
101
  }
102
+ /** Who the Jira CLI is: shared by its auth and its `auth` commands, so both name the same scopes. */
103
+ export declare const jiraCliDescriptor: AtlassianCliDescriptor;
101
104
  /**
102
105
  * Layer for JiraAuth service.
103
106
  *
@@ -1 +1 @@
1
- {"version":3,"file":"JiraAuth.d.ts","sourceRoot":"","sources":["../src/JiraAuth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"JiraAuth.d.ts","sourceRoot":"","sources":["../src/JiraAuth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAA;AAC9D,OAAO,EAAE,KAAK,sBAAsB,EAAyC,MAAM,kCAAkC,CAAA;AACrH,OAAO,KAAK,EACV,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,WAAW,EACX,SAAS,EACV,MAAM,gCAAgC,CAAA;AACvC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,KAAK,aAAa,MAAM,sBAAsB,CAAA;AAC1D,OAAO,KAAK,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAqBzD;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,4DAA4D;IAC5D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,yCAAyC;IACzC,QAAQ,CAAC,SAAS,EAAE,CAClB,MAAM,EAAE,WAAW,KAChB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,GAAG,kBAAkB,GAAG,aAAa,CAAC,aAAa,CAAC,CAAA;IAC5F,mCAAmC;IACnC,QAAQ,CAAC,YAAY,EAAE,MAAM,MAAM,CAAC,MAAM,CACxC,OAAO,EACP,eAAe,GAAG,kBAAkB,GAAG,aAAa,CAAC,aAAa,CACnE,CAAA;IACD,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,EAAE,CACd,OAAO,CAAC,EAAE,YAAY,KACnB,MAAM,CAAC,MAAM,CAChB,aAAa,CAAC,cAAc,CAAC,GAAG,IAAI,EACpC,UAAU,GAAG,eAAe,GAAG,kBAAkB,GAAG,aAAa,CAAC,aAAa,CAChF,CAAA;IACD,mCAAmC;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC,MAAM,CAClC,IAAI,EACJ,UAAU,GAAG,eAAe,GAAG,kBAAkB,GAAG,aAAa,CAAC,aAAa,CAChF,CAAA;IACD,6CAA6C;IAC7C,QAAQ,CAAC,cAAc,EAAE,MAAM,MAAM,CAAC,MAAM,CAC1C,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EACzB,gBAAgB,GAAG,UAAU,GAAG,eAAe,GAAG,kBAAkB,GAAG,aAAa,CAAC,aAAa,CACnG,CAAA;IACD,qCAAqC;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,MAAM,CAAC,MAAM,CACtC,MAAM,EACN,gBAAgB,GAAG,eAAe,GAAG,kBAAkB,GAAG,aAAa,CAAC,aAAa,CACtF,CAAA;IACD,qCAAqC;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,MAAM,CAAC,MAAM,CACtC,MAAM,EACN,gBAAgB,GAAG,eAAe,GAAG,kBAAkB,GAAG,aAAa,CAAC,aAAa,CACtF,CAAA;IACD,8CAA8C;IAC9C,QAAQ,CAAC,cAAc,EAAE,MAAM,MAAM,CAAC,MAAM,CAC1C,SAAS,GAAG,IAAI,EAChB,eAAe,GAAG,kBAAkB,GAAG,aAAa,CAAC,aAAa,CACnE,CAAA;IACD,8BAA8B;IAC9B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,MAAM,CAAC,MAAM,CAC5C,WAAW,GAAG,IAAI,EAClB,eAAe,GAAG,kBAAkB,GAAG,aAAa,CAAC,aAAa,CACnE,CAAA;IACD,gCAAgC;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,MAAM,CAAC,MAAM,CACxC,aAAa,CAAC,WAAW,CAAC,EAC1B,eAAe,GAAG,kBAAkB,GAAG,aAAa,CAAC,aAAa,CACnE,CAAA;IACD,2EAA2E;IAC3E,QAAQ,CAAC,aAAa,EAAE,CACtB,QAAQ,EAAE,MAAM,KACb,MAAM,CAAC,MAAM,CAAC,WAAW,GAAG,IAAI,EAAE,eAAe,GAAG,kBAAkB,GAAG,aAAa,CAAC,aAAa,CAAC,CAAA;IAC1G,2EAA2E;IAC3E,QAAQ,CAAC,aAAa,EAAE,CACtB,QAAQ,EAAE,MAAM,KACb,MAAM,CAAC,MAAM,CAAC,WAAW,GAAG,IAAI,EAAE,eAAe,GAAG,kBAAkB,GAAG,aAAa,CAAC,aAAa,CAAC,CAAA;IAC1G,iCAAiC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,eAAe,GAAG,kBAAkB,GAAG,aAAa,CAAC,aAAa,CAAC,CAAA;CACtH;;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,QAAS,SAAQ,aAGC;CAAG;AAElC,qGAAqG;AACrG,eAAO,MAAM,iBAAiB,EAAE,sBAI/B,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,KAAK,+KAOoB,CAAA"}
package/dist/JiraAuth.js CHANGED
@@ -40,16 +40,20 @@ const JIRA_CLI_SCOPES = [
40
40
  */
41
41
  export class JiraAuth extends Context.Service()("@knpkv/jira-cli/JiraAuth") {
42
42
  }
43
+ /** Who the Jira CLI is: shared by its auth and its `auth` commands, so both name the same scopes. */
44
+ export const jiraCliDescriptor = {
45
+ commandName: "jira",
46
+ productName: "Jira",
47
+ scopes: JIRA_CLI_SCOPES
48
+ };
43
49
  /**
44
50
  * Layer for JiraAuth service.
45
51
  *
46
52
  * @category Layers
47
53
  */
48
54
  export const layer = Layer.effect(JiraAuth, makeAtlassianCliAuth({
55
+ ...jiraCliDescriptor,
49
56
  toolName: "jira-cli",
50
- commandName: "jira",
51
- productName: "Jira",
52
- scopes: JIRA_CLI_SCOPES,
53
57
  authMissing
54
58
  })).pipe(Layer.provide(NodeCliAuthLive));
55
59
  //# sourceMappingURL=JiraAuth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"JiraAuth.js","sourceRoot":"","sources":["../src/JiraAuth.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAA;AAQxF,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AAEzC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAIrC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C,+GAA+G;AAC/G,MAAM,eAAe,GAAG;IACtB,0CAA0C;IAC1C,gBAAgB;IAChB,kCAAkC;IAClC,iBAAiB;IACjB,oEAAoE;IACpE,sEAAsE;IACtE,iEAAiE;IACjE,qBAAqB;IACrB,0EAA0E;IAC1E,gBAAgB;IAChB,oEAAoE;IACpE,SAAS;IACT,gEAAgE;IAChE,gBAAgB;CACjB,CAAA;AA4FD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,OAAO,QAAS,SAAQ,OAAO,CAAC,OAAO,EAG1C,CAAC,0BAA0B,CAAC;CAAG;AAElC;;;;GAIG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAC/B,QAAQ,EACR,oBAAoB,CAAC;IACnB,QAAQ,EAAE,UAAU;IACpB,WAAW,EAAE,MAAM;IACnB,WAAW,EAAE,MAAM;IACnB,MAAM,EAAE,eAAe;IACvB,WAAW;CACZ,CAAC,CACH,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"JiraAuth.js","sourceRoot":"","sources":["../src/JiraAuth.ts"],"names":[],"mappings":"AAmBA,OAAO,EAA+B,oBAAoB,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAA;AAQrH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AAEzC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAIrC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C,+GAA+G;AAC/G,MAAM,eAAe,GAAG;IACtB,0CAA0C;IAC1C,gBAAgB;IAChB,kCAAkC;IAClC,iBAAiB;IACjB,oEAAoE;IACpE,sEAAsE;IACtE,iEAAiE;IACjE,qBAAqB;IACrB,0EAA0E;IAC1E,gBAAgB;IAChB,oEAAoE;IACpE,SAAS;IACT,gEAAgE;IAChE,gBAAgB;CACjB,CAAA;AA4FD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,OAAO,QAAS,SAAQ,OAAO,CAAC,OAAO,EAG1C,CAAC,0BAA0B,CAAC;CAAG;AAElC,qGAAqG;AACrG,MAAM,CAAC,MAAM,iBAAiB,GAA2B;IACvD,WAAW,EAAE,MAAM;IACnB,WAAW,EAAE,MAAM;IACnB,MAAM,EAAE,eAAe;CACxB,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAC/B,QAAQ,EACR,oBAAoB,CAAC;IACnB,GAAG,iBAAiB;IACpB,QAAQ,EAAE,UAAU;IACpB,WAAW;CACZ,CAAC,CACH,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAA"}
@@ -1,4 +1,3 @@
1
- import { Command, Prompt } from "effect/cli";
2
1
  import { JiraAuth } from "../JiraAuth.js";
3
- export declare const authCommand: Command.Command<"auth", {}, {}, import("@knpkv/atlassian-common/config").FileSystemError | import("@knpkv/atlassian-common/config").HomeDirectoryError | import("@knpkv/atlassian-common/auth").OAuthError | import("effect/PlatformError").PlatformError | import("effect/Terminal").QuitError, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | JiraAuth | Prompt.Environment>;
2
+ export declare const authCommand: import("effect/cli/Command").Command<"auth", {}, {}, import("@knpkv/atlassian-common/cli-auth").BrowserOpenError | import("@knpkv/atlassian-common").FileSystemError | import("@knpkv/atlassian-common").HomeDirectoryError | import("@knpkv/atlassian-common").OAuthError | import("effect/PlatformError").PlatformError | import("effect/Terminal").QuitError, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | JiraAuth | import("effect/cli/Prompt").Environment>;
4
3
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAWA,OAAO,EAAoB,OAAO,EAAmB,MAAM,EAAE,MAAM,YAAY,CAAA;AAI/E,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAgJzC,eAAO,MAAM,WAAW,oYAYvB,CAAA"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,QAAQ,EAAqB,MAAM,gBAAgB,CAAA;AAE5D,eAAO,MAAM,WAAW,ydAA2E,CAAA"}
@@ -1,133 +1,9 @@
1
1
  /**
2
- * Auth subcommands: create, configure, login, logout, status.
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 { openBrowser } from "@knpkv/atlassian-common/cli-auth";
12
- import { Argument as Args, Command, Flag as Options, Prompt } from "effect/cli";
13
- import * as Console from "effect/Console";
14
- import * as Effect from "effect/Effect";
15
- import * as Option from "effect/Option";
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":"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"}
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/config").FileSystemError | import("@knpkv/atlassian-common/config").HomeDirectoryError | import("@knpkv/atlassian-common/auth").OAuthError | import("effect/PlatformError").PlatformError, never>;
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,kdASpB,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"}
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.4.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,8 +60,8 @@
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.2",
64
- "@knpkv/atlassian-common": "1.6.0",
63
+ "@knpkv/agent-skills": "^0.3.3",
64
+ "@knpkv/atlassian-common": "1.7.0",
65
65
  "@knpkv/jira-api-client": "2.0.0"
66
66
  },
67
67
  "devDependencies": {
@@ -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
package/src/JiraAuth.ts CHANGED
@@ -17,7 +17,7 @@
17
17
  * @module
18
18
  */
19
19
  import type { OAuthError } from "@knpkv/atlassian-common/auth"
20
- import { makeAtlassianCliAuth, NodeCliAuthLive } from "@knpkv/atlassian-common/cli-auth"
20
+ import { type AtlassianCliDescriptor, makeAtlassianCliAuth, NodeCliAuthLive } from "@knpkv/atlassian-common/cli-auth"
21
21
  import type {
22
22
  AuthProfile,
23
23
  FileSystemError,
@@ -165,6 +165,13 @@ export class JiraAuth extends Context.Service<
165
165
  JiraAuthService
166
166
  >()("@knpkv/jira-cli/JiraAuth") {}
167
167
 
168
+ /** Who the Jira CLI is: shared by its auth and its `auth` commands, so both name the same scopes. */
169
+ export const jiraCliDescriptor: AtlassianCliDescriptor = {
170
+ commandName: "jira",
171
+ productName: "Jira",
172
+ scopes: JIRA_CLI_SCOPES
173
+ }
174
+
168
175
  /**
169
176
  * Layer for JiraAuth service.
170
177
  *
@@ -173,10 +180,8 @@ export class JiraAuth extends Context.Service<
173
180
  export const layer = Layer.effect(
174
181
  JiraAuth,
175
182
  makeAtlassianCliAuth({
183
+ ...jiraCliDescriptor,
176
184
  toolName: "jira-cli",
177
- commandName: "jira",
178
- productName: "Jira",
179
- scopes: JIRA_CLI_SCOPES,
180
185
  authMissing
181
186
  })
182
187
  ).pipe(Layer.provide(NodeCliAuthLive))
@@ -1,172 +1,9 @@
1
1
  /**
2
- * Auth subcommands: create, configure, login, logout, status.
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 { openBrowser } from "@knpkv/atlassian-common/cli-auth"
12
- import { Argument as Args, Command, Flag as Options, Prompt } from "effect/cli"
13
- import * as Console from "effect/Console"
14
- import * as Effect from "effect/Effect"
15
- import * as Option from "effect/Option"
16
- import { JiraAuth } from "../JiraAuth.js"
17
-
18
- // === Auth create command ===
19
- const createCommand = Command.make("create", {}, () =>
20
- Effect.gen(function*() {
21
- yield* Console.log(`
22
- Creating OAuth app in Atlassian Developer Console...
23
-
24
- 1. Browser will open to create a new OAuth 2.0 (3LO) app
25
- 2. Enter app name (e.g., "Jira CLI")
26
- 3. After creation, go to "Permissions" and add:
27
-
28
- Jira API:
29
- - read:jira-work Search and read issues, comments, attachments
30
- - read:jira-user Read user info for assignee/reporter fields
31
-
32
- User Identity API:
33
- - read:me Get your account ID and email for auth
34
-
35
- 4. Go to "Authorization" and set callback URL:
36
- http://localhost:8585/callback
37
- 5. Go to "Settings" and copy Client ID and Secret
38
- 6. Run: jira auth configure --client-id <ID> --client-secret <SECRET>
39
- `)
40
- const url = "https://developer.atlassian.com/console/myapps/create-3lo-app/"
41
- yield* openBrowser(url).pipe(Effect.catch(() => Effect.void))
42
- })).pipe(Command.withDescription("Create OAuth app in Atlassian Developer Console"))
43
-
44
- // === Auth configure command ===
45
- const clientIdOption = Options.String("client-id").pipe(
46
- Options.withDescription("OAuth client ID from Atlassian Developer Console"),
47
- Options.optional
48
- )
49
- const clientSecretOption = Options.String("client-secret").pipe(
50
- Options.withDescription("OAuth client secret"),
51
- Options.optional
52
- )
53
-
54
- const configureCommand = Command.make(
55
- "configure",
56
- { clientId: clientIdOption, clientSecret: clientSecretOption },
57
- ({ clientId, clientSecret }) =>
58
- Effect.gen(function*() {
59
- const auth = yield* JiraAuth
60
-
61
- const rawClientId = Option.isSome(clientId)
62
- ? clientId.value
63
- : yield* Prompt.String({ message: "Enter OAuth client ID:" })
64
- const rawClientSecret = Option.isSome(clientSecret)
65
- ? clientSecret.value
66
- : yield* Prompt.String({ message: "Enter OAuth client secret:" })
67
-
68
- yield* auth.configure({ clientId: rawClientId, clientSecret: rawClientSecret })
69
- yield* Console.log("OAuth configured. Run 'jira auth login' to authenticate.")
70
- })
71
- ).pipe(Command.withDescription("Configure OAuth client credentials"))
72
-
73
- // === Auth login command ===
74
- const siteOption = Options.String("site").pipe(
75
- Options.withDescription("Jira site URL to use (for accounts with multiple sites)"),
76
- Options.optional
77
- )
78
-
79
- const loginCommand = Command.make("login", { site: siteOption }, ({ site }) =>
80
- Effect.gen(function*() {
81
- const auth = yield* JiraAuth
82
- const result = yield* auth.login(Option.isSome(site) ? { siteUrl: site.value } : undefined)
83
- if (Array.isArray(result) && result.length > 0) {
84
- yield* Console.log("\nRe-run with --site to select a specific site.")
85
- }
86
- })).pipe(Command.withDescription("Authenticate with Atlassian via OAuth"))
87
-
88
- // === Auth logout command ===
89
- const logoutCommand = Command.make("logout", {}, () =>
90
- Effect.gen(function*() {
91
- const auth = yield* JiraAuth
92
- yield* auth.logout()
93
- yield* Console.log("Logged out")
94
- })).pipe(Command.withDescription("Remove stored authentication"))
95
-
96
- // === Auth status command ===
97
- const statusCommand = Command.make("status", {}, () =>
98
- Effect.gen(function*() {
99
- const auth = yield* JiraAuth
100
- const profile = yield* auth.getActiveProfile()
101
- if (profile) {
102
- const user = profile.token.user
103
- const account = user ? `${user.name} (${user.email})` : "unknown user"
104
- yield* Console.log(`Active profile: ${profile.name}`)
105
- yield* Console.log(`Account: ${account}`)
106
- yield* Console.log(`Site: ${profile.token.site_url}`)
107
- yield* Console.log(`Profile ID: ${profile.id}`)
108
- } else {
109
- yield* Console.log("Not logged in. Use 'jira auth login' to authenticate.")
110
- }
111
- })).pipe(Command.withDescription("Show authentication status"))
112
-
113
- // === Auth profiles command ===
114
- const profilesCommand = Command.make("profiles", {}, () =>
115
- Effect.gen(function*() {
116
- const auth = yield* JiraAuth
117
- const [profiles, active] = yield* Effect.all([auth.listProfiles(), auth.getActiveProfile()])
118
- if (profiles.length === 0) {
119
- yield* Console.log("No auth profiles. Use 'jira auth login' to authenticate.")
120
- return
121
- }
122
-
123
- for (const profile of profiles) {
124
- const marker = active?.id === profile.id ? "*" : " "
125
- yield* Console.log(`${marker} ${profile.id}`)
126
- yield* Console.log(` ${profile.name}`)
127
- yield* Console.log(` ${profile.token.site_url}`)
128
- }
129
- })).pipe(Command.withDescription("List stored auth profiles"))
130
-
131
- const profileArg = Args.String("profile").pipe(
132
- Args.withDescription("Profile ID, name, site URL, cloud ID, or account ID")
133
- )
134
-
135
- // === Auth use command ===
136
- const useCommand = Command.make("use", { profile: profileArg }, ({ profile }) =>
137
- Effect.gen(function*() {
138
- const auth = yield* JiraAuth
139
- const selected = yield* auth.switchProfile(profile)
140
- if (!selected) {
141
- yield* Console.log(`Profile not found: ${profile}`)
142
- return
143
- }
144
- yield* Console.log(`Active profile: ${selected.name}`)
145
- })).pipe(Command.withDescription("Switch active auth profile"))
146
-
147
- // === Auth remove command ===
148
- const removeCommand = Command.make("remove", { profile: profileArg }, ({ profile }) =>
149
- Effect.gen(function*() {
150
- const auth = yield* JiraAuth
151
- const removed = yield* auth.removeProfile(profile)
152
- if (!removed) {
153
- yield* Console.log(`Profile not found: ${profile}`)
154
- return
155
- }
156
- yield* Console.log(`Removed profile: ${removed.name}`)
157
- })).pipe(Command.withDescription("Remove stored auth profile"))
6
+ import { makeAuthCommand } from "@knpkv/atlassian-common/cli-auth"
7
+ import { JiraAuth, jiraCliDescriptor } from "../JiraAuth.js"
158
8
 
159
- // === Auth command group ===
160
- export const authCommand = Command.make("auth").pipe(
161
- Command.withDescription("Manage OAuth authentication"),
162
- Command.withSubcommands([
163
- createCommand,
164
- configureCommand,
165
- loginCommand,
166
- logoutCommand,
167
- statusCommand,
168
- profilesCommand,
169
- useCommand,
170
- removeCommand
171
- ])
172
- )
9
+ export const authCommand = makeAuthCommand(JiraAuth, jiraCliDescriptor, { apiSection: "Jira API" })
@@ -0,0 +1,54 @@
1
+ /** @effect-diagnostics strictEffectProvide:skip-file */
2
+ /**
3
+ * `jira auth create` must list every scope `jira auth login` requests: Atlassian rejects an
4
+ * authorization request naming a scope the app lacks, so a shorter list is a setup that cannot log in.
5
+ */
6
+ import { NodeServices } from "@effect/platform-node"
7
+ import { expect, it } from "@effect/vitest"
8
+ import { Command } from "effect/cli"
9
+ import * as Console from "effect/Console"
10
+ import * as Effect from "effect/Effect"
11
+ import { FetchHttpClient } from "effect/http"
12
+ import * as Layer from "effect/Layer"
13
+ import { ChildProcessSpawner } from "effect/process"
14
+ import * as Sink from "effect/Sink"
15
+ import * as Stream from "effect/Stream"
16
+ import { authCommand } from "../src/commands/auth.js"
17
+ import { jiraCliDescriptor, layer } from "../src/JiraAuth.js"
18
+
19
+ const browserOpens = ChildProcessSpawner.make(() =>
20
+ Effect.succeed(ChildProcessSpawner.makeHandle({
21
+ all: Stream.empty,
22
+ exitCode: Effect.succeed(ChildProcessSpawner.ExitCode(0)),
23
+ getInputFd: () => Sink.drain,
24
+ getOutputFd: () => Stream.empty,
25
+ isRunning: Effect.succeed(false),
26
+ kill: () => Effect.void,
27
+ pid: ChildProcessSpawner.ProcessId(1),
28
+ reref: Effect.void,
29
+ stderr: Stream.empty,
30
+ stdin: Sink.drain,
31
+ stdout: Stream.empty,
32
+ unref: Effect.succeed(Effect.void)
33
+ }))
34
+ )
35
+
36
+ it.effect("auth create lists every scope JiraAuth logs in with", () =>
37
+ Effect.gen(function*() {
38
+ const lines: Array<string> = []
39
+ const capture: Console.Console = Object.assign(Object.create(console), {
40
+ log: (...parts: ReadonlyArray<unknown>) => lines.push(parts.join(" "))
41
+ })
42
+ const cli = Command.runWith(Command.make("jira").pipe(Command.withSubcommands([authCommand])), { version: "0" })
43
+ const exit = yield* cli(["auth", "create"]).pipe(Effect.provideService(Console.Console, capture), Effect.exit)
44
+ expect(exit._tag).toBe("Success")
45
+ const output = lines.join("\n")
46
+ const permissions = jiraCliDescriptor.scopes.filter((scope) => scope !== "offline_access")
47
+ expect(permissions.length).toBeGreaterThan(2)
48
+ for (const scope of permissions) expect(output).toContain(scope)
49
+ expect(output).toContain("jira auth configure")
50
+ }).pipe(
51
+ // The command's browser launch sees the fake; the auth layer is built over real platform services.
52
+ Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, browserOpens),
53
+ Effect.provide(layer.pipe(Layer.provideMerge(Layer.mergeAll(FetchHttpClient.layer, NodeServices.layer))))
54
+ ))