@knpkv/jira-cli 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +21 -0
  3. package/README.md +141 -0
  4. package/dist/IssueService.d.ts +144 -0
  5. package/dist/IssueService.d.ts.map +1 -0
  6. package/dist/IssueService.js +250 -0
  7. package/dist/IssueService.js.map +1 -0
  8. package/dist/JiraAuth.d.ts +84 -0
  9. package/dist/JiraAuth.d.ts.map +1 -0
  10. package/dist/JiraAuth.js +246 -0
  11. package/dist/JiraAuth.js.map +1 -0
  12. package/dist/JiraCliError.d.ts +42 -0
  13. package/dist/JiraCliError.d.ts.map +1 -0
  14. package/dist/JiraCliError.js +35 -0
  15. package/dist/JiraCliError.js.map +1 -0
  16. package/dist/MarkdownWriter.d.ts +56 -0
  17. package/dist/MarkdownWriter.d.ts.map +1 -0
  18. package/dist/MarkdownWriter.js +66 -0
  19. package/dist/MarkdownWriter.js.map +1 -0
  20. package/dist/bin.d.ts +3 -0
  21. package/dist/bin.d.ts.map +1 -0
  22. package/dist/bin.js +39 -0
  23. package/dist/bin.js.map +1 -0
  24. package/dist/commands/auth.d.ts +22 -0
  25. package/dist/commands/auth.d.ts.map +1 -0
  26. package/dist/commands/auth.js +89 -0
  27. package/dist/commands/auth.js.map +1 -0
  28. package/dist/commands/errorHandler.d.ts +13 -0
  29. package/dist/commands/errorHandler.d.ts.map +1 -0
  30. package/dist/commands/errorHandler.js +13 -0
  31. package/dist/commands/errorHandler.js.map +1 -0
  32. package/dist/commands/get.d.ts +13 -0
  33. package/dist/commands/get.d.ts.map +1 -0
  34. package/dist/commands/get.js +25 -0
  35. package/dist/commands/get.js.map +1 -0
  36. package/dist/commands/index.d.ts +11 -0
  37. package/dist/commands/index.d.ts.map +1 -0
  38. package/dist/commands/index.js +11 -0
  39. package/dist/commands/index.js.map +1 -0
  40. package/dist/commands/layers.d.ts +44 -0
  41. package/dist/commands/layers.d.ts.map +1 -0
  42. package/dist/commands/layers.js +100 -0
  43. package/dist/commands/layers.js.map +1 -0
  44. package/dist/commands/search.d.ts +18 -0
  45. package/dist/commands/search.d.ts.map +1 -0
  46. package/dist/commands/search.js +64 -0
  47. package/dist/commands/search.js.map +1 -0
  48. package/dist/index.d.ts +10 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +10 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/internal/NodeLayers.d.ts +7 -0
  53. package/dist/internal/NodeLayers.d.ts.map +1 -0
  54. package/dist/internal/NodeLayers.js +15 -0
  55. package/dist/internal/NodeLayers.js.map +1 -0
  56. package/dist/internal/frontmatter.d.ts +60 -0
  57. package/dist/internal/frontmatter.d.ts.map +1 -0
  58. package/dist/internal/frontmatter.js +130 -0
  59. package/dist/internal/frontmatter.js.map +1 -0
  60. package/dist/internal/jqlBuilder.d.ts +39 -0
  61. package/dist/internal/jqlBuilder.d.ts.map +1 -0
  62. package/dist/internal/jqlBuilder.js +47 -0
  63. package/dist/internal/jqlBuilder.js.map +1 -0
  64. package/dist/internal/oauthServer.d.ts +55 -0
  65. package/dist/internal/oauthServer.d.ts.map +1 -0
  66. package/dist/internal/oauthServer.js +113 -0
  67. package/dist/internal/oauthServer.js.map +1 -0
  68. package/package.json +86 -0
  69. package/src/IssueService.ts +378 -0
  70. package/src/JiraAuth.ts +476 -0
  71. package/src/JiraCliError.ts +44 -0
  72. package/src/MarkdownWriter.ts +112 -0
  73. package/src/bin.ts +62 -0
  74. package/src/commands/auth.ts +124 -0
  75. package/src/commands/errorHandler.ts +14 -0
  76. package/src/commands/get.ts +42 -0
  77. package/src/commands/index.ts +11 -0
  78. package/src/commands/layers.ts +142 -0
  79. package/src/commands/search.ts +102 -0
  80. package/src/index.ts +26 -0
  81. package/src/internal/NodeLayers.ts +17 -0
  82. package/src/internal/frontmatter.ts +170 -0
  83. package/src/internal/jqlBuilder.ts +49 -0
  84. package/src/internal/oauthServer.ts +203 -0
  85. package/test/jqlBuilder.test.ts +45 -0
  86. package/tsconfig.json +32 -0
  87. package/vitest.config.ts +12 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # @knpkv/jira-cli
