@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
@@ -0,0 +1,246 @@
1
+ /**
2
+ * OAuth2 authentication service for Jira CLI with token refresh and concurrency locking.
3
+ *
4
+ * **Mental model**
5
+ *
6
+ * - **Service pattern**: {@link JiraAuth} is a `Context.Tag` whose layer requires `HttpClient`
7
+ * and `CommandExecutor`. All token storage operations are pre-bound to
8
+ * `@knpkv/atlassian-common/config` with a `"jira-cli"` tool name.
9
+ * - **Refresh lock**: A `Ref<Option<Deferred>>` prevents concurrent token refreshes — the
10
+ * first caller refreshes, others await the same Deferred.
11
+ * - **Browser-based login**: {@link JiraAuthService.login} starts a local callback server,
12
+ * opens the browser, and awaits the OAuth code with a 5-minute timeout.
13
+ *
14
+ * **Common tasks**
15
+ *
16
+ * - Get a valid access token: `auth.getAccessToken()` (auto-refreshes if expired)
17
+ * - Full login flow: `auth.login()`
18
+ * - Check auth state: `auth.isLoggedIn()`
19
+ *
20
+ * @module
21
+ */
22
+ import * as NodeFileSystem from "@effect/platform-node/NodeFileSystem";
23
+ import * as NodePath from "@effect/platform-node/NodePath";
24
+ import * as Command from "@effect/platform/Command";
25
+ import * as CommandExecutor from "@effect/platform/CommandExecutor";
26
+ import * as HttpClient from "@effect/platform/HttpClient";
27
+ import { buildAuthUrl, buildOAuthToken, computeCodeChallenge, exchangeCodeForTokens, generateCodeVerifier, generateUUID, getAccessibleResources, getUserInfo, OAuthError, refreshToken, revokeToken } from "@knpkv/atlassian-common/auth";
28
+ import { deleteToken, HomeDirectoryLive, isTokenExpired, loadOAuthConfig, loadToken, saveOAuthConfig, saveToken } from "@knpkv/atlassian-common/config";
29
+ import * as Console from "effect/Console";
30
+ import * as Context from "effect/Context";
31
+ import * as Deferred from "effect/Deferred";
32
+ import * as Effect from "effect/Effect";
33
+ import * as Layer from "effect/Layer";
34
+ import * as Option from "effect/Option";
35
+ import * as Redacted from "effect/Redacted";
36
+ import * as Ref from "effect/Ref";
37
+ import { HttpServerFactoryLive } from "./internal/NodeLayers.js";
38
+ import { startCallbackServer } from "./internal/oauthServer.js";
39
+ import { authMissing } from "./JiraCliError.js";
40
+ /** Scopes for Jira CLI (includes write:jira-work for worklog) */
41
+ const JIRA_CLI_SCOPES = [
42
+ "read:jira-work",
43
+ "write:jira-work",
44
+ "read:jira-user",
45
+ "read:me",
46
+ "offline_access"
47
+ ];
48
+ const TOOL_NAME = "jira-cli";
49
+ // Layer for token storage operations (FileSystem + Path + HomeDirectory)
50
+ const TokenStorageLive = Layer.mergeAll(NodeFileSystem.layer, NodePath.layer, HomeDirectoryLive);
51
+ // Wrap token storage operations with their required layers
52
+ const loadTokenOp = () => loadToken(TOOL_NAME).pipe(Effect.provide(TokenStorageLive));
53
+ const saveTokenOp = (token) => saveToken(TOOL_NAME, token).pipe(Effect.provide(TokenStorageLive));
54
+ const deleteTokenOp = () => deleteToken(TOOL_NAME).pipe(Effect.provide(TokenStorageLive));
55
+ const loadOAuthConfigOp = () => loadOAuthConfig(TOOL_NAME).pipe(Effect.provide(TokenStorageLive));
56
+ const saveOAuthConfigOp = (config) => saveOAuthConfig(TOOL_NAME, config).pipe(Effect.provide(TokenStorageLive));
57
+ /**
58
+ * JiraAuth service tag.
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * import { Effect } from "effect"
63
+ * import { JiraAuth } from "@knpkv/jira-cli/JiraAuth"
64
+ *
65
+ * Effect.gen(function* () {
66
+ * const auth = yield* JiraAuth
67
+ * const isLoggedIn = yield* auth.isLoggedIn()
68
+ * if (!isLoggedIn) {
69
+ * yield* auth.login()
70
+ * }
71
+ * })
72
+ * ```
73
+ *
74
+ * @category Services
75
+ */
76
+ export class JiraAuth extends Context.Tag("@knpkv/jira-cli/JiraAuth")() {
77
+ }
78
+ const make = Effect.gen(function* () {
79
+ const httpClient = yield* HttpClient.HttpClient;
80
+ const commandExecutor = yield* CommandExecutor.CommandExecutor;
81
+ // Ref to track ongoing refresh operation to prevent concurrent refreshes
82
+ const refreshLock = yield* Ref.make(Option.none());
83
+ const openBrowserImpl = (url) => Command.make("open", url).pipe(Command.exitCode, Effect.catchAll(() => Command.make("xdg-open", url).pipe(Command.exitCode)), Effect.catchAll(() => Command.make("cmd", "/c", "start", "", url).pipe(Command.exitCode)), Effect.provide(Layer.succeed(CommandExecutor.CommandExecutor, commandExecutor)), Effect.asVoid, Effect.mapError((cause) => new OAuthError({ step: "authorize", cause })));
84
+ const getConfig = () => Effect.gen(function* () {
85
+ const config = yield* loadOAuthConfigOp();
86
+ if (config === null) {
87
+ return yield* Effect.fail(new OAuthError({
88
+ step: "authorize",
89
+ cause: "OAuth not configured. Run 'jira auth configure' first."
90
+ }));
91
+ }
92
+ return config;
93
+ });
94
+ const refreshTokenImpl = (token, config) => Effect.gen(function* () {
95
+ const updated = yield* refreshToken(token, config).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, httpClient)));
96
+ yield* saveTokenOp(updated);
97
+ return updated;
98
+ });
99
+ const revokeTokenImpl = (token, config) => revokeToken(token, config).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, httpClient)));
100
+ const configure = (config) => saveOAuthConfigOp(config);
101
+ const isConfigured = () => Effect.gen(function* () {
102
+ const config = yield* loadOAuthConfigOp();
103
+ return config !== null;
104
+ });
105
+ const login = (options) => Effect.gen(function* () {
106
+ const config = yield* getConfig();
107
+ const state = yield* generateUUID();
108
+ const codeVerifier = generateCodeVerifier();
109
+ const codeChallenge = yield* computeCodeChallenge(codeVerifier);
110
+ const { codePromise, port, shutdown } = yield* startCallbackServer(state).pipe(Effect.provide(HttpServerFactoryLive));
111
+ const authUrl = buildAuthUrl({ clientId: config.clientId, state, port, scopes: JIRA_CLI_SCOPES, codeChallenge });
112
+ yield* Console.log(`Opening browser for Atlassian login (callback on port ${port})...`);
113
+ yield* Console.log(`If browser doesn't open, visit: ${authUrl}`);
114
+ yield* openBrowserImpl(authUrl);
115
+ yield* Console.log("Waiting for authorization (press Ctrl+C to cancel)...");
116
+ const code = yield* codePromise.pipe(Effect.timeout("5 minutes"), Effect.catchTag("TimeoutException", () => Effect.fail(new OAuthError({ step: "authorize", cause: "Authorization timed out" }))), Effect.ensuring(shutdown));
117
+ yield* Console.log("Exchanging code for tokens...");
118
+ const tokens = yield* exchangeCodeForTokens(code, config, { port, codeVerifier }).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, httpClient)));
119
+ yield* Console.log("Fetching accessible sites...");
120
+ const sites = yield* getAccessibleResources(tokens.access_token).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, httpClient)));
121
+ if (sites.length === 0) {
122
+ return yield* Effect.fail(new OAuthError({
123
+ step: "authorize",
124
+ cause: "No Jira sites found for this account"
125
+ }));
126
+ }
127
+ let site;
128
+ if (sites.length > 1) {
129
+ if (options?.siteUrl) {
130
+ const matched = sites.find((s) => s.url === options.siteUrl);
131
+ if (!matched) {
132
+ const available = sites.map((s) => ` - ${s.name}: ${s.url}`).join("\n");
133
+ return yield* Effect.fail(new OAuthError({
134
+ step: "authorize",
135
+ cause: `Site '${options.siteUrl}' not found. Available sites:\n${available}`
136
+ }));
137
+ }
138
+ site = matched;
139
+ }
140
+ else {
141
+ yield* Console.log("Multiple Jira sites found. Please select one:");
142
+ for (const s of sites) {
143
+ yield* Console.log(` - ${s.name}: ${s.url}`);
144
+ }
145
+ yield* Console.log("\nRun 'jira auth login --site <url>' to select a site");
146
+ return sites.map((s) => ({ id: s.id, name: s.name, url: s.url }));
147
+ }
148
+ }
149
+ else {
150
+ site = sites[0];
151
+ }
152
+ yield* Console.log("Fetching user info...");
153
+ const user = yield* getUserInfo(tokens.access_token).pipe(Effect.provide(Layer.succeed(HttpClient.HttpClient, httpClient)));
154
+ const tokenData = buildOAuthToken(tokens, site, user);
155
+ yield* saveTokenOp(tokenData);
156
+ yield* Console.log(`Logged in as ${user.name} (${user.email})`);
157
+ return undefined;
158
+ });
159
+ const logout = () => Effect.gen(function* () {
160
+ const token = yield* loadTokenOp();
161
+ if (token === null) {
162
+ yield* Console.log("Not logged in");
163
+ return;
164
+ }
165
+ const config = yield* loadOAuthConfigOp();
166
+ if (config !== null) {
167
+ yield* revokeTokenImpl(token, config).pipe(Effect.tap(() => Effect.log("Token revoked with Atlassian")), Effect.catchAll((error) => Effect.log(`Warning: Failed to revoke token: ${error.message}`)));
168
+ }
169
+ yield* deleteTokenOp();
170
+ });
171
+ const getAccessToken = () => Effect.gen(function* () {
172
+ const token = yield* loadTokenOp();
173
+ if (token === null) {
174
+ return yield* Effect.fail(authMissing());
175
+ }
176
+ if (!isTokenExpired(token)) {
177
+ return Redacted.make(token.access_token);
178
+ }
179
+ // Atomically check-then-set refresh lock to avoid TOCTOU race
180
+ const deferred = yield* Deferred.make();
181
+ const existing = yield* Ref.modify(refreshLock, (current) => Option.isSome(current)
182
+ ? [current.value, current]
183
+ : [deferred, Option.some(deferred)]);
184
+ // Another fiber is already refreshing — just await its result
185
+ if (existing !== deferred) {
186
+ const refreshed = yield* Deferred.await(existing);
187
+ return Redacted.make(refreshed.access_token);
188
+ }
189
+ // This fiber owns the refresh
190
+ const config = yield* getConfig();
191
+ yield* Console.log("Token expired, refreshing...");
192
+ const result = yield* refreshTokenImpl(token, config).pipe(Effect.tap((refreshed) => Deferred.succeed(deferred, refreshed)), Effect.tapError((error) => Deferred.fail(deferred, error)), Effect.ensuring(Ref.set(refreshLock, Option.none())), Effect.catchTag("OAuthError", (error) => {
193
+ if (error.step === "refresh") {
194
+ return Effect.gen(function* () {
195
+ yield* deleteTokenOp();
196
+ return yield* Effect.fail(new OAuthError({
197
+ step: "refresh",
198
+ cause: "Refresh token expired. Please run 'jira auth login' to re-authenticate."
199
+ }));
200
+ });
201
+ }
202
+ return Effect.fail(error);
203
+ }));
204
+ return Redacted.make(result.access_token);
205
+ });
206
+ const getCloudId = () => Effect.gen(function* () {
207
+ const token = yield* loadTokenOp();
208
+ if (token === null) {
209
+ return yield* Effect.fail(authMissing());
210
+ }
211
+ return token.cloud_id;
212
+ });
213
+ const getSiteUrl = () => Effect.gen(function* () {
214
+ const token = yield* loadTokenOp();
215
+ if (token === null) {
216
+ return yield* Effect.fail(authMissing());
217
+ }
218
+ return token.site_url;
219
+ });
220
+ const getCurrentUser = () => Effect.gen(function* () {
221
+ const token = yield* loadTokenOp();
222
+ return token?.user ?? null;
223
+ });
224
+ const isLoggedIn = () => Effect.gen(function* () {
225
+ const token = yield* loadTokenOp();
226
+ return token !== null;
227
+ });
228
+ return JiraAuth.of({
229
+ configure,
230
+ isConfigured,
231
+ login,
232
+ logout,
233
+ getAccessToken,
234
+ getCloudId,
235
+ getSiteUrl,
236
+ getCurrentUser,
237
+ isLoggedIn
238
+ });
239
+ });
240
+ /**
241
+ * Layer for JiraAuth service.
242
+ *
243
+ * @category Layers
244
+ */
245
+ export const layer = Layer.effect(JiraAuth, make);
246
+ //# sourceMappingURL=JiraAuth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JiraAuth.js","sourceRoot":"","sources":["../src/JiraAuth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ declare const AuthMissingError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
2
+ readonly _tag: "AuthMissingError";
3
+ } & Readonly<A>;
4
+ /**
5
+ * Error when user is not authenticated.
6
+ *
7
+ * @category Errors
8
+ */
9
+ export declare class AuthMissingError extends AuthMissingError_base<{
10
+ readonly message: string;
11
+ }> {
12
+ }
13
+ export declare const authMissing: () => AuthMissingError;
14
+ declare const JiraApiError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
15
+ readonly _tag: "JiraApiError";
16
+ } & Readonly<A>;
17
+ /**
18
+ * Error during Jira API operations.
19
+ *
20
+ * @category Errors
21
+ */
22
+ export declare class JiraApiError extends JiraApiError_base<{
23
+ readonly message: string;
24
+ readonly cause?: unknown;
25
+ }> {
26
+ }
27
+ declare const WriteError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
28
+ readonly _tag: "WriteError";
29
+ } & Readonly<A>;
30
+ /**
31
+ * Error when writing files.
32
+ *
33
+ * @category Errors
34
+ */
35
+ export declare class WriteError extends WriteError_base<{
36
+ readonly path: string;
37
+ readonly message: string;
38
+ readonly cause?: unknown;
39
+ }> {
40
+ }
41
+ export {};
42
+ //# sourceMappingURL=JiraCliError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JiraCliError.d.ts","sourceRoot":"","sources":["../src/JiraCliError.ts"],"names":[],"mappings":";;;AAaA;;;;GAIG;AACH,qBAAa,gBAAiB,SAAQ,sBAAqC;IACzE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB,CAAC;CAAG;AAEL,eAAO,MAAM,WAAW,wBAAyF,CAAA;;;;AAEjH;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,kBAAiC;IACjE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CACzB,CAAC;CAAG;;;;AAEL;;;;GAIG;AACH,qBAAa,UAAW,SAAQ,gBAA+B;IAC7D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CACzB,CAAC;CAAG"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Tagged error types for Jira CLI operations.
3
+ *
4
+ * **Mental model**
5
+ *
6
+ * - **Three error tags**: {@link AuthMissingError} (not logged in),
7
+ * {@link JiraApiError} (API call failed), {@link WriteError} (file I/O failed).
8
+ * - **Factory helper**: {@link authMissing} creates `AuthMissingError` with the default message.
9
+ *
10
+ * @module
11
+ */
12
+ import * as Data from "effect/Data";
13
+ /**
14
+ * Error when user is not authenticated.
15
+ *
16
+ * @category Errors
17
+ */
18
+ export class AuthMissingError extends Data.TaggedError("AuthMissingError") {
19
+ }
20
+ export const authMissing = () => new AuthMissingError({ message: "Not logged in. Run 'jira auth login' first." });
21
+ /**
22
+ * Error during Jira API operations.
23
+ *
24
+ * @category Errors
25
+ */
26
+ export class JiraApiError extends Data.TaggedError("JiraApiError") {
27
+ }
28
+ /**
29
+ * Error when writing files.
30
+ *
31
+ * @category Errors
32
+ */
33
+ export class WriteError extends Data.TaggedError("WriteError") {
34
+ }
35
+ //# sourceMappingURL=JiraCliError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JiraCliError.js","sourceRoot":"","sources":["../src/JiraCliError.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,IAAI,MAAM,aAAa,CAAA;AAEnC;;;;GAIG;AACH,MAAM,OAAO,gBAAiB,SAAQ,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAEvE;CAAG;AAEL,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,IAAI,gBAAgB,CAAC,EAAE,OAAO,EAAE,6CAA6C,EAAE,CAAC,CAAA;AAEjH;;;;GAIG;AACH,MAAM,OAAO,YAAa,SAAQ,IAAI,CAAC,WAAW,CAAC,cAAc,CAG/D;CAAG;AAEL;;;;GAIG;AACH,MAAM,OAAO,UAAW,SAAQ,IAAI,CAAC,WAAW,CAAC,YAAY,CAI3D;CAAG"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * File I/O service for writing Jira issues as Markdown with YAML frontmatter.
3
+ *
4
+ * **Mental model**
5
+ *
6
+ * - **Two output modes**: {@link MarkdownWriterShape.writeMulti} creates one `.md` per issue;
7
+ * {@link MarkdownWriterShape.writeSingle} combines all into `jira-export.md`.
8
+ * - **Effect service**: Requires `FileSystem` and `Path` from `@effect/platform`.
9
+ *
10
+ * @module
11
+ */
12
+ import * as FileSystem from "@effect/platform/FileSystem";
13
+ import * as Path from "@effect/platform/Path";
14
+ import * as Context from "effect/Context";
15
+ import * as Effect from "effect/Effect";
16
+ import * as Layer from "effect/Layer";
17
+ import type { Issue } from "./IssueService.js";
18
+ import { WriteError } from "./JiraCliError.js";
19
+ /**
20
+ * MarkdownWriter service interface.
21
+ *
22
+ * @category Services
23
+ */
24
+ export interface MarkdownWriterShape {
25
+ /** Write each issue to a separate markdown file */
26
+ readonly writeMulti: (issues: ReadonlyArray<Issue>, outputDir: string) => Effect.Effect<void, WriteError>;
27
+ /** Write all issues to a single markdown file */
28
+ readonly writeSingle: (issues: ReadonlyArray<Issue>, outputDir: string, jql: string) => Effect.Effect<void, WriteError>;
29
+ }
30
+ declare const MarkdownWriter_base: Context.TagClass<MarkdownWriter, "@knpkv/jira-cli/MarkdownWriter", MarkdownWriterShape>;
31
+ /**
32
+ * MarkdownWriter service tag.
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * import { Effect } from "effect"
37
+ * import { MarkdownWriter } from "@knpkv/jira-cli/MarkdownWriter"
38
+ *
39
+ * Effect.gen(function* () {
40
+ * const writer = yield* MarkdownWriter
41
+ * yield* writer.writeMulti(issues, "./output")
42
+ * })
43
+ * ```
44
+ *
45
+ * @category Services
46
+ */
47
+ export declare class MarkdownWriter extends MarkdownWriter_base {
48
+ }
49
+ /**
50
+ * Layer for MarkdownWriter service.
51
+ *
52
+ * @category Layers
53
+ */
54
+ export declare const layer: Layer.Layer<MarkdownWriter, never, FileSystem.FileSystem | Path.Path>;
55
+ export {};
56
+ //# sourceMappingURL=MarkdownWriter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownWriter.d.ts","sourceRoot":"","sources":["../src/MarkdownWriter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,UAAU,MAAM,6BAA6B,CAAA;AACzD,OAAO,KAAK,IAAI,MAAM,uBAAuB,CAAA;AAC7C,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAErC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,mDAAmD;IACnD,QAAQ,CAAC,UAAU,EAAE,CACnB,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,EAC5B,SAAS,EAAE,MAAM,KACd,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;IACpC,iDAAiD;IACjD,QAAQ,CAAC,WAAW,EAAE,CACpB,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,EAC5B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,KACR,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;CACrC;;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,cAAe,SAAQ,mBAGjC;CAAG;AA6CN;;;;GAIG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAGvF,CAAA"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * File I/O service for writing Jira issues as Markdown with YAML frontmatter.
3
+ *
4
+ * **Mental model**
5
+ *
6
+ * - **Two output modes**: {@link MarkdownWriterShape.writeMulti} creates one `.md` per issue;
7
+ * {@link MarkdownWriterShape.writeSingle} combines all into `jira-export.md`.
8
+ * - **Effect service**: Requires `FileSystem` and `Path` from `@effect/platform`.
9
+ *
10
+ * @module
11
+ */
12
+ import * as FileSystem from "@effect/platform/FileSystem";
13
+ import * as Path from "@effect/platform/Path";
14
+ import * as Context from "effect/Context";
15
+ import * as Effect from "effect/Effect";
16
+ import * as Layer from "effect/Layer";
17
+ import { buildCombinedMarkdown, serializeIssue } from "./internal/frontmatter.js";
18
+ import { WriteError } from "./JiraCliError.js";
19
+ /**
20
+ * MarkdownWriter service tag.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * import { Effect } from "effect"
25
+ * import { MarkdownWriter } from "@knpkv/jira-cli/MarkdownWriter"
26
+ *
27
+ * Effect.gen(function* () {
28
+ * const writer = yield* MarkdownWriter
29
+ * yield* writer.writeMulti(issues, "./output")
30
+ * })
31
+ * ```
32
+ *
33
+ * @category Services
34
+ */
35
+ export class MarkdownWriter extends Context.Tag("@knpkv/jira-cli/MarkdownWriter")() {
36
+ }
37
+ const make = Effect.gen(function* () {
38
+ const fs = yield* FileSystem.FileSystem;
39
+ const path = yield* Path.Path;
40
+ const ensureDir = (dir) => fs.makeDirectory(dir, { recursive: true }).pipe(Effect.catchAll((cause) => Effect.fail(new WriteError({ path: dir, message: "Failed to create directory", cause }))));
41
+ const writeFile = (filePath, content) => fs.writeFileString(filePath, content).pipe(Effect.catchAll((cause) => Effect.fail(new WriteError({ path: filePath, message: "Failed to write file", cause }))));
42
+ const writeMulti = (issues, outputDir) => Effect.gen(function* () {
43
+ yield* ensureDir(outputDir);
44
+ for (const issue of issues) {
45
+ const filename = `${issue.key}.md`;
46
+ const filePath = path.join(outputDir, filename);
47
+ const content = serializeIssue(issue);
48
+ yield* writeFile(filePath, content);
49
+ }
50
+ });
51
+ const writeSingle = (issues, outputDir, jql) => Effect.gen(function* () {
52
+ yield* ensureDir(outputDir);
53
+ const filename = "jira-export.md";
54
+ const filePath = path.join(outputDir, filename);
55
+ const content = buildCombinedMarkdown(issues, jql);
56
+ yield* writeFile(filePath, content);
57
+ });
58
+ return MarkdownWriter.of({ writeMulti, writeSingle });
59
+ });
60
+ /**
61
+ * Layer for MarkdownWriter service.
62
+ *
63
+ * @category Layers
64
+ */
65
+ export const layer = Layer.effect(MarkdownWriter, make);
66
+ //# sourceMappingURL=MarkdownWriter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownWriter.js","sourceRoot":"","sources":["../src/MarkdownWriter.ts"],"names":[],"mappings":"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"}
package/dist/bin.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=bin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}
package/dist/bin.js ADDED
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI entry point — assembles commands, selects layer by subcommand, runs via `NodeRuntime`.
4
+ *
5
+ * `process.argv` is read once at the edge and passed to Effect — no globals in effectful code.
6
+ *
7
+ * @module
8
+ */
9
+ import { Command } from "@effect/cli";
10
+ import { NodeRuntime } from "@effect/platform-node";
11
+ import * as Effect from "effect/Effect";
12
+ import * as Logger from "effect/Logger";
13
+ import * as LogLevel from "effect/LogLevel";
14
+ import pkg from "../package.json" with { type: "json" };
15
+ import { AppLayer, authCommand, AuthOnlyLayer, getCommand, getLayerType, handleError, MinimalLayer, searchCommand } from "./commands/index.js";
16
+ // === Main command ===
17
+ const jira = Command.make("jira").pipe(Command.withDescription("Fetch Jira tickets and export to markdown"), Command.withSubcommands([
18
+ authCommand,
19
+ getCommand,
20
+ searchCommand
21
+ ]));
22
+ // === Run CLI ===
23
+ const cli = Command.run(jira, {
24
+ name: pkg.name,
25
+ version: pkg.version
26
+ });
27
+ // Read argv once at the edge
28
+ const argv = globalThis.process.argv;
29
+ const layerType = getLayerType(argv);
30
+ const layer = layerType === "full"
31
+ ? AppLayer
32
+ : layerType === "auth"
33
+ ? AuthOnlyLayer
34
+ : MinimalLayer;
35
+ // Suppress verbose Effect logs
36
+ const SilentLogger = Logger.replace(Logger.defaultLogger, Logger.none);
37
+ const program = cli(argv).pipe(Effect.provide(layer), Effect.provide(SilentLogger), Logger.withMinimumLogLevel(LogLevel.None), Effect.catchAllCause((cause) => handleError(cause)));
38
+ NodeRuntime.runMain(program);
39
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA;;;;;;GAMG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACnD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAC3C,OAAO,GAAG,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;AACvD,OAAO,EACL,QAAQ,EACR,WAAW,EACX,aAAa,EACb,UAAU,EACV,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,aAAa,EACd,MAAM,qBAAqB,CAAA;AAE5B,uBAAuB;AACvB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CACpC,OAAO,CAAC,eAAe,CAAC,2CAA2C,CAAC,EACpE,OAAO,CAAC,eAAe,CAAC;IACtB,WAAW;IACX,UAAU;IACV,aAAa;CACd,CAAC,CACH,CAAA;AAED,kBAAkB;AAClB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE;IAC5B,IAAI,EAAE,GAAG,CAAC,IAAI;IACd,OAAO,EAAE,GAAG,CAAC,OAAO;CACrB,CAAC,CAAA;AAEF,6BAA6B;AAC7B,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAA;AAEpC,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,CAAA;AACpC,MAAM,KAAK,GAAG,SAAS,KAAK,MAAM;IAChC,CAAC,CAAC,QAAQ;IACV,CAAC,CAAC,SAAS,KAAK,MAAM;QACtB,CAAC,CAAC,aAAa;QACf,CAAC,CAAC,YAAY,CAAA;AAEhB,+BAA+B;AAC/B,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,CAAA;AAEtE,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAC5B,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EACrB,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAC5B,MAAM,CAAC,mBAAmB,CAAC,QAAQ,CAAC,IAAI,CAAC,EACzC,MAAM,CAAC,aAAa,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CACpD,CAAA;AAED,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA"}
@@ -0,0 +1,22 @@
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.
8
+ *
9
+ * @internal
10
+ */
11
+ import { Command } from "@effect/cli";
12
+ import * as Option from "effect/Option";
13
+ import { JiraAuth } from "../JiraAuth.js";
14
+ export declare const authCommand: Command.Command<"auth", JiraAuth | import("@effect/platform/CommandExecutor").CommandExecutor | import("@effect/platform/Terminal").Terminal, import("@knpkv/atlassian-common/auth").OAuthError | import("@knpkv/atlassian-common/config").FileSystemError | import("@knpkv/atlassian-common/config").HomeDirectoryError | import("@effect/platform/Error").PlatformError | import("@effect/platform/Terminal").QuitException, {
15
+ readonly subcommand: Option.Option<{} | {
16
+ readonly clientId: Option.Option<string>;
17
+ readonly clientSecret: Option.Option<string>;
18
+ } | {
19
+ readonly site: Option.Option<string>;
20
+ } | {} | {}>;
21
+ }>;
22
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,OAAO,EAAmB,MAAM,aAAa,CAAA;AAItD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAmGzC,eAAO,MAAM,WAAW;;;;;;;EASvB,CAAA"}