2
+
3
+ ## 0.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [[`fc7be8f`](https://github.com/knpkv/npm/commit/fc7be8ffaf5b6b094c7f81551e8ace6f2a8f2c4c)]:
8
+ - @knpkv/atlassian-common@0.2.0
9
+ - @knpkv/jira-api-client@0.2.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 knpkv
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,141 @@
1
+ # @knpkv/jira-cli
2
+
3
+ CLI tool to fetch Jira tickets and export to markdown.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @knpkv/jira-cli
9
+ ```
10
+
11
+ Or link globally for development:
12
+
13
+ ```bash
14
+ cd packages/jira-cli && pnpm link --global
15
+ ```
16
+
17
+ ## Setup
18
+
19
+ ### 1. Create OAuth App
20
+
21
+ ```bash
22
+ jira auth create
23
+ ```
24
+
25
+ Opens Atlassian Developer Console. Create a new OAuth 2.0 (3LO) app with:
26
+
27
+ **Permissions:**
28
+
29
+ - Jira API: `read:jira-work`, `read:jira-user`
30
+ - User Identity API: `read:me`
31
+
32
+ **Callback URL:**
33
+
34
+ ```
35
+ http://localhost:8585/callback
36
+ ```
37
+
38
+ ### 2. Configure Credentials
39
+
40
+ ```bash
41
+ jira auth configure --client-id <ID> --client-secret <SECRET>
42
+ ```
43
+
44
+ ### 3. Login
45
+
46
+ ```bash
47
+ jira auth login
48
+ ```
49
+
50
+ ## Usage
51
+
52
+ ### Search by JQL
53
+
54
+ ```bash
55
+ jira search 'project = PROJ AND status = Done'
56
+ ```
57
+
58
+ ### Search by Fix Version
59
+
60
+ ```bash
61
+ jira search --by-version "1.0.0"
62
+ jira search --by-version "1.0.0" --project PROJ
63
+ ```
64
+
65
+ ### Options
66
+
67
+ | Option | Alias | Description | Default |
68
+ | --------------- | ----- | ---------------------------------------- | ---------------- |
69
+ | `--by-version` | `-v` | Search by fix version | - |
70
+ | `--project` | `-p` | Filter by project key | - |
71
+ | `--output-dir` | `-o` | Output directory | `./jira-tickets` |
72
+ | `--format` | `-f` | `multi` (one file per issue) or `single` | `multi` |
73
+ | `--max-results` | `-m` | Max results to fetch | `100` |
74
+
75
+ ### Output Formats
76
+
77
+ **Multi (default):** One markdown file per issue with YAML front-matter.
78
+
79
+ ```
80
+ ./jira-tickets/
81
+ ├── PROJ-123.md
82
+ ├── PROJ-124.md
83
+ └── PROJ-125.md
84
+ ```
85
+
86
+ **Single:** All issues in one combined file.
87
+
88
+ ```
89
+ ./jira-tickets/
90
+ └── jira-export.md
91
+ ```
92
+
93
+ ## Auth Commands
94
+
95
+ ```bash
96
+ jira auth create # Open Atlassian console to create OAuth app
97
+ jira auth configure # Set client ID and secret
98
+ jira auth login # Authenticate via OAuth
99
+ jira auth logout # Remove stored credentials
100
+ jira auth status # Show current auth status
101
+ ```
102
+
103
+ ## Programmatic Usage
104
+
105
+ ```typescript
106
+ import { Effect, Layer } from "effect"
107
+ import * as Redacted from "effect/Redacted"
108
+ import { IssueService, IssueServiceLayer } from "@knpkv/jira-cli"
109
+ import { JiraApiClient, JiraApiConfig, toEffect } from "@knpkv/jira-api-client"
110
+
111
+ const configLayer = Layer.succeed(JiraApiConfig, {
112
+ baseUrl: "https://mysite.atlassian.net",
113
+ auth: {
114
+ type: "basic",
115
+ email: "user@example.com",
116
+ apiToken: Redacted.make("your-api-token")
117
+ }
118
+ })
119
+
120
+ // Using IssueService (high-level)
121
+ const program = Effect.gen(function* () {
122
+ const service = yield* IssueService
123
+ const issues = yield* service.searchAll('fixVersion = "1.0.0"')
124
+ console.log(`Found ${issues.length} issues`)
125
+ }).pipe(Effect.provide(IssueServiceLayer), Effect.provide(JiraApiClient.layer), Effect.provide(configLayer))
126
+
127
+ // Or using JiraApiClient directly (low-level)
128
+ const direct = Effect.gen(function* () {
129
+ const client = yield* JiraApiClient
130
+ const issue = yield* toEffect(
131
+ client.v3.client.GET("/rest/api/3/issue/{issueIdOrKey}", {
132
+ params: { path: { issueIdOrKey: "PROJ-123" } }
133
+ })
134
+ )
135
+ console.log(issue.fields?.summary)
136
+ }).pipe(Effect.provide(JiraApiClient.layer), Effect.provide(configLayer))
137
+ ```
138
+
139
+ ## License
140
+
141
+ MIT
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Jira issue fetching with field extraction and cursor-based pagination.
3
+ *
4
+ * **Mental model**
5
+ *
6
+ * - **API → domain mapping**: {@link IssueService} wraps the generated V3 client, extracting
7
+ * typed {@link Issue} objects from the loosely-typed API response via helper functions
8
+ * like `extractDisplayName` and `extractNameArray`.
9
+ * - **Rendered fields**: Requests include `expand: "renderedFields"` to get HTML-rendered
10
+ * descriptions and comments, falling back to plain text.
11
+ * - **Pagination guard**: {@link IssueServiceShape.searchAll} iterates pages using
12
+ * `nextPageToken` with a MAX_PAGES (1000) safety limit.
13
+ *
14
+ * **Common tasks**
15
+ *
16
+ * - Fetch single issue: `service.getByKey("PROJ-123")`
17
+ * - Search with pagination: `service.searchAll(jql)`
18
+ *
19
+ * @module
20
+ */
21
+ import { JiraApiClient } from "@knpkv/jira-api-client";
22
+ import * as Context from "effect/Context";
23
+ import * as Effect from "effect/Effect";
24
+ import * as Layer from "effect/Layer";
25
+ import { JiraApiError } from "./JiraCliError.js";
26
+ declare const SiteUrl_base: Context.TagClass<SiteUrl, "@knpkv/jira-cli/SiteUrl", string>;
27
+ /**
28
+ * Site URL configuration for issue links.
29
+ *
30
+ * @category Config
31
+ */
32
+ export declare class SiteUrl extends SiteUrl_base {
33
+ }
34
+ /**
35
+ * Attachment metadata.
36
+ *
37
+ * @category Types
38
+ */
39
+ export interface Attachment {
40
+ readonly id: string;
41
+ readonly filename: string;
42
+ readonly url: string;
43
+ readonly mimeType: string;
44
+ readonly size: number;
45
+ }
46
+ /**
47
+ * Comment on an issue.
48
+ *
49
+ * @category Types
50
+ */
51
+ export interface Comment {
52
+ readonly id: string;
53
+ readonly author: string;
54
+ readonly body: string;
55
+ readonly created: Date;
56
+ readonly updated: Date;
57
+ }
58
+ /**
59
+ * Jira issue with relevant fields.
60
+ *
61
+ * @category Types
62
+ */
63
+ export interface Issue {
64
+ readonly key: string;
65
+ readonly id: string;
66
+ readonly summary: string;
67
+ readonly status: string;
68
+ readonly type: string;
69
+ readonly priority: string | null;
70
+ readonly assignee: string | null;
71
+ readonly reporter: string | null;
72
+ readonly created: Date;
73
+ readonly updated: Date;
74
+ readonly fixVersions: ReadonlyArray<string>;
75
+ readonly labels: ReadonlyArray<string>;
76
+ readonly components: ReadonlyArray<string>;
77
+ readonly description: string;
78
+ readonly attachments: ReadonlyArray<Attachment>;
79
+ readonly comments: ReadonlyArray<Comment>;
80
+ readonly url: string;
81
+ }
82
+ /**
83
+ * Search options for issue queries.
84
+ *
85
+ * @category Types
86
+ */
87
+ export interface SearchOptions {
88
+ readonly maxResults?: number;
89
+ }
90
+ /**
91
+ * Search result with pagination info.
92
+ *
93
+ * @category Types
94
+ */
95
+ export interface SearchResult {
96
+ readonly issues: ReadonlyArray<Issue>;
97
+ /** True if this is the last page (API uses cursor pagination, no total count) */
98
+ readonly isLast: boolean;
99
+ readonly nextPageToken: string | null;
100
+ readonly maxResults: number;
101
+ }
102
+ /**
103
+ * IssueService interface.
104
+ *
105
+ * @category Services
106
+ */
107
+ export interface IssueServiceShape {
108
+ /** Get a single issue by key */
109
+ readonly getByKey: (key: string) => Effect.Effect<Issue, JiraApiError>;
110
+ /** Search issues by JQL query */
111
+ readonly search: (jql: string, options?: SearchOptions) => Effect.Effect<SearchResult, JiraApiError>;
112
+ /** Search all issues by JQL query (handles pagination) */
113
+ readonly searchAll: (jql: string, options?: {
114
+ readonly maxResults?: number;
115
+ }) => Effect.Effect<ReadonlyArray<Issue>, JiraApiError>;
116
+ }
117
+ declare const IssueService_base: Context.TagClass<IssueService, "@knpkv/jira-cli/IssueService", IssueServiceShape>;
118
+ /**
119
+ * IssueService tag.
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * import { Effect } from "effect"
124
+ * import { IssueService } from "@knpkv/jira-cli/IssueService"
125
+ *
126
+ * Effect.gen(function* () {
127
+ * const service = yield* IssueService
128
+ * const issues = yield* service.searchAll('fixVersion = "1.0.0"')
129
+ * console.log(`Found ${issues.length} issues`)
130
+ * })
131
+ * ```
132
+ *
133
+ * @category Services
134
+ */
135
+ export declare class IssueService extends IssueService_base {
136
+ }
137
+ /**
138
+ * Layer for IssueService.
139
+ *
140
+ * @category Layers
141
+ */
142
+ export declare const layer: Layer.Layer<IssueService, never, SiteUrl | JiraApiClient>;
143
+ export {};
144
+ //# sourceMappingURL=IssueService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IssueService.d.ts","sourceRoot":"","sources":["../src/IssueService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,250 @@
1
+ /**
2
+ * Jira issue fetching with field extraction and cursor-based pagination.
3
+ *
4
+ * **Mental model**
5
+ *
6
+ * - **API → domain mapping**: {@link IssueService} wraps the generated V3 client, extracting
7
+ * typed {@link Issue} objects from the loosely-typed API response via helper functions
8
+ * like `extractDisplayName` and `extractNameArray`.
9
+ * - **Rendered fields**: Requests include `expand: "renderedFields"` to get HTML-rendered
10
+ * descriptions and comments, falling back to plain text.
11
+ * - **Pagination guard**: {@link IssueServiceShape.searchAll} iterates pages using
12
+ * `nextPageToken` with a MAX_PAGES (1000) safety limit.
13
+ *
14
+ * **Common tasks**
15
+ *
16
+ * - Fetch single issue: `service.getByKey("PROJ-123")`
17
+ * - Search with pagination: `service.searchAll(jql)`
18
+ *
19
+ * @module
20
+ */
21
+ import { JiraApiClient, toEffect } from "@knpkv/jira-api-client";
22
+ import * as Context from "effect/Context";
23
+ import * as Effect from "effect/Effect";
24
+ import * as Layer from "effect/Layer";
25
+ import { JiraApiError } from "./JiraCliError.js";
26
+ /**
27
+ * Site URL configuration for issue links.
28
+ *
29
+ * @category Config
30
+ */
31
+ export class SiteUrl extends Context.Tag("@knpkv/jira-cli/SiteUrl")() {
32
+ }
33
+ /**
34
+ * IssueService tag.
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * import { Effect } from "effect"
39
+ * import { IssueService } from "@knpkv/jira-cli/IssueService"
40
+ *
41
+ * Effect.gen(function* () {
42
+ * const service = yield* IssueService
43
+ * const issues = yield* service.searchAll('fixVersion = "1.0.0"')
44
+ * console.log(`Found ${issues.length} issues`)
45
+ * })
46
+ * ```
47
+ *
48
+ * @category Services
49
+ */
50
+ export class IssueService extends Context.Tag("@knpkv/jira-cli/IssueService")() {
51
+ }
52
+ const FIELDS = [
53
+ "summary",
54
+ "description",
55
+ "status",
56
+ "issuetype",
57
+ "priority",
58
+ "assignee",
59
+ "reporter",
60
+ "created",
61
+ "updated",
62
+ "fixVersions",
63
+ "labels",
64
+ "components",
65
+ "attachment",
66
+ "comment"
67
+ ];
68
+ /**
69
+ * Extract string from a field that may be an object with displayName/name.
70
+ */
71
+ const extractDisplayName = (field) => {
72
+ if (field === null || field === undefined)
73
+ return null;
74
+ if (typeof field === "string")
75
+ return field;
76
+ if (typeof field === "object") {
77
+ const obj = field;
78
+ if (typeof obj["displayName"] === "string")
79
+ return obj["displayName"];
80
+ if (typeof obj["name"] === "string")
81
+ return obj["name"];
82
+ }
83
+ return null;
84
+ };
85
+ /**
86
+ * Extract array of strings from a field that may be array of objects with name.
87
+ */
88
+ const extractNameArray = (field) => {
89
+ if (!Array.isArray(field))
90
+ return [];
91
+ return field
92
+ .map((item) => {
93
+ if (typeof item === "string")
94
+ return item;
95
+ if (typeof item === "object" && item !== null) {
96
+ const obj = item;
97
+ if (typeof obj["name"] === "string")
98
+ return obj["name"];
99
+ }
100
+ return null;
101
+ })
102
+ .filter((x) => x !== null);
103
+ };
104
+ /**
105
+ * Parse date from unknown value, returning epoch date if invalid.
106
+ */
107
+ const parseDate = (val) => {
108
+ const str = String(val ?? "");
109
+ if (!str)
110
+ return new Date(0);
111
+ const date = new Date(str);
112
+ return isNaN(date.getTime()) ? new Date(0) : date;
113
+ };
114
+ /**
115
+ * Map IssueBean from API to our Issue type.
116
+ */
117
+ const mapIssue = (bean, baseUrl) => {
118
+ const fields = (bean["fields"] ?? {});
119
+ const renderedFields = (bean["renderedFields"] ?? {});
120
+ const key = String(bean["key"] ?? "");
121
+ const id = String(bean["id"] ?? "");
122
+ // Extract attachments
123
+ const attachmentField = fields["attachment"];
124
+ const attachments = Array.isArray(attachmentField)
125
+ ? attachmentField.map((a) => {
126
+ const att = a;
127
+ return {
128
+ id: String(att["id"] ?? ""),
129
+ filename: String(att["filename"] ?? ""),
130
+ url: String(att["content"] ?? ""),
131
+ mimeType: String(att["mimeType"] ?? ""),
132
+ size: Number(att["size"] ?? 0)
133
+ };
134
+ })
135
+ : [];
136
+ // Extract comments
137
+ const commentField = fields["comment"];
138
+ const commentList = (commentField?.["comments"] ?? []);
139
+ const renderedComments = (renderedFields["comment"]?.["comments"] ?? []);
140
+ // Build map of rendered comments by ID for accurate matching
141
+ const renderedMap = new Map();
142
+ for (const r of renderedComments) {
143
+ const rId = String(r["id"] ?? "");
144
+ if (rId)
145
+ renderedMap.set(rId, r);
146
+ }
147
+ const comments = commentList.map((c) => {
148
+ const author = c["author"];
149
+ const commentId = String(c["id"] ?? "");
150
+ const rendered = renderedMap.get(commentId);
151
+ const renderedBody = rendered?.["body"];
152
+ return {
153
+ id: commentId,
154
+ author: extractDisplayName(author) ?? "Unknown",
155
+ body: typeof renderedBody === "string" ? renderedBody : String(c["body"] ?? ""),
156
+ created: parseDate(c["created"]),
157
+ updated: parseDate(c["updated"])
158
+ };
159
+ });
160
+ // Use rendered description (HTML) if available
161
+ const description = typeof renderedFields["description"] === "string"
162
+ ? renderedFields["description"]
163
+ : String(fields["description"] ?? "");
164
+ return {
165
+ key,
166
+ id,
167
+ summary: String(fields["summary"] ?? ""),
168
+ status: extractDisplayName(fields["status"]) ?? "Unknown",
169
+ type: extractDisplayName(fields["issuetype"]) ?? "Unknown",
170
+ priority: extractDisplayName(fields["priority"]),
171
+ assignee: extractDisplayName(fields["assignee"]),
172
+ reporter: extractDisplayName(fields["reporter"]),
173
+ created: parseDate(fields["created"]),
174
+ updated: parseDate(fields["updated"]),
175
+ fixVersions: extractNameArray(fields["fixVersions"]),
176
+ labels: extractNameArray(fields["labels"]),
177
+ components: extractNameArray(fields["components"]),
178
+ description,
179
+ attachments,
180
+ comments,
181
+ url: `${baseUrl}/browse/${key}`
182
+ };
183
+ };
184
+ const make = Effect.gen(function* () {
185
+ const client = yield* JiraApiClient;
186
+ const siteUrl = yield* SiteUrl;
187
+ const getByKey = (key) => toEffect(client.v3.client.GET("/rest/api/3/issue/{issueIdOrKey}", {
188
+ params: {
189
+ path: { issueIdOrKey: key },
190
+ query: { fields: FIELDS, expand: "renderedFields" }
191
+ }
192
+ })).pipe(Effect.map((result) => mapIssue(result, siteUrl)), Effect.mapError((cause) => new JiraApiError({ message: `Failed to get issue ${key}`, cause })));
193
+ const searchJql = (jql, maxResults, nextPageToken) => toEffect(client.v3.client.GET("/rest/api/3/search/jql", {
194
+ params: {
195
+ query: {
196
+ jql,
197
+ maxResults,
198
+ ...(nextPageToken ? { nextPageToken } : {}),
199
+ fields: FIELDS,
200
+ expand: "renderedFields"
201
+ }
202
+ }
203
+ })).pipe(Effect.mapError((cause) => new JiraApiError({ message: "Failed to search issues", cause })));
204
+ const search = (jql, options) => searchJql(jql, options?.maxResults ?? 50).pipe(Effect.map((result) => {
205
+ const issues = result.issues ?? [];
206
+ const mappedIssues = [];
207
+ for (const bean of issues) {
208
+ mappedIssues.push(mapIssue(bean, siteUrl));
209
+ }
210
+ return {
211
+ issues: mappedIssues,
212
+ isLast: result.isLast ?? true,
213
+ nextPageToken: result.nextPageToken ?? null,
214
+ maxResults: options?.maxResults ?? 50
215
+ };
216
+ }));
217
+ const MAX_PAGES = 1000;
218
+ const searchAll = (jql, options) => Effect.gen(function* () {
219
+ const allIssues = [];
220
+ const maxResults = options?.maxResults ?? 100;
221
+ let nextPageToken = undefined;
222
+ let pageCount = 0;
223
+ // Fetch first page
224
+ let result = yield* searchJql(jql, maxResults, nextPageToken);
225
+ let issues = result.issues ?? [];
226
+ pageCount++;
227
+ for (const bean of issues) {
228
+ allIssues.push(mapIssue(bean, siteUrl));
229
+ }
230
+ // Fetch remaining pages with iteration guard
231
+ while (!result.isLast && result.nextPageToken && pageCount < MAX_PAGES) {
232
+ nextPageToken = result.nextPageToken;
233
+ result = yield* searchJql(jql, maxResults, nextPageToken);
234
+ issues = result.issues ?? [];
235
+ pageCount++;
236
+ for (const bean of issues) {
237
+ allIssues.push(mapIssue(bean, siteUrl));
238
+ }
239
+ }
240
+ return allIssues;
241
+ });
242
+ return IssueService.of({ getByKey, search, searchAll });
243
+ });
244
+ /**
245
+ * Layer for IssueService.
246
+ *
247
+ * @category Layers
248
+ */
249
+ export const layer = Layer.effect(IssueService, make);
250
+ //# sourceMappingURL=IssueService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IssueService.js","sourceRoot":"","sources":["../src/IssueService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ import * as CommandExecutor from "@effect/platform/CommandExecutor";
2
+ import type * as Error from "@effect/platform/Error";
3
+ import * as HttpClient from "@effect/platform/HttpClient";
4
+ import { OAuthError } from "@knpkv/atlassian-common/auth";
5
+ import { type FileSystemError, type HomeDirectoryError, type OAuthConfig, type OAuthUser } from "@knpkv/atlassian-common/config";
6
+ import * as Context from "effect/Context";
7
+ import * as Effect from "effect/Effect";
8
+ import * as Layer from "effect/Layer";
9
+ import * as Redacted from "effect/Redacted";
10
+ import type { AuthMissingError } from "./JiraCliError.js";
11
+ /**
12
+ * Options for the login method.
13
+ *
14
+ * @category Types
15
+ */
16
+ export interface LoginOptions {
17
+ /** Site URL to select (for accounts with multiple sites) */
18
+ readonly siteUrl?: string;
19
+ }
20
+ /**
21
+ * Information about an accessible Jira site.
22
+ *
23
+ * @category Types
24
+ */
25
+ export interface AccessibleSite {
26
+ readonly id: string;
27
+ readonly name: string;
28
+ readonly url: string;
29
+ }
30
+ /**
31
+ * JiraAuth service interface.
32
+ *
33
+ * @category Services
34
+ */
35
+ export interface JiraAuthService {
36
+ /** Configure OAuth client credentials */
37
+ readonly configure: (config: OAuthConfig) => Effect.Effect<void, FileSystemError | HomeDirectoryError | Error.PlatformError>;
38
+ /** Check if OAuth is configured */
39
+ readonly isConfigured: () => Effect.Effect<boolean, FileSystemError | HomeDirectoryError | Error.PlatformError>;
40
+ /** Start OAuth login flow. Returns list of sites if multiple are available. */
41
+ readonly login: (options?: LoginOptions) => Effect.Effect<ReadonlyArray<AccessibleSite> | void, OAuthError | FileSystemError | HomeDirectoryError | Error.PlatformError>;
42
+ /** Remove stored authentication */
43
+ readonly logout: () => Effect.Effect<void, OAuthError | FileSystemError | HomeDirectoryError | Error.PlatformError>;
44
+ /** Get access token, refreshing if needed */
45
+ readonly getAccessToken: () => Effect.Effect<Redacted.Redacted<string>, AuthMissingError | OAuthError | FileSystemError | HomeDirectoryError | Error.PlatformError>;
46
+ /** Get cloud ID from stored token */
47
+ readonly getCloudId: () => Effect.Effect<string, AuthMissingError | FileSystemError | HomeDirectoryError | Error.PlatformError>;
48
+ /** Get site URL from stored token */
49
+ readonly getSiteUrl: () => Effect.Effect<string, AuthMissingError | FileSystemError | HomeDirectoryError | Error.PlatformError>;
50
+ /** Get current user info from stored token */
51
+ readonly getCurrentUser: () => Effect.Effect<OAuthUser | null, FileSystemError | HomeDirectoryError | Error.PlatformError>;
52
+ /** Check if user is logged in */
53
+ readonly isLoggedIn: () => Effect.Effect<boolean, FileSystemError | HomeDirectoryError | Error.PlatformError>;
54
+ }
55
+ declare const JiraAuth_base: Context.TagClass<JiraAuth, "@knpkv/jira-cli/JiraAuth", JiraAuthService>;
56
+ /**
57
+ * JiraAuth service tag.
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * import { Effect } from "effect"
62
+ * import { JiraAuth } from "@knpkv/jira-cli/JiraAuth"
63
+ *
64
+ * Effect.gen(function* () {
65
+ * const auth = yield* JiraAuth
66
+ * const isLoggedIn = yield* auth.isLoggedIn()
67
+ * if (!isLoggedIn) {
68
+ * yield* auth.login()
69
+ * }
70
+ * })
71
+ * ```
72
+ *
73
+ * @category Services
74
+ */
75
+ export declare class JiraAuth extends JiraAuth_base {
76
+ }
77
+ /**
78
+ * Layer for JiraAuth service.
79
+ *
80
+ * @category Layers
81
+ */
82
+ export declare const layer: Layer.Layer<JiraAuth, never, HttpClient.HttpClient | CommandExecutor.CommandExecutor>;
83
+ export {};
84
+ //# sourceMappingURL=JiraAuth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JiraAuth.d.ts","sourceRoot":"","sources":["../src/JiraAuth.ts"],"names":[],"mappings":"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"